From 1b18aa8d19a4263271d6d4bfa557239d831d69ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 13 Jul 2023 13:25:30 -0600 Subject: [PATCH 001/173] Add QueryExt.jl --- Project.toml | 4 ++ ext/QueryExt.jl | 48 ++++++++++++++++++++ src/NEOs.jl | 2 +- src/init.jl | 1 + src/orbit_determination/gauss_method.jl | 58 ++++++++++++++++++++++++- 5 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 ext/QueryExt.jl diff --git a/Project.toml b/Project.toml index 6ec448d8..ccdd001e 100644 --- a/Project.toml +++ b/Project.toml @@ -33,10 +33,12 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [weakdeps] DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +Query = "1a8c2f83-1ff3-5112-b086-8aa67b057ba1" Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" [extensions] DataFramesExt = ["DataFrames", "Tables"] +QueryExt = "Query" [compat] AutoHashEquals = "0.2" @@ -50,6 +52,7 @@ IntervalRootFinding = "0.5.11" JLD2 = "0.4" PlanetaryEphemeris = "0.7" Quadmath = "0.5" +Query = "1" Requires = "0.5.2, 1" SPICE = "0.2" SatelliteToolboxTransformations = "0.1" @@ -62,4 +65,5 @@ julia = "1.6" [extras] DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +Query = "1a8c2f83-1ff3-5112-b086-8aa67b057ba1" Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" diff --git a/ext/QueryExt.jl b/ext/QueryExt.jl new file mode 100644 index 00000000..46dc6df2 --- /dev/null +++ b/ext/QueryExt.jl @@ -0,0 +1,48 @@ +module QueryExt + +using Dates +using NEOs: ObservatoryMPC, RadecMPC +import NEOs: reduce_nights + +if isdefined(Base, :get_extension) + using Query +else + using ..Query +end + +@doc raw""" + reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + +Return one observatory, date, right ascension and declination per observation night in `radec`. The reduction is performed +via Laplace interpolation. +""" +function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + # Observations per observatory + radec_per_obs = radec |> @groupby(_.observatory) |> @filter(length(_) >= 3) .|> collect + # Initialize output vectos + observatories = Vector{ObservatoryMPC{T}}(undef, 0) + dates = Vector{DateTime}(undef, 0) + α = Vector{T}(undef, 0) + δ = Vector{T}(undef, 0) + # Find observation nights per observatory + for i in eachindex(radec_per_obs) + # Current observatory + obs = observatory(radec_per_obs[i][1]) + # Filter observation night + nights = radec_per_obs[i] |> + @groupby(Date(_.date)) |> + @filter(length(_) >= 3) |> + @map(laplace_interpolation(_)) |> + @filter( !isnan(_[2]) && !isnan(_[3]) ) |> + collect + # Add observation night + observatories = vcat(observatories, fill(obs, length(nights))) + dates = vcat(dates, first.(nights)) + α = vcat(α, getindex.(nights, 2)) + δ = vcat(δ, last.(nights)) + end + + return observatories, dates, α, δ +end + +end # module \ No newline at end of file diff --git a/src/NEOs.jl b/src/NEOs.jl index bf969524..79aab661 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -57,7 +57,7 @@ export compute_radec, debiasing, w8sveres17, radec_astrometry, residuals # Process radar export compute_delay, radar_astrometry # Gauss method -export gauss_method +export gauss_method, reduce_nights # Asteroid dynamical models export RNp1BP_pN_A_J23E_J2S_ng_eph_threads!, RNp1BP_pN_A_J23E_J2S_eph_threads! # Propagate diff --git a/src/init.jl b/src/init.jl index 737ef32f..5923e1b3 100644 --- a/src/init.jl +++ b/src/init.jl @@ -20,5 +20,6 @@ function __init__() @require Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" begin @require DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" include("../ext/DataFramesExt.jl") end + @require Query = "1a8c2f83-1ff3-5112-b086-8aa67b057ba1" include("../ext/QueryExt.jl") end end \ No newline at end of file diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 85e3dde1..fc03de71 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -204,6 +204,8 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da # Check we have exactly three observations @assert length(observatories) == length(dates) == length(α) == length(δ) == 3 "Gauss method requires exactly three observations" + # Check observations are in temporal order + @assert issorted(dates) # Julian days of observation t_julian = datetime2julian.(dates) @@ -310,4 +312,58 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da end -end \ No newline at end of file +end + +function vandermonde(x::Vector{T}, order::Int) where {T <: Real} + # Number of points + L = length(x) + # Initialize Vandermonde matrix + V = Matrix{T}(undef, L, order+1) + # Fill first column + V[:, 1] .= one(T) + # Fill matrix + for j in 1:order + for i in 1:L + V[i, j+1] = x[i]^j + end + end + return V +end + +function laplace_interpolation(x::Vector{T}, y::Vector{T}) where {T <: Real} + # Check we have as many x as y + @assert length(x) == length(y) + # Polynomial order + order = length(x) - 1 + # Vandermonde matrix + V = vandermonde(x, order) + # Solve the system of equations + if iszero(det(V)) + coeffs = fill(T(NaN), order+1) + else + coeffs = V \ y + end + # Return polynomial + return Taylor1{T}(coeffs, order) +end + +function laplace_interpolation(radec::AbstractVector{RadecMPC{T}}) where {T <: Real} + # Julian days of observation + t_julian = datetime2julian.(date.(radec)) + # Days of observation [relative to first observation] + t_rel = t_julian .- t_julian[1] + # Mean date + t_mean = sum(t_rel) / length(t_rel) + + # Interpolating polynomials + α_p = laplace_interpolation(t_rel, ra.(radec)) + δ_p = laplace_interpolation(t_rel, dec.(radec)) + # Evaluate polynomials at mean date + α_mean = α_p(t_mean) + δ_mean = δ_p(t_mean) + + return julian2datetime(t_julian[1] + t_mean), α_mean, δ_mean +end + +# Empty method of reduce_nights, overloaded by QueryExt +function reduce_nights end \ No newline at end of file From 989681f2f9371261dee5186c2548fbd79d9f4274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 13 Jul 2023 13:29:08 -0600 Subject: [PATCH 002/173] Minor fix in QueryExt.jl --- ext/QueryExt.jl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ext/QueryExt.jl b/ext/QueryExt.jl index 46dc6df2..adcdb2f2 100644 --- a/ext/QueryExt.jl +++ b/ext/QueryExt.jl @@ -1,7 +1,7 @@ module QueryExt -using Dates -using NEOs: ObservatoryMPC, RadecMPC +using Dates: DateTime, Date +using NEOs: ObservatoryMPC, RadecMPC, observatory, date, laplace_interpolation import NEOs: reduce_nights if isdefined(Base, :get_extension) @@ -18,7 +18,10 @@ via Laplace interpolation. """ function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} # Observations per observatory - radec_per_obs = radec |> @groupby(_.observatory) |> @filter(length(_) >= 3) .|> collect + radec_per_obs = radec |> + @groupby(observatory(_)) |> + @filter(length(_) >= 3) .|> + collect # Initialize output vectos observatories = Vector{ObservatoryMPC{T}}(undef, 0) dates = Vector{DateTime}(undef, 0) @@ -30,7 +33,7 @@ function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} obs = observatory(radec_per_obs[i][1]) # Filter observation night nights = radec_per_obs[i] |> - @groupby(Date(_.date)) |> + @groupby(Date(date(_))) |> @filter(length(_) >= 3) |> @map(laplace_interpolation(_)) |> @filter( !isnan(_[2]) && !isnan(_[3]) ) |> From b9dcfc51ab78aa311f82ef8eef018d842510c3ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 14 Jul 2023 11:22:06 -0600 Subject: [PATCH 003/173] Gauss initial conditions --- ext/QueryExt.jl | 148 ++++++++++++++++++++---- src/NEOs.jl | 4 +- src/orbit_determination/gauss_method.jl | 107 +++++++++++------ src/propagation/propagation.jl | 2 +- 4 files changed, 204 insertions(+), 57 deletions(-) diff --git a/ext/QueryExt.jl b/ext/QueryExt.jl index adcdb2f2..d943728b 100644 --- a/ext/QueryExt.jl +++ b/ext/QueryExt.jl @@ -1,8 +1,12 @@ module QueryExt -using Dates: DateTime, Date -using NEOs: ObservatoryMPC, RadecMPC, observatory, date, laplace_interpolation -import NEOs: reduce_nights +using Dates: DateTime, Date, DatePeriod, Day, datetime2julian +using TaylorSeries: get_numvars +using PlanetaryEphemeris: J2000, selecteph, su, ea, yr, daysec, auday2kmsec +using NEOs: ObservatoryMPC, RadecMPC, observatory, date, polynomial_interpolation, gauss_idxs, propagate, + RNp1BP_pN_A_J23E_J2S_eph_threads!, order, abstol, sseph, scaled_variables, gauss_method, residuals, + bwdfwdeph, newtonls, diffcorr, nrms, hascoord +import NEOs: reduce_nights, gaussinitcond if isdefined(Base, :get_extension) using Query @@ -19,33 +23,135 @@ via Laplace interpolation. function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} # Observations per observatory radec_per_obs = radec |> + @filter(hascoord(observatory(_))) |> @groupby(observatory(_)) |> @filter(length(_) >= 3) .|> collect - # Initialize output vectos - observatories = Vector{ObservatoryMPC{T}}(undef, 0) - dates = Vector{DateTime}(undef, 0) - α = Vector{T}(undef, 0) - δ = Vector{T}(undef, 0) + # Initialize output + output = Vector{Tuple{ObservatoryMPC{T}, DateTime, T, T}}(undef, 0) # Find observation nights per observatory for i in eachindex(radec_per_obs) # Current observatory obs = observatory(radec_per_obs[i][1]) - # Filter observation night - nights = radec_per_obs[i] |> - @groupby(Date(date(_))) |> - @filter(length(_) >= 3) |> - @map(laplace_interpolation(_)) |> - @filter( !isnan(_[2]) && !isnan(_[3]) ) |> - collect - # Add observation night - observatories = vcat(observatories, fill(obs, length(nights))) - dates = vcat(dates, first.(nights)) - α = vcat(α, getindex.(nights, 2)) - δ = vcat(δ, last.(nights)) + # Reduce nights by interpolation + interp = radec_per_obs[i] |> + @groupby(Date(date(_))) |> + @filter(length(_) >= 3) |> + @map(polynomial_interpolation(_)) |> + @filter( !isnan(_[2]) && !isnan(_[3]) ) |> + collect + for j in eachindex(interp) + output = vcat(output, (obs, interp[j]...)) + end end - return observatories, dates, α, δ + sort!(output, by = x -> x[2]) + + return first.(output), getindex.(output, 2), getindex.(output, 3), last.(output) +end + +@doc raw""" + gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), niter::Int = 5, maxsteps::Int = 100, varorder::Int = 5, + order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} + +Return initial conditions via Gauss method. + +See also [`gauss_method`](@ref). + +# Arguments +- `radec::Vector{RadecMPC{T}}`: vector of oobservations. +- `Δ::DatePeriod`: see [`gauss_idxs`](@ref). +- `niter::Int`: number of iterations for Newton's method. +- `maxsteps::Int`: maximum number of steps for propagation. +- `varorder::Int`: order of jet transport perturbation. +- `order::Int`: order of Taylor polynomials w.r.t. time. +- `abstol::T`: absolute tolerance. +- `parse_eqs::Bool`: whether to use the taylorized method of `RNp1BP_pN_A_J23E_J2S_eph_threads!` or not. + +!!! warning + This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. +""" +function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), niter::Int = 5, maxsteps::Int = 100, varorder::Int = 5, + order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} + + filter!(x -> hascoord(observatory(x)), radec) + + # Sun's ephemeris + eph_su = selecteph(sseph, su) + # Earth's ephemeris + eph_ea = selecteph(sseph, ea) + + # Reduce nights by interpolation + observatories, dates, α, δ = reduce_nights(radec) + # Pick three observations for Gauss method + idxs = gauss_idxs(dates, Δ) + + # [julian days] + t0, jd0, tf = datetime2julian.(dates[idxs]) + # Number of years in forward integration + nyears_fwd = (tf - jd0 + 2) / yr + # Number of years in backward integration + nyears_bwd = -(jd0 - t0 + 2) / yr + + # Subset of radec for residuals + sub_radec = filter(x -> dates[idxs[1]] <= date(x) <= dates[idxs[3]], radec) + + # Jet transport perturbation (ra/dec) + dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃"; order = varorder) + # Gauss method solution + sol = gauss_method(observatories[idxs], dates[idxs], α[idxs] + dq[1:3], δ[idxs] .+ dq[4:6]; niter = niter) + + # Vector of errors + Q = Vector{T}(undef, length(sol)) + # Vector of initial conditions + Q0 = Matrix{T}(undef, length(sol), 6) + + # Iterate over Gauss solutions + for i in eachindex(sol) + # Initial conditions (jet transport) + q0 = sol[i].statevect .+ eph_su(jd0 - J2000) + + # Propagation + bwd, fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_bwd, nyears_fwd, q0, Val(true); + order = order, abstol = abstol, parse_eqs = parse_eqs) + + # O-C residuals + res, w = residuals(sub_radec; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), + xva = et -> bwdfwdeph(et, bwd, fwd)) + + # Orbit fit + success, x_new, Γ = newtonls(res, w, zeros(get_numvars()), niter) + @show success, x_new, Γ + # TO DO: check cases where newton converges but diffcorr no + + if success + # NRMS of the solution + Q[i] = nrms(res(x_new), w) + # Initial conditions + Q0[i, :] = bwd(bwd.t0)(x_new) + else + success, x_new, Γ = diffcorr(res, w, zeros(get_numvars()), niter) + if success + Q[i] = nrms(res(x_new), w) + Q0[i, :] = bwd(bwd.t0)(x_new) + else + Q[i] = T(Inf) + Q0[i, :] .= T(Inf) + end + end + end + + # Solution with minimum NRMS + i = findmin(Q)[2] + # Case: all solutions were unsuccesful + if isinf(Q[i]) + q00 = Vector{T}(undef, 0) + # Case: at least one solution was succesful + else + q00 = Q0[i, :] + end + + return jd0, q00 end end # module \ No newline at end of file diff --git a/src/NEOs.jl b/src/NEOs.jl index 79aab661..2a83a2bb 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -17,7 +17,7 @@ using PlanetaryEphemeris: daysec, su, ea, α_p_sun, δ_p_sun, t2c_jpl_de430, pol au, c_au_per_day, R_sun, c_cm_per_sec, c_au_per_sec, yr, RE, TaylorInterpolant, Rx, Ry, Rz, semimajoraxis, eccentricity, inclination, longascnode, argperi, timeperipass, nbodyind, ordpres_differentiate, numberofbodies, kmsec2auday, auday2kmsec, meanmotion, - meananomaly + meananomaly, selecteph using Healpix: ang2pixRing, Resolution using SatelliteToolboxTransformations import SatelliteToolboxTransformations.sv_ecef_to_eci @@ -57,7 +57,7 @@ export compute_radec, debiasing, w8sveres17, radec_astrometry, residuals # Process radar export compute_delay, radar_astrometry # Gauss method -export gauss_method, reduce_nights +export gauss_method, gauss_idxs, reduce_nights, gaussinitcond # Asteroid dynamical models export RNp1BP_pN_A_J23E_J2S_ng_eph_threads!, RNp1BP_pN_A_J23E_J2S_eph_threads! # Propagate diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index fc03de71..2c2c493f 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -46,9 +46,9 @@ end # Print method for GaussSolution # Examples: -# unique Gauss solution (r = 1.0800950907383229) +# unique Gauss solution (r = 1.0800950907383229 AU) function show(io::IO, g::GaussSolution{T, U}) where {T <: Real, U <: Number} - print(io, g.status, " Gauss solution (r = ", norm(cte.(g.statevect[1:3])), ")") + print(io, g.status, " Gauss solution (r = ", norm(cte.(g.statevect[1:3])), " AU)") end @doc raw""" @@ -124,11 +124,11 @@ Derivative of Lagrange polynomial to be solved during Gauss method. lagrange_derivative(x::T, a::U, b::U) where {T, U <: Number} = 8*x^7 + 6*a*x^5 + 3*b*x^2 # TO DO: Allow to control interval over which to look for solutions -# Currently we look between the radius of the Sun ((0.00465047 au) and the radius of the Solar System (40 au) +# Currently we look between the radius of the Sun (0.00465047 au) and the radius of the Solar System (40 au) @doc raw""" - solve_lagrange(a::T, b::T, c::T; niter::Int = niter) where {T <: Real} - solve_lagrange(a::TaylorN{T}, b::TaylorN{T}, c::TaylorN{T}; niter::Int = niter) where {T <: Real} + solve_lagrange(a::T, b::T, c::T; niter::Int = 5) where {T <: Real} + solve_lagrange(a::TaylorN{T}, b::TaylorN{T}, c::TaylorN{T}; niter::Int = 5) where {T <: Real} Solve Lagrange polynomial. @@ -162,10 +162,9 @@ function solve_lagrange(a::TaylorN{T}, b::TaylorN{T}, c::TaylorN{T}; niter::Int end @doc raw""" - gauss_method(obs::Vector{RadecMPC{T}}; xve::EarthEph = et -> kmsec2auday(getposvel(399, 10, et)), - niter::Int = 10) where {T <: AbstractFloat, EarthEph} + gauss_method(obs::Vector{RadecMPC{T}}; niter::Int = 5) where {T <: AbstractFloat} gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{DateTime}, α::Vector{U}, δ::Vector{U}; - xve::EarthEph = et -> kmsec2auday(getposvel(399, 10, et)), niter::Int = 5) where {T <: Real, U <: Number, EarthEph} + niter::Int = 5) where {T <: Real, U <: Number} Core Gauss method of Initial Orbit determination (IOD). See Algorithm 5.5 in page 274 https://doi.org/10.1016/C2016-0-02107-1. @@ -174,12 +173,11 @@ Core Gauss method of Initial Orbit determination (IOD). See Algorithm 5.5 in pag - `obs::Vector{RadecMPC{T}}`: three observations. - `observatories::Vector{ObservatoryMPC{T}}`: sites of observation. - `dates::Vector{DateTime}`: times of observation. -- `α::Vector{U}`: right ascension. -- `δ::Vector{U}`: declination. -- `xve::EarthEph`: Earth's ephemeris [et -> au, au/day]. +- `α::Vector{U}`: right ascension [rad]. +- `δ::Vector{U}`: declination [rad]. - `niter::Int`: Number of iterations for Newton's method. """ -function gauss_method(obs::Vector{RadecMPC{T}}; xve::EarthEph = et -> kmsec2auday(getposvel(399, 10, et)), niter::Int = 5) where {T <: AbstractFloat, EarthEph} +function gauss_method(obs::Vector{RadecMPC{T}}; niter::Int = 5) where {T <: AbstractFloat} # Make sure observations are in temporal order sort!(obs) @@ -196,37 +194,37 @@ function gauss_method(obs::Vector{RadecMPC{T}}; xve::EarthEph = et -> kmsec2auda # Declination δ = dec.(obs) - return gauss_method(observatories, dates, α, δ; xve = xve, niter = niter) + return gauss_method(observatories, dates, α, δ; niter = niter) end function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{DateTime}, α::Vector{U}, δ::Vector{U}; - xve::EarthEph = et -> kmsec2auday(getposvel(399, 10, et)), niter::Int = 5) where {T <: Real, U <: Number, EarthEph} + niter::Int = 5) where {T <: Real, U <: Number} # Check we have exactly three observations @assert length(observatories) == length(dates) == length(α) == length(δ) == 3 "Gauss method requires exactly three observations" # Check observations are in temporal order - @assert issorted(dates) + @assert issorted(dates) "Observations must be in temporal order" - # Julian days of observation - t_julian = datetime2julian.(dates) + # Times of observation [et] + t_et = datetime2et.(dates) + # Times of observation [days since J2000] + t_days = t_et ./ daysec # Time intervals - τ_1 = t_julian[1] - t_julian[2] - τ_3 = t_julian[3] - t_julian[2] + τ_1 = t_days[1] - t_days[2] + τ_3 = t_days[3] - t_days[2] τ = τ_3 - τ_1 # NEO's topocentric position unit vectors ρ_vec = vectors2matrix(topounit.(α, δ)) - - # Times of observation [et] - t_et = datetime2et.(dates) - # Geocentric state vector of the observer [au, au/day] g_vec = kmsec2auday.(obsposvelECI.(observatories, t_et)) - + # Sun's ephemeris + eph_su = selecteph(sseph, su) + # Earth's ephemeris + eph_ea = selecteph(sseph, ea) # Heliocentric state vector of the Earth [au, au/day] - G_vec = xve.(t_et) - + G_vec = eph_ea.(t_days) - eph_su.(t_days) # Observer's heliocentric positions [au, au/day] R_vec = vectors2matrix(G_vec .+ g_vec)[:, 1:3] @@ -266,7 +264,7 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da # Number of solutions n_sol = length(sol) - if n_sol == 0 + if iszero(n_sol) @warn("""No solutions found for Lagrange equation $(_format_Lagrange_equation(cte(a), cte(b), cte(c)))""") @@ -314,6 +312,11 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da end +@doc raw""" + vandermonde(x::Vector{T}, order::Int) where {T <: Real} + +Return the Vandermonde matrix of order `order` for points `x`. +""" function vandermonde(x::Vector{T}, order::Int) where {T <: Real} # Number of points L = length(x) @@ -330,7 +333,12 @@ function vandermonde(x::Vector{T}, order::Int) where {T <: Real} return V end -function laplace_interpolation(x::Vector{T}, y::Vector{T}) where {T <: Real} +@doc raw""" + polynomial_interpolation(x::Vector{T}, y::Vector{T}) where {T <: Real} + +Return the polynomial that passes through points `(x, y)`. +""" +function polynomial_interpolation(x::Vector{T}, y::Vector{T}) where {T <: Real} # Check we have as many x as y @assert length(x) == length(y) # Polynomial order @@ -347,7 +355,12 @@ function laplace_interpolation(x::Vector{T}, y::Vector{T}) where {T <: Real} return Taylor1{T}(coeffs, order) end -function laplace_interpolation(radec::AbstractVector{RadecMPC{T}}) where {T <: Real} +@doc raw""" + polynomial_interpolation(radec::AbstractVector{RadecMPC{T}}) where {T <: Real} + +Return `(τ, α(τ), δ(τ))` where `τ` is the mean date, `α` the right ascension and `δ` the declination. +""" +function polynomial_interpolation(radec::AbstractVector{RadecMPC{T}}) where {T <: Real} # Julian days of observation t_julian = datetime2julian.(date.(radec)) # Days of observation [relative to first observation] @@ -356,8 +369,8 @@ function laplace_interpolation(radec::AbstractVector{RadecMPC{T}}) where {T <: R t_mean = sum(t_rel) / length(t_rel) # Interpolating polynomials - α_p = laplace_interpolation(t_rel, ra.(radec)) - δ_p = laplace_interpolation(t_rel, dec.(radec)) + α_p = polynomial_interpolation(t_rel, ra.(radec)) + δ_p = polynomial_interpolation(t_rel, dec.(radec)) # Evaluate polynomials at mean date α_mean = α_p(t_mean) δ_mean = δ_p(t_mean) @@ -365,5 +378,33 @@ function laplace_interpolation(radec::AbstractVector{RadecMPC{T}}) where {T <: R return julian2datetime(t_julian[1] + t_mean), α_mean, δ_mean end -# Empty method of reduce_nights, overloaded by QueryExt -function reduce_nights end \ No newline at end of file +@doc raw""" + gauss_idxs(dates::Vector{DateTime}, Δ::DatePeriod = Day(1)) + +Return `[i, j, k]` such that `j = length(dates)÷2` and `|dates[m] - dates[n]| > Δ` for `m, n ∈ {i, j, k}` with `m != n`. +""" +function gauss_idxs(dates::Vector{DateTime}, Δ::DatePeriod = Day(1)) + # Number of points + L = length(dates) + # Naive indexes + j = Int[1, L ÷ 2, L] + # Right iteration + for i in j[2]+1:L + if (dates[i] - dates[j[2]]) > Δ + j[3] = i + break + end + end + # Left iteration + for i in j[2]-1:-1:1 + if (dates[j[2]] - dates[i]) > Δ + j[1] = i + break + end + end + return j +end + +# Empty methods to be overloaded by QueryExt +function reduce_nights end +function gaussinitcond end \ No newline at end of file diff --git a/src/propagation/propagation.jl b/src/propagation/propagation.jl index c44c52cb..7d671556 100644 --- a/src/propagation/propagation.jl +++ b/src/propagation/propagation.jl @@ -268,7 +268,7 @@ Compute the Lyapunov spectrum of a NEO. - `order::Int=order`: order of the Taylor expansions to be used in the integration. - `abstol::T`: absolute tolerance. - `parse_eqs::Bool`: whether to use the specialized method of `jetcoeffs` (`true`) or not. -""" propagate_lyap +""" function propagate_lyap(dynamics::D, maxsteps::Int, jd0::T, tspan::T, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: Real, U <: Number, D} From 9a62ff4e7da2daba10b9f562871f8d88ced89b1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 14 Jul 2023 14:50:32 -0600 Subject: [PATCH 004/173] Remove show --- ext/QueryExt.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/QueryExt.jl b/ext/QueryExt.jl index d943728b..2b9a1911 100644 --- a/ext/QueryExt.jl +++ b/ext/QueryExt.jl @@ -121,7 +121,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), nite # Orbit fit success, x_new, Γ = newtonls(res, w, zeros(get_numvars()), niter) - @show success, x_new, Γ + # TO DO: check cases where newton converges but diffcorr no if success From 23ddfdcd442a2658c391a2986d5aa22307096f94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 15 Jul 2023 13:01:10 -0600 Subject: [PATCH 005/173] Change Query for DataFrames approach --- Project.toml | 4 - ext/DataFramesExt.jl | 166 +++++++++++++++++++++++- ext/QueryExt.jl | 157 ---------------------- src/NEOs.jl | 2 +- src/init.jl | 1 - src/orbit_determination/gauss_method.jl | 33 +---- 6 files changed, 169 insertions(+), 194 deletions(-) delete mode 100644 ext/QueryExt.jl diff --git a/Project.toml b/Project.toml index ccdd001e..6ec448d8 100644 --- a/Project.toml +++ b/Project.toml @@ -33,12 +33,10 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [weakdeps] DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" -Query = "1a8c2f83-1ff3-5112-b086-8aa67b057ba1" Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" [extensions] DataFramesExt = ["DataFrames", "Tables"] -QueryExt = "Query" [compat] AutoHashEquals = "0.2" @@ -52,7 +50,6 @@ IntervalRootFinding = "0.5.11" JLD2 = "0.4" PlanetaryEphemeris = "0.7" Quadmath = "0.5" -Query = "1" Requires = "0.5.2, 1" SPICE = "0.2" SatelliteToolboxTransformations = "0.1" @@ -65,5 +62,4 @@ julia = "1.6" [extras] DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" -Query = "1a8c2f83-1ff3-5112-b086-8aa67b057ba1" Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index 2e98d1e9..8216e6ab 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -1,13 +1,19 @@ module DataFramesExt +using Dates: Date, DatePeriod, Day, datetime2julian, julian2datetime +using TaylorSeries: get_numvars +using PlanetaryEphemeris: J2000, selecteph, su, ea, yr, daysec, auday2kmsec +using NEOs: RadecMPC, date, gauss_idxs, propagate, RNp1BP_pN_A_J23E_J2S_eph_threads!, order, abstol, sseph, + scaled_variables, gauss_method, residuals, bwdfwdeph, newtonls, diffcorr, nrms, hascoord + import Base: convert -import NEOs: AbstractAstrometry +import NEOs: AbstractAstrometry, polynomial_interpolation, reduce_nights, gaussinitcond if isdefined(Base, :get_extension) - using DataFrames: DataFrame, nrow, eachcol, eachrow + using DataFrames: AbstractDataFrame, DataFrame, nrow, eachcol, eachrow, groupby, combine import Tables: istable, rowaccess, rows, schema, Schema else - using ..DataFrames: DataFrame, nrow, eachcol, eachrow + using ..DataFrames: AbstractDataFrame, DataFrame, nrow, eachcol, eachrow, groupby, combine import ..Tables: istable, rowaccess, rows, schema, Schema end @@ -30,4 +36,158 @@ end convert(::Type{Vector{T}}, df::DataFrame) where {T <: AbstractAstrometry} = Vector{T}(df) +@doc raw""" + polynomial_interpolation(df::AbstractDataFrame) + +Special method of [`polynomial_interpolation`](@ref) to be used by [`gaussinitcond`](@ref). +""" +function polynomial_interpolation(df::AbstractDataFrame) + if nrow(df) < 3 + return (observatory = df.observatory[1], date = julian2datetime(0), α = NaN, δ = NaN) + end + + # Julian days of observation + t_julian = datetime2julian.(df.date) + # Days of observation [relative to first observation] + t_rel = t_julian .- t_julian[1] + # Mean date + t_mean = sum(t_rel) / length(t_rel) + + # Interpolating polynomials + α_p = polynomial_interpolation(t_rel, df.α) + δ_p = polynomial_interpolation(t_rel, df.δ) + # Evaluate polynomials at mean date + α_mean = α_p(t_mean) + δ_mean = δ_p(t_mean) + + return (observatory = df.observatory[1], date = julian2datetime(t_julian[1] + t_mean), α = α_mean, δ = δ_mean) +end + +@doc raw""" + reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + +Return one observatory, date, right ascension and declination per observation night in `radec`. The reduction is performed +via polynomial interpolation. +""" +function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + # Convert to DataFrame + df = DataFrame(radec) + # Eliminate observatories without coordinates + filter!(:observatory => hascoord, df) + # Group by observatory and Date + df.Date = Date.(df.date) + gdf = groupby(df, [:observatory, :Date]) + # Interpolate observation nights + cdf = combine(gdf, polynomial_interpolation, keepkeys = false) + # Eliminate unsuccesful interpolations + filter!(:α => !isnan, cdf) + filter!(:δ => !isnan, cdf) + # Sorbt by date + sort!(cdf, :date) + + return cdf.observatory, cdf.date, cdf.α, cdf.δ +end + +@doc raw""" + gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), niter::Int = 5, maxsteps::Int = 100, varorder::Int = 5, + order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} + +Return initial conditions via Gauss method. + +See also [`gauss_method`](@ref). + +# Arguments +- `radec::Vector{RadecMPC{T}}`: vector of observations. +- `Δ::DatePeriod`: see [`gauss_idxs`](@ref). +- `niter::Int`: number of iterations for Newton's method. +- `maxsteps::Int`: maximum number of steps for propagation. +- `varorder::Int`: order of jet transport perturbation. +- `order::Int`: order of Taylor polynomials w.r.t. time. +- `abstol::T`: absolute tolerance. +- `parse_eqs::Bool`: whether to use the taylorized method of `RNp1BP_pN_A_J23E_J2S_eph_threads!` or not. + +!!! warning + This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. +""" +function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), niter::Int = 5, maxsteps::Int = 100, varorder::Int = 5, + order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} + + # Sun's ephemeris + eph_su = selecteph(sseph, su) + # Earth's ephemeris + eph_ea = selecteph(sseph, ea) + + # Reduce nights by interpolation + observatories, dates, α, δ = reduce_nights(radec) + # Pick three observations for Gauss method + idxs = gauss_idxs(dates, Δ) + + # [julian days] + t0, jd0, tf = datetime2julian.(dates[idxs]) + # Number of years in forward integration + nyears_fwd = (tf - jd0 + 2) / yr + # Number of years in backward integration + nyears_bwd = -(jd0 - t0 + 2) / yr + + # Subset of radec for residuals + sub_radec = filter(x -> dates[idxs[1]] <= date(x) <= dates[idxs[3]], radec) + + # Jet transport perturbation (ra/dec) + dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃"; order = varorder) + # Gauss method solution + sol = gauss_method(observatories[idxs], dates[idxs], α[idxs] + dq[1:3], δ[idxs] .+ dq[4:6]; niter = niter) + + # Vector of errors + Q = Vector{T}(undef, length(sol)) + # Vector of initial conditions + Q0 = Matrix{T}(undef, length(sol), 6) + + # Iterate over Gauss solutions + for i in eachindex(sol) + # Initial conditions (jet transport) + q0 = sol[i].statevect .+ eph_su(jd0 - J2000) + + # Propagation + bwd, fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_bwd, nyears_fwd, q0, Val(true); + order = order, abstol = abstol, parse_eqs = parse_eqs) + + # O-C residuals + res, w = residuals(sub_radec; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), + xva = et -> bwdfwdeph(et, bwd, fwd)) + + # Orbit fit + success, x_new, Γ = newtonls(res, w, zeros(get_numvars()), niter) + + # TO DO: check cases where newton converges but diffcorr no + + if success + # NRMS of the solution + Q[i] = nrms(res(x_new), w) + # Initial conditions + Q0[i, :] = bwd(bwd.t0)(x_new) + else + success, x_new, Γ = diffcorr(res, w, zeros(get_numvars()), niter) + if success + Q[i] = nrms(res(x_new), w) + Q0[i, :] = bwd(bwd.t0)(x_new) + else + Q[i] = T(Inf) + Q0[i, :] .= T(Inf) + end + end + end + + # Solution with minimum NRMS + i = findmin(Q)[2] + # Case: all solutions were unsuccesful + if isinf(Q[i]) + q00 = Vector{T}(undef, 0) + # Case: at least one solution was succesful + else + q00 = Q0[i, :] + end + + return jd0, q00 +end + end # module \ No newline at end of file diff --git a/ext/QueryExt.jl b/ext/QueryExt.jl deleted file mode 100644 index 2b9a1911..00000000 --- a/ext/QueryExt.jl +++ /dev/null @@ -1,157 +0,0 @@ -module QueryExt - -using Dates: DateTime, Date, DatePeriod, Day, datetime2julian -using TaylorSeries: get_numvars -using PlanetaryEphemeris: J2000, selecteph, su, ea, yr, daysec, auday2kmsec -using NEOs: ObservatoryMPC, RadecMPC, observatory, date, polynomial_interpolation, gauss_idxs, propagate, - RNp1BP_pN_A_J23E_J2S_eph_threads!, order, abstol, sseph, scaled_variables, gauss_method, residuals, - bwdfwdeph, newtonls, diffcorr, nrms, hascoord -import NEOs: reduce_nights, gaussinitcond - -if isdefined(Base, :get_extension) - using Query -else - using ..Query -end - -@doc raw""" - reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - -Return one observatory, date, right ascension and declination per observation night in `radec`. The reduction is performed -via Laplace interpolation. -""" -function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - # Observations per observatory - radec_per_obs = radec |> - @filter(hascoord(observatory(_))) |> - @groupby(observatory(_)) |> - @filter(length(_) >= 3) .|> - collect - # Initialize output - output = Vector{Tuple{ObservatoryMPC{T}, DateTime, T, T}}(undef, 0) - # Find observation nights per observatory - for i in eachindex(radec_per_obs) - # Current observatory - obs = observatory(radec_per_obs[i][1]) - # Reduce nights by interpolation - interp = radec_per_obs[i] |> - @groupby(Date(date(_))) |> - @filter(length(_) >= 3) |> - @map(polynomial_interpolation(_)) |> - @filter( !isnan(_[2]) && !isnan(_[3]) ) |> - collect - for j in eachindex(interp) - output = vcat(output, (obs, interp[j]...)) - end - end - - sort!(output, by = x -> x[2]) - - return first.(output), getindex.(output, 2), getindex.(output, 3), last.(output) -end - -@doc raw""" - gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), niter::Int = 5, maxsteps::Int = 100, varorder::Int = 5, - order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} - -Return initial conditions via Gauss method. - -See also [`gauss_method`](@ref). - -# Arguments -- `radec::Vector{RadecMPC{T}}`: vector of oobservations. -- `Δ::DatePeriod`: see [`gauss_idxs`](@ref). -- `niter::Int`: number of iterations for Newton's method. -- `maxsteps::Int`: maximum number of steps for propagation. -- `varorder::Int`: order of jet transport perturbation. -- `order::Int`: order of Taylor polynomials w.r.t. time. -- `abstol::T`: absolute tolerance. -- `parse_eqs::Bool`: whether to use the taylorized method of `RNp1BP_pN_A_J23E_J2S_eph_threads!` or not. - -!!! warning - This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. -""" -function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), niter::Int = 5, maxsteps::Int = 100, varorder::Int = 5, - order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} - - filter!(x -> hascoord(observatory(x)), radec) - - # Sun's ephemeris - eph_su = selecteph(sseph, su) - # Earth's ephemeris - eph_ea = selecteph(sseph, ea) - - # Reduce nights by interpolation - observatories, dates, α, δ = reduce_nights(radec) - # Pick three observations for Gauss method - idxs = gauss_idxs(dates, Δ) - - # [julian days] - t0, jd0, tf = datetime2julian.(dates[idxs]) - # Number of years in forward integration - nyears_fwd = (tf - jd0 + 2) / yr - # Number of years in backward integration - nyears_bwd = -(jd0 - t0 + 2) / yr - - # Subset of radec for residuals - sub_radec = filter(x -> dates[idxs[1]] <= date(x) <= dates[idxs[3]], radec) - - # Jet transport perturbation (ra/dec) - dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃"; order = varorder) - # Gauss method solution - sol = gauss_method(observatories[idxs], dates[idxs], α[idxs] + dq[1:3], δ[idxs] .+ dq[4:6]; niter = niter) - - # Vector of errors - Q = Vector{T}(undef, length(sol)) - # Vector of initial conditions - Q0 = Matrix{T}(undef, length(sol), 6) - - # Iterate over Gauss solutions - for i in eachindex(sol) - # Initial conditions (jet transport) - q0 = sol[i].statevect .+ eph_su(jd0 - J2000) - - # Propagation - bwd, fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_bwd, nyears_fwd, q0, Val(true); - order = order, abstol = abstol, parse_eqs = parse_eqs) - - # O-C residuals - res, w = residuals(sub_radec; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), - xva = et -> bwdfwdeph(et, bwd, fwd)) - - # Orbit fit - success, x_new, Γ = newtonls(res, w, zeros(get_numvars()), niter) - - # TO DO: check cases where newton converges but diffcorr no - - if success - # NRMS of the solution - Q[i] = nrms(res(x_new), w) - # Initial conditions - Q0[i, :] = bwd(bwd.t0)(x_new) - else - success, x_new, Γ = diffcorr(res, w, zeros(get_numvars()), niter) - if success - Q[i] = nrms(res(x_new), w) - Q0[i, :] = bwd(bwd.t0)(x_new) - else - Q[i] = T(Inf) - Q0[i, :] .= T(Inf) - end - end - end - - # Solution with minimum NRMS - i = findmin(Q)[2] - # Case: all solutions were unsuccesful - if isinf(Q[i]) - q00 = Vector{T}(undef, 0) - # Case: at least one solution was succesful - else - q00 = Q0[i, :] - end - - return jd0, q00 -end - -end # module \ No newline at end of file diff --git a/src/NEOs.jl b/src/NEOs.jl index 2a83a2bb..6bf86473 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -57,7 +57,7 @@ export compute_radec, debiasing, w8sveres17, radec_astrometry, residuals # Process radar export compute_delay, radar_astrometry # Gauss method -export gauss_method, gauss_idxs, reduce_nights, gaussinitcond +export gauss_method, gaussinitcond # Asteroid dynamical models export RNp1BP_pN_A_J23E_J2S_ng_eph_threads!, RNp1BP_pN_A_J23E_J2S_eph_threads! # Propagate diff --git a/src/init.jl b/src/init.jl index 5923e1b3..737ef32f 100644 --- a/src/init.jl +++ b/src/init.jl @@ -20,6 +20,5 @@ function __init__() @require Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" begin @require DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" include("../ext/DataFramesExt.jl") end - @require Query = "1a8c2f83-1ff3-5112-b086-8aa67b057ba1" include("../ext/QueryExt.jl") end end \ No newline at end of file diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 2c2c493f..7a3008f3 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -313,11 +313,11 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da end @doc raw""" - vandermonde(x::Vector{T}, order::Int) where {T <: Real} + vandermonde(x::AbstractVector{T}, order::Int) where {T <: Real} Return the Vandermonde matrix of order `order` for points `x`. """ -function vandermonde(x::Vector{T}, order::Int) where {T <: Real} +function vandermonde(x::AbstractVector{T}, order::Int) where {T <: Real} # Number of points L = length(x) # Initialize Vandermonde matrix @@ -334,11 +334,11 @@ function vandermonde(x::Vector{T}, order::Int) where {T <: Real} end @doc raw""" - polynomial_interpolation(x::Vector{T}, y::Vector{T}) where {T <: Real} + polynomial_interpolation(x::AbstractVector{T}, y::AbstractVector{T}) where {T <: Real} Return the polynomial that passes through points `(x, y)`. """ -function polynomial_interpolation(x::Vector{T}, y::Vector{T}) where {T <: Real} +function polynomial_interpolation(x::AbstractVector{T}, y::AbstractVector{T}) where {T <: Real} # Check we have as many x as y @assert length(x) == length(y) # Polynomial order @@ -355,29 +355,6 @@ function polynomial_interpolation(x::Vector{T}, y::Vector{T}) where {T <: Real} return Taylor1{T}(coeffs, order) end -@doc raw""" - polynomial_interpolation(radec::AbstractVector{RadecMPC{T}}) where {T <: Real} - -Return `(τ, α(τ), δ(τ))` where `τ` is the mean date, `α` the right ascension and `δ` the declination. -""" -function polynomial_interpolation(radec::AbstractVector{RadecMPC{T}}) where {T <: Real} - # Julian days of observation - t_julian = datetime2julian.(date.(radec)) - # Days of observation [relative to first observation] - t_rel = t_julian .- t_julian[1] - # Mean date - t_mean = sum(t_rel) / length(t_rel) - - # Interpolating polynomials - α_p = polynomial_interpolation(t_rel, ra.(radec)) - δ_p = polynomial_interpolation(t_rel, dec.(radec)) - # Evaluate polynomials at mean date - α_mean = α_p(t_mean) - δ_mean = δ_p(t_mean) - - return julian2datetime(t_julian[1] + t_mean), α_mean, δ_mean -end - @doc raw""" gauss_idxs(dates::Vector{DateTime}, Δ::DatePeriod = Day(1)) @@ -405,6 +382,6 @@ function gauss_idxs(dates::Vector{DateTime}, Δ::DatePeriod = Day(1)) return j end -# Empty methods to be overloaded by QueryExt +# Empty methods to be overloaded by DataFramesExt function reduce_nights end function gaussinitcond end \ No newline at end of file From 82ccf9ec760f074743c228ccfa6cc2c61b3f0584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Mon, 17 Jul 2023 14:20:25 -0600 Subject: [PATCH 006/173] Minor fix in gauss_idxs --- ext/DataFramesExt.jl | 2 +- src/orbit_determination/gauss_method.jl | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index 8216e6ab..aa0b67a3 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -135,7 +135,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), nite # Jet transport perturbation (ra/dec) dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃"; order = varorder) # Gauss method solution - sol = gauss_method(observatories[idxs], dates[idxs], α[idxs] + dq[1:3], δ[idxs] .+ dq[4:6]; niter = niter) + sol = gauss_method(observatories[idxs], dates[idxs], α[idxs] .+ dq[1:3], δ[idxs] .+ dq[4:6]; niter = niter) # Vector of errors Q = Vector{T}(undef, length(sol)) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 7a3008f3..9ef3fe05 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -361,19 +361,24 @@ end Return `[i, j, k]` such that `j = length(dates)÷2` and `|dates[m] - dates[n]| > Δ` for `m, n ∈ {i, j, k}` with `m != n`. """ function gauss_idxs(dates::Vector{DateTime}, Δ::DatePeriod = Day(1)) + @assert length(dates) >= 3 "length(dates) must be at least 3" # Number of points L = length(dates) # Naive indexes - j = Int[1, L ÷ 2, L] + if isodd(L) + j = Int[1, (L+1) ÷ 2, L] + else + j = Int[1, L ÷ 2, L] + end # Right iteration - for i in j[2]+1:L + for i in j[2]+1:L-1 if (dates[i] - dates[j[2]]) > Δ j[3] = i break end end # Left iteration - for i in j[2]-1:-1:1 + for i in j[2]-1:-1:2 if (dates[j[2]] - dates[i]) > Δ j[1] = i break From 95d61edadc34905cefc7922a1732990c9fd7e171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 18 Jul 2023 15:40:56 -0600 Subject: [PATCH 007/173] Change to Interpolations.jl --- Project.toml | 2 ++ ext/DataFramesExt.jl | 20 +++++------ src/NEOs.jl | 1 + src/orbit_determination/gauss_method.jl | 45 +++++-------------------- 4 files changed, 22 insertions(+), 46 deletions(-) diff --git a/Project.toml b/Project.toml index 6ec448d8..b54c689c 100644 --- a/Project.toml +++ b/Project.toml @@ -14,6 +14,7 @@ HORIZONS = "5a3ac768-beb4-554a-9c98-3342fe3377f5" HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" Healpix = "9f4e344d-96bc-545a-84a3-ae6b9e1b672b" InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" +Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59" IntervalArithmetic = "d1acc4aa-44c8-5952-acd4-ba5d80a2a253" IntervalRootFinding = "d2bf35a9-74e0-55ec-b149-d360ff49b807" JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" @@ -45,6 +46,7 @@ DelimitedFiles = "1" HORIZONS = "0.3" HTTP = "1.9.5" Healpix = "4" +Interpolations = "0.14" IntervalArithmetic = "0.20" IntervalRootFinding = "0.5.11" JLD2 = "0.4" diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index aa0b67a3..c2d34ba2 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -7,7 +7,7 @@ using NEOs: RadecMPC, date, gauss_idxs, propagate, RNp1BP_pN_A_J23E_J2S_eph_thre scaled_variables, gauss_method, residuals, bwdfwdeph, newtonls, diffcorr, nrms, hascoord import Base: convert -import NEOs: AbstractAstrometry, polynomial_interpolation, reduce_nights, gaussinitcond +import NEOs: AbstractAstrometry, extrapolation, reduce_nights, gaussinitcond if isdefined(Base, :get_extension) using DataFrames: AbstractDataFrame, DataFrame, nrow, eachcol, eachrow, groupby, combine @@ -37,13 +37,13 @@ end convert(::Type{Vector{T}}, df::DataFrame) where {T <: AbstractAstrometry} = Vector{T}(df) @doc raw""" - polynomial_interpolation(df::AbstractDataFrame) + extrapolation(df::AbstractDataFrame) -Special method of [`polynomial_interpolation`](@ref) to be used by [`gaussinitcond`](@ref). +Special method of [`extrapolation`](@ref) to be used by [`gaussinitcond`](@ref). """ -function polynomial_interpolation(df::AbstractDataFrame) - if nrow(df) < 3 - return (observatory = df.observatory[1], date = julian2datetime(0), α = NaN, δ = NaN) +function extrapolation(df::AbstractDataFrame) + if isone(nrow(df)) + return (observatory = df.observatory[1], date = df.date[1], α = df.α[1], δ = df.δ[1]) end # Julian days of observation @@ -53,9 +53,9 @@ function polynomial_interpolation(df::AbstractDataFrame) # Mean date t_mean = sum(t_rel) / length(t_rel) - # Interpolating polynomials - α_p = polynomial_interpolation(t_rel, df.α) - δ_p = polynomial_interpolation(t_rel, df.δ) + # Extrapolate + α_p = extrapolation(t_rel, df.α) + δ_p = extrapolation(t_rel, df.δ) # Evaluate polynomials at mean date α_mean = α_p(t_mean) δ_mean = δ_p(t_mean) @@ -78,7 +78,7 @@ function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} df.Date = Date.(df.date) gdf = groupby(df, [:observatory, :Date]) # Interpolate observation nights - cdf = combine(gdf, polynomial_interpolation, keepkeys = false) + cdf = combine(gdf, extrapolation, keepkeys = false) # Eliminate unsuccesful interpolations filter!(:α => !isnan, cdf) filter!(:δ => !isnan, cdf) diff --git a/src/NEOs.jl b/src/NEOs.jl index 6bf86473..720a0e5a 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -27,6 +27,7 @@ using Downloads: download import Downloads using HTTP: get using IntervalRootFinding: roots, interval, Interval, mid +using Interpolations: Flat, Gridded, Linear, interpolate, extrapolate # Constants export d_EM_km, d_EM_au diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 9ef3fe05..6d65376b 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -313,46 +313,19 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da end @doc raw""" - vandermonde(x::AbstractVector{T}, order::Int) where {T <: Real} + extrapolation(x::AbstractVector{T}, y::AbstractVector{T}) where {T <: Real} -Return the Vandermonde matrix of order `order` for points `x`. +Return an extrapolation of points `(x, y)`. """ -function vandermonde(x::AbstractVector{T}, order::Int) where {T <: Real} - # Number of points - L = length(x) - # Initialize Vandermonde matrix - V = Matrix{T}(undef, L, order+1) - # Fill first column - V[:, 1] .= one(T) - # Fill matrix - for j in 1:order - for i in 1:L - V[i, j+1] = x[i]^j - end - end - return V -end - -@doc raw""" - polynomial_interpolation(x::AbstractVector{T}, y::AbstractVector{T}) where {T <: Real} - -Return the polynomial that passes through points `(x, y)`. -""" -function polynomial_interpolation(x::AbstractVector{T}, y::AbstractVector{T}) where {T <: Real} +function extrapolation(x::AbstractVector{T}, y::AbstractVector{T}) where {T <: Real} # Check we have as many x as y @assert length(x) == length(y) - # Polynomial order - order = length(x) - 1 - # Vandermonde matrix - V = vandermonde(x, order) - # Solve the system of equations - if iszero(det(V)) - coeffs = fill(T(NaN), order+1) - else - coeffs = V \ y - end - # Return polynomial - return Taylor1{T}(coeffs, order) + # Interpolation + itp = interpolate((x,), y, Gridded(Linear())) + # Extrapolation + etpf = extrapolate(itp, Flat()) + + return etpf end @doc raw""" From c17e016170cf2fae4c8647d553dc16f33dd08ddb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 18 Jul 2023 17:53:21 -0600 Subject: [PATCH 008/173] Modify gauss_idxs --- src/orbit_determination/gauss_method.jl | 74 ++++++++++++++++++------- 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 6d65376b..9e9d4c2e 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -328,38 +328,72 @@ function extrapolation(x::AbstractVector{T}, y::AbstractVector{T}) where {T <: R return etpf end +function closest_index_sorted(x::AbstractVector{T}, val::T) where {T} + L = length(x) + i = searchsortedfirst(x, val) + if i == L + 1 + return 0 + end + j = searchsortedlast(x, val) + if j == 0 + j = 1 + end + + if abs(x[i] - val) < abs(x[j] - val) + return i + else + return j + end +end + +gauss_norm(dates::Vector{DateTime}) = abs( (dates[2] - dates[1]).value - (dates[3] - dates[2]).value ) + @doc raw""" gauss_idxs(dates::Vector{DateTime}, Δ::DatePeriod = Day(1)) Return `[i, j, k]` such that `j = length(dates)÷2` and `|dates[m] - dates[n]| > Δ` for `m, n ∈ {i, j, k}` with `m != n`. """ function gauss_idxs(dates::Vector{DateTime}, Δ::DatePeriod = Day(1)) - @assert length(dates) >= 3 "length(dates) must be at least 3" - # Number of points L = length(dates) + @assert L >= 3 "length(dates) must be at least 3" + @assert issorted(dates) "Vector of dates must be sorted" + if L == 3 + return [1, 2, 3] + end # Naive indexes if isodd(L) - j = Int[1, (L+1) ÷ 2, L] + best_idxs = [1, (L+1) ÷ 2, L] else - j = Int[1, L ÷ 2, L] + best_idxs = [1, L ÷ 2, L] end - # Right iteration - for i in j[2]+1:L-1 - if (dates[i] - dates[j[2]]) > Δ - j[3] = i - break - end - end - # Left iteration - for i in j[2]-1:-1:2 - if (dates[j[2]] - dates[i]) > Δ - j[1] = i + best_norm = gauss_norm(dates[best_idxs]) + + idxs = [0, 0, 0] + norm = Inf + + for i in 1:L-2 + idxs[1] = i + idxs[2] = closest_index_sorted(view(dates, idxs[1]+1:L), dates[idxs[1]] + Δ) + idxs[2] += idxs[1] + if (idxs[2] == idxs[1]) || (idxs[2] > L) break - end - end - return j -end + else + idxs[3] = closest_index_sorted(view(dates, idxs[2]+1:L), dates[idxs[2]] + Δ) + idxs[3] += idxs[2] + if (idxs[3] == idxs[2]) || (idxs[3] > L) + break + end + end + norm = gauss_norm(dates[idxs]) + if norm < best_norm + best_norm = norm + best_idxs .= idxs + end + end + + return best_idxs +end # Empty methods to be overloaded by DataFramesExt function reduce_nights end -function gaussinitcond end \ No newline at end of file +function gaussinitcond end \ No newline at end of file From e19e0c6d0c79154041ea6706b19c48cad466e6b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 19 Jul 2023 07:03:43 -0600 Subject: [PATCH 009/173] Document new functions --- src/orbit_determination/gauss_method.jl | 44 ++++++++++++++++++++----- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 9e9d4c2e..3eebe74d 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -328,17 +328,27 @@ function extrapolation(x::AbstractVector{T}, y::AbstractVector{T}) where {T <: R return etpf end +@doc raw""" + closest_index_sorted(x::AbstractVector{T}, val::T) where {T} + +Return the index of the element in `x` that is closest to `val`, assuming `x` is sorted. +""" function closest_index_sorted(x::AbstractVector{T}, val::T) where {T} + # Number of elements L = length(x) + # Right closure i = searchsortedfirst(x, val) + # All x is below val if i == L + 1 return 0 end + # Left closure j = searchsortedlast(x, val) + # All x is above val if j == 0 j = 1 end - + # Choose closest element if abs(x[i] - val) < abs(x[j] - val) return i else @@ -346,17 +356,30 @@ function closest_index_sorted(x::AbstractVector{T}, val::T) where {T} end end +@doc raw""" + gauss_norm(dates::Vector{DateTime}) + +Return a measure of how evenly distributed in time a triplet is; used within [`gauss_idxs`](@ref) to select observations +for Gauss method. The function assumes `dates` is sorted. +""" gauss_norm(dates::Vector{DateTime}) = abs( (dates[2] - dates[1]).value - (dates[3] - dates[2]).value ) @doc raw""" gauss_idxs(dates::Vector{DateTime}, Δ::DatePeriod = Day(1)) -Return `[i, j, k]` such that `j = length(dates)÷2` and `|dates[m] - dates[n]| > Δ` for `m, n ∈ {i, j, k}` with `m != n`. +Return three indices `[i, j, k]` based on two criteria: + 1.- The three dates are separated by `Δ` as close as possible, + 2.- `|j - i|` and `|k - j|` are as close as possible. + +See also [`gauss_norm`](@ref) and [`closest_index_sorted`](@ref). """ function gauss_idxs(dates::Vector{DateTime}, Δ::DatePeriod = Day(1)) + # Number of elements L = length(dates) + # Checks @assert L >= 3 "length(dates) must be at least 3" @assert issorted(dates) "Vector of dates must be sorted" + # Minimal case if L == 3 return [1, 2, 3] end @@ -365,30 +388,33 @@ function gauss_idxs(dates::Vector{DateTime}, Δ::DatePeriod = Day(1)) best_idxs = [1, (L+1) ÷ 2, L] else best_idxs = [1, L ÷ 2, L] - end + end + # Naive norm best_norm = gauss_norm(dates[best_idxs]) - + # Temporary idexes idxs = [0, 0, 0] + # Temporary norm norm = Inf for i in 1:L-2 + # First criterion idxs[1] = i - idxs[2] = closest_index_sorted(view(dates, idxs[1]+1:L), dates[idxs[1]] + Δ) - idxs[2] += idxs[1] + idxs[2] = closest_index_sorted(view(dates, idxs[1]+1:L), dates[idxs[1]] + Δ) + idxs[1] if (idxs[2] == idxs[1]) || (idxs[2] > L) break else - idxs[3] = closest_index_sorted(view(dates, idxs[2]+1:L), dates[idxs[2]] + Δ) - idxs[3] += idxs[2] + idxs[3] = closest_index_sorted(view(dates, idxs[2]+1:L), dates[idxs[2]] + Δ) + idxs[2] if (idxs[3] == idxs[2]) || (idxs[3] > L) break end end + # Second criterion norm = gauss_norm(dates[idxs]) + # Update norm and indexes if norm < best_norm best_norm = norm best_idxs .= idxs - end + end end return best_idxs From 8a53dafde40d15682438197fa5ff529235cd9075 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 19 Jul 2023 12:16:04 -0600 Subject: [PATCH 010/173] Change gauss_idxs for gauss_triplets --- ext/DataFramesExt.jl | 127 ++++++++++++++++-------- src/orbit_determination/gauss_method.jl | 55 ++++------ 2 files changed, 104 insertions(+), 78 deletions(-) diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index c2d34ba2..2f0b387f 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -3,7 +3,7 @@ module DataFramesExt using Dates: Date, DatePeriod, Day, datetime2julian, julian2datetime using TaylorSeries: get_numvars using PlanetaryEphemeris: J2000, selecteph, su, ea, yr, daysec, auday2kmsec -using NEOs: RadecMPC, date, gauss_idxs, propagate, RNp1BP_pN_A_J23E_J2S_eph_threads!, order, abstol, sseph, +using NEOs: RadecMPC, date, gauss_triplets, propagate, RNp1BP_pN_A_J23E_J2S_eph_threads!, order, abstol, sseph, scaled_variables, gauss_method, residuals, bwdfwdeph, newtonls, diffcorr, nrms, hascoord import Base: convert @@ -98,7 +98,7 @@ See also [`gauss_method`](@ref). # Arguments - `radec::Vector{RadecMPC{T}}`: vector of observations. -- `Δ::DatePeriod`: see [`gauss_idxs`](@ref). +- `Δ::DatePeriod`: see [`gauss_triplets`](@ref). - `niter::Int`: number of iterations for Newton's method. - `maxsteps::Int`: maximum number of steps for propagation. - `varorder::Int`: order of jet transport perturbation. @@ -119,66 +119,107 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), nite # Reduce nights by interpolation observatories, dates, α, δ = reduce_nights(radec) - # Pick three observations for Gauss method - idxs = gauss_idxs(dates, Δ) - - # [julian days] - t0, jd0, tf = datetime2julian.(dates[idxs]) - # Number of years in forward integration - nyears_fwd = (tf - jd0 + 2) / yr - # Number of years in backward integration - nyears_bwd = -(jd0 - t0 + 2) / yr + # Observations triplets + triplets = gauss_triplets(dates, Δ) - # Subset of radec for residuals - sub_radec = filter(x -> dates[idxs[1]] <= date(x) <= dates[idxs[3]], radec) + # Initial date of integration [julian days] + jd0 = zero(T) # Jet transport perturbation (ra/dec) dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃"; order = varorder) - # Gauss method solution - sol = gauss_method(observatories[idxs], dates[idxs], α[idxs] .+ dq[1:3], δ[idxs] .+ dq[4:6]; niter = niter) # Vector of errors - Q = Vector{T}(undef, length(sol)) + Q = Vector{T}(undef, 3*length(triplets)) # Vector of initial conditions - Q0 = Matrix{T}(undef, length(sol), 6) + Q0 = Matrix{T}(undef, 3*length(triplets), 6) + + # Global counter + k = 1 + # Break flag + flag = false + + # Iterate over triplets + for j in eachindex(triplets) + + # Current triplet + idxs = triplets[j] + + # [julian days] + t0, jd0, tf = datetime2julian.(dates[idxs]) + # Number of years in forward integration + nyears_fwd = (tf - jd0 + 2) / yr + # Number of years in backward integration + nyears_bwd = -(jd0 - t0 + 2) / yr - # Iterate over Gauss solutions - for i in eachindex(sol) - # Initial conditions (jet transport) - q0 = sol[i].statevect .+ eph_su(jd0 - J2000) + # Subset of radec for residuals + sub_radec = filter(x -> dates[idxs[1]] <= date(x) <= dates[idxs[3]], radec) - # Propagation - bwd, fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_bwd, nyears_fwd, q0, Val(true); - order = order, abstol = abstol, parse_eqs = parse_eqs) + # Gauss method solution + sol = gauss_method(observatories[idxs], dates[idxs], α[idxs] .+ dq[1:3], δ[idxs] .+ dq[4:6]; niter = niter) - # O-C residuals - res, w = residuals(sub_radec; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), - xva = et -> bwdfwdeph(et, bwd, fwd)) + # Iterate over Gauss solutions + for i in eachindex(sol) - # Orbit fit - success, x_new, Γ = newtonls(res, w, zeros(get_numvars()), niter) + # Initial conditions (jet transport) + q0 = sol[i].statevect .+ eph_su(jd0 - J2000) - # TO DO: check cases where newton converges but diffcorr no + # Propagation + bwd, fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_bwd, nyears_fwd, q0, Val(true); + order = order, abstol = abstol, parse_eqs = parse_eqs) + + # O-C residuals + res, w = residuals(sub_radec; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), + xva = et -> bwdfwdeph(et, bwd, fwd)) + + # Orbit fit (Newton) + success, x_new, Γ = newtonls(res, w, zeros(get_numvars()), niter) + # Normalized root mean square error + tmpQ = nrms(res(x_new), w) + + # TO DO: check cases where newton converges but diffcorr no - if success - # NRMS of the solution - Q[i] = nrms(res(x_new), w) - # Initial conditions - Q0[i, :] = bwd(bwd.t0)(x_new) - else - success, x_new, Γ = diffcorr(res, w, zeros(get_numvars()), niter) if success - Q[i] = nrms(res(x_new), w) - Q0[i, :] = bwd(bwd.t0)(x_new) + # NRMS of the solution + Q[k] = tmpQ + # Initial conditions + Q0[k, :] = bwd(bwd.t0)(x_new) + # Break condition + if tmpQ <= 1 + flag = true + end else - Q[i] = T(Inf) - Q0[i, :] .= T(Inf) + # Orbit fit (differential corrections) + success, x_new, Γ = diffcorr(res, w, zeros(get_numvars()), niter) + # Normalized root mean square error + tmpQ = nrms(res(x_new), w) + + if success + # NRMS of the solution + Q[k] = tmpQ + # Initial conditions + Q0[k, :] = bwd(bwd.t0)(x_new) + # Break condition + if tmpQ <= 1 + flag = true + end + else + Q[k] = T(Inf) + Q0[k, :] .= T(Inf) + end + end + k += 1 + # Break condition + if flag + break end - end + end + if flag + break + end end # Solution with minimum NRMS - i = findmin(Q)[2] + i = findmin(Q[1:k-1])[2] # Case: all solutions were unsuccesful if isinf(Q[i]) q00 = Vector{T}(undef, 0) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 3eebe74d..34fe10db 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -359,65 +359,50 @@ end @doc raw""" gauss_norm(dates::Vector{DateTime}) -Return a measure of how evenly distributed in time a triplet is; used within [`gauss_idxs`](@ref) to select observations +Return a measure of how evenly distributed in time a triplet is; used within [`gauss_triplets`](@ref) to sort triplets for Gauss method. The function assumes `dates` is sorted. """ gauss_norm(dates::Vector{DateTime}) = abs( (dates[2] - dates[1]).value - (dates[3] - dates[2]).value ) @doc raw""" - gauss_idxs(dates::Vector{DateTime}, Δ::DatePeriod = Day(1)) + gauss_triplets(dates::Vector{DateTime}, Δ::DatePeriod = Day(1)) -Return three indices `[i, j, k]` based on two criteria: - 1.- The three dates are separated by `Δ` as close as possible, - 2.- `|j - i|` and `|k - j|` are as close as possible. +Return a vector of triplets to be used within [`gaussinitcond`](@ref) to select the best observations for Gauss method. +The triplets are sorted by [`gauss_norm`](@ref). -See also [`gauss_norm`](@ref) and [`closest_index_sorted`](@ref). +See also [`closest_index_sorted`](@ref). """ -function gauss_idxs(dates::Vector{DateTime}, Δ::DatePeriod = Day(1)) +function gauss_triplets(dates::Vector{DateTime}, Δ::DatePeriod = Day(1)) # Number of elements L = length(dates) # Checks @assert L >= 3 "length(dates) must be at least 3" @assert issorted(dates) "Vector of dates must be sorted" - # Minimal case - if L == 3 - return [1, 2, 3] - end - # Naive indexes - if isodd(L) - best_idxs = [1, (L+1) ÷ 2, L] - else - best_idxs = [1, L ÷ 2, L] - end - # Naive norm - best_norm = gauss_norm(dates[best_idxs]) - # Temporary idexes + # Initialize triplets + triplets = Vector{Vector{Int}}(undef, L-2) + # Initialize global counter + j = 1 + # Temporary triplet idxs = [0, 0, 0] - # Temporary norm - norm = Inf - + for i in 1:L-2 - # First criterion + # Construct triplet idxs[1] = i idxs[2] = closest_index_sorted(view(dates, idxs[1]+1:L), dates[idxs[1]] + Δ) + idxs[1] if (idxs[2] == idxs[1]) || (idxs[2] > L) - break + continue else idxs[3] = closest_index_sorted(view(dates, idxs[2]+1:L), dates[idxs[2]] + Δ) + idxs[2] if (idxs[3] == idxs[2]) || (idxs[3] > L) - break + continue end end - # Second criterion - norm = gauss_norm(dates[idxs]) - # Update norm and indexes - if norm < best_norm - best_norm = norm - best_idxs .= idxs - end + # Add triplet + triplets[j] = copy(idxs) + j += 1 end - - return best_idxs + # Sort by gauss_norm + return sort(triplets[1:j-1], by = x -> gauss_norm(dates[x])) end # Empty methods to be overloaded by DataFramesExt From 9060e6717e18d2d2a997f6239ef0882b177d48db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 19 Jul 2023 13:26:56 -0600 Subject: [PATCH 011/173] Fix gauss_triplets --- ext/DataFramesExt.jl | 51 +++++++++++-------------- src/orbit_determination/gauss_method.jl | 6 +-- 2 files changed, 26 insertions(+), 31 deletions(-) diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index 2f0b387f..2672fb35 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -128,10 +128,10 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), nite # Jet transport perturbation (ra/dec) dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃"; order = varorder) - # Vector of errors - Q = Vector{T}(undef, 3*length(triplets)) - # Vector of initial conditions - Q0 = Matrix{T}(undef, 3*length(triplets), 6) + # Normalized root mean square error (NRMS) + best_Q = T(Inf) + # Initial conditions + best_Q0 = zeros(T, 6) # Global counter k = 1 @@ -173,38 +173,37 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), nite # Orbit fit (Newton) success, x_new, Γ = newtonls(res, w, zeros(get_numvars()), niter) - # Normalized root mean square error - tmpQ = nrms(res(x_new), w) + # NRMS + Q = nrms(res(x_new), w) # TO DO: check cases where newton converges but diffcorr no if success - # NRMS of the solution - Q[k] = tmpQ - # Initial conditions - Q0[k, :] = bwd(bwd.t0)(x_new) + # Update NRMS and initial conditions + if Q < best_Q + best_Q = Q + best_Q0 .= bwd(bwd.t0)(x_new) + end # Break condition - if tmpQ <= 1 + if Q <= one(T) flag = true end else # Orbit fit (differential corrections) success, x_new, Γ = diffcorr(res, w, zeros(get_numvars()), niter) - # Normalized root mean square error - tmpQ = nrms(res(x_new), w) + # NRMS + Q = nrms(res(x_new), w) if success - # NRMS of the solution - Q[k] = tmpQ - # Initial conditions - Q0[k, :] = bwd(bwd.t0)(x_new) + # Update NRMS and initial conditions + if Q < best_Q + best_Q = Q + best_Q0 .= bwd(bwd.t0)(x_new) + end # Break condition - if tmpQ <= 1 + if Q <= one(T) flag = true end - else - Q[k] = T(Inf) - Q0[k, :] .= T(Inf) end end k += 1 @@ -218,17 +217,13 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), nite end end - # Solution with minimum NRMS - i = findmin(Q[1:k-1])[2] # Case: all solutions were unsuccesful - if isinf(Q[i]) - q00 = Vector{T}(undef, 0) + if isinf(best_Q) + return jd0, Vector{T}(undef, 0) # Case: at least one solution was succesful else - q00 = Q0[i, :] + return jd0, best_Q0 end - - return jd0, q00 end end # module \ No newline at end of file diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 34fe10db..a98e6081 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -340,7 +340,7 @@ function closest_index_sorted(x::AbstractVector{T}, val::T) where {T} i = searchsortedfirst(x, val) # All x is below val if i == L + 1 - return 0 + i = L end # Left closure j = searchsortedlast(x, val) @@ -389,11 +389,11 @@ function gauss_triplets(dates::Vector{DateTime}, Δ::DatePeriod = Day(1)) # Construct triplet idxs[1] = i idxs[2] = closest_index_sorted(view(dates, idxs[1]+1:L), dates[idxs[1]] + Δ) + idxs[1] - if (idxs[2] == idxs[1]) || (idxs[2] > L) + if idxs[2] >= L continue else idxs[3] = closest_index_sorted(view(dates, idxs[2]+1:L), dates[idxs[2]] + Δ) + idxs[2] - if (idxs[3] == idxs[2]) || (idxs[3] > L) + if idxs[3] > L continue end end From 4ec4fe87778917601c1e31209106d3549adefc13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 19 Jul 2023 15:13:12 -0600 Subject: [PATCH 012/173] Add Q_max kwarg to gaussinitcond --- ext/DataFramesExt.jl | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index 2672fb35..1f58f622 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -89,8 +89,8 @@ function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} end @doc raw""" - gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), niter::Int = 5, maxsteps::Int = 100, varorder::Int = 5, - order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} + gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), Q_max::T = 0.75, niter::Int = 5, maxsteps::Int = 100, + varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} Return initial conditions via Gauss method. @@ -99,6 +99,7 @@ See also [`gauss_method`](@ref). # Arguments - `radec::Vector{RadecMPC{T}}`: vector of observations. - `Δ::DatePeriod`: see [`gauss_triplets`](@ref). +- `Q_max::T`: The maximum nrms that is considered a good enough orbit. - `niter::Int`: number of iterations for Newton's method. - `maxsteps::Int`: maximum number of steps for propagation. - `varorder::Int`: order of jet transport perturbation. @@ -109,8 +110,8 @@ See also [`gauss_method`](@ref). !!! warning This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. """ -function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), niter::Int = 5, maxsteps::Int = 100, varorder::Int = 5, - order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} +function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), Q_max::T = 0.75, niter::Int = 5, maxsteps::Int = 100, + varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} # Sun's ephemeris eph_su = selecteph(sseph, su) @@ -185,7 +186,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), nite best_Q0 .= bwd(bwd.t0)(x_new) end # Break condition - if Q <= one(T) + if Q <= Q_max flag = true end else @@ -201,7 +202,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), nite best_Q0 .= bwd(bwd.t0)(x_new) end # Break condition - if Q <= one(T) + if Q <= Q_max flag = true end end From 0ae1e2b913e0cb8e77e9d5963c67e0c22c27e951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 19 Jul 2023 16:17:50 -0600 Subject: [PATCH 013/173] Minor fix --- ext/DataFramesExt.jl | 4 ++-- src/orbit_determination/gauss_method.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index 1f58f622..e82982c3 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -1,6 +1,6 @@ module DataFramesExt -using Dates: Date, DatePeriod, Day, datetime2julian, julian2datetime +using Dates: Date, Period, Day, datetime2julian, julian2datetime using TaylorSeries: get_numvars using PlanetaryEphemeris: J2000, selecteph, su, ea, yr, daysec, auday2kmsec using NEOs: RadecMPC, date, gauss_triplets, propagate, RNp1BP_pN_A_J23E_J2S_eph_threads!, order, abstol, sseph, @@ -110,7 +110,7 @@ See also [`gauss_method`](@ref). !!! warning This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. """ -function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), Q_max::T = 0.75, niter::Int = 5, maxsteps::Int = 100, +function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::Period = Day(1), Q_max::T = 0.75, niter::Int = 5, maxsteps::Int = 100, varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} # Sun's ephemeris diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index a98e6081..10f61604 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -372,7 +372,7 @@ The triplets are sorted by [`gauss_norm`](@ref). See also [`closest_index_sorted`](@ref). """ -function gauss_triplets(dates::Vector{DateTime}, Δ::DatePeriod = Day(1)) +function gauss_triplets(dates::Vector{DateTime}, Δ::Period = Day(1)) # Number of elements L = length(dates) # Checks From 4edf7ba14bb49b38ef60c123c9e8608b6dffd4f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 19 Jul 2023 16:19:18 -0600 Subject: [PATCH 014/173] Fix documentation typo --- ext/DataFramesExt.jl | 4 ++-- src/orbit_determination/gauss_method.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index e82982c3..98558bc6 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -89,7 +89,7 @@ function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} end @doc raw""" - gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::DatePeriod = Day(1), Q_max::T = 0.75, niter::Int = 5, maxsteps::Int = 100, + gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::Period = Day(1), Q_max::T = 0.75, niter::Int = 5, maxsteps::Int = 100, varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} Return initial conditions via Gauss method. @@ -98,7 +98,7 @@ See also [`gauss_method`](@ref). # Arguments - `radec::Vector{RadecMPC{T}}`: vector of observations. -- `Δ::DatePeriod`: see [`gauss_triplets`](@ref). +- `Δ::Period`: see [`gauss_triplets`](@ref). - `Q_max::T`: The maximum nrms that is considered a good enough orbit. - `niter::Int`: number of iterations for Newton's method. - `maxsteps::Int`: maximum number of steps for propagation. diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 10f61604..4d494c3a 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -365,7 +365,7 @@ for Gauss method. The function assumes `dates` is sorted. gauss_norm(dates::Vector{DateTime}) = abs( (dates[2] - dates[1]).value - (dates[3] - dates[2]).value ) @doc raw""" - gauss_triplets(dates::Vector{DateTime}, Δ::DatePeriod = Day(1)) + gauss_triplets(dates::Vector{DateTime}, Δ::Period = Day(1)) Return a vector of triplets to be used within [`gaussinitcond`](@ref) to select the best observations for Gauss method. The triplets are sorted by [`gauss_norm`](@ref). From 3855609015d6f51f3a5929859cf0446698e4e39f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 21 Jul 2023 07:34:59 -0600 Subject: [PATCH 015/173] Fix propagate_root return --- src/propagation/propagation.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/propagation/propagation.jl b/src/propagation/propagation.jl index 7d671556..bb87819a 100644 --- a/src/propagation/propagation.jl +++ b/src/propagation/propagation.jl @@ -216,6 +216,16 @@ for V_dense in V_true_false @time sol = taylorinteg(dynamics, rvelea, _q0, _t0, _tmax, order, abstol, $V_dense(), _params; maxsteps, parse_eqs, eventorder, newtoniter, nrabstol) + + # Dense output (save Taylor polynomials in each step) + if $V_dense == Val{true} + tv, xv, psol, tvS, xvS, gvS = sol + return TaylorInterpolant(jd0 - JD_J2000, tv .- tv[1], psol), tvS, xvS, gvS + # Point output + elseif $V_dense == Val{false} + return sol + end + return sol end From a3ccc88a13d1580e988c297837999c08aed280bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 3 Aug 2023 18:46:07 -0600 Subject: [PATCH 016/173] Heliocentric energy --- ext/DataFramesExt.jl | 4 ++-- src/constants.jl | 5 ++++- src/orbit_determination/gauss_method.jl | 14 ++++++++++++++ src/propagation/propagation.jl | 9 +++++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index 98558bc6..383816dd 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -220,10 +220,10 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::Period = Day(1), Q_max::T # Case: all solutions were unsuccesful if isinf(best_Q) - return jd0, Vector{T}(undef, 0) + return jd0::T, Vector{T}(undef, 0) # Case: at least one solution was succesful else - return jd0, best_Q0 + return jd0::T, best_Q0 end end diff --git a/src/constants.jl b/src/constants.jl index 4adf666d..e577e0ed 100644 --- a/src/constants.jl +++ b/src/constants.jl @@ -69,4 +69,7 @@ const d_EM_au = 384_400 / au # Zeroth order obliquity of the ecliptic in degrees # See equation (5-153) in page 5-61 of https://doi.org/10.1002/0471728470. -const ϵ0_deg = 84381.448/3_600 \ No newline at end of file +const ϵ0_deg = 84381.448/3_600 + +# Gauss gravitational constant +const k_gauss = 0.017_202_098_95 \ No newline at end of file diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 4d494c3a..df33b162 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -161,6 +161,18 @@ function solve_lagrange(a::TaylorN{T}, b::TaylorN{T}, c::TaylorN{T}; niter::Int return sol, status[idxs] end +@doc raw""" + heliocentric_energy(r::Vector{T}) where {T <: Number} + +Return the heliocentric energy per unit mass for heliocentric state vector `r` [au, au/day]. +""" +function heliocentric_energy(r::Vector{T}) where {T <: Number} + @assert length(r) == 6 "r must have length 6" + kinetic = 0.5 * (r[4]^2 + r[5]^2 + r[6]^2) + potential = k_gauss^2 / sqrt(r[1]^2 + r[2]^2 + r[3]^2) + return kinetic - potential +end + @doc raw""" gauss_method(obs::Vector{RadecMPC{T}}; niter::Int = 5) where {T <: AbstractFloat} gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{DateTime}, α::Vector{U}, δ::Vector{U}; @@ -306,6 +318,8 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da sol_gauss[i] = GaussSolution{T, U}(vcat(r_vec[2, :], v_2_vec), D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3, status[i]) end + filter!(x -> heliocentric_energy(x.statevect) <= 0, sol_gauss) + return sort!(sol_gauss, by = x -> norm(x.statevect[1:3])) end diff --git a/src/propagation/propagation.jl b/src/propagation/propagation.jl index bb87819a..eaf05074 100644 --- a/src/propagation/propagation.jl +++ b/src/propagation/propagation.jl @@ -161,6 +161,9 @@ for V_dense in V_true_false μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: Real, U <: Number, D} + # Check order + @assert order <= get_order(sseph.x[1]) "order ($(order)) must be less or equal than SS ephemeris order ($(get_order(sseph.x[1])))" + # Parameters for taylorinteg _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast = μ_ast, order = order, abstol = abstol) @@ -209,6 +212,9 @@ for V_dense in V_true_false eventorder::Int = 0, newtoniter::Int = 10, nrabstol::T = eps(T), μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number, D} + # Check order + @assert order <= get_order(sseph.x[1]) "order ($(order)) must be less or equal than SS ephemeris order ($(get_order(sseph.x[1])))" + # Parameters for neosinteg _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast = μ_ast, order = order, abstol = abstol) @@ -282,6 +288,9 @@ Compute the Lyapunov spectrum of a NEO. function propagate_lyap(dynamics::D, maxsteps::Int, jd0::T, tspan::T, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: Real, U <: Number, D} + # Check order + @assert order <= get_order(sseph.x[1]) "order ($(order)) must be less or equal than SS ephemeris order ($(get_order(sseph.x[1])))" + # Parameters for taylorinteg _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast = μ_ast, order = order, abstol = abstol) From 4ab88fb43fc6d642692e4ded7994e31ba8cbff08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 4 Aug 2023 18:15:10 -0600 Subject: [PATCH 017/173] Modify gauss_triplets --- ext/DataFramesExt.jl | 2 +- src/observations/radec_mpc.jl | 2 +- src/orbit_determination/gauss_method.jl | 21 +++++++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index 383816dd..472fa6a9 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -121,7 +121,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::Period = Day(1), Q_max::T # Reduce nights by interpolation observatories, dates, α, δ = reduce_nights(radec) # Observations triplets - triplets = gauss_triplets(dates, Δ) + triplets = gauss_triplets(dates) # Initial date of integration [julian days] jd0 = zero(T) diff --git a/src/observations/radec_mpc.jl b/src/observations/radec_mpc.jl index caa40457..6209f7f9 100644 --- a/src/observations/radec_mpc.jl +++ b/src/observations/radec_mpc.jl @@ -501,7 +501,7 @@ end Download MPC optical astrometry of NEO `id` and save the output to `filename`. """ -function get_radec_mpc(id::AbstractString, filename::AbstractString) +function get_radec_mpc(id::AbstractString, filename::AbstractString = replace(id, " " => "_") * ".txt") # MPC search url search_url = search_mpc_url * replace(id, " " => "+") # MPC observations file url diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index df33b162..ab0cc5be 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -386,6 +386,7 @@ The triplets are sorted by [`gauss_norm`](@ref). See also [`closest_index_sorted`](@ref). """ +#= function gauss_triplets(dates::Vector{DateTime}, Δ::Period = Day(1)) # Number of elements L = length(dates) @@ -418,6 +419,26 @@ function gauss_triplets(dates::Vector{DateTime}, Δ::Period = Day(1)) # Sort by gauss_norm return sort(triplets[1:j-1], by = x -> gauss_norm(dates[x])) end +=# +function gauss_triplets(dates::Vector{DateTime}; Δ_min::Period = Hour(1), Δ_max::Period = Day(7), N::Int = 10) + triplets = Vector{Vector{Int}}(undef, 0) + L = length(dates) + for i_1 in 1:L-2 + for i_2 in i_1+1:L-1 + for i_3 in i_2+1:L + if Δ_min <= dates[i_3] - dates[i_1] <= Δ_max + push!(triplets, [i_1, i_2, i_3]) + end + end + end + end + + sort!(triplets, by = x -> gauss_norm(dates[x])) + + n = min(length(triplets), N) + + return triplets[1:n] +end # Empty methods to be overloaded by DataFramesExt function reduce_nights end From 0346d4dab1c0b9012c2d09ded9b460a28134f88d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 4 Aug 2023 18:29:47 -0600 Subject: [PATCH 018/173] Change min delta --- ext/DataFramesExt.jl | 7 ++++--- src/orbit_determination/gauss_method.jl | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index 472fa6a9..b51c1429 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -110,8 +110,9 @@ See also [`gauss_method`](@ref). !!! warning This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. """ -function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::Period = Day(1), Q_max::T = 0.75, niter::Int = 5, maxsteps::Int = 100, - varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} +function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ_min::Period = Hour(20), Δ_max::Period = Day(7), max_triplets::Int = 10, + Q_max::T = 0.75, niter::Int = 5, maxsteps::Int = 100, varorder::Int = 5, order::Int = order, + abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} # Sun's ephemeris eph_su = selecteph(sseph, su) @@ -121,7 +122,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::Period = Day(1), Q_max::T # Reduce nights by interpolation observatories, dates, α, δ = reduce_nights(radec) # Observations triplets - triplets = gauss_triplets(dates) + triplets = gauss_triplets(dates; Δ_min = Δ_min, Δ_max = Δ_max, max_triplets = max_triplets) # Initial date of integration [julian days] jd0 = zero(T) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index ab0cc5be..49a0ee2a 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -420,7 +420,7 @@ function gauss_triplets(dates::Vector{DateTime}, Δ::Period = Day(1)) return sort(triplets[1:j-1], by = x -> gauss_norm(dates[x])) end =# -function gauss_triplets(dates::Vector{DateTime}; Δ_min::Period = Hour(1), Δ_max::Period = Day(7), N::Int = 10) +function gauss_triplets(dates::Vector{DateTime}; Δ_min::Period = Hour(20), Δ_max::Period = Day(7), max_triplets::Int = 10) triplets = Vector{Vector{Int}}(undef, 0) L = length(dates) for i_1 in 1:L-2 @@ -435,7 +435,7 @@ function gauss_triplets(dates::Vector{DateTime}; Δ_min::Period = Hour(1), Δ_ma sort!(triplets, by = x -> gauss_norm(dates[x])) - n = min(length(triplets), N) + n = min(length(triplets), max_triplets) return triplets[1:n] end From 6c86a85bffd604ca2614b6d5fa60399044d5fb83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 4 Aug 2023 18:32:43 -0600 Subject: [PATCH 019/173] Minor fix --- ext/DataFramesExt.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index b51c1429..e4198d4f 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -1,6 +1,6 @@ module DataFramesExt -using Dates: Date, Period, Day, datetime2julian, julian2datetime +using Dates: Date, Period, Hour, Day, datetime2julian, julian2datetime using TaylorSeries: get_numvars using PlanetaryEphemeris: J2000, selecteph, su, ea, yr, daysec, auday2kmsec using NEOs: RadecMPC, date, gauss_triplets, propagate, RNp1BP_pN_A_J23E_J2S_eph_threads!, order, abstol, sseph, From e1c7a883d185c3bbcf07b8ac9a609424615ccd34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 5 Aug 2023 09:46:31 -0600 Subject: [PATCH 020/173] Add tryls --- src/postprocessing/least_squares.jl | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/postprocessing/least_squares.jl b/src/postprocessing/least_squares.jl index 664c0521..3bb2025d 100644 --- a/src/postprocessing/least_squares.jl +++ b/src/postprocessing/least_squares.jl @@ -293,6 +293,29 @@ function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, niters:: return true, x_new, Γ end +function tryls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, niters::Int = 5) where {T <: Real} + # Newton's method + success_1, x_1, Γ_1 = newtonls(res, w, x0, niters) + # Differential corrections + success_2, x_2, Γ_2 = diffcorr(res, w, x0, niters) + if success_1 && success_2 + Q_1 = nrms(res(x_1), w) + Q_2 = nrms(res(x_2), w) + if Q_1 <= Q_2 + return success_1, x_1, Γ_1 + else + return success_2, x_2, Γ_2 + end + elseif success_1 + return success_1, x_1, Γ_1 + elseif success_2 + return success_2, x_2, Γ_2 + else + return false, x_1, Γ_1 + end + +end + @doc raw""" newtonls_Q(Q, nobs, x0, niters=5) From 605654d1b567d79ef2fce8991067b149d0b414de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 6 Aug 2023 12:17:29 -0600 Subject: [PATCH 021/173] Adaptative time delta --- ext/DataFramesExt.jl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index e4198d4f..1604adc2 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -122,7 +122,14 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ_min::Period = Hour(20), Δ # Reduce nights by interpolation observatories, dates, α, δ = reduce_nights(radec) # Observations triplets - triplets = gauss_triplets(dates; Δ_min = Δ_min, Δ_max = Δ_max, max_triplets = max_triplets) + Δ_min = Hour(20) + Δ_max = Day(7) + triplets = Vector{Vector{Int}}(undef, 0) + while iszero(length(triplets)) || Δ_min.value > 0 + triplets = gauss_triplets(dates; Δ_min = Δ_min, Δ_max = Δ_max, max_triplets = max_triplets) + Δ_min -= Hour(1) + Δ_max += Day(1) + end # Initial date of integration [julian days] jd0 = zero(T) From 72dff6abb0110ccf0d862e49e84c176d394eff39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 6 Aug 2023 12:24:08 -0600 Subject: [PATCH 022/173] Minor correction --- ext/DataFramesExt.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index 1604adc2..e3081f47 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -125,7 +125,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ_min::Period = Hour(20), Δ Δ_min = Hour(20) Δ_max = Day(7) triplets = Vector{Vector{Int}}(undef, 0) - while iszero(length(triplets)) || Δ_min.value > 0 + while iszero(length(triplets)) && Δ_min.value > 0 triplets = gauss_triplets(dates; Δ_min = Δ_min, Δ_max = Δ_max, max_triplets = max_triplets) Δ_min -= Hour(1) Δ_max += Day(1) From e7efe248ce5024da6692d308c10fbc2aba469d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 6 Aug 2023 16:27:14 -0600 Subject: [PATCH 023/173] Modify gauss_triplets --- ext/DataFramesExt.jl | 16 ++--- src/orbit_determination/gauss_method.jl | 85 ++++++------------------- 2 files changed, 25 insertions(+), 76 deletions(-) diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index e3081f47..8bc7fc49 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -110,9 +110,8 @@ See also [`gauss_method`](@ref). !!! warning This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. """ -function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ_min::Period = Hour(20), Δ_max::Period = Day(7), max_triplets::Int = 10, - Q_max::T = 0.75, niter::Int = 5, maxsteps::Int = 100, varorder::Int = 5, order::Int = order, - abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} +function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max::T = 0.5, niter::Int = 5, maxsteps::Int = 100, + varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} # Sun's ephemeris eph_su = selecteph(sseph, su) @@ -122,15 +121,8 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; Δ_min::Period = Hour(20), Δ # Reduce nights by interpolation observatories, dates, α, δ = reduce_nights(radec) # Observations triplets - Δ_min = Hour(20) - Δ_max = Day(7) - triplets = Vector{Vector{Int}}(undef, 0) - while iszero(length(triplets)) && Δ_min.value > 0 - triplets = gauss_triplets(dates; Δ_min = Δ_min, Δ_max = Δ_max, max_triplets = max_triplets) - Δ_min -= Hour(1) - Δ_max += Day(1) - end - + triplets = gauss_triplets(dates, max_triplets) + # Initial date of integration [julian days] jd0 = zero(T) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 49a0ee2a..c853d631 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -342,34 +342,6 @@ function extrapolation(x::AbstractVector{T}, y::AbstractVector{T}) where {T <: R return etpf end -@doc raw""" - closest_index_sorted(x::AbstractVector{T}, val::T) where {T} - -Return the index of the element in `x` that is closest to `val`, assuming `x` is sorted. -""" -function closest_index_sorted(x::AbstractVector{T}, val::T) where {T} - # Number of elements - L = length(x) - # Right closure - i = searchsortedfirst(x, val) - # All x is below val - if i == L + 1 - i = L - end - # Left closure - j = searchsortedlast(x, val) - # All x is above val - if j == 0 - j = 1 - end - # Choose closest element - if abs(x[i] - val) < abs(x[j] - val) - return i - else - return j - end -end - @doc raw""" gauss_norm(dates::Vector{DateTime}) @@ -386,48 +358,16 @@ The triplets are sorted by [`gauss_norm`](@ref). See also [`closest_index_sorted`](@ref). """ -#= -function gauss_triplets(dates::Vector{DateTime}, Δ::Period = Day(1)) - # Number of elements - L = length(dates) - # Checks - @assert L >= 3 "length(dates) must be at least 3" - @assert issorted(dates) "Vector of dates must be sorted" - # Initialize triplets - triplets = Vector{Vector{Int}}(undef, L-2) - # Initialize global counter - j = 1 - # Temporary triplet - idxs = [0, 0, 0] +function gauss_triplets(dates::Vector{DateTime}, Δ_min::Period, Δ_max::Period, avoid::Vector{Vector{Int}}, max_triplets) - for i in 1:L-2 - # Construct triplet - idxs[1] = i - idxs[2] = closest_index_sorted(view(dates, idxs[1]+1:L), dates[idxs[1]] + Δ) + idxs[1] - if idxs[2] >= L - continue - else - idxs[3] = closest_index_sorted(view(dates, idxs[2]+1:L), dates[idxs[2]] + Δ) + idxs[2] - if idxs[3] > L - continue - end - end - # Add triplet - triplets[j] = copy(idxs) - j += 1 - end - # Sort by gauss_norm - return sort(triplets[1:j-1], by = x -> gauss_norm(dates[x])) -end -=# -function gauss_triplets(dates::Vector{DateTime}; Δ_min::Period = Hour(20), Δ_max::Period = Day(7), max_triplets::Int = 10) triplets = Vector{Vector{Int}}(undef, 0) L = length(dates) for i_1 in 1:L-2 for i_2 in i_1+1:L-1 for i_3 in i_2+1:L - if Δ_min <= dates[i_3] - dates[i_1] <= Δ_max - push!(triplets, [i_1, i_2, i_3]) + tmp = [i_1, i_2, i_3] + if (Δ_min <= dates[i_3] - dates[i_1] <= Δ_max) && !(tmp in avoid) + push!(triplets, tmp) end end end @@ -440,6 +380,23 @@ function gauss_triplets(dates::Vector{DateTime}; Δ_min::Period = Hour(20), Δ_m return triplets[1:n] end +function gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10) + Δ_min = Hour(20) + Δ_max = Day(7) + + triplets = Vector{Vector{Int}}(undef, 0) + + while length(triplets) < max_triplets + triplets = vcat(triplets, gauss_triplets(dates, Δ_min, Δ_max, triplets, max_triplets)) + if Δ_min >= Hour(1) + Δ_min -= Hour(1) + end + Δ_max += Day(1) + end + + return triplets[1:max_triplets] +end + # Empty methods to be overloaded by DataFramesExt function reduce_nights end function gaussinitcond end \ No newline at end of file From f08c44577efbf214fd526cbd544b8cc7a7a7ec14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Mon, 7 Aug 2023 15:28:05 -0600 Subject: [PATCH 024/173] Relaxation factor --- ext/DataFramesExt.jl | 86 +++++++++++++------------ pha/apophis.jl | 24 +++---- src/NEOs.jl | 2 +- src/orbit_determination/gauss_method.jl | 3 +- src/postprocessing/least_squares.jl | 60 ++++++++++++----- 5 files changed, 103 insertions(+), 72 deletions(-) diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index 8bc7fc49..d1f07cd2 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -4,10 +4,10 @@ using Dates: Date, Period, Hour, Day, datetime2julian, julian2datetime using TaylorSeries: get_numvars using PlanetaryEphemeris: J2000, selecteph, su, ea, yr, daysec, auday2kmsec using NEOs: RadecMPC, date, gauss_triplets, propagate, RNp1BP_pN_A_J23E_J2S_eph_threads!, order, abstol, sseph, - scaled_variables, gauss_method, residuals, bwdfwdeph, newtonls, diffcorr, nrms, hascoord + scaled_variables, gauss_method, residuals, bwdfwdeph, newtonls, diffcorr, nrms, hascoord, tryls import Base: convert -import NEOs: AbstractAstrometry, extrapolation, reduce_nights, gaussinitcond +import NEOs: AbstractAstrometry, extrapolation, reduce_nights, gaussinitcond, relax_factor if isdefined(Base, :get_extension) using DataFrames: AbstractDataFrame, DataFrame, nrow, eachcol, eachrow, groupby, combine @@ -72,8 +72,6 @@ via polynomial interpolation. function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} # Convert to DataFrame df = DataFrame(radec) - # Eliminate observatories without coordinates - filter!(:observatory => hascoord, df) # Group by observatory and Date df.Date = Date.(df.date) gdf = groupby(df, [:observatory, :Date]) @@ -88,6 +86,20 @@ function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} return cdf.observatory, cdf.date, cdf.α, cdf.δ end +function relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + # Convert to DataFrame + df = DataFrame(radec) + # Group by observatory and Date + df.Date = Date.(df.date) + gdf = groupby(df, [:observatory, :Date]) + # Interpolate observation nights + cdf = combine(gdf, nrow) + # Count observations in each group + Nv = cdf[gdf.groups, :nrow] + # Relaxation factor + return map(x -> x > 4.0 ? x/4.0 : 1.0, Nv) +end + @doc raw""" gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::Period = Day(1), Q_max::T = 0.75, niter::Int = 5, maxsteps::Int = 100, varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} @@ -110,7 +122,7 @@ See also [`gauss_method`](@ref). !!! warning This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. """ -function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max::T = 0.5, niter::Int = 5, maxsteps::Int = 100, +function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max::T = 100., niter::Int = 5, maxsteps::Int = 100, varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} # Sun's ephemeris @@ -118,12 +130,16 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max # Earth's ephemeris eph_ea = selecteph(sseph, ea) + # Eliminate observatories without coordinates + filter!(x -> hascoord(x.observatory), radec) # Reduce nights by interpolation observatories, dates, α, δ = reduce_nights(radec) # Observations triplets triplets = gauss_triplets(dates, max_triplets) - - # Initial date of integration [julian days] + + # Julian day of first (last) observation + t0, tf = datetime2julian(radec[1].date), datetime2julian(radec[end].date) + # Julian day when to start propagation jd0 = zero(T) # Jet transport perturbation (ra/dec) @@ -133,9 +149,6 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max best_Q = T(Inf) # Initial conditions best_Q0 = zeros(T, 6) - - # Global counter - k = 1 # Break flag flag = false @@ -143,20 +156,17 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max for j in eachindex(triplets) # Current triplet - idxs = triplets[j] + triplet = triplets[j] - # [julian days] - t0, jd0, tf = datetime2julian.(dates[idxs]) + # Julian day when to start propagation + jd0 = datetime2julian(dates[triplet[2]]) # Number of years in forward integration nyears_fwd = (tf - jd0 + 2) / yr # Number of years in backward integration nyears_bwd = -(jd0 - t0 + 2) / yr - # Subset of radec for residuals - sub_radec = filter(x -> dates[idxs[1]] <= date(x) <= dates[idxs[3]], radec) - # Gauss method solution - sol = gauss_method(observatories[idxs], dates[idxs], α[idxs] .+ dq[1:3], δ[idxs] .+ dq[4:6]; niter = niter) + sol = gauss_method(observatories[triplet], dates[triplet], α[triplet] .+ dq[1:3], δ[triplet] .+ dq[4:6]; niter = niter) # Iterate over Gauss solutions for i in eachindex(sol) @@ -169,45 +179,37 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max order = order, abstol = abstol, parse_eqs = parse_eqs) # O-C residuals - res, w = residuals(sub_radec; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), - xva = et -> bwdfwdeph(et, bwd, fwd)) + res, w = residuals(radec; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), + xva = et -> bwdfwdeph(et, bwd, fwd)) + + # Subset of radec for orbit fit + i_O = findall(x -> dates[triplet[1]] <= date(x) <= dates[triplet[3]], radec) + i_ξ = vcat(i_O, i_O .+ length(radec)) + + # Relaxation factor + rex = relax_factor(radec) + rex = vcat(rex, rex) + w = w ./ rex + + # Orbit fit + fit = tryls(res[i_ξ], w[i_ξ], zeros(get_numvars()), niter) - # Orbit fit (Newton) - success, x_new, Γ = newtonls(res, w, zeros(get_numvars()), niter) # NRMS - Q = nrms(res(x_new), w) + Q = nrms(res(fit.x), w) # TO DO: check cases where newton converges but diffcorr no - if success + if fit.success # Update NRMS and initial conditions if Q < best_Q best_Q = Q - best_Q0 .= bwd(bwd.t0)(x_new) + best_Q0 .= bwd(bwd.t0)(fit.x) end # Break condition if Q <= Q_max flag = true end - else - # Orbit fit (differential corrections) - success, x_new, Γ = diffcorr(res, w, zeros(get_numvars()), niter) - # NRMS - Q = nrms(res(x_new), w) - - if success - # Update NRMS and initial conditions - if Q < best_Q - best_Q = Q - best_Q0 .= bwd(bwd.t0)(x_new) - end - # Break condition - if Q <= Q_max - flag = true - end - end end - k += 1 # Break condition if flag break diff --git a/pha/apophis.jl b/pha/apophis.jl index fdca5417..e7442acb 100644 --- a/pha/apophis.jl +++ b/pha/apophis.jl @@ -231,9 +231,9 @@ function main(dynamics::D, maxsteps::Int, jd0_datetime::DateTime, nyears_bwd::T, res = vcat(res_radec, res_del, res_dop) w = vcat(w_radec, w_del, w_dop) - success, δx_OR8, Γ_OR8 = newtonls(res, w, zeros(get_numvars()), 10) - x_OR8 = sol_fwd(sol_fwd.t0)(δx_OR8) - σ_OR8 = sqrt.(diag(Γ_OR8)).*scalings + fit_OR8 = newtonls(res, w, zeros(get_numvars()), 10) + x_OR8 = sol_fwd(sol_fwd.t0)(fit_OR8.x) + σ_OR8 = sqrt.(diag(fit_OR8.Γ)).*scalings nradec = length(res_radec) res_ra = view(res_radec, 1:nradec÷2) @@ -246,19 +246,19 @@ function main(dynamics::D, maxsteps::Int, jd0_datetime::DateTime, nyears_bwd::T, print_header("Orbital fit (8-DOF) and post-fit statistics", 2) # orbital fit - println("Success flag : ", success, "\n") + println("Success flag : ", fit_OR8.success, "\n") println("Nominal solution [au,au,au,au/d,au/d,au/d,au/d²,au/d²]: ", x_OR8, "\n") println("1-sigma formal uncertainties [au,au,au,au/d,au/d,au/d,au/d²,au/d²]: ", σ_OR8, "\n") # post-fit statistics - println("Normalized RMS (optical-only) [adimensional] : ", nrms(res_radec(δx_OR8),w_radec)) - println("Normalized RMS (radar-only) [adimensional] : ", nrms(vcat(res_del,res_dop)(δx_OR8),vcat(w_del,w_dop))) - println("Normalized RMS (combined optical and radar) [adimensional] : ", nrms(res(δx_OR8),w), "\n") - println("Mean weighted right-ascension residual [arcseconds] : ", mean(res_ra(δx_OR8), weights(w_ra))) - println("Mean weighted declination residual [arcseconds] : ", mean(res_dec(δx_OR8), weights(w_dec))) - println("Mean weighted time-delay residual [micro-seconds]: ", mean(res_del(δx_OR8), weights(w_del))) - println("Mean weighted Doppler-shift residual [Hz] : ", mean(res_dop(δx_OR8), weights(w_dop)), "\n") - println("Chi-squared statistic (χ²): [adimensional] : ", chi2(res(δx_OR8),w)) + println("Normalized RMS (optical-only) [adimensional] : ", nrms(res_radec(fit_OR8.x),w_radec)) + println("Normalized RMS (radar-only) [adimensional] : ", nrms(vcat(res_del,res_dop)(fit_OR8.x),vcat(w_del,w_dop))) + println("Normalized RMS (combined optical and radar) [adimensional] : ", nrms(res(fit_OR8.x),w), "\n") + println("Mean weighted right-ascension residual [arcseconds] : ", mean(res_ra(fit_OR8.x), weights(w_ra))) + println("Mean weighted declination residual [arcseconds] : ", mean(res_dec(fit_OR8.x), weights(w_dec))) + println("Mean weighted time-delay residual [micro-seconds]: ", mean(res_del(fit_OR8.x), weights(w_del))) + println("Mean weighted Doppler-shift residual [Hz] : ", mean(res_dop(fit_OR8.x), weights(w_dop)), "\n") + println("Chi-squared statistic (χ²): [adimensional] : ", chi2(res(fit_OR8.x),w)) return sol_bwd, sol_fwd, res_radec, res_del, res_dop, w_radec, w_del, w_dop end diff --git a/src/NEOs.jl b/src/NEOs.jl index 720a0e5a..fe0d7fa2 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -64,7 +64,7 @@ export RNp1BP_pN_A_J23E_J2S_ng_eph_threads!, RNp1BP_pN_A_J23E_J2S_eph_threads! # Propagate export propagate, propagate_lyap, propagate_root -export valsecchi_circle, nrms, chi2, newtonls, newtonls_6v, diffcorr, newtonls_Q, bopik +export valsecchi_circle, nrms, chi2, newtonls, newtonls_6v, diffcorr, newtonls_Q, bopik, tryls, project include("constants.jl") include("observations/process_radar.jl") diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index c853d631..0be7286b 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -399,4 +399,5 @@ end # Empty methods to be overloaded by DataFramesExt function reduce_nights end -function gaussinitcond end \ No newline at end of file +function gaussinitcond end +function relax_factor end \ No newline at end of file diff --git a/src/postprocessing/least_squares.jl b/src/postprocessing/least_squares.jl index 3bb2025d..5e70f170 100644 --- a/src/postprocessing/least_squares.jl +++ b/src/postprocessing/least_squares.jl @@ -1,5 +1,33 @@ include("b_plane.jl") +struct OrbitFit{T <: Real} + success::Bool + x::Vector{T} + Γ::Matrix{T} + routine::Symbol + OrbitFit{T}(success::Bool, x::Vector{T}, Γ::Matrix{T}, routine::Symbol) where {T <: Real} = new{T}(success, x, Γ, routine) +end + +OrbitFit(success::Bool, x::Vector{T}, Γ::Matrix{T}, routine::Symbol) where {T <: Real} = OrbitFit{T}(success, x, Γ, routine) + +# Print method for OrbitFit +# Examples: +# N00hp15 α: 608995.65 δ: -25653.3 t: 2020-12-04T10:41:43.209 obs: 703 +# 99942 α: 422475.3 δ: 97289.49 t: 2021-05-12T06:28:35.904 obs: F51 +function show(io::IO, fit::OrbitFit{T}) where {T <: Real} + success_s = fit.success ? "Succesful" : "Unsuccesful" + routine_s = fit.routine == :newton ? "Newton" : "differential corrections" + print(io, success_s, " ", routine_s) +end + +function project(y::Vector{TaylorN{T}}, fit::OrbitFit{T}) where {T <: Real} + J = Matrix{T}(undef, get_numvars(), length(y)) + for i in eachindex(y) + J[:, i] = TS.gradient(y[i])(fit.x) + end + return (J') * fit.Γ * J +end + @doc raw""" nrms(res, w) @@ -194,7 +222,7 @@ function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, niters:: error[i+1] = sqrt(error2) # The method do not converge else - return false, x[:, i+1], inv(C) + return OrbitFit(false, x[:, i+1], inv(C), :diffcorr) end end # Index with the lowest error @@ -206,7 +234,7 @@ function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, niters:: # Covariance matrix Γ = inv(C) - return true, x_new, Γ + return OrbitFit(true, x_new, Γ, :diffcorr) end @doc raw""" @@ -274,7 +302,7 @@ function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, niters:: error[i+1] = sqrt(error2) # The method do not converge else - return false, x[:, i+1], inv(C) + return OrbitFit(false, x[:, i+1], inv(C), :newton) end end # TO DO: study Gauss method solution dependence on jt order @@ -290,28 +318,28 @@ function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, niters:: # Covariance matrix Γ = inv(C) - return true, x_new, Γ + return OrbitFit(true, x_new, Γ, :newton) end function tryls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, niters::Int = 5) where {T <: Real} # Newton's method - success_1, x_1, Γ_1 = newtonls(res, w, x0, niters) + fit_1 = newtonls(res, w, x0, niters) # Differential corrections - success_2, x_2, Γ_2 = diffcorr(res, w, x0, niters) - if success_1 && success_2 - Q_1 = nrms(res(x_1), w) - Q_2 = nrms(res(x_2), w) + fit_2 = diffcorr(res, w, x0, niters) + if fit_1.success && fit_2.success + Q_1 = nrms(res(fit_1.x), w) + Q_2 = nrms(res(fit_2.x), w) if Q_1 <= Q_2 - return success_1, x_1, Γ_1 + return fit_1 else - return success_2, x_2, Γ_2 + return fit_2 end - elseif success_1 - return success_1, x_1, Γ_1 - elseif success_2 - return success_2, x_2, Γ_2 + elseif fit_1.success + return fit_1 + elseif fit_2.success + return fit_2 else - return false, x_1, Γ_1 + return fit_1 end end From 152dd47a7543303c62bae4835e0b578b7f3a7bbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 8 Aug 2023 16:54:57 -0600 Subject: [PATCH 025/173] Fix infinite while --- src/orbit_determination/gauss_method.jl | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 0be7286b..3224bd3c 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -380,21 +380,26 @@ function gauss_triplets(dates::Vector{DateTime}, Δ_min::Period, Δ_max::Period, return triplets[1:n] end -function gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10) +function gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_iter::Int = 100) Δ_min = Hour(20) Δ_max = Day(7) triplets = Vector{Vector{Int}}(undef, 0) - while length(triplets) < max_triplets + niter = 0 + + while length(triplets) < max_triplets && niter < max_iter triplets = vcat(triplets, gauss_triplets(dates, Δ_min, Δ_max, triplets, max_triplets)) if Δ_min >= Hour(1) Δ_min -= Hour(1) end Δ_max += Day(1) + niter += 1 end - return triplets[1:max_triplets] + n = min(length(triplets), max_triplets) + + return triplets[1:n] end # Empty methods to be overloaded by DataFramesExt From 30f7cd49896c019f4dab09d869d660759b1acd2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 10 Aug 2023 16:42:59 -0600 Subject: [PATCH 026/173] Fix M_ --- src/propagation/asteroid_dynamical_models.jl | 8 +- src/propagation/jetcoeffs.jl | 2430 +++++++++--------- 2 files changed, 1221 insertions(+), 1217 deletions(-) diff --git a/src/propagation/asteroid_dynamical_models.jl b/src/propagation/asteroid_dynamical_models.jl index 6a6535c1..89ee8718 100644 --- a/src/propagation/asteroid_dynamical_models.jl +++ b/src/propagation/asteroid_dynamical_models.jl @@ -306,8 +306,8 @@ function RNp1BP_pN_A_J23E_J2S_ng_eph_threads!(dq, q, params, t) # Rotations to and from Earth, Sun and Moon pole-oriented frames local M_ = Array{S}(undef, 3, 3, N) - - local M_[:,:,ea] = t2c_jpl_de430(dsj2k) + local M_ .= zero_q_1 + local M_[:, :, ea] .= t2c_jpl_de430(dsj2k)[:, :] .+ zero_q_1 # Fill first 3 elements of dq with velocities dq[1] = q[4] @@ -873,8 +873,8 @@ function RNp1BP_pN_A_J23E_J2S_eph_threads!(dq, q, params, t) # Rotations to and from Earth, Sun and Moon pole-oriented frames local M_ = Array{S}(undef, 3, 3, N) - - local M_[:,:,ea] = t2c_jpl_de430(dsj2k) + local M_ .= zero_q_1 + local M_[:, :, ea] .= t2c_jpl_de430(dsj2k)[:, :] .+ zero_q_1 # Fill first 3 elements of dq with velocities dq[1] = q[4] diff --git a/src/propagation/jetcoeffs.jl b/src/propagation/jetcoeffs.jl index 11944f69..9547bbdc 100644 --- a/src/propagation/jetcoeffs.jl +++ b/src/propagation/jetcoeffs.jl @@ -138,94 +138,95 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_ep accY = Taylor1(identity(constant_term(zero_q_1)), order) accZ = Taylor1(identity(constant_term(zero_q_1)), order) local M_ = Array{S}(undef, 3, 3, N) - local M_[:, :, ea] = t2c_jpl_de430(dsj2k) + local M_ .= zero_q_1 + local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 dq[1] = Taylor1(identity(constant_term(q[4])), order) dq[2] = Taylor1(identity(constant_term(q[5])), order) dq[3] = Taylor1(identity(constant_term(q[6])), order) newtonianNb_Potential[N] = Taylor1(identity(constant_term(zero_q_1)), order) - tmp1343 = Array{Taylor1{_S}}(undef, size(dq)) - tmp1343 .= Taylor1(zero(_S), order) - tmp1345 = Array{Taylor1{_S}}(undef, size(ui)) - tmp1345 .= Taylor1(zero(_S), order) - tmp1348 = Array{Taylor1{_S}}(undef, size(dq)) - tmp1348 .= Taylor1(zero(_S), order) - tmp1350 = Array{Taylor1{_S}}(undef, size(vi)) - tmp1350 .= Taylor1(zero(_S), order) - tmp1353 = Array{Taylor1{_S}}(undef, size(dq)) - tmp1353 .= Taylor1(zero(_S), order) - tmp1355 = Array{Taylor1{_S}}(undef, size(wi)) - tmp1355 .= Taylor1(zero(_S), order) + tmp687 = Array{Taylor1{_S}}(undef, size(dq)) + tmp687 .= Taylor1(zero(_S), order) + tmp689 = Array{Taylor1{_S}}(undef, size(ui)) + tmp689 .= Taylor1(zero(_S), order) + tmp692 = Array{Taylor1{_S}}(undef, size(dq)) + tmp692 .= Taylor1(zero(_S), order) + tmp694 = Array{Taylor1{_S}}(undef, size(vi)) + tmp694 .= Taylor1(zero(_S), order) + tmp697 = Array{Taylor1{_S}}(undef, size(dq)) + tmp697 .= Taylor1(zero(_S), order) + tmp699 = Array{Taylor1{_S}}(undef, size(wi)) + tmp699 .= Taylor1(zero(_S), order) pn2x = Array{Taylor1{_S}}(undef, size(X)) pn2x .= Taylor1(zero(_S), order) pn2y = Array{Taylor1{_S}}(undef, size(Y)) pn2y .= Taylor1(zero(_S), order) pn2z = Array{Taylor1{_S}}(undef, size(Z)) pn2z .= Taylor1(zero(_S), order) - tmp1363 = Array{Taylor1{_S}}(undef, size(UU)) - tmp1363 .= Taylor1(zero(_S), order) - tmp1366 = Array{Taylor1{_S}}(undef, size(X)) - tmp1366 .= Taylor1(zero(_S), order) - tmp1368 = Array{Taylor1{_S}}(undef, size(Y)) - tmp1368 .= Taylor1(zero(_S), order) - tmp1369 = Array{Taylor1{_S}}(undef, size(tmp1366)) - tmp1369 .= Taylor1(zero(_S), order) - tmp1371 = Array{Taylor1{_S}}(undef, size(Z)) - tmp1371 .= Taylor1(zero(_S), order) - tmp1379 = Array{Taylor1{_S}}(undef, size(pn2x)) - tmp1379 .= Taylor1(zero(_S), order) - tmp1380 = Array{Taylor1{_S}}(undef, size(tmp1379)) - tmp1380 .= Taylor1(zero(_S), order) - tmp1475 = Array{Taylor1{_S}}(undef, size(ui)) - tmp1475 .= Taylor1(zero(_S), order) - tmp1477 = Array{Taylor1{_S}}(undef, size(vi)) - tmp1477 .= Taylor1(zero(_S), order) - tmp1478 = Array{Taylor1{_S}}(undef, size(tmp1475)) - tmp1478 .= Taylor1(zero(_S), order) - tmp1480 = Array{Taylor1{_S}}(undef, size(wi)) - tmp1480 .= Taylor1(zero(_S), order) - tmp1391 = Array{Taylor1{_S}}(undef, size(X)) - tmp1391 .= Taylor1(zero(_S), order) - tmp1393 = Array{Taylor1{_S}}(undef, size(Y)) - tmp1393 .= Taylor1(zero(_S), order) - tmp1395 = Array{Taylor1{_S}}(undef, size(Z)) - tmp1395 .= Taylor1(zero(_S), order) - tmp1397 = Array{Taylor1{_S}}(undef, size(t31)) - tmp1397 .= Taylor1(zero(_S), order) - tmp1604 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp1604 .= Taylor1(zero(_S), order) - tmp1605 = Array{Taylor1{_S}}(undef, size(ϕ)) - tmp1605 .= Taylor1(zero(_S), order) - tmp1407 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp1407 .= Taylor1(zero(_S), order) - tmp1413 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp1413 .= Taylor1(zero(_S), order) - tmp1415 = Array{Taylor1{_S}}(undef, size(sin3_ϕ)) - tmp1415 .= Taylor1(zero(_S), order) - tmp1419 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp1419 .= Taylor1(zero(_S), order) - tmp1422 = Array{Taylor1{_S}}(undef, size(r_p2)) - tmp1422 .= Taylor1(zero(_S), order) - tmp1423 = Array{Taylor1{_S}}(undef, size(Λ2)) - tmp1423 .= Taylor1(zero(_S), order) - tmp1426 = Array{Taylor1{_S}}(undef, size(r_p1d2)) - tmp1426 .= Taylor1(zero(_S), order) - tmp1427 = Array{Taylor1{_S}}(undef, size(Λ3)) - tmp1427 .= Taylor1(zero(_S), order) - tmp1429 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp1429 .= Taylor1(zero(_S), order) - tmp1431 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp1431 .= Taylor1(zero(_S), order) - tmp1434 = Array{Taylor1{_S}}(undef, size(Λ2j_div_r4)) - tmp1434 .= Taylor1(zero(_S), order) - tmp1438 = Array{Taylor1{_S}}(undef, size(Λ3j_div_r5)) - tmp1438 .= Taylor1(zero(_S), order) - tmp1441 = Array{Taylor1{_S}}(undef, size(X)) - tmp1441 .= Taylor1(zero(_S), order) - tmp1443 = Array{Taylor1{_S}}(undef, size(Y)) - tmp1443 .= Taylor1(zero(_S), order) - tmp1445 = Array{Taylor1{_S}}(undef, size(Z)) - tmp1445 .= Taylor1(zero(_S), order) - #= C:\Users\luisi\.julia\dev\NEOs.jl\ex.jl:245 =# Threads.@threads for i = 1:Nm1 + tmp707 = Array{Taylor1{_S}}(undef, size(UU)) + tmp707 .= Taylor1(zero(_S), order) + tmp710 = Array{Taylor1{_S}}(undef, size(X)) + tmp710 .= Taylor1(zero(_S), order) + tmp712 = Array{Taylor1{_S}}(undef, size(Y)) + tmp712 .= Taylor1(zero(_S), order) + tmp713 = Array{Taylor1{_S}}(undef, size(tmp710)) + tmp713 .= Taylor1(zero(_S), order) + tmp715 = Array{Taylor1{_S}}(undef, size(Z)) + tmp715 .= Taylor1(zero(_S), order) + tmp723 = Array{Taylor1{_S}}(undef, size(pn2x)) + tmp723 .= Taylor1(zero(_S), order) + tmp724 = Array{Taylor1{_S}}(undef, size(tmp723)) + tmp724 .= Taylor1(zero(_S), order) + tmp819 = Array{Taylor1{_S}}(undef, size(ui)) + tmp819 .= Taylor1(zero(_S), order) + tmp821 = Array{Taylor1{_S}}(undef, size(vi)) + tmp821 .= Taylor1(zero(_S), order) + tmp822 = Array{Taylor1{_S}}(undef, size(tmp819)) + tmp822 .= Taylor1(zero(_S), order) + tmp824 = Array{Taylor1{_S}}(undef, size(wi)) + tmp824 .= Taylor1(zero(_S), order) + tmp735 = Array{Taylor1{_S}}(undef, size(X)) + tmp735 .= Taylor1(zero(_S), order) + tmp737 = Array{Taylor1{_S}}(undef, size(Y)) + tmp737 .= Taylor1(zero(_S), order) + tmp739 = Array{Taylor1{_S}}(undef, size(Z)) + tmp739 .= Taylor1(zero(_S), order) + tmp741 = Array{Taylor1{_S}}(undef, size(t31)) + tmp741 .= Taylor1(zero(_S), order) + tmp948 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) + tmp948 .= Taylor1(zero(_S), order) + tmp949 = Array{Taylor1{_S}}(undef, size(ϕ)) + tmp949 .= Taylor1(zero(_S), order) + tmp751 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) + tmp751 .= Taylor1(zero(_S), order) + tmp757 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) + tmp757 .= Taylor1(zero(_S), order) + tmp759 = Array{Taylor1{_S}}(undef, size(sin3_ϕ)) + tmp759 .= Taylor1(zero(_S), order) + tmp763 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) + tmp763 .= Taylor1(zero(_S), order) + tmp766 = Array{Taylor1{_S}}(undef, size(r_p2)) + tmp766 .= Taylor1(zero(_S), order) + tmp767 = Array{Taylor1{_S}}(undef, size(Λ2)) + tmp767 .= Taylor1(zero(_S), order) + tmp770 = Array{Taylor1{_S}}(undef, size(r_p1d2)) + tmp770 .= Taylor1(zero(_S), order) + tmp771 = Array{Taylor1{_S}}(undef, size(Λ3)) + tmp771 .= Taylor1(zero(_S), order) + tmp773 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) + tmp773 .= Taylor1(zero(_S), order) + tmp775 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) + tmp775 .= Taylor1(zero(_S), order) + tmp778 = Array{Taylor1{_S}}(undef, size(Λ2j_div_r4)) + tmp778 .= Taylor1(zero(_S), order) + tmp782 = Array{Taylor1{_S}}(undef, size(Λ3j_div_r5)) + tmp782 .= Taylor1(zero(_S), order) + tmp785 = Array{Taylor1{_S}}(undef, size(X)) + tmp785 .= Taylor1(zero(_S), order) + tmp787 = Array{Taylor1{_S}}(undef, size(Y)) + tmp787 .= Taylor1(zero(_S), order) + tmp789 = Array{Taylor1{_S}}(undef, size(Z)) + tmp789 .= Taylor1(zero(_S), order) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 ui[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])), order) vi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])), order) wi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])), order) @@ -235,35 +236,35 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_ep U[i] = Taylor1(constant_term(ui[i]) - constant_term(dq[1]), order) V[i] = Taylor1(constant_term(vi[i]) - constant_term(dq[2]), order) W[i] = Taylor1(constant_term(wi[i]) - constant_term(dq[3]), order) - tmp1343[1] = Taylor1(constant_term(4) * constant_term(dq[1]), order) - tmp1345[i] = Taylor1(constant_term(3) * constant_term(ui[i]), order) - _4U_m_3X[i] = Taylor1(constant_term(tmp1343[1]) - constant_term(tmp1345[i]), order) - tmp1348[2] = Taylor1(constant_term(4) * constant_term(dq[2]), order) - tmp1350[i] = Taylor1(constant_term(3) * constant_term(vi[i]), order) - _4V_m_3Y[i] = Taylor1(constant_term(tmp1348[2]) - constant_term(tmp1350[i]), order) - tmp1353[3] = Taylor1(constant_term(4) * constant_term(dq[3]), order) - tmp1355[i] = Taylor1(constant_term(3) * constant_term(wi[i]), order) - _4W_m_3Z[i] = Taylor1(constant_term(tmp1353[3]) - constant_term(tmp1355[i]), order) + tmp687[1] = Taylor1(constant_term(4) * constant_term(dq[1]), order) + tmp689[i] = Taylor1(constant_term(3) * constant_term(ui[i]), order) + _4U_m_3X[i] = Taylor1(constant_term(tmp687[1]) - constant_term(tmp689[i]), order) + tmp692[2] = Taylor1(constant_term(4) * constant_term(dq[2]), order) + tmp694[i] = Taylor1(constant_term(3) * constant_term(vi[i]), order) + _4V_m_3Y[i] = Taylor1(constant_term(tmp692[2]) - constant_term(tmp694[i]), order) + tmp697[3] = Taylor1(constant_term(4) * constant_term(dq[3]), order) + tmp699[i] = Taylor1(constant_term(3) * constant_term(wi[i]), order) + _4W_m_3Z[i] = Taylor1(constant_term(tmp697[3]) - constant_term(tmp699[i]), order) pn2x[i] = Taylor1(constant_term(X[i]) * constant_term(_4U_m_3X[i]), order) pn2y[i] = Taylor1(constant_term(Y[i]) * constant_term(_4V_m_3Y[i]), order) pn2z[i] = Taylor1(constant_term(Z[i]) * constant_term(_4W_m_3Z[i]), order) UU[i] = Taylor1(constant_term(ui[i]) * constant_term(dq[1]), order) VV[i] = Taylor1(constant_term(vi[i]) * constant_term(dq[2]), order) WW[i] = Taylor1(constant_term(wi[i]) * constant_term(dq[3]), order) - tmp1363[i] = Taylor1(constant_term(UU[i]) + constant_term(VV[i]), order) - vi_dot_vj[i] = Taylor1(constant_term(tmp1363[i]) + constant_term(WW[i]), order) - tmp1366[i] = Taylor1(constant_term(X[i]) ^ float(constant_term(2)), order) - tmp1368[i] = Taylor1(constant_term(Y[i]) ^ float(constant_term(2)), order) - tmp1369[i] = Taylor1(constant_term(tmp1366[i]) + constant_term(tmp1368[i]), order) - tmp1371[i] = Taylor1(constant_term(Z[i]) ^ float(constant_term(2)), order) - r_p2[i] = Taylor1(constant_term(tmp1369[i]) + constant_term(tmp1371[i]), order) + tmp707[i] = Taylor1(constant_term(UU[i]) + constant_term(VV[i]), order) + vi_dot_vj[i] = Taylor1(constant_term(tmp707[i]) + constant_term(WW[i]), order) + tmp710[i] = Taylor1(constant_term(X[i]) ^ float(constant_term(2)), order) + tmp712[i] = Taylor1(constant_term(Y[i]) ^ float(constant_term(2)), order) + tmp713[i] = Taylor1(constant_term(tmp710[i]) + constant_term(tmp712[i]), order) + tmp715[i] = Taylor1(constant_term(Z[i]) ^ float(constant_term(2)), order) + r_p2[i] = Taylor1(constant_term(tmp713[i]) + constant_term(tmp715[i]), order) r_p1d2[i] = Taylor1(sqrt(constant_term(r_p2[i])), order) r_p3d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(1.5)), order) r_p7d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(3.5)), order) newtonianCoeff[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p3d2[i]), order) - tmp1379[i] = Taylor1(constant_term(pn2x[i]) + constant_term(pn2y[i]), order) - tmp1380[i] = Taylor1(constant_term(tmp1379[i]) + constant_term(pn2z[i]), order) - pn2[i] = Taylor1(constant_term(newtonianCoeff[i]) * constant_term(tmp1380[i]), order) + tmp723[i] = Taylor1(constant_term(pn2x[i]) + constant_term(pn2y[i]), order) + tmp724[i] = Taylor1(constant_term(tmp723[i]) + constant_term(pn2z[i]), order) + pn2[i] = Taylor1(constant_term(newtonianCoeff[i]) * constant_term(tmp724[i]), order) newton_acc_X[i] = Taylor1(constant_term(X[i]) * constant_term(newtonianCoeff[i]), order) newton_acc_Y[i] = Taylor1(constant_term(Y[i]) * constant_term(newtonianCoeff[i]), order) newton_acc_Z[i] = Taylor1(constant_term(Z[i]) * constant_term(newtonianCoeff[i]), order) @@ -273,53 +274,53 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_ep V_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(V[i]), order) W_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(W[i]), order) if UJ_interaction[i] - tmp1391[i] = Taylor1(-(constant_term(X[i])), order) - t31[i] = Taylor1(constant_term(tmp1391[i]) * constant_term(M_[1, 3, i]), order) - tmp1393[i] = Taylor1(-(constant_term(Y[i])), order) - t32[i] = Taylor1(constant_term(tmp1393[i]) * constant_term(M_[2, 3, i]), order) - tmp1395[i] = Taylor1(-(constant_term(Z[i])), order) - t33[i] = Taylor1(constant_term(tmp1395[i]) * constant_term(M_[3, 3, i]), order) - tmp1397[i] = Taylor1(constant_term(t31[i]) + constant_term(t32[i]), order) - r_sin_ϕ[i] = Taylor1(constant_term(tmp1397[i]) + constant_term(t33[i]), order) + tmp735[i] = Taylor1(-(constant_term(X[i])), order) + t31[i] = Taylor1(constant_term(tmp735[i]) * constant_term(M_[1, 3, i]), order) + tmp737[i] = Taylor1(-(constant_term(Y[i])), order) + t32[i] = Taylor1(constant_term(tmp737[i]) * constant_term(M_[2, 3, i]), order) + tmp739[i] = Taylor1(-(constant_term(Z[i])), order) + t33[i] = Taylor1(constant_term(tmp739[i]) * constant_term(M_[3, 3, i]), order) + tmp741[i] = Taylor1(constant_term(t31[i]) + constant_term(t32[i]), order) + r_sin_ϕ[i] = Taylor1(constant_term(tmp741[i]) + constant_term(t33[i]), order) sin_ϕ[i] = Taylor1(constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]), order) ϕ[i] = Taylor1(asin(constant_term(sin_ϕ[i])), order) - tmp1604[i] = Taylor1(sqrt(1 - constant_term(sin_ϕ[i]) ^ 2), order) + tmp948[i] = Taylor1(sqrt(1 - constant_term(sin_ϕ[i]) ^ 2), order) cos_ϕ[i] = Taylor1(cos(constant_term(ϕ[i])), order) - tmp1605[i] = Taylor1(sin(constant_term(ϕ[i])), order) + tmp949[i] = Taylor1(sin(constant_term(ϕ[i])), order) sin2_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(2)), order) sin3_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(3)), order) - tmp1407[i] = Taylor1(constant_term(1.5) * constant_term(sin2_ϕ[i]), order) - P_2_sin_ϕ[i] = Taylor1(constant_term(tmp1407[i]) - constant_term(0.5), order) + tmp751[i] = Taylor1(constant_term(1.5) * constant_term(sin2_ϕ[i]), order) + P_2_sin_ϕ[i] = Taylor1(constant_term(tmp751[i]) - constant_term(0.5), order) ∂P_2_sin_ϕ[i] = Taylor1(constant_term(3) * constant_term(sin_ϕ[i]), order) - tmp1413[i] = Taylor1(constant_term(-1.5) * constant_term(sin_ϕ[i]), order) - tmp1415[i] = Taylor1(constant_term(2.5) * constant_term(sin3_ϕ[i]), order) - P_3_sin_ϕ[i] = Taylor1(constant_term(tmp1413[i]) + constant_term(tmp1415[i]), order) - tmp1419[i] = Taylor1(constant_term(7.5) * constant_term(sin2_ϕ[i]), order) - ∂P_3_sin_ϕ[i] = Taylor1(constant_term(-1.5) + constant_term(tmp1419[i]), order) - tmp1422[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(2)), order) - tmp1423[i] = Taylor1(constant_term(Λ2[i]) / constant_term(tmp1422[i]), order) - Λ2j_div_r4[i] = Taylor1(-(constant_term(tmp1423[i])), order) - tmp1426[i] = Taylor1(constant_term(r_p1d2[i]) ^ float(constant_term(5)), order) - tmp1427[i] = Taylor1(constant_term(Λ3[i]) / constant_term(tmp1426[i]), order) - Λ3j_div_r5[i] = Taylor1(-(constant_term(tmp1427[i])), order) - tmp1429[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) - m_c_ϕ_∂P_2[i] = Taylor1(constant_term(tmp1429[i]) * constant_term(∂P_2_sin_ϕ[i]), order) - tmp1431[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) - m_c_ϕ_∂P_3[i] = Taylor1(constant_term(tmp1431[i]) * constant_term(∂P_3_sin_ϕ[i]), order) - tmp1434[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(3), order) - F_J2_ξ[i] = Taylor1(constant_term(tmp1434[i]) * constant_term(P_2_sin_ϕ[i]), order) + tmp757[i] = Taylor1(constant_term(-1.5) * constant_term(sin_ϕ[i]), order) + tmp759[i] = Taylor1(constant_term(2.5) * constant_term(sin3_ϕ[i]), order) + P_3_sin_ϕ[i] = Taylor1(constant_term(tmp757[i]) + constant_term(tmp759[i]), order) + tmp763[i] = Taylor1(constant_term(7.5) * constant_term(sin2_ϕ[i]), order) + ∂P_3_sin_ϕ[i] = Taylor1(constant_term(-1.5) + constant_term(tmp763[i]), order) + tmp766[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(2)), order) + tmp767[i] = Taylor1(constant_term(Λ2[i]) / constant_term(tmp766[i]), order) + Λ2j_div_r4[i] = Taylor1(-(constant_term(tmp767[i])), order) + tmp770[i] = Taylor1(constant_term(r_p1d2[i]) ^ float(constant_term(5)), order) + tmp771[i] = Taylor1(constant_term(Λ3[i]) / constant_term(tmp770[i]), order) + Λ3j_div_r5[i] = Taylor1(-(constant_term(tmp771[i])), order) + tmp773[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) + m_c_ϕ_∂P_2[i] = Taylor1(constant_term(tmp773[i]) * constant_term(∂P_2_sin_ϕ[i]), order) + tmp775[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) + m_c_ϕ_∂P_3[i] = Taylor1(constant_term(tmp775[i]) * constant_term(∂P_3_sin_ϕ[i]), order) + tmp778[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(3), order) + F_J2_ξ[i] = Taylor1(constant_term(tmp778[i]) * constant_term(P_2_sin_ϕ[i]), order) F_J2_ζ[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]), order) - tmp1438[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(4), order) - F_J3_ξ[i] = Taylor1(constant_term(tmp1438[i]) * constant_term(P_3_sin_ϕ[i]), order) + tmp782[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(4), order) + F_J3_ξ[i] = Taylor1(constant_term(tmp782[i]) * constant_term(P_3_sin_ϕ[i]), order) F_J3_ζ[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]), order) F_J_ξ[i] = Taylor1(identity(constant_term(F_J2_ξ[i])), order) F_J_ζ[i] = Taylor1(identity(constant_term(F_J2_ζ[i])), order) - tmp1441[i] = Taylor1(-(constant_term(X[i])), order) - ξx[i] = Taylor1(constant_term(tmp1441[i]) / constant_term(r_p1d2[i]), order) - tmp1443[i] = Taylor1(-(constant_term(Y[i])), order) - ξy[i] = Taylor1(constant_term(tmp1443[i]) / constant_term(r_p1d2[i]), order) - tmp1445[i] = Taylor1(-(constant_term(Z[i])), order) - ξz[i] = Taylor1(constant_term(tmp1445[i]) / constant_term(r_p1d2[i]), order) + tmp785[i] = Taylor1(-(constant_term(X[i])), order) + ξx[i] = Taylor1(constant_term(tmp785[i]) / constant_term(r_p1d2[i]), order) + tmp787[i] = Taylor1(-(constant_term(Y[i])), order) + ξy[i] = Taylor1(constant_term(tmp787[i]) / constant_term(r_p1d2[i]), order) + tmp789[i] = Taylor1(-(constant_term(Z[i])), order) + ξz[i] = Taylor1(constant_term(tmp789[i]) / constant_term(r_p1d2[i]), order) ηx1[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξz[i]), order) ηy1[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξx[i]), order) ηz1[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξy[i]), order) @@ -348,95 +349,95 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_ep F_J2_y[i] = Taylor1(constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]), order) F_J2_z[i] = Taylor1(constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]), order) end - tmp1475[i] = Taylor1(constant_term(ui[i]) ^ float(constant_term(2)), order) - tmp1477[i] = Taylor1(constant_term(vi[i]) ^ float(constant_term(2)), order) - tmp1478[i] = Taylor1(constant_term(tmp1475[i]) + constant_term(tmp1477[i]), order) - tmp1480[i] = Taylor1(constant_term(wi[i]) ^ float(constant_term(2)), order) - v2[i] = Taylor1(constant_term(tmp1478[i]) + constant_term(tmp1480[i]), order) + tmp819[i] = Taylor1(constant_term(ui[i]) ^ float(constant_term(2)), order) + tmp821[i] = Taylor1(constant_term(vi[i]) ^ float(constant_term(2)), order) + tmp822[i] = Taylor1(constant_term(tmp819[i]) + constant_term(tmp821[i]), order) + tmp824[i] = Taylor1(constant_term(wi[i]) ^ float(constant_term(2)), order) + v2[i] = Taylor1(constant_term(tmp822[i]) + constant_term(tmp824[i]), order) end - tmp1483 = Taylor1(constant_term(q[4]) ^ float(constant_term(2)), order) - tmp1485 = Taylor1(constant_term(q[5]) ^ float(constant_term(2)), order) - tmp1486 = Taylor1(constant_term(tmp1483) + constant_term(tmp1485), order) - tmp1488 = Taylor1(constant_term(q[6]) ^ float(constant_term(2)), order) - v2[N] = Taylor1(constant_term(tmp1486) + constant_term(tmp1488), order) + tmp827 = Taylor1(constant_term(q[4]) ^ float(constant_term(2)), order) + tmp829 = Taylor1(constant_term(q[5]) ^ float(constant_term(2)), order) + tmp830 = Taylor1(constant_term(tmp827) + constant_term(tmp829), order) + tmp832 = Taylor1(constant_term(q[6]) ^ float(constant_term(2)), order) + v2[N] = Taylor1(constant_term(tmp830) + constant_term(tmp832), order) temp_004 = Array{Taylor1{_S}}(undef, size(newtonian1b_Potential)) temp_004 .= Taylor1(zero(_S), order) - tmp1491 = Array{Taylor1{_S}}(undef, size(μ)) - tmp1491 .= Taylor1(zero(_S), order) - tmp1493 = Array{Taylor1{_S}}(undef, size(μ)) - tmp1493 .= Taylor1(zero(_S), order) - tmp1495 = Array{Taylor1{_S}}(undef, size(μ)) - tmp1495 .= Taylor1(zero(_S), order) + tmp835 = Array{Taylor1{_S}}(undef, size(μ)) + tmp835 .= Taylor1(zero(_S), order) + tmp837 = Array{Taylor1{_S}}(undef, size(μ)) + tmp837 .= Taylor1(zero(_S), order) + tmp839 = Array{Taylor1{_S}}(undef, size(μ)) + tmp839 .= Taylor1(zero(_S), order) for i = 1:Nm1 temp_004[i] = Taylor1(constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]), order) newtonianNb_Potential[N] = Taylor1(identity(constant_term(temp_004[i])), order) if UJ_interaction[i] - tmp1491[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_x[i]), order) - temp_accX_i[i] = Taylor1(constant_term(accX) - constant_term(tmp1491[i]), order) + tmp835[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_x[i]), order) + temp_accX_i[i] = Taylor1(constant_term(accX) - constant_term(tmp835[i]), order) accX = Taylor1(identity(constant_term(temp_accX_i[i])), order) - tmp1493[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_y[i]), order) - temp_accY_i[i] = Taylor1(constant_term(accY) - constant_term(tmp1493[i]), order) + tmp837[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_y[i]), order) + temp_accY_i[i] = Taylor1(constant_term(accY) - constant_term(tmp837[i]), order) accY = Taylor1(identity(constant_term(temp_accY_i[i])), order) - tmp1495[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_z[i]), order) - temp_accZ_i[i] = Taylor1(constant_term(accZ) - constant_term(tmp1495[i]), order) + tmp839[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_z[i]), order) + temp_accZ_i[i] = Taylor1(constant_term(accZ) - constant_term(tmp839[i]), order) accZ = Taylor1(identity(constant_term(temp_accZ_i[i])), order) end end _4ϕj[N] = Taylor1(constant_term(4) * constant_term(newtonianNb_Potential[N]), order) - tmp1501 = Array{Taylor1{_S}}(undef, size(v2)) - tmp1501 .= Taylor1(zero(_S), order) - tmp1503 = Array{Taylor1{_S}}(undef, size(vi_dot_vj)) - tmp1503 .= Taylor1(zero(_S), order) - tmp1504 = Array{Taylor1{_S}}(undef, size(tmp1501)) - tmp1504 .= Taylor1(zero(_S), order) + tmp845 = Array{Taylor1{_S}}(undef, size(v2)) + tmp845 .= Taylor1(zero(_S), order) + tmp847 = Array{Taylor1{_S}}(undef, size(vi_dot_vj)) + tmp847 .= Taylor1(zero(_S), order) + tmp848 = Array{Taylor1{_S}}(undef, size(tmp845)) + tmp848 .= Taylor1(zero(_S), order) Xij_t_Ui = Array{Taylor1{_S}}(undef, size(X)) Xij_t_Ui .= Taylor1(zero(_S), order) Yij_t_Vi = Array{Taylor1{_S}}(undef, size(Y)) Yij_t_Vi .= Taylor1(zero(_S), order) Zij_t_Wi = Array{Taylor1{_S}}(undef, size(Z)) Zij_t_Wi .= Taylor1(zero(_S), order) - tmp1510 = Array{Taylor1{_S}}(undef, size(Xij_t_Ui)) - tmp1510 .= Taylor1(zero(_S), order) - Rij_dot_Vi = Array{Taylor1{_S}}(undef, size(tmp1510)) + tmp854 = Array{Taylor1{_S}}(undef, size(Xij_t_Ui)) + tmp854 .= Taylor1(zero(_S), order) + Rij_dot_Vi = Array{Taylor1{_S}}(undef, size(tmp854)) Rij_dot_Vi .= Taylor1(zero(_S), order) - tmp1513 = Array{Taylor1{_S}}(undef, size(Rij_dot_Vi)) - tmp1513 .= Taylor1(zero(_S), order) - pn1t7 = Array{Taylor1{_S}}(undef, size(tmp1513)) + tmp857 = Array{Taylor1{_S}}(undef, size(Rij_dot_Vi)) + tmp857 .= Taylor1(zero(_S), order) + pn1t7 = Array{Taylor1{_S}}(undef, size(tmp857)) pn1t7 .= Taylor1(zero(_S), order) - tmp1516 = Array{Taylor1{_S}}(undef, size(pn1t7)) - tmp1516 .= Taylor1(zero(_S), order) + tmp860 = Array{Taylor1{_S}}(undef, size(pn1t7)) + tmp860 .= Taylor1(zero(_S), order) pn1t2_7 = Array{Taylor1{_S}}(undef, size(ϕs_and_vs)) pn1t2_7 .= Taylor1(zero(_S), order) - tmp1523 = Array{Taylor1{_S}}(undef, size(pNX_t_X)) - tmp1523 .= Taylor1(zero(_S), order) - tmp1524 = Array{Taylor1{_S}}(undef, size(tmp1523)) - tmp1524 .= Taylor1(zero(_S), order) - tmp1525 = Array{Taylor1{_S}}(undef, size(tmp1524)) - tmp1525 .= Taylor1(zero(_S), order) - #= C:\Users\luisi\.julia\dev\NEOs.jl\ex.jl:447 =# Threads.@threads for i = 1:10 + tmp867 = Array{Taylor1{_S}}(undef, size(pNX_t_X)) + tmp867 .= Taylor1(zero(_S), order) + tmp868 = Array{Taylor1{_S}}(undef, size(tmp867)) + tmp868 .= Taylor1(zero(_S), order) + tmp869 = Array{Taylor1{_S}}(undef, size(tmp868)) + tmp869 .= Taylor1(zero(_S), order) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 ϕi_plus_4ϕj[i] = Taylor1(constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]), order) - tmp1501[i] = Taylor1(constant_term(2) * constant_term(v2[i]), order) - tmp1503[i] = Taylor1(constant_term(4) * constant_term(vi_dot_vj[i]), order) - tmp1504[i] = Taylor1(constant_term(tmp1501[i]) - constant_term(tmp1503[i]), order) - sj2_plus_2si2_minus_4vivj[i] = Taylor1(constant_term(tmp1504[i]) + constant_term(v2[N]), order) + tmp845[i] = Taylor1(constant_term(2) * constant_term(v2[i]), order) + tmp847[i] = Taylor1(constant_term(4) * constant_term(vi_dot_vj[i]), order) + tmp848[i] = Taylor1(constant_term(tmp845[i]) - constant_term(tmp847[i]), order) + sj2_plus_2si2_minus_4vivj[i] = Taylor1(constant_term(tmp848[i]) + constant_term(v2[N]), order) ϕs_and_vs[i] = Taylor1(constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]), order) Xij_t_Ui[i] = Taylor1(constant_term(X[i]) * constant_term(ui[i]), order) Yij_t_Vi[i] = Taylor1(constant_term(Y[i]) * constant_term(vi[i]), order) Zij_t_Wi[i] = Taylor1(constant_term(Z[i]) * constant_term(wi[i]), order) - tmp1510[i] = Taylor1(constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]), order) - Rij_dot_Vi[i] = Taylor1(constant_term(tmp1510[i]) + constant_term(Zij_t_Wi[i]), order) - tmp1513[i] = Taylor1(constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)), order) - pn1t7[i] = Taylor1(constant_term(tmp1513[i]) / constant_term(r_p2[i]), order) - tmp1516[i] = Taylor1(constant_term(1.5) * constant_term(pn1t7[i]), order) - pn1t2_7[i] = Taylor1(constant_term(ϕs_and_vs[i]) - constant_term(tmp1516[i]), order) + tmp854[i] = Taylor1(constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]), order) + Rij_dot_Vi[i] = Taylor1(constant_term(tmp854[i]) + constant_term(Zij_t_Wi[i]), order) + tmp857[i] = Taylor1(constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)), order) + pn1t7[i] = Taylor1(constant_term(tmp857[i]) / constant_term(r_p2[i]), order) + tmp860[i] = Taylor1(constant_term(1.5) * constant_term(pn1t7[i]), order) + pn1t2_7[i] = Taylor1(constant_term(ϕs_and_vs[i]) - constant_term(tmp860[i]), order) pn1t1_7[i] = Taylor1(constant_term(c_p2) + constant_term(pn1t2_7[i]), order) pNX_t_X[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(X[i]), order) pNY_t_Y[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(Y[i]), order) pNZ_t_Z[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(Z[i]), order) - tmp1523[i] = Taylor1(constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]), order) - tmp1524[i] = Taylor1(constant_term(tmp1523[i]) + constant_term(pNZ_t_Z[i]), order) - tmp1525[i] = Taylor1(constant_term(0.5) * constant_term(tmp1524[i]), order) - pn1[i] = Taylor1(constant_term(pn1t1_7[i]) + constant_term(tmp1525[i]), order) + tmp867[i] = Taylor1(constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]), order) + tmp868[i] = Taylor1(constant_term(tmp867[i]) + constant_term(pNZ_t_Z[i]), order) + tmp869[i] = Taylor1(constant_term(0.5) * constant_term(tmp868[i]), order) + pn1[i] = Taylor1(constant_term(pn1t1_7[i]) + constant_term(tmp869[i]), order) X_t_pn1[i] = Taylor1(constant_term(newton_acc_X[i]) * constant_term(pn1[i]), order) Y_t_pn1[i] = Taylor1(constant_term(newton_acc_Y[i]) * constant_term(pn1[i]), order) Z_t_pn1[i] = Taylor1(constant_term(newton_acc_Z[i]) * constant_term(pn1[i]), order) @@ -444,39 +445,39 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_ep pNY_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]), order) pNZ_t_pn3[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(pn3[i]), order) end - tmp1533 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) - tmp1533 .= Taylor1(zero(_S), order) + tmp877 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) + tmp877 .= Taylor1(zero(_S), order) termpnx = Array{Taylor1{_S}}(undef, size(X_t_pn1)) termpnx .= Taylor1(zero(_S), order) sumpnx = Array{Taylor1{_S}}(undef, size(termpnx)) sumpnx .= Taylor1(zero(_S), order) - tmp1536 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) - tmp1536 .= Taylor1(zero(_S), order) + tmp880 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) + tmp880 .= Taylor1(zero(_S), order) termpny = Array{Taylor1{_S}}(undef, size(Y_t_pn1)) termpny .= Taylor1(zero(_S), order) sumpny = Array{Taylor1{_S}}(undef, size(termpny)) sumpny .= Taylor1(zero(_S), order) - tmp1539 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) - tmp1539 .= Taylor1(zero(_S), order) + tmp883 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) + tmp883 .= Taylor1(zero(_S), order) termpnz = Array{Taylor1{_S}}(undef, size(Z_t_pn1)) termpnz .= Taylor1(zero(_S), order) sumpnz = Array{Taylor1{_S}}(undef, size(termpnz)) sumpnz .= Taylor1(zero(_S), order) for i = 1:10 - tmp1533[i] = Taylor1(constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]), order) - termpnx[i] = Taylor1(constant_term(X_t_pn1[i]) + constant_term(tmp1533[i]), order) + tmp877[i] = Taylor1(constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]), order) + termpnx[i] = Taylor1(constant_term(X_t_pn1[i]) + constant_term(tmp877[i]), order) sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) - tmp1536[i] = Taylor1(constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]), order) - termpny[i] = Taylor1(constant_term(Y_t_pn1[i]) + constant_term(tmp1536[i]), order) + tmp880[i] = Taylor1(constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]), order) + termpny[i] = Taylor1(constant_term(Y_t_pn1[i]) + constant_term(tmp880[i]), order) sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) pntempY = Taylor1(identity(constant_term(sumpny[i])), order) - tmp1539[i] = Taylor1(constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]), order) - termpnz[i] = Taylor1(constant_term(Z_t_pn1[i]) + constant_term(tmp1539[i]), order) + tmp883[i] = Taylor1(constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]), order) + termpnz[i] = Taylor1(constant_term(Z_t_pn1[i]) + constant_term(tmp883[i]), order) sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) end - #= C:\Users\luisi\.julia\dev\NEOs.jl\ex.jl:500 =# Threads.@threads for i = 11:Nm1 + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 X_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_X[i]), order) Y_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Y[i]), order) Z_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Z[i]), order) @@ -495,97 +496,97 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_ep postNewtonX = Taylor1(constant_term(pntempX) * constant_term(c_m2), order) postNewtonY = Taylor1(constant_term(pntempY) * constant_term(c_m2), order) postNewtonZ = Taylor1(constant_term(pntempZ) * constant_term(c_m2), order) - tmp1551 = Taylor1(constant_term(Y[1]) * constant_term(W[1]), order) - tmp1552 = Taylor1(constant_term(Z[1]) * constant_term(V[1]), order) - hx = Taylor1(constant_term(tmp1551) - constant_term(tmp1552), order) - tmp1554 = Taylor1(constant_term(Z[1]) * constant_term(U[1]), order) - tmp1555 = Taylor1(constant_term(X[1]) * constant_term(W[1]), order) - hy = Taylor1(constant_term(tmp1554) - constant_term(tmp1555), order) - tmp1557 = Taylor1(constant_term(X[1]) * constant_term(V[1]), order) - tmp1558 = Taylor1(constant_term(Y[1]) * constant_term(U[1]), order) - hz = Taylor1(constant_term(tmp1557) - constant_term(tmp1558), order) - tmp1560 = Taylor1(constant_term(hz) * constant_term(Y[1]), order) - tmp1561 = Taylor1(constant_term(hy) * constant_term(Z[1]), order) - t_x = Taylor1(constant_term(tmp1560) - constant_term(tmp1561), order) - tmp1563 = Taylor1(constant_term(hx) * constant_term(Z[1]), order) - tmp1564 = Taylor1(constant_term(hz) * constant_term(X[1]), order) - t_y = Taylor1(constant_term(tmp1563) - constant_term(tmp1564), order) - tmp1566 = Taylor1(constant_term(hy) * constant_term(X[1]), order) - tmp1567 = Taylor1(constant_term(hx) * constant_term(Y[1]), order) - t_z = Taylor1(constant_term(tmp1566) - constant_term(tmp1567), order) - tmp1570 = Taylor1(constant_term(t_x) ^ float(constant_term(2)), order) - tmp1572 = Taylor1(constant_term(t_y) ^ float(constant_term(2)), order) - tmp1573 = Taylor1(constant_term(tmp1570) + constant_term(tmp1572), order) - tmp1575 = Taylor1(constant_term(t_z) ^ float(constant_term(2)), order) - tmp1576 = Taylor1(constant_term(tmp1573) + constant_term(tmp1575), order) - t_norm = Taylor1(sqrt(constant_term(tmp1576)), order) + tmp895 = Taylor1(constant_term(Y[1]) * constant_term(W[1]), order) + tmp896 = Taylor1(constant_term(Z[1]) * constant_term(V[1]), order) + hx = Taylor1(constant_term(tmp895) - constant_term(tmp896), order) + tmp898 = Taylor1(constant_term(Z[1]) * constant_term(U[1]), order) + tmp899 = Taylor1(constant_term(X[1]) * constant_term(W[1]), order) + hy = Taylor1(constant_term(tmp898) - constant_term(tmp899), order) + tmp901 = Taylor1(constant_term(X[1]) * constant_term(V[1]), order) + tmp902 = Taylor1(constant_term(Y[1]) * constant_term(U[1]), order) + hz = Taylor1(constant_term(tmp901) - constant_term(tmp902), order) + tmp904 = Taylor1(constant_term(hz) * constant_term(Y[1]), order) + tmp905 = Taylor1(constant_term(hy) * constant_term(Z[1]), order) + t_x = Taylor1(constant_term(tmp904) - constant_term(tmp905), order) + tmp907 = Taylor1(constant_term(hx) * constant_term(Z[1]), order) + tmp908 = Taylor1(constant_term(hz) * constant_term(X[1]), order) + t_y = Taylor1(constant_term(tmp907) - constant_term(tmp908), order) + tmp910 = Taylor1(constant_term(hy) * constant_term(X[1]), order) + tmp911 = Taylor1(constant_term(hx) * constant_term(Y[1]), order) + t_z = Taylor1(constant_term(tmp910) - constant_term(tmp911), order) + tmp914 = Taylor1(constant_term(t_x) ^ float(constant_term(2)), order) + tmp916 = Taylor1(constant_term(t_y) ^ float(constant_term(2)), order) + tmp917 = Taylor1(constant_term(tmp914) + constant_term(tmp916), order) + tmp919 = Taylor1(constant_term(t_z) ^ float(constant_term(2)), order) + tmp920 = Taylor1(constant_term(tmp917) + constant_term(tmp919), order) + t_norm = Taylor1(sqrt(constant_term(tmp920)), order) t_x_unit = Taylor1(constant_term(t_x) / constant_term(t_norm), order) t_y_unit = Taylor1(constant_term(t_y) / constant_term(t_norm), order) t_z_unit = Taylor1(constant_term(t_z) / constant_term(t_norm), order) - tmp1581 = Taylor1(constant_term(X[1]) / constant_term(r_p1d2[1]), order) - r_x_unit = Taylor1(-(constant_term(tmp1581)), order) - tmp1583 = Taylor1(constant_term(Y[1]) / constant_term(r_p1d2[1]), order) - r_y_unit = Taylor1(-(constant_term(tmp1583)), order) - tmp1585 = Taylor1(constant_term(Z[1]) / constant_term(r_p1d2[1]), order) - r_z_unit = Taylor1(-(constant_term(tmp1585)), order) + tmp925 = Taylor1(constant_term(X[1]) / constant_term(r_p1d2[1]), order) + r_x_unit = Taylor1(-(constant_term(tmp925)), order) + tmp927 = Taylor1(constant_term(Y[1]) / constant_term(r_p1d2[1]), order) + r_y_unit = Taylor1(-(constant_term(tmp927)), order) + tmp929 = Taylor1(constant_term(Z[1]) / constant_term(r_p1d2[1]), order) + r_z_unit = Taylor1(-(constant_term(tmp929)), order) g_r = Taylor1(identity(constant_term(r_p2[1])), order) A2_t_g_r = Taylor1(constant_term(q[7]) / constant_term(g_r), order) A1_t_g_r = Taylor1(constant_term(q[8]) / constant_term(g_r), order) - tmp1589 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_x_unit), order) - tmp1590 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_x_unit), order) - NGAx = Taylor1(constant_term(tmp1589) + constant_term(tmp1590), order) - tmp1592 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_y_unit), order) - tmp1593 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_y_unit), order) - NGAy = Taylor1(constant_term(tmp1592) + constant_term(tmp1593), order) - tmp1595 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_z_unit), order) - tmp1596 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_z_unit), order) - NGAz = Taylor1(constant_term(tmp1595) + constant_term(tmp1596), order) - tmp1598 = Taylor1(constant_term(postNewtonX) + constant_term(accX), order) - dq[4] = Taylor1(constant_term(tmp1598) + constant_term(NGAx), order) - tmp1600 = Taylor1(constant_term(postNewtonY) + constant_term(accY), order) - dq[5] = Taylor1(constant_term(tmp1600) + constant_term(NGAy), order) - tmp1602 = Taylor1(constant_term(postNewtonZ) + constant_term(accZ), order) - dq[6] = Taylor1(constant_term(tmp1602) + constant_term(NGAz), order) + tmp933 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_x_unit), order) + tmp934 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_x_unit), order) + NGAx = Taylor1(constant_term(tmp933) + constant_term(tmp934), order) + tmp936 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_y_unit), order) + tmp937 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_y_unit), order) + NGAy = Taylor1(constant_term(tmp936) + constant_term(tmp937), order) + tmp939 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_z_unit), order) + tmp940 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_z_unit), order) + NGAz = Taylor1(constant_term(tmp939) + constant_term(tmp940), order) + tmp942 = Taylor1(constant_term(postNewtonX) + constant_term(accX), order) + dq[4] = Taylor1(constant_term(tmp942) + constant_term(NGAx), order) + tmp944 = Taylor1(constant_term(postNewtonY) + constant_term(accY), order) + dq[5] = Taylor1(constant_term(tmp944) + constant_term(NGAy), order) + tmp946 = Taylor1(constant_term(postNewtonZ) + constant_term(accZ), order) + dq[6] = Taylor1(constant_term(tmp946) + constant_term(NGAz), order) dq[7] = Taylor1(identity(constant_term(zero_q_1)), order) - return TaylorIntegration.RetAlloc{Taylor1{_S}}([tmp1483, tmp1485, tmp1486, tmp1488, tmp1551, tmp1552, tmp1554, tmp1555, tmp1557, tmp1558, tmp1560, tmp1561, tmp1563, tmp1564, tmp1566, tmp1567, tmp1570, tmp1572, tmp1573, tmp1575, tmp1576, tmp1581, tmp1583, tmp1585, tmp1589, tmp1590, tmp1592, tmp1593, tmp1595, tmp1596, tmp1598, tmp1600, tmp1602, pntempX, pntempY, pntempZ, accX, accY, accZ, postNewtonX, postNewtonY, postNewtonZ, hx, hy, hz, t_x, t_y, t_z, t_norm, t_x_unit, t_y_unit, t_z_unit, r_x_unit, r_y_unit, r_z_unit, g_r, A2_t_g_r, A1_t_g_r, NGAx, NGAy, NGAz], [X, Y, Z, r_p2, r_p1d2, r_p3d2, r_p7d2, newtonianCoeff, ui, vi, wi, U, V, W, _4U_m_3X, _4V_m_3Y, _4W_m_3Z, UU, VV, WW, newtonian1b_Potential, newtonianNb_Potential, newton_acc_X, newton_acc_Y, newton_acc_Z, v2, vi_dot_vj, pn2, U_t_pn2, V_t_pn2, W_t_pn2, pn3, pNX_t_pn3, pNY_t_pn3, pNZ_t_pn3, _4ϕj, ϕi_plus_4ϕj, sj2_plus_2si2_minus_4vivj, ϕs_and_vs, pn1t1_7, pNX_t_X, pNY_t_Y, pNZ_t_Z, pn1, X_t_pn1, Y_t_pn1, Z_t_pn1, t31, t32, t33, r_sin_ϕ, sin_ϕ, ϕ, cos_ϕ, sin2_ϕ, sin3_ϕ, F_J2_x, F_J2_y, F_J2_z, F_J2_x1, F_J2_y1, F_J2_z1, F_J2_x2, F_J2_y2, F_J2_z2, temp_accX_i, temp_accY_i, temp_accZ_i, P_2_sin_ϕ, ∂P_2_sin_ϕ, P_3_sin_ϕ, ∂P_3_sin_ϕ, m_c_ϕ_∂P_2, m_c_ϕ_∂P_3, Λ2j_div_r4, Λ3j_div_r5, F_J_ξ, F_J_ζ, F_J2_ξ, F_J2_ζ, F_J3_ξ, F_J3_ζ, ξx, ξy, ξz, ηx, ηy, ηz, ηx1, ηy1, ηz1, ηx2, ηy2, ηz2, ζx, ζy, ζz, ζx1, ζy1, ζz1, ζx2, ζy2, ζz2, tmp1343, tmp1345, tmp1348, tmp1350, tmp1353, tmp1355, pn2x, pn2y, pn2z, tmp1363, tmp1366, tmp1368, tmp1369, tmp1371, tmp1379, tmp1380, tmp1391, tmp1393, tmp1395, tmp1397, tmp1604, tmp1605, tmp1407, tmp1413, tmp1415, tmp1419, tmp1422, tmp1423, tmp1426, tmp1427, tmp1429, tmp1431, tmp1434, tmp1438, tmp1441, tmp1443, tmp1445, tmp1475, tmp1477, tmp1478, tmp1480, temp_004, tmp1491, tmp1493, tmp1495, tmp1501, tmp1503, tmp1504, Xij_t_Ui, Yij_t_Vi, Zij_t_Wi, tmp1510, Rij_dot_Vi, tmp1513, pn1t7, tmp1516, pn1t2_7, tmp1523, tmp1524, tmp1525, tmp1533, termpnx, sumpnx, tmp1536, termpny, sumpny, tmp1539, termpnz, sumpnz], [Array{Taylor1{_S}, 2}(undef, 0, 0)], [Array{Taylor1{_S}, 3}(undef, 0, 0, 0)], [Array{Taylor1{_S}, 4}(undef, 0, 0, 0, 0)]) + return TaylorIntegration.RetAlloc{Taylor1{_S}}([tmp827, tmp829, tmp830, tmp832, tmp895, tmp896, tmp898, tmp899, tmp901, tmp902, tmp904, tmp905, tmp907, tmp908, tmp910, tmp911, tmp914, tmp916, tmp917, tmp919, tmp920, tmp925, tmp927, tmp929, tmp933, tmp934, tmp936, tmp937, tmp939, tmp940, tmp942, tmp944, tmp946, pntempX, pntempY, pntempZ, accX, accY, accZ, postNewtonX, postNewtonY, postNewtonZ, hx, hy, hz, t_x, t_y, t_z, t_norm, t_x_unit, t_y_unit, t_z_unit, r_x_unit, r_y_unit, r_z_unit, g_r, A2_t_g_r, A1_t_g_r, NGAx, NGAy, NGAz], [X, Y, Z, r_p2, r_p1d2, r_p3d2, r_p7d2, newtonianCoeff, ui, vi, wi, U, V, W, _4U_m_3X, _4V_m_3Y, _4W_m_3Z, UU, VV, WW, newtonian1b_Potential, newtonianNb_Potential, newton_acc_X, newton_acc_Y, newton_acc_Z, v2, vi_dot_vj, pn2, U_t_pn2, V_t_pn2, W_t_pn2, pn3, pNX_t_pn3, pNY_t_pn3, pNZ_t_pn3, _4ϕj, ϕi_plus_4ϕj, sj2_plus_2si2_minus_4vivj, ϕs_and_vs, pn1t1_7, pNX_t_X, pNY_t_Y, pNZ_t_Z, pn1, X_t_pn1, Y_t_pn1, Z_t_pn1, t31, t32, t33, r_sin_ϕ, sin_ϕ, ϕ, cos_ϕ, sin2_ϕ, sin3_ϕ, F_J2_x, F_J2_y, F_J2_z, F_J2_x1, F_J2_y1, F_J2_z1, F_J2_x2, F_J2_y2, F_J2_z2, temp_accX_i, temp_accY_i, temp_accZ_i, P_2_sin_ϕ, ∂P_2_sin_ϕ, P_3_sin_ϕ, ∂P_3_sin_ϕ, m_c_ϕ_∂P_2, m_c_ϕ_∂P_3, Λ2j_div_r4, Λ3j_div_r5, F_J_ξ, F_J_ζ, F_J2_ξ, F_J2_ζ, F_J3_ξ, F_J3_ζ, ξx, ξy, ξz, ηx, ηy, ηz, ηx1, ηy1, ηz1, ηx2, ηy2, ηz2, ζx, ζy, ζz, ζx1, ζy1, ζz1, ζx2, ζy2, ζz2, tmp687, tmp689, tmp692, tmp694, tmp697, tmp699, pn2x, pn2y, pn2z, tmp707, tmp710, tmp712, tmp713, tmp715, tmp723, tmp724, tmp735, tmp737, tmp739, tmp741, tmp948, tmp949, tmp751, tmp757, tmp759, tmp763, tmp766, tmp767, tmp770, tmp771, tmp773, tmp775, tmp778, tmp782, tmp785, tmp787, tmp789, tmp819, tmp821, tmp822, tmp824, temp_004, tmp835, tmp837, tmp839, tmp845, tmp847, tmp848, Xij_t_Ui, Yij_t_Vi, Zij_t_Wi, tmp854, Rij_dot_Vi, tmp857, pn1t7, tmp860, pn1t2_7, tmp867, tmp868, tmp869, tmp877, termpnx, sumpnx, tmp880, termpny, sumpny, tmp883, termpnz, sumpnz], [Array{Taylor1{_S}, 2}(undef, 0, 0)], [Array{Taylor1{_S}, 3}(undef, 0, 0, 0)], [Array{Taylor1{_S}, 4}(undef, 0, 0, 0, 0)]) end # TaylorIntegration.jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_ng_eph_threads! function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params, __ralloc::TaylorIntegration.RetAlloc{Taylor1{_S}}) where {_T <: Real, _S <: Number, _N} order = t.order - tmp1483 = __ralloc.v0[1] - tmp1485 = __ralloc.v0[2] - tmp1486 = __ralloc.v0[3] - tmp1488 = __ralloc.v0[4] - tmp1551 = __ralloc.v0[5] - tmp1552 = __ralloc.v0[6] - tmp1554 = __ralloc.v0[7] - tmp1555 = __ralloc.v0[8] - tmp1557 = __ralloc.v0[9] - tmp1558 = __ralloc.v0[10] - tmp1560 = __ralloc.v0[11] - tmp1561 = __ralloc.v0[12] - tmp1563 = __ralloc.v0[13] - tmp1564 = __ralloc.v0[14] - tmp1566 = __ralloc.v0[15] - tmp1567 = __ralloc.v0[16] - tmp1570 = __ralloc.v0[17] - tmp1572 = __ralloc.v0[18] - tmp1573 = __ralloc.v0[19] - tmp1575 = __ralloc.v0[20] - tmp1576 = __ralloc.v0[21] - tmp1581 = __ralloc.v0[22] - tmp1583 = __ralloc.v0[23] - tmp1585 = __ralloc.v0[24] - tmp1589 = __ralloc.v0[25] - tmp1590 = __ralloc.v0[26] - tmp1592 = __ralloc.v0[27] - tmp1593 = __ralloc.v0[28] - tmp1595 = __ralloc.v0[29] - tmp1596 = __ralloc.v0[30] - tmp1598 = __ralloc.v0[31] - tmp1600 = __ralloc.v0[32] - tmp1602 = __ralloc.v0[33] + tmp827 = __ralloc.v0[1] + tmp829 = __ralloc.v0[2] + tmp830 = __ralloc.v0[3] + tmp832 = __ralloc.v0[4] + tmp895 = __ralloc.v0[5] + tmp896 = __ralloc.v0[6] + tmp898 = __ralloc.v0[7] + tmp899 = __ralloc.v0[8] + tmp901 = __ralloc.v0[9] + tmp902 = __ralloc.v0[10] + tmp904 = __ralloc.v0[11] + tmp905 = __ralloc.v0[12] + tmp907 = __ralloc.v0[13] + tmp908 = __ralloc.v0[14] + tmp910 = __ralloc.v0[15] + tmp911 = __ralloc.v0[16] + tmp914 = __ralloc.v0[17] + tmp916 = __ralloc.v0[18] + tmp917 = __ralloc.v0[19] + tmp919 = __ralloc.v0[20] + tmp920 = __ralloc.v0[21] + tmp925 = __ralloc.v0[22] + tmp927 = __ralloc.v0[23] + tmp929 = __ralloc.v0[24] + tmp933 = __ralloc.v0[25] + tmp934 = __ralloc.v0[26] + tmp936 = __ralloc.v0[27] + tmp937 = __ralloc.v0[28] + tmp939 = __ralloc.v0[29] + tmp940 = __ralloc.v0[30] + tmp942 = __ralloc.v0[31] + tmp944 = __ralloc.v0[32] + tmp946 = __ralloc.v0[33] pntempX = __ralloc.v0[34] pntempY = __ralloc.v0[35] pntempZ = __ralloc.v0[36] @@ -717,73 +718,73 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! ζx2 = __ralloc.v1[101] ζy2 = __ralloc.v1[102] ζz2 = __ralloc.v1[103] - tmp1343 = __ralloc.v1[104] - tmp1345 = __ralloc.v1[105] - tmp1348 = __ralloc.v1[106] - tmp1350 = __ralloc.v1[107] - tmp1353 = __ralloc.v1[108] - tmp1355 = __ralloc.v1[109] + tmp687 = __ralloc.v1[104] + tmp689 = __ralloc.v1[105] + tmp692 = __ralloc.v1[106] + tmp694 = __ralloc.v1[107] + tmp697 = __ralloc.v1[108] + tmp699 = __ralloc.v1[109] pn2x = __ralloc.v1[110] pn2y = __ralloc.v1[111] pn2z = __ralloc.v1[112] - tmp1363 = __ralloc.v1[113] - tmp1366 = __ralloc.v1[114] - tmp1368 = __ralloc.v1[115] - tmp1369 = __ralloc.v1[116] - tmp1371 = __ralloc.v1[117] - tmp1379 = __ralloc.v1[118] - tmp1380 = __ralloc.v1[119] - tmp1391 = __ralloc.v1[120] - tmp1393 = __ralloc.v1[121] - tmp1395 = __ralloc.v1[122] - tmp1397 = __ralloc.v1[123] - tmp1604 = __ralloc.v1[124] - tmp1605 = __ralloc.v1[125] - tmp1407 = __ralloc.v1[126] - tmp1413 = __ralloc.v1[127] - tmp1415 = __ralloc.v1[128] - tmp1419 = __ralloc.v1[129] - tmp1422 = __ralloc.v1[130] - tmp1423 = __ralloc.v1[131] - tmp1426 = __ralloc.v1[132] - tmp1427 = __ralloc.v1[133] - tmp1429 = __ralloc.v1[134] - tmp1431 = __ralloc.v1[135] - tmp1434 = __ralloc.v1[136] - tmp1438 = __ralloc.v1[137] - tmp1441 = __ralloc.v1[138] - tmp1443 = __ralloc.v1[139] - tmp1445 = __ralloc.v1[140] - tmp1475 = __ralloc.v1[141] - tmp1477 = __ralloc.v1[142] - tmp1478 = __ralloc.v1[143] - tmp1480 = __ralloc.v1[144] + tmp707 = __ralloc.v1[113] + tmp710 = __ralloc.v1[114] + tmp712 = __ralloc.v1[115] + tmp713 = __ralloc.v1[116] + tmp715 = __ralloc.v1[117] + tmp723 = __ralloc.v1[118] + tmp724 = __ralloc.v1[119] + tmp735 = __ralloc.v1[120] + tmp737 = __ralloc.v1[121] + tmp739 = __ralloc.v1[122] + tmp741 = __ralloc.v1[123] + tmp948 = __ralloc.v1[124] + tmp949 = __ralloc.v1[125] + tmp751 = __ralloc.v1[126] + tmp757 = __ralloc.v1[127] + tmp759 = __ralloc.v1[128] + tmp763 = __ralloc.v1[129] + tmp766 = __ralloc.v1[130] + tmp767 = __ralloc.v1[131] + tmp770 = __ralloc.v1[132] + tmp771 = __ralloc.v1[133] + tmp773 = __ralloc.v1[134] + tmp775 = __ralloc.v1[135] + tmp778 = __ralloc.v1[136] + tmp782 = __ralloc.v1[137] + tmp785 = __ralloc.v1[138] + tmp787 = __ralloc.v1[139] + tmp789 = __ralloc.v1[140] + tmp819 = __ralloc.v1[141] + tmp821 = __ralloc.v1[142] + tmp822 = __ralloc.v1[143] + tmp824 = __ralloc.v1[144] temp_004 = __ralloc.v1[145] - tmp1491 = __ralloc.v1[146] - tmp1493 = __ralloc.v1[147] - tmp1495 = __ralloc.v1[148] - tmp1501 = __ralloc.v1[149] - tmp1503 = __ralloc.v1[150] - tmp1504 = __ralloc.v1[151] + tmp835 = __ralloc.v1[146] + tmp837 = __ralloc.v1[147] + tmp839 = __ralloc.v1[148] + tmp845 = __ralloc.v1[149] + tmp847 = __ralloc.v1[150] + tmp848 = __ralloc.v1[151] Xij_t_Ui = __ralloc.v1[152] Yij_t_Vi = __ralloc.v1[153] Zij_t_Wi = __ralloc.v1[154] - tmp1510 = __ralloc.v1[155] + tmp854 = __ralloc.v1[155] Rij_dot_Vi = __ralloc.v1[156] - tmp1513 = __ralloc.v1[157] + tmp857 = __ralloc.v1[157] pn1t7 = __ralloc.v1[158] - tmp1516 = __ralloc.v1[159] + tmp860 = __ralloc.v1[159] pn1t2_7 = __ralloc.v1[160] - tmp1523 = __ralloc.v1[161] - tmp1524 = __ralloc.v1[162] - tmp1525 = __ralloc.v1[163] - tmp1533 = __ralloc.v1[164] + tmp867 = __ralloc.v1[161] + tmp868 = __ralloc.v1[162] + tmp869 = __ralloc.v1[163] + tmp877 = __ralloc.v1[164] termpnx = __ralloc.v1[165] sumpnx = __ralloc.v1[166] - tmp1536 = __ralloc.v1[167] + tmp880 = __ralloc.v1[167] termpny = __ralloc.v1[168] sumpny = __ralloc.v1[169] - tmp1539 = __ralloc.v1[170] + tmp883 = __ralloc.v1[170] termpnz = __ralloc.v1[171] sumpnz = __ralloc.v1[172] local jd0 = params[4] @@ -810,7 +811,8 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! accZ.coeffs[1] = identity(constant_term(zero_q_1)) accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) local M_ = Array{S}(undef, 3, 3, N) - local M_[:, :, ea] = t2c_jpl_de430(dsj2k) + local M_ .= zero_q_1 + local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 (dq[1]).coeffs[1] = identity(constant_term(q[4])) (dq[1]).coeffs[2:order + 1] .= zero((dq[1]).coeffs[1]) (dq[2]).coeffs[1] = identity(constant_term(q[5])) @@ -819,7 +821,7 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! (dq[3]).coeffs[2:order + 1] .= zero((dq[3]).coeffs[1]) (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(zero_q_1)) (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) - #= C:\Users\luisi\.julia\dev\NEOs.jl\ex.jl:245 =# Threads.@threads for i = 1:Nm1 + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 (ui[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])) (ui[i]).coeffs[2:order + 1] .= zero((ui[i]).coeffs[1]) (vi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])) @@ -838,23 +840,23 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! (V[i]).coeffs[2:order + 1] .= zero((V[i]).coeffs[1]) (W[i]).coeffs[1] = constant_term(wi[i]) - constant_term(dq[3]) (W[i]).coeffs[2:order + 1] .= zero((W[i]).coeffs[1]) - (tmp1343[1]).coeffs[1] = constant_term(4) * constant_term(dq[1]) - (tmp1343[1]).coeffs[2:order + 1] .= zero((tmp1343[1]).coeffs[1]) - (tmp1345[i]).coeffs[1] = constant_term(3) * constant_term(ui[i]) - (tmp1345[i]).coeffs[2:order + 1] .= zero((tmp1345[i]).coeffs[1]) - (_4U_m_3X[i]).coeffs[1] = constant_term(tmp1343[1]) - constant_term(tmp1345[i]) + (tmp687[1]).coeffs[1] = constant_term(4) * constant_term(dq[1]) + (tmp687[1]).coeffs[2:order + 1] .= zero((tmp687[1]).coeffs[1]) + (tmp689[i]).coeffs[1] = constant_term(3) * constant_term(ui[i]) + (tmp689[i]).coeffs[2:order + 1] .= zero((tmp689[i]).coeffs[1]) + (_4U_m_3X[i]).coeffs[1] = constant_term(tmp687[1]) - constant_term(tmp689[i]) (_4U_m_3X[i]).coeffs[2:order + 1] .= zero((_4U_m_3X[i]).coeffs[1]) - (tmp1348[2]).coeffs[1] = constant_term(4) * constant_term(dq[2]) - (tmp1348[2]).coeffs[2:order + 1] .= zero((tmp1348[2]).coeffs[1]) - (tmp1350[i]).coeffs[1] = constant_term(3) * constant_term(vi[i]) - (tmp1350[i]).coeffs[2:order + 1] .= zero((tmp1350[i]).coeffs[1]) - (_4V_m_3Y[i]).coeffs[1] = constant_term(tmp1348[2]) - constant_term(tmp1350[i]) + (tmp692[2]).coeffs[1] = constant_term(4) * constant_term(dq[2]) + (tmp692[2]).coeffs[2:order + 1] .= zero((tmp692[2]).coeffs[1]) + (tmp694[i]).coeffs[1] = constant_term(3) * constant_term(vi[i]) + (tmp694[i]).coeffs[2:order + 1] .= zero((tmp694[i]).coeffs[1]) + (_4V_m_3Y[i]).coeffs[1] = constant_term(tmp692[2]) - constant_term(tmp694[i]) (_4V_m_3Y[i]).coeffs[2:order + 1] .= zero((_4V_m_3Y[i]).coeffs[1]) - (tmp1353[3]).coeffs[1] = constant_term(4) * constant_term(dq[3]) - (tmp1353[3]).coeffs[2:order + 1] .= zero((tmp1353[3]).coeffs[1]) - (tmp1355[i]).coeffs[1] = constant_term(3) * constant_term(wi[i]) - (tmp1355[i]).coeffs[2:order + 1] .= zero((tmp1355[i]).coeffs[1]) - (_4W_m_3Z[i]).coeffs[1] = constant_term(tmp1353[3]) - constant_term(tmp1355[i]) + (tmp697[3]).coeffs[1] = constant_term(4) * constant_term(dq[3]) + (tmp697[3]).coeffs[2:order + 1] .= zero((tmp697[3]).coeffs[1]) + (tmp699[i]).coeffs[1] = constant_term(3) * constant_term(wi[i]) + (tmp699[i]).coeffs[2:order + 1] .= zero((tmp699[i]).coeffs[1]) + (_4W_m_3Z[i]).coeffs[1] = constant_term(tmp697[3]) - constant_term(tmp699[i]) (_4W_m_3Z[i]).coeffs[2:order + 1] .= zero((_4W_m_3Z[i]).coeffs[1]) (pn2x[i]).coeffs[1] = constant_term(X[i]) * constant_term(_4U_m_3X[i]) (pn2x[i]).coeffs[2:order + 1] .= zero((pn2x[i]).coeffs[1]) @@ -868,19 +870,19 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! (VV[i]).coeffs[2:order + 1] .= zero((VV[i]).coeffs[1]) (WW[i]).coeffs[1] = constant_term(wi[i]) * constant_term(dq[3]) (WW[i]).coeffs[2:order + 1] .= zero((WW[i]).coeffs[1]) - (tmp1363[i]).coeffs[1] = constant_term(UU[i]) + constant_term(VV[i]) - (tmp1363[i]).coeffs[2:order + 1] .= zero((tmp1363[i]).coeffs[1]) - (vi_dot_vj[i]).coeffs[1] = constant_term(tmp1363[i]) + constant_term(WW[i]) + (tmp707[i]).coeffs[1] = constant_term(UU[i]) + constant_term(VV[i]) + (tmp707[i]).coeffs[2:order + 1] .= zero((tmp707[i]).coeffs[1]) + (vi_dot_vj[i]).coeffs[1] = constant_term(tmp707[i]) + constant_term(WW[i]) (vi_dot_vj[i]).coeffs[2:order + 1] .= zero((vi_dot_vj[i]).coeffs[1]) - (tmp1366[i]).coeffs[1] = constant_term(X[i]) ^ float(constant_term(2)) - (tmp1366[i]).coeffs[2:order + 1] .= zero((tmp1366[i]).coeffs[1]) - (tmp1368[i]).coeffs[1] = constant_term(Y[i]) ^ float(constant_term(2)) - (tmp1368[i]).coeffs[2:order + 1] .= zero((tmp1368[i]).coeffs[1]) - (tmp1369[i]).coeffs[1] = constant_term(tmp1366[i]) + constant_term(tmp1368[i]) - (tmp1369[i]).coeffs[2:order + 1] .= zero((tmp1369[i]).coeffs[1]) - (tmp1371[i]).coeffs[1] = constant_term(Z[i]) ^ float(constant_term(2)) - (tmp1371[i]).coeffs[2:order + 1] .= zero((tmp1371[i]).coeffs[1]) - (r_p2[i]).coeffs[1] = constant_term(tmp1369[i]) + constant_term(tmp1371[i]) + (tmp710[i]).coeffs[1] = constant_term(X[i]) ^ float(constant_term(2)) + (tmp710[i]).coeffs[2:order + 1] .= zero((tmp710[i]).coeffs[1]) + (tmp712[i]).coeffs[1] = constant_term(Y[i]) ^ float(constant_term(2)) + (tmp712[i]).coeffs[2:order + 1] .= zero((tmp712[i]).coeffs[1]) + (tmp713[i]).coeffs[1] = constant_term(tmp710[i]) + constant_term(tmp712[i]) + (tmp713[i]).coeffs[2:order + 1] .= zero((tmp713[i]).coeffs[1]) + (tmp715[i]).coeffs[1] = constant_term(Z[i]) ^ float(constant_term(2)) + (tmp715[i]).coeffs[2:order + 1] .= zero((tmp715[i]).coeffs[1]) + (r_p2[i]).coeffs[1] = constant_term(tmp713[i]) + constant_term(tmp715[i]) (r_p2[i]).coeffs[2:order + 1] .= zero((r_p2[i]).coeffs[1]) (r_p1d2[i]).coeffs[1] = sqrt(constant_term(r_p2[i])) (r_p1d2[i]).coeffs[2:order + 1] .= zero((r_p1d2[i]).coeffs[1]) @@ -890,11 +892,11 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! (r_p7d2[i]).coeffs[2:order + 1] .= zero((r_p7d2[i]).coeffs[1]) (newtonianCoeff[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p3d2[i]) (newtonianCoeff[i]).coeffs[2:order + 1] .= zero((newtonianCoeff[i]).coeffs[1]) - (tmp1379[i]).coeffs[1] = constant_term(pn2x[i]) + constant_term(pn2y[i]) - (tmp1379[i]).coeffs[2:order + 1] .= zero((tmp1379[i]).coeffs[1]) - (tmp1380[i]).coeffs[1] = constant_term(tmp1379[i]) + constant_term(pn2z[i]) - (tmp1380[i]).coeffs[2:order + 1] .= zero((tmp1380[i]).coeffs[1]) - (pn2[i]).coeffs[1] = constant_term(newtonianCoeff[i]) * constant_term(tmp1380[i]) + (tmp723[i]).coeffs[1] = constant_term(pn2x[i]) + constant_term(pn2y[i]) + (tmp723[i]).coeffs[2:order + 1] .= zero((tmp723[i]).coeffs[1]) + (tmp724[i]).coeffs[1] = constant_term(tmp723[i]) + constant_term(pn2z[i]) + (tmp724[i]).coeffs[2:order + 1] .= zero((tmp724[i]).coeffs[1]) + (pn2[i]).coeffs[1] = constant_term(newtonianCoeff[i]) * constant_term(tmp724[i]) (pn2[i]).coeffs[2:order + 1] .= zero((pn2[i]).coeffs[1]) (newton_acc_X[i]).coeffs[1] = constant_term(X[i]) * constant_term(newtonianCoeff[i]) (newton_acc_X[i]).coeffs[2:order + 1] .= zero((newton_acc_X[i]).coeffs[1]) @@ -913,81 +915,81 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! (W_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(W[i]) (W_t_pn2[i]).coeffs[2:order + 1] .= zero((W_t_pn2[i]).coeffs[1]) if UJ_interaction[i] - (tmp1391[i]).coeffs[1] = -(constant_term(X[i])) - (tmp1391[i]).coeffs[2:order + 1] .= zero((tmp1391[i]).coeffs[1]) - (t31[i]).coeffs[1] = constant_term(tmp1391[i]) * constant_term(M_[1, 3, i]) + (tmp735[i]).coeffs[1] = -(constant_term(X[i])) + (tmp735[i]).coeffs[2:order + 1] .= zero((tmp735[i]).coeffs[1]) + (t31[i]).coeffs[1] = constant_term(tmp735[i]) * constant_term(M_[1, 3, i]) (t31[i]).coeffs[2:order + 1] .= zero((t31[i]).coeffs[1]) - (tmp1393[i]).coeffs[1] = -(constant_term(Y[i])) - (tmp1393[i]).coeffs[2:order + 1] .= zero((tmp1393[i]).coeffs[1]) - (t32[i]).coeffs[1] = constant_term(tmp1393[i]) * constant_term(M_[2, 3, i]) + (tmp737[i]).coeffs[1] = -(constant_term(Y[i])) + (tmp737[i]).coeffs[2:order + 1] .= zero((tmp737[i]).coeffs[1]) + (t32[i]).coeffs[1] = constant_term(tmp737[i]) * constant_term(M_[2, 3, i]) (t32[i]).coeffs[2:order + 1] .= zero((t32[i]).coeffs[1]) - (tmp1395[i]).coeffs[1] = -(constant_term(Z[i])) - (tmp1395[i]).coeffs[2:order + 1] .= zero((tmp1395[i]).coeffs[1]) - (t33[i]).coeffs[1] = constant_term(tmp1395[i]) * constant_term(M_[3, 3, i]) + (tmp739[i]).coeffs[1] = -(constant_term(Z[i])) + (tmp739[i]).coeffs[2:order + 1] .= zero((tmp739[i]).coeffs[1]) + (t33[i]).coeffs[1] = constant_term(tmp739[i]) * constant_term(M_[3, 3, i]) (t33[i]).coeffs[2:order + 1] .= zero((t33[i]).coeffs[1]) - (tmp1397[i]).coeffs[1] = constant_term(t31[i]) + constant_term(t32[i]) - (tmp1397[i]).coeffs[2:order + 1] .= zero((tmp1397[i]).coeffs[1]) - (r_sin_ϕ[i]).coeffs[1] = constant_term(tmp1397[i]) + constant_term(t33[i]) + (tmp741[i]).coeffs[1] = constant_term(t31[i]) + constant_term(t32[i]) + (tmp741[i]).coeffs[2:order + 1] .= zero((tmp741[i]).coeffs[1]) + (r_sin_ϕ[i]).coeffs[1] = constant_term(tmp741[i]) + constant_term(t33[i]) (r_sin_ϕ[i]).coeffs[2:order + 1] .= zero((r_sin_ϕ[i]).coeffs[1]) (sin_ϕ[i]).coeffs[1] = constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]) (sin_ϕ[i]).coeffs[2:order + 1] .= zero((sin_ϕ[i]).coeffs[1]) (ϕ[i]).coeffs[1] = asin(constant_term(sin_ϕ[i])) (ϕ[i]).coeffs[2:order + 1] .= zero((ϕ[i]).coeffs[1]) - (tmp1604[i]).coeffs[1] = sqrt(1 - constant_term(sin_ϕ[i]) ^ 2) - (tmp1604[i]).coeffs[2:order + 1] .= zero((tmp1604[i]).coeffs[1]) + (tmp948[i]).coeffs[1] = sqrt(1 - constant_term(sin_ϕ[i]) ^ 2) + (tmp948[i]).coeffs[2:order + 1] .= zero((tmp948[i]).coeffs[1]) (cos_ϕ[i]).coeffs[1] = cos(constant_term(ϕ[i])) (cos_ϕ[i]).coeffs[2:order + 1] .= zero((cos_ϕ[i]).coeffs[1]) - (tmp1605[i]).coeffs[1] = sin(constant_term(ϕ[i])) - (tmp1605[i]).coeffs[2:order + 1] .= zero((tmp1605[i]).coeffs[1]) + (tmp949[i]).coeffs[1] = sin(constant_term(ϕ[i])) + (tmp949[i]).coeffs[2:order + 1] .= zero((tmp949[i]).coeffs[1]) (sin2_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(2)) (sin2_ϕ[i]).coeffs[2:order + 1] .= zero((sin2_ϕ[i]).coeffs[1]) (sin3_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(3)) (sin3_ϕ[i]).coeffs[2:order + 1] .= zero((sin3_ϕ[i]).coeffs[1]) - (tmp1407[i]).coeffs[1] = constant_term(1.5) * constant_term(sin2_ϕ[i]) - (tmp1407[i]).coeffs[2:order + 1] .= zero((tmp1407[i]).coeffs[1]) - (P_2_sin_ϕ[i]).coeffs[1] = constant_term(tmp1407[i]) - constant_term(0.5) + (tmp751[i]).coeffs[1] = constant_term(1.5) * constant_term(sin2_ϕ[i]) + (tmp751[i]).coeffs[2:order + 1] .= zero((tmp751[i]).coeffs[1]) + (P_2_sin_ϕ[i]).coeffs[1] = constant_term(tmp751[i]) - constant_term(0.5) (P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_2_sin_ϕ[i]).coeffs[1]) (∂P_2_sin_ϕ[i]).coeffs[1] = constant_term(3) * constant_term(sin_ϕ[i]) (∂P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_2_sin_ϕ[i]).coeffs[1]) - (tmp1413[i]).coeffs[1] = constant_term(-1.5) * constant_term(sin_ϕ[i]) - (tmp1413[i]).coeffs[2:order + 1] .= zero((tmp1413[i]).coeffs[1]) - (tmp1415[i]).coeffs[1] = constant_term(2.5) * constant_term(sin3_ϕ[i]) - (tmp1415[i]).coeffs[2:order + 1] .= zero((tmp1415[i]).coeffs[1]) - (P_3_sin_ϕ[i]).coeffs[1] = constant_term(tmp1413[i]) + constant_term(tmp1415[i]) + (tmp757[i]).coeffs[1] = constant_term(-1.5) * constant_term(sin_ϕ[i]) + (tmp757[i]).coeffs[2:order + 1] .= zero((tmp757[i]).coeffs[1]) + (tmp759[i]).coeffs[1] = constant_term(2.5) * constant_term(sin3_ϕ[i]) + (tmp759[i]).coeffs[2:order + 1] .= zero((tmp759[i]).coeffs[1]) + (P_3_sin_ϕ[i]).coeffs[1] = constant_term(tmp757[i]) + constant_term(tmp759[i]) (P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_3_sin_ϕ[i]).coeffs[1]) - (tmp1419[i]).coeffs[1] = constant_term(7.5) * constant_term(sin2_ϕ[i]) - (tmp1419[i]).coeffs[2:order + 1] .= zero((tmp1419[i]).coeffs[1]) - (∂P_3_sin_ϕ[i]).coeffs[1] = constant_term(-1.5) + constant_term(tmp1419[i]) + (tmp763[i]).coeffs[1] = constant_term(7.5) * constant_term(sin2_ϕ[i]) + (tmp763[i]).coeffs[2:order + 1] .= zero((tmp763[i]).coeffs[1]) + (∂P_3_sin_ϕ[i]).coeffs[1] = constant_term(-1.5) + constant_term(tmp763[i]) (∂P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_3_sin_ϕ[i]).coeffs[1]) - (tmp1422[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(2)) - (tmp1422[i]).coeffs[2:order + 1] .= zero((tmp1422[i]).coeffs[1]) - (tmp1423[i]).coeffs[1] = constant_term(Λ2[i]) / constant_term(tmp1422[i]) - (tmp1423[i]).coeffs[2:order + 1] .= zero((tmp1423[i]).coeffs[1]) - (Λ2j_div_r4[i]).coeffs[1] = -(constant_term(tmp1423[i])) + (tmp766[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(2)) + (tmp766[i]).coeffs[2:order + 1] .= zero((tmp766[i]).coeffs[1]) + (tmp767[i]).coeffs[1] = constant_term(Λ2[i]) / constant_term(tmp766[i]) + (tmp767[i]).coeffs[2:order + 1] .= zero((tmp767[i]).coeffs[1]) + (Λ2j_div_r4[i]).coeffs[1] = -(constant_term(tmp767[i])) (Λ2j_div_r4[i]).coeffs[2:order + 1] .= zero((Λ2j_div_r4[i]).coeffs[1]) - (tmp1426[i]).coeffs[1] = constant_term(r_p1d2[i]) ^ float(constant_term(5)) - (tmp1426[i]).coeffs[2:order + 1] .= zero((tmp1426[i]).coeffs[1]) - (tmp1427[i]).coeffs[1] = constant_term(Λ3[i]) / constant_term(tmp1426[i]) - (tmp1427[i]).coeffs[2:order + 1] .= zero((tmp1427[i]).coeffs[1]) - (Λ3j_div_r5[i]).coeffs[1] = -(constant_term(tmp1427[i])) + (tmp770[i]).coeffs[1] = constant_term(r_p1d2[i]) ^ float(constant_term(5)) + (tmp770[i]).coeffs[2:order + 1] .= zero((tmp770[i]).coeffs[1]) + (tmp771[i]).coeffs[1] = constant_term(Λ3[i]) / constant_term(tmp770[i]) + (tmp771[i]).coeffs[2:order + 1] .= zero((tmp771[i]).coeffs[1]) + (Λ3j_div_r5[i]).coeffs[1] = -(constant_term(tmp771[i])) (Λ3j_div_r5[i]).coeffs[2:order + 1] .= zero((Λ3j_div_r5[i]).coeffs[1]) - (tmp1429[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) - (tmp1429[i]).coeffs[2:order + 1] .= zero((tmp1429[i]).coeffs[1]) - (m_c_ϕ_∂P_2[i]).coeffs[1] = constant_term(tmp1429[i]) * constant_term(∂P_2_sin_ϕ[i]) + (tmp773[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) + (tmp773[i]).coeffs[2:order + 1] .= zero((tmp773[i]).coeffs[1]) + (m_c_ϕ_∂P_2[i]).coeffs[1] = constant_term(tmp773[i]) * constant_term(∂P_2_sin_ϕ[i]) (m_c_ϕ_∂P_2[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_2[i]).coeffs[1]) - (tmp1431[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) - (tmp1431[i]).coeffs[2:order + 1] .= zero((tmp1431[i]).coeffs[1]) - (m_c_ϕ_∂P_3[i]).coeffs[1] = constant_term(tmp1431[i]) * constant_term(∂P_3_sin_ϕ[i]) + (tmp775[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) + (tmp775[i]).coeffs[2:order + 1] .= zero((tmp775[i]).coeffs[1]) + (m_c_ϕ_∂P_3[i]).coeffs[1] = constant_term(tmp775[i]) * constant_term(∂P_3_sin_ϕ[i]) (m_c_ϕ_∂P_3[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_3[i]).coeffs[1]) - (tmp1434[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(3) - (tmp1434[i]).coeffs[2:order + 1] .= zero((tmp1434[i]).coeffs[1]) - (F_J2_ξ[i]).coeffs[1] = constant_term(tmp1434[i]) * constant_term(P_2_sin_ϕ[i]) + (tmp778[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(3) + (tmp778[i]).coeffs[2:order + 1] .= zero((tmp778[i]).coeffs[1]) + (F_J2_ξ[i]).coeffs[1] = constant_term(tmp778[i]) * constant_term(P_2_sin_ϕ[i]) (F_J2_ξ[i]).coeffs[2:order + 1] .= zero((F_J2_ξ[i]).coeffs[1]) (F_J2_ζ[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]) (F_J2_ζ[i]).coeffs[2:order + 1] .= zero((F_J2_ζ[i]).coeffs[1]) - (tmp1438[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(4) - (tmp1438[i]).coeffs[2:order + 1] .= zero((tmp1438[i]).coeffs[1]) - (F_J3_ξ[i]).coeffs[1] = constant_term(tmp1438[i]) * constant_term(P_3_sin_ϕ[i]) + (tmp782[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(4) + (tmp782[i]).coeffs[2:order + 1] .= zero((tmp782[i]).coeffs[1]) + (F_J3_ξ[i]).coeffs[1] = constant_term(tmp782[i]) * constant_term(P_3_sin_ϕ[i]) (F_J3_ξ[i]).coeffs[2:order + 1] .= zero((F_J3_ξ[i]).coeffs[1]) (F_J3_ζ[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]) (F_J3_ζ[i]).coeffs[2:order + 1] .= zero((F_J3_ζ[i]).coeffs[1]) @@ -995,17 +997,17 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! (F_J_ξ[i]).coeffs[2:order + 1] .= zero((F_J_ξ[i]).coeffs[1]) (F_J_ζ[i]).coeffs[1] = identity(constant_term(F_J2_ζ[i])) (F_J_ζ[i]).coeffs[2:order + 1] .= zero((F_J_ζ[i]).coeffs[1]) - (tmp1441[i]).coeffs[1] = -(constant_term(X[i])) - (tmp1441[i]).coeffs[2:order + 1] .= zero((tmp1441[i]).coeffs[1]) - (ξx[i]).coeffs[1] = constant_term(tmp1441[i]) / constant_term(r_p1d2[i]) + (tmp785[i]).coeffs[1] = -(constant_term(X[i])) + (tmp785[i]).coeffs[2:order + 1] .= zero((tmp785[i]).coeffs[1]) + (ξx[i]).coeffs[1] = constant_term(tmp785[i]) / constant_term(r_p1d2[i]) (ξx[i]).coeffs[2:order + 1] .= zero((ξx[i]).coeffs[1]) - (tmp1443[i]).coeffs[1] = -(constant_term(Y[i])) - (tmp1443[i]).coeffs[2:order + 1] .= zero((tmp1443[i]).coeffs[1]) - (ξy[i]).coeffs[1] = constant_term(tmp1443[i]) / constant_term(r_p1d2[i]) + (tmp787[i]).coeffs[1] = -(constant_term(Y[i])) + (tmp787[i]).coeffs[2:order + 1] .= zero((tmp787[i]).coeffs[1]) + (ξy[i]).coeffs[1] = constant_term(tmp787[i]) / constant_term(r_p1d2[i]) (ξy[i]).coeffs[2:order + 1] .= zero((ξy[i]).coeffs[1]) - (tmp1445[i]).coeffs[1] = -(constant_term(Z[i])) - (tmp1445[i]).coeffs[2:order + 1] .= zero((tmp1445[i]).coeffs[1]) - (ξz[i]).coeffs[1] = constant_term(tmp1445[i]) / constant_term(r_p1d2[i]) + (tmp789[i]).coeffs[1] = -(constant_term(Z[i])) + (tmp789[i]).coeffs[2:order + 1] .= zero((tmp789[i]).coeffs[1]) + (ξz[i]).coeffs[1] = constant_term(tmp789[i]) / constant_term(r_p1d2[i]) (ξz[i]).coeffs[2:order + 1] .= zero((ξz[i]).coeffs[1]) (ηx1[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξz[i]) (ηx1[i]).coeffs[2:order + 1] .= zero((ηx1[i]).coeffs[1]) @@ -1062,26 +1064,26 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! (F_J2_z[i]).coeffs[1] = constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]) (F_J2_z[i]).coeffs[2:order + 1] .= zero((F_J2_z[i]).coeffs[1]) end - (tmp1475[i]).coeffs[1] = constant_term(ui[i]) ^ float(constant_term(2)) - (tmp1475[i]).coeffs[2:order + 1] .= zero((tmp1475[i]).coeffs[1]) - (tmp1477[i]).coeffs[1] = constant_term(vi[i]) ^ float(constant_term(2)) - (tmp1477[i]).coeffs[2:order + 1] .= zero((tmp1477[i]).coeffs[1]) - (tmp1478[i]).coeffs[1] = constant_term(tmp1475[i]) + constant_term(tmp1477[i]) - (tmp1478[i]).coeffs[2:order + 1] .= zero((tmp1478[i]).coeffs[1]) - (tmp1480[i]).coeffs[1] = constant_term(wi[i]) ^ float(constant_term(2)) - (tmp1480[i]).coeffs[2:order + 1] .= zero((tmp1480[i]).coeffs[1]) - (v2[i]).coeffs[1] = constant_term(tmp1478[i]) + constant_term(tmp1480[i]) + (tmp819[i]).coeffs[1] = constant_term(ui[i]) ^ float(constant_term(2)) + (tmp819[i]).coeffs[2:order + 1] .= zero((tmp819[i]).coeffs[1]) + (tmp821[i]).coeffs[1] = constant_term(vi[i]) ^ float(constant_term(2)) + (tmp821[i]).coeffs[2:order + 1] .= zero((tmp821[i]).coeffs[1]) + (tmp822[i]).coeffs[1] = constant_term(tmp819[i]) + constant_term(tmp821[i]) + (tmp822[i]).coeffs[2:order + 1] .= zero((tmp822[i]).coeffs[1]) + (tmp824[i]).coeffs[1] = constant_term(wi[i]) ^ float(constant_term(2)) + (tmp824[i]).coeffs[2:order + 1] .= zero((tmp824[i]).coeffs[1]) + (v2[i]).coeffs[1] = constant_term(tmp822[i]) + constant_term(tmp824[i]) (v2[i]).coeffs[2:order + 1] .= zero((v2[i]).coeffs[1]) end - tmp1483.coeffs[1] = constant_term(q[4]) ^ float(constant_term(2)) - tmp1483.coeffs[2:order + 1] .= zero(tmp1483.coeffs[1]) - tmp1485.coeffs[1] = constant_term(q[5]) ^ float(constant_term(2)) - tmp1485.coeffs[2:order + 1] .= zero(tmp1485.coeffs[1]) - tmp1486.coeffs[1] = constant_term(tmp1483) + constant_term(tmp1485) - tmp1486.coeffs[2:order + 1] .= zero(tmp1486.coeffs[1]) - tmp1488.coeffs[1] = constant_term(q[6]) ^ float(constant_term(2)) - tmp1488.coeffs[2:order + 1] .= zero(tmp1488.coeffs[1]) - (v2[N]).coeffs[1] = constant_term(tmp1486) + constant_term(tmp1488) + tmp827.coeffs[1] = constant_term(q[4]) ^ float(constant_term(2)) + tmp827.coeffs[2:order + 1] .= zero(tmp827.coeffs[1]) + tmp829.coeffs[1] = constant_term(q[5]) ^ float(constant_term(2)) + tmp829.coeffs[2:order + 1] .= zero(tmp829.coeffs[1]) + tmp830.coeffs[1] = constant_term(tmp827) + constant_term(tmp829) + tmp830.coeffs[2:order + 1] .= zero(tmp830.coeffs[1]) + tmp832.coeffs[1] = constant_term(q[6]) ^ float(constant_term(2)) + tmp832.coeffs[2:order + 1] .= zero(tmp832.coeffs[1]) + (v2[N]).coeffs[1] = constant_term(tmp830) + constant_term(tmp832) (v2[N]).coeffs[2:order + 1] .= zero((v2[N]).coeffs[1]) for i = 1:Nm1 (temp_004[i]).coeffs[1] = constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]) @@ -1089,21 +1091,21 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(temp_004[i])) (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) if UJ_interaction[i] - (tmp1491[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_x[i]) - (tmp1491[i]).coeffs[2:order + 1] .= zero((tmp1491[i]).coeffs[1]) - (temp_accX_i[i]).coeffs[1] = constant_term(accX) - constant_term(tmp1491[i]) + (tmp835[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_x[i]) + (tmp835[i]).coeffs[2:order + 1] .= zero((tmp835[i]).coeffs[1]) + (temp_accX_i[i]).coeffs[1] = constant_term(accX) - constant_term(tmp835[i]) (temp_accX_i[i]).coeffs[2:order + 1] .= zero((temp_accX_i[i]).coeffs[1]) accX.coeffs[1] = identity(constant_term(temp_accX_i[i])) accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) - (tmp1493[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_y[i]) - (tmp1493[i]).coeffs[2:order + 1] .= zero((tmp1493[i]).coeffs[1]) - (temp_accY_i[i]).coeffs[1] = constant_term(accY) - constant_term(tmp1493[i]) + (tmp837[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_y[i]) + (tmp837[i]).coeffs[2:order + 1] .= zero((tmp837[i]).coeffs[1]) + (temp_accY_i[i]).coeffs[1] = constant_term(accY) - constant_term(tmp837[i]) (temp_accY_i[i]).coeffs[2:order + 1] .= zero((temp_accY_i[i]).coeffs[1]) accY.coeffs[1] = identity(constant_term(temp_accY_i[i])) accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) - (tmp1495[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_z[i]) - (tmp1495[i]).coeffs[2:order + 1] .= zero((tmp1495[i]).coeffs[1]) - (temp_accZ_i[i]).coeffs[1] = constant_term(accZ) - constant_term(tmp1495[i]) + (tmp839[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_z[i]) + (tmp839[i]).coeffs[2:order + 1] .= zero((tmp839[i]).coeffs[1]) + (temp_accZ_i[i]).coeffs[1] = constant_term(accZ) - constant_term(tmp839[i]) (temp_accZ_i[i]).coeffs[2:order + 1] .= zero((temp_accZ_i[i]).coeffs[1]) accZ.coeffs[1] = identity(constant_term(temp_accZ_i[i])) accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) @@ -1111,16 +1113,16 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! end (_4ϕj[N]).coeffs[1] = constant_term(4) * constant_term(newtonianNb_Potential[N]) (_4ϕj[N]).coeffs[2:order + 1] .= zero((_4ϕj[N]).coeffs[1]) - #= C:\Users\luisi\.julia\dev\NEOs.jl\ex.jl:447 =# Threads.@threads for i = 1:10 + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 (ϕi_plus_4ϕj[i]).coeffs[1] = constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]) (ϕi_plus_4ϕj[i]).coeffs[2:order + 1] .= zero((ϕi_plus_4ϕj[i]).coeffs[1]) - (tmp1501[i]).coeffs[1] = constant_term(2) * constant_term(v2[i]) - (tmp1501[i]).coeffs[2:order + 1] .= zero((tmp1501[i]).coeffs[1]) - (tmp1503[i]).coeffs[1] = constant_term(4) * constant_term(vi_dot_vj[i]) - (tmp1503[i]).coeffs[2:order + 1] .= zero((tmp1503[i]).coeffs[1]) - (tmp1504[i]).coeffs[1] = constant_term(tmp1501[i]) - constant_term(tmp1503[i]) - (tmp1504[i]).coeffs[2:order + 1] .= zero((tmp1504[i]).coeffs[1]) - (sj2_plus_2si2_minus_4vivj[i]).coeffs[1] = constant_term(tmp1504[i]) + constant_term(v2[N]) + (tmp845[i]).coeffs[1] = constant_term(2) * constant_term(v2[i]) + (tmp845[i]).coeffs[2:order + 1] .= zero((tmp845[i]).coeffs[1]) + (tmp847[i]).coeffs[1] = constant_term(4) * constant_term(vi_dot_vj[i]) + (tmp847[i]).coeffs[2:order + 1] .= zero((tmp847[i]).coeffs[1]) + (tmp848[i]).coeffs[1] = constant_term(tmp845[i]) - constant_term(tmp847[i]) + (tmp848[i]).coeffs[2:order + 1] .= zero((tmp848[i]).coeffs[1]) + (sj2_plus_2si2_minus_4vivj[i]).coeffs[1] = constant_term(tmp848[i]) + constant_term(v2[N]) (sj2_plus_2si2_minus_4vivj[i]).coeffs[2:order + 1] .= zero((sj2_plus_2si2_minus_4vivj[i]).coeffs[1]) (ϕs_and_vs[i]).coeffs[1] = constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]) (ϕs_and_vs[i]).coeffs[2:order + 1] .= zero((ϕs_and_vs[i]).coeffs[1]) @@ -1130,17 +1132,17 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! (Yij_t_Vi[i]).coeffs[2:order + 1] .= zero((Yij_t_Vi[i]).coeffs[1]) (Zij_t_Wi[i]).coeffs[1] = constant_term(Z[i]) * constant_term(wi[i]) (Zij_t_Wi[i]).coeffs[2:order + 1] .= zero((Zij_t_Wi[i]).coeffs[1]) - (tmp1510[i]).coeffs[1] = constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]) - (tmp1510[i]).coeffs[2:order + 1] .= zero((tmp1510[i]).coeffs[1]) - (Rij_dot_Vi[i]).coeffs[1] = constant_term(tmp1510[i]) + constant_term(Zij_t_Wi[i]) + (tmp854[i]).coeffs[1] = constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]) + (tmp854[i]).coeffs[2:order + 1] .= zero((tmp854[i]).coeffs[1]) + (Rij_dot_Vi[i]).coeffs[1] = constant_term(tmp854[i]) + constant_term(Zij_t_Wi[i]) (Rij_dot_Vi[i]).coeffs[2:order + 1] .= zero((Rij_dot_Vi[i]).coeffs[1]) - (tmp1513[i]).coeffs[1] = constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)) - (tmp1513[i]).coeffs[2:order + 1] .= zero((tmp1513[i]).coeffs[1]) - (pn1t7[i]).coeffs[1] = constant_term(tmp1513[i]) / constant_term(r_p2[i]) + (tmp857[i]).coeffs[1] = constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)) + (tmp857[i]).coeffs[2:order + 1] .= zero((tmp857[i]).coeffs[1]) + (pn1t7[i]).coeffs[1] = constant_term(tmp857[i]) / constant_term(r_p2[i]) (pn1t7[i]).coeffs[2:order + 1] .= zero((pn1t7[i]).coeffs[1]) - (tmp1516[i]).coeffs[1] = constant_term(1.5) * constant_term(pn1t7[i]) - (tmp1516[i]).coeffs[2:order + 1] .= zero((tmp1516[i]).coeffs[1]) - (pn1t2_7[i]).coeffs[1] = constant_term(ϕs_and_vs[i]) - constant_term(tmp1516[i]) + (tmp860[i]).coeffs[1] = constant_term(1.5) * constant_term(pn1t7[i]) + (tmp860[i]).coeffs[2:order + 1] .= zero((tmp860[i]).coeffs[1]) + (pn1t2_7[i]).coeffs[1] = constant_term(ϕs_and_vs[i]) - constant_term(tmp860[i]) (pn1t2_7[i]).coeffs[2:order + 1] .= zero((pn1t2_7[i]).coeffs[1]) (pn1t1_7[i]).coeffs[1] = constant_term(c_p2) + constant_term(pn1t2_7[i]) (pn1t1_7[i]).coeffs[2:order + 1] .= zero((pn1t1_7[i]).coeffs[1]) @@ -1150,13 +1152,13 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! (pNY_t_Y[i]).coeffs[2:order + 1] .= zero((pNY_t_Y[i]).coeffs[1]) (pNZ_t_Z[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(Z[i]) (pNZ_t_Z[i]).coeffs[2:order + 1] .= zero((pNZ_t_Z[i]).coeffs[1]) - (tmp1523[i]).coeffs[1] = constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]) - (tmp1523[i]).coeffs[2:order + 1] .= zero((tmp1523[i]).coeffs[1]) - (tmp1524[i]).coeffs[1] = constant_term(tmp1523[i]) + constant_term(pNZ_t_Z[i]) - (tmp1524[i]).coeffs[2:order + 1] .= zero((tmp1524[i]).coeffs[1]) - (tmp1525[i]).coeffs[1] = constant_term(0.5) * constant_term(tmp1524[i]) - (tmp1525[i]).coeffs[2:order + 1] .= zero((tmp1525[i]).coeffs[1]) - (pn1[i]).coeffs[1] = constant_term(pn1t1_7[i]) + constant_term(tmp1525[i]) + (tmp867[i]).coeffs[1] = constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]) + (tmp867[i]).coeffs[2:order + 1] .= zero((tmp867[i]).coeffs[1]) + (tmp868[i]).coeffs[1] = constant_term(tmp867[i]) + constant_term(pNZ_t_Z[i]) + (tmp868[i]).coeffs[2:order + 1] .= zero((tmp868[i]).coeffs[1]) + (tmp869[i]).coeffs[1] = constant_term(0.5) * constant_term(tmp868[i]) + (tmp869[i]).coeffs[2:order + 1] .= zero((tmp869[i]).coeffs[1]) + (pn1[i]).coeffs[1] = constant_term(pn1t1_7[i]) + constant_term(tmp869[i]) (pn1[i]).coeffs[2:order + 1] .= zero((pn1[i]).coeffs[1]) (X_t_pn1[i]).coeffs[1] = constant_term(newton_acc_X[i]) * constant_term(pn1[i]) (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) @@ -1172,32 +1174,32 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! (pNZ_t_pn3[i]).coeffs[2:order + 1] .= zero((pNZ_t_pn3[i]).coeffs[1]) end for i = 1:10 - (tmp1533[i]).coeffs[1] = constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]) - (tmp1533[i]).coeffs[2:order + 1] .= zero((tmp1533[i]).coeffs[1]) - (termpnx[i]).coeffs[1] = constant_term(X_t_pn1[i]) + constant_term(tmp1533[i]) + (tmp877[i]).coeffs[1] = constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]) + (tmp877[i]).coeffs[2:order + 1] .= zero((tmp877[i]).coeffs[1]) + (termpnx[i]).coeffs[1] = constant_term(X_t_pn1[i]) + constant_term(tmp877[i]) (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) - (tmp1536[i]).coeffs[1] = constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]) - (tmp1536[i]).coeffs[2:order + 1] .= zero((tmp1536[i]).coeffs[1]) - (termpny[i]).coeffs[1] = constant_term(Y_t_pn1[i]) + constant_term(tmp1536[i]) + (tmp880[i]).coeffs[1] = constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]) + (tmp880[i]).coeffs[2:order + 1] .= zero((tmp880[i]).coeffs[1]) + (termpny[i]).coeffs[1] = constant_term(Y_t_pn1[i]) + constant_term(tmp880[i]) (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) pntempY.coeffs[1] = identity(constant_term(sumpny[i])) pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) - (tmp1539[i]).coeffs[1] = constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]) - (tmp1539[i]).coeffs[2:order + 1] .= zero((tmp1539[i]).coeffs[1]) - (termpnz[i]).coeffs[1] = constant_term(Z_t_pn1[i]) + constant_term(tmp1539[i]) + (tmp883[i]).coeffs[1] = constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]) + (tmp883[i]).coeffs[2:order + 1] .= zero((tmp883[i]).coeffs[1]) + (termpnz[i]).coeffs[1] = constant_term(Z_t_pn1[i]) + constant_term(tmp883[i]) (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) end - #= C:\Users\luisi\.julia\dev\NEOs.jl\ex.jl:500 =# Threads.@threads for i = 11:Nm1 + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 (X_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_X[i]) (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) (Y_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Y[i]) @@ -1231,53 +1233,53 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! postNewtonY.coeffs[2:order + 1] .= zero(postNewtonY.coeffs[1]) postNewtonZ.coeffs[1] = constant_term(pntempZ) * constant_term(c_m2) postNewtonZ.coeffs[2:order + 1] .= zero(postNewtonZ.coeffs[1]) - tmp1551.coeffs[1] = constant_term(Y[1]) * constant_term(W[1]) - tmp1551.coeffs[2:order + 1] .= zero(tmp1551.coeffs[1]) - tmp1552.coeffs[1] = constant_term(Z[1]) * constant_term(V[1]) - tmp1552.coeffs[2:order + 1] .= zero(tmp1552.coeffs[1]) - hx.coeffs[1] = constant_term(tmp1551) - constant_term(tmp1552) + tmp895.coeffs[1] = constant_term(Y[1]) * constant_term(W[1]) + tmp895.coeffs[2:order + 1] .= zero(tmp895.coeffs[1]) + tmp896.coeffs[1] = constant_term(Z[1]) * constant_term(V[1]) + tmp896.coeffs[2:order + 1] .= zero(tmp896.coeffs[1]) + hx.coeffs[1] = constant_term(tmp895) - constant_term(tmp896) hx.coeffs[2:order + 1] .= zero(hx.coeffs[1]) - tmp1554.coeffs[1] = constant_term(Z[1]) * constant_term(U[1]) - tmp1554.coeffs[2:order + 1] .= zero(tmp1554.coeffs[1]) - tmp1555.coeffs[1] = constant_term(X[1]) * constant_term(W[1]) - tmp1555.coeffs[2:order + 1] .= zero(tmp1555.coeffs[1]) - hy.coeffs[1] = constant_term(tmp1554) - constant_term(tmp1555) + tmp898.coeffs[1] = constant_term(Z[1]) * constant_term(U[1]) + tmp898.coeffs[2:order + 1] .= zero(tmp898.coeffs[1]) + tmp899.coeffs[1] = constant_term(X[1]) * constant_term(W[1]) + tmp899.coeffs[2:order + 1] .= zero(tmp899.coeffs[1]) + hy.coeffs[1] = constant_term(tmp898) - constant_term(tmp899) hy.coeffs[2:order + 1] .= zero(hy.coeffs[1]) - tmp1557.coeffs[1] = constant_term(X[1]) * constant_term(V[1]) - tmp1557.coeffs[2:order + 1] .= zero(tmp1557.coeffs[1]) - tmp1558.coeffs[1] = constant_term(Y[1]) * constant_term(U[1]) - tmp1558.coeffs[2:order + 1] .= zero(tmp1558.coeffs[1]) - hz.coeffs[1] = constant_term(tmp1557) - constant_term(tmp1558) + tmp901.coeffs[1] = constant_term(X[1]) * constant_term(V[1]) + tmp901.coeffs[2:order + 1] .= zero(tmp901.coeffs[1]) + tmp902.coeffs[1] = constant_term(Y[1]) * constant_term(U[1]) + tmp902.coeffs[2:order + 1] .= zero(tmp902.coeffs[1]) + hz.coeffs[1] = constant_term(tmp901) - constant_term(tmp902) hz.coeffs[2:order + 1] .= zero(hz.coeffs[1]) - tmp1560.coeffs[1] = constant_term(hz) * constant_term(Y[1]) - tmp1560.coeffs[2:order + 1] .= zero(tmp1560.coeffs[1]) - tmp1561.coeffs[1] = constant_term(hy) * constant_term(Z[1]) - tmp1561.coeffs[2:order + 1] .= zero(tmp1561.coeffs[1]) - t_x.coeffs[1] = constant_term(tmp1560) - constant_term(tmp1561) + tmp904.coeffs[1] = constant_term(hz) * constant_term(Y[1]) + tmp904.coeffs[2:order + 1] .= zero(tmp904.coeffs[1]) + tmp905.coeffs[1] = constant_term(hy) * constant_term(Z[1]) + tmp905.coeffs[2:order + 1] .= zero(tmp905.coeffs[1]) + t_x.coeffs[1] = constant_term(tmp904) - constant_term(tmp905) t_x.coeffs[2:order + 1] .= zero(t_x.coeffs[1]) - tmp1563.coeffs[1] = constant_term(hx) * constant_term(Z[1]) - tmp1563.coeffs[2:order + 1] .= zero(tmp1563.coeffs[1]) - tmp1564.coeffs[1] = constant_term(hz) * constant_term(X[1]) - tmp1564.coeffs[2:order + 1] .= zero(tmp1564.coeffs[1]) - t_y.coeffs[1] = constant_term(tmp1563) - constant_term(tmp1564) + tmp907.coeffs[1] = constant_term(hx) * constant_term(Z[1]) + tmp907.coeffs[2:order + 1] .= zero(tmp907.coeffs[1]) + tmp908.coeffs[1] = constant_term(hz) * constant_term(X[1]) + tmp908.coeffs[2:order + 1] .= zero(tmp908.coeffs[1]) + t_y.coeffs[1] = constant_term(tmp907) - constant_term(tmp908) t_y.coeffs[2:order + 1] .= zero(t_y.coeffs[1]) - tmp1566.coeffs[1] = constant_term(hy) * constant_term(X[1]) - tmp1566.coeffs[2:order + 1] .= zero(tmp1566.coeffs[1]) - tmp1567.coeffs[1] = constant_term(hx) * constant_term(Y[1]) - tmp1567.coeffs[2:order + 1] .= zero(tmp1567.coeffs[1]) - t_z.coeffs[1] = constant_term(tmp1566) - constant_term(tmp1567) + tmp910.coeffs[1] = constant_term(hy) * constant_term(X[1]) + tmp910.coeffs[2:order + 1] .= zero(tmp910.coeffs[1]) + tmp911.coeffs[1] = constant_term(hx) * constant_term(Y[1]) + tmp911.coeffs[2:order + 1] .= zero(tmp911.coeffs[1]) + t_z.coeffs[1] = constant_term(tmp910) - constant_term(tmp911) t_z.coeffs[2:order + 1] .= zero(t_z.coeffs[1]) - tmp1570.coeffs[1] = constant_term(t_x) ^ float(constant_term(2)) - tmp1570.coeffs[2:order + 1] .= zero(tmp1570.coeffs[1]) - tmp1572.coeffs[1] = constant_term(t_y) ^ float(constant_term(2)) - tmp1572.coeffs[2:order + 1] .= zero(tmp1572.coeffs[1]) - tmp1573.coeffs[1] = constant_term(tmp1570) + constant_term(tmp1572) - tmp1573.coeffs[2:order + 1] .= zero(tmp1573.coeffs[1]) - tmp1575.coeffs[1] = constant_term(t_z) ^ float(constant_term(2)) - tmp1575.coeffs[2:order + 1] .= zero(tmp1575.coeffs[1]) - tmp1576.coeffs[1] = constant_term(tmp1573) + constant_term(tmp1575) - tmp1576.coeffs[2:order + 1] .= zero(tmp1576.coeffs[1]) - t_norm.coeffs[1] = sqrt(constant_term(tmp1576)) + tmp914.coeffs[1] = constant_term(t_x) ^ float(constant_term(2)) + tmp914.coeffs[2:order + 1] .= zero(tmp914.coeffs[1]) + tmp916.coeffs[1] = constant_term(t_y) ^ float(constant_term(2)) + tmp916.coeffs[2:order + 1] .= zero(tmp916.coeffs[1]) + tmp917.coeffs[1] = constant_term(tmp914) + constant_term(tmp916) + tmp917.coeffs[2:order + 1] .= zero(tmp917.coeffs[1]) + tmp919.coeffs[1] = constant_term(t_z) ^ float(constant_term(2)) + tmp919.coeffs[2:order + 1] .= zero(tmp919.coeffs[1]) + tmp920.coeffs[1] = constant_term(tmp917) + constant_term(tmp919) + tmp920.coeffs[2:order + 1] .= zero(tmp920.coeffs[1]) + t_norm.coeffs[1] = sqrt(constant_term(tmp920)) t_norm.coeffs[2:order + 1] .= zero(t_norm.coeffs[1]) t_x_unit.coeffs[1] = constant_term(t_x) / constant_term(t_norm) t_x_unit.coeffs[2:order + 1] .= zero(t_x_unit.coeffs[1]) @@ -1285,17 +1287,17 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! t_y_unit.coeffs[2:order + 1] .= zero(t_y_unit.coeffs[1]) t_z_unit.coeffs[1] = constant_term(t_z) / constant_term(t_norm) t_z_unit.coeffs[2:order + 1] .= zero(t_z_unit.coeffs[1]) - tmp1581.coeffs[1] = constant_term(X[1]) / constant_term(r_p1d2[1]) - tmp1581.coeffs[2:order + 1] .= zero(tmp1581.coeffs[1]) - r_x_unit.coeffs[1] = -(constant_term(tmp1581)) + tmp925.coeffs[1] = constant_term(X[1]) / constant_term(r_p1d2[1]) + tmp925.coeffs[2:order + 1] .= zero(tmp925.coeffs[1]) + r_x_unit.coeffs[1] = -(constant_term(tmp925)) r_x_unit.coeffs[2:order + 1] .= zero(r_x_unit.coeffs[1]) - tmp1583.coeffs[1] = constant_term(Y[1]) / constant_term(r_p1d2[1]) - tmp1583.coeffs[2:order + 1] .= zero(tmp1583.coeffs[1]) - r_y_unit.coeffs[1] = -(constant_term(tmp1583)) + tmp927.coeffs[1] = constant_term(Y[1]) / constant_term(r_p1d2[1]) + tmp927.coeffs[2:order + 1] .= zero(tmp927.coeffs[1]) + r_y_unit.coeffs[1] = -(constant_term(tmp927)) r_y_unit.coeffs[2:order + 1] .= zero(r_y_unit.coeffs[1]) - tmp1585.coeffs[1] = constant_term(Z[1]) / constant_term(r_p1d2[1]) - tmp1585.coeffs[2:order + 1] .= zero(tmp1585.coeffs[1]) - r_z_unit.coeffs[1] = -(constant_term(tmp1585)) + tmp929.coeffs[1] = constant_term(Z[1]) / constant_term(r_p1d2[1]) + tmp929.coeffs[2:order + 1] .= zero(tmp929.coeffs[1]) + r_z_unit.coeffs[1] = -(constant_term(tmp929)) r_z_unit.coeffs[2:order + 1] .= zero(r_z_unit.coeffs[1]) g_r.coeffs[1] = identity(constant_term(r_p2[1])) g_r.coeffs[2:order + 1] .= zero(g_r.coeffs[1]) @@ -1303,35 +1305,35 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! A2_t_g_r.coeffs[2:order + 1] .= zero(A2_t_g_r.coeffs[1]) A1_t_g_r.coeffs[1] = constant_term(q[8]) / constant_term(g_r) A1_t_g_r.coeffs[2:order + 1] .= zero(A1_t_g_r.coeffs[1]) - tmp1589.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_x_unit) - tmp1589.coeffs[2:order + 1] .= zero(tmp1589.coeffs[1]) - tmp1590.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_x_unit) - tmp1590.coeffs[2:order + 1] .= zero(tmp1590.coeffs[1]) - NGAx.coeffs[1] = constant_term(tmp1589) + constant_term(tmp1590) + tmp933.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_x_unit) + tmp933.coeffs[2:order + 1] .= zero(tmp933.coeffs[1]) + tmp934.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_x_unit) + tmp934.coeffs[2:order + 1] .= zero(tmp934.coeffs[1]) + NGAx.coeffs[1] = constant_term(tmp933) + constant_term(tmp934) NGAx.coeffs[2:order + 1] .= zero(NGAx.coeffs[1]) - tmp1592.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_y_unit) - tmp1592.coeffs[2:order + 1] .= zero(tmp1592.coeffs[1]) - tmp1593.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_y_unit) - tmp1593.coeffs[2:order + 1] .= zero(tmp1593.coeffs[1]) - NGAy.coeffs[1] = constant_term(tmp1592) + constant_term(tmp1593) + tmp936.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_y_unit) + tmp936.coeffs[2:order + 1] .= zero(tmp936.coeffs[1]) + tmp937.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_y_unit) + tmp937.coeffs[2:order + 1] .= zero(tmp937.coeffs[1]) + NGAy.coeffs[1] = constant_term(tmp936) + constant_term(tmp937) NGAy.coeffs[2:order + 1] .= zero(NGAy.coeffs[1]) - tmp1595.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_z_unit) - tmp1595.coeffs[2:order + 1] .= zero(tmp1595.coeffs[1]) - tmp1596.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_z_unit) - tmp1596.coeffs[2:order + 1] .= zero(tmp1596.coeffs[1]) - NGAz.coeffs[1] = constant_term(tmp1595) + constant_term(tmp1596) + tmp939.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_z_unit) + tmp939.coeffs[2:order + 1] .= zero(tmp939.coeffs[1]) + tmp940.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_z_unit) + tmp940.coeffs[2:order + 1] .= zero(tmp940.coeffs[1]) + NGAz.coeffs[1] = constant_term(tmp939) + constant_term(tmp940) NGAz.coeffs[2:order + 1] .= zero(NGAz.coeffs[1]) - tmp1598.coeffs[1] = constant_term(postNewtonX) + constant_term(accX) - tmp1598.coeffs[2:order + 1] .= zero(tmp1598.coeffs[1]) - (dq[4]).coeffs[1] = constant_term(tmp1598) + constant_term(NGAx) + tmp942.coeffs[1] = constant_term(postNewtonX) + constant_term(accX) + tmp942.coeffs[2:order + 1] .= zero(tmp942.coeffs[1]) + (dq[4]).coeffs[1] = constant_term(tmp942) + constant_term(NGAx) (dq[4]).coeffs[2:order + 1] .= zero((dq[4]).coeffs[1]) - tmp1600.coeffs[1] = constant_term(postNewtonY) + constant_term(accY) - tmp1600.coeffs[2:order + 1] .= zero(tmp1600.coeffs[1]) - (dq[5]).coeffs[1] = constant_term(tmp1600) + constant_term(NGAy) + tmp944.coeffs[1] = constant_term(postNewtonY) + constant_term(accY) + tmp944.coeffs[2:order + 1] .= zero(tmp944.coeffs[1]) + (dq[5]).coeffs[1] = constant_term(tmp944) + constant_term(NGAy) (dq[5]).coeffs[2:order + 1] .= zero((dq[5]).coeffs[1]) - tmp1602.coeffs[1] = constant_term(postNewtonZ) + constant_term(accZ) - tmp1602.coeffs[2:order + 1] .= zero(tmp1602.coeffs[1]) - (dq[6]).coeffs[1] = constant_term(tmp1602) + constant_term(NGAz) + tmp946.coeffs[1] = constant_term(postNewtonZ) + constant_term(accZ) + tmp946.coeffs[2:order + 1] .= zero(tmp946.coeffs[1]) + (dq[6]).coeffs[1] = constant_term(tmp946) + constant_term(NGAz) (dq[6]).coeffs[2:order + 1] .= zero((dq[6]).coeffs[1]) (dq[7]).coeffs[1] = identity(constant_term(zero_q_1)) (dq[7]).coeffs[2:order + 1] .= zero((dq[7]).coeffs[1]) @@ -1350,7 +1352,7 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! TaylorSeries.identity!(dq[2], q[5], ord) TaylorSeries.identity!(dq[3], q[6], ord) TaylorSeries.identity!(newtonianNb_Potential[N], zero_q_1, ord) - #= C:\Users\luisi\.julia\dev\NEOs.jl\ex.jl:245 =# Threads.@threads for i = 1:Nm1 + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 TaylorSeries.identity!(ui[i], ss16asteph_t[3 * ((N - 1) + i) - 2], ord) TaylorSeries.identity!(vi[i], ss16asteph_t[3 * ((N - 1) + i) - 1], ord) TaylorSeries.identity!(wi[i], ss16asteph_t[3 * ((N - 1) + i)], ord) @@ -1360,35 +1362,35 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! TaylorSeries.subst!(U[i], ui[i], dq[1], ord) TaylorSeries.subst!(V[i], vi[i], dq[2], ord) TaylorSeries.subst!(W[i], wi[i], dq[3], ord) - TaylorSeries.mul!(tmp1343[1], 4, dq[1], ord) - TaylorSeries.mul!(tmp1345[i], 3, ui[i], ord) - TaylorSeries.subst!(_4U_m_3X[i], tmp1343[1], tmp1345[i], ord) - TaylorSeries.mul!(tmp1348[2], 4, dq[2], ord) - TaylorSeries.mul!(tmp1350[i], 3, vi[i], ord) - TaylorSeries.subst!(_4V_m_3Y[i], tmp1348[2], tmp1350[i], ord) - TaylorSeries.mul!(tmp1353[3], 4, dq[3], ord) - TaylorSeries.mul!(tmp1355[i], 3, wi[i], ord) - TaylorSeries.subst!(_4W_m_3Z[i], tmp1353[3], tmp1355[i], ord) + TaylorSeries.mul!(tmp687[1], 4, dq[1], ord) + TaylorSeries.mul!(tmp689[i], 3, ui[i], ord) + TaylorSeries.subst!(_4U_m_3X[i], tmp687[1], tmp689[i], ord) + TaylorSeries.mul!(tmp692[2], 4, dq[2], ord) + TaylorSeries.mul!(tmp694[i], 3, vi[i], ord) + TaylorSeries.subst!(_4V_m_3Y[i], tmp692[2], tmp694[i], ord) + TaylorSeries.mul!(tmp697[3], 4, dq[3], ord) + TaylorSeries.mul!(tmp699[i], 3, wi[i], ord) + TaylorSeries.subst!(_4W_m_3Z[i], tmp697[3], tmp699[i], ord) TaylorSeries.mul!(pn2x[i], X[i], _4U_m_3X[i], ord) TaylorSeries.mul!(pn2y[i], Y[i], _4V_m_3Y[i], ord) TaylorSeries.mul!(pn2z[i], Z[i], _4W_m_3Z[i], ord) TaylorSeries.mul!(UU[i], ui[i], dq[1], ord) TaylorSeries.mul!(VV[i], vi[i], dq[2], ord) TaylorSeries.mul!(WW[i], wi[i], dq[3], ord) - TaylorSeries.add!(tmp1363[i], UU[i], VV[i], ord) - TaylorSeries.add!(vi_dot_vj[i], tmp1363[i], WW[i], ord) - TaylorSeries.pow!(tmp1366[i], X[i], 2, ord) - TaylorSeries.pow!(tmp1368[i], Y[i], 2, ord) - TaylorSeries.add!(tmp1369[i], tmp1366[i], tmp1368[i], ord) - TaylorSeries.pow!(tmp1371[i], Z[i], 2, ord) - TaylorSeries.add!(r_p2[i], tmp1369[i], tmp1371[i], ord) + TaylorSeries.add!(tmp707[i], UU[i], VV[i], ord) + TaylorSeries.add!(vi_dot_vj[i], tmp707[i], WW[i], ord) + TaylorSeries.pow!(tmp710[i], X[i], 2, ord) + TaylorSeries.pow!(tmp712[i], Y[i], 2, ord) + TaylorSeries.add!(tmp713[i], tmp710[i], tmp712[i], ord) + TaylorSeries.pow!(tmp715[i], Z[i], 2, ord) + TaylorSeries.add!(r_p2[i], tmp713[i], tmp715[i], ord) TaylorSeries.sqrt!(r_p1d2[i], r_p2[i], ord) TaylorSeries.pow!(r_p3d2[i], r_p2[i], 1.5, ord) TaylorSeries.pow!(r_p7d2[i], r_p2[i], 3.5, ord) TaylorSeries.div!(newtonianCoeff[i], μ[i], r_p3d2[i], ord) - TaylorSeries.add!(tmp1379[i], pn2x[i], pn2y[i], ord) - TaylorSeries.add!(tmp1380[i], tmp1379[i], pn2z[i], ord) - TaylorSeries.mul!(pn2[i], newtonianCoeff[i], tmp1380[i], ord) + TaylorSeries.add!(tmp723[i], pn2x[i], pn2y[i], ord) + TaylorSeries.add!(tmp724[i], tmp723[i], pn2z[i], ord) + TaylorSeries.mul!(pn2[i], newtonianCoeff[i], tmp724[i], ord) TaylorSeries.mul!(newton_acc_X[i], X[i], newtonianCoeff[i], ord) TaylorSeries.mul!(newton_acc_Y[i], Y[i], newtonianCoeff[i], ord) TaylorSeries.mul!(newton_acc_Z[i], Z[i], newtonianCoeff[i], ord) @@ -1398,51 +1400,51 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! TaylorSeries.mul!(V_t_pn2[i], pn2[i], V[i], ord) TaylorSeries.mul!(W_t_pn2[i], pn2[i], W[i], ord) if UJ_interaction[i] - TaylorSeries.subst!(tmp1391[i], X[i], ord) - TaylorSeries.mul!(t31[i], tmp1391[i], M_[1, 3, i], ord) - TaylorSeries.subst!(tmp1393[i], Y[i], ord) - TaylorSeries.mul!(t32[i], tmp1393[i], M_[2, 3, i], ord) - TaylorSeries.subst!(tmp1395[i], Z[i], ord) - TaylorSeries.mul!(t33[i], tmp1395[i], M_[3, 3, i], ord) - TaylorSeries.add!(tmp1397[i], t31[i], t32[i], ord) - TaylorSeries.add!(r_sin_ϕ[i], tmp1397[i], t33[i], ord) + TaylorSeries.subst!(tmp735[i], X[i], ord) + TaylorSeries.mul!(t31[i], tmp735[i], M_[1, 3, i], ord) + TaylorSeries.subst!(tmp737[i], Y[i], ord) + TaylorSeries.mul!(t32[i], tmp737[i], M_[2, 3, i], ord) + TaylorSeries.subst!(tmp739[i], Z[i], ord) + TaylorSeries.mul!(t33[i], tmp739[i], M_[3, 3, i], ord) + TaylorSeries.add!(tmp741[i], t31[i], t32[i], ord) + TaylorSeries.add!(r_sin_ϕ[i], tmp741[i], t33[i], ord) TaylorSeries.div!(sin_ϕ[i], r_sin_ϕ[i], r_p1d2[i], ord) - TaylorSeries.asin!(ϕ[i], sin_ϕ[i], tmp1604[i], ord) - TaylorSeries.sincos!(tmp1605[i], cos_ϕ[i], ϕ[i], ord) + TaylorSeries.asin!(ϕ[i], sin_ϕ[i], tmp948[i], ord) + TaylorSeries.sincos!(tmp949[i], cos_ϕ[i], ϕ[i], ord) TaylorSeries.pow!(sin2_ϕ[i], sin_ϕ[i], 2, ord) TaylorSeries.pow!(sin3_ϕ[i], sin_ϕ[i], 3, ord) - TaylorSeries.mul!(tmp1407[i], 1.5, sin2_ϕ[i], ord) - TaylorSeries.subst!(P_2_sin_ϕ[i], tmp1407[i], 0.5, ord) + TaylorSeries.mul!(tmp751[i], 1.5, sin2_ϕ[i], ord) + TaylorSeries.subst!(P_2_sin_ϕ[i], tmp751[i], 0.5, ord) TaylorSeries.mul!(∂P_2_sin_ϕ[i], 3, sin_ϕ[i], ord) - TaylorSeries.mul!(tmp1413[i], -1.5, sin_ϕ[i], ord) - TaylorSeries.mul!(tmp1415[i], 2.5, sin3_ϕ[i], ord) - TaylorSeries.add!(P_3_sin_ϕ[i], tmp1413[i], tmp1415[i], ord) - TaylorSeries.mul!(tmp1419[i], 7.5, sin2_ϕ[i], ord) - TaylorSeries.add!(∂P_3_sin_ϕ[i], -1.5, tmp1419[i], ord) - TaylorSeries.pow!(tmp1422[i], r_p2[i], 2, ord) - TaylorSeries.div!(tmp1423[i], Λ2[i], tmp1422[i], ord) - TaylorSeries.subst!(Λ2j_div_r4[i], tmp1423[i], ord) - TaylorSeries.pow!(tmp1426[i], r_p1d2[i], 5, ord) - TaylorSeries.div!(tmp1427[i], Λ3[i], tmp1426[i], ord) - TaylorSeries.subst!(Λ3j_div_r5[i], tmp1427[i], ord) - TaylorSeries.subst!(tmp1429[i], cos_ϕ[i], ord) - TaylorSeries.mul!(m_c_ϕ_∂P_2[i], tmp1429[i], ∂P_2_sin_ϕ[i], ord) - TaylorSeries.subst!(tmp1431[i], cos_ϕ[i], ord) - TaylorSeries.mul!(m_c_ϕ_∂P_3[i], tmp1431[i], ∂P_3_sin_ϕ[i], ord) - TaylorSeries.mul!(tmp1434[i], Λ2j_div_r4[i], 3, ord) - TaylorSeries.mul!(F_J2_ξ[i], tmp1434[i], P_2_sin_ϕ[i], ord) + TaylorSeries.mul!(tmp757[i], -1.5, sin_ϕ[i], ord) + TaylorSeries.mul!(tmp759[i], 2.5, sin3_ϕ[i], ord) + TaylorSeries.add!(P_3_sin_ϕ[i], tmp757[i], tmp759[i], ord) + TaylorSeries.mul!(tmp763[i], 7.5, sin2_ϕ[i], ord) + TaylorSeries.add!(∂P_3_sin_ϕ[i], -1.5, tmp763[i], ord) + TaylorSeries.pow!(tmp766[i], r_p2[i], 2, ord) + TaylorSeries.div!(tmp767[i], Λ2[i], tmp766[i], ord) + TaylorSeries.subst!(Λ2j_div_r4[i], tmp767[i], ord) + TaylorSeries.pow!(tmp770[i], r_p1d2[i], 5, ord) + TaylorSeries.div!(tmp771[i], Λ3[i], tmp770[i], ord) + TaylorSeries.subst!(Λ3j_div_r5[i], tmp771[i], ord) + TaylorSeries.subst!(tmp773[i], cos_ϕ[i], ord) + TaylorSeries.mul!(m_c_ϕ_∂P_2[i], tmp773[i], ∂P_2_sin_ϕ[i], ord) + TaylorSeries.subst!(tmp775[i], cos_ϕ[i], ord) + TaylorSeries.mul!(m_c_ϕ_∂P_3[i], tmp775[i], ∂P_3_sin_ϕ[i], ord) + TaylorSeries.mul!(tmp778[i], Λ2j_div_r4[i], 3, ord) + TaylorSeries.mul!(F_J2_ξ[i], tmp778[i], P_2_sin_ϕ[i], ord) TaylorSeries.mul!(F_J2_ζ[i], Λ2j_div_r4[i], m_c_ϕ_∂P_2[i], ord) - TaylorSeries.mul!(tmp1438[i], Λ3j_div_r5[i], 4, ord) - TaylorSeries.mul!(F_J3_ξ[i], tmp1438[i], P_3_sin_ϕ[i], ord) + TaylorSeries.mul!(tmp782[i], Λ3j_div_r5[i], 4, ord) + TaylorSeries.mul!(F_J3_ξ[i], tmp782[i], P_3_sin_ϕ[i], ord) TaylorSeries.mul!(F_J3_ζ[i], Λ3j_div_r5[i], m_c_ϕ_∂P_3[i], ord) TaylorSeries.identity!(F_J_ξ[i], F_J2_ξ[i], ord) TaylorSeries.identity!(F_J_ζ[i], F_J2_ζ[i], ord) - TaylorSeries.subst!(tmp1441[i], X[i], ord) - TaylorSeries.div!(ξx[i], tmp1441[i], r_p1d2[i], ord) - TaylorSeries.subst!(tmp1443[i], Y[i], ord) - TaylorSeries.div!(ξy[i], tmp1443[i], r_p1d2[i], ord) - TaylorSeries.subst!(tmp1445[i], Z[i], ord) - TaylorSeries.div!(ξz[i], tmp1445[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp785[i], X[i], ord) + TaylorSeries.div!(ξx[i], tmp785[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp787[i], Y[i], ord) + TaylorSeries.div!(ξy[i], tmp787[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp789[i], Z[i], ord) + TaylorSeries.div!(ξz[i], tmp789[i], r_p1d2[i], ord) TaylorSeries.mul!(ηx1[i], M_[2, 3, i], ξz[i], ord) TaylorSeries.mul!(ηy1[i], M_[3, 3, i], ξx[i], ord) TaylorSeries.mul!(ηz1[i], M_[1, 3, i], ξy[i], ord) @@ -1471,57 +1473,57 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! TaylorSeries.add!(F_J2_y[i], F_J2_y1[i], F_J2_y2[i], ord) TaylorSeries.add!(F_J2_z[i], F_J2_z1[i], F_J2_z2[i], ord) end - TaylorSeries.pow!(tmp1475[i], ui[i], 2, ord) - TaylorSeries.pow!(tmp1477[i], vi[i], 2, ord) - TaylorSeries.add!(tmp1478[i], tmp1475[i], tmp1477[i], ord) - TaylorSeries.pow!(tmp1480[i], wi[i], 2, ord) - TaylorSeries.add!(v2[i], tmp1478[i], tmp1480[i], ord) + TaylorSeries.pow!(tmp819[i], ui[i], 2, ord) + TaylorSeries.pow!(tmp821[i], vi[i], 2, ord) + TaylorSeries.add!(tmp822[i], tmp819[i], tmp821[i], ord) + TaylorSeries.pow!(tmp824[i], wi[i], 2, ord) + TaylorSeries.add!(v2[i], tmp822[i], tmp824[i], ord) end - TaylorSeries.pow!(tmp1483, q[4], 2, ord) - TaylorSeries.pow!(tmp1485, q[5], 2, ord) - TaylorSeries.add!(tmp1486, tmp1483, tmp1485, ord) - TaylorSeries.pow!(tmp1488, q[6], 2, ord) - TaylorSeries.add!(v2[N], tmp1486, tmp1488, ord) + TaylorSeries.pow!(tmp827, q[4], 2, ord) + TaylorSeries.pow!(tmp829, q[5], 2, ord) + TaylorSeries.add!(tmp830, tmp827, tmp829, ord) + TaylorSeries.pow!(tmp832, q[6], 2, ord) + TaylorSeries.add!(v2[N], tmp830, tmp832, ord) for i = 1:Nm1 TaylorSeries.add!(temp_004[i], newtonian1b_Potential[i], newtonianNb_Potential[N], ord) TaylorSeries.identity!(newtonianNb_Potential[N], temp_004[i], ord) if UJ_interaction[i] - TaylorSeries.mul!(tmp1491[i], μ[i], F_J2_x[i], ord) - TaylorSeries.subst!(temp_accX_i[i], accX, tmp1491[i], ord) + TaylorSeries.mul!(tmp835[i], μ[i], F_J2_x[i], ord) + TaylorSeries.subst!(temp_accX_i[i], accX, tmp835[i], ord) TaylorSeries.identity!(accX, temp_accX_i[i], ord) - TaylorSeries.mul!(tmp1493[i], μ[i], F_J2_y[i], ord) - TaylorSeries.subst!(temp_accY_i[i], accY, tmp1493[i], ord) + TaylorSeries.mul!(tmp837[i], μ[i], F_J2_y[i], ord) + TaylorSeries.subst!(temp_accY_i[i], accY, tmp837[i], ord) TaylorSeries.identity!(accY, temp_accY_i[i], ord) - TaylorSeries.mul!(tmp1495[i], μ[i], F_J2_z[i], ord) - TaylorSeries.subst!(temp_accZ_i[i], accZ, tmp1495[i], ord) + TaylorSeries.mul!(tmp839[i], μ[i], F_J2_z[i], ord) + TaylorSeries.subst!(temp_accZ_i[i], accZ, tmp839[i], ord) TaylorSeries.identity!(accZ, temp_accZ_i[i], ord) end end TaylorSeries.mul!(_4ϕj[N], 4, newtonianNb_Potential[N], ord) - #= C:\Users\luisi\.julia\dev\NEOs.jl\ex.jl:447 =# Threads.@threads for i = 1:10 + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 TaylorSeries.add!(ϕi_plus_4ϕj[i], newtonianNb_Potential_t[i], _4ϕj[N], ord) - TaylorSeries.mul!(tmp1501[i], 2, v2[i], ord) - TaylorSeries.mul!(tmp1503[i], 4, vi_dot_vj[i], ord) - TaylorSeries.subst!(tmp1504[i], tmp1501[i], tmp1503[i], ord) - TaylorSeries.add!(sj2_plus_2si2_minus_4vivj[i], tmp1504[i], v2[N], ord) + TaylorSeries.mul!(tmp845[i], 2, v2[i], ord) + TaylorSeries.mul!(tmp847[i], 4, vi_dot_vj[i], ord) + TaylorSeries.subst!(tmp848[i], tmp845[i], tmp847[i], ord) + TaylorSeries.add!(sj2_plus_2si2_minus_4vivj[i], tmp848[i], v2[N], ord) TaylorSeries.subst!(ϕs_and_vs[i], sj2_plus_2si2_minus_4vivj[i], ϕi_plus_4ϕj[i], ord) TaylorSeries.mul!(Xij_t_Ui[i], X[i], ui[i], ord) TaylorSeries.mul!(Yij_t_Vi[i], Y[i], vi[i], ord) TaylorSeries.mul!(Zij_t_Wi[i], Z[i], wi[i], ord) - TaylorSeries.add!(tmp1510[i], Xij_t_Ui[i], Yij_t_Vi[i], ord) - TaylorSeries.add!(Rij_dot_Vi[i], tmp1510[i], Zij_t_Wi[i], ord) - TaylorSeries.pow!(tmp1513[i], Rij_dot_Vi[i], 2, ord) - TaylorSeries.div!(pn1t7[i], tmp1513[i], r_p2[i], ord) - TaylorSeries.mul!(tmp1516[i], 1.5, pn1t7[i], ord) - TaylorSeries.subst!(pn1t2_7[i], ϕs_and_vs[i], tmp1516[i], ord) + TaylorSeries.add!(tmp854[i], Xij_t_Ui[i], Yij_t_Vi[i], ord) + TaylorSeries.add!(Rij_dot_Vi[i], tmp854[i], Zij_t_Wi[i], ord) + TaylorSeries.pow!(tmp857[i], Rij_dot_Vi[i], 2, ord) + TaylorSeries.div!(pn1t7[i], tmp857[i], r_p2[i], ord) + TaylorSeries.mul!(tmp860[i], 1.5, pn1t7[i], ord) + TaylorSeries.subst!(pn1t2_7[i], ϕs_and_vs[i], tmp860[i], ord) TaylorSeries.add!(pn1t1_7[i], c_p2, pn1t2_7[i], ord) TaylorSeries.mul!(pNX_t_X[i], acceph_t[3i - 2], X[i], ord) TaylorSeries.mul!(pNY_t_Y[i], acceph_t[3i - 1], Y[i], ord) TaylorSeries.mul!(pNZ_t_Z[i], acceph_t[3i], Z[i], ord) - TaylorSeries.add!(tmp1523[i], pNX_t_X[i], pNY_t_Y[i], ord) - TaylorSeries.add!(tmp1524[i], tmp1523[i], pNZ_t_Z[i], ord) - TaylorSeries.mul!(tmp1525[i], 0.5, tmp1524[i], ord) - TaylorSeries.add!(pn1[i], pn1t1_7[i], tmp1525[i], ord) + TaylorSeries.add!(tmp867[i], pNX_t_X[i], pNY_t_Y[i], ord) + TaylorSeries.add!(tmp868[i], tmp867[i], pNZ_t_Z[i], ord) + TaylorSeries.mul!(tmp869[i], 0.5, tmp868[i], ord) + TaylorSeries.add!(pn1[i], pn1t1_7[i], tmp869[i], ord) TaylorSeries.mul!(X_t_pn1[i], newton_acc_X[i], pn1[i], ord) TaylorSeries.mul!(Y_t_pn1[i], newton_acc_Y[i], pn1[i], ord) TaylorSeries.mul!(Z_t_pn1[i], newton_acc_Z[i], pn1[i], ord) @@ -1530,20 +1532,20 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! TaylorSeries.mul!(pNZ_t_pn3[i], acceph_t[3i], pn3[i], ord) end for i = 1:10 - TaylorSeries.add!(tmp1533[i], U_t_pn2[i], pNX_t_pn3[i], ord) - TaylorSeries.add!(termpnx[i], X_t_pn1[i], tmp1533[i], ord) + TaylorSeries.add!(tmp877[i], U_t_pn2[i], pNX_t_pn3[i], ord) + TaylorSeries.add!(termpnx[i], X_t_pn1[i], tmp877[i], ord) TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) TaylorSeries.identity!(pntempX, sumpnx[i], ord) - TaylorSeries.add!(tmp1536[i], V_t_pn2[i], pNY_t_pn3[i], ord) - TaylorSeries.add!(termpny[i], Y_t_pn1[i], tmp1536[i], ord) + TaylorSeries.add!(tmp880[i], V_t_pn2[i], pNY_t_pn3[i], ord) + TaylorSeries.add!(termpny[i], Y_t_pn1[i], tmp880[i], ord) TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) TaylorSeries.identity!(pntempY, sumpny[i], ord) - TaylorSeries.add!(tmp1539[i], W_t_pn2[i], pNZ_t_pn3[i], ord) - TaylorSeries.add!(termpnz[i], Z_t_pn1[i], tmp1539[i], ord) + TaylorSeries.add!(tmp883[i], W_t_pn2[i], pNZ_t_pn3[i], ord) + TaylorSeries.add!(termpnz[i], Z_t_pn1[i], tmp883[i], ord) TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) TaylorSeries.identity!(pntempZ, sumpnz[i], ord) end - #= C:\Users\luisi\.julia\dev\NEOs.jl\ex.jl:500 =# Threads.@threads for i = 11:Nm1 + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 TaylorSeries.mul!(X_t_pn1[i], c_p2, newton_acc_X[i], ord) TaylorSeries.mul!(Y_t_pn1[i], c_p2, newton_acc_Y[i], ord) TaylorSeries.mul!(Z_t_pn1[i], c_p2, newton_acc_Z[i], ord) @@ -1562,57 +1564,57 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! TaylorSeries.mul!(postNewtonX, pntempX, c_m2, ord) TaylorSeries.mul!(postNewtonY, pntempY, c_m2, ord) TaylorSeries.mul!(postNewtonZ, pntempZ, c_m2, ord) - TaylorSeries.mul!(tmp1551, Y[1], W[1], ord) - TaylorSeries.mul!(tmp1552, Z[1], V[1], ord) - TaylorSeries.subst!(hx, tmp1551, tmp1552, ord) - TaylorSeries.mul!(tmp1554, Z[1], U[1], ord) - TaylorSeries.mul!(tmp1555, X[1], W[1], ord) - TaylorSeries.subst!(hy, tmp1554, tmp1555, ord) - TaylorSeries.mul!(tmp1557, X[1], V[1], ord) - TaylorSeries.mul!(tmp1558, Y[1], U[1], ord) - TaylorSeries.subst!(hz, tmp1557, tmp1558, ord) - TaylorSeries.mul!(tmp1560, hz, Y[1], ord) - TaylorSeries.mul!(tmp1561, hy, Z[1], ord) - TaylorSeries.subst!(t_x, tmp1560, tmp1561, ord) - TaylorSeries.mul!(tmp1563, hx, Z[1], ord) - TaylorSeries.mul!(tmp1564, hz, X[1], ord) - TaylorSeries.subst!(t_y, tmp1563, tmp1564, ord) - TaylorSeries.mul!(tmp1566, hy, X[1], ord) - TaylorSeries.mul!(tmp1567, hx, Y[1], ord) - TaylorSeries.subst!(t_z, tmp1566, tmp1567, ord) - TaylorSeries.pow!(tmp1570, t_x, 2, ord) - TaylorSeries.pow!(tmp1572, t_y, 2, ord) - TaylorSeries.add!(tmp1573, tmp1570, tmp1572, ord) - TaylorSeries.pow!(tmp1575, t_z, 2, ord) - TaylorSeries.add!(tmp1576, tmp1573, tmp1575, ord) - TaylorSeries.sqrt!(t_norm, tmp1576, ord) + TaylorSeries.mul!(tmp895, Y[1], W[1], ord) + TaylorSeries.mul!(tmp896, Z[1], V[1], ord) + TaylorSeries.subst!(hx, tmp895, tmp896, ord) + TaylorSeries.mul!(tmp898, Z[1], U[1], ord) + TaylorSeries.mul!(tmp899, X[1], W[1], ord) + TaylorSeries.subst!(hy, tmp898, tmp899, ord) + TaylorSeries.mul!(tmp901, X[1], V[1], ord) + TaylorSeries.mul!(tmp902, Y[1], U[1], ord) + TaylorSeries.subst!(hz, tmp901, tmp902, ord) + TaylorSeries.mul!(tmp904, hz, Y[1], ord) + TaylorSeries.mul!(tmp905, hy, Z[1], ord) + TaylorSeries.subst!(t_x, tmp904, tmp905, ord) + TaylorSeries.mul!(tmp907, hx, Z[1], ord) + TaylorSeries.mul!(tmp908, hz, X[1], ord) + TaylorSeries.subst!(t_y, tmp907, tmp908, ord) + TaylorSeries.mul!(tmp910, hy, X[1], ord) + TaylorSeries.mul!(tmp911, hx, Y[1], ord) + TaylorSeries.subst!(t_z, tmp910, tmp911, ord) + TaylorSeries.pow!(tmp914, t_x, 2, ord) + TaylorSeries.pow!(tmp916, t_y, 2, ord) + TaylorSeries.add!(tmp917, tmp914, tmp916, ord) + TaylorSeries.pow!(tmp919, t_z, 2, ord) + TaylorSeries.add!(tmp920, tmp917, tmp919, ord) + TaylorSeries.sqrt!(t_norm, tmp920, ord) TaylorSeries.div!(t_x_unit, t_x, t_norm, ord) TaylorSeries.div!(t_y_unit, t_y, t_norm, ord) TaylorSeries.div!(t_z_unit, t_z, t_norm, ord) - TaylorSeries.div!(tmp1581, X[1], r_p1d2[1], ord) - TaylorSeries.subst!(r_x_unit, tmp1581, ord) - TaylorSeries.div!(tmp1583, Y[1], r_p1d2[1], ord) - TaylorSeries.subst!(r_y_unit, tmp1583, ord) - TaylorSeries.div!(tmp1585, Z[1], r_p1d2[1], ord) - TaylorSeries.subst!(r_z_unit, tmp1585, ord) + TaylorSeries.div!(tmp925, X[1], r_p1d2[1], ord) + TaylorSeries.subst!(r_x_unit, tmp925, ord) + TaylorSeries.div!(tmp927, Y[1], r_p1d2[1], ord) + TaylorSeries.subst!(r_y_unit, tmp927, ord) + TaylorSeries.div!(tmp929, Z[1], r_p1d2[1], ord) + TaylorSeries.subst!(r_z_unit, tmp929, ord) TaylorSeries.identity!(g_r, r_p2[1], ord) TaylorSeries.div!(A2_t_g_r, q[7], g_r, ord) TaylorSeries.div!(A1_t_g_r, q[8], g_r, ord) - TaylorSeries.mul!(tmp1589, A2_t_g_r, t_x_unit, ord) - TaylorSeries.mul!(tmp1590, A1_t_g_r, r_x_unit, ord) - TaylorSeries.add!(NGAx, tmp1589, tmp1590, ord) - TaylorSeries.mul!(tmp1592, A2_t_g_r, t_y_unit, ord) - TaylorSeries.mul!(tmp1593, A1_t_g_r, r_y_unit, ord) - TaylorSeries.add!(NGAy, tmp1592, tmp1593, ord) - TaylorSeries.mul!(tmp1595, A2_t_g_r, t_z_unit, ord) - TaylorSeries.mul!(tmp1596, A1_t_g_r, r_z_unit, ord) - TaylorSeries.add!(NGAz, tmp1595, tmp1596, ord) - TaylorSeries.add!(tmp1598, postNewtonX, accX, ord) - TaylorSeries.add!(dq[4], tmp1598, NGAx, ord) - TaylorSeries.add!(tmp1600, postNewtonY, accY, ord) - TaylorSeries.add!(dq[5], tmp1600, NGAy, ord) - TaylorSeries.add!(tmp1602, postNewtonZ, accZ, ord) - TaylorSeries.add!(dq[6], tmp1602, NGAz, ord) + TaylorSeries.mul!(tmp933, A2_t_g_r, t_x_unit, ord) + TaylorSeries.mul!(tmp934, A1_t_g_r, r_x_unit, ord) + TaylorSeries.add!(NGAx, tmp933, tmp934, ord) + TaylorSeries.mul!(tmp936, A2_t_g_r, t_y_unit, ord) + TaylorSeries.mul!(tmp937, A1_t_g_r, r_y_unit, ord) + TaylorSeries.add!(NGAy, tmp936, tmp937, ord) + TaylorSeries.mul!(tmp939, A2_t_g_r, t_z_unit, ord) + TaylorSeries.mul!(tmp940, A1_t_g_r, r_z_unit, ord) + TaylorSeries.add!(NGAz, tmp939, tmp940, ord) + TaylorSeries.add!(tmp942, postNewtonX, accX, ord) + TaylorSeries.add!(dq[4], tmp942, NGAx, ord) + TaylorSeries.add!(tmp944, postNewtonY, accY, ord) + TaylorSeries.add!(dq[5], tmp944, NGAy, ord) + TaylorSeries.add!(tmp946, postNewtonZ, accZ, ord) + TaylorSeries.add!(dq[6], tmp946, NGAz, ord) TaylorSeries.identity!(dq[7], zero_q_1, ord) for __idx = eachindex(q) (q[__idx]).coeffs[ordnext + 1] = (dq[__idx]).coeffs[ordnext] / ordnext @@ -1749,94 +1751,95 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_t accY = Taylor1(identity(constant_term(zero_q_1)), order) accZ = Taylor1(identity(constant_term(zero_q_1)), order) local M_ = Array{S}(undef, 3, 3, N) - local M_[:, :, ea] = t2c_jpl_de430(dsj2k) + local M_ .= zero_q_1 + local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 dq[1] = Taylor1(identity(constant_term(q[4])), order) dq[2] = Taylor1(identity(constant_term(q[5])), order) dq[3] = Taylor1(identity(constant_term(q[6])), order) newtonianNb_Potential[N] = Taylor1(identity(constant_term(zero_q_1)), order) - tmp1972 = Array{Taylor1{_S}}(undef, size(dq)) - tmp1972 .= Taylor1(zero(_S), order) - tmp1974 = Array{Taylor1{_S}}(undef, size(ui)) - tmp1974 .= Taylor1(zero(_S), order) - tmp1977 = Array{Taylor1{_S}}(undef, size(dq)) - tmp1977 .= Taylor1(zero(_S), order) - tmp1979 = Array{Taylor1{_S}}(undef, size(vi)) - tmp1979 .= Taylor1(zero(_S), order) - tmp1982 = Array{Taylor1{_S}}(undef, size(dq)) - tmp1982 .= Taylor1(zero(_S), order) - tmp1984 = Array{Taylor1{_S}}(undef, size(wi)) - tmp1984 .= Taylor1(zero(_S), order) + tmp1317 = Array{Taylor1{_S}}(undef, size(dq)) + tmp1317 .= Taylor1(zero(_S), order) + tmp1319 = Array{Taylor1{_S}}(undef, size(ui)) + tmp1319 .= Taylor1(zero(_S), order) + tmp1322 = Array{Taylor1{_S}}(undef, size(dq)) + tmp1322 .= Taylor1(zero(_S), order) + tmp1324 = Array{Taylor1{_S}}(undef, size(vi)) + tmp1324 .= Taylor1(zero(_S), order) + tmp1327 = Array{Taylor1{_S}}(undef, size(dq)) + tmp1327 .= Taylor1(zero(_S), order) + tmp1329 = Array{Taylor1{_S}}(undef, size(wi)) + tmp1329 .= Taylor1(zero(_S), order) pn2x = Array{Taylor1{_S}}(undef, size(X)) pn2x .= Taylor1(zero(_S), order) pn2y = Array{Taylor1{_S}}(undef, size(Y)) pn2y .= Taylor1(zero(_S), order) pn2z = Array{Taylor1{_S}}(undef, size(Z)) pn2z .= Taylor1(zero(_S), order) - tmp1992 = Array{Taylor1{_S}}(undef, size(UU)) - tmp1992 .= Taylor1(zero(_S), order) - tmp1995 = Array{Taylor1{_S}}(undef, size(X)) - tmp1995 .= Taylor1(zero(_S), order) - tmp1997 = Array{Taylor1{_S}}(undef, size(Y)) - tmp1997 .= Taylor1(zero(_S), order) - tmp1998 = Array{Taylor1{_S}}(undef, size(tmp1995)) - tmp1998 .= Taylor1(zero(_S), order) - tmp2000 = Array{Taylor1{_S}}(undef, size(Z)) - tmp2000 .= Taylor1(zero(_S), order) - tmp2008 = Array{Taylor1{_S}}(undef, size(pn2x)) - tmp2008 .= Taylor1(zero(_S), order) - tmp2009 = Array{Taylor1{_S}}(undef, size(tmp2008)) - tmp2009 .= Taylor1(zero(_S), order) - tmp2104 = Array{Taylor1{_S}}(undef, size(ui)) - tmp2104 .= Taylor1(zero(_S), order) - tmp2106 = Array{Taylor1{_S}}(undef, size(vi)) - tmp2106 .= Taylor1(zero(_S), order) - tmp2107 = Array{Taylor1{_S}}(undef, size(tmp2104)) - tmp2107 .= Taylor1(zero(_S), order) - tmp2109 = Array{Taylor1{_S}}(undef, size(wi)) - tmp2109 .= Taylor1(zero(_S), order) - tmp2020 = Array{Taylor1{_S}}(undef, size(X)) - tmp2020 .= Taylor1(zero(_S), order) - tmp2022 = Array{Taylor1{_S}}(undef, size(Y)) - tmp2022 .= Taylor1(zero(_S), order) - tmp2024 = Array{Taylor1{_S}}(undef, size(Z)) - tmp2024 .= Taylor1(zero(_S), order) - tmp2026 = Array{Taylor1{_S}}(undef, size(t31)) - tmp2026 .= Taylor1(zero(_S), order) - tmp2183 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp2183 .= Taylor1(zero(_S), order) - tmp2184 = Array{Taylor1{_S}}(undef, size(ϕ)) - tmp2184 .= Taylor1(zero(_S), order) - tmp2036 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp2036 .= Taylor1(zero(_S), order) - tmp2042 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp2042 .= Taylor1(zero(_S), order) - tmp2044 = Array{Taylor1{_S}}(undef, size(sin3_ϕ)) - tmp2044 .= Taylor1(zero(_S), order) - tmp2048 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp2048 .= Taylor1(zero(_S), order) - tmp2051 = Array{Taylor1{_S}}(undef, size(r_p2)) - tmp2051 .= Taylor1(zero(_S), order) - tmp2052 = Array{Taylor1{_S}}(undef, size(Λ2)) - tmp2052 .= Taylor1(zero(_S), order) - tmp2055 = Array{Taylor1{_S}}(undef, size(r_p1d2)) - tmp2055 .= Taylor1(zero(_S), order) - tmp2056 = Array{Taylor1{_S}}(undef, size(Λ3)) - tmp2056 .= Taylor1(zero(_S), order) - tmp2058 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp2058 .= Taylor1(zero(_S), order) - tmp2060 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp2060 .= Taylor1(zero(_S), order) - tmp2063 = Array{Taylor1{_S}}(undef, size(Λ2j_div_r4)) - tmp2063 .= Taylor1(zero(_S), order) - tmp2067 = Array{Taylor1{_S}}(undef, size(Λ3j_div_r5)) - tmp2067 .= Taylor1(zero(_S), order) - tmp2070 = Array{Taylor1{_S}}(undef, size(X)) - tmp2070 .= Taylor1(zero(_S), order) - tmp2072 = Array{Taylor1{_S}}(undef, size(Y)) - tmp2072 .= Taylor1(zero(_S), order) - tmp2074 = Array{Taylor1{_S}}(undef, size(Z)) - tmp2074 .= Taylor1(zero(_S), order) - #= C:\Users\luisi\.julia\dev\NEOs.jl\ex.jl:245 =# Threads.@threads for i = 1:Nm1 + tmp1337 = Array{Taylor1{_S}}(undef, size(UU)) + tmp1337 .= Taylor1(zero(_S), order) + tmp1340 = Array{Taylor1{_S}}(undef, size(X)) + tmp1340 .= Taylor1(zero(_S), order) + tmp1342 = Array{Taylor1{_S}}(undef, size(Y)) + tmp1342 .= Taylor1(zero(_S), order) + tmp1343 = Array{Taylor1{_S}}(undef, size(tmp1340)) + tmp1343 .= Taylor1(zero(_S), order) + tmp1345 = Array{Taylor1{_S}}(undef, size(Z)) + tmp1345 .= Taylor1(zero(_S), order) + tmp1353 = Array{Taylor1{_S}}(undef, size(pn2x)) + tmp1353 .= Taylor1(zero(_S), order) + tmp1354 = Array{Taylor1{_S}}(undef, size(tmp1353)) + tmp1354 .= Taylor1(zero(_S), order) + tmp1449 = Array{Taylor1{_S}}(undef, size(ui)) + tmp1449 .= Taylor1(zero(_S), order) + tmp1451 = Array{Taylor1{_S}}(undef, size(vi)) + tmp1451 .= Taylor1(zero(_S), order) + tmp1452 = Array{Taylor1{_S}}(undef, size(tmp1449)) + tmp1452 .= Taylor1(zero(_S), order) + tmp1454 = Array{Taylor1{_S}}(undef, size(wi)) + tmp1454 .= Taylor1(zero(_S), order) + tmp1365 = Array{Taylor1{_S}}(undef, size(X)) + tmp1365 .= Taylor1(zero(_S), order) + tmp1367 = Array{Taylor1{_S}}(undef, size(Y)) + tmp1367 .= Taylor1(zero(_S), order) + tmp1369 = Array{Taylor1{_S}}(undef, size(Z)) + tmp1369 .= Taylor1(zero(_S), order) + tmp1371 = Array{Taylor1{_S}}(undef, size(t31)) + tmp1371 .= Taylor1(zero(_S), order) + tmp1528 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) + tmp1528 .= Taylor1(zero(_S), order) + tmp1529 = Array{Taylor1{_S}}(undef, size(ϕ)) + tmp1529 .= Taylor1(zero(_S), order) + tmp1381 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) + tmp1381 .= Taylor1(zero(_S), order) + tmp1387 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) + tmp1387 .= Taylor1(zero(_S), order) + tmp1389 = Array{Taylor1{_S}}(undef, size(sin3_ϕ)) + tmp1389 .= Taylor1(zero(_S), order) + tmp1393 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) + tmp1393 .= Taylor1(zero(_S), order) + tmp1396 = Array{Taylor1{_S}}(undef, size(r_p2)) + tmp1396 .= Taylor1(zero(_S), order) + tmp1397 = Array{Taylor1{_S}}(undef, size(Λ2)) + tmp1397 .= Taylor1(zero(_S), order) + tmp1400 = Array{Taylor1{_S}}(undef, size(r_p1d2)) + tmp1400 .= Taylor1(zero(_S), order) + tmp1401 = Array{Taylor1{_S}}(undef, size(Λ3)) + tmp1401 .= Taylor1(zero(_S), order) + tmp1403 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) + tmp1403 .= Taylor1(zero(_S), order) + tmp1405 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) + tmp1405 .= Taylor1(zero(_S), order) + tmp1408 = Array{Taylor1{_S}}(undef, size(Λ2j_div_r4)) + tmp1408 .= Taylor1(zero(_S), order) + tmp1412 = Array{Taylor1{_S}}(undef, size(Λ3j_div_r5)) + tmp1412 .= Taylor1(zero(_S), order) + tmp1415 = Array{Taylor1{_S}}(undef, size(X)) + tmp1415 .= Taylor1(zero(_S), order) + tmp1417 = Array{Taylor1{_S}}(undef, size(Y)) + tmp1417 .= Taylor1(zero(_S), order) + tmp1419 = Array{Taylor1{_S}}(undef, size(Z)) + tmp1419 .= Taylor1(zero(_S), order) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 ui[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])), order) vi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])), order) wi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])), order) @@ -1846,35 +1849,35 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_t U[i] = Taylor1(constant_term(ui[i]) - constant_term(dq[1]), order) V[i] = Taylor1(constant_term(vi[i]) - constant_term(dq[2]), order) W[i] = Taylor1(constant_term(wi[i]) - constant_term(dq[3]), order) - tmp1972[1] = Taylor1(constant_term(4) * constant_term(dq[1]), order) - tmp1974[i] = Taylor1(constant_term(3) * constant_term(ui[i]), order) - _4U_m_3X[i] = Taylor1(constant_term(tmp1972[1]) - constant_term(tmp1974[i]), order) - tmp1977[2] = Taylor1(constant_term(4) * constant_term(dq[2]), order) - tmp1979[i] = Taylor1(constant_term(3) * constant_term(vi[i]), order) - _4V_m_3Y[i] = Taylor1(constant_term(tmp1977[2]) - constant_term(tmp1979[i]), order) - tmp1982[3] = Taylor1(constant_term(4) * constant_term(dq[3]), order) - tmp1984[i] = Taylor1(constant_term(3) * constant_term(wi[i]), order) - _4W_m_3Z[i] = Taylor1(constant_term(tmp1982[3]) - constant_term(tmp1984[i]), order) + tmp1317[1] = Taylor1(constant_term(4) * constant_term(dq[1]), order) + tmp1319[i] = Taylor1(constant_term(3) * constant_term(ui[i]), order) + _4U_m_3X[i] = Taylor1(constant_term(tmp1317[1]) - constant_term(tmp1319[i]), order) + tmp1322[2] = Taylor1(constant_term(4) * constant_term(dq[2]), order) + tmp1324[i] = Taylor1(constant_term(3) * constant_term(vi[i]), order) + _4V_m_3Y[i] = Taylor1(constant_term(tmp1322[2]) - constant_term(tmp1324[i]), order) + tmp1327[3] = Taylor1(constant_term(4) * constant_term(dq[3]), order) + tmp1329[i] = Taylor1(constant_term(3) * constant_term(wi[i]), order) + _4W_m_3Z[i] = Taylor1(constant_term(tmp1327[3]) - constant_term(tmp1329[i]), order) pn2x[i] = Taylor1(constant_term(X[i]) * constant_term(_4U_m_3X[i]), order) pn2y[i] = Taylor1(constant_term(Y[i]) * constant_term(_4V_m_3Y[i]), order) pn2z[i] = Taylor1(constant_term(Z[i]) * constant_term(_4W_m_3Z[i]), order) UU[i] = Taylor1(constant_term(ui[i]) * constant_term(dq[1]), order) VV[i] = Taylor1(constant_term(vi[i]) * constant_term(dq[2]), order) WW[i] = Taylor1(constant_term(wi[i]) * constant_term(dq[3]), order) - tmp1992[i] = Taylor1(constant_term(UU[i]) + constant_term(VV[i]), order) - vi_dot_vj[i] = Taylor1(constant_term(tmp1992[i]) + constant_term(WW[i]), order) - tmp1995[i] = Taylor1(constant_term(X[i]) ^ float(constant_term(2)), order) - tmp1997[i] = Taylor1(constant_term(Y[i]) ^ float(constant_term(2)), order) - tmp1998[i] = Taylor1(constant_term(tmp1995[i]) + constant_term(tmp1997[i]), order) - tmp2000[i] = Taylor1(constant_term(Z[i]) ^ float(constant_term(2)), order) - r_p2[i] = Taylor1(constant_term(tmp1998[i]) + constant_term(tmp2000[i]), order) + tmp1337[i] = Taylor1(constant_term(UU[i]) + constant_term(VV[i]), order) + vi_dot_vj[i] = Taylor1(constant_term(tmp1337[i]) + constant_term(WW[i]), order) + tmp1340[i] = Taylor1(constant_term(X[i]) ^ float(constant_term(2)), order) + tmp1342[i] = Taylor1(constant_term(Y[i]) ^ float(constant_term(2)), order) + tmp1343[i] = Taylor1(constant_term(tmp1340[i]) + constant_term(tmp1342[i]), order) + tmp1345[i] = Taylor1(constant_term(Z[i]) ^ float(constant_term(2)), order) + r_p2[i] = Taylor1(constant_term(tmp1343[i]) + constant_term(tmp1345[i]), order) r_p1d2[i] = Taylor1(sqrt(constant_term(r_p2[i])), order) r_p3d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(1.5)), order) r_p7d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(3.5)), order) newtonianCoeff[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p3d2[i]), order) - tmp2008[i] = Taylor1(constant_term(pn2x[i]) + constant_term(pn2y[i]), order) - tmp2009[i] = Taylor1(constant_term(tmp2008[i]) + constant_term(pn2z[i]), order) - pn2[i] = Taylor1(constant_term(newtonianCoeff[i]) * constant_term(tmp2009[i]), order) + tmp1353[i] = Taylor1(constant_term(pn2x[i]) + constant_term(pn2y[i]), order) + tmp1354[i] = Taylor1(constant_term(tmp1353[i]) + constant_term(pn2z[i]), order) + pn2[i] = Taylor1(constant_term(newtonianCoeff[i]) * constant_term(tmp1354[i]), order) newton_acc_X[i] = Taylor1(constant_term(X[i]) * constant_term(newtonianCoeff[i]), order) newton_acc_Y[i] = Taylor1(constant_term(Y[i]) * constant_term(newtonianCoeff[i]), order) newton_acc_Z[i] = Taylor1(constant_term(Z[i]) * constant_term(newtonianCoeff[i]), order) @@ -1884,53 +1887,53 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_t V_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(V[i]), order) W_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(W[i]), order) if UJ_interaction[i] - tmp2020[i] = Taylor1(-(constant_term(X[i])), order) - t31[i] = Taylor1(constant_term(tmp2020[i]) * constant_term(M_[1, 3, i]), order) - tmp2022[i] = Taylor1(-(constant_term(Y[i])), order) - t32[i] = Taylor1(constant_term(tmp2022[i]) * constant_term(M_[2, 3, i]), order) - tmp2024[i] = Taylor1(-(constant_term(Z[i])), order) - t33[i] = Taylor1(constant_term(tmp2024[i]) * constant_term(M_[3, 3, i]), order) - tmp2026[i] = Taylor1(constant_term(t31[i]) + constant_term(t32[i]), order) - r_sin_ϕ[i] = Taylor1(constant_term(tmp2026[i]) + constant_term(t33[i]), order) + tmp1365[i] = Taylor1(-(constant_term(X[i])), order) + t31[i] = Taylor1(constant_term(tmp1365[i]) * constant_term(M_[1, 3, i]), order) + tmp1367[i] = Taylor1(-(constant_term(Y[i])), order) + t32[i] = Taylor1(constant_term(tmp1367[i]) * constant_term(M_[2, 3, i]), order) + tmp1369[i] = Taylor1(-(constant_term(Z[i])), order) + t33[i] = Taylor1(constant_term(tmp1369[i]) * constant_term(M_[3, 3, i]), order) + tmp1371[i] = Taylor1(constant_term(t31[i]) + constant_term(t32[i]), order) + r_sin_ϕ[i] = Taylor1(constant_term(tmp1371[i]) + constant_term(t33[i]), order) sin_ϕ[i] = Taylor1(constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]), order) ϕ[i] = Taylor1(asin(constant_term(sin_ϕ[i])), order) - tmp2183[i] = Taylor1(sqrt(1 - constant_term(sin_ϕ[i]) ^ 2), order) + tmp1528[i] = Taylor1(sqrt(1 - constant_term(sin_ϕ[i]) ^ 2), order) cos_ϕ[i] = Taylor1(cos(constant_term(ϕ[i])), order) - tmp2184[i] = Taylor1(sin(constant_term(ϕ[i])), order) + tmp1529[i] = Taylor1(sin(constant_term(ϕ[i])), order) sin2_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(2)), order) sin3_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(3)), order) - tmp2036[i] = Taylor1(constant_term(1.5) * constant_term(sin2_ϕ[i]), order) - P_2_sin_ϕ[i] = Taylor1(constant_term(tmp2036[i]) - constant_term(0.5), order) + tmp1381[i] = Taylor1(constant_term(1.5) * constant_term(sin2_ϕ[i]), order) + P_2_sin_ϕ[i] = Taylor1(constant_term(tmp1381[i]) - constant_term(0.5), order) ∂P_2_sin_ϕ[i] = Taylor1(constant_term(3) * constant_term(sin_ϕ[i]), order) - tmp2042[i] = Taylor1(constant_term(-1.5) * constant_term(sin_ϕ[i]), order) - tmp2044[i] = Taylor1(constant_term(2.5) * constant_term(sin3_ϕ[i]), order) - P_3_sin_ϕ[i] = Taylor1(constant_term(tmp2042[i]) + constant_term(tmp2044[i]), order) - tmp2048[i] = Taylor1(constant_term(7.5) * constant_term(sin2_ϕ[i]), order) - ∂P_3_sin_ϕ[i] = Taylor1(constant_term(-1.5) + constant_term(tmp2048[i]), order) - tmp2051[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(2)), order) - tmp2052[i] = Taylor1(constant_term(Λ2[i]) / constant_term(tmp2051[i]), order) - Λ2j_div_r4[i] = Taylor1(-(constant_term(tmp2052[i])), order) - tmp2055[i] = Taylor1(constant_term(r_p1d2[i]) ^ float(constant_term(5)), order) - tmp2056[i] = Taylor1(constant_term(Λ3[i]) / constant_term(tmp2055[i]), order) - Λ3j_div_r5[i] = Taylor1(-(constant_term(tmp2056[i])), order) - tmp2058[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) - m_c_ϕ_∂P_2[i] = Taylor1(constant_term(tmp2058[i]) * constant_term(∂P_2_sin_ϕ[i]), order) - tmp2060[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) - m_c_ϕ_∂P_3[i] = Taylor1(constant_term(tmp2060[i]) * constant_term(∂P_3_sin_ϕ[i]), order) - tmp2063[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(3), order) - F_J2_ξ[i] = Taylor1(constant_term(tmp2063[i]) * constant_term(P_2_sin_ϕ[i]), order) + tmp1387[i] = Taylor1(constant_term(-1.5) * constant_term(sin_ϕ[i]), order) + tmp1389[i] = Taylor1(constant_term(2.5) * constant_term(sin3_ϕ[i]), order) + P_3_sin_ϕ[i] = Taylor1(constant_term(tmp1387[i]) + constant_term(tmp1389[i]), order) + tmp1393[i] = Taylor1(constant_term(7.5) * constant_term(sin2_ϕ[i]), order) + ∂P_3_sin_ϕ[i] = Taylor1(constant_term(-1.5) + constant_term(tmp1393[i]), order) + tmp1396[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(2)), order) + tmp1397[i] = Taylor1(constant_term(Λ2[i]) / constant_term(tmp1396[i]), order) + Λ2j_div_r4[i] = Taylor1(-(constant_term(tmp1397[i])), order) + tmp1400[i] = Taylor1(constant_term(r_p1d2[i]) ^ float(constant_term(5)), order) + tmp1401[i] = Taylor1(constant_term(Λ3[i]) / constant_term(tmp1400[i]), order) + Λ3j_div_r5[i] = Taylor1(-(constant_term(tmp1401[i])), order) + tmp1403[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) + m_c_ϕ_∂P_2[i] = Taylor1(constant_term(tmp1403[i]) * constant_term(∂P_2_sin_ϕ[i]), order) + tmp1405[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) + m_c_ϕ_∂P_3[i] = Taylor1(constant_term(tmp1405[i]) * constant_term(∂P_3_sin_ϕ[i]), order) + tmp1408[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(3), order) + F_J2_ξ[i] = Taylor1(constant_term(tmp1408[i]) * constant_term(P_2_sin_ϕ[i]), order) F_J2_ζ[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]), order) - tmp2067[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(4), order) - F_J3_ξ[i] = Taylor1(constant_term(tmp2067[i]) * constant_term(P_3_sin_ϕ[i]), order) + tmp1412[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(4), order) + F_J3_ξ[i] = Taylor1(constant_term(tmp1412[i]) * constant_term(P_3_sin_ϕ[i]), order) F_J3_ζ[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]), order) F_J_ξ[i] = Taylor1(identity(constant_term(F_J2_ξ[i])), order) F_J_ζ[i] = Taylor1(identity(constant_term(F_J2_ζ[i])), order) - tmp2070[i] = Taylor1(-(constant_term(X[i])), order) - ξx[i] = Taylor1(constant_term(tmp2070[i]) / constant_term(r_p1d2[i]), order) - tmp2072[i] = Taylor1(-(constant_term(Y[i])), order) - ξy[i] = Taylor1(constant_term(tmp2072[i]) / constant_term(r_p1d2[i]), order) - tmp2074[i] = Taylor1(-(constant_term(Z[i])), order) - ξz[i] = Taylor1(constant_term(tmp2074[i]) / constant_term(r_p1d2[i]), order) + tmp1415[i] = Taylor1(-(constant_term(X[i])), order) + ξx[i] = Taylor1(constant_term(tmp1415[i]) / constant_term(r_p1d2[i]), order) + tmp1417[i] = Taylor1(-(constant_term(Y[i])), order) + ξy[i] = Taylor1(constant_term(tmp1417[i]) / constant_term(r_p1d2[i]), order) + tmp1419[i] = Taylor1(-(constant_term(Z[i])), order) + ξz[i] = Taylor1(constant_term(tmp1419[i]) / constant_term(r_p1d2[i]), order) ηx1[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξz[i]), order) ηy1[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξx[i]), order) ηz1[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξy[i]), order) @@ -1959,95 +1962,95 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_t F_J2_y[i] = Taylor1(constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]), order) F_J2_z[i] = Taylor1(constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]), order) end - tmp2104[i] = Taylor1(constant_term(ui[i]) ^ float(constant_term(2)), order) - tmp2106[i] = Taylor1(constant_term(vi[i]) ^ float(constant_term(2)), order) - tmp2107[i] = Taylor1(constant_term(tmp2104[i]) + constant_term(tmp2106[i]), order) - tmp2109[i] = Taylor1(constant_term(wi[i]) ^ float(constant_term(2)), order) - v2[i] = Taylor1(constant_term(tmp2107[i]) + constant_term(tmp2109[i]), order) + tmp1449[i] = Taylor1(constant_term(ui[i]) ^ float(constant_term(2)), order) + tmp1451[i] = Taylor1(constant_term(vi[i]) ^ float(constant_term(2)), order) + tmp1452[i] = Taylor1(constant_term(tmp1449[i]) + constant_term(tmp1451[i]), order) + tmp1454[i] = Taylor1(constant_term(wi[i]) ^ float(constant_term(2)), order) + v2[i] = Taylor1(constant_term(tmp1452[i]) + constant_term(tmp1454[i]), order) end - tmp2112 = Taylor1(constant_term(q[4]) ^ float(constant_term(2)), order) - tmp2114 = Taylor1(constant_term(q[5]) ^ float(constant_term(2)), order) - tmp2115 = Taylor1(constant_term(tmp2112) + constant_term(tmp2114), order) - tmp2117 = Taylor1(constant_term(q[6]) ^ float(constant_term(2)), order) - v2[N] = Taylor1(constant_term(tmp2115) + constant_term(tmp2117), order) + tmp1457 = Taylor1(constant_term(q[4]) ^ float(constant_term(2)), order) + tmp1459 = Taylor1(constant_term(q[5]) ^ float(constant_term(2)), order) + tmp1460 = Taylor1(constant_term(tmp1457) + constant_term(tmp1459), order) + tmp1462 = Taylor1(constant_term(q[6]) ^ float(constant_term(2)), order) + v2[N] = Taylor1(constant_term(tmp1460) + constant_term(tmp1462), order) temp_004 = Array{Taylor1{_S}}(undef, size(newtonian1b_Potential)) temp_004 .= Taylor1(zero(_S), order) - tmp2120 = Array{Taylor1{_S}}(undef, size(μ)) - tmp2120 .= Taylor1(zero(_S), order) - tmp2122 = Array{Taylor1{_S}}(undef, size(μ)) - tmp2122 .= Taylor1(zero(_S), order) - tmp2124 = Array{Taylor1{_S}}(undef, size(μ)) - tmp2124 .= Taylor1(zero(_S), order) + tmp1465 = Array{Taylor1{_S}}(undef, size(μ)) + tmp1465 .= Taylor1(zero(_S), order) + tmp1467 = Array{Taylor1{_S}}(undef, size(μ)) + tmp1467 .= Taylor1(zero(_S), order) + tmp1469 = Array{Taylor1{_S}}(undef, size(μ)) + tmp1469 .= Taylor1(zero(_S), order) for i = 1:Nm1 temp_004[i] = Taylor1(constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]), order) newtonianNb_Potential[N] = Taylor1(identity(constant_term(temp_004[i])), order) if UJ_interaction[i] - tmp2120[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_x[i]), order) - temp_accX_i[i] = Taylor1(constant_term(accX) - constant_term(tmp2120[i]), order) + tmp1465[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_x[i]), order) + temp_accX_i[i] = Taylor1(constant_term(accX) - constant_term(tmp1465[i]), order) accX = Taylor1(identity(constant_term(temp_accX_i[i])), order) - tmp2122[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_y[i]), order) - temp_accY_i[i] = Taylor1(constant_term(accY) - constant_term(tmp2122[i]), order) + tmp1467[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_y[i]), order) + temp_accY_i[i] = Taylor1(constant_term(accY) - constant_term(tmp1467[i]), order) accY = Taylor1(identity(constant_term(temp_accY_i[i])), order) - tmp2124[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_z[i]), order) - temp_accZ_i[i] = Taylor1(constant_term(accZ) - constant_term(tmp2124[i]), order) + tmp1469[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_z[i]), order) + temp_accZ_i[i] = Taylor1(constant_term(accZ) - constant_term(tmp1469[i]), order) accZ = Taylor1(identity(constant_term(temp_accZ_i[i])), order) end end _4ϕj[N] = Taylor1(constant_term(4) * constant_term(newtonianNb_Potential[N]), order) - tmp2130 = Array{Taylor1{_S}}(undef, size(v2)) - tmp2130 .= Taylor1(zero(_S), order) - tmp2132 = Array{Taylor1{_S}}(undef, size(vi_dot_vj)) - tmp2132 .= Taylor1(zero(_S), order) - tmp2133 = Array{Taylor1{_S}}(undef, size(tmp2130)) - tmp2133 .= Taylor1(zero(_S), order) + tmp1475 = Array{Taylor1{_S}}(undef, size(v2)) + tmp1475 .= Taylor1(zero(_S), order) + tmp1477 = Array{Taylor1{_S}}(undef, size(vi_dot_vj)) + tmp1477 .= Taylor1(zero(_S), order) + tmp1478 = Array{Taylor1{_S}}(undef, size(tmp1475)) + tmp1478 .= Taylor1(zero(_S), order) Xij_t_Ui = Array{Taylor1{_S}}(undef, size(X)) Xij_t_Ui .= Taylor1(zero(_S), order) Yij_t_Vi = Array{Taylor1{_S}}(undef, size(Y)) Yij_t_Vi .= Taylor1(zero(_S), order) Zij_t_Wi = Array{Taylor1{_S}}(undef, size(Z)) Zij_t_Wi .= Taylor1(zero(_S), order) - tmp2139 = Array{Taylor1{_S}}(undef, size(Xij_t_Ui)) - tmp2139 .= Taylor1(zero(_S), order) - Rij_dot_Vi = Array{Taylor1{_S}}(undef, size(tmp2139)) + tmp1484 = Array{Taylor1{_S}}(undef, size(Xij_t_Ui)) + tmp1484 .= Taylor1(zero(_S), order) + Rij_dot_Vi = Array{Taylor1{_S}}(undef, size(tmp1484)) Rij_dot_Vi .= Taylor1(zero(_S), order) - tmp2142 = Array{Taylor1{_S}}(undef, size(Rij_dot_Vi)) - tmp2142 .= Taylor1(zero(_S), order) - pn1t7 = Array{Taylor1{_S}}(undef, size(tmp2142)) + tmp1487 = Array{Taylor1{_S}}(undef, size(Rij_dot_Vi)) + tmp1487 .= Taylor1(zero(_S), order) + pn1t7 = Array{Taylor1{_S}}(undef, size(tmp1487)) pn1t7 .= Taylor1(zero(_S), order) - tmp2145 = Array{Taylor1{_S}}(undef, size(pn1t7)) - tmp2145 .= Taylor1(zero(_S), order) + tmp1490 = Array{Taylor1{_S}}(undef, size(pn1t7)) + tmp1490 .= Taylor1(zero(_S), order) pn1t2_7 = Array{Taylor1{_S}}(undef, size(ϕs_and_vs)) pn1t2_7 .= Taylor1(zero(_S), order) - tmp2152 = Array{Taylor1{_S}}(undef, size(pNX_t_X)) - tmp2152 .= Taylor1(zero(_S), order) - tmp2153 = Array{Taylor1{_S}}(undef, size(tmp2152)) - tmp2153 .= Taylor1(zero(_S), order) - tmp2154 = Array{Taylor1{_S}}(undef, size(tmp2153)) - tmp2154 .= Taylor1(zero(_S), order) - #= C:\Users\luisi\.julia\dev\NEOs.jl\ex.jl:447 =# Threads.@threads for i = 1:10 + tmp1497 = Array{Taylor1{_S}}(undef, size(pNX_t_X)) + tmp1497 .= Taylor1(zero(_S), order) + tmp1498 = Array{Taylor1{_S}}(undef, size(tmp1497)) + tmp1498 .= Taylor1(zero(_S), order) + tmp1499 = Array{Taylor1{_S}}(undef, size(tmp1498)) + tmp1499 .= Taylor1(zero(_S), order) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 ϕi_plus_4ϕj[i] = Taylor1(constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]), order) - tmp2130[i] = Taylor1(constant_term(2) * constant_term(v2[i]), order) - tmp2132[i] = Taylor1(constant_term(4) * constant_term(vi_dot_vj[i]), order) - tmp2133[i] = Taylor1(constant_term(tmp2130[i]) - constant_term(tmp2132[i]), order) - sj2_plus_2si2_minus_4vivj[i] = Taylor1(constant_term(tmp2133[i]) + constant_term(v2[N]), order) + tmp1475[i] = Taylor1(constant_term(2) * constant_term(v2[i]), order) + tmp1477[i] = Taylor1(constant_term(4) * constant_term(vi_dot_vj[i]), order) + tmp1478[i] = Taylor1(constant_term(tmp1475[i]) - constant_term(tmp1477[i]), order) + sj2_plus_2si2_minus_4vivj[i] = Taylor1(constant_term(tmp1478[i]) + constant_term(v2[N]), order) ϕs_and_vs[i] = Taylor1(constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]), order) Xij_t_Ui[i] = Taylor1(constant_term(X[i]) * constant_term(ui[i]), order) Yij_t_Vi[i] = Taylor1(constant_term(Y[i]) * constant_term(vi[i]), order) Zij_t_Wi[i] = Taylor1(constant_term(Z[i]) * constant_term(wi[i]), order) - tmp2139[i] = Taylor1(constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]), order) - Rij_dot_Vi[i] = Taylor1(constant_term(tmp2139[i]) + constant_term(Zij_t_Wi[i]), order) - tmp2142[i] = Taylor1(constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)), order) - pn1t7[i] = Taylor1(constant_term(tmp2142[i]) / constant_term(r_p2[i]), order) - tmp2145[i] = Taylor1(constant_term(1.5) * constant_term(pn1t7[i]), order) - pn1t2_7[i] = Taylor1(constant_term(ϕs_and_vs[i]) - constant_term(tmp2145[i]), order) + tmp1484[i] = Taylor1(constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]), order) + Rij_dot_Vi[i] = Taylor1(constant_term(tmp1484[i]) + constant_term(Zij_t_Wi[i]), order) + tmp1487[i] = Taylor1(constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)), order) + pn1t7[i] = Taylor1(constant_term(tmp1487[i]) / constant_term(r_p2[i]), order) + tmp1490[i] = Taylor1(constant_term(1.5) * constant_term(pn1t7[i]), order) + pn1t2_7[i] = Taylor1(constant_term(ϕs_and_vs[i]) - constant_term(tmp1490[i]), order) pn1t1_7[i] = Taylor1(constant_term(c_p2) + constant_term(pn1t2_7[i]), order) pNX_t_X[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(X[i]), order) pNY_t_Y[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(Y[i]), order) pNZ_t_Z[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(Z[i]), order) - tmp2152[i] = Taylor1(constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]), order) - tmp2153[i] = Taylor1(constant_term(tmp2152[i]) + constant_term(pNZ_t_Z[i]), order) - tmp2154[i] = Taylor1(constant_term(0.5) * constant_term(tmp2153[i]), order) - pn1[i] = Taylor1(constant_term(pn1t1_7[i]) + constant_term(tmp2154[i]), order) + tmp1497[i] = Taylor1(constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]), order) + tmp1498[i] = Taylor1(constant_term(tmp1497[i]) + constant_term(pNZ_t_Z[i]), order) + tmp1499[i] = Taylor1(constant_term(0.5) * constant_term(tmp1498[i]), order) + pn1[i] = Taylor1(constant_term(pn1t1_7[i]) + constant_term(tmp1499[i]), order) X_t_pn1[i] = Taylor1(constant_term(newton_acc_X[i]) * constant_term(pn1[i]), order) Y_t_pn1[i] = Taylor1(constant_term(newton_acc_Y[i]) * constant_term(pn1[i]), order) Z_t_pn1[i] = Taylor1(constant_term(newton_acc_Z[i]) * constant_term(pn1[i]), order) @@ -2055,39 +2058,39 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_t pNY_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]), order) pNZ_t_pn3[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(pn3[i]), order) end - tmp2162 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) - tmp2162 .= Taylor1(zero(_S), order) + tmp1507 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) + tmp1507 .= Taylor1(zero(_S), order) termpnx = Array{Taylor1{_S}}(undef, size(X_t_pn1)) termpnx .= Taylor1(zero(_S), order) sumpnx = Array{Taylor1{_S}}(undef, size(termpnx)) sumpnx .= Taylor1(zero(_S), order) - tmp2165 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) - tmp2165 .= Taylor1(zero(_S), order) + tmp1510 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) + tmp1510 .= Taylor1(zero(_S), order) termpny = Array{Taylor1{_S}}(undef, size(Y_t_pn1)) termpny .= Taylor1(zero(_S), order) sumpny = Array{Taylor1{_S}}(undef, size(termpny)) sumpny .= Taylor1(zero(_S), order) - tmp2168 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) - tmp2168 .= Taylor1(zero(_S), order) + tmp1513 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) + tmp1513 .= Taylor1(zero(_S), order) termpnz = Array{Taylor1{_S}}(undef, size(Z_t_pn1)) termpnz .= Taylor1(zero(_S), order) sumpnz = Array{Taylor1{_S}}(undef, size(termpnz)) sumpnz .= Taylor1(zero(_S), order) for i = 1:10 - tmp2162[i] = Taylor1(constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]), order) - termpnx[i] = Taylor1(constant_term(X_t_pn1[i]) + constant_term(tmp2162[i]), order) + tmp1507[i] = Taylor1(constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]), order) + termpnx[i] = Taylor1(constant_term(X_t_pn1[i]) + constant_term(tmp1507[i]), order) sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) - tmp2165[i] = Taylor1(constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]), order) - termpny[i] = Taylor1(constant_term(Y_t_pn1[i]) + constant_term(tmp2165[i]), order) + tmp1510[i] = Taylor1(constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]), order) + termpny[i] = Taylor1(constant_term(Y_t_pn1[i]) + constant_term(tmp1510[i]), order) sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) pntempY = Taylor1(identity(constant_term(sumpny[i])), order) - tmp2168[i] = Taylor1(constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]), order) - termpnz[i] = Taylor1(constant_term(Z_t_pn1[i]) + constant_term(tmp2168[i]), order) + tmp1513[i] = Taylor1(constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]), order) + termpnz[i] = Taylor1(constant_term(Z_t_pn1[i]) + constant_term(tmp1513[i]), order) sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) end - #= C:\Users\luisi\.julia\dev\NEOs.jl\ex.jl:500 =# Threads.@threads for i = 11:Nm1 + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 X_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_X[i]), order) Y_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Y[i]), order) Z_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Z[i]), order) @@ -2109,16 +2112,16 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_t dq[4] = Taylor1(constant_term(postNewtonX) + constant_term(accX), order) dq[5] = Taylor1(constant_term(postNewtonY) + constant_term(accY), order) dq[6] = Taylor1(constant_term(postNewtonZ) + constant_term(accZ), order) - return TaylorIntegration.RetAlloc{Taylor1{_S}}([tmp2112, tmp2114, tmp2115, tmp2117, pntempX, pntempY, pntempZ, accX, accY, accZ, postNewtonX, postNewtonY, postNewtonZ], [X, Y, Z, r_p2, r_p1d2, r_p3d2, r_p7d2, newtonianCoeff, ui, vi, wi, U, V, W, _4U_m_3X, _4V_m_3Y, _4W_m_3Z, UU, VV, WW, newtonian1b_Potential, newtonianNb_Potential, newton_acc_X, newton_acc_Y, newton_acc_Z, v2, vi_dot_vj, pn2, U_t_pn2, V_t_pn2, W_t_pn2, pn3, pNX_t_pn3, pNY_t_pn3, pNZ_t_pn3, _4ϕj, ϕi_plus_4ϕj, sj2_plus_2si2_minus_4vivj, ϕs_and_vs, pn1t1_7, pNX_t_X, pNY_t_Y, pNZ_t_Z, pn1, X_t_pn1, Y_t_pn1, Z_t_pn1, t31, t32, t33, r_sin_ϕ, sin_ϕ, ϕ, cos_ϕ, sin2_ϕ, sin3_ϕ, F_J2_x, F_J2_y, F_J2_z, F_J2_x1, F_J2_y1, F_J2_z1, F_J2_x2, F_J2_y2, F_J2_z2, temp_accX_i, temp_accY_i, temp_accZ_i, P_2_sin_ϕ, ∂P_2_sin_ϕ, P_3_sin_ϕ, ∂P_3_sin_ϕ, m_c_ϕ_∂P_2, m_c_ϕ_∂P_3, Λ2j_div_r4, Λ3j_div_r5, F_J_ξ, F_J_ζ, F_J2_ξ, F_J2_ζ, F_J3_ξ, F_J3_ζ, ξx, ξy, ξz, ηx, ηy, ηz, ηx1, ηy1, ηz1, ηx2, ηy2, ηz2, ζx, ζy, ζz, ζx1, ζy1, ζz1, ζx2, ζy2, ζz2, tmp1972, tmp1974, tmp1977, tmp1979, tmp1982, tmp1984, pn2x, pn2y, pn2z, tmp1992, tmp1995, tmp1997, tmp1998, tmp2000, tmp2008, tmp2009, tmp2020, tmp2022, tmp2024, tmp2026, tmp2183, tmp2184, tmp2036, tmp2042, tmp2044, tmp2048, tmp2051, tmp2052, tmp2055, tmp2056, tmp2058, tmp2060, tmp2063, tmp2067, tmp2070, tmp2072, tmp2074, tmp2104, tmp2106, tmp2107, tmp2109, temp_004, tmp2120, tmp2122, tmp2124, tmp2130, tmp2132, tmp2133, Xij_t_Ui, Yij_t_Vi, Zij_t_Wi, tmp2139, Rij_dot_Vi, tmp2142, pn1t7, tmp2145, pn1t2_7, tmp2152, tmp2153, tmp2154, tmp2162, termpnx, sumpnx, tmp2165, termpny, sumpny, tmp2168, termpnz, sumpnz], [Array{Taylor1{_S}, 2}(undef, 0, 0)], [Array{Taylor1{_S}, 3}(undef, 0, 0, 0)], [Array{Taylor1{_S}, 4}(undef, 0, 0, 0, 0)]) + return TaylorIntegration.RetAlloc{Taylor1{_S}}([tmp1457, tmp1459, tmp1460, tmp1462, pntempX, pntempY, pntempZ, accX, accY, accZ, postNewtonX, postNewtonY, postNewtonZ], [X, Y, Z, r_p2, r_p1d2, r_p3d2, r_p7d2, newtonianCoeff, ui, vi, wi, U, V, W, _4U_m_3X, _4V_m_3Y, _4W_m_3Z, UU, VV, WW, newtonian1b_Potential, newtonianNb_Potential, newton_acc_X, newton_acc_Y, newton_acc_Z, v2, vi_dot_vj, pn2, U_t_pn2, V_t_pn2, W_t_pn2, pn3, pNX_t_pn3, pNY_t_pn3, pNZ_t_pn3, _4ϕj, ϕi_plus_4ϕj, sj2_plus_2si2_minus_4vivj, ϕs_and_vs, pn1t1_7, pNX_t_X, pNY_t_Y, pNZ_t_Z, pn1, X_t_pn1, Y_t_pn1, Z_t_pn1, t31, t32, t33, r_sin_ϕ, sin_ϕ, ϕ, cos_ϕ, sin2_ϕ, sin3_ϕ, F_J2_x, F_J2_y, F_J2_z, F_J2_x1, F_J2_y1, F_J2_z1, F_J2_x2, F_J2_y2, F_J2_z2, temp_accX_i, temp_accY_i, temp_accZ_i, P_2_sin_ϕ, ∂P_2_sin_ϕ, P_3_sin_ϕ, ∂P_3_sin_ϕ, m_c_ϕ_∂P_2, m_c_ϕ_∂P_3, Λ2j_div_r4, Λ3j_div_r5, F_J_ξ, F_J_ζ, F_J2_ξ, F_J2_ζ, F_J3_ξ, F_J3_ζ, ξx, ξy, ξz, ηx, ηy, ηz, ηx1, ηy1, ηz1, ηx2, ηy2, ηz2, ζx, ζy, ζz, ζx1, ζy1, ζz1, ζx2, ζy2, ζz2, tmp1317, tmp1319, tmp1322, tmp1324, tmp1327, tmp1329, pn2x, pn2y, pn2z, tmp1337, tmp1340, tmp1342, tmp1343, tmp1345, tmp1353, tmp1354, tmp1365, tmp1367, tmp1369, tmp1371, tmp1528, tmp1529, tmp1381, tmp1387, tmp1389, tmp1393, tmp1396, tmp1397, tmp1400, tmp1401, tmp1403, tmp1405, tmp1408, tmp1412, tmp1415, tmp1417, tmp1419, tmp1449, tmp1451, tmp1452, tmp1454, temp_004, tmp1465, tmp1467, tmp1469, tmp1475, tmp1477, tmp1478, Xij_t_Ui, Yij_t_Vi, Zij_t_Wi, tmp1484, Rij_dot_Vi, tmp1487, pn1t7, tmp1490, pn1t2_7, tmp1497, tmp1498, tmp1499, tmp1507, termpnx, sumpnx, tmp1510, termpny, sumpny, tmp1513, termpnz, sumpnz], [Array{Taylor1{_S}, 2}(undef, 0, 0)], [Array{Taylor1{_S}, 3}(undef, 0, 0, 0)], [Array{Taylor1{_S}, 4}(undef, 0, 0, 0, 0)]) end # TaylorIntegration.jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_eph_threads! function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params, __ralloc::TaylorIntegration.RetAlloc{Taylor1{_S}}) where {_T <: Real, _S <: Number, _N} order = t.order - tmp2112 = __ralloc.v0[1] - tmp2114 = __ralloc.v0[2] - tmp2115 = __ralloc.v0[3] - tmp2117 = __ralloc.v0[4] + tmp1457 = __ralloc.v0[1] + tmp1459 = __ralloc.v0[2] + tmp1460 = __ralloc.v0[3] + tmp1462 = __ralloc.v0[4] pntempX = __ralloc.v0[5] pntempY = __ralloc.v0[6] pntempZ = __ralloc.v0[7] @@ -2231,73 +2234,73 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, ζx2 = __ralloc.v1[101] ζy2 = __ralloc.v1[102] ζz2 = __ralloc.v1[103] - tmp1972 = __ralloc.v1[104] - tmp1974 = __ralloc.v1[105] - tmp1977 = __ralloc.v1[106] - tmp1979 = __ralloc.v1[107] - tmp1982 = __ralloc.v1[108] - tmp1984 = __ralloc.v1[109] + tmp1317 = __ralloc.v1[104] + tmp1319 = __ralloc.v1[105] + tmp1322 = __ralloc.v1[106] + tmp1324 = __ralloc.v1[107] + tmp1327 = __ralloc.v1[108] + tmp1329 = __ralloc.v1[109] pn2x = __ralloc.v1[110] pn2y = __ralloc.v1[111] pn2z = __ralloc.v1[112] - tmp1992 = __ralloc.v1[113] - tmp1995 = __ralloc.v1[114] - tmp1997 = __ralloc.v1[115] - tmp1998 = __ralloc.v1[116] - tmp2000 = __ralloc.v1[117] - tmp2008 = __ralloc.v1[118] - tmp2009 = __ralloc.v1[119] - tmp2020 = __ralloc.v1[120] - tmp2022 = __ralloc.v1[121] - tmp2024 = __ralloc.v1[122] - tmp2026 = __ralloc.v1[123] - tmp2183 = __ralloc.v1[124] - tmp2184 = __ralloc.v1[125] - tmp2036 = __ralloc.v1[126] - tmp2042 = __ralloc.v1[127] - tmp2044 = __ralloc.v1[128] - tmp2048 = __ralloc.v1[129] - tmp2051 = __ralloc.v1[130] - tmp2052 = __ralloc.v1[131] - tmp2055 = __ralloc.v1[132] - tmp2056 = __ralloc.v1[133] - tmp2058 = __ralloc.v1[134] - tmp2060 = __ralloc.v1[135] - tmp2063 = __ralloc.v1[136] - tmp2067 = __ralloc.v1[137] - tmp2070 = __ralloc.v1[138] - tmp2072 = __ralloc.v1[139] - tmp2074 = __ralloc.v1[140] - tmp2104 = __ralloc.v1[141] - tmp2106 = __ralloc.v1[142] - tmp2107 = __ralloc.v1[143] - tmp2109 = __ralloc.v1[144] + tmp1337 = __ralloc.v1[113] + tmp1340 = __ralloc.v1[114] + tmp1342 = __ralloc.v1[115] + tmp1343 = __ralloc.v1[116] + tmp1345 = __ralloc.v1[117] + tmp1353 = __ralloc.v1[118] + tmp1354 = __ralloc.v1[119] + tmp1365 = __ralloc.v1[120] + tmp1367 = __ralloc.v1[121] + tmp1369 = __ralloc.v1[122] + tmp1371 = __ralloc.v1[123] + tmp1528 = __ralloc.v1[124] + tmp1529 = __ralloc.v1[125] + tmp1381 = __ralloc.v1[126] + tmp1387 = __ralloc.v1[127] + tmp1389 = __ralloc.v1[128] + tmp1393 = __ralloc.v1[129] + tmp1396 = __ralloc.v1[130] + tmp1397 = __ralloc.v1[131] + tmp1400 = __ralloc.v1[132] + tmp1401 = __ralloc.v1[133] + tmp1403 = __ralloc.v1[134] + tmp1405 = __ralloc.v1[135] + tmp1408 = __ralloc.v1[136] + tmp1412 = __ralloc.v1[137] + tmp1415 = __ralloc.v1[138] + tmp1417 = __ralloc.v1[139] + tmp1419 = __ralloc.v1[140] + tmp1449 = __ralloc.v1[141] + tmp1451 = __ralloc.v1[142] + tmp1452 = __ralloc.v1[143] + tmp1454 = __ralloc.v1[144] temp_004 = __ralloc.v1[145] - tmp2120 = __ralloc.v1[146] - tmp2122 = __ralloc.v1[147] - tmp2124 = __ralloc.v1[148] - tmp2130 = __ralloc.v1[149] - tmp2132 = __ralloc.v1[150] - tmp2133 = __ralloc.v1[151] + tmp1465 = __ralloc.v1[146] + tmp1467 = __ralloc.v1[147] + tmp1469 = __ralloc.v1[148] + tmp1475 = __ralloc.v1[149] + tmp1477 = __ralloc.v1[150] + tmp1478 = __ralloc.v1[151] Xij_t_Ui = __ralloc.v1[152] Yij_t_Vi = __ralloc.v1[153] Zij_t_Wi = __ralloc.v1[154] - tmp2139 = __ralloc.v1[155] + tmp1484 = __ralloc.v1[155] Rij_dot_Vi = __ralloc.v1[156] - tmp2142 = __ralloc.v1[157] + tmp1487 = __ralloc.v1[157] pn1t7 = __ralloc.v1[158] - tmp2145 = __ralloc.v1[159] + tmp1490 = __ralloc.v1[159] pn1t2_7 = __ralloc.v1[160] - tmp2152 = __ralloc.v1[161] - tmp2153 = __ralloc.v1[162] - tmp2154 = __ralloc.v1[163] - tmp2162 = __ralloc.v1[164] + tmp1497 = __ralloc.v1[161] + tmp1498 = __ralloc.v1[162] + tmp1499 = __ralloc.v1[163] + tmp1507 = __ralloc.v1[164] termpnx = __ralloc.v1[165] sumpnx = __ralloc.v1[166] - tmp2165 = __ralloc.v1[167] + tmp1510 = __ralloc.v1[167] termpny = __ralloc.v1[168] sumpny = __ralloc.v1[169] - tmp2168 = __ralloc.v1[170] + tmp1513 = __ralloc.v1[170] termpnz = __ralloc.v1[171] sumpnz = __ralloc.v1[172] local jd0 = params[4] @@ -2324,7 +2327,8 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, accZ.coeffs[1] = identity(constant_term(zero_q_1)) accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) local M_ = Array{S}(undef, 3, 3, N) - local M_[:, :, ea] = t2c_jpl_de430(dsj2k) + local M_ .= zero_q_1 + local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 (dq[1]).coeffs[1] = identity(constant_term(q[4])) (dq[1]).coeffs[2:order + 1] .= zero((dq[1]).coeffs[1]) (dq[2]).coeffs[1] = identity(constant_term(q[5])) @@ -2333,7 +2337,7 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, (dq[3]).coeffs[2:order + 1] .= zero((dq[3]).coeffs[1]) (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(zero_q_1)) (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) - #= C:\Users\luisi\.julia\dev\NEOs.jl\ex.jl:245 =# Threads.@threads for i = 1:Nm1 + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 (ui[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])) (ui[i]).coeffs[2:order + 1] .= zero((ui[i]).coeffs[1]) (vi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])) @@ -2352,23 +2356,23 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, (V[i]).coeffs[2:order + 1] .= zero((V[i]).coeffs[1]) (W[i]).coeffs[1] = constant_term(wi[i]) - constant_term(dq[3]) (W[i]).coeffs[2:order + 1] .= zero((W[i]).coeffs[1]) - (tmp1972[1]).coeffs[1] = constant_term(4) * constant_term(dq[1]) - (tmp1972[1]).coeffs[2:order + 1] .= zero((tmp1972[1]).coeffs[1]) - (tmp1974[i]).coeffs[1] = constant_term(3) * constant_term(ui[i]) - (tmp1974[i]).coeffs[2:order + 1] .= zero((tmp1974[i]).coeffs[1]) - (_4U_m_3X[i]).coeffs[1] = constant_term(tmp1972[1]) - constant_term(tmp1974[i]) + (tmp1317[1]).coeffs[1] = constant_term(4) * constant_term(dq[1]) + (tmp1317[1]).coeffs[2:order + 1] .= zero((tmp1317[1]).coeffs[1]) + (tmp1319[i]).coeffs[1] = constant_term(3) * constant_term(ui[i]) + (tmp1319[i]).coeffs[2:order + 1] .= zero((tmp1319[i]).coeffs[1]) + (_4U_m_3X[i]).coeffs[1] = constant_term(tmp1317[1]) - constant_term(tmp1319[i]) (_4U_m_3X[i]).coeffs[2:order + 1] .= zero((_4U_m_3X[i]).coeffs[1]) - (tmp1977[2]).coeffs[1] = constant_term(4) * constant_term(dq[2]) - (tmp1977[2]).coeffs[2:order + 1] .= zero((tmp1977[2]).coeffs[1]) - (tmp1979[i]).coeffs[1] = constant_term(3) * constant_term(vi[i]) - (tmp1979[i]).coeffs[2:order + 1] .= zero((tmp1979[i]).coeffs[1]) - (_4V_m_3Y[i]).coeffs[1] = constant_term(tmp1977[2]) - constant_term(tmp1979[i]) + (tmp1322[2]).coeffs[1] = constant_term(4) * constant_term(dq[2]) + (tmp1322[2]).coeffs[2:order + 1] .= zero((tmp1322[2]).coeffs[1]) + (tmp1324[i]).coeffs[1] = constant_term(3) * constant_term(vi[i]) + (tmp1324[i]).coeffs[2:order + 1] .= zero((tmp1324[i]).coeffs[1]) + (_4V_m_3Y[i]).coeffs[1] = constant_term(tmp1322[2]) - constant_term(tmp1324[i]) (_4V_m_3Y[i]).coeffs[2:order + 1] .= zero((_4V_m_3Y[i]).coeffs[1]) - (tmp1982[3]).coeffs[1] = constant_term(4) * constant_term(dq[3]) - (tmp1982[3]).coeffs[2:order + 1] .= zero((tmp1982[3]).coeffs[1]) - (tmp1984[i]).coeffs[1] = constant_term(3) * constant_term(wi[i]) - (tmp1984[i]).coeffs[2:order + 1] .= zero((tmp1984[i]).coeffs[1]) - (_4W_m_3Z[i]).coeffs[1] = constant_term(tmp1982[3]) - constant_term(tmp1984[i]) + (tmp1327[3]).coeffs[1] = constant_term(4) * constant_term(dq[3]) + (tmp1327[3]).coeffs[2:order + 1] .= zero((tmp1327[3]).coeffs[1]) + (tmp1329[i]).coeffs[1] = constant_term(3) * constant_term(wi[i]) + (tmp1329[i]).coeffs[2:order + 1] .= zero((tmp1329[i]).coeffs[1]) + (_4W_m_3Z[i]).coeffs[1] = constant_term(tmp1327[3]) - constant_term(tmp1329[i]) (_4W_m_3Z[i]).coeffs[2:order + 1] .= zero((_4W_m_3Z[i]).coeffs[1]) (pn2x[i]).coeffs[1] = constant_term(X[i]) * constant_term(_4U_m_3X[i]) (pn2x[i]).coeffs[2:order + 1] .= zero((pn2x[i]).coeffs[1]) @@ -2382,19 +2386,19 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, (VV[i]).coeffs[2:order + 1] .= zero((VV[i]).coeffs[1]) (WW[i]).coeffs[1] = constant_term(wi[i]) * constant_term(dq[3]) (WW[i]).coeffs[2:order + 1] .= zero((WW[i]).coeffs[1]) - (tmp1992[i]).coeffs[1] = constant_term(UU[i]) + constant_term(VV[i]) - (tmp1992[i]).coeffs[2:order + 1] .= zero((tmp1992[i]).coeffs[1]) - (vi_dot_vj[i]).coeffs[1] = constant_term(tmp1992[i]) + constant_term(WW[i]) + (tmp1337[i]).coeffs[1] = constant_term(UU[i]) + constant_term(VV[i]) + (tmp1337[i]).coeffs[2:order + 1] .= zero((tmp1337[i]).coeffs[1]) + (vi_dot_vj[i]).coeffs[1] = constant_term(tmp1337[i]) + constant_term(WW[i]) (vi_dot_vj[i]).coeffs[2:order + 1] .= zero((vi_dot_vj[i]).coeffs[1]) - (tmp1995[i]).coeffs[1] = constant_term(X[i]) ^ float(constant_term(2)) - (tmp1995[i]).coeffs[2:order + 1] .= zero((tmp1995[i]).coeffs[1]) - (tmp1997[i]).coeffs[1] = constant_term(Y[i]) ^ float(constant_term(2)) - (tmp1997[i]).coeffs[2:order + 1] .= zero((tmp1997[i]).coeffs[1]) - (tmp1998[i]).coeffs[1] = constant_term(tmp1995[i]) + constant_term(tmp1997[i]) - (tmp1998[i]).coeffs[2:order + 1] .= zero((tmp1998[i]).coeffs[1]) - (tmp2000[i]).coeffs[1] = constant_term(Z[i]) ^ float(constant_term(2)) - (tmp2000[i]).coeffs[2:order + 1] .= zero((tmp2000[i]).coeffs[1]) - (r_p2[i]).coeffs[1] = constant_term(tmp1998[i]) + constant_term(tmp2000[i]) + (tmp1340[i]).coeffs[1] = constant_term(X[i]) ^ float(constant_term(2)) + (tmp1340[i]).coeffs[2:order + 1] .= zero((tmp1340[i]).coeffs[1]) + (tmp1342[i]).coeffs[1] = constant_term(Y[i]) ^ float(constant_term(2)) + (tmp1342[i]).coeffs[2:order + 1] .= zero((tmp1342[i]).coeffs[1]) + (tmp1343[i]).coeffs[1] = constant_term(tmp1340[i]) + constant_term(tmp1342[i]) + (tmp1343[i]).coeffs[2:order + 1] .= zero((tmp1343[i]).coeffs[1]) + (tmp1345[i]).coeffs[1] = constant_term(Z[i]) ^ float(constant_term(2)) + (tmp1345[i]).coeffs[2:order + 1] .= zero((tmp1345[i]).coeffs[1]) + (r_p2[i]).coeffs[1] = constant_term(tmp1343[i]) + constant_term(tmp1345[i]) (r_p2[i]).coeffs[2:order + 1] .= zero((r_p2[i]).coeffs[1]) (r_p1d2[i]).coeffs[1] = sqrt(constant_term(r_p2[i])) (r_p1d2[i]).coeffs[2:order + 1] .= zero((r_p1d2[i]).coeffs[1]) @@ -2404,11 +2408,11 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, (r_p7d2[i]).coeffs[2:order + 1] .= zero((r_p7d2[i]).coeffs[1]) (newtonianCoeff[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p3d2[i]) (newtonianCoeff[i]).coeffs[2:order + 1] .= zero((newtonianCoeff[i]).coeffs[1]) - (tmp2008[i]).coeffs[1] = constant_term(pn2x[i]) + constant_term(pn2y[i]) - (tmp2008[i]).coeffs[2:order + 1] .= zero((tmp2008[i]).coeffs[1]) - (tmp2009[i]).coeffs[1] = constant_term(tmp2008[i]) + constant_term(pn2z[i]) - (tmp2009[i]).coeffs[2:order + 1] .= zero((tmp2009[i]).coeffs[1]) - (pn2[i]).coeffs[1] = constant_term(newtonianCoeff[i]) * constant_term(tmp2009[i]) + (tmp1353[i]).coeffs[1] = constant_term(pn2x[i]) + constant_term(pn2y[i]) + (tmp1353[i]).coeffs[2:order + 1] .= zero((tmp1353[i]).coeffs[1]) + (tmp1354[i]).coeffs[1] = constant_term(tmp1353[i]) + constant_term(pn2z[i]) + (tmp1354[i]).coeffs[2:order + 1] .= zero((tmp1354[i]).coeffs[1]) + (pn2[i]).coeffs[1] = constant_term(newtonianCoeff[i]) * constant_term(tmp1354[i]) (pn2[i]).coeffs[2:order + 1] .= zero((pn2[i]).coeffs[1]) (newton_acc_X[i]).coeffs[1] = constant_term(X[i]) * constant_term(newtonianCoeff[i]) (newton_acc_X[i]).coeffs[2:order + 1] .= zero((newton_acc_X[i]).coeffs[1]) @@ -2427,81 +2431,81 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, (W_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(W[i]) (W_t_pn2[i]).coeffs[2:order + 1] .= zero((W_t_pn2[i]).coeffs[1]) if UJ_interaction[i] - (tmp2020[i]).coeffs[1] = -(constant_term(X[i])) - (tmp2020[i]).coeffs[2:order + 1] .= zero((tmp2020[i]).coeffs[1]) - (t31[i]).coeffs[1] = constant_term(tmp2020[i]) * constant_term(M_[1, 3, i]) + (tmp1365[i]).coeffs[1] = -(constant_term(X[i])) + (tmp1365[i]).coeffs[2:order + 1] .= zero((tmp1365[i]).coeffs[1]) + (t31[i]).coeffs[1] = constant_term(tmp1365[i]) * constant_term(M_[1, 3, i]) (t31[i]).coeffs[2:order + 1] .= zero((t31[i]).coeffs[1]) - (tmp2022[i]).coeffs[1] = -(constant_term(Y[i])) - (tmp2022[i]).coeffs[2:order + 1] .= zero((tmp2022[i]).coeffs[1]) - (t32[i]).coeffs[1] = constant_term(tmp2022[i]) * constant_term(M_[2, 3, i]) + (tmp1367[i]).coeffs[1] = -(constant_term(Y[i])) + (tmp1367[i]).coeffs[2:order + 1] .= zero((tmp1367[i]).coeffs[1]) + (t32[i]).coeffs[1] = constant_term(tmp1367[i]) * constant_term(M_[2, 3, i]) (t32[i]).coeffs[2:order + 1] .= zero((t32[i]).coeffs[1]) - (tmp2024[i]).coeffs[1] = -(constant_term(Z[i])) - (tmp2024[i]).coeffs[2:order + 1] .= zero((tmp2024[i]).coeffs[1]) - (t33[i]).coeffs[1] = constant_term(tmp2024[i]) * constant_term(M_[3, 3, i]) + (tmp1369[i]).coeffs[1] = -(constant_term(Z[i])) + (tmp1369[i]).coeffs[2:order + 1] .= zero((tmp1369[i]).coeffs[1]) + (t33[i]).coeffs[1] = constant_term(tmp1369[i]) * constant_term(M_[3, 3, i]) (t33[i]).coeffs[2:order + 1] .= zero((t33[i]).coeffs[1]) - (tmp2026[i]).coeffs[1] = constant_term(t31[i]) + constant_term(t32[i]) - (tmp2026[i]).coeffs[2:order + 1] .= zero((tmp2026[i]).coeffs[1]) - (r_sin_ϕ[i]).coeffs[1] = constant_term(tmp2026[i]) + constant_term(t33[i]) + (tmp1371[i]).coeffs[1] = constant_term(t31[i]) + constant_term(t32[i]) + (tmp1371[i]).coeffs[2:order + 1] .= zero((tmp1371[i]).coeffs[1]) + (r_sin_ϕ[i]).coeffs[1] = constant_term(tmp1371[i]) + constant_term(t33[i]) (r_sin_ϕ[i]).coeffs[2:order + 1] .= zero((r_sin_ϕ[i]).coeffs[1]) (sin_ϕ[i]).coeffs[1] = constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]) (sin_ϕ[i]).coeffs[2:order + 1] .= zero((sin_ϕ[i]).coeffs[1]) (ϕ[i]).coeffs[1] = asin(constant_term(sin_ϕ[i])) (ϕ[i]).coeffs[2:order + 1] .= zero((ϕ[i]).coeffs[1]) - (tmp2183[i]).coeffs[1] = sqrt(1 - constant_term(sin_ϕ[i]) ^ 2) - (tmp2183[i]).coeffs[2:order + 1] .= zero((tmp2183[i]).coeffs[1]) + (tmp1528[i]).coeffs[1] = sqrt(1 - constant_term(sin_ϕ[i]) ^ 2) + (tmp1528[i]).coeffs[2:order + 1] .= zero((tmp1528[i]).coeffs[1]) (cos_ϕ[i]).coeffs[1] = cos(constant_term(ϕ[i])) (cos_ϕ[i]).coeffs[2:order + 1] .= zero((cos_ϕ[i]).coeffs[1]) - (tmp2184[i]).coeffs[1] = sin(constant_term(ϕ[i])) - (tmp2184[i]).coeffs[2:order + 1] .= zero((tmp2184[i]).coeffs[1]) + (tmp1529[i]).coeffs[1] = sin(constant_term(ϕ[i])) + (tmp1529[i]).coeffs[2:order + 1] .= zero((tmp1529[i]).coeffs[1]) (sin2_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(2)) (sin2_ϕ[i]).coeffs[2:order + 1] .= zero((sin2_ϕ[i]).coeffs[1]) (sin3_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(3)) (sin3_ϕ[i]).coeffs[2:order + 1] .= zero((sin3_ϕ[i]).coeffs[1]) - (tmp2036[i]).coeffs[1] = constant_term(1.5) * constant_term(sin2_ϕ[i]) - (tmp2036[i]).coeffs[2:order + 1] .= zero((tmp2036[i]).coeffs[1]) - (P_2_sin_ϕ[i]).coeffs[1] = constant_term(tmp2036[i]) - constant_term(0.5) + (tmp1381[i]).coeffs[1] = constant_term(1.5) * constant_term(sin2_ϕ[i]) + (tmp1381[i]).coeffs[2:order + 1] .= zero((tmp1381[i]).coeffs[1]) + (P_2_sin_ϕ[i]).coeffs[1] = constant_term(tmp1381[i]) - constant_term(0.5) (P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_2_sin_ϕ[i]).coeffs[1]) (∂P_2_sin_ϕ[i]).coeffs[1] = constant_term(3) * constant_term(sin_ϕ[i]) (∂P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_2_sin_ϕ[i]).coeffs[1]) - (tmp2042[i]).coeffs[1] = constant_term(-1.5) * constant_term(sin_ϕ[i]) - (tmp2042[i]).coeffs[2:order + 1] .= zero((tmp2042[i]).coeffs[1]) - (tmp2044[i]).coeffs[1] = constant_term(2.5) * constant_term(sin3_ϕ[i]) - (tmp2044[i]).coeffs[2:order + 1] .= zero((tmp2044[i]).coeffs[1]) - (P_3_sin_ϕ[i]).coeffs[1] = constant_term(tmp2042[i]) + constant_term(tmp2044[i]) + (tmp1387[i]).coeffs[1] = constant_term(-1.5) * constant_term(sin_ϕ[i]) + (tmp1387[i]).coeffs[2:order + 1] .= zero((tmp1387[i]).coeffs[1]) + (tmp1389[i]).coeffs[1] = constant_term(2.5) * constant_term(sin3_ϕ[i]) + (tmp1389[i]).coeffs[2:order + 1] .= zero((tmp1389[i]).coeffs[1]) + (P_3_sin_ϕ[i]).coeffs[1] = constant_term(tmp1387[i]) + constant_term(tmp1389[i]) (P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_3_sin_ϕ[i]).coeffs[1]) - (tmp2048[i]).coeffs[1] = constant_term(7.5) * constant_term(sin2_ϕ[i]) - (tmp2048[i]).coeffs[2:order + 1] .= zero((tmp2048[i]).coeffs[1]) - (∂P_3_sin_ϕ[i]).coeffs[1] = constant_term(-1.5) + constant_term(tmp2048[i]) + (tmp1393[i]).coeffs[1] = constant_term(7.5) * constant_term(sin2_ϕ[i]) + (tmp1393[i]).coeffs[2:order + 1] .= zero((tmp1393[i]).coeffs[1]) + (∂P_3_sin_ϕ[i]).coeffs[1] = constant_term(-1.5) + constant_term(tmp1393[i]) (∂P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_3_sin_ϕ[i]).coeffs[1]) - (tmp2051[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(2)) - (tmp2051[i]).coeffs[2:order + 1] .= zero((tmp2051[i]).coeffs[1]) - (tmp2052[i]).coeffs[1] = constant_term(Λ2[i]) / constant_term(tmp2051[i]) - (tmp2052[i]).coeffs[2:order + 1] .= zero((tmp2052[i]).coeffs[1]) - (Λ2j_div_r4[i]).coeffs[1] = -(constant_term(tmp2052[i])) + (tmp1396[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(2)) + (tmp1396[i]).coeffs[2:order + 1] .= zero((tmp1396[i]).coeffs[1]) + (tmp1397[i]).coeffs[1] = constant_term(Λ2[i]) / constant_term(tmp1396[i]) + (tmp1397[i]).coeffs[2:order + 1] .= zero((tmp1397[i]).coeffs[1]) + (Λ2j_div_r4[i]).coeffs[1] = -(constant_term(tmp1397[i])) (Λ2j_div_r4[i]).coeffs[2:order + 1] .= zero((Λ2j_div_r4[i]).coeffs[1]) - (tmp2055[i]).coeffs[1] = constant_term(r_p1d2[i]) ^ float(constant_term(5)) - (tmp2055[i]).coeffs[2:order + 1] .= zero((tmp2055[i]).coeffs[1]) - (tmp2056[i]).coeffs[1] = constant_term(Λ3[i]) / constant_term(tmp2055[i]) - (tmp2056[i]).coeffs[2:order + 1] .= zero((tmp2056[i]).coeffs[1]) - (Λ3j_div_r5[i]).coeffs[1] = -(constant_term(tmp2056[i])) + (tmp1400[i]).coeffs[1] = constant_term(r_p1d2[i]) ^ float(constant_term(5)) + (tmp1400[i]).coeffs[2:order + 1] .= zero((tmp1400[i]).coeffs[1]) + (tmp1401[i]).coeffs[1] = constant_term(Λ3[i]) / constant_term(tmp1400[i]) + (tmp1401[i]).coeffs[2:order + 1] .= zero((tmp1401[i]).coeffs[1]) + (Λ3j_div_r5[i]).coeffs[1] = -(constant_term(tmp1401[i])) (Λ3j_div_r5[i]).coeffs[2:order + 1] .= zero((Λ3j_div_r5[i]).coeffs[1]) - (tmp2058[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) - (tmp2058[i]).coeffs[2:order + 1] .= zero((tmp2058[i]).coeffs[1]) - (m_c_ϕ_∂P_2[i]).coeffs[1] = constant_term(tmp2058[i]) * constant_term(∂P_2_sin_ϕ[i]) + (tmp1403[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) + (tmp1403[i]).coeffs[2:order + 1] .= zero((tmp1403[i]).coeffs[1]) + (m_c_ϕ_∂P_2[i]).coeffs[1] = constant_term(tmp1403[i]) * constant_term(∂P_2_sin_ϕ[i]) (m_c_ϕ_∂P_2[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_2[i]).coeffs[1]) - (tmp2060[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) - (tmp2060[i]).coeffs[2:order + 1] .= zero((tmp2060[i]).coeffs[1]) - (m_c_ϕ_∂P_3[i]).coeffs[1] = constant_term(tmp2060[i]) * constant_term(∂P_3_sin_ϕ[i]) + (tmp1405[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) + (tmp1405[i]).coeffs[2:order + 1] .= zero((tmp1405[i]).coeffs[1]) + (m_c_ϕ_∂P_3[i]).coeffs[1] = constant_term(tmp1405[i]) * constant_term(∂P_3_sin_ϕ[i]) (m_c_ϕ_∂P_3[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_3[i]).coeffs[1]) - (tmp2063[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(3) - (tmp2063[i]).coeffs[2:order + 1] .= zero((tmp2063[i]).coeffs[1]) - (F_J2_ξ[i]).coeffs[1] = constant_term(tmp2063[i]) * constant_term(P_2_sin_ϕ[i]) + (tmp1408[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(3) + (tmp1408[i]).coeffs[2:order + 1] .= zero((tmp1408[i]).coeffs[1]) + (F_J2_ξ[i]).coeffs[1] = constant_term(tmp1408[i]) * constant_term(P_2_sin_ϕ[i]) (F_J2_ξ[i]).coeffs[2:order + 1] .= zero((F_J2_ξ[i]).coeffs[1]) (F_J2_ζ[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]) (F_J2_ζ[i]).coeffs[2:order + 1] .= zero((F_J2_ζ[i]).coeffs[1]) - (tmp2067[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(4) - (tmp2067[i]).coeffs[2:order + 1] .= zero((tmp2067[i]).coeffs[1]) - (F_J3_ξ[i]).coeffs[1] = constant_term(tmp2067[i]) * constant_term(P_3_sin_ϕ[i]) + (tmp1412[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(4) + (tmp1412[i]).coeffs[2:order + 1] .= zero((tmp1412[i]).coeffs[1]) + (F_J3_ξ[i]).coeffs[1] = constant_term(tmp1412[i]) * constant_term(P_3_sin_ϕ[i]) (F_J3_ξ[i]).coeffs[2:order + 1] .= zero((F_J3_ξ[i]).coeffs[1]) (F_J3_ζ[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]) (F_J3_ζ[i]).coeffs[2:order + 1] .= zero((F_J3_ζ[i]).coeffs[1]) @@ -2509,17 +2513,17 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, (F_J_ξ[i]).coeffs[2:order + 1] .= zero((F_J_ξ[i]).coeffs[1]) (F_J_ζ[i]).coeffs[1] = identity(constant_term(F_J2_ζ[i])) (F_J_ζ[i]).coeffs[2:order + 1] .= zero((F_J_ζ[i]).coeffs[1]) - (tmp2070[i]).coeffs[1] = -(constant_term(X[i])) - (tmp2070[i]).coeffs[2:order + 1] .= zero((tmp2070[i]).coeffs[1]) - (ξx[i]).coeffs[1] = constant_term(tmp2070[i]) / constant_term(r_p1d2[i]) + (tmp1415[i]).coeffs[1] = -(constant_term(X[i])) + (tmp1415[i]).coeffs[2:order + 1] .= zero((tmp1415[i]).coeffs[1]) + (ξx[i]).coeffs[1] = constant_term(tmp1415[i]) / constant_term(r_p1d2[i]) (ξx[i]).coeffs[2:order + 1] .= zero((ξx[i]).coeffs[1]) - (tmp2072[i]).coeffs[1] = -(constant_term(Y[i])) - (tmp2072[i]).coeffs[2:order + 1] .= zero((tmp2072[i]).coeffs[1]) - (ξy[i]).coeffs[1] = constant_term(tmp2072[i]) / constant_term(r_p1d2[i]) + (tmp1417[i]).coeffs[1] = -(constant_term(Y[i])) + (tmp1417[i]).coeffs[2:order + 1] .= zero((tmp1417[i]).coeffs[1]) + (ξy[i]).coeffs[1] = constant_term(tmp1417[i]) / constant_term(r_p1d2[i]) (ξy[i]).coeffs[2:order + 1] .= zero((ξy[i]).coeffs[1]) - (tmp2074[i]).coeffs[1] = -(constant_term(Z[i])) - (tmp2074[i]).coeffs[2:order + 1] .= zero((tmp2074[i]).coeffs[1]) - (ξz[i]).coeffs[1] = constant_term(tmp2074[i]) / constant_term(r_p1d2[i]) + (tmp1419[i]).coeffs[1] = -(constant_term(Z[i])) + (tmp1419[i]).coeffs[2:order + 1] .= zero((tmp1419[i]).coeffs[1]) + (ξz[i]).coeffs[1] = constant_term(tmp1419[i]) / constant_term(r_p1d2[i]) (ξz[i]).coeffs[2:order + 1] .= zero((ξz[i]).coeffs[1]) (ηx1[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξz[i]) (ηx1[i]).coeffs[2:order + 1] .= zero((ηx1[i]).coeffs[1]) @@ -2576,26 +2580,26 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, (F_J2_z[i]).coeffs[1] = constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]) (F_J2_z[i]).coeffs[2:order + 1] .= zero((F_J2_z[i]).coeffs[1]) end - (tmp2104[i]).coeffs[1] = constant_term(ui[i]) ^ float(constant_term(2)) - (tmp2104[i]).coeffs[2:order + 1] .= zero((tmp2104[i]).coeffs[1]) - (tmp2106[i]).coeffs[1] = constant_term(vi[i]) ^ float(constant_term(2)) - (tmp2106[i]).coeffs[2:order + 1] .= zero((tmp2106[i]).coeffs[1]) - (tmp2107[i]).coeffs[1] = constant_term(tmp2104[i]) + constant_term(tmp2106[i]) - (tmp2107[i]).coeffs[2:order + 1] .= zero((tmp2107[i]).coeffs[1]) - (tmp2109[i]).coeffs[1] = constant_term(wi[i]) ^ float(constant_term(2)) - (tmp2109[i]).coeffs[2:order + 1] .= zero((tmp2109[i]).coeffs[1]) - (v2[i]).coeffs[1] = constant_term(tmp2107[i]) + constant_term(tmp2109[i]) + (tmp1449[i]).coeffs[1] = constant_term(ui[i]) ^ float(constant_term(2)) + (tmp1449[i]).coeffs[2:order + 1] .= zero((tmp1449[i]).coeffs[1]) + (tmp1451[i]).coeffs[1] = constant_term(vi[i]) ^ float(constant_term(2)) + (tmp1451[i]).coeffs[2:order + 1] .= zero((tmp1451[i]).coeffs[1]) + (tmp1452[i]).coeffs[1] = constant_term(tmp1449[i]) + constant_term(tmp1451[i]) + (tmp1452[i]).coeffs[2:order + 1] .= zero((tmp1452[i]).coeffs[1]) + (tmp1454[i]).coeffs[1] = constant_term(wi[i]) ^ float(constant_term(2)) + (tmp1454[i]).coeffs[2:order + 1] .= zero((tmp1454[i]).coeffs[1]) + (v2[i]).coeffs[1] = constant_term(tmp1452[i]) + constant_term(tmp1454[i]) (v2[i]).coeffs[2:order + 1] .= zero((v2[i]).coeffs[1]) end - tmp2112.coeffs[1] = constant_term(q[4]) ^ float(constant_term(2)) - tmp2112.coeffs[2:order + 1] .= zero(tmp2112.coeffs[1]) - tmp2114.coeffs[1] = constant_term(q[5]) ^ float(constant_term(2)) - tmp2114.coeffs[2:order + 1] .= zero(tmp2114.coeffs[1]) - tmp2115.coeffs[1] = constant_term(tmp2112) + constant_term(tmp2114) - tmp2115.coeffs[2:order + 1] .= zero(tmp2115.coeffs[1]) - tmp2117.coeffs[1] = constant_term(q[6]) ^ float(constant_term(2)) - tmp2117.coeffs[2:order + 1] .= zero(tmp2117.coeffs[1]) - (v2[N]).coeffs[1] = constant_term(tmp2115) + constant_term(tmp2117) + tmp1457.coeffs[1] = constant_term(q[4]) ^ float(constant_term(2)) + tmp1457.coeffs[2:order + 1] .= zero(tmp1457.coeffs[1]) + tmp1459.coeffs[1] = constant_term(q[5]) ^ float(constant_term(2)) + tmp1459.coeffs[2:order + 1] .= zero(tmp1459.coeffs[1]) + tmp1460.coeffs[1] = constant_term(tmp1457) + constant_term(tmp1459) + tmp1460.coeffs[2:order + 1] .= zero(tmp1460.coeffs[1]) + tmp1462.coeffs[1] = constant_term(q[6]) ^ float(constant_term(2)) + tmp1462.coeffs[2:order + 1] .= zero(tmp1462.coeffs[1]) + (v2[N]).coeffs[1] = constant_term(tmp1460) + constant_term(tmp1462) (v2[N]).coeffs[2:order + 1] .= zero((v2[N]).coeffs[1]) for i = 1:Nm1 (temp_004[i]).coeffs[1] = constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]) @@ -2603,21 +2607,21 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(temp_004[i])) (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) if UJ_interaction[i] - (tmp2120[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_x[i]) - (tmp2120[i]).coeffs[2:order + 1] .= zero((tmp2120[i]).coeffs[1]) - (temp_accX_i[i]).coeffs[1] = constant_term(accX) - constant_term(tmp2120[i]) + (tmp1465[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_x[i]) + (tmp1465[i]).coeffs[2:order + 1] .= zero((tmp1465[i]).coeffs[1]) + (temp_accX_i[i]).coeffs[1] = constant_term(accX) - constant_term(tmp1465[i]) (temp_accX_i[i]).coeffs[2:order + 1] .= zero((temp_accX_i[i]).coeffs[1]) accX.coeffs[1] = identity(constant_term(temp_accX_i[i])) accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) - (tmp2122[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_y[i]) - (tmp2122[i]).coeffs[2:order + 1] .= zero((tmp2122[i]).coeffs[1]) - (temp_accY_i[i]).coeffs[1] = constant_term(accY) - constant_term(tmp2122[i]) + (tmp1467[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_y[i]) + (tmp1467[i]).coeffs[2:order + 1] .= zero((tmp1467[i]).coeffs[1]) + (temp_accY_i[i]).coeffs[1] = constant_term(accY) - constant_term(tmp1467[i]) (temp_accY_i[i]).coeffs[2:order + 1] .= zero((temp_accY_i[i]).coeffs[1]) accY.coeffs[1] = identity(constant_term(temp_accY_i[i])) accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) - (tmp2124[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_z[i]) - (tmp2124[i]).coeffs[2:order + 1] .= zero((tmp2124[i]).coeffs[1]) - (temp_accZ_i[i]).coeffs[1] = constant_term(accZ) - constant_term(tmp2124[i]) + (tmp1469[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_z[i]) + (tmp1469[i]).coeffs[2:order + 1] .= zero((tmp1469[i]).coeffs[1]) + (temp_accZ_i[i]).coeffs[1] = constant_term(accZ) - constant_term(tmp1469[i]) (temp_accZ_i[i]).coeffs[2:order + 1] .= zero((temp_accZ_i[i]).coeffs[1]) accZ.coeffs[1] = identity(constant_term(temp_accZ_i[i])) accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) @@ -2625,16 +2629,16 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, end (_4ϕj[N]).coeffs[1] = constant_term(4) * constant_term(newtonianNb_Potential[N]) (_4ϕj[N]).coeffs[2:order + 1] .= zero((_4ϕj[N]).coeffs[1]) - #= C:\Users\luisi\.julia\dev\NEOs.jl\ex.jl:447 =# Threads.@threads for i = 1:10 + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 (ϕi_plus_4ϕj[i]).coeffs[1] = constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]) (ϕi_plus_4ϕj[i]).coeffs[2:order + 1] .= zero((ϕi_plus_4ϕj[i]).coeffs[1]) - (tmp2130[i]).coeffs[1] = constant_term(2) * constant_term(v2[i]) - (tmp2130[i]).coeffs[2:order + 1] .= zero((tmp2130[i]).coeffs[1]) - (tmp2132[i]).coeffs[1] = constant_term(4) * constant_term(vi_dot_vj[i]) - (tmp2132[i]).coeffs[2:order + 1] .= zero((tmp2132[i]).coeffs[1]) - (tmp2133[i]).coeffs[1] = constant_term(tmp2130[i]) - constant_term(tmp2132[i]) - (tmp2133[i]).coeffs[2:order + 1] .= zero((tmp2133[i]).coeffs[1]) - (sj2_plus_2si2_minus_4vivj[i]).coeffs[1] = constant_term(tmp2133[i]) + constant_term(v2[N]) + (tmp1475[i]).coeffs[1] = constant_term(2) * constant_term(v2[i]) + (tmp1475[i]).coeffs[2:order + 1] .= zero((tmp1475[i]).coeffs[1]) + (tmp1477[i]).coeffs[1] = constant_term(4) * constant_term(vi_dot_vj[i]) + (tmp1477[i]).coeffs[2:order + 1] .= zero((tmp1477[i]).coeffs[1]) + (tmp1478[i]).coeffs[1] = constant_term(tmp1475[i]) - constant_term(tmp1477[i]) + (tmp1478[i]).coeffs[2:order + 1] .= zero((tmp1478[i]).coeffs[1]) + (sj2_plus_2si2_minus_4vivj[i]).coeffs[1] = constant_term(tmp1478[i]) + constant_term(v2[N]) (sj2_plus_2si2_minus_4vivj[i]).coeffs[2:order + 1] .= zero((sj2_plus_2si2_minus_4vivj[i]).coeffs[1]) (ϕs_and_vs[i]).coeffs[1] = constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]) (ϕs_and_vs[i]).coeffs[2:order + 1] .= zero((ϕs_and_vs[i]).coeffs[1]) @@ -2644,17 +2648,17 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, (Yij_t_Vi[i]).coeffs[2:order + 1] .= zero((Yij_t_Vi[i]).coeffs[1]) (Zij_t_Wi[i]).coeffs[1] = constant_term(Z[i]) * constant_term(wi[i]) (Zij_t_Wi[i]).coeffs[2:order + 1] .= zero((Zij_t_Wi[i]).coeffs[1]) - (tmp2139[i]).coeffs[1] = constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]) - (tmp2139[i]).coeffs[2:order + 1] .= zero((tmp2139[i]).coeffs[1]) - (Rij_dot_Vi[i]).coeffs[1] = constant_term(tmp2139[i]) + constant_term(Zij_t_Wi[i]) + (tmp1484[i]).coeffs[1] = constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]) + (tmp1484[i]).coeffs[2:order + 1] .= zero((tmp1484[i]).coeffs[1]) + (Rij_dot_Vi[i]).coeffs[1] = constant_term(tmp1484[i]) + constant_term(Zij_t_Wi[i]) (Rij_dot_Vi[i]).coeffs[2:order + 1] .= zero((Rij_dot_Vi[i]).coeffs[1]) - (tmp2142[i]).coeffs[1] = constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)) - (tmp2142[i]).coeffs[2:order + 1] .= zero((tmp2142[i]).coeffs[1]) - (pn1t7[i]).coeffs[1] = constant_term(tmp2142[i]) / constant_term(r_p2[i]) + (tmp1487[i]).coeffs[1] = constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)) + (tmp1487[i]).coeffs[2:order + 1] .= zero((tmp1487[i]).coeffs[1]) + (pn1t7[i]).coeffs[1] = constant_term(tmp1487[i]) / constant_term(r_p2[i]) (pn1t7[i]).coeffs[2:order + 1] .= zero((pn1t7[i]).coeffs[1]) - (tmp2145[i]).coeffs[1] = constant_term(1.5) * constant_term(pn1t7[i]) - (tmp2145[i]).coeffs[2:order + 1] .= zero((tmp2145[i]).coeffs[1]) - (pn1t2_7[i]).coeffs[1] = constant_term(ϕs_and_vs[i]) - constant_term(tmp2145[i]) + (tmp1490[i]).coeffs[1] = constant_term(1.5) * constant_term(pn1t7[i]) + (tmp1490[i]).coeffs[2:order + 1] .= zero((tmp1490[i]).coeffs[1]) + (pn1t2_7[i]).coeffs[1] = constant_term(ϕs_and_vs[i]) - constant_term(tmp1490[i]) (pn1t2_7[i]).coeffs[2:order + 1] .= zero((pn1t2_7[i]).coeffs[1]) (pn1t1_7[i]).coeffs[1] = constant_term(c_p2) + constant_term(pn1t2_7[i]) (pn1t1_7[i]).coeffs[2:order + 1] .= zero((pn1t1_7[i]).coeffs[1]) @@ -2664,13 +2668,13 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, (pNY_t_Y[i]).coeffs[2:order + 1] .= zero((pNY_t_Y[i]).coeffs[1]) (pNZ_t_Z[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(Z[i]) (pNZ_t_Z[i]).coeffs[2:order + 1] .= zero((pNZ_t_Z[i]).coeffs[1]) - (tmp2152[i]).coeffs[1] = constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]) - (tmp2152[i]).coeffs[2:order + 1] .= zero((tmp2152[i]).coeffs[1]) - (tmp2153[i]).coeffs[1] = constant_term(tmp2152[i]) + constant_term(pNZ_t_Z[i]) - (tmp2153[i]).coeffs[2:order + 1] .= zero((tmp2153[i]).coeffs[1]) - (tmp2154[i]).coeffs[1] = constant_term(0.5) * constant_term(tmp2153[i]) - (tmp2154[i]).coeffs[2:order + 1] .= zero((tmp2154[i]).coeffs[1]) - (pn1[i]).coeffs[1] = constant_term(pn1t1_7[i]) + constant_term(tmp2154[i]) + (tmp1497[i]).coeffs[1] = constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]) + (tmp1497[i]).coeffs[2:order + 1] .= zero((tmp1497[i]).coeffs[1]) + (tmp1498[i]).coeffs[1] = constant_term(tmp1497[i]) + constant_term(pNZ_t_Z[i]) + (tmp1498[i]).coeffs[2:order + 1] .= zero((tmp1498[i]).coeffs[1]) + (tmp1499[i]).coeffs[1] = constant_term(0.5) * constant_term(tmp1498[i]) + (tmp1499[i]).coeffs[2:order + 1] .= zero((tmp1499[i]).coeffs[1]) + (pn1[i]).coeffs[1] = constant_term(pn1t1_7[i]) + constant_term(tmp1499[i]) (pn1[i]).coeffs[2:order + 1] .= zero((pn1[i]).coeffs[1]) (X_t_pn1[i]).coeffs[1] = constant_term(newton_acc_X[i]) * constant_term(pn1[i]) (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) @@ -2686,32 +2690,32 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, (pNZ_t_pn3[i]).coeffs[2:order + 1] .= zero((pNZ_t_pn3[i]).coeffs[1]) end for i = 1:10 - (tmp2162[i]).coeffs[1] = constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]) - (tmp2162[i]).coeffs[2:order + 1] .= zero((tmp2162[i]).coeffs[1]) - (termpnx[i]).coeffs[1] = constant_term(X_t_pn1[i]) + constant_term(tmp2162[i]) + (tmp1507[i]).coeffs[1] = constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]) + (tmp1507[i]).coeffs[2:order + 1] .= zero((tmp1507[i]).coeffs[1]) + (termpnx[i]).coeffs[1] = constant_term(X_t_pn1[i]) + constant_term(tmp1507[i]) (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) - (tmp2165[i]).coeffs[1] = constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]) - (tmp2165[i]).coeffs[2:order + 1] .= zero((tmp2165[i]).coeffs[1]) - (termpny[i]).coeffs[1] = constant_term(Y_t_pn1[i]) + constant_term(tmp2165[i]) + (tmp1510[i]).coeffs[1] = constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]) + (tmp1510[i]).coeffs[2:order + 1] .= zero((tmp1510[i]).coeffs[1]) + (termpny[i]).coeffs[1] = constant_term(Y_t_pn1[i]) + constant_term(tmp1510[i]) (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) pntempY.coeffs[1] = identity(constant_term(sumpny[i])) pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) - (tmp2168[i]).coeffs[1] = constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]) - (tmp2168[i]).coeffs[2:order + 1] .= zero((tmp2168[i]).coeffs[1]) - (termpnz[i]).coeffs[1] = constant_term(Z_t_pn1[i]) + constant_term(tmp2168[i]) + (tmp1513[i]).coeffs[1] = constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]) + (tmp1513[i]).coeffs[2:order + 1] .= zero((tmp1513[i]).coeffs[1]) + (termpnz[i]).coeffs[1] = constant_term(Z_t_pn1[i]) + constant_term(tmp1513[i]) (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) end - #= C:\Users\luisi\.julia\dev\NEOs.jl\ex.jl:500 =# Threads.@threads for i = 11:Nm1 + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 (X_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_X[i]) (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) (Y_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Y[i]) @@ -2766,7 +2770,7 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorSeries.identity!(dq[2], q[5], ord) TaylorSeries.identity!(dq[3], q[6], ord) TaylorSeries.identity!(newtonianNb_Potential[N], zero_q_1, ord) - #= C:\Users\luisi\.julia\dev\NEOs.jl\ex.jl:245 =# Threads.@threads for i = 1:Nm1 + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 TaylorSeries.identity!(ui[i], ss16asteph_t[3 * ((N - 1) + i) - 2], ord) TaylorSeries.identity!(vi[i], ss16asteph_t[3 * ((N - 1) + i) - 1], ord) TaylorSeries.identity!(wi[i], ss16asteph_t[3 * ((N - 1) + i)], ord) @@ -2776,35 +2780,35 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorSeries.subst!(U[i], ui[i], dq[1], ord) TaylorSeries.subst!(V[i], vi[i], dq[2], ord) TaylorSeries.subst!(W[i], wi[i], dq[3], ord) - TaylorSeries.mul!(tmp1972[1], 4, dq[1], ord) - TaylorSeries.mul!(tmp1974[i], 3, ui[i], ord) - TaylorSeries.subst!(_4U_m_3X[i], tmp1972[1], tmp1974[i], ord) - TaylorSeries.mul!(tmp1977[2], 4, dq[2], ord) - TaylorSeries.mul!(tmp1979[i], 3, vi[i], ord) - TaylorSeries.subst!(_4V_m_3Y[i], tmp1977[2], tmp1979[i], ord) - TaylorSeries.mul!(tmp1982[3], 4, dq[3], ord) - TaylorSeries.mul!(tmp1984[i], 3, wi[i], ord) - TaylorSeries.subst!(_4W_m_3Z[i], tmp1982[3], tmp1984[i], ord) + TaylorSeries.mul!(tmp1317[1], 4, dq[1], ord) + TaylorSeries.mul!(tmp1319[i], 3, ui[i], ord) + TaylorSeries.subst!(_4U_m_3X[i], tmp1317[1], tmp1319[i], ord) + TaylorSeries.mul!(tmp1322[2], 4, dq[2], ord) + TaylorSeries.mul!(tmp1324[i], 3, vi[i], ord) + TaylorSeries.subst!(_4V_m_3Y[i], tmp1322[2], tmp1324[i], ord) + TaylorSeries.mul!(tmp1327[3], 4, dq[3], ord) + TaylorSeries.mul!(tmp1329[i], 3, wi[i], ord) + TaylorSeries.subst!(_4W_m_3Z[i], tmp1327[3], tmp1329[i], ord) TaylorSeries.mul!(pn2x[i], X[i], _4U_m_3X[i], ord) TaylorSeries.mul!(pn2y[i], Y[i], _4V_m_3Y[i], ord) TaylorSeries.mul!(pn2z[i], Z[i], _4W_m_3Z[i], ord) TaylorSeries.mul!(UU[i], ui[i], dq[1], ord) TaylorSeries.mul!(VV[i], vi[i], dq[2], ord) TaylorSeries.mul!(WW[i], wi[i], dq[3], ord) - TaylorSeries.add!(tmp1992[i], UU[i], VV[i], ord) - TaylorSeries.add!(vi_dot_vj[i], tmp1992[i], WW[i], ord) - TaylorSeries.pow!(tmp1995[i], X[i], 2, ord) - TaylorSeries.pow!(tmp1997[i], Y[i], 2, ord) - TaylorSeries.add!(tmp1998[i], tmp1995[i], tmp1997[i], ord) - TaylorSeries.pow!(tmp2000[i], Z[i], 2, ord) - TaylorSeries.add!(r_p2[i], tmp1998[i], tmp2000[i], ord) + TaylorSeries.add!(tmp1337[i], UU[i], VV[i], ord) + TaylorSeries.add!(vi_dot_vj[i], tmp1337[i], WW[i], ord) + TaylorSeries.pow!(tmp1340[i], X[i], 2, ord) + TaylorSeries.pow!(tmp1342[i], Y[i], 2, ord) + TaylorSeries.add!(tmp1343[i], tmp1340[i], tmp1342[i], ord) + TaylorSeries.pow!(tmp1345[i], Z[i], 2, ord) + TaylorSeries.add!(r_p2[i], tmp1343[i], tmp1345[i], ord) TaylorSeries.sqrt!(r_p1d2[i], r_p2[i], ord) TaylorSeries.pow!(r_p3d2[i], r_p2[i], 1.5, ord) TaylorSeries.pow!(r_p7d2[i], r_p2[i], 3.5, ord) TaylorSeries.div!(newtonianCoeff[i], μ[i], r_p3d2[i], ord) - TaylorSeries.add!(tmp2008[i], pn2x[i], pn2y[i], ord) - TaylorSeries.add!(tmp2009[i], tmp2008[i], pn2z[i], ord) - TaylorSeries.mul!(pn2[i], newtonianCoeff[i], tmp2009[i], ord) + TaylorSeries.add!(tmp1353[i], pn2x[i], pn2y[i], ord) + TaylorSeries.add!(tmp1354[i], tmp1353[i], pn2z[i], ord) + TaylorSeries.mul!(pn2[i], newtonianCoeff[i], tmp1354[i], ord) TaylorSeries.mul!(newton_acc_X[i], X[i], newtonianCoeff[i], ord) TaylorSeries.mul!(newton_acc_Y[i], Y[i], newtonianCoeff[i], ord) TaylorSeries.mul!(newton_acc_Z[i], Z[i], newtonianCoeff[i], ord) @@ -2814,51 +2818,51 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorSeries.mul!(V_t_pn2[i], pn2[i], V[i], ord) TaylorSeries.mul!(W_t_pn2[i], pn2[i], W[i], ord) if UJ_interaction[i] - TaylorSeries.subst!(tmp2020[i], X[i], ord) - TaylorSeries.mul!(t31[i], tmp2020[i], M_[1, 3, i], ord) - TaylorSeries.subst!(tmp2022[i], Y[i], ord) - TaylorSeries.mul!(t32[i], tmp2022[i], M_[2, 3, i], ord) - TaylorSeries.subst!(tmp2024[i], Z[i], ord) - TaylorSeries.mul!(t33[i], tmp2024[i], M_[3, 3, i], ord) - TaylorSeries.add!(tmp2026[i], t31[i], t32[i], ord) - TaylorSeries.add!(r_sin_ϕ[i], tmp2026[i], t33[i], ord) + TaylorSeries.subst!(tmp1365[i], X[i], ord) + TaylorSeries.mul!(t31[i], tmp1365[i], M_[1, 3, i], ord) + TaylorSeries.subst!(tmp1367[i], Y[i], ord) + TaylorSeries.mul!(t32[i], tmp1367[i], M_[2, 3, i], ord) + TaylorSeries.subst!(tmp1369[i], Z[i], ord) + TaylorSeries.mul!(t33[i], tmp1369[i], M_[3, 3, i], ord) + TaylorSeries.add!(tmp1371[i], t31[i], t32[i], ord) + TaylorSeries.add!(r_sin_ϕ[i], tmp1371[i], t33[i], ord) TaylorSeries.div!(sin_ϕ[i], r_sin_ϕ[i], r_p1d2[i], ord) - TaylorSeries.asin!(ϕ[i], sin_ϕ[i], tmp2183[i], ord) - TaylorSeries.sincos!(tmp2184[i], cos_ϕ[i], ϕ[i], ord) + TaylorSeries.asin!(ϕ[i], sin_ϕ[i], tmp1528[i], ord) + TaylorSeries.sincos!(tmp1529[i], cos_ϕ[i], ϕ[i], ord) TaylorSeries.pow!(sin2_ϕ[i], sin_ϕ[i], 2, ord) TaylorSeries.pow!(sin3_ϕ[i], sin_ϕ[i], 3, ord) - TaylorSeries.mul!(tmp2036[i], 1.5, sin2_ϕ[i], ord) - TaylorSeries.subst!(P_2_sin_ϕ[i], tmp2036[i], 0.5, ord) + TaylorSeries.mul!(tmp1381[i], 1.5, sin2_ϕ[i], ord) + TaylorSeries.subst!(P_2_sin_ϕ[i], tmp1381[i], 0.5, ord) TaylorSeries.mul!(∂P_2_sin_ϕ[i], 3, sin_ϕ[i], ord) - TaylorSeries.mul!(tmp2042[i], -1.5, sin_ϕ[i], ord) - TaylorSeries.mul!(tmp2044[i], 2.5, sin3_ϕ[i], ord) - TaylorSeries.add!(P_3_sin_ϕ[i], tmp2042[i], tmp2044[i], ord) - TaylorSeries.mul!(tmp2048[i], 7.5, sin2_ϕ[i], ord) - TaylorSeries.add!(∂P_3_sin_ϕ[i], -1.5, tmp2048[i], ord) - TaylorSeries.pow!(tmp2051[i], r_p2[i], 2, ord) - TaylorSeries.div!(tmp2052[i], Λ2[i], tmp2051[i], ord) - TaylorSeries.subst!(Λ2j_div_r4[i], tmp2052[i], ord) - TaylorSeries.pow!(tmp2055[i], r_p1d2[i], 5, ord) - TaylorSeries.div!(tmp2056[i], Λ3[i], tmp2055[i], ord) - TaylorSeries.subst!(Λ3j_div_r5[i], tmp2056[i], ord) - TaylorSeries.subst!(tmp2058[i], cos_ϕ[i], ord) - TaylorSeries.mul!(m_c_ϕ_∂P_2[i], tmp2058[i], ∂P_2_sin_ϕ[i], ord) - TaylorSeries.subst!(tmp2060[i], cos_ϕ[i], ord) - TaylorSeries.mul!(m_c_ϕ_∂P_3[i], tmp2060[i], ∂P_3_sin_ϕ[i], ord) - TaylorSeries.mul!(tmp2063[i], Λ2j_div_r4[i], 3, ord) - TaylorSeries.mul!(F_J2_ξ[i], tmp2063[i], P_2_sin_ϕ[i], ord) + TaylorSeries.mul!(tmp1387[i], -1.5, sin_ϕ[i], ord) + TaylorSeries.mul!(tmp1389[i], 2.5, sin3_ϕ[i], ord) + TaylorSeries.add!(P_3_sin_ϕ[i], tmp1387[i], tmp1389[i], ord) + TaylorSeries.mul!(tmp1393[i], 7.5, sin2_ϕ[i], ord) + TaylorSeries.add!(∂P_3_sin_ϕ[i], -1.5, tmp1393[i], ord) + TaylorSeries.pow!(tmp1396[i], r_p2[i], 2, ord) + TaylorSeries.div!(tmp1397[i], Λ2[i], tmp1396[i], ord) + TaylorSeries.subst!(Λ2j_div_r4[i], tmp1397[i], ord) + TaylorSeries.pow!(tmp1400[i], r_p1d2[i], 5, ord) + TaylorSeries.div!(tmp1401[i], Λ3[i], tmp1400[i], ord) + TaylorSeries.subst!(Λ3j_div_r5[i], tmp1401[i], ord) + TaylorSeries.subst!(tmp1403[i], cos_ϕ[i], ord) + TaylorSeries.mul!(m_c_ϕ_∂P_2[i], tmp1403[i], ∂P_2_sin_ϕ[i], ord) + TaylorSeries.subst!(tmp1405[i], cos_ϕ[i], ord) + TaylorSeries.mul!(m_c_ϕ_∂P_3[i], tmp1405[i], ∂P_3_sin_ϕ[i], ord) + TaylorSeries.mul!(tmp1408[i], Λ2j_div_r4[i], 3, ord) + TaylorSeries.mul!(F_J2_ξ[i], tmp1408[i], P_2_sin_ϕ[i], ord) TaylorSeries.mul!(F_J2_ζ[i], Λ2j_div_r4[i], m_c_ϕ_∂P_2[i], ord) - TaylorSeries.mul!(tmp2067[i], Λ3j_div_r5[i], 4, ord) - TaylorSeries.mul!(F_J3_ξ[i], tmp2067[i], P_3_sin_ϕ[i], ord) + TaylorSeries.mul!(tmp1412[i], Λ3j_div_r5[i], 4, ord) + TaylorSeries.mul!(F_J3_ξ[i], tmp1412[i], P_3_sin_ϕ[i], ord) TaylorSeries.mul!(F_J3_ζ[i], Λ3j_div_r5[i], m_c_ϕ_∂P_3[i], ord) TaylorSeries.identity!(F_J_ξ[i], F_J2_ξ[i], ord) TaylorSeries.identity!(F_J_ζ[i], F_J2_ζ[i], ord) - TaylorSeries.subst!(tmp2070[i], X[i], ord) - TaylorSeries.div!(ξx[i], tmp2070[i], r_p1d2[i], ord) - TaylorSeries.subst!(tmp2072[i], Y[i], ord) - TaylorSeries.div!(ξy[i], tmp2072[i], r_p1d2[i], ord) - TaylorSeries.subst!(tmp2074[i], Z[i], ord) - TaylorSeries.div!(ξz[i], tmp2074[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp1415[i], X[i], ord) + TaylorSeries.div!(ξx[i], tmp1415[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp1417[i], Y[i], ord) + TaylorSeries.div!(ξy[i], tmp1417[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp1419[i], Z[i], ord) + TaylorSeries.div!(ξz[i], tmp1419[i], r_p1d2[i], ord) TaylorSeries.mul!(ηx1[i], M_[2, 3, i], ξz[i], ord) TaylorSeries.mul!(ηy1[i], M_[3, 3, i], ξx[i], ord) TaylorSeries.mul!(ηz1[i], M_[1, 3, i], ξy[i], ord) @@ -2887,57 +2891,57 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorSeries.add!(F_J2_y[i], F_J2_y1[i], F_J2_y2[i], ord) TaylorSeries.add!(F_J2_z[i], F_J2_z1[i], F_J2_z2[i], ord) end - TaylorSeries.pow!(tmp2104[i], ui[i], 2, ord) - TaylorSeries.pow!(tmp2106[i], vi[i], 2, ord) - TaylorSeries.add!(tmp2107[i], tmp2104[i], tmp2106[i], ord) - TaylorSeries.pow!(tmp2109[i], wi[i], 2, ord) - TaylorSeries.add!(v2[i], tmp2107[i], tmp2109[i], ord) + TaylorSeries.pow!(tmp1449[i], ui[i], 2, ord) + TaylorSeries.pow!(tmp1451[i], vi[i], 2, ord) + TaylorSeries.add!(tmp1452[i], tmp1449[i], tmp1451[i], ord) + TaylorSeries.pow!(tmp1454[i], wi[i], 2, ord) + TaylorSeries.add!(v2[i], tmp1452[i], tmp1454[i], ord) end - TaylorSeries.pow!(tmp2112, q[4], 2, ord) - TaylorSeries.pow!(tmp2114, q[5], 2, ord) - TaylorSeries.add!(tmp2115, tmp2112, tmp2114, ord) - TaylorSeries.pow!(tmp2117, q[6], 2, ord) - TaylorSeries.add!(v2[N], tmp2115, tmp2117, ord) + TaylorSeries.pow!(tmp1457, q[4], 2, ord) + TaylorSeries.pow!(tmp1459, q[5], 2, ord) + TaylorSeries.add!(tmp1460, tmp1457, tmp1459, ord) + TaylorSeries.pow!(tmp1462, q[6], 2, ord) + TaylorSeries.add!(v2[N], tmp1460, tmp1462, ord) for i = 1:Nm1 TaylorSeries.add!(temp_004[i], newtonian1b_Potential[i], newtonianNb_Potential[N], ord) TaylorSeries.identity!(newtonianNb_Potential[N], temp_004[i], ord) if UJ_interaction[i] - TaylorSeries.mul!(tmp2120[i], μ[i], F_J2_x[i], ord) - TaylorSeries.subst!(temp_accX_i[i], accX, tmp2120[i], ord) + TaylorSeries.mul!(tmp1465[i], μ[i], F_J2_x[i], ord) + TaylorSeries.subst!(temp_accX_i[i], accX, tmp1465[i], ord) TaylorSeries.identity!(accX, temp_accX_i[i], ord) - TaylorSeries.mul!(tmp2122[i], μ[i], F_J2_y[i], ord) - TaylorSeries.subst!(temp_accY_i[i], accY, tmp2122[i], ord) + TaylorSeries.mul!(tmp1467[i], μ[i], F_J2_y[i], ord) + TaylorSeries.subst!(temp_accY_i[i], accY, tmp1467[i], ord) TaylorSeries.identity!(accY, temp_accY_i[i], ord) - TaylorSeries.mul!(tmp2124[i], μ[i], F_J2_z[i], ord) - TaylorSeries.subst!(temp_accZ_i[i], accZ, tmp2124[i], ord) + TaylorSeries.mul!(tmp1469[i], μ[i], F_J2_z[i], ord) + TaylorSeries.subst!(temp_accZ_i[i], accZ, tmp1469[i], ord) TaylorSeries.identity!(accZ, temp_accZ_i[i], ord) end end TaylorSeries.mul!(_4ϕj[N], 4, newtonianNb_Potential[N], ord) - #= C:\Users\luisi\.julia\dev\NEOs.jl\ex.jl:447 =# Threads.@threads for i = 1:10 + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 TaylorSeries.add!(ϕi_plus_4ϕj[i], newtonianNb_Potential_t[i], _4ϕj[N], ord) - TaylorSeries.mul!(tmp2130[i], 2, v2[i], ord) - TaylorSeries.mul!(tmp2132[i], 4, vi_dot_vj[i], ord) - TaylorSeries.subst!(tmp2133[i], tmp2130[i], tmp2132[i], ord) - TaylorSeries.add!(sj2_plus_2si2_minus_4vivj[i], tmp2133[i], v2[N], ord) + TaylorSeries.mul!(tmp1475[i], 2, v2[i], ord) + TaylorSeries.mul!(tmp1477[i], 4, vi_dot_vj[i], ord) + TaylorSeries.subst!(tmp1478[i], tmp1475[i], tmp1477[i], ord) + TaylorSeries.add!(sj2_plus_2si2_minus_4vivj[i], tmp1478[i], v2[N], ord) TaylorSeries.subst!(ϕs_and_vs[i], sj2_plus_2si2_minus_4vivj[i], ϕi_plus_4ϕj[i], ord) TaylorSeries.mul!(Xij_t_Ui[i], X[i], ui[i], ord) TaylorSeries.mul!(Yij_t_Vi[i], Y[i], vi[i], ord) TaylorSeries.mul!(Zij_t_Wi[i], Z[i], wi[i], ord) - TaylorSeries.add!(tmp2139[i], Xij_t_Ui[i], Yij_t_Vi[i], ord) - TaylorSeries.add!(Rij_dot_Vi[i], tmp2139[i], Zij_t_Wi[i], ord) - TaylorSeries.pow!(tmp2142[i], Rij_dot_Vi[i], 2, ord) - TaylorSeries.div!(pn1t7[i], tmp2142[i], r_p2[i], ord) - TaylorSeries.mul!(tmp2145[i], 1.5, pn1t7[i], ord) - TaylorSeries.subst!(pn1t2_7[i], ϕs_and_vs[i], tmp2145[i], ord) + TaylorSeries.add!(tmp1484[i], Xij_t_Ui[i], Yij_t_Vi[i], ord) + TaylorSeries.add!(Rij_dot_Vi[i], tmp1484[i], Zij_t_Wi[i], ord) + TaylorSeries.pow!(tmp1487[i], Rij_dot_Vi[i], 2, ord) + TaylorSeries.div!(pn1t7[i], tmp1487[i], r_p2[i], ord) + TaylorSeries.mul!(tmp1490[i], 1.5, pn1t7[i], ord) + TaylorSeries.subst!(pn1t2_7[i], ϕs_and_vs[i], tmp1490[i], ord) TaylorSeries.add!(pn1t1_7[i], c_p2, pn1t2_7[i], ord) TaylorSeries.mul!(pNX_t_X[i], acceph_t[3i - 2], X[i], ord) TaylorSeries.mul!(pNY_t_Y[i], acceph_t[3i - 1], Y[i], ord) TaylorSeries.mul!(pNZ_t_Z[i], acceph_t[3i], Z[i], ord) - TaylorSeries.add!(tmp2152[i], pNX_t_X[i], pNY_t_Y[i], ord) - TaylorSeries.add!(tmp2153[i], tmp2152[i], pNZ_t_Z[i], ord) - TaylorSeries.mul!(tmp2154[i], 0.5, tmp2153[i], ord) - TaylorSeries.add!(pn1[i], pn1t1_7[i], tmp2154[i], ord) + TaylorSeries.add!(tmp1497[i], pNX_t_X[i], pNY_t_Y[i], ord) + TaylorSeries.add!(tmp1498[i], tmp1497[i], pNZ_t_Z[i], ord) + TaylorSeries.mul!(tmp1499[i], 0.5, tmp1498[i], ord) + TaylorSeries.add!(pn1[i], pn1t1_7[i], tmp1499[i], ord) TaylorSeries.mul!(X_t_pn1[i], newton_acc_X[i], pn1[i], ord) TaylorSeries.mul!(Y_t_pn1[i], newton_acc_Y[i], pn1[i], ord) TaylorSeries.mul!(Z_t_pn1[i], newton_acc_Z[i], pn1[i], ord) @@ -2946,20 +2950,20 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorSeries.mul!(pNZ_t_pn3[i], acceph_t[3i], pn3[i], ord) end for i = 1:10 - TaylorSeries.add!(tmp2162[i], U_t_pn2[i], pNX_t_pn3[i], ord) - TaylorSeries.add!(termpnx[i], X_t_pn1[i], tmp2162[i], ord) + TaylorSeries.add!(tmp1507[i], U_t_pn2[i], pNX_t_pn3[i], ord) + TaylorSeries.add!(termpnx[i], X_t_pn1[i], tmp1507[i], ord) TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) TaylorSeries.identity!(pntempX, sumpnx[i], ord) - TaylorSeries.add!(tmp2165[i], V_t_pn2[i], pNY_t_pn3[i], ord) - TaylorSeries.add!(termpny[i], Y_t_pn1[i], tmp2165[i], ord) + TaylorSeries.add!(tmp1510[i], V_t_pn2[i], pNY_t_pn3[i], ord) + TaylorSeries.add!(termpny[i], Y_t_pn1[i], tmp1510[i], ord) TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) TaylorSeries.identity!(pntempY, sumpny[i], ord) - TaylorSeries.add!(tmp2168[i], W_t_pn2[i], pNZ_t_pn3[i], ord) - TaylorSeries.add!(termpnz[i], Z_t_pn1[i], tmp2168[i], ord) + TaylorSeries.add!(tmp1513[i], W_t_pn2[i], pNZ_t_pn3[i], ord) + TaylorSeries.add!(termpnz[i], Z_t_pn1[i], tmp1513[i], ord) TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) TaylorSeries.identity!(pntempZ, sumpnz[i], ord) end - #= C:\Users\luisi\.julia\dev\NEOs.jl\ex.jl:500 =# Threads.@threads for i = 11:Nm1 + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 TaylorSeries.mul!(X_t_pn1[i], c_p2, newton_acc_X[i], ord) TaylorSeries.mul!(Y_t_pn1[i], c_p2, newton_acc_Y[i], ord) TaylorSeries.mul!(Z_t_pn1[i], c_p2, newton_acc_Z[i], ord) From 26a47c2584b384f2d966c5970daa27732d399043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 12 Aug 2023 11:33:32 -0600 Subject: [PATCH 027/173] Change reduce from Date to TimeOfDay --- ext/DataFramesExt.jl | 17 +++---- src/observations/topocentric.jl | 80 +++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 8 deletions(-) diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index d1f07cd2..c35cd876 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -1,10 +1,11 @@ module DataFramesExt -using Dates: Date, Period, Hour, Day, datetime2julian, julian2datetime +using Dates: Period, Hour, Day, datetime2julian, julian2datetime using TaylorSeries: get_numvars using PlanetaryEphemeris: J2000, selecteph, su, ea, yr, daysec, auday2kmsec using NEOs: RadecMPC, date, gauss_triplets, propagate, RNp1BP_pN_A_J23E_J2S_eph_threads!, order, abstol, sseph, - scaled_variables, gauss_method, residuals, bwdfwdeph, newtonls, diffcorr, nrms, hascoord, tryls + scaled_variables, gauss_method, residuals, bwdfwdeph, newtonls, diffcorr, nrms, hascoord, tryls, + TimeOfDay import Base: convert import NEOs: AbstractAstrometry, extrapolation, reduce_nights, gaussinitcond, relax_factor @@ -72,9 +73,9 @@ via polynomial interpolation. function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} # Convert to DataFrame df = DataFrame(radec) - # Group by observatory and Date - df.Date = Date.(df.date) - gdf = groupby(df, [:observatory, :Date]) + # Group by observatory and TimeOfDay + df.TimeOfDay = TimeOfDay.(df.date, df.observatory) + gdf = groupby(df, [:observatory, :TimeOfDay]) # Interpolate observation nights cdf = combine(gdf, extrapolation, keepkeys = false) # Eliminate unsuccesful interpolations @@ -89,9 +90,9 @@ end function relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} # Convert to DataFrame df = DataFrame(radec) - # Group by observatory and Date - df.Date = Date.(df.date) - gdf = groupby(df, [:observatory, :Date]) + # Group by observatory and TimeOfDay + df.TimeOfDay = TimeOfDay.(df.date, df.observatory) + gdf = groupby(df, [:observatory, :TimeOfDay]) # Interpolate observation nights cdf = combine(gdf, nrow) # Count observations in each group diff --git a/src/observations/topocentric.jl b/src/observations/topocentric.jl index b9d5bb3e..e3d193cd 100644 --- a/src/observations/topocentric.jl +++ b/src/observations/topocentric.jl @@ -1,6 +1,86 @@ # Earth orientation parameters (eop) 2000 const eop_IAU2000A::EopIau2000A = fetch_iers_eop(Val(:IAU2000A)) +@auto_hash_equals struct TimeOfDay + light::Symbol + start::Date + stop::Date + utc::Int + function TimeOfDay(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + # Hours from UTC + utc = hours_from_UTC(observatory) + # Today's sunrise / sunset + today = sunriseset(date, observatory) + # Yesterday's sunrise / sunset + yesterday = sunriseset(date - Day(1), observatory) + # Tomorrow's sunrise / sunset + tomorrow = sunriseset(date + Day(1), observatory) + # Selection + if yesterday[2] <= date <= today[1] + return new(:night, yesterday[2], today[1], utc) + elseif today[1] <= date <= today[2] + return new(:day, today[1], today[2], utc) + elseif today[2] <= date <= tomorrow[1] + return new(:night, today[2], tomorrow[1], utc) + end + + end +end + +isday(x::TimeOfDay) = x.light == :day +isnight(x::TimeOfDay) = x.light == :night + +# Print method for RadecMPC +# Examples: +# N00hp15 α: 608995.65 δ: -25653.3 t: 2020-12-04T10:41:43.209 obs: 703 +# 99942 α: 422475.3 δ: 97289.49 t: 2021-05-12T06:28:35.904 obs: F51 +function show(io::IO, m::TimeOfDay) + print(io, uppercasefirst(string(m.light)), " from ", m.start, " to ", m.stop, " at UTC", @sprintf("%+d", m.utc)) +end + +hours_from_UTC(lon::T) where {T <: Number} = ceil(Int, 12*lon/π - 0.5) +function hours_from_UTC(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + lon, _ = lonlat(observatory) + return hours_from_UTC(lon) +end + +function lonlat(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + # ECEF [km] + p_ECEF = obs_pos_ECEF(observatory) + # ECEF [m] -> Geodetic [m] + lat_geodetic, lon, altitude = ecef_to_geodetic(1_000 * p_ECEF) + # Geodetic [m] -> Geocentric [m] + lat_geocentric, _ = geodetic_to_geocentric(lat_geodetic, altitude) + + return lon, lat_geocentric +end + +function sunriseset(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + # Fractional year [rad] + γ = 2π * (dayofyear(date) - 1 + (hour(date)-12)/24) / daysinyear(date) + # Equation of time [min] + eqtime = 229.18 * (0.000075 + 0.001868*cos(γ) - 0.032077*sin(γ) - 0.014615*cos(2γ) - 0.040849*sin(2γ) ) + # Solar declination angle [rad] + δ = 0.006918 - 0.399912*cos(γ) + 0.070257*sin(γ) - 0.006758*cos(2γ) + 0.000907*sin(2γ) - 0.002697*cos(3γ) + 0.00148*sin(3γ) + # Longitude and latitude [rad] + lon, lat = lonlat(observatory) + # Solar hour angle [deg] + ha_sunrise = acosd(cosd(90.833)/cos(lat)/cos(δ) - tan(lat)*tan(δ)) + ha_sunset = -ha_sunrise + # Day [DateTime] + day = DateTime(Date(date)) + # UTC time of sunrise [min] + sunrise_min = 720 - 4*(rad2deg(lon) + ha_sunrise) - eqtime + # UTC time of sunrise [DateTime] + sunrise = day + Microsecond(round(Int, sunrise_min*6e7)) + # UTC time of sunset [min] + sunset_min = 720 - 4*(rad2deg(lon) + ha_sunset) - eqtime + # UTC time of sunset [DateTime] + sunset = day + Microsecond(round(Int, sunset_min*6e7)) + + return sunrise, sunset +end + @doc raw""" obs_pos_ECEF(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} obs_pos_ECEF(x::RadecMPC{T}) where {T <: AbstractFloat} From 45e1b6b20c384215064edb1ceb996f63a35eee95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 13 Aug 2023 15:19:37 -0600 Subject: [PATCH 028/173] Add preliminary docstrings --- ext/DataFramesExt.jl | 38 ++-- src/observations/process_radec.jl | 76 ++++++- src/observations/topocentric.jl | 41 +++- src/orbit_determination/gauss_method.jl | 25 +-- src/postprocessing/least_squares.jl | 148 ++++++++++--- src/propagation/jetcoeffs.jl | 276 ++++++++++++------------ 6 files changed, 405 insertions(+), 199 deletions(-) diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index c35cd876..c63a6d5e 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -5,7 +5,7 @@ using TaylorSeries: get_numvars using PlanetaryEphemeris: J2000, selecteph, su, ea, yr, daysec, auday2kmsec using NEOs: RadecMPC, date, gauss_triplets, propagate, RNp1BP_pN_A_J23E_J2S_eph_threads!, order, abstol, sseph, scaled_variables, gauss_method, residuals, bwdfwdeph, newtonls, diffcorr, nrms, hascoord, tryls, - TimeOfDay + TimeOfDay, OpticalResidual, heliocentric_energy import Base: convert import NEOs: AbstractAstrometry, extrapolation, reduce_nights, gaussinitcond, relax_factor @@ -87,6 +87,12 @@ function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} return cdf.observatory, cdf.date, cdf.α, cdf.δ end +@doc raw""" + relax_factor(radec::Vector{RadecMPC{T}}, ξs::Vector{OpticalResidual{T}}) where {T <: Real} + +Modify the weights in `ξs` by a relaxing factor quantifying the correlation between observations taken on the +same night by the same observatory. +""" function relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} # Convert to DataFrame df = DataFrame(radec) @@ -101,8 +107,14 @@ function relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} return map(x -> x > 4.0 ? x/4.0 : 1.0, Nv) end +function relax_factor(radec::Vector{RadecMPC{T}}, ξs::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + rex = relax_factor(radec) + return OpticalResidual.(getfield.(ξs, :ξ_α), getfield.(ξs, :ξ_δ), getfield.(ξs, :w_α), getfield.(ξs, :w_δ), rex, + getfield.(ξs, :outlier)) +end + @doc raw""" - gaussinitcond(radec::Vector{RadecMPC{T}}; Δ::Period = Day(1), Q_max::T = 0.75, niter::Int = 5, maxsteps::Int = 100, + gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max::T = 100., niter::Int = 5, maxsteps::Int = 100, varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} Return initial conditions via Gauss method. @@ -111,7 +123,7 @@ See also [`gauss_method`](@ref). # Arguments - `radec::Vector{RadecMPC{T}}`: vector of observations. -- `Δ::Period`: see [`gauss_triplets`](@ref). +- `max_triplets::Int`: maximum number of triplets. - `Q_max::T`: The maximum nrms that is considered a good enough orbit. - `niter::Int`: number of iterations for Newton's method. - `maxsteps::Int`: maximum number of steps for propagation. @@ -169,6 +181,9 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max # Gauss method solution sol = gauss_method(observatories[triplet], dates[triplet], α[triplet] .+ dq[1:3], δ[triplet] .+ dq[4:6]; niter = niter) + # Filter Gauss solutions by heliocentric energy + filter!(x -> heliocentric_energy(x.statevect) <= 0, sol) + # Iterate over Gauss solutions for i in eachindex(sol) @@ -180,23 +195,20 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max order = order, abstol = abstol, parse_eqs = parse_eqs) # O-C residuals - res, w = residuals(radec; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), - xva = et -> bwdfwdeph(et, bwd, fwd)) + res = residuals(radec; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), + xva = et -> bwdfwdeph(et, bwd, fwd)) # Subset of radec for orbit fit - i_O = findall(x -> dates[triplet[1]] <= date(x) <= dates[triplet[3]], radec) - i_ξ = vcat(i_O, i_O .+ length(radec)) + idxs = findall(x -> dates[triplet[1]] <= date(x) <= dates[triplet[3]], radec) # Relaxation factor - rex = relax_factor(radec) - rex = vcat(rex, rex) - w = w ./ rex - + res = relax_factor(radec, res) + # Orbit fit - fit = tryls(res[i_ξ], w[i_ξ], zeros(get_numvars()), niter) + fit = tryls(res[idxs], zeros(get_numvars()), niter) # NRMS - Q = nrms(res(fit.x), w) + Q = nrms(res, fit) # TO DO: check cases where newton converges but diffcorr no diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index 657efa5e..109037f2 100644 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -1,3 +1,70 @@ +@doc raw""" + OpticalResidual{T <: Real, U <: Number} + +An astrometric optical observed minus computed residual. + +# Fields + +- `ξ_α::U`: right ascension residual. +- `ξ_δ::U`: declination residual. +- `w_α::T`: right ascension weight. +- `w_δ::T`: declination weight. +- `relax_factor::T`: relaxation factor. +- `outlier::Bool`: whether the residual is an outlier or not. +""" +@auto_hash_equals struct OpticalResidual{T <: Real, U <: Number} + ξ_α::U + ξ_δ::U + w_α::T + w_δ::T + relax_factor::T + outlier::Bool + function OpticalResidual{T, U}(ξ_α::U, ξ_δ::U, w_α::T, w_δ::T, relax_factor::T = one(T), + outlier::Bool = false) where {T <: Real, U <: Number} + new{T, U}(ξ_α, ξ_δ, w_α, w_δ, relax_factor, outlier) + end +end + +function OpticalResidual(ξ_α::U, ξ_δ::U, w_α::T, w_δ::T, relax_factor::T = one(T), + outlier::Bool = false) where {T <: Real, U <: Number} + return OpticalResidual{T, U}(ξ_α, ξ_δ, w_α, w_δ, relax_factor, outlier) +end + +# Evaluate methods +function evaluate(res::OpticalResidual{T, TaylorN{T}}, x::Vector{T}) where {T <: Real} + return OpticalResidual(res.ξ_α(x), res.ξ_δ(x), res.w_α, res.w_δ, res.relax_factor, res.outlier) +end +(res::OpticalResidual{T, TaylorN{T}})(x::Vector{T}) where {T <: Real} = evaluate(res, x) + +function evaluate(res::Vector{OpticalResidual{T, TaylorN{T}}}, x::Vector{T}) where {T <: Real} + res_new = Vector{OpticalResidual{T, T}}(undef, length(res)) + for i in eachindex(res) + res_new[i] = evaluate(res[i], x) + end + return res_new +end +(res::AbstractVector{OpticalResidual{T, TaylorN{T}}})(x::Vector{T}) where {T <: Real} = evaluate(res, x) + +# Print method for OpticalResidual +# Examples: +# α: -138.7980136773549 δ: -89.8002527255012 +# α: -134.79449984291568 δ: -91.42509376643284 +function show(io::IO, x::OpticalResidual{T, U}) where {T <: Real, U <: Number} + print(io, "α: ", cte(x.ξ_α), " δ: ", cte(x.ξ_δ)) +end + +@doc raw""" + unfold(ξs::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + +Concatenate right ascension and declination residuals for an orbit fit. +""" +function unfold(ξs::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + res = vcat(getfield.(ξs, :ξ_α), getfield.(ξs, :ξ_δ)) + relax_factor = getfield.(ξs, :relax_factor) + w = vcat(getfield.(ξs, :w_α) ./ relax_factor, getfield.(ξs, :w_δ) ./ relax_factor) + return res, w +end + @doc raw""" compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter::Int = 5, xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} @@ -493,7 +560,6 @@ See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and - `xva::AstEph`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ function residuals(obs::Vector{RadecMPC{T}}; kwargs...) where {T <: AbstractFloat} - # Optical astrometry (dates + observed + computed + debiasing + weights) x_jt = radec_astrometry(obs; kwargs...) # Right ascension residuals @@ -501,9 +567,5 @@ function residuals(obs::Vector{RadecMPC{T}}; kwargs...) where {T <: AbstractFloa # Declination residuals res_δ = x_jt[3] .- x_jt[7] .- x_jt[5] # Total residuals - res = vcat(res_α, res_δ) - # Weights - w = repeat(1 ./ x_jt[end].^2, 2) - - return res, w -end + return OpticalResidual.(res_α, res_δ, 1 ./ x_jt[end].^2, 1 ./ x_jt[end].^2, one(T), false) +end \ No newline at end of file diff --git a/src/observations/topocentric.jl b/src/observations/topocentric.jl index e3d193cd..c70257fa 100644 --- a/src/observations/topocentric.jl +++ b/src/observations/topocentric.jl @@ -1,6 +1,17 @@ # Earth orientation parameters (eop) 2000 const eop_IAU2000A::EopIau2000A = fetch_iers_eop(Val(:IAU2000A)) +@doc raw""" + TimeOfDay + +Day/night at a particular timezone. + +# Fields +- `light::Symbol`: `:day` or `:night`. +- `start::Date`. +- `stop::Date`. +- `utc::Int`: hours from UTC. +""" @auto_hash_equals struct TimeOfDay light::Symbol start::Date @@ -27,23 +38,35 @@ const eop_IAU2000A::EopIau2000A = fetch_iers_eop(Val(:IAU2000A)) end end +TimeOfDay(radec::RadecMPC{T}) where {T <: AbstractFloat} = TimeOfDay(date(radec), observatory(radec)) + isday(x::TimeOfDay) = x.light == :day isnight(x::TimeOfDay) = x.light == :night -# Print method for RadecMPC +# Print method for TimeOfDay # Examples: -# N00hp15 α: 608995.65 δ: -25653.3 t: 2020-12-04T10:41:43.209 obs: 703 -# 99942 α: 422475.3 δ: 97289.49 t: 2021-05-12T06:28:35.904 obs: F51 +# Night from 2023-06-29 to 2023-06-29 at UTC-7 +# Night from 2023-06-29 to 2023-06-30 at UTC+3 function show(io::IO, m::TimeOfDay) print(io, uppercasefirst(string(m.light)), " from ", m.start, " to ", m.stop, " at UTC", @sprintf("%+d", m.utc)) end -hours_from_UTC(lon::T) where {T <: Number} = ceil(Int, 12*lon/π - 0.5) +@doc raw""" + hours_from_UTC(lon::T) where {T <: Real} + +Return the naive hour difference between longitude `lon` [rad] and UTC. +""" +hours_from_UTC(lon::T) where {T <: Real} = ceil(Int, 12*lon/π - 0.5) function hours_from_UTC(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} lon, _ = lonlat(observatory) return hours_from_UTC(lon) end +@doc raw""" + lonlat(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + +Return longitude and latitude (both in rad) of an observatory. +""" function lonlat(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} # ECEF [km] p_ECEF = obs_pos_ECEF(observatory) @@ -55,6 +78,14 @@ function lonlat(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} return lon, lat_geocentric end +@doc raw""" + sunriseset(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + +Return `DateTime` of sunrise and sunset at a particular date and location. + +!!! reference + See "General Solar Position Calculations" by NOAA at https://gml.noaa.gov/grad/solcalc/solareqns.PDF. +""" function sunriseset(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} # Fractional year [rad] γ = 2π * (dayofyear(date) - 1 + (hour(date)-12)/24) / daysinyear(date) @@ -81,6 +112,8 @@ function sunriseset(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: return sunrise, sunset end +sunriseset(radec::RadecMPC{T}) where {T <: AbstractFloat} = sunriseset(date(radec), observatory(radec)) + @doc raw""" obs_pos_ECEF(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} obs_pos_ECEF(x::RadecMPC{T}) where {T <: AbstractFloat} diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 3224bd3c..30542b7e 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -3,8 +3,7 @@ include("osculating.jl") @doc raw""" GaussSolution{T <: Real, U <: Number} -A preliminary orbit obtained from Gauss method of orbit determination. See Algorithm 5.5 in page 274 of -https://doi.org/10.1016/C2016-0-02107-1. +A preliminary orbit obtained from Gauss method of orbit determination. See also [`gauss_method`](@ref). @@ -18,6 +17,9 @@ See also [`gauss_method`](@ref). - `τ_3::T`: time between third and second observations. - `f_1, g_1, f_3, g_3::U`: Lagrange coefficients. - `status::Symbol`: the status of the solution (`:empty`, `:unkown` or `:unique`) + +!!! reference + See Algorithm 5.5 in page 274 of https://doi.org/10.1016/C2016-0-02107-1. """ @auto_hash_equals struct GaussSolution{T <: Real, U <: Number} statevect::Vector{U} @@ -48,7 +50,7 @@ end # Examples: # unique Gauss solution (r = 1.0800950907383229 AU) function show(io::IO, g::GaussSolution{T, U}) where {T <: Real, U <: Number} - print(io, g.status, " Gauss solution (r = ", norm(cte.(g.statevect[1:3])), " AU)") + print(io, uppercasefirst(string(g.status)), " Gauss solution (r = ", norm(cte.(g.statevect[1:3])), " AU)") end @doc raw""" @@ -178,7 +180,7 @@ end gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{DateTime}, α::Vector{U}, δ::Vector{U}; niter::Int = 5) where {T <: Real, U <: Number} -Core Gauss method of Initial Orbit determination (IOD). See Algorithm 5.5 in page 274 https://doi.org/10.1016/C2016-0-02107-1. +Core Gauss method of Initial Orbit determination (IOD). # Arguments @@ -188,6 +190,9 @@ Core Gauss method of Initial Orbit determination (IOD). See Algorithm 5.5 in pag - `α::Vector{U}`: right ascension [rad]. - `δ::Vector{U}`: declination [rad]. - `niter::Int`: Number of iterations for Newton's method. + +!!! reference + See Algorithm 5.5 in page 274 https://doi.org/10.1016/C2016-0-02107-1. """ function gauss_method(obs::Vector{RadecMPC{T}}; niter::Int = 5) where {T <: AbstractFloat} @@ -317,9 +322,7 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da sol_gauss[i] = GaussSolution{T, U}(vcat(r_vec[2, :], v_2_vec), D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3, status[i]) end - - filter!(x -> heliocentric_energy(x.statevect) <= 0, sol_gauss) - + # Sort solutions by heliocentric range return sort!(sol_gauss, by = x -> norm(x.statevect[1:3])) end @@ -351,14 +354,12 @@ for Gauss method. The function assumes `dates` is sorted. gauss_norm(dates::Vector{DateTime}) = abs( (dates[2] - dates[1]).value - (dates[3] - dates[2]).value ) @doc raw""" - gauss_triplets(dates::Vector{DateTime}, Δ::Period = Day(1)) + gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_iter::Int = 100) -Return a vector of triplets to be used within [`gaussinitcond`](@ref) to select the best observations for Gauss method. +Return a vector of `max_triplets` triplets to be used within [`gaussinitcond`](@ref) to select the best observations for Gauss method. The triplets are sorted by [`gauss_norm`](@ref). - -See also [`closest_index_sorted`](@ref). """ -function gauss_triplets(dates::Vector{DateTime}, Δ_min::Period, Δ_max::Period, avoid::Vector{Vector{Int}}, max_triplets) +function gauss_triplets(dates::Vector{DateTime}, Δ_min::Period, Δ_max::Period, avoid::Vector{Vector{Int}}, max_triplets::Int) triplets = Vector{Vector{Int}}(undef, 0) L = length(dates) diff --git a/src/postprocessing/least_squares.jl b/src/postprocessing/least_squares.jl index 5e70f170..8dbb9f3c 100644 --- a/src/postprocessing/least_squares.jl +++ b/src/postprocessing/least_squares.jl @@ -1,5 +1,16 @@ include("b_plane.jl") +@doc raw""" + OrbitFit{T <: Real} + +A least squares fit. + +# Fields +- `success::Bool`: wheter the routine converged or not. +- `x::Vector{T}`: deltas that minimize the objective function. +- `Γ::Matrix{T}`: covariance matrix. +- `routine::Symbol`: minimization routine (`:newton` or `:diffcorr`). +""" struct OrbitFit{T <: Real} success::Bool x::Vector{T} @@ -12,14 +23,85 @@ OrbitFit(success::Bool, x::Vector{T}, Γ::Matrix{T}, routine::Symbol) where {T < # Print method for OrbitFit # Examples: -# N00hp15 α: 608995.65 δ: -25653.3 t: 2020-12-04T10:41:43.209 obs: 703 -# 99942 α: 422475.3 δ: 97289.49 t: 2021-05-12T06:28:35.904 obs: F51 +# Succesful Newton +# Succesful differential corrections function show(io::IO, fit::OrbitFit{T}) where {T <: Real} success_s = fit.success ? "Succesful" : "Unsuccesful" routine_s = fit.routine == :newton ? "Newton" : "differential corrections" print(io, success_s, " ", routine_s) end +@doc raw""" + carpino_smoothing(n::T) where {T <: Real} + +Fudge term for rejection condition in [`outlier_rejection`](@ref). + +!!! reference + See page 253 of https://doi.org/10.1016/S0019-1035(03)00051-4. +""" +carpino_smoothing(n::T) where {T <: Real} = 400*(1.2)^(-n) + +@doc raw""" + outlier_rejection(ξs::Vector{OpticalResidual{T}}, fit::OrbitFit{T}; χ2_rec::T = 7., χ2_rej::T = 8., + α::T = 0.25) where {T <: Real} + +Outlier rejection algorithm. + +# Arguments + +- `ξs::Vector{OpticalResidual{T}}`: vector of residuals. +- `fit::OrbitFit{T}`: least squares fit. +- `χ2_rec::T`: recovery conditions. +- `χ2_rej::T`: rejection condition. +- `α::T`: scaling factor for maximum chi. + +!!! reference + See https://doi.org/10.1016/S0019-1035(03)00051-4. +""" +function outlier_rejection(ξs::Vector{OpticalResidual{T}}, fit::OrbitFit{T}; χ2_rec::T = 7., χ2_rej::T = 8., + α::T = 0.25) where {T <: Real} + # Number of residuals + N = length(ξs) + # Vector of chi2s + χ2s = Vector{T}(undef, N) + + for i in eachindex(χ2s) + # Current observation covariance matrix + γ = diagm([ξs[i].w_α/ξs[i].relax_factor, ξs[i].w_δ/ξs[i].relax_factor]) + # Current model matrix + A = hcat(TS.gradient(ξs[i].ξ_α)(fit.x), TS.gradient(ξs[i].ξ_δ)(fit.x)) + # Outlier sign + outlier_sign = ξs[i].outlier*2-1 + # Current residual covariance matrix + γ_ξ = γ + outlier_sign*(A')*fit.Γ*A + # Current residual + ξ = [ξs[i].ξ_α(fit.x), ξs[i].ξ_δ(fit.x)] + # Current chi2 + χ2s[i] = ξ' * inv(γ_ξ) * ξ + end + + χ2_max = maximum(χ2s) + new_ξs = Vector{OpticalResidual{T}}(undef, N) + N_sel = count(x -> !x.outlier, ξs) + + for i in eachindex(χ2s) + if χ2s[i] > max(χ2_rej + carpino_smoothing(N_sel), α*χ2_max) + new_ξs[i] = OpticalResidual(ξs[i].ξ_α, ξs[i].ξ_δ, ξs[i].w_α, ξs[i].w_δ, ξs[i].relax_factor, true) + elseif χ2s[i] < χ2_rec + new_ξs[i] = OpticalResidual(ξs[i].ξ_α, ξs[i].ξ_δ, ξs[i].w_α, ξs[i].w_δ, ξs[i].relax_factor, false) + else + new_ξs[i] = ξs[i] + end + end + + return new_ξs +end + +@doc raw""" + project(y::Vector{TaylorN{T}}, fit::OrbitFit{T}) where {T <: Real} + +Project `fit`'s covariance matrix into `y`. +""" function project(y::Vector{TaylorN{T}}, fit::OrbitFit{T}) where {T <: Real} J = Matrix{T}(undef, get_numvars(), length(y)) for i in eachindex(y) @@ -29,8 +111,9 @@ function project(y::Vector{TaylorN{T}}, fit::OrbitFit{T}) where {T <: Real} end @doc raw""" - nrms(res, w) - + nrms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} + nrms(res::Vector{OpticalResidual{T}}, fit::OrbitFit{T}) where {T <: Real} + Returns the normalized root mean square error ```math \texttt{NRMS} = \sqrt{\frac{\chi^2}{m}}, @@ -44,15 +127,21 @@ See also [`chi2`](@ref). - `res`: Vector of residuals. - `w`: Vector of weights. +- `fit`: least squares fit. """ -function nrms(res, w) +function nrms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} # Have as many residuals as weights @assert length(res) == length(w) # Normalized root mean square error return sqrt( chi2(res, w)/length(res) ) end +function nrms(res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}) where {T <: Real, U <: Number} + res_, w = unfold(res) + return nrms(res_(fit.x), w) +end + @doc raw""" chi2(res, w) @@ -159,7 +248,7 @@ function ξTH(w, res, H_mat, npar) end @doc raw""" - diffcorr(res, w, x0, niters=5) + diffcorr(ξs::Vector{OpticalResidual{T}}, x0::Vector{T}, niters::Int = 5) where {T <: Real} Differential corrections subroutine for least-squares fitting. Returns the `niters`-th correction @@ -181,14 +270,13 @@ See also [`BHC`](@ref). # Arguments -- `res`: Vector of residuals. -- `w`: Vector of weights. -- `x_0`: First guess for the initial conditions. -- `niters`: Number of iterations. +- `ξs::Vector{OpticalResidual{T, TaylorN{T}}}`: Vector of residuals. +- `x_0::Vector{T}`: First guess for the initial conditions. +- `niters::Int`: Number of iterations. """ -function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, niters::Int = 5) where {T <: Real} - # Have as many residuals as weights - @assert length(res) == length(w) +function diffcorr(ξs::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, niters::Int = 5) where {T <: Real} + # Unfold residuals and weights + res, w = unfold(ξs) # Degrees of freedom npar = length(x0) # Design matrix B, H array and normal matrix C @@ -260,14 +348,13 @@ See also [`chi2`](@ref). # Arguments -- `res`: Vector of residuals. -- `w`: Vector of weights. -- `x_0`: First guess for the initial conditions. -- `niters`: Number of iterations. +- `ξs::Vector{OpticalResidual{T, TaylorN{T}}}`: Vector of residuals. +- `x_0::Vector{T}`: First guess for the initial conditions. +- `niters::Int`: Number of iterations. """ -function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, niters::Int = 5) where {T <: Real} - # Have as many residuals as weights - @assert length(res) == length(w) +function newtonls(ξs::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, niters::Int = 5) where {T <: Real} + # Unfold residuals and weights + res, w = unfold(ξs) # Number of observations nobs = length(res) # Degrees of freedom @@ -321,14 +408,25 @@ function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, niters:: return OrbitFit(true, x_new, Γ, :newton) end -function tryls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, niters::Int = 5) where {T <: Real} +@doc raw""" + tryls(ξs::Vector{OpticalResidual{T}}, x0::Vector{T}, niters::Int = 5) where {T <: Real} + +Returns the best least squares fit between two routines: [`newtonls`](@ref) and [`diffcorr`](@ref). + +# Arguments + +- `ξs::Vector{OpticalResidual{T, TaylorN{T}}}`: Vector of residuals. +- `x_0::Vector{T}`: First guess for the initial conditions. +- `niters::Int`: Number of iterations. +""" +function tryls(ξs::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, niters::Int = 5) where {T <: Real} # Newton's method - fit_1 = newtonls(res, w, x0, niters) + fit_1 = newtonls(ξs, x0, niters) # Differential corrections - fit_2 = diffcorr(res, w, x0, niters) + fit_2 = diffcorr(ξs, x0, niters) if fit_1.success && fit_2.success - Q_1 = nrms(res(fit_1.x), w) - Q_2 = nrms(res(fit_2.x), w) + Q_1 = nrms(ξs, fit_1) + Q_2 = nrms(ξs, fit_2) if Q_1 <= Q_2 return fit_1 else diff --git a/src/propagation/jetcoeffs.jl b/src/propagation/jetcoeffs.jl index 9547bbdc..f4990048 100644 --- a/src/propagation/jetcoeffs.jl +++ b/src/propagation/jetcoeffs.jl @@ -145,87 +145,87 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_ep dq[3] = Taylor1(identity(constant_term(q[6])), order) newtonianNb_Potential[N] = Taylor1(identity(constant_term(zero_q_1)), order) tmp687 = Array{Taylor1{_S}}(undef, size(dq)) - tmp687 .= Taylor1(zero(_S), order) + tmp687 .= Taylor1(zero(constant_term(q[1])), order) tmp689 = Array{Taylor1{_S}}(undef, size(ui)) - tmp689 .= Taylor1(zero(_S), order) + tmp689 .= Taylor1(zero(constant_term(q[1])), order) tmp692 = Array{Taylor1{_S}}(undef, size(dq)) - tmp692 .= Taylor1(zero(_S), order) + tmp692 .= Taylor1(zero(constant_term(q[1])), order) tmp694 = Array{Taylor1{_S}}(undef, size(vi)) - tmp694 .= Taylor1(zero(_S), order) + tmp694 .= Taylor1(zero(constant_term(q[1])), order) tmp697 = Array{Taylor1{_S}}(undef, size(dq)) - tmp697 .= Taylor1(zero(_S), order) + tmp697 .= Taylor1(zero(constant_term(q[1])), order) tmp699 = Array{Taylor1{_S}}(undef, size(wi)) - tmp699 .= Taylor1(zero(_S), order) + tmp699 .= Taylor1(zero(constant_term(q[1])), order) pn2x = Array{Taylor1{_S}}(undef, size(X)) - pn2x .= Taylor1(zero(_S), order) + pn2x .= Taylor1(zero(constant_term(q[1])), order) pn2y = Array{Taylor1{_S}}(undef, size(Y)) - pn2y .= Taylor1(zero(_S), order) + pn2y .= Taylor1(zero(constant_term(q[1])), order) pn2z = Array{Taylor1{_S}}(undef, size(Z)) - pn2z .= Taylor1(zero(_S), order) + pn2z .= Taylor1(zero(constant_term(q[1])), order) tmp707 = Array{Taylor1{_S}}(undef, size(UU)) - tmp707 .= Taylor1(zero(_S), order) + tmp707 .= Taylor1(zero(constant_term(q[1])), order) tmp710 = Array{Taylor1{_S}}(undef, size(X)) - tmp710 .= Taylor1(zero(_S), order) + tmp710 .= Taylor1(zero(constant_term(q[1])), order) tmp712 = Array{Taylor1{_S}}(undef, size(Y)) - tmp712 .= Taylor1(zero(_S), order) + tmp712 .= Taylor1(zero(constant_term(q[1])), order) tmp713 = Array{Taylor1{_S}}(undef, size(tmp710)) - tmp713 .= Taylor1(zero(_S), order) + tmp713 .= Taylor1(zero(constant_term(q[1])), order) tmp715 = Array{Taylor1{_S}}(undef, size(Z)) - tmp715 .= Taylor1(zero(_S), order) + tmp715 .= Taylor1(zero(constant_term(q[1])), order) tmp723 = Array{Taylor1{_S}}(undef, size(pn2x)) - tmp723 .= Taylor1(zero(_S), order) + tmp723 .= Taylor1(zero(constant_term(q[1])), order) tmp724 = Array{Taylor1{_S}}(undef, size(tmp723)) - tmp724 .= Taylor1(zero(_S), order) + tmp724 .= Taylor1(zero(constant_term(q[1])), order) tmp819 = Array{Taylor1{_S}}(undef, size(ui)) - tmp819 .= Taylor1(zero(_S), order) + tmp819 .= Taylor1(zero(constant_term(q[1])), order) tmp821 = Array{Taylor1{_S}}(undef, size(vi)) - tmp821 .= Taylor1(zero(_S), order) + tmp821 .= Taylor1(zero(constant_term(q[1])), order) tmp822 = Array{Taylor1{_S}}(undef, size(tmp819)) - tmp822 .= Taylor1(zero(_S), order) + tmp822 .= Taylor1(zero(constant_term(q[1])), order) tmp824 = Array{Taylor1{_S}}(undef, size(wi)) - tmp824 .= Taylor1(zero(_S), order) + tmp824 .= Taylor1(zero(constant_term(q[1])), order) tmp735 = Array{Taylor1{_S}}(undef, size(X)) - tmp735 .= Taylor1(zero(_S), order) + tmp735 .= Taylor1(zero(constant_term(q[1])), order) tmp737 = Array{Taylor1{_S}}(undef, size(Y)) - tmp737 .= Taylor1(zero(_S), order) + tmp737 .= Taylor1(zero(constant_term(q[1])), order) tmp739 = Array{Taylor1{_S}}(undef, size(Z)) - tmp739 .= Taylor1(zero(_S), order) + tmp739 .= Taylor1(zero(constant_term(q[1])), order) tmp741 = Array{Taylor1{_S}}(undef, size(t31)) - tmp741 .= Taylor1(zero(_S), order) + tmp741 .= Taylor1(zero(constant_term(q[1])), order) tmp948 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp948 .= Taylor1(zero(_S), order) + tmp948 .= Taylor1(zero(constant_term(q[1])), order) tmp949 = Array{Taylor1{_S}}(undef, size(ϕ)) - tmp949 .= Taylor1(zero(_S), order) + tmp949 .= Taylor1(zero(constant_term(q[1])), order) tmp751 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp751 .= Taylor1(zero(_S), order) + tmp751 .= Taylor1(zero(constant_term(q[1])), order) tmp757 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp757 .= Taylor1(zero(_S), order) + tmp757 .= Taylor1(zero(constant_term(q[1])), order) tmp759 = Array{Taylor1{_S}}(undef, size(sin3_ϕ)) - tmp759 .= Taylor1(zero(_S), order) + tmp759 .= Taylor1(zero(constant_term(q[1])), order) tmp763 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp763 .= Taylor1(zero(_S), order) + tmp763 .= Taylor1(zero(constant_term(q[1])), order) tmp766 = Array{Taylor1{_S}}(undef, size(r_p2)) - tmp766 .= Taylor1(zero(_S), order) + tmp766 .= Taylor1(zero(constant_term(q[1])), order) tmp767 = Array{Taylor1{_S}}(undef, size(Λ2)) - tmp767 .= Taylor1(zero(_S), order) + tmp767 .= Taylor1(zero(constant_term(q[1])), order) tmp770 = Array{Taylor1{_S}}(undef, size(r_p1d2)) - tmp770 .= Taylor1(zero(_S), order) + tmp770 .= Taylor1(zero(constant_term(q[1])), order) tmp771 = Array{Taylor1{_S}}(undef, size(Λ3)) - tmp771 .= Taylor1(zero(_S), order) + tmp771 .= Taylor1(zero(constant_term(q[1])), order) tmp773 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp773 .= Taylor1(zero(_S), order) + tmp773 .= Taylor1(zero(constant_term(q[1])), order) tmp775 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp775 .= Taylor1(zero(_S), order) + tmp775 .= Taylor1(zero(constant_term(q[1])), order) tmp778 = Array{Taylor1{_S}}(undef, size(Λ2j_div_r4)) - tmp778 .= Taylor1(zero(_S), order) + tmp778 .= Taylor1(zero(constant_term(q[1])), order) tmp782 = Array{Taylor1{_S}}(undef, size(Λ3j_div_r5)) - tmp782 .= Taylor1(zero(_S), order) + tmp782 .= Taylor1(zero(constant_term(q[1])), order) tmp785 = Array{Taylor1{_S}}(undef, size(X)) - tmp785 .= Taylor1(zero(_S), order) + tmp785 .= Taylor1(zero(constant_term(q[1])), order) tmp787 = Array{Taylor1{_S}}(undef, size(Y)) - tmp787 .= Taylor1(zero(_S), order) + tmp787 .= Taylor1(zero(constant_term(q[1])), order) tmp789 = Array{Taylor1{_S}}(undef, size(Z)) - tmp789 .= Taylor1(zero(_S), order) + tmp789 .= Taylor1(zero(constant_term(q[1])), order) #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 ui[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])), order) vi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])), order) @@ -361,13 +361,13 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_ep tmp832 = Taylor1(constant_term(q[6]) ^ float(constant_term(2)), order) v2[N] = Taylor1(constant_term(tmp830) + constant_term(tmp832), order) temp_004 = Array{Taylor1{_S}}(undef, size(newtonian1b_Potential)) - temp_004 .= Taylor1(zero(_S), order) + temp_004 .= Taylor1(zero(constant_term(q[1])), order) tmp835 = Array{Taylor1{_S}}(undef, size(μ)) - tmp835 .= Taylor1(zero(_S), order) + tmp835 .= Taylor1(zero(constant_term(q[1])), order) tmp837 = Array{Taylor1{_S}}(undef, size(μ)) - tmp837 .= Taylor1(zero(_S), order) + tmp837 .= Taylor1(zero(constant_term(q[1])), order) tmp839 = Array{Taylor1{_S}}(undef, size(μ)) - tmp839 .= Taylor1(zero(_S), order) + tmp839 .= Taylor1(zero(constant_term(q[1])), order) for i = 1:Nm1 temp_004[i] = Taylor1(constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]), order) newtonianNb_Potential[N] = Taylor1(identity(constant_term(temp_004[i])), order) @@ -385,35 +385,35 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_ep end _4ϕj[N] = Taylor1(constant_term(4) * constant_term(newtonianNb_Potential[N]), order) tmp845 = Array{Taylor1{_S}}(undef, size(v2)) - tmp845 .= Taylor1(zero(_S), order) + tmp845 .= Taylor1(zero(constant_term(q[1])), order) tmp847 = Array{Taylor1{_S}}(undef, size(vi_dot_vj)) - tmp847 .= Taylor1(zero(_S), order) + tmp847 .= Taylor1(zero(constant_term(q[1])), order) tmp848 = Array{Taylor1{_S}}(undef, size(tmp845)) - tmp848 .= Taylor1(zero(_S), order) + tmp848 .= Taylor1(zero(constant_term(q[1])), order) Xij_t_Ui = Array{Taylor1{_S}}(undef, size(X)) - Xij_t_Ui .= Taylor1(zero(_S), order) + Xij_t_Ui .= Taylor1(zero(constant_term(q[1])), order) Yij_t_Vi = Array{Taylor1{_S}}(undef, size(Y)) - Yij_t_Vi .= Taylor1(zero(_S), order) + Yij_t_Vi .= Taylor1(zero(constant_term(q[1])), order) Zij_t_Wi = Array{Taylor1{_S}}(undef, size(Z)) - Zij_t_Wi .= Taylor1(zero(_S), order) + Zij_t_Wi .= Taylor1(zero(constant_term(q[1])), order) tmp854 = Array{Taylor1{_S}}(undef, size(Xij_t_Ui)) - tmp854 .= Taylor1(zero(_S), order) + tmp854 .= Taylor1(zero(constant_term(q[1])), order) Rij_dot_Vi = Array{Taylor1{_S}}(undef, size(tmp854)) - Rij_dot_Vi .= Taylor1(zero(_S), order) + Rij_dot_Vi .= Taylor1(zero(constant_term(q[1])), order) tmp857 = Array{Taylor1{_S}}(undef, size(Rij_dot_Vi)) - tmp857 .= Taylor1(zero(_S), order) + tmp857 .= Taylor1(zero(constant_term(q[1])), order) pn1t7 = Array{Taylor1{_S}}(undef, size(tmp857)) - pn1t7 .= Taylor1(zero(_S), order) + pn1t7 .= Taylor1(zero(constant_term(q[1])), order) tmp860 = Array{Taylor1{_S}}(undef, size(pn1t7)) - tmp860 .= Taylor1(zero(_S), order) + tmp860 .= Taylor1(zero(constant_term(q[1])), order) pn1t2_7 = Array{Taylor1{_S}}(undef, size(ϕs_and_vs)) - pn1t2_7 .= Taylor1(zero(_S), order) + pn1t2_7 .= Taylor1(zero(constant_term(q[1])), order) tmp867 = Array{Taylor1{_S}}(undef, size(pNX_t_X)) - tmp867 .= Taylor1(zero(_S), order) + tmp867 .= Taylor1(zero(constant_term(q[1])), order) tmp868 = Array{Taylor1{_S}}(undef, size(tmp867)) - tmp868 .= Taylor1(zero(_S), order) + tmp868 .= Taylor1(zero(constant_term(q[1])), order) tmp869 = Array{Taylor1{_S}}(undef, size(tmp868)) - tmp869 .= Taylor1(zero(_S), order) + tmp869 .= Taylor1(zero(constant_term(q[1])), order) #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 ϕi_plus_4ϕj[i] = Taylor1(constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]), order) tmp845[i] = Taylor1(constant_term(2) * constant_term(v2[i]), order) @@ -446,23 +446,23 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_ep pNZ_t_pn3[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(pn3[i]), order) end tmp877 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) - tmp877 .= Taylor1(zero(_S), order) + tmp877 .= Taylor1(zero(constant_term(q[1])), order) termpnx = Array{Taylor1{_S}}(undef, size(X_t_pn1)) - termpnx .= Taylor1(zero(_S), order) + termpnx .= Taylor1(zero(constant_term(q[1])), order) sumpnx = Array{Taylor1{_S}}(undef, size(termpnx)) - sumpnx .= Taylor1(zero(_S), order) + sumpnx .= Taylor1(zero(constant_term(q[1])), order) tmp880 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) - tmp880 .= Taylor1(zero(_S), order) + tmp880 .= Taylor1(zero(constant_term(q[1])), order) termpny = Array{Taylor1{_S}}(undef, size(Y_t_pn1)) - termpny .= Taylor1(zero(_S), order) + termpny .= Taylor1(zero(constant_term(q[1])), order) sumpny = Array{Taylor1{_S}}(undef, size(termpny)) - sumpny .= Taylor1(zero(_S), order) + sumpny .= Taylor1(zero(constant_term(q[1])), order) tmp883 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) - tmp883 .= Taylor1(zero(_S), order) + tmp883 .= Taylor1(zero(constant_term(q[1])), order) termpnz = Array{Taylor1{_S}}(undef, size(Z_t_pn1)) - termpnz .= Taylor1(zero(_S), order) + termpnz .= Taylor1(zero(constant_term(q[1])), order) sumpnz = Array{Taylor1{_S}}(undef, size(termpnz)) - sumpnz .= Taylor1(zero(_S), order) + sumpnz .= Taylor1(zero(constant_term(q[1])), order) for i = 1:10 tmp877[i] = Taylor1(constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]), order) termpnx[i] = Taylor1(constant_term(X_t_pn1[i]) + constant_term(tmp877[i]), order) @@ -1758,87 +1758,87 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_t dq[3] = Taylor1(identity(constant_term(q[6])), order) newtonianNb_Potential[N] = Taylor1(identity(constant_term(zero_q_1)), order) tmp1317 = Array{Taylor1{_S}}(undef, size(dq)) - tmp1317 .= Taylor1(zero(_S), order) + tmp1317 .= Taylor1(zero(constant_term(q[1])), order) tmp1319 = Array{Taylor1{_S}}(undef, size(ui)) - tmp1319 .= Taylor1(zero(_S), order) + tmp1319 .= Taylor1(zero(constant_term(q[1])), order) tmp1322 = Array{Taylor1{_S}}(undef, size(dq)) - tmp1322 .= Taylor1(zero(_S), order) + tmp1322 .= Taylor1(zero(constant_term(q[1])), order) tmp1324 = Array{Taylor1{_S}}(undef, size(vi)) - tmp1324 .= Taylor1(zero(_S), order) + tmp1324 .= Taylor1(zero(constant_term(q[1])), order) tmp1327 = Array{Taylor1{_S}}(undef, size(dq)) - tmp1327 .= Taylor1(zero(_S), order) + tmp1327 .= Taylor1(zero(constant_term(q[1])), order) tmp1329 = Array{Taylor1{_S}}(undef, size(wi)) - tmp1329 .= Taylor1(zero(_S), order) + tmp1329 .= Taylor1(zero(constant_term(q[1])), order) pn2x = Array{Taylor1{_S}}(undef, size(X)) - pn2x .= Taylor1(zero(_S), order) + pn2x .= Taylor1(zero(constant_term(q[1])), order) pn2y = Array{Taylor1{_S}}(undef, size(Y)) - pn2y .= Taylor1(zero(_S), order) + pn2y .= Taylor1(zero(constant_term(q[1])), order) pn2z = Array{Taylor1{_S}}(undef, size(Z)) - pn2z .= Taylor1(zero(_S), order) + pn2z .= Taylor1(zero(constant_term(q[1])), order) tmp1337 = Array{Taylor1{_S}}(undef, size(UU)) - tmp1337 .= Taylor1(zero(_S), order) + tmp1337 .= Taylor1(zero(constant_term(q[1])), order) tmp1340 = Array{Taylor1{_S}}(undef, size(X)) - tmp1340 .= Taylor1(zero(_S), order) + tmp1340 .= Taylor1(zero(constant_term(q[1])), order) tmp1342 = Array{Taylor1{_S}}(undef, size(Y)) - tmp1342 .= Taylor1(zero(_S), order) + tmp1342 .= Taylor1(zero(constant_term(q[1])), order) tmp1343 = Array{Taylor1{_S}}(undef, size(tmp1340)) - tmp1343 .= Taylor1(zero(_S), order) + tmp1343 .= Taylor1(zero(constant_term(q[1])), order) tmp1345 = Array{Taylor1{_S}}(undef, size(Z)) - tmp1345 .= Taylor1(zero(_S), order) + tmp1345 .= Taylor1(zero(constant_term(q[1])), order) tmp1353 = Array{Taylor1{_S}}(undef, size(pn2x)) - tmp1353 .= Taylor1(zero(_S), order) + tmp1353 .= Taylor1(zero(constant_term(q[1])), order) tmp1354 = Array{Taylor1{_S}}(undef, size(tmp1353)) - tmp1354 .= Taylor1(zero(_S), order) + tmp1354 .= Taylor1(zero(constant_term(q[1])), order) tmp1449 = Array{Taylor1{_S}}(undef, size(ui)) - tmp1449 .= Taylor1(zero(_S), order) + tmp1449 .= Taylor1(zero(constant_term(q[1])), order) tmp1451 = Array{Taylor1{_S}}(undef, size(vi)) - tmp1451 .= Taylor1(zero(_S), order) + tmp1451 .= Taylor1(zero(constant_term(q[1])), order) tmp1452 = Array{Taylor1{_S}}(undef, size(tmp1449)) - tmp1452 .= Taylor1(zero(_S), order) + tmp1452 .= Taylor1(zero(constant_term(q[1])), order) tmp1454 = Array{Taylor1{_S}}(undef, size(wi)) - tmp1454 .= Taylor1(zero(_S), order) + tmp1454 .= Taylor1(zero(constant_term(q[1])), order) tmp1365 = Array{Taylor1{_S}}(undef, size(X)) - tmp1365 .= Taylor1(zero(_S), order) + tmp1365 .= Taylor1(zero(constant_term(q[1])), order) tmp1367 = Array{Taylor1{_S}}(undef, size(Y)) - tmp1367 .= Taylor1(zero(_S), order) + tmp1367 .= Taylor1(zero(constant_term(q[1])), order) tmp1369 = Array{Taylor1{_S}}(undef, size(Z)) - tmp1369 .= Taylor1(zero(_S), order) + tmp1369 .= Taylor1(zero(constant_term(q[1])), order) tmp1371 = Array{Taylor1{_S}}(undef, size(t31)) - tmp1371 .= Taylor1(zero(_S), order) + tmp1371 .= Taylor1(zero(constant_term(q[1])), order) tmp1528 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp1528 .= Taylor1(zero(_S), order) + tmp1528 .= Taylor1(zero(constant_term(q[1])), order) tmp1529 = Array{Taylor1{_S}}(undef, size(ϕ)) - tmp1529 .= Taylor1(zero(_S), order) + tmp1529 .= Taylor1(zero(constant_term(q[1])), order) tmp1381 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp1381 .= Taylor1(zero(_S), order) + tmp1381 .= Taylor1(zero(constant_term(q[1])), order) tmp1387 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp1387 .= Taylor1(zero(_S), order) + tmp1387 .= Taylor1(zero(constant_term(q[1])), order) tmp1389 = Array{Taylor1{_S}}(undef, size(sin3_ϕ)) - tmp1389 .= Taylor1(zero(_S), order) + tmp1389 .= Taylor1(zero(constant_term(q[1])), order) tmp1393 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp1393 .= Taylor1(zero(_S), order) + tmp1393 .= Taylor1(zero(constant_term(q[1])), order) tmp1396 = Array{Taylor1{_S}}(undef, size(r_p2)) - tmp1396 .= Taylor1(zero(_S), order) + tmp1396 .= Taylor1(zero(constant_term(q[1])), order) tmp1397 = Array{Taylor1{_S}}(undef, size(Λ2)) - tmp1397 .= Taylor1(zero(_S), order) + tmp1397 .= Taylor1(zero(constant_term(q[1])), order) tmp1400 = Array{Taylor1{_S}}(undef, size(r_p1d2)) - tmp1400 .= Taylor1(zero(_S), order) + tmp1400 .= Taylor1(zero(constant_term(q[1])), order) tmp1401 = Array{Taylor1{_S}}(undef, size(Λ3)) - tmp1401 .= Taylor1(zero(_S), order) + tmp1401 .= Taylor1(zero(constant_term(q[1])), order) tmp1403 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp1403 .= Taylor1(zero(_S), order) + tmp1403 .= Taylor1(zero(constant_term(q[1])), order) tmp1405 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp1405 .= Taylor1(zero(_S), order) + tmp1405 .= Taylor1(zero(constant_term(q[1])), order) tmp1408 = Array{Taylor1{_S}}(undef, size(Λ2j_div_r4)) - tmp1408 .= Taylor1(zero(_S), order) + tmp1408 .= Taylor1(zero(constant_term(q[1])), order) tmp1412 = Array{Taylor1{_S}}(undef, size(Λ3j_div_r5)) - tmp1412 .= Taylor1(zero(_S), order) + tmp1412 .= Taylor1(zero(constant_term(q[1])), order) tmp1415 = Array{Taylor1{_S}}(undef, size(X)) - tmp1415 .= Taylor1(zero(_S), order) + tmp1415 .= Taylor1(zero(constant_term(q[1])), order) tmp1417 = Array{Taylor1{_S}}(undef, size(Y)) - tmp1417 .= Taylor1(zero(_S), order) + tmp1417 .= Taylor1(zero(constant_term(q[1])), order) tmp1419 = Array{Taylor1{_S}}(undef, size(Z)) - tmp1419 .= Taylor1(zero(_S), order) + tmp1419 .= Taylor1(zero(constant_term(q[1])), order) #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 ui[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])), order) vi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])), order) @@ -1974,13 +1974,13 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_t tmp1462 = Taylor1(constant_term(q[6]) ^ float(constant_term(2)), order) v2[N] = Taylor1(constant_term(tmp1460) + constant_term(tmp1462), order) temp_004 = Array{Taylor1{_S}}(undef, size(newtonian1b_Potential)) - temp_004 .= Taylor1(zero(_S), order) + temp_004 .= Taylor1(zero(constant_term(q[1])), order) tmp1465 = Array{Taylor1{_S}}(undef, size(μ)) - tmp1465 .= Taylor1(zero(_S), order) + tmp1465 .= Taylor1(zero(constant_term(q[1])), order) tmp1467 = Array{Taylor1{_S}}(undef, size(μ)) - tmp1467 .= Taylor1(zero(_S), order) + tmp1467 .= Taylor1(zero(constant_term(q[1])), order) tmp1469 = Array{Taylor1{_S}}(undef, size(μ)) - tmp1469 .= Taylor1(zero(_S), order) + tmp1469 .= Taylor1(zero(constant_term(q[1])), order) for i = 1:Nm1 temp_004[i] = Taylor1(constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]), order) newtonianNb_Potential[N] = Taylor1(identity(constant_term(temp_004[i])), order) @@ -1998,35 +1998,35 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_t end _4ϕj[N] = Taylor1(constant_term(4) * constant_term(newtonianNb_Potential[N]), order) tmp1475 = Array{Taylor1{_S}}(undef, size(v2)) - tmp1475 .= Taylor1(zero(_S), order) + tmp1475 .= Taylor1(zero(constant_term(q[1])), order) tmp1477 = Array{Taylor1{_S}}(undef, size(vi_dot_vj)) - tmp1477 .= Taylor1(zero(_S), order) + tmp1477 .= Taylor1(zero(constant_term(q[1])), order) tmp1478 = Array{Taylor1{_S}}(undef, size(tmp1475)) - tmp1478 .= Taylor1(zero(_S), order) + tmp1478 .= Taylor1(zero(constant_term(q[1])), order) Xij_t_Ui = Array{Taylor1{_S}}(undef, size(X)) - Xij_t_Ui .= Taylor1(zero(_S), order) + Xij_t_Ui .= Taylor1(zero(constant_term(q[1])), order) Yij_t_Vi = Array{Taylor1{_S}}(undef, size(Y)) - Yij_t_Vi .= Taylor1(zero(_S), order) + Yij_t_Vi .= Taylor1(zero(constant_term(q[1])), order) Zij_t_Wi = Array{Taylor1{_S}}(undef, size(Z)) - Zij_t_Wi .= Taylor1(zero(_S), order) + Zij_t_Wi .= Taylor1(zero(constant_term(q[1])), order) tmp1484 = Array{Taylor1{_S}}(undef, size(Xij_t_Ui)) - tmp1484 .= Taylor1(zero(_S), order) + tmp1484 .= Taylor1(zero(constant_term(q[1])), order) Rij_dot_Vi = Array{Taylor1{_S}}(undef, size(tmp1484)) - Rij_dot_Vi .= Taylor1(zero(_S), order) + Rij_dot_Vi .= Taylor1(zero(constant_term(q[1])), order) tmp1487 = Array{Taylor1{_S}}(undef, size(Rij_dot_Vi)) - tmp1487 .= Taylor1(zero(_S), order) + tmp1487 .= Taylor1(zero(constant_term(q[1])), order) pn1t7 = Array{Taylor1{_S}}(undef, size(tmp1487)) - pn1t7 .= Taylor1(zero(_S), order) + pn1t7 .= Taylor1(zero(constant_term(q[1])), order) tmp1490 = Array{Taylor1{_S}}(undef, size(pn1t7)) - tmp1490 .= Taylor1(zero(_S), order) + tmp1490 .= Taylor1(zero(constant_term(q[1])), order) pn1t2_7 = Array{Taylor1{_S}}(undef, size(ϕs_and_vs)) - pn1t2_7 .= Taylor1(zero(_S), order) + pn1t2_7 .= Taylor1(zero(constant_term(q[1])), order) tmp1497 = Array{Taylor1{_S}}(undef, size(pNX_t_X)) - tmp1497 .= Taylor1(zero(_S), order) + tmp1497 .= Taylor1(zero(constant_term(q[1])), order) tmp1498 = Array{Taylor1{_S}}(undef, size(tmp1497)) - tmp1498 .= Taylor1(zero(_S), order) + tmp1498 .= Taylor1(zero(constant_term(q[1])), order) tmp1499 = Array{Taylor1{_S}}(undef, size(tmp1498)) - tmp1499 .= Taylor1(zero(_S), order) + tmp1499 .= Taylor1(zero(constant_term(q[1])), order) #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 ϕi_plus_4ϕj[i] = Taylor1(constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]), order) tmp1475[i] = Taylor1(constant_term(2) * constant_term(v2[i]), order) @@ -2059,23 +2059,23 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_t pNZ_t_pn3[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(pn3[i]), order) end tmp1507 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) - tmp1507 .= Taylor1(zero(_S), order) + tmp1507 .= Taylor1(zero(constant_term(q[1])), order) termpnx = Array{Taylor1{_S}}(undef, size(X_t_pn1)) - termpnx .= Taylor1(zero(_S), order) + termpnx .= Taylor1(zero(constant_term(q[1])), order) sumpnx = Array{Taylor1{_S}}(undef, size(termpnx)) - sumpnx .= Taylor1(zero(_S), order) + sumpnx .= Taylor1(zero(constant_term(q[1])), order) tmp1510 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) - tmp1510 .= Taylor1(zero(_S), order) + tmp1510 .= Taylor1(zero(constant_term(q[1])), order) termpny = Array{Taylor1{_S}}(undef, size(Y_t_pn1)) - termpny .= Taylor1(zero(_S), order) + termpny .= Taylor1(zero(constant_term(q[1])), order) sumpny = Array{Taylor1{_S}}(undef, size(termpny)) - sumpny .= Taylor1(zero(_S), order) + sumpny .= Taylor1(zero(constant_term(q[1])), order) tmp1513 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) - tmp1513 .= Taylor1(zero(_S), order) + tmp1513 .= Taylor1(zero(constant_term(q[1])), order) termpnz = Array{Taylor1{_S}}(undef, size(Z_t_pn1)) - termpnz .= Taylor1(zero(_S), order) + termpnz .= Taylor1(zero(constant_term(q[1])), order) sumpnz = Array{Taylor1{_S}}(undef, size(termpnz)) - sumpnz .= Taylor1(zero(_S), order) + sumpnz .= Taylor1(zero(constant_term(q[1])), order) for i = 1:10 tmp1507[i] = Taylor1(constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]), order) termpnx[i] = Taylor1(constant_term(X_t_pn1[i]) + constant_term(tmp1507[i]), order) From 3b8c42f81202cdedb51f1e4b5c93838050007b10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Mon, 14 Aug 2023 12:15:06 -0600 Subject: [PATCH 029/173] Try fit Gauss to full radec --- ext/DataFramesExt.jl | 69 +++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 17 deletions(-) diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl index c63a6d5e..dfd9c3ae 100644 --- a/ext/DataFramesExt.jl +++ b/ext/DataFramesExt.jl @@ -1,9 +1,9 @@ module DataFramesExt -using Dates: Period, Hour, Day, datetime2julian, julian2datetime +using Dates: Period, Hour, Day, DateTime, datetime2julian, julian2datetime using TaylorSeries: get_numvars using PlanetaryEphemeris: J2000, selecteph, su, ea, yr, daysec, auday2kmsec -using NEOs: RadecMPC, date, gauss_triplets, propagate, RNp1BP_pN_A_J23E_J2S_eph_threads!, order, abstol, sseph, +using NEOs: RadecMPC, ObservatoryMPC, date, gauss_triplets, propagate, RNp1BP_pN_A_J23E_J2S_eph_threads!, order, abstol, sseph, scaled_variables, gauss_method, residuals, bwdfwdeph, newtonls, diffcorr, nrms, hascoord, tryls, TimeOfDay, OpticalResidual, heliocentric_energy @@ -11,10 +11,10 @@ import Base: convert import NEOs: AbstractAstrometry, extrapolation, reduce_nights, gaussinitcond, relax_factor if isdefined(Base, :get_extension) - using DataFrames: AbstractDataFrame, DataFrame, nrow, eachcol, eachrow, groupby, combine + using DataFrames: AbstractDataFrame, GroupedDataFrame, DataFrame, nrow, eachcol, eachrow, groupby, combine import Tables: istable, rowaccess, rows, schema, Schema else - using ..DataFrames: AbstractDataFrame, DataFrame, nrow, eachcol, eachrow, groupby, combine + using ..DataFrames: AbstractDataFrame, GroupedDataFrame, DataFrame, nrow, eachcol, eachrow, groupby, combine import ..Tables: istable, rowaccess, rows, schema, Schema end @@ -73,18 +73,19 @@ via polynomial interpolation. function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} # Convert to DataFrame df = DataFrame(radec) - # Group by observatory and TimeOfDay + # Compute TimeOfDay df.TimeOfDay = TimeOfDay.(df.date, df.observatory) + # Group by observatory and TimeOfDay gdf = groupby(df, [:observatory, :TimeOfDay]) # Interpolate observation nights cdf = combine(gdf, extrapolation, keepkeys = false) # Eliminate unsuccesful interpolations filter!(:α => !isnan, cdf) filter!(:δ => !isnan, cdf) - # Sorbt by date - sort!(cdf, :date) + # Sort by date + idxs = sortperm(cdf, :date) - return cdf.observatory, cdf.date, cdf.α, cdf.δ + return cdf.observatory[idxs], cdf.date[idxs], cdf.α[idxs], cdf.δ[idxs], gdf[idxs] end @doc raw""" @@ -135,7 +136,7 @@ See also [`gauss_method`](@ref). !!! warning This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. """ -function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max::T = 100., niter::Int = 5, maxsteps::Int = 100, +function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max::T = 10., niter::Int = 5, maxsteps::Int = 100, varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} # Sun's ephemeris @@ -146,7 +147,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max # Eliminate observatories without coordinates filter!(x -> hascoord(x.observatory), radec) # Reduce nights by interpolation - observatories, dates, α, δ = reduce_nights(radec) + observatories, dates, α, δ, gdf = reduce_nights(radec) # Observations triplets triplets = gauss_triplets(dates, max_triplets) @@ -162,6 +163,9 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max best_Q = T(Inf) # Initial conditions best_Q0 = zeros(T, 6) + # Boundaries + best_min = 0 + best_max = 0 # Break flag flag = false @@ -198,31 +202,62 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max res = residuals(radec; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), xva = et -> bwdfwdeph(et, bwd, fwd)) - # Subset of radec for orbit fit - idxs = findall(x -> dates[triplet[1]] <= date(x) <= dates[triplet[3]], radec) - # Relaxation factor res = relax_factor(radec, res) - + + # Subset of radec for orbit fit + idxs = findall(x -> triplet[1] <= x <= triplet[3], gdf.groups) + sort!(idxs) + # Orbit fit fit = tryls(res[idxs], zeros(get_numvars()), niter) + !fit.success && continue + + # Right iteration + for k in triplet[3]+1:length(gdf) + extra = findall(x -> x == k, gdf.groups) + fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) + if fit_new.success + fit = fit_new + idxs = vcat(idxs, extra) + sort!(idxs) + else + break + end + end + + # Left iteration + for k in triplet[1]-1:-1:1 + extra = findall(x -> x == k, gdf.groups) + fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) + if fit_new.success + fit = fit_new + idxs = vcat(idxs, extra) + sort!(idxs) + else + break + end + end + # NRMS Q = nrms(res, fit) # TO DO: check cases where newton converges but diffcorr no - if fit.success # Update NRMS and initial conditions if Q < best_Q best_Q = Q best_Q0 .= bwd(bwd.t0)(fit.x) + best_min = idxs[1] + best_max = idxs[end] end # Break condition if Q <= Q_max flag = true end end + # Break condition if flag break @@ -235,10 +270,10 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max # Case: all solutions were unsuccesful if isinf(best_Q) - return jd0::T, Vector{T}(undef, 0) + return jd0::T, Vector{T}(undef, 0), zero(T), 0, 0 # Case: at least one solution was succesful else - return jd0::T, best_Q0 + return jd0::T, best_Q0, best_Q, best_min, best_max end end From 501c5a5302bf3c2155211a2e8b4c2a6eee8a8ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 19 Aug 2023 12:29:03 -0600 Subject: [PATCH 030/173] Upgrade DF to fulldep --- Project.toml | 17 +- ext/DataFramesExt.jl | 280 ------------------------ src/NEOs.jl | 21 +- src/init.jl | 6 - src/observations/process_radec.jl | 98 ++++++++- src/observations/radec_mpc.jl | 21 +- src/orbit_determination/gauss_method.jl | 174 +++++++++++++-- src/postprocessing/least_squares.jl | 12 +- src/postprocessing/neosolution.jl | 127 +++++++++++ src/propagation/propagation.jl | 160 ++++---------- 10 files changed, 457 insertions(+), 459 deletions(-) delete mode 100644 ext/DataFramesExt.jl create mode 100644 src/postprocessing/neosolution.jl diff --git a/Project.toml b/Project.toml index b54c689c..0efaf103 100644 --- a/Project.toml +++ b/Project.toml @@ -1,11 +1,12 @@ name = "NEOs" uuid = "b41c07a2-2abb-11e9-070a-c3c1b239e7df" authors = ["Jorge A. Pérez Hernández", "Luis Benet", "Luis Eduardo Ramírez Montoya"] -version = "0.7.1" +version = "0.7.2" [deps] Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" AutoHashEquals = "15f4f7f2-30c1-5605-9d31-71845cf9641f" +DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" @@ -23,22 +24,15 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" PlanetaryEphemeris = "d83715d0-7e5f-11e9-1a59-4137b20d8363" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Quadmath = "be4d8f0f-7fa4-5f49-b795-2f01399ab2dd" -Requires = "ae029012-a4dd-5104-9daa-d747884805df" SPICE = "5bab7191-041a-5c2e-a744-024b9c3a5062" SatelliteToolboxTransformations = "6b019ec1-7a1e-4f04-96c7-a9db1ca5514d" Scratch = "6c6a2e73-6563-6170-7368-637461726353" StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" +Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" TaylorIntegration = "92b13dbe-c966-51a2-8445-caca9f8a7d42" TaylorSeries = "6aa5eb33-94cf-58f4-a9d0-e4b2c4fc25ea" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -[weakdeps] -DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" -Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" - -[extensions] -DataFramesExt = ["DataFrames", "Tables"] - [compat] AutoHashEquals = "0.2" DataFrames = "1.5" @@ -52,7 +46,6 @@ IntervalRootFinding = "0.5.11" JLD2 = "0.4" PlanetaryEphemeris = "0.7" Quadmath = "0.5" -Requires = "0.5.2, 1" SPICE = "0.2" SatelliteToolboxTransformations = "0.1" Scratch = "1.2" @@ -61,7 +54,3 @@ Tables = "1.10" TaylorIntegration = "0.14" TaylorSeries = "0.15" julia = "1.6" - -[extras] -DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" -Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl deleted file mode 100644 index dfd9c3ae..00000000 --- a/ext/DataFramesExt.jl +++ /dev/null @@ -1,280 +0,0 @@ -module DataFramesExt - -using Dates: Period, Hour, Day, DateTime, datetime2julian, julian2datetime -using TaylorSeries: get_numvars -using PlanetaryEphemeris: J2000, selecteph, su, ea, yr, daysec, auday2kmsec -using NEOs: RadecMPC, ObservatoryMPC, date, gauss_triplets, propagate, RNp1BP_pN_A_J23E_J2S_eph_threads!, order, abstol, sseph, - scaled_variables, gauss_method, residuals, bwdfwdeph, newtonls, diffcorr, nrms, hascoord, tryls, - TimeOfDay, OpticalResidual, heliocentric_energy - -import Base: convert -import NEOs: AbstractAstrometry, extrapolation, reduce_nights, gaussinitcond, relax_factor - -if isdefined(Base, :get_extension) - using DataFrames: AbstractDataFrame, GroupedDataFrame, DataFrame, nrow, eachcol, eachrow, groupby, combine - import Tables: istable, rowaccess, rows, schema, Schema -else - using ..DataFrames: AbstractDataFrame, GroupedDataFrame, DataFrame, nrow, eachcol, eachrow, groupby, combine - import ..Tables: istable, rowaccess, rows, schema, Schema -end - -# Methods to convert a Vector{<:AbstractAstrometry} to a DataFrame -istable(::Type{Vector{<:AbstractAstrometry}}) = true -rowaccess(::Type{Vector{<:AbstractAstrometry}}) = true -rows(x::Vector{<:AbstractAstrometry}) = x -schema(::Vector{T}) where {T <: AbstractAstrometry} = Schema(fieldnames(T), Tuple{fieldtypes(T)...}) - -# Methods to convert a DataFrame to a Vector{<:AbstractAstrometry} -function Vector{T}(df::DataFrame) where {T <: AbstractAstrometry} - @assert all(String.(fieldnames(T)) .== names(df)) "`DataFrame` column names don't match `$T` fieldnames" - @assert all(fieldtypes(T) .== eltype.(eachcol(df))) "`DataFrame` column types don't match `$T` fieldtypes" - obs = Vector{T}(undef, nrow(df)) - for (i, row) in zip(eachindex(obs), eachrow(df)) - obs[i] = T(values(row)...) - end - return obs -end - -convert(::Type{Vector{T}}, df::DataFrame) where {T <: AbstractAstrometry} = Vector{T}(df) - -@doc raw""" - extrapolation(df::AbstractDataFrame) - -Special method of [`extrapolation`](@ref) to be used by [`gaussinitcond`](@ref). -""" -function extrapolation(df::AbstractDataFrame) - if isone(nrow(df)) - return (observatory = df.observatory[1], date = df.date[1], α = df.α[1], δ = df.δ[1]) - end - - # Julian days of observation - t_julian = datetime2julian.(df.date) - # Days of observation [relative to first observation] - t_rel = t_julian .- t_julian[1] - # Mean date - t_mean = sum(t_rel) / length(t_rel) - - # Extrapolate - α_p = extrapolation(t_rel, df.α) - δ_p = extrapolation(t_rel, df.δ) - # Evaluate polynomials at mean date - α_mean = α_p(t_mean) - δ_mean = δ_p(t_mean) - - return (observatory = df.observatory[1], date = julian2datetime(t_julian[1] + t_mean), α = α_mean, δ = δ_mean) -end - -@doc raw""" - reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - -Return one observatory, date, right ascension and declination per observation night in `radec`. The reduction is performed -via polynomial interpolation. -""" -function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - # Convert to DataFrame - df = DataFrame(radec) - # Compute TimeOfDay - df.TimeOfDay = TimeOfDay.(df.date, df.observatory) - # Group by observatory and TimeOfDay - gdf = groupby(df, [:observatory, :TimeOfDay]) - # Interpolate observation nights - cdf = combine(gdf, extrapolation, keepkeys = false) - # Eliminate unsuccesful interpolations - filter!(:α => !isnan, cdf) - filter!(:δ => !isnan, cdf) - # Sort by date - idxs = sortperm(cdf, :date) - - return cdf.observatory[idxs], cdf.date[idxs], cdf.α[idxs], cdf.δ[idxs], gdf[idxs] -end - -@doc raw""" - relax_factor(radec::Vector{RadecMPC{T}}, ξs::Vector{OpticalResidual{T}}) where {T <: Real} - -Modify the weights in `ξs` by a relaxing factor quantifying the correlation between observations taken on the -same night by the same observatory. -""" -function relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - # Convert to DataFrame - df = DataFrame(radec) - # Group by observatory and TimeOfDay - df.TimeOfDay = TimeOfDay.(df.date, df.observatory) - gdf = groupby(df, [:observatory, :TimeOfDay]) - # Interpolate observation nights - cdf = combine(gdf, nrow) - # Count observations in each group - Nv = cdf[gdf.groups, :nrow] - # Relaxation factor - return map(x -> x > 4.0 ? x/4.0 : 1.0, Nv) -end - -function relax_factor(radec::Vector{RadecMPC{T}}, ξs::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} - rex = relax_factor(radec) - return OpticalResidual.(getfield.(ξs, :ξ_α), getfield.(ξs, :ξ_δ), getfield.(ξs, :w_α), getfield.(ξs, :w_δ), rex, - getfield.(ξs, :outlier)) -end - -@doc raw""" - gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max::T = 100., niter::Int = 5, maxsteps::Int = 100, - varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} - -Return initial conditions via Gauss method. - -See also [`gauss_method`](@ref). - -# Arguments -- `radec::Vector{RadecMPC{T}}`: vector of observations. -- `max_triplets::Int`: maximum number of triplets. -- `Q_max::T`: The maximum nrms that is considered a good enough orbit. -- `niter::Int`: number of iterations for Newton's method. -- `maxsteps::Int`: maximum number of steps for propagation. -- `varorder::Int`: order of jet transport perturbation. -- `order::Int`: order of Taylor polynomials w.r.t. time. -- `abstol::T`: absolute tolerance. -- `parse_eqs::Bool`: whether to use the taylorized method of `RNp1BP_pN_A_J23E_J2S_eph_threads!` or not. - -!!! warning - This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. -""" -function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max::T = 10., niter::Int = 5, maxsteps::Int = 100, - varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} - - # Sun's ephemeris - eph_su = selecteph(sseph, su) - # Earth's ephemeris - eph_ea = selecteph(sseph, ea) - - # Eliminate observatories without coordinates - filter!(x -> hascoord(x.observatory), radec) - # Reduce nights by interpolation - observatories, dates, α, δ, gdf = reduce_nights(radec) - # Observations triplets - triplets = gauss_triplets(dates, max_triplets) - - # Julian day of first (last) observation - t0, tf = datetime2julian(radec[1].date), datetime2julian(radec[end].date) - # Julian day when to start propagation - jd0 = zero(T) - - # Jet transport perturbation (ra/dec) - dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃"; order = varorder) - - # Normalized root mean square error (NRMS) - best_Q = T(Inf) - # Initial conditions - best_Q0 = zeros(T, 6) - # Boundaries - best_min = 0 - best_max = 0 - # Break flag - flag = false - - # Iterate over triplets - for j in eachindex(triplets) - - # Current triplet - triplet = triplets[j] - - # Julian day when to start propagation - jd0 = datetime2julian(dates[triplet[2]]) - # Number of years in forward integration - nyears_fwd = (tf - jd0 + 2) / yr - # Number of years in backward integration - nyears_bwd = -(jd0 - t0 + 2) / yr - - # Gauss method solution - sol = gauss_method(observatories[triplet], dates[triplet], α[triplet] .+ dq[1:3], δ[triplet] .+ dq[4:6]; niter = niter) - - # Filter Gauss solutions by heliocentric energy - filter!(x -> heliocentric_energy(x.statevect) <= 0, sol) - - # Iterate over Gauss solutions - for i in eachindex(sol) - - # Initial conditions (jet transport) - q0 = sol[i].statevect .+ eph_su(jd0 - J2000) - - # Propagation - bwd, fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_bwd, nyears_fwd, q0, Val(true); - order = order, abstol = abstol, parse_eqs = parse_eqs) - - # O-C residuals - res = residuals(radec; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), - xva = et -> bwdfwdeph(et, bwd, fwd)) - - # Relaxation factor - res = relax_factor(radec, res) - - # Subset of radec for orbit fit - idxs = findall(x -> triplet[1] <= x <= triplet[3], gdf.groups) - sort!(idxs) - - # Orbit fit - fit = tryls(res[idxs], zeros(get_numvars()), niter) - - !fit.success && continue - - # Right iteration - for k in triplet[3]+1:length(gdf) - extra = findall(x -> x == k, gdf.groups) - fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) - if fit_new.success - fit = fit_new - idxs = vcat(idxs, extra) - sort!(idxs) - else - break - end - end - - # Left iteration - for k in triplet[1]-1:-1:1 - extra = findall(x -> x == k, gdf.groups) - fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) - if fit_new.success - fit = fit_new - idxs = vcat(idxs, extra) - sort!(idxs) - else - break - end - end - - # NRMS - Q = nrms(res, fit) - - # TO DO: check cases where newton converges but diffcorr no - if fit.success - # Update NRMS and initial conditions - if Q < best_Q - best_Q = Q - best_Q0 .= bwd(bwd.t0)(fit.x) - best_min = idxs[1] - best_max = idxs[end] - end - # Break condition - if Q <= Q_max - flag = true - end - end - - # Break condition - if flag - break - end - end - if flag - break - end - end - - # Case: all solutions were unsuccesful - if isinf(best_Q) - return jd0::T, Vector{T}(undef, 0), zero(T), 0, 0 - # Case: at least one solution was succesful - else - return jd0::T, best_Q0, best_Q, best_min, best_max - end -end - -end # module \ No newline at end of file diff --git a/src/NEOs.jl b/src/NEOs.jl index fe0d7fa2..eeab461c 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -2,13 +2,13 @@ module NEOs # __precompile__(false) -if !isdefined(Base, :get_extension) - using Requires -end - -import Base: hash, ==, show, isless, isnan, convert +import Base: hash, ==, show, isless, isnan, convert, zero, iszero import PlanetaryEphemeris as PE import JLD2: writeas +import Tables: istable, rowaccess, rows, schema, Schema +import SatelliteToolboxTransformations.sv_ecef_to_eci +import SatelliteToolboxTransformations.sv_ecef_to_ecef +import Downloads using Distributed, JLD2, TaylorIntegration, Printf, DelimitedFiles, Test, LinearAlgebra, Dates, SPICE, Quadmath, LazyArtifacts, TaylorSeries, @@ -20,11 +20,9 @@ using PlanetaryEphemeris: daysec, su, ea, α_p_sun, δ_p_sun, t2c_jpl_de430, pol meananomaly, selecteph using Healpix: ang2pixRing, Resolution using SatelliteToolboxTransformations -import SatelliteToolboxTransformations.sv_ecef_to_eci -import SatelliteToolboxTransformations.sv_ecef_to_ecef using Dates: format using Downloads: download -import Downloads +using DataFrames: AbstractDataFrame, GroupedDataFrame, DataFrame, nrow, eachcol, eachrow, groupby, combine using HTTP: get using IntervalRootFinding: roots, interval, Interval, mid using Interpolations: Flat, Gridded, Linear, interpolate, extrapolate @@ -63,14 +61,15 @@ export gauss_method, gaussinitcond export RNp1BP_pN_A_J23E_J2S_ng_eph_threads!, RNp1BP_pN_A_J23E_J2S_eph_threads! # Propagate export propagate, propagate_lyap, propagate_root - -export valsecchi_circle, nrms, chi2, newtonls, newtonls_6v, diffcorr, newtonls_Q, bopik, tryls, project +# Post processing +export valsecchi_circle, nrms, chi2, newtonls, newtonls_6v, diffcorr, newtonls_Q, bopik, tryls, project, + orbitdetermination include("constants.jl") include("observations/process_radar.jl") include("orbit_determination/gauss_method.jl") include("propagation/propagation.jl") -include("postprocessing/least_squares.jl") +include("postprocessing/neosolution.jl") include("init.jl") end \ No newline at end of file diff --git a/src/init.jl b/src/init.jl index 737ef32f..39c5c50c 100644 --- a/src/init.jl +++ b/src/init.jl @@ -14,11 +14,5 @@ function __init__() global mpc_observatories[] = read_observatories_mpc(ObsCodes_path) else update_observatories_mpc() - end - # Extensions - @static if !isdefined(Base, :get_extension) - @require Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" begin - @require DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" include("../ext/DataFramesExt.jl") - end end end \ No newline at end of file diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index 109037f2..73562a4d 100644 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -536,6 +536,30 @@ function radec_astrometry(obs::Vector{RadecMPC{T}}; debias_table::String = "2018 return datetime_obs, α_obs, δ_obs, α_comp, δ_comp, α_corr, δ_corr, w8s end + +@doc raw""" + relax_factor(radec::Vector{RadecMPC{T}}) where {T <: Real} + +Return a relax factor for each element of `radec` quantifying the correlation between observations taken on +the same night by the same observatory. + +!!! reference + See https://doi.org/10.1016/j.icarus.2017.05.021. +""" +function relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + # Convert to DataFrame + df = DataFrame(radec) + # Group by observatory and TimeOfDay + df.TimeOfDay = TimeOfDay.(df.date, df.observatory) + gdf = groupby(df, [:observatory, :TimeOfDay]) + # Interpolate observation nights + cdf = combine(gdf, nrow) + # Count observations in each group + Nv = cdf[gdf.groups, :nrow] + # Relaxation factor + return map(x -> x > 4.0 ? x/4.0 : 1.0, Nv) +end + @doc raw""" residuals(obs::Vector{RadecMPC{T}}; niter::Int = 5, debias_table::String = "2018", xvs::SunEph = sunposvel, xve::EarthEph = earthposvel, xva::AstEph) where {T <: AbstractFloat, SunEph, EarthEph, AstEph} @@ -566,6 +590,76 @@ function residuals(obs::Vector{RadecMPC{T}}; kwargs...) where {T <: AbstractFloa res_α = x_jt[2] .- x_jt[6] .- x_jt[4] # Declination residuals res_δ = x_jt[3] .- x_jt[7] .- x_jt[5] + # Relax factors + rex = relax_factor(obs) # Total residuals - return OpticalResidual.(res_α, res_δ, 1 ./ x_jt[end].^2, 1 ./ x_jt[end].^2, one(T), false) -end \ No newline at end of file + return OpticalResidual.(res_α, res_δ, 1 ./ x_jt[end].^2, 1 ./ x_jt[end].^2, rex, false) +end + + +@doc raw""" + extrapolation(x::AbstractVector{T}, y::AbstractVector{T}) where {T <: Real} + +Return an extrapolation of points `(x, y)`. +""" +function extrapolation(x::AbstractVector{T}, y::AbstractVector{T}) where {T <: Real} + # Check we have as many x as y + @assert length(x) == length(y) + # Interpolation + itp = interpolate((x,), y, Gridded(Linear())) + # Extrapolation + etpf = extrapolate(itp, Flat()) + + return etpf +end + +@doc raw""" + extrapolation(df::AbstractDataFrame) + +Special method of [`extrapolation`](@ref) to be used by [`gaussinitcond`](@ref). +""" +function extrapolation(df::AbstractDataFrame) + if isone(nrow(df)) + return (observatory = df.observatory[1], date = df.date[1], α = df.α[1], δ = df.δ[1]) + end + + # Julian days of observation + t_julian = datetime2julian.(df.date) + # Days of observation [relative to first observation] + t_rel = t_julian .- t_julian[1] + # Mean date + t_mean = sum(t_rel) / length(t_rel) + + # Extrapolate + α_p = extrapolation(t_rel, df.α) + δ_p = extrapolation(t_rel, df.δ) + # Evaluate polynomials at mean date + α_mean = α_p(t_mean) + δ_mean = δ_p(t_mean) + + return (observatory = df.observatory[1], date = julian2datetime(t_julian[1] + t_mean), α = α_mean, δ = δ_mean) +end + +@doc raw""" + reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + +Return one observatory, date, right ascension and declination per observation night in `radec`. The reduction is performed +via polynomial interpolation. +""" +function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + # Convert to DataFrame + df = DataFrame(radec) + # Compute TimeOfDay + df.TimeOfDay = TimeOfDay.(df.date, df.observatory) + # Group by observatory and TimeOfDay + gdf = groupby(df, [:observatory, :TimeOfDay]) + # Interpolate observation nights + cdf = combine(gdf, extrapolation, keepkeys = false) + # Eliminate unsuccesful interpolations + filter!(:α => !isnan, cdf) + filter!(:δ => !isnan, cdf) + # Sort by date + idxs = sortperm(cdf, :date) + + return cdf.observatory[idxs], cdf.date[idxs], cdf.α[idxs], cdf.δ[idxs], gdf[idxs] +end \ No newline at end of file diff --git a/src/observations/radec_mpc.jl b/src/observations/radec_mpc.jl index 6209f7f9..4e6d2d3e 100644 --- a/src/observations/radec_mpc.jl +++ b/src/observations/radec_mpc.jl @@ -511,4 +511,23 @@ function get_radec_mpc(id::AbstractString, filename::AbstractString = replace(id # Download observations file download(obs_url, filename) return nothing -end \ No newline at end of file +end + +# Methods to convert a Vector{<:AbstractAstrometry} to a DataFrame +istable(::Type{Vector{<:AbstractAstrometry}}) = true +rowaccess(::Type{Vector{<:AbstractAstrometry}}) = true +rows(x::Vector{<:AbstractAstrometry}) = x +schema(::Vector{T}) where {T <: AbstractAstrometry} = Schema(fieldnames(T), Tuple{fieldtypes(T)...}) + +# Methods to convert a DataFrame to a Vector{<:AbstractAstrometry} +function Vector{T}(df::DataFrame) where {T <: AbstractAstrometry} + @assert all(String.(fieldnames(T)) .== names(df)) "`DataFrame` column names don't match `$T` fieldnames" + @assert all(fieldtypes(T) .== eltype.(eachcol(df))) "`DataFrame` column types don't match `$T` fieldtypes" + obs = Vector{T}(undef, nrow(df)) + for (i, row) in zip(eachindex(obs), eachrow(df)) + obs[i] = T(values(row)...) + end + return obs +end + +convert(::Type{Vector{T}}, df::DataFrame) where {T <: AbstractAstrometry} = Vector{T}(df) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 30542b7e..742a5211 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -329,22 +329,6 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da end -@doc raw""" - extrapolation(x::AbstractVector{T}, y::AbstractVector{T}) where {T <: Real} - -Return an extrapolation of points `(x, y)`. -""" -function extrapolation(x::AbstractVector{T}, y::AbstractVector{T}) where {T <: Real} - # Check we have as many x as y - @assert length(x) == length(y) - # Interpolation - itp = interpolate((x,), y, Gridded(Linear())) - # Extrapolation - etpf = extrapolate(itp, Flat()) - - return etpf -end - @doc raw""" gauss_norm(dates::Vector{DateTime}) @@ -403,7 +387,157 @@ function gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_ite return triplets[1:n] end -# Empty methods to be overloaded by DataFramesExt -function reduce_nights end -function gaussinitcond end -function relax_factor end \ No newline at end of file +@doc raw""" + gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max::T = 100., niter::Int = 5, maxsteps::Int = 100, + varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} + +Return initial conditions via Gauss method. + +See also [`gauss_method`](@ref). + +# Arguments +- `radec::Vector{RadecMPC{T}}`: vector of observations. +- `max_triplets::Int`: maximum number of triplets. +- `Q_max::T`: The maximum nrms that is considered a good enough orbit. +- `niter::Int`: number of iterations for Newton's method. +- `maxsteps::Int`: maximum number of steps for propagation. +- `varorder::Int`: order of jet transport perturbation. +- `order::Int`: order of Taylor polynomials w.r.t. time. +- `abstol::T`: absolute tolerance. +- `parse_eqs::Bool`: whether to use the taylorized method of `RNp1BP_pN_A_J23E_J2S_eph_threads!` or not. + +!!! warning + This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. +""" +function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max::T = 10., niter::Int = 5, maxsteps::Int = 100, + varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} + + # Sun's ephemeris + eph_su = selecteph(sseph, su) + # Earth's ephemeris + eph_ea = selecteph(sseph, ea) + + # Eliminate observatories without coordinates + filter!(x -> hascoord(x.observatory), radec) + # Reduce nights by interpolation + observatories, dates, α, δ, gdf = reduce_nights(radec) + # Observations triplets + triplets = gauss_triplets(dates, max_triplets) + + # Julian day of first (last) observation + t0, tf = datetime2julian(radec[1].date), datetime2julian(radec[end].date) + # Julian day when to start propagation + jd0 = zero(T) + + # Jet transport perturbation (ra/dec) + dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃"; order = varorder) + + # Normalized root mean square error (NRMS) + best_Q = T(Inf) + # Initial conditions + best_sol = zero(NEOSolution{T, T}) + # Break flag + flag = false + + # Iterate over triplets + for j in eachindex(triplets) + + # Current triplet + triplet = triplets[j] + + # Julian day when to start propagation + jd0 = datetime2julian(dates[triplet[2]]) + # Number of years in forward integration + nyears_fwd = (tf - jd0 + 2) / yr + # Number of years in backward integration + nyears_bwd = -(jd0 - t0 + 2) / yr + + # Gauss method solution + sol = gauss_method(observatories[triplet], dates[triplet], α[triplet] .+ dq[1:3], δ[triplet] .+ dq[4:6]; niter = niter) + + # Filter Gauss solutions by heliocentric energy + filter!(x -> heliocentric_energy(x.statevect) <= 0, sol) + + # Iterate over Gauss solutions + for i in eachindex(sol) + + # Initial conditions (jet transport) + q0 = sol[i].statevect .+ eph_su(jd0 - J2000) + + # Propagation + bwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_bwd, q0; + order = order, abstol = abstol, parse_eqs = parse_eqs) + fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_fwd, q0; + order = order, abstol = abstol, parse_eqs = parse_eqs) + + if length(bwd.t) == maxsteps+1 || length(fwd.t) == maxsteps + 1 + continue + end + + # O-C residuals + res = residuals(radec; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), + xva = et -> bwdfwdeph(et, bwd, fwd)) + + # Subset of radec for orbit fit + idxs = findall(x -> triplet[1] <= x <= triplet[3], gdf.groups) + sort!(idxs) + + # Orbit fit + fit = tryls(res[idxs], zeros(get_numvars()), niter) + + !fit.success && continue + + # Right iteration + for k in triplet[3]+1:length(gdf) + extra = findall(x -> x == k, gdf.groups) + fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) + if fit_new.success + fit = fit_new + idxs = vcat(idxs, extra) + sort!(idxs) + else + break + end + end + + # Left iteration + for k in triplet[1]-1:-1:1 + extra = findall(x -> x == k, gdf.groups) + fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) + if fit_new.success + fit = fit_new + idxs = vcat(idxs, extra) + sort!(idxs) + else + break + end + end + + # NRMS + Q = nrms(res, fit) + + # TO DO: check cases where newton converges but diffcorr no + # Update NRMS and initial conditions + if Q < best_Q + best_Q = Q + best_sol = evalfit(NEOSolution(bwd, fwd, res, fit)) + end + # Break condition + if Q <= Q_max + flag = true + break + end + end + if flag + break + end + end + + # Case: all solutions were unsuccesful + if isinf(best_Q) + return zero(NEOSolution{T, T}) + # Case: at least one solution was succesful + else + return best_sol + end +end \ No newline at end of file diff --git a/src/postprocessing/least_squares.jl b/src/postprocessing/least_squares.jl index 8dbb9f3c..1a00f9dd 100644 --- a/src/postprocessing/least_squares.jl +++ b/src/postprocessing/least_squares.jl @@ -1,5 +1,3 @@ -include("b_plane.jl") - @doc raw""" OrbitFit{T <: Real} @@ -112,7 +110,8 @@ end @doc raw""" nrms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} - nrms(res::Vector{OpticalResidual{T}}, fit::OrbitFit{T}) where {T <: Real} + nrms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + nrms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}) where {T <: Real} Returns the normalized root mean square error ```math @@ -137,7 +136,12 @@ function nrms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} return sqrt( chi2(res, w)/length(res) ) end -function nrms(res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}) where {T <: Real, U <: Number} +function nrms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + res_, w = unfold(res) + return nrms(res_, w) +end + +function nrms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}) where {T <: Real} res_, w = unfold(res) return nrms(res_(fit.x), w) end diff --git a/src/postprocessing/neosolution.jl b/src/postprocessing/neosolution.jl new file mode 100644 index 00000000..d2514a4b --- /dev/null +++ b/src/postprocessing/neosolution.jl @@ -0,0 +1,127 @@ +include("b_plane.jl") +include("least_squares.jl") + +@auto_hash_equals struct NEOSolution{T <: Real, U <: Number} + bwd::TaylorInterpolant{T, U, 2} + t_bwd::Vector{U} + x_bwd::Vector{U} + g_bwd::Vector{U} + fwd::TaylorInterpolant{T, U, 2} + t_fwd::Vector{U} + x_fwd::Vector{U} + g_fwd::Vector{U} + res::Vector{OpticalResidual{T, U}} + fit::OrbitFit{T} + function NEOSolution{T, U}(bwd::TaylorInterpolant{T, U, 2}, t_bwd::Vector{U}, x_bwd::Vector{U}, g_bwd::Vector{U}, + fwd::TaylorInterpolant{T, U, 2}, t_fwd::Vector{U}, x_fwd::Vector{U}, g_fwd::Vector{U}, + res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}) where {T <: Real, U <: Number} + @assert bwd.t0 == fwd.t0 "Backward and forward propagation initial times must match" + new{T, U}(bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, res, fit) + end +end + +function NEOSolution(bwd::TaylorInterpolant{T, U, 2}, t_bwd::Vector{U}, x_bwd::Vector{U}, g_bwd::Vector{U}, + fwd::TaylorInterpolant{T, U, 2}, t_fwd::Vector{U}, x_fwd::Vector{U}, g_fwd::Vector{U}, + res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}) where {T <: Real, U <: Number} + NEOSolution{T, U}(bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, res, fit) +end + +function NEOSolution(bwd::TaylorInterpolant{T, U, 2}, fwd::TaylorInterpolant{T, U, 2}, + res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}) where {T <: Real, U <: Number} + # Backward roots + t_bwd = Vector{U}(undef, 0) + x_bwd = Vector{U}(undef, 0) + g_bwd = Vector{U}(undef, 0) + # forward roots + t_fwd = Vector{U}(undef, 0) + x_fwd = Vector{U}(undef, 0) + g_fwd = Vector{U}(undef, 0) + + return NEOSolution{T, U}(bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, res, fit) +end + +# Print method for NEOSolution +# Examples: +# NEO solution with 123 residuals +function show(io::IO, x::NEOSolution{T, U}) where {T <: Real, U <: Number} + print(io, "NEO solution with ", length(x.res), " residuals") +end + +# Evaluation in time method +function (sol::NEOSolution{T, U})(t::V) where {T <: Real, U <: Number, V <: Number} + if t <= sol.bwd.t0 + return sol.bwd(t) + else + return sol.fwd(t) + end +end + +# Evaluation in fit δs method +function evalfit(sol::NEOSolution{T, TaylorN{T}}) where {T <: Real} + # Fit δs + δs = sol.fit.x + # Evaluate backward integration + new_bwd_x = map(x -> Taylor1(x.coeffs(δs)), sol.bwd.x); + new_bwd = TaylorInterpolant{T, T, 2}(sol.bwd.t0, sol.bwd.t, new_bwd_x) + # Evaluate backward roots + new_t_bwd = sol.t_bwd(δs) + new_x_bwd = sol.x_bwd(δs) + new_g_bwd = sol.g_bwd(δs) + # Evaluate forward integration + new_fwd_x = map(x -> Taylor1(x.coeffs(δs)), sol.fwd.x); + new_fwd = TaylorInterpolant{T, T, 2}(sol.fwd.t0, sol.fwd.t, new_fwd_x) + # Evaluate forward roots + new_t_fwd = sol.t_fwd(δs) + new_x_fwd = sol.x_fwd(δs) + new_g_fwd = sol.g_fwd(δs) + # Evaluate residuals + new_res = sol.res(δs) + + return NEOSolution{T, T}(new_bwd, new_t_bwd, new_x_bwd, new_g_bwd, + new_fwd, new_t_fwd, new_x_fwd, new_g_fwd, + new_res, sol.fit) +end + +function zero(::Type{NEOSolution{T, U}}) where {T <: Real, U <: Number} + bwd = TaylorInterpolant{T, U, 2}(zero(T), zeros(T, 1), Matrix{Taylor1{U}}(undef, 0, 0)) + t_bwd = Vector{U}(undef, 0) + x_bwd = Vector{U}(undef, 0) + g_bwd = Vector{U}(undef, 0) + fwd = TaylorInterpolant{T, U, 2}(zero(T), zeros(T, 1), Matrix{Taylor1{U}}(undef, 0, 0)) + t_fwd = Vector{U}(undef, 0) + x_fwd = Vector{U}(undef, 0) + g_fwd = Vector{U}(undef, 0) + res = Vector{OpticalResidual{T, U}}(undef, 0) + fit = OrbitFit{T}(false, Vector{T}(undef, 0), Matrix{T}(undef, 0, 0), :newton) + return NEOSolution{T, U}(bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, + res, fit) +end + +iszero(x::NEOSolution{T, U}) where {T <: Real, U <: Number} = x == zero(NEOSolution{T, U}) + +function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::Int, jd0::T, nyears_bwd::T, + nyears_fwd::T, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], niter::Int = 5, + order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: Real, U <: Number, D} + + # Sun's ephemeris + eph_su = selecteph(sseph, su) + # Earth's ephemeris + eph_ea = selecteph(sseph, ea) + + # Backward integration + bwd = propagate(dynamics, maxsteps, jd0, nyears_bwd, q0; μ_ast = μ_ast, order = order, + abstol = abstol, parse_eqs = parse_eqs) + # Forward integration + fwd = propagate(dynamics, maxsteps, jd0, nyears_fwd, q0; μ_ast = μ_ast, order = order, + abstol = abstol, parse_eqs = parse_eqs) + + # Residuals + res = residuals(radec; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), + xva = et -> bwdfwdeph(et, bwd, fwd)) + # Orbit fit + fit = tryls(res, zeros(get_numvars()), niter) + + # Return NEOs solution + return evalfit(NEOSolution(bwd, fwd, res, fit)) + +end diff --git a/src/propagation/propagation.jl b/src/propagation/propagation.jl index eaf05074..e4db6cc1 100644 --- a/src/propagation/propagation.jl +++ b/src/propagation/propagation.jl @@ -2,10 +2,6 @@ include("asteroid_dynamical_models.jl") include("jetcoeffs.jl") include("serialization.jl") -const V_true = :(Val{true}) -const V_false = :(Val{false}) -const V_true_false = (V_true, V_false) - @doc raw""" rvelea(dx, x, params, t) @@ -109,9 +105,9 @@ function propagate_params(jd0::T, tspan::T, q0::Vector{U}; μ_ast::Vector = μ_a end @doc raw""" - propagate(dynamics::D, maxsteps::Int, jd0::T, tspan::T, q0::Vector{U}, Val(true/false); - μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol, - parse_eqs::Bool = true) where {T <: Real, U <: Number, D} + propagate(dynamics::D, maxsteps::Int, jd0::T, tspan::T, q0::Vector{U}; + μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, + abstol::T = abstol, parse_eqs::Bool = true) where {T <: Real, U <: Number, D} Integrate the orbit of a NEO via the Taylor method. @@ -122,16 +118,35 @@ Integrate the orbit of a NEO via the Taylor method. - `jd0::T`: initial Julian date. - `tspan::T`: time span of the integration [in years]. - `q0::Vector{U}`: vector of initial conditions. -- `Val(true/false)`: whether to output the Taylor polynomials generated at each time step (`true`) or not. - `μ_ast::Vector`: vector of gravitational parameters. - `order::Int=order`: order of the Taylor expansions to be used in the integration. - `abstol::T`: absolute tolerance. - `parse_eqs::Bool`: whether to use the specialized method of `jetcoeffs` (`true`) or not. -""" propagate +""" +function propagate(dynamics::D, maxsteps::Int, jd0::T, tspan::T, q0::Vector{U}; + μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, + abstol::T = abstol, parse_eqs::Bool = true) where {T <: Real, U <: Number, D} + + # Check order + @assert order <= get_order(sseph.x[1]) "order ($(order)) must be less or equal than SS ephemeris order ($(get_order(sseph.x[1])))" + + # Parameters for taylorinteg + _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast = μ_ast, order = order, abstol = abstol) + + # Propagate orbit + + @time tv, xv, psol = taylorinteg(dynamics, _q0, _t0, _tmax, order, abstol, Val(true), _params; + maxsteps = maxsteps, parse_eqs = parse_eqs) + + return TaylorInterpolant(jd0 - JD_J2000, tv .- tv[1], psol) + +end + @doc raw""" - propagate_root(dynamics::D, maxsteps::Int, jd0::T, tspan::T, q0::Vector{U}, Val(true/false); parse_eqs::Bool = true, - eventorder::Int = 0, newtoniter::Int = 10, nrabstol::T = eps(T), μ_ast::Vector = μ_ast343_DE430[1:end], + propagate_root(dynamics::D, maxsteps::Int, jd0::T, tspan::T, q0::Vector{U}; + parse_eqs::Bool = true, eventorder::Int = 0, newtoniter::Int = 10, + nrabstol::T = eps(T), μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number, D} Integrate the orbit of a NEO via the Taylor method while finding the zeros of `rvelea`. @@ -143,7 +158,6 @@ Integrate the orbit of a NEO via the Taylor method while finding the zeros of `r - `jd0::T`: initial Julian date. - `tspan::T`: time span of the integration [in years]. - `q0::Vector{U}`: vector of initial conditions. -- `Val(true/false)`: whether to output the Taylor polynomials generated at each time step (`true`) or not. - `parse_eqs::Bool`: whether to use the specialized method of `jetcoeffs` (`true`) or not. - `eventorder::Int`: order of the derivative of `rvelea` whose roots are computed. - `newtoniter::Int`: maximum Newton-Raphson iterations per detected root. @@ -151,120 +165,24 @@ Integrate the orbit of a NEO via the Taylor method while finding the zeros of `r - `μ_ast::Vector`: vector of gravitational parameters. - `order::Int`: order of the Taylor expansions to be used in the integration. - `abstol::T`: absolute tolerance. -""" propagate_root - -for V_dense in V_true_false - - @eval begin - - function propagate(dynamics::D, maxsteps::Int, jd0::T, tspan::T, q0::Vector{U}, ::$V_dense; - μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol, - parse_eqs::Bool = true) where {T <: Real, U <: Number, D} - - # Check order - @assert order <= get_order(sseph.x[1]) "order ($(order)) must be less or equal than SS ephemeris order ($(get_order(sseph.x[1])))" - - # Parameters for taylorinteg - _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast = μ_ast, order = order, abstol = abstol) - - # Propagate orbit - - @time sol = taylorinteg(dynamics, _q0, _t0, _tmax, order, abstol, $V_dense(), _params; - maxsteps = maxsteps, parse_eqs = parse_eqs) - - # Dense output (save Taylor polynomials in each step) - if $V_dense == Val{true} - tv, xv, psol = sol - return TaylorInterpolant(jd0 - JD_J2000, tv .- tv[1], psol) - # Point output - elseif $V_dense == Val{false} - return sol - end - - end - - function propagate(dynamics::D, maxsteps::Int, jd0::T1, tspan::T2, q0::Vector{U}, ::$V_dense; - μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T3 = abstol, - parse_eqs::Bool = true) where {T1, T2, T3 <: Real, U <: Number, D} - - _jd0, _tspan, _abstol = promote(jd0, tspan, abstol) - - return propagate(dynamics, maxsteps, _jd0, _tspan, q0, $V_dense(); μ_ast = μ_ast, order = order, - abstol = _abstol, parse_eqs = parse_eqs) - end - - function propagate(dynamics::D, maxsteps::Int, jd0::T, nyears_bwd::T, nyears_fwd::T, q0::Vector{U}, ::$V_dense; - μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol, - parse_eqs::Bool = true) where {T <: Real, U <: Number, D} - - # Backward integration - bwd = propagate(dynamics, maxsteps, jd0, nyears_bwd, q0, $V_dense(); μ_ast = μ_ast, order = order, - abstol = abstol, parse_eqs = parse_eqs) - # Forward integration - fwd = propagate(dynamics, maxsteps, jd0, nyears_fwd, q0, $V_dense(); μ_ast = μ_ast, order = order, - abstol = abstol, parse_eqs = parse_eqs) - - return bwd, fwd - - end - - function propagate_root(dynamics::D, maxsteps::Int, jd0::T, tspan::T, q0::Vector{U}, ::$V_dense; parse_eqs::Bool = true, - eventorder::Int = 0, newtoniter::Int = 10, nrabstol::T = eps(T), μ_ast::Vector = μ_ast343_DE430[1:end], - order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number, D} - - # Check order - @assert order <= get_order(sseph.x[1]) "order ($(order)) must be less or equal than SS ephemeris order ($(get_order(sseph.x[1])))" - - # Parameters for neosinteg - _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast = μ_ast, order = order, abstol = abstol) - - # Propagate orbit - @time sol = taylorinteg(dynamics, rvelea, _q0, _t0, _tmax, order, abstol, $V_dense(), _params; - maxsteps, parse_eqs, eventorder, newtoniter, nrabstol) - - - # Dense output (save Taylor polynomials in each step) - if $V_dense == Val{true} - tv, xv, psol, tvS, xvS, gvS = sol - return TaylorInterpolant(jd0 - JD_J2000, tv .- tv[1], psol), tvS, xvS, gvS - # Point output - elseif $V_dense == Val{false} - return sol - end - - return sol - - end - - function propagate_root(dynamics::D, maxsteps::Int, jd0::T1, tspan::T2, q0::Vector{U}, ::$V_dense; parse_eqs::Bool = true, - eventorder::Int = 0, newtoniter::Int = 10, nrabstol::T3 = eps(T), μ_ast::Vector = μ_ast343_DE430[1:end], - order::Int = order, abstol::T4 = abstol) where {T1, T2, T3, T4 <: Real, U <: Number, D} - - _jd0, _tspan, _nrabstol, _abstol = promote(jd0, tspan, nrabstol, abstol) - - return propagate_root(dynamics, maxsteps, _jd0, _tspan, q0, $V_dense(); parse_eqs = parse_eqs, - eventorder = eventorder, newtoniter = newtoniter, nrabstol = _nrabstol, μ_ast = μ_ast, - order = order, abstol = _abstol) - end +""" +function propagate_root(dynamics::D, maxsteps::Int, jd0::T, tspan::T, q0::Vector{U}; + parse_eqs::Bool = true, eventorder::Int = 0, newtoniter::Int = 10, + nrabstol::T = eps(T), μ_ast::Vector = μ_ast343_DE430[1:end], + order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number, D} - function propagate_root(dynamics::D, maxsteps::Int, jd0::T, nyears_bwd::T, nyears_fwd::T, q0::Vector{U}, ::$V_dense; - parse_eqs::Bool = true, eventorder::Int = 0, newtoniter::Int = 10, nrabstol::T = eps(T), - μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number, D} + # Check order + @assert order <= get_order(sseph.x[1]) "order ($(order)) must be less or equal than SS ephemeris order ($(get_order(sseph.x[1])))" - # Backward integration - bwd, tvS_bwd, xvS_bwd, gvS_bwd = propagate_root(dynamics, maxsteps, jd0, nyears_bwd, q0, $V_dense(); parse_eqs = parse_eqs, - eventorder = eventorder, newtoniter = newtoniter, nrabstol = nrabstol, - μ_ast = μ_ast, order = order, abstol = abstol) - # Forward integration - fwd, tvS_fwd, xvS_fwd, gvS_fwd = propagate_root(dynamics, maxsteps, jd0, nyears_fwd, q0, $V_dense(); parse_eqs = parse_eqs, - eventorder = eventorder, newtoniter = newtoniter, nrabstol = nrabstol, - μ_ast = μ_ast, order = order, abstol = abstol) + # Parameters for neosinteg + _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast = μ_ast, order = order, abstol = abstol) - return bwd, tvS_bwd, xvS_bwd, gvS_bwd, fwd, tvS_fwd, xvS_fwd, gvS_fwd + # Propagate orbit + @time tv, xv, psol, tvS, xvS, gvS = taylorinteg(dynamics, rvelea, _q0, _t0, _tmax, order, abstol, val(true), _params; + maxsteps, parse_eqs, eventorder, newtoniter, nrabstol) - end + return TaylorInterpolant(jd0 - JD_J2000, tv .- tv[1], psol), tvS, xvS, gvS - end end @doc raw""" From 043ae2bcd39a36dabb7ff31c640b0076c398d207 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 19 Aug 2023 12:42:14 -0600 Subject: [PATCH 031/173] Minor fix --- src/orbit_determination/gauss_method.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 742a5211..4515ffe8 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -462,7 +462,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max for i in eachindex(sol) # Initial conditions (jet transport) - q0 = sol[i].statevect .+ eph_su(jd0 - J2000) + q0 = sol[i].statevect .+ eph_su(jd0 - PE.J2000) # Propagation bwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_bwd, q0; From aa24c77ff190c4bfd681039ad0efd7d18f933faa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 20 Aug 2023 11:34:58 -0600 Subject: [PATCH 032/173] Equality of OrbitFit --- src/postprocessing/least_squares.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/postprocessing/least_squares.jl b/src/postprocessing/least_squares.jl index 1a00f9dd..25e2fdde 100644 --- a/src/postprocessing/least_squares.jl +++ b/src/postprocessing/least_squares.jl @@ -9,7 +9,7 @@ A least squares fit. - `Γ::Matrix{T}`: covariance matrix. - `routine::Symbol`: minimization routine (`:newton` or `:diffcorr`). """ -struct OrbitFit{T <: Real} +@auto_hash_equals struct OrbitFit{T <: Real} success::Bool x::Vector{T} Γ::Matrix{T} From e73bf7242892a068a85fca7dfca7003f9246c135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Mon, 21 Aug 2023 18:16:27 -0600 Subject: [PATCH 033/173] Adaptative maxsteps --- src/orbit_determination/gauss_method.jl | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 4515ffe8..4aca131b 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -387,8 +387,15 @@ function gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_ite return triplets[1:n] end +function numberofdays(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + # Time difference [ms] + Δ_ms = getfield(date(radec[end]) - date(radec[1]), :value) + # Time difference [days] + return Δ_ms / 86_400_000 +end + @doc raw""" - gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max::T = 100., niter::Int = 5, maxsteps::Int = 100, + gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max::T = 100., niter::Int = 5, varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} Return initial conditions via Gauss method. @@ -400,7 +407,6 @@ See also [`gauss_method`](@ref). - `max_triplets::Int`: maximum number of triplets. - `Q_max::T`: The maximum nrms that is considered a good enough orbit. - `niter::Int`: number of iterations for Newton's method. -- `maxsteps::Int`: maximum number of steps for propagation. - `varorder::Int`: order of jet transport perturbation. - `order::Int`: order of Taylor polynomials w.r.t. time. - `abstol::T`: absolute tolerance. @@ -409,7 +415,7 @@ See also [`gauss_method`](@ref). !!! warning This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. """ -function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max::T = 10., niter::Int = 5, maxsteps::Int = 100, +function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max::T = 10., niter::Int = 5, varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} # Sun's ephemeris @@ -428,6 +434,8 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max t0, tf = datetime2julian(radec[1].date), datetime2julian(radec[end].date) # Julian day when to start propagation jd0 = zero(T) + # Maximum number of steps + maxsteps = ceil(Int, 1.5 * numberofdays(radec)) # Jet transport perturbation (ra/dec) dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃"; order = varorder) @@ -467,10 +475,14 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max # Propagation bwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_bwd, q0; order = order, abstol = abstol, parse_eqs = parse_eqs) + if length(bwd.t) == maxsteps+1 + continue + end + fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_fwd, q0; order = order, abstol = abstol, parse_eqs = parse_eqs) - if length(bwd.t) == maxsteps+1 || length(fwd.t) == maxsteps + 1 + if length(fwd.t) == maxsteps + 1 continue end From f50772e31902a22f484d93c04b1de4572cc131d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 22 Aug 2023 13:37:44 -0600 Subject: [PATCH 034/173] HTTP/JSON for get_radec_mpc --- Project.toml | 2 ++ src/NEOs.jl | 2 +- src/observations/radec_mpc.jl | 31 ++++++++++++++++++++++--------- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/Project.toml b/Project.toml index 0efaf103..5c3ec794 100644 --- a/Project.toml +++ b/Project.toml @@ -19,6 +19,7 @@ Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59" IntervalArithmetic = "d1acc4aa-44c8-5952-acd4-ba5d80a2a253" IntervalRootFinding = "d2bf35a9-74e0-55ec-b149-d360ff49b807" JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" +JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" LazyArtifacts = "4af54fe1-eca0-43a8-85a7-787d91b784e3" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" PlanetaryEphemeris = "d83715d0-7e5f-11e9-1a59-4137b20d8363" @@ -44,6 +45,7 @@ Interpolations = "0.14" IntervalArithmetic = "0.20" IntervalRootFinding = "0.5.11" JLD2 = "0.4" +JSON = "0.21" PlanetaryEphemeris = "0.7" Quadmath = "0.5" SPICE = "0.2" diff --git a/src/NEOs.jl b/src/NEOs.jl index eeab461c..cffa8832 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -11,7 +11,7 @@ import SatelliteToolboxTransformations.sv_ecef_to_ecef import Downloads using Distributed, JLD2, TaylorIntegration, Printf, DelimitedFiles, Test, LinearAlgebra, - Dates, SPICE, Quadmath, LazyArtifacts, TaylorSeries, + Dates, SPICE, Quadmath, LazyArtifacts, TaylorSeries, JSON, InteractiveUtils, AutoHashEquals, Scratch using PlanetaryEphemeris: daysec, su, ea, α_p_sun, δ_p_sun, t2c_jpl_de430, pole_rotation, au, c_au_per_day, R_sun, c_cm_per_sec, c_au_per_sec, yr, RE, TaylorInterpolant, Rx, diff --git a/src/observations/radec_mpc.jl b/src/observations/radec_mpc.jl index 4e6d2d3e..cf51e34b 100644 --- a/src/observations/radec_mpc.jl +++ b/src/observations/radec_mpc.jl @@ -502,15 +502,28 @@ end Download MPC optical astrometry of NEO `id` and save the output to `filename`. """ function get_radec_mpc(id::AbstractString, filename::AbstractString = replace(id, " " => "_") * ".txt") - # MPC search url - search_url = search_mpc_url * replace(id, " " => "+") - # MPC observations file url - obs_url = obs_mpc_url * replace(id, " " => "_") * ".txt" - # Download database search - download(search_url, filename) - # Download observations file - download(obs_url, filename) - return nothing + # HTTP query + resp = get( + "http://minorplanetcenter.net/search_db"; + query = ["table" => "observations", "designation" => id] + ) + # Converty to String + text = String(resp.body) + # Parse JSON + obs = JSON.parse(text) + # Find matches + matches = Vector{RegexMatch}(undef, length(obs)) + for i in eachindex(obs) + s = obs[i]["original_record"] + matches[i] = match(mpc_radec_regex, s) + end + filter!(!isnothing, matches) + # Parse RadecMPC + radec = RadecMPC.(matches) + # Write observations to file + write_radec_mpc(radec, filename) + + return radec end # Methods to convert a Vector{<:AbstractAstrometry} to a DataFrame From 6314e5e7588a71415089af0fefb3740d6b67565f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 23 Aug 2023 07:25:33 -0600 Subject: [PATCH 035/173] Fix get_radec_mpc --- src/observations/radec_mpc.jl | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/observations/radec_mpc.jl b/src/observations/radec_mpc.jl index cf51e34b..6cd93cee 100644 --- a/src/observations/radec_mpc.jl +++ b/src/observations/radec_mpc.jl @@ -497,16 +497,14 @@ function write_radec_mpc(obs::Vector{RadecMPC{T}}, filename::String) where {T <: end @doc raw""" - get_radec_mpc(id::AbstractString, filename::AbstractString) + get_radec_mpc(id::Pair{String, String}, filename::String = replace(id[2], " " => "_") * ".txt") Download MPC optical astrometry of NEO `id` and save the output to `filename`. """ -function get_radec_mpc(id::AbstractString, filename::AbstractString = replace(id, " " => "_") * ".txt") +function get_radec_mpc(id::Pair{String, String}, filename::String = replace(id[2], " " => "_") * ".txt") # HTTP query - resp = get( - "http://minorplanetcenter.net/search_db"; - query = ["table" => "observations", "designation" => id] - ) + query = ["table" => "observations", id] + resp = get("http://minorplanetcenter.net/search_db"; query = query) # Converty to String text = String(resp.body) # Parse JSON @@ -523,7 +521,7 @@ function get_radec_mpc(id::AbstractString, filename::AbstractString = replace(id # Write observations to file write_radec_mpc(radec, filename) - return radec + return filename end # Methods to convert a Vector{<:AbstractAstrometry} to a DataFrame From 95c232da551ad0bd8244ec4e60d6a780f11ccf25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 25 Aug 2023 16:56:28 -0600 Subject: [PATCH 036/173] Fix adaptative maxsteps --- src/orbit_determination/gauss_method.jl | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 4aca131b..5b94f681 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -387,11 +387,17 @@ function gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_ite return triplets[1:n] end -function numberofdays(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} +function adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} # Time difference [ms] Δ_ms = getfield(date(radec[end]) - date(radec[1]), :value) # Time difference [days] - return Δ_ms / 86_400_000 + Δ_day = Δ_ms / 86_400_000 + # Adaptative maxsteps + if Δ_day <= 6 + return ceil(Int, 5*Δ_day) + else + return ceil(Int, Δ_day/2 + 27) + end end @doc raw""" @@ -435,7 +441,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max # Julian day when to start propagation jd0 = zero(T) # Maximum number of steps - maxsteps = ceil(Int, 1.5 * numberofdays(radec)) + maxsteps = adaptative_maxsteps(radec) # Jet transport perturbation (ra/dec) dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃"; order = varorder) From 9c995c94c19b4cc98870a4dea13f206a1f812ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Mon, 28 Aug 2023 08:23:28 -0600 Subject: [PATCH 037/173] Fix ra discontinuity --- src/observations/process_radec.jl | 98 +++---- src/orbit_determination/gauss_method.jl | 323 ++++++++++++++---------- src/postprocessing/least_squares.jl | 4 +- 3 files changed, 247 insertions(+), 178 deletions(-) diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index 73562a4d..ff48223c 100644 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -446,6 +446,19 @@ function w8sveres17(obs::RadecMPC{T}) where {T <: AbstractFloat} end end +function anglediff(x::T, y::S) where {T, S <: Number} + # Signed difference + Δ = x - y + # Absolute difference + Δ_abs = abs(Δ) + # Reflection + if Δ_abs > 648_000 # Half circle in arcsec + return -sign(cte(Δ)) * (1_296_000 - Δ_abs) + else + return Δ + end +end + @doc raw""" radec_astrometry(obs::Vector{RadecMPC{T}}; niter::Int = 5, debias_table::String = "2018", xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph) where {T <: AbstractFloat, SunEph, EarthEph, AstEph} @@ -470,13 +483,13 @@ See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and - `xvs`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xva`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ -function radec_astrometry(obs::Vector{RadecMPC{T}}; debias_table::String = "2018", xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} +function residuals(obs::Vector{RadecMPC{T}}; debias_table::String = "2018", xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} # Number of observations - n_optical_obs = length(obs) + N_obs = length(obs) # UTC time of first astrometric observation - utc1 = obs[1].date + utc1 = date(obs[1]) # TDB seconds since J2000.0 for first astrometric observation et1 = datetime2et(utc1) # Asteroid ephemeris at et1 @@ -484,56 +497,45 @@ function radec_astrometry(obs::Vector{RadecMPC{T}}; debias_table::String = "2018 # Type of asteroid ephemeris S = typeof(a1_et1) - # Observed right ascension - α_obs = Array{Float64}(undef, n_optical_obs) - # Observed declination - δ_obs = Array{Float64}(undef, n_optical_obs) - - # Computed right ascension - α_comp = Array{S}(undef, n_optical_obs) - # Computed declination - δ_comp = Array{S}(undef, n_optical_obs) - - # Total debiasing correction in right ascension (arcsec) - α_corr = Array{Float64}(undef, n_optical_obs) - # Total debiasing correction in declination (arcsec) - δ_corr = Array{Float64}(undef, n_optical_obs) - - # Times of observations - datetime_obs = Array{DateTime}(undef, n_optical_obs) - # Statistical weights - w8s = Array{Float64}(undef, n_optical_obs) - # Select debias table mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) - # Iterate over the observations - Threads.@threads for i in 1:n_optical_obs + # Relax factors + rex = relax_factor(obs) + + # Vector of residuals + res = Vector{OpticalResidual{T, S}}(undef, N_obs) - # Time of observation - datetime_obs[i] = obs[i].date + # Iterate over the observations + Threads.@threads for i in 1:N_obs # Observed ra/dec - # Note: ra is multiplied by a metric factor cos(dec) to match the format of debiasing corrections - δ_obs[i] = rad2arcsec(obs[i].δ) # arcsec - α_obs[i] = rad2arcsec(obs[i].α) * cos(obs[i].δ) # arcsec + α_obs = rad2arcsec(ra(obs[i])) # arcsec + δ_obs = rad2arcsec(dec(obs[i])) # arcsec # Computed ra/dec - α_comp_as, δ_comp_as = compute_radec(obs[i]; xva, kwargs...) - # Multiply by metric factor cos(dec) - α_comp[i] = α_comp_as * cos(obs[i].δ) # arcsec - δ_comp[i] = δ_comp_as # arcsec + α_comp, δ_comp = compute_radec(obs[i]; xva, kwargs...) # arcsec # Debiasing corrections - α_corr[i], δ_corr[i] = debiasing(obs[i], mpc_catalogue_codes_201X, truth, resol, bias_matrix) + α_corr, δ_corr = debiasing(obs[i], mpc_catalogue_codes_201X, truth, resol, bias_matrix) # Statistical weights from Veres et al. (2017) - w8s[i] = w8sveres17(obs[i]) + w8 = w8sveres17(obs[i]) + + # O-C residual ra/dec + # Note: ra is multiplied by a metric factor cos(dec) to match the format of debiasing corrections + res[i] = OpticalResidual( + anglediff(α_obs, α_comp) * cos(δ_obs) - α_corr, + δ_obs - δ_comp - δ_corr, + 1 / w8^2, + 1 / w8^2, + rex[i], + false + ) end - # Return time of observation, observed ra/dec, computed ra/dec, total debiasing correction in ra/dec and statistical weights - return datetime_obs, α_obs, δ_obs, α_comp, δ_comp, α_corr, δ_corr, w8s + return res end @@ -583,11 +585,12 @@ See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and - `xve::SunEph`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xva::AstEph`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ +#= function residuals(obs::Vector{RadecMPC{T}}; kwargs...) where {T <: AbstractFloat} # Optical astrometry (dates + observed + computed + debiasing + weights) x_jt = radec_astrometry(obs; kwargs...) # Right ascension residuals - res_α = x_jt[2] .- x_jt[6] .- x_jt[4] + res_α = x_jt[4] .- x_jt[6] # .- x_jt[4] # Declination residuals res_δ = x_jt[3] .- x_jt[7] .- x_jt[5] # Relax factors @@ -595,7 +598,7 @@ function residuals(obs::Vector{RadecMPC{T}}; kwargs...) where {T <: AbstractFloa # Total residuals return OpticalResidual.(res_α, res_δ, 1 ./ x_jt[end].^2, 1 ./ x_jt[end].^2, rex, false) end - +=# @doc raw""" extrapolation(x::AbstractVector{T}, y::AbstractVector{T}) where {T <: Real} @@ -631,11 +634,20 @@ function extrapolation(df::AbstractDataFrame) t_mean = sum(t_rel) / length(t_rel) # Extrapolate - α_p = extrapolation(t_rel, df.α) + if issorted(df.α) || issorted(df.α, rev = true) + α_p = extrapolation(t_rel, df.α) + elseif df.α[1] > π && df.α[end] < π + α = map(x -> x < π ? x + 2π : x, df.α) + α_p = extrapolation(t_rel, α) + elseif df.α[1] < π && df.α[end] > π + α = map(x -> x > π ? x - 2π : x, df.α) + α_p = extrapolation(t_rel, α) + end δ_p = extrapolation(t_rel, df.δ) + # Evaluate polynomials at mean date - α_mean = α_p(t_mean) - δ_mean = δ_p(t_mean) + α_mean = mod2pi(α_p(t_mean)) + δ_mean = mod2pi(δ_p(t_mean)) return (observatory = df.observatory[1], date = julian2datetime(t_julian[1] + t_mean), α = α_mean, δ = δ_mean) end diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 5b94f681..542c8393 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -387,16 +387,190 @@ function gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_ite return triplets[1:n] end +function numberofdays(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + t0 = date(radec[1]) + tf = date(radec[end]) + Δ = (tf - t0).value / 86_400_000 + return Δ +end + function adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} # Time difference [ms] Δ_ms = getfield(date(radec[end]) - date(radec[1]), :value) # Time difference [days] Δ_day = Δ_ms / 86_400_000 # Adaptative maxsteps - if Δ_day <= 6 - return ceil(Int, 5*Δ_day) - else - return ceil(Int, Δ_day/2 + 27) + return 30 + ceil(Int, Δ_day/4) +end + +for i in 1:2 + @eval begin + function _gaussinitcond(radec::Vector{RadecMPC{T}}, max_triplets::Int, Q_max::T, niter::Int, varorder::Int, order::Int, + abstol::T, parse_eqs::Bool, ::Val{$i}) where {T <: AbstractFloat} + + # Allocate memory for initial conditions + best_sol = zero(NEOSolution{T, T}) + + if $i == 1 + # Reduce nights by interpolation + observatories, dates, α, δ, gdf = reduce_nights(radec) + elseif $i == 2 + # Use plain observations + observatories, dates, α, δ = observatory.(radec), date.(radec), ra.(radec), dec.(radec) + end + + # Cannot process less than 3 nights / observations + if length(dates) < 3 + return best_sol + end + # Observations triplets + triplets = gauss_triplets(dates, max_triplets) + # Julian day of first (last) observation + t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) + # Julian day when to start propagation + jd0 = zero(T) + # Maximum number of steps + maxsteps = adaptative_maxsteps(radec) + # Jet transport perturbation (ra/dec) + dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃"; order = varorder) + # Sun's ephemeris + eph_su = selecteph(sseph, su) + # Earth's ephemeris + eph_ea = selecteph(sseph, ea) + # Normalized root mean square error (NRMS) + best_Q = T(Inf) + # Break flag + flag = false + + # Iterate over triplets + for j in eachindex(triplets) + + # Current triplet + triplet = triplets[j] + # Julian day when to start propagation + jd0 = datetime2julian(dates[triplet[2]]) + # Number of years in forward integration + nyears_fwd = (tf - jd0 + 2) / yr + # Number of years in backward integration + nyears_bwd = -(jd0 - t0 + 2) / yr + # Gauss method solution + sol = gauss_method(observatories[triplet], dates[triplet], α[triplet] .+ dq[1:3], δ[triplet] .+ dq[4:6]; niter = niter) + # Filter Gauss solutions by heliocentric energy + filter!(x -> heliocentric_energy(x.statevect) <= 0, sol) + + # Iterate over Gauss solutions + for i in eachindex(sol) + + # Initial conditions (jet transport) + q0 = sol[i].statevect .+ eph_su(jd0 - PE.J2000) + # Backward propagation + bwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_bwd, q0; + order = order, abstol = abstol, parse_eqs = parse_eqs) + if length(bwd.t) == maxsteps + 1 + continue + end + # Forward propagation + fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_fwd, q0; + order = order, abstol = abstol, parse_eqs = parse_eqs) + if length(fwd.t) == maxsteps + 1 + continue + end + # O-C residuals + res = residuals(radec; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), + xva = et -> bwdfwdeph(et, bwd, fwd)) + + # Subset of radec for orbit fit + if $i == 1 + idxs = findall(x -> triplet[1] <= x <= triplet[3], gdf.groups) + elseif $i == 2 + # Subset of radec for orbit fit + idxs = findall(x -> dates[triplet[1]] <= x <= dates[triplet[3]], dates) + end + sort!(idxs) + # Orbit fit + fit = tryls(res[idxs], zeros(get_numvars()), niter) + !fit.success && continue + + if $i == 1 + # Right iteration + for k in triplet[3]+1:length(gdf) + extra = findall(x -> x == k, gdf.groups) + fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) + if fit_new.success + fit = fit_new + idxs = vcat(idxs, extra) + sort!(idxs) + else + break + end + end + + # Left iteration + for k in triplet[1]-1:-1:1 + extra = findall(x -> x == k, gdf.groups) + fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) + if fit_new.success + fit = fit_new + idxs = vcat(idxs, extra) + sort!(idxs) + else + break + end + end + elseif $i == 2 + # Right iteration + for k in triplet[3]+1:length(dates) + fit_new = tryls(res[idxs ∪ k], zeros(get_numvars()), niter) + if fit_new.success + fit = fit_new + idxs = vcat(idxs, k) + sort!(idxs) + else + break + end + end + + # Left iteration + for k in triplet[1]-1:-1:1 + fit_new = tryls(res[idxs ∪ k], zeros(get_numvars()), niter) + if fit_new.success + fit = fit_new + idxs = vcat(idxs, k) + sort!(idxs) + else + break + end + end + end + + # NRMS + Q = nrms(res, fit) + + # TO DO: check cases where newton converges but diffcorr no + # Update NRMS and initial conditions + if Q < best_Q + best_Q = Q + best_sol = evalfit(NEOSolution(bwd, fwd, res[idxs], fit)) + end + # Break condition + if Q <= Q_max + flag = true + break + end + end + if flag + break + end + end + + # Case: all solutions were unsuccesful + if isinf(best_Q) + return zero(NEOSolution{T, T}) + # Case: at least one solution was succesful + else + return best_sol + end + end end end @@ -424,138 +598,21 @@ See also [`gauss_method`](@ref). function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max::T = 10., niter::Int = 5, varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} - # Sun's ephemeris - eph_su = selecteph(sseph, su) - # Earth's ephemeris - eph_ea = selecteph(sseph, ea) - # Eliminate observatories without coordinates - filter!(x -> hascoord(x.observatory), radec) - # Reduce nights by interpolation - observatories, dates, α, δ, gdf = reduce_nights(radec) - # Observations triplets - triplets = gauss_triplets(dates, max_triplets) - - # Julian day of first (last) observation - t0, tf = datetime2julian(radec[1].date), datetime2julian(radec[end].date) - # Julian day when to start propagation - jd0 = zero(T) - # Maximum number of steps - maxsteps = adaptative_maxsteps(radec) - - # Jet transport perturbation (ra/dec) - dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃"; order = varorder) - - # Normalized root mean square error (NRMS) - best_Q = T(Inf) - # Initial conditions - best_sol = zero(NEOSolution{T, T}) - # Break flag - flag = false - - # Iterate over triplets - for j in eachindex(triplets) - - # Current triplet - triplet = triplets[j] - - # Julian day when to start propagation - jd0 = datetime2julian(dates[triplet[2]]) - # Number of years in forward integration - nyears_fwd = (tf - jd0 + 2) / yr - # Number of years in backward integration - nyears_bwd = -(jd0 - t0 + 2) / yr - - # Gauss method solution - sol = gauss_method(observatories[triplet], dates[triplet], α[triplet] .+ dq[1:3], δ[triplet] .+ dq[4:6]; niter = niter) - - # Filter Gauss solutions by heliocentric energy - filter!(x -> heliocentric_energy(x.statevect) <= 0, sol) - - # Iterate over Gauss solutions - for i in eachindex(sol) - - # Initial conditions (jet transport) - q0 = sol[i].statevect .+ eph_su(jd0 - PE.J2000) - - # Propagation - bwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_bwd, q0; - order = order, abstol = abstol, parse_eqs = parse_eqs) - if length(bwd.t) == maxsteps+1 - continue - end - - fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_fwd, q0; - order = order, abstol = abstol, parse_eqs = parse_eqs) + filter!(x -> hascoord(observatory(x)), radec) - if length(fwd.t) == maxsteps + 1 - continue - end - - # O-C residuals - res = residuals(radec; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), - xva = et -> bwdfwdeph(et, bwd, fwd)) - - # Subset of radec for orbit fit - idxs = findall(x -> triplet[1] <= x <= triplet[3], gdf.groups) - sort!(idxs) - - # Orbit fit - fit = tryls(res[idxs], zeros(get_numvars()), niter) - - !fit.success && continue - - # Right iteration - for k in triplet[3]+1:length(gdf) - extra = findall(x -> x == k, gdf.groups) - fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) - if fit_new.success - fit = fit_new - idxs = vcat(idxs, extra) - sort!(idxs) - else - break - end - end - - # Left iteration - for k in triplet[1]-1:-1:1 - extra = findall(x -> x == k, gdf.groups) - fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) - if fit_new.success - fit = fit_new - idxs = vcat(idxs, extra) - sort!(idxs) - else - break - end - end - - # NRMS - Q = nrms(res, fit) - - # TO DO: check cases where newton converges but diffcorr no - # Update NRMS and initial conditions - if Q < best_Q - best_Q = Q - best_sol = evalfit(NEOSolution(bwd, fwd, res, fit)) - end - # Break condition - if Q <= Q_max - flag = true - break - end - end - if flag - break + best_sol_1 = _gaussinitcond(radec, max_triplets, Q_max, niter, varorder, order, abstol, parse_eqs, Val(1)) + Q_1 = nrms(best_sol_1.res) + + if Q_1 > Q_max && numberofdays(radec) <= 3 + best_sol_2 = _gaussinitcond(radec, max_triplets, Q_max, niter, varorder, order, abstol, parse_eqs, Val(2)) + Q_2 = nrms(best_sol_2.res) + if Q_2 < Q_1 + return best_sol_2 + else + return best_sol_1 end - end - - # Case: all solutions were unsuccesful - if isinf(best_Q) - return zero(NEOSolution{T, T}) - # Case: at least one solution was succesful else - return best_sol + return best_sol_1 end end \ No newline at end of file diff --git a/src/postprocessing/least_squares.jl b/src/postprocessing/least_squares.jl index 25e2fdde..42f58ff1 100644 --- a/src/postprocessing/least_squares.jl +++ b/src/postprocessing/least_squares.jl @@ -56,7 +56,7 @@ Outlier rejection algorithm. !!! reference See https://doi.org/10.1016/S0019-1035(03)00051-4. """ -function outlier_rejection(ξs::Vector{OpticalResidual{T}}, fit::OrbitFit{T}; χ2_rec::T = 7., χ2_rej::T = 8., +function outlier_rejection(ξs::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}; χ2_rec::T = 7., χ2_rej::T = 8., α::T = 0.25) where {T <: Real} # Number of residuals N = length(ξs) @@ -79,7 +79,7 @@ function outlier_rejection(ξs::Vector{OpticalResidual{T}}, fit::OrbitFit{T}; χ end χ2_max = maximum(χ2s) - new_ξs = Vector{OpticalResidual{T}}(undef, N) + new_ξs = Vector{OpticalResidual{T, TaylorN{T}}}(undef, N) N_sel = count(x -> !x.outlier, ξs) for i in eachindex(χ2s) From bfcc9def5e507a3f4ec13715de87331def9a3623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Mon, 28 Aug 2023 08:51:12 -0600 Subject: [PATCH 038/173] Softer _gaussinitcond Val(2) condition --- src/orbit_determination/gauss_method.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 542c8393..56b1d882 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -604,7 +604,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max best_sol_1 = _gaussinitcond(radec, max_triplets, Q_max, niter, varorder, order, abstol, parse_eqs, Val(1)) Q_1 = nrms(best_sol_1.res) - if Q_1 > Q_max && numberofdays(radec) <= 3 + if Q_1 > Q_max best_sol_2 = _gaussinitcond(radec, max_triplets, Q_max, niter, varorder, order, abstol, parse_eqs, Val(2)) Q_2 = nrms(best_sol_2.res) if Q_2 < Q_1 From 6daf1c8dacf2d4e6e5cb9531af171012e3bf6e93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 29 Aug 2023 18:38:38 -0600 Subject: [PATCH 039/173] Fix unfold and nrms --- src/observations/process_radec.jl | 17 ++++++++++++++--- src/orbit_determination/gauss_method.jl | 6 +++--- src/postprocessing/neosolution.jl | 8 ++++++++ 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index ff48223c..6d5cbd3a 100644 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -59,9 +59,18 @@ end Concatenate right ascension and declination residuals for an orbit fit. """ function unfold(ξs::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} - res = vcat(getfield.(ξs, :ξ_α), getfield.(ξs, :ξ_δ)) - relax_factor = getfield.(ξs, :relax_factor) - w = vcat(getfield.(ξs, :w_α) ./ relax_factor, getfield.(ξs, :w_δ) ./ relax_factor) + L = length(ξs) + + res = Vector{U}(undef, 2*L) + w = Vector{T}(undef, 2*L) + + for i in eachindex(ξs) + res[i] = ξs[i].ξ_α + res[i+L] = ξs[i].ξ_δ + w[i] = ξs[i].w_α / ξs[i].relax_factor + w[i+L] = ξs[i].w_δ / ξs[i].relax_factor + end + return res, w end @@ -633,6 +642,8 @@ function extrapolation(df::AbstractDataFrame) # Mean date t_mean = sum(t_rel) / length(t_rel) + α_p = extrapolation([0., 1.], [0., 1.]) + # Extrapolate if issorted(df.α) || issorted(df.α, rev = true) α_p = extrapolation(t_rel, df.α) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 56b1d882..ffb74898 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -602,11 +602,11 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max filter!(x -> hascoord(observatory(x)), radec) best_sol_1 = _gaussinitcond(radec, max_triplets, Q_max, niter, varorder, order, abstol, parse_eqs, Val(1)) - Q_1 = nrms(best_sol_1.res) - + Q_1 = nrms(best_sol_1) + if Q_1 > Q_max best_sol_2 = _gaussinitcond(radec, max_triplets, Q_max, niter, varorder, order, abstol, parse_eqs, Val(2)) - Q_2 = nrms(best_sol_2.res) + Q_2 = nrms(best_sol_2) if Q_2 < Q_1 return best_sol_2 else diff --git a/src/postprocessing/neosolution.jl b/src/postprocessing/neosolution.jl index d2514a4b..4998b68d 100644 --- a/src/postprocessing/neosolution.jl +++ b/src/postprocessing/neosolution.jl @@ -125,3 +125,11 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::I return evalfit(NEOSolution(bwd, fwd, res, fit)) end + +function nrms(sol::NEOSolution{T, T}) where {T <: Real} + if iszero(sol) + return T(Inf) + else + return nrms(sol.res) + end +end \ No newline at end of file From 1a195cc96bc4531c82876dac1c74145ec33f3269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 2 Sep 2023 11:16:20 -0600 Subject: [PATCH 040/173] Fix Val(2) _gaussinitcond --- src/observations/process_radec.jl | 101 ++++++++---------------- src/orbit_determination/gauss_method.jl | 83 +++++++------------ src/postprocessing/least_squares.jl | 46 +++++------ 3 files changed, 84 insertions(+), 146 deletions(-) diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index 6d5cbd3a..f783a2e3 100644 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -455,6 +455,29 @@ function w8sveres17(obs::RadecMPC{T}) where {T <: AbstractFloat} end end +@doc raw""" + relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + +Return a relax factor for each element of `radec` quantifying the correlation between observations taken on +the same night by the same observatory. + +!!! reference + See https://doi.org/10.1016/j.icarus.2017.05.021. +""" +function relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + # Convert to DataFrame + df = DataFrame(radec) + # Group by observatory and TimeOfDay + df.TimeOfDay = TimeOfDay.(df.date, df.observatory) + gdf = groupby(df, [:observatory, :TimeOfDay]) + # Interpolate observation nights + cdf = combine(gdf, nrow) + # Count observations in each group + Nv = cdf[gdf.groups, :nrow] + # Relaxation factor + return map(x -> x > 4.0 ? x/4.0 : 1.0, Nv) +end + function anglediff(x::T, y::S) where {T, S <: Number} # Signed difference Δ = x - y @@ -469,11 +492,9 @@ function anglediff(x::T, y::S) where {T, S <: Number} end @doc raw""" - radec_astrometry(obs::Vector{RadecMPC{T}}; niter::Int = 5, debias_table::String = "2018", - xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph) where {T <: AbstractFloat, SunEph, EarthEph, AstEph} + residuals(obs::Vector{RadecMPC{T}}; debias_table::String = "2018", xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} -Compute optical astrometry, i.e. dates of observation plus observed, computed, debiasing corrections and statistical weights for -right ascension and declination (in arcsec). Corrections to Earth orientation parameters provided by IERS are computed by default. +Compute O-C residuals for optical astrometry. Corrections due to Earth orientation, LOD, polar motion are computed by default. See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and [`Healpix.ang2pixRing`](@ref). @@ -493,6 +514,11 @@ See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and - `xva`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ function residuals(obs::Vector{RadecMPC{T}}; debias_table::String = "2018", xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} + mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) + return residuals(obs, mpc_catalogue_codes_201X, truth, resol, bias_matrix; xva, kwargs...) +end +function residuals(obs::Vector{RadecMPC{T}}, mpc_catalogue_codes_201X::Vector{String}, truth::String, resol::Resolution, + bias_matrix::Matrix{T}; xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} # Number of observations N_obs = length(obs) @@ -506,9 +532,6 @@ function residuals(obs::Vector{RadecMPC{T}}; debias_table::String = "2018", xva: # Type of asteroid ephemeris S = typeof(a1_et1) - # Select debias table - mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) - # Relax factors rex = relax_factor(obs) @@ -547,68 +570,6 @@ function residuals(obs::Vector{RadecMPC{T}}; debias_table::String = "2018", xva: return res end - -@doc raw""" - relax_factor(radec::Vector{RadecMPC{T}}) where {T <: Real} - -Return a relax factor for each element of `radec` quantifying the correlation between observations taken on -the same night by the same observatory. - -!!! reference - See https://doi.org/10.1016/j.icarus.2017.05.021. -""" -function relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - # Convert to DataFrame - df = DataFrame(radec) - # Group by observatory and TimeOfDay - df.TimeOfDay = TimeOfDay.(df.date, df.observatory) - gdf = groupby(df, [:observatory, :TimeOfDay]) - # Interpolate observation nights - cdf = combine(gdf, nrow) - # Count observations in each group - Nv = cdf[gdf.groups, :nrow] - # Relaxation factor - return map(x -> x > 4.0 ? x/4.0 : 1.0, Nv) -end - -@doc raw""" - residuals(obs::Vector{RadecMPC{T}}; niter::Int = 5, debias_table::String = "2018", - xvs::SunEph = sunposvel, xve::EarthEph = earthposvel, xva::AstEph) where {T <: AbstractFloat, SunEph, EarthEph, AstEph} - -Compute O-C residuals for optical astrometry. Corrections due to Earth orientation, LOD, polar motion are computed by default. - -See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and [`radec_astrometry`](@ref). - -# Arguments - -- `obs::Vector{RadecMPC{T}}`: vector of observations. - -# Keyword arguments - -- `niter::Int`: number of light-time solution iterations. -- `debias_table::String`: possible values are: - - `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, - - `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, - - `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. -- `xvs::EarthEph`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xve::SunEph`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xva::AstEph`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -""" -#= -function residuals(obs::Vector{RadecMPC{T}}; kwargs...) where {T <: AbstractFloat} - # Optical astrometry (dates + observed + computed + debiasing + weights) - x_jt = radec_astrometry(obs; kwargs...) - # Right ascension residuals - res_α = x_jt[4] .- x_jt[6] # .- x_jt[4] - # Declination residuals - res_δ = x_jt[3] .- x_jt[7] .- x_jt[5] - # Relax factors - rex = relax_factor(obs) - # Total residuals - return OpticalResidual.(res_α, res_δ, 1 ./ x_jt[end].^2, 1 ./ x_jt[end].^2, rex, false) -end -=# - @doc raw""" extrapolation(x::AbstractVector{T}, y::AbstractVector{T}) where {T <: Real} @@ -684,5 +645,5 @@ function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} # Sort by date idxs = sortperm(cdf, :date) - return cdf.observatory[idxs], cdf.date[idxs], cdf.α[idxs], cdf.δ[idxs], gdf[idxs] + return gdf[idxs], cdf[idxs, :] end \ No newline at end of file diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index ffb74898..e25ff0e3 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -410,15 +410,14 @@ for i in 1:2 # Allocate memory for initial conditions best_sol = zero(NEOSolution{T, T}) - + # Reduce nights by interpolation + gdf, cdf = reduce_nights(radec) if $i == 1 - # Reduce nights by interpolation - observatories, dates, α, δ, gdf = reduce_nights(radec) + observatories, dates, α, δ = cdf.observatory, cdf.date, cdf.α, cdf.δ elseif $i == 2 # Use plain observations observatories, dates, α, δ = observatory.(radec), date.(radec), ra.(radec), dec.(radec) end - # Cannot process less than 3 nights / observations if length(dates) < 3 return best_sol @@ -481,65 +480,41 @@ for i in 1:2 # Subset of radec for orbit fit if $i == 1 - idxs = findall(x -> triplet[1] <= x <= triplet[3], gdf.groups) + g_0 = triplet[1] + g_f = triplet[3] elseif $i == 2 - # Subset of radec for orbit fit - idxs = findall(x -> dates[triplet[1]] <= x <= dates[triplet[3]], dates) + g_0 = gdf.groups[triplet[1]] + g_f = gdf.groups[triplet[3]] end + idxs = findall(x -> g_0 <= x <= g_f, gdf.groups) sort!(idxs) # Orbit fit fit = tryls(res[idxs], zeros(get_numvars()), niter) !fit.success && continue - if $i == 1 - # Right iteration - for k in triplet[3]+1:length(gdf) - extra = findall(x -> x == k, gdf.groups) - fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) - if fit_new.success - fit = fit_new - idxs = vcat(idxs, extra) - sort!(idxs) - else - break - end - end - - # Left iteration - for k in triplet[1]-1:-1:1 - extra = findall(x -> x == k, gdf.groups) - fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) - if fit_new.success - fit = fit_new - idxs = vcat(idxs, extra) - sort!(idxs) - else - break - end - end - elseif $i == 2 - # Right iteration - for k in triplet[3]+1:length(dates) - fit_new = tryls(res[idxs ∪ k], zeros(get_numvars()), niter) - if fit_new.success - fit = fit_new - idxs = vcat(idxs, k) - sort!(idxs) - else - break - end + # Right iteration + for k in g_f+1:length(gdf) + extra = findall(x -> x == k, gdf.groups) + fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) + if fit_new.success + fit = fit_new + idxs = vcat(idxs, extra) + sort!(idxs) + else + break end + end - # Left iteration - for k in triplet[1]-1:-1:1 - fit_new = tryls(res[idxs ∪ k], zeros(get_numvars()), niter) - if fit_new.success - fit = fit_new - idxs = vcat(idxs, k) - sort!(idxs) - else - break - end + # Left iteration + for k in g_0-1:-1:1 + extra = findall(x -> x == k, gdf.groups) + fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) + if fit_new.success + fit = fit_new + idxs = vcat(idxs, extra) + sort!(idxs) + else + break end end diff --git a/src/postprocessing/least_squares.jl b/src/postprocessing/least_squares.jl index 42f58ff1..f6fd0143 100644 --- a/src/postprocessing/least_squares.jl +++ b/src/postprocessing/least_squares.jl @@ -108,6 +108,30 @@ function project(y::Vector{TaylorN{T}}, fit::OrbitFit{T}) where {T <: Real} return (J') * fit.Γ * J end +@doc raw""" + chi2(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} + +Returns the chi square +```math +\chi^2 = \sum_{i=1}^m \frac{ \xi_i^2}{\sigma_i^2}, +``` +where ``\mathbf{w} = (1/\sigma_1^2,\ldots,1/\sigma_m^2)^T`` and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` +are the vectors of weights and residuals respectively. + +# Arguments + +- `res::Vector{U}`: Vector of residuals. +- `w::Vector{T}`: Vector of weights. +""" +function chi2(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} + # Have as many residuals as weights + @assert length(res) == length(w) + # Chi square + return sum(w .* (res.^2)) +end + +nms(res, w) = chi2(res, w) / length(res) + @doc raw""" nrms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} nrms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} @@ -146,28 +170,6 @@ function nrms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}) whe return nrms(res_(fit.x), w) end -@doc raw""" - chi2(res, w) - -Returns the chi square -```math -\chi^2 = \sum_{i=1}^m \frac{ \xi_i^2}{\sigma_i^2}, -``` -where ``\mathbf{w} = (1/\sigma_1^2,\ldots,1/\sigma_m^2)^T`` and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` -are the vectors of weights and residuals respectively. - -# Arguments - -- `res`: Vector of residuals. -- `w`: Vector of weights. -""" -function chi2(res, w) - # Have as many residuals as weights - @assert length(res) == length(w) - # Chi square - return sum(w .* (res.^2)) -end - @doc raw""" BHC(res, w, npar) From 4a4e323b6862ad8116aac71e8020cb422541f6a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 2 Sep 2023 11:37:33 -0600 Subject: [PATCH 041/173] New adaptative maxsteps --- src/orbit_determination/gauss_method.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index e25ff0e3..d1c92107 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -400,7 +400,7 @@ function adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFlo # Time difference [days] Δ_day = Δ_ms / 86_400_000 # Adaptative maxsteps - return 30 + ceil(Int, Δ_day/4) + return 35 + ceil(Int, 5*Δ_day/160) end for i in 1:2 From 326d79c51e20285a87a98f8a6d76eaf9e2ced550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 3 Sep 2023 16:12:07 -0600 Subject: [PATCH 042/173] Yet another adaptative maxsteps --- src/orbit_determination/gauss_method.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index d1c92107..2d8f3a53 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -400,7 +400,11 @@ function adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFlo # Time difference [days] Δ_day = Δ_ms / 86_400_000 # Adaptative maxsteps - return 35 + ceil(Int, 5*Δ_day/160) + if Δ_day <= 30 + return ceil(Int, -7*Δ_day/3) + 100 + else + return ceil(Int, (Δ_day + 360)/13) + end end for i in 1:2 From b24c9afddca9db43994b82feba952451193dfa0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 3 Sep 2023 16:35:42 -0600 Subject: [PATCH 043/173] Avoid loading debiasing table more than once --- src/NEOs.jl | 2 +- src/orbit_determination/gauss_method.jl | 34 ++++++++++++++++++------- src/postprocessing/neosolution.jl | 16 +++++++++--- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index cffa8832..fac1f912 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -52,7 +52,7 @@ export pv2kep, yarkp2adot # Topocentric export obs_pos_ECEF, obsposvelECI # Process radec -export compute_radec, debiasing, w8sveres17, radec_astrometry, residuals +export compute_radec, select_debiasing_table, debiasing, w8sveres17, residuals # Process radar export compute_delay, radar_astrometry # Gauss method diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 2d8f3a53..9b2b1072 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -409,8 +409,9 @@ end for i in 1:2 @eval begin - function _gaussinitcond(radec::Vector{RadecMPC{T}}, max_triplets::Int, Q_max::T, niter::Int, varorder::Int, order::Int, - abstol::T, parse_eqs::Bool, ::Val{$i}) where {T <: AbstractFloat} + function _gaussinitcond(radec::Vector{RadecMPC{T}}, mpc_catalogue_codes_201X::Vector{String}, truth::String, + resol::Resolution, bias_matrix::Matrix{T}, max_triplets::Int, Q_max::T, niter::Int, + varorder::Int, order::Int, abstol::T, parse_eqs::Bool, ::Val{$i}) where {T <: AbstractFloat} # Allocate memory for initial conditions best_sol = zero(NEOSolution{T, T}) @@ -479,7 +480,8 @@ for i in 1:2 continue end # O-C residuals - res = residuals(radec; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), + res = residuals(radec; mpc_catalogue_codes_201X, truth, resol, bias_matrix, + xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), xva = et -> bwdfwdeph(et, bwd, fwd)) # Subset of radec for orbit fit @@ -554,8 +556,7 @@ for i in 1:2 end @doc raw""" - gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max::T = 100., niter::Int = 5, - varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} + gaussinitcond(radec::Vector{RadecMPC{T}}; debias_table::String = "2018", kwargs...) where {T <: AbstractFloat} Return initial conditions via Gauss method. @@ -563,6 +564,12 @@ See also [`gauss_method`](@ref). # Arguments - `radec::Vector{RadecMPC{T}}`: vector of observations. + +# Keyword arguments +- `debias_table::String`: possible values are: + - `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, + - `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, + - `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. - `max_triplets::Int`: maximum number of triplets. - `Q_max::T`: The maximum nrms that is considered a good enough orbit. - `niter::Int`: number of iterations for Newton's method. @@ -574,17 +581,26 @@ See also [`gauss_method`](@ref). !!! warning This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. """ -function gaussinitcond(radec::Vector{RadecMPC{T}}; max_triplets::Int = 10, Q_max::T = 10., niter::Int = 5, - varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} +function gaussinitcond(radec::Vector{RadecMPC{T}}; debias_table::String = "2018", kwargs...) where {T <: AbstractFloat} + mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) + return gaussinitcond(radec; mpc_catalogue_codes_201X, truth, resol, bias_matrix, kwargs...) +end + +function gaussinitcond(radec::Vector{RadecMPC{T}}; mpc_catalogue_codes_201X::Vector{String}, truth::String, + resol::Resolution, bias_matrix::Matrix{T}, max_triplets::Int = 10, Q_max::T = 10., + niter::Int = 5, varorder::Int = 5, order::Int = order, abstol::T = abstol, + parse_eqs::Bool = true) where {T <: AbstractFloat} # Eliminate observatories without coordinates filter!(x -> hascoord(observatory(x)), radec) - best_sol_1 = _gaussinitcond(radec, max_triplets, Q_max, niter, varorder, order, abstol, parse_eqs, Val(1)) + best_sol_1 = _gaussinitcond(radec, mpc_catalogue_codes_201X, truth, resol, bias_matrix, + max_triplets, Q_max, niter, varorder, order, abstol, parse_eqs, Val(1)) Q_1 = nrms(best_sol_1) if Q_1 > Q_max - best_sol_2 = _gaussinitcond(radec, max_triplets, Q_max, niter, varorder, order, abstol, parse_eqs, Val(2)) + best_sol_2 = _gaussinitcond(radec, mpc_catalogue_codes_201X, truth, resol, bias_matrix, + max_triplets, Q_max, niter, varorder, order, abstol, parse_eqs, Val(2)) Q_2 = nrms(best_sol_2) if Q_2 < Q_1 return best_sol_2 diff --git a/src/postprocessing/neosolution.jl b/src/postprocessing/neosolution.jl index 4998b68d..e4235fe7 100644 --- a/src/postprocessing/neosolution.jl +++ b/src/postprocessing/neosolution.jl @@ -99,9 +99,18 @@ end iszero(x::NEOSolution{T, U}) where {T <: Real, U <: Number} = x == zero(NEOSolution{T, U}) +function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::Int, jd0::T, nyears_bwd::T, nyears_fwd::T, + q0::Vector{U}; debias_table::String = "2018", kwargs...) where {T <: Real, U <: Number, D} + mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) + return orbitdetermination(radec, dynamics, maxsteps, jd0, nyears_bwd, nyears_fwd, q0; + mpc_catalogue_codes_201X, truth, resol, bias_matrix, kwargs...) +end + function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::Int, jd0::T, nyears_bwd::T, - nyears_fwd::T, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], niter::Int = 5, - order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: Real, U <: Number, D} + nyears_fwd::T, q0::Vector{U}; mpc_catalogue_codes_201X::Vector{String}, truth::String, + resol::Resolution, bias_matrix::Matrix{T}, niter::Int = 5, order::Int = order, + abstol::T = abstol, parse_eqs::Bool = true, + μ_ast::Vector = μ_ast343_DE430[1:end], ) where {T <: Real, U <: Number, D} # Sun's ephemeris eph_su = selecteph(sseph, su) @@ -116,7 +125,8 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::I abstol = abstol, parse_eqs = parse_eqs) # Residuals - res = residuals(radec; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), + res = residuals(radec; mpc_catalogue_codes_201X, truth, resol, bias_matrix, + xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), xva = et -> bwdfwdeph(et, bwd, fwd)) # Orbit fit fit = tryls(res, zeros(get_numvars()), niter) From 6a6b27d81bec84b8c06a90c5f8bc2fc49fdb8a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 3 Sep 2023 16:39:07 -0600 Subject: [PATCH 044/173] Fix signatures --- src/orbit_determination/gauss_method.jl | 6 +++--- src/postprocessing/neosolution.jl | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 9b2b1072..6b2985a6 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -583,11 +583,11 @@ See also [`gauss_method`](@ref). """ function gaussinitcond(radec::Vector{RadecMPC{T}}; debias_table::String = "2018", kwargs...) where {T <: AbstractFloat} mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) - return gaussinitcond(radec; mpc_catalogue_codes_201X, truth, resol, bias_matrix, kwargs...) + return gaussinitcond(radec, mpc_catalogue_codes_201X, truth, resol, bias_matrix; kwargs...) end -function gaussinitcond(radec::Vector{RadecMPC{T}}; mpc_catalogue_codes_201X::Vector{String}, truth::String, - resol::Resolution, bias_matrix::Matrix{T}, max_triplets::Int = 10, Q_max::T = 10., +function gaussinitcond(radec::Vector{RadecMPC{T}}, mpc_catalogue_codes_201X::Vector{String}, truth::String, + resol::Resolution, bias_matrix::Matrix{T}; max_triplets::Int = 10, Q_max::T = 10., niter::Int = 5, varorder::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: AbstractFloat} diff --git a/src/postprocessing/neosolution.jl b/src/postprocessing/neosolution.jl index e4235fe7..e57e0eb1 100644 --- a/src/postprocessing/neosolution.jl +++ b/src/postprocessing/neosolution.jl @@ -102,13 +102,13 @@ iszero(x::NEOSolution{T, U}) where {T <: Real, U <: Number} = x == zero(NEOSolut function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::Int, jd0::T, nyears_bwd::T, nyears_fwd::T, q0::Vector{U}; debias_table::String = "2018", kwargs...) where {T <: Real, U <: Number, D} mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) - return orbitdetermination(radec, dynamics, maxsteps, jd0, nyears_bwd, nyears_fwd, q0; - mpc_catalogue_codes_201X, truth, resol, bias_matrix, kwargs...) + return orbitdetermination(radec, dynamics, maxsteps, jd0, nyears_bwd, nyears_fwd, q0, + mpc_catalogue_codes_201X, truth, resol, bias_matrix; kwargs...) end function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::Int, jd0::T, nyears_bwd::T, - nyears_fwd::T, q0::Vector{U}; mpc_catalogue_codes_201X::Vector{String}, truth::String, - resol::Resolution, bias_matrix::Matrix{T}, niter::Int = 5, order::Int = order, + nyears_fwd::T, q0::Vector{U}, mpc_catalogue_codes_201X::Vector{String}, truth::String, + resol::Resolution, bias_matrix::Matrix{T}; niter::Int = 5, order::Int = order, abstol::T = abstol, parse_eqs::Bool = true, μ_ast::Vector = μ_ast343_DE430[1:end], ) where {T <: Real, U <: Number, D} From 547adf6a63a86c48fb577b390bbd4141ed0e6b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 3 Sep 2023 16:47:23 -0600 Subject: [PATCH 045/173] Fix more signatures --- src/orbit_determination/gauss_method.jl | 2 +- src/postprocessing/neosolution.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 6b2985a6..ec9fd13f 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -480,7 +480,7 @@ for i in 1:2 continue end # O-C residuals - res = residuals(radec; mpc_catalogue_codes_201X, truth, resol, bias_matrix, + res = residuals(radec, mpc_catalogue_codes_201X, truth, resol, bias_matrix; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), xva = et -> bwdfwdeph(et, bwd, fwd)) diff --git a/src/postprocessing/neosolution.jl b/src/postprocessing/neosolution.jl index e57e0eb1..84b0739e 100644 --- a/src/postprocessing/neosolution.jl +++ b/src/postprocessing/neosolution.jl @@ -125,7 +125,7 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::I abstol = abstol, parse_eqs = parse_eqs) # Residuals - res = residuals(radec; mpc_catalogue_codes_201X, truth, resol, bias_matrix, + res = residuals(radec, mpc_catalogue_codes_201X, truth, resol, bias_matrix; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), xva = et -> bwdfwdeph(et, bwd, fwd)) # Orbit fit From 361edd9eb3c6e1c37f4f380db4d75636f69d3424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 6 Sep 2023 17:48:01 -0600 Subject: [PATCH 046/173] Update CatalogueMPC to new observations API --- src/NEOs.jl | 4 +- src/constants.jl | 2 - src/init.jl | 2 +- src/observations/catalogue_mpc.jl | 105 +++++++++++------------------- src/observations/radec_mpc.jl | 77 ++++++---------------- test/observations.jl | 41 +++--------- 6 files changed, 71 insertions(+), 160 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index fac1f912..109415ee 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -2,7 +2,7 @@ module NEOs # __precompile__(false) -import Base: hash, ==, show, isless, isnan, convert, zero, iszero +import Base: hash, ==, show, isless, isnan, convert, zero, iszero, string import PlanetaryEphemeris as PE import JLD2: writeas import Tables: istable, rowaccess, rows, schema, Schema @@ -30,7 +30,7 @@ using Interpolations: Flat, Gridded, Linear, interpolate, extrapolate # Constants export d_EM_km, d_EM_au # CatalogueMPC -export unknowncat, isunknown, read_catalogues_mpc, parse_catalogues_mpc, write_catalogues_mpc, update_catalogues_mpc, +export unknowncat, isunknown, read_catalogues_mpc, write_catalogues_mpc, update_catalogues_mpc, search_cat_code # ObservatoryMPC export unknownobs, hascoord, read_observatories_mpc, parse_observatories_mpc, write_observatories_mpc, diff --git a/src/constants.jl b/src/constants.jl index e577e0ed..93cb7e74 100644 --- a/src/constants.jl +++ b/src/constants.jl @@ -7,8 +7,6 @@ const scratch_path = Ref{String}("") # URLs -# MPC catalogues file url -const mpc_catalogues_url = "https://minorplanetcenter.net/iau/info/CatalogueCodes.html" # MPC observatories file url const mpc_observatories_url = "https://minorplanetcenter.net/iau/lists/ObsCodes.html" # MPC database search url diff --git a/src/init.jl b/src/init.jl index 39c5c50c..f4ee76b8 100644 --- a/src/init.jl +++ b/src/init.jl @@ -4,7 +4,7 @@ function __init__() # Load catalogues CatalogueCodes_path = joinpath(scratch_path[], "CatalogueCodes.txt") if isfile(CatalogueCodes_path) - global mpc_catalogues[] = read_catalogues_mpc(CatalogueCodes_path) + global CATALOGUES_MPC[] = read_catalogues_mpc(CatalogueCodes_path) else update_catalogues_mpc() end diff --git a/src/observations/catalogue_mpc.jl b/src/observations/catalogue_mpc.jl index 6a240432..a0b45c88 100644 --- a/src/observations/catalogue_mpc.jl +++ b/src/observations/catalogue_mpc.jl @@ -47,8 +47,12 @@ function show(io::IO, m::CatalogueMPC) end end +neoparse(x::RegexMatch, i::Int, ::Type{String}) = String(strip(x[i])) + # Regular expression to parse a catalogue in MPC format -const mpc_catalogue_regex = r"\s{2}(?P\w{1})\s{4}(?P.*)" +const CATALOGUE_MPC_REGEX = r"\s{2}(?P\w{1})\s{4}(?P.*)" +# Header of MPC catalogues file +const CATALOGUES_MPC_HEADER = "Char Catalogue" @doc raw""" CatalogueMPC(m::RegexMatch) @@ -56,83 +60,49 @@ const mpc_catalogue_regex = r"\s{2}(?P\w{1})\s{4}(?P.*)" Convert a match of `NEOs.mpc_catalogue_regex` to `CatalogueMPC`. """ function CatalogueMPC(m::RegexMatch) - @assert m.regex == mpc_catalogue_regex "Only matches of `NEOs.mpc_catalogue_regex` can be converted to `CatalogueMPC`." - return CatalogueMPC(string(m["code"]), string(m["name"])) + # Check that matched regex is correct + @assert m.regex == CATALOGUE_MPC_REGEX "Only matches of `NEOs.CATALOGUE_MPC_REGEX` can be converted to `CatalogueMPC`." + # Field types + types = fieldtypes(CatalogueMPC) + # CatalogueMPC fields + args = map(i -> neoparse(m, i, types[i]), 1:length(types)) + + return CatalogueMPC(args...) end @doc raw""" - read_catalogues_mpc(filename::String) + read_catalogues_mpc(s::String) -Return the matches of `NEOs.mpc_catalogue_regex` in `filename` as `CatalogueMPC`. +Return the matches of `NEOs.CATALOGUE_MPC_REGEX` in `s` as `CatalogueMPC`. `s` can be either a filename or a text. """ -function read_catalogues_mpc(filename::String) - # Check that file exists - @assert isfile(filename) "Invalid filename" - # Read lines of mpc formatted file (except header) - lines = readlines(filename)[2:end] - # Apply regular expressions - matches = match.(mpc_catalogue_regex, lines) - # Eliminate nothings - filter!(!isnothing, matches) - # Convert matches to CatalogueMPC - cats = CatalogueMPC.(matches) - # Eliminate repeated entries - unique!(cats) - - return cats -end - -@doc raw""" - get_raw_html(url::String) - -Return the raw html text of webpage `url`. -""" -function get_raw_html(url::String) - # Get raw html - resp = get(url) - # Convert to string - text = String(resp.body) - - return text -end - -# Header of MPC catalogues file -const mpc_catalogues_header = "Char Catalogue" - -@doc raw""" - parse_catalogues_mpc(text::String) - -Return de matches of `NEOs.mpc_catalogue_regex` in `text` as `CatalogueMPC`. -""" -function parse_catalogues_mpc(text::String) - # Eliminate catalogues file header - text = replace(text, mpc_catalogues_header => "") +function read_catalogues_mpc(s::String) + if isfile(s) + # Read MPC formatted file + s = String(read(s)) + end + # Remove header + s = replace(s, CATALOGUES_MPC_HEADER => "") # Vector of MPC catalogues cats = Vector{CatalogueMPC}(undef, 0) # Iterate over the matches - for m in eachmatch(mpc_catalogue_regex, text) + for m in eachmatch(CATALOGUE_MPC_REGEX, s) push!(cats, CatalogueMPC(m)) end - # Eliminate repeated entries unique!(cats) return cats end -@doc raw""" - mpc_catalogue_str(cat::CatalogueMPC) - -Convert `cat` to a string according to MPC format. -""" -function mpc_catalogue_str(cat::CatalogueMPC) +# Convert `cat` to a string according to MPC format. +function string(cat::CatalogueMPC) if isunknown(cat) return "" else # Code string - code_s = join([" ", cat.code, " "]) + code_s = string(" ", cat.code, " ") # Join everything - cat_s = join([code_s, cat.name]) + cat_s = string(code_s, cat.name) return cat_s end @@ -146,15 +116,18 @@ Write `cats` to `filename` in MPC format. function write_catalogues_mpc(cats::Vector{CatalogueMPC}, filename::String) open(filename, "w") do file # Header - write(file, mpc_catalogues_header, "\n") + write(file, CATALOGUES_MPC_HEADER, "\n") # Write observatories for i in eachindex(cats) - line = mpc_catalogue_str(cats[i]) + line = string(cats[i]) write(file, line, "\n") end end end +# MPC catalogues file url +const CATALOGUES_MPC_URL = "https://minorplanetcenter.net/iau/info/CatalogueCodes.html" + @doc raw""" download_scratch(url::String, filename::String; connect_timeout=180, readtimeout=180) @@ -172,7 +145,7 @@ function download_scratch(url::String, filename::String; connect_timeout=180, re end # List of MPC catalogues -const mpc_catalogues = Ref{Vector{CatalogueMPC}}([unknowncat()]) +const CATALOGUES_MPC = Ref{Vector{CatalogueMPC}}([unknowncat()]) @doc raw""" update_catalogues_mpc() @@ -181,13 +154,13 @@ Update the local catalogues file. """ function update_catalogues_mpc() # Download and read catalogues file - CatalogueCodes_path, txt = download_scratch(mpc_catalogues_url, "CatalogueCodes.txt") + CatalogueCodes_path, txt = download_scratch(CATALOGUES_MPC_URL, "CatalogueCodes.txt") # Parse catalogues - cats = parse_catalogues_mpc(txt) + cats = read_catalogues_mpc(txt) # Write catalogues to local file write_catalogues_mpc(cats, CatalogueCodes_path) # Update global variable - global mpc_catalogues[] = read_catalogues_mpc(CatalogueCodes_path) + global CATALOGUES_MPC[] = read_catalogues_mpc(CatalogueCodes_path) return nothing end @@ -200,7 +173,7 @@ Return the catalogue in `NEOs.mpc_catalogues` that matches `catcode`. function search_cat_code(catcode::String) # Find indexes in mpc_catalogues that match catcode - idxs = findall(x -> x.code == catcode, mpc_catalogues[]) + idxs = findall(x -> x.code == catcode, CATALOGUES_MPC[]) L_i = length(idxs) # No catalog matches catcode @@ -208,10 +181,10 @@ function search_cat_code(catcode::String) catalogue = unknowncat() # Exactly one catalogue matches catcode else - catalogue = mpc_catalogues[][idxs[1]] + catalogue = CATALOGUES_MPC[][idxs[1]] # More than one catalogue matches catcode if L_i > 1 - @warn("""More than one catalogue $(mpc_catalogues[][idxs]) has code $catcode, + @warn("""More than one catalogue $(CATALOGUES_MPC[][idxs]) has code $catcode, selecting first: $(catalogue.name)""") end end diff --git a/src/observations/radec_mpc.jl b/src/observations/radec_mpc.jl index 6cd93cee..c4ca321a 100644 --- a/src/observations/radec_mpc.jl +++ b/src/observations/radec_mpc.jl @@ -135,6 +135,25 @@ const mpc_radec_regex = Regex(join( raw"(?P.{3})" ] )) +#= +re = NEOs.mpc_radec_regex * Regex(string( + raw"(?:\n)?", + raw"(?P<_num_>.{5})?", + raw"(?P<_tmpdesig_>.{7})?", + raw"(?P<_discovery_>.{1})?", + raw"(?P<_publishnote_>.{1})?", + raw"(?P<_obstech_>.{1})?", + raw"(?P<_year_>\d{4})?(?:\s)?", + raw"(?P<_month_>\d{2})?(?:\s)?", + raw"(?P<_day_>\d{2})?", + raw"(?P<_utc_>\.[\d\s]{6})?", + raw"(?P<_sep_>1\s)?", + raw"(?P[\-\+]{1}[\.\d\s]{11})?", + raw"(?P[\-\+]{1}[\.\d\s]{11})?", + raw"(?P[\-\+]{1}[\.\d\s]{11})?" +)) + +=# @doc raw""" datetime(year::Int, month::Int, day::Int, utc::T) where {T <: Real} @@ -280,64 +299,6 @@ function parse_radec_mpc(f::F, text::String) where F end parse_radec_mpc(text::String) = parse_radec_mpc(t -> true, text) -# MPC main page url -const mpc_url = "https://minorplanetcenter.net" - -# Regex for next circular url -const next_circular_regex = r".*)\"> Bool` can be passed to filter the observations. If `url2` is not -reached before `max_iter` iterations, the function will print a warning and return the -matches found so far. -""" -function search_circulars_mpc(f::F, url1::String, url2::String; max_iter::Int = 10_000) where F - - # Vector of observations - obs = Vector{RadecMPC{Float64}}(undef, 0) - - # Number of urls checked - n = 0 - # First url - u = url1 - - while true - n += 1 - if n > max_iter - @warn("$n pages checked before getting to $url2") - break - end - # Raw html text of webpage u - text = get_raw_html(u) - # Observations found in text - obs_ = parse_radec_mpc(f, text) - # Add new observations - obs = vcat(obs, obs_) - # Final url - if u == url2 - break - end - # Next circular url - next = match(next_circular_regex, text)["next"] - u = mpc_url * next - end - # If there is at least one observation - if length(obs) > 0 - # Sort observations by date - sort!(obs) - # Eliminate repeated observations - unique!(obs) - end - - return obs -end - -search_circulars_mpc(url1::String, url2::String; max_iter::Int = 10_000) = search_circulars_mpc(t -> true, url1, url2; max_iter = max_iter) - @doc raw""" mpc_date_str(date::DateTime) diff --git a/test/observations.jl b/test/observations.jl index ef7a7fc8..57d28315 100644 --- a/test/observations.jl +++ b/test/observations.jl @@ -9,15 +9,15 @@ using NEOs: src_path @testset "CatalogueMPC" begin - using NEOs: mpc_catalogue_regex, CatalogueMPC + using NEOs: CATALOGUE_MPC_REGEX, CatalogueMPC - # Check global variable NEOs.mpc_catalogues[] - @test allunique(NEOs.mpc_catalogues[]) - @test isa(NEOs.mpc_catalogues[], Vector{CatalogueMPC}) + # Check global variable NEOs.CATALOGUES_MPC[] + @test allunique(NEOs.CATALOGUES_MPC[]) + @test isa(NEOs.CATALOGUES_MPC[], Vector{CatalogueMPC}) # Parse CatalogueMPC gaia_s = " 6 Gaia2016" - gaia_m = match(mpc_catalogue_regex, gaia_s) + gaia_m = match(CATALOGUE_MPC_REGEX, gaia_s) gaia = CatalogueMPC(gaia_m) @test gaia.code == "6" @test gaia.name == "Gaia2016" @@ -34,15 +34,15 @@ using NEOs: src_path # Read/write catalogues file check_file = joinpath(dirname(src_path), "test", "data", "CatalogueCodes.txt") - write_catalogues_mpc(NEOs.mpc_catalogues[], check_file) + write_catalogues_mpc(NEOs.CATALOGUES_MPC[], check_file) check_cat = read_catalogues_mpc(check_file) rm(check_file) - @test NEOs.mpc_catalogues[] == check_cat + @test NEOs.CATALOGUES_MPC[] == check_cat # Update catalogues file update_catalogues_mpc() - @test allunique(NEOs.mpc_catalogues[]) - @test isa(NEOs.mpc_catalogues[], Vector{CatalogueMPC}) + @test allunique(NEOs.CATALOGUES_MPC[]) + @test isa(NEOs.CATALOGUES_MPC[], Vector{CatalogueMPC}) # Search catalogue code cat = search_cat_code("6") @@ -157,30 +157,9 @@ using NEOs: src_path @test source_radec == check_radec - # Search MPC circulars - function search_apophis(m::RegexMatch) - if (m["num"] == "99942") || (m["tmpdesig"] == "N00hp15") - return true - else - return false - end - end - - obs = search_circulars_mpc( - search_apophis, - "https://minorplanetcenter.net/mpec/K20/K20YA9.html", - "https://minorplanetcenter.net/mpec/K21/K21JL0.html"; - max_iter = 10 - ) - - @test isa(obs, Vector{RadecMPC{Float64}}) - @test issorted(obs) - @test allunique(obs) - @test all( (getfield.(obs, :num) .== "99942") .| (getfield.(obs, :tmpdesig) .== "N00hp15") ) - # Get RadecMPC source_file = joinpath("data", "99942.txt") - get_radec_mpc("99942", source_file) + get_radec_mpc("number" => "99942", source_file) @test isfile(source_file) From 6f793ca97b5f676387315d07af9db9fa35be698b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 7 Sep 2023 18:10:14 -0600 Subject: [PATCH 047/173] Update ObservatoryMPC to new observations API --- src/NEOs.jl | 3 +- src/constants.jl | 2 - src/init.jl | 2 +- src/observations/catalogue_mpc.jl | 2 +- src/observations/observatory_mpc.jl | 217 +++++++++++++--------------- src/observations/radec_mpc.jl | 2 +- test/observations.jl | 20 +-- 7 files changed, 116 insertions(+), 132 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index 109415ee..8b752ef9 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -33,8 +33,7 @@ export d_EM_km, d_EM_au export unknowncat, isunknown, read_catalogues_mpc, write_catalogues_mpc, update_catalogues_mpc, search_cat_code # ObservatoryMPC -export unknownobs, hascoord, read_observatories_mpc, parse_observatories_mpc, write_observatories_mpc, - update_observatories_mpc, search_obs_code +export unknownobs, hascoord, read_observatories_mpc, write_observatories_mpc, update_observatories_mpc, search_obs_code # RadecMPC export num, tmpdesig, discovery, publishnote, obstech, ra, dec, info1, mag, band, catalogue, info2, observatory, read_radec_mpc, parse_radec_mpc, search_circulars_mpc, write_radec_mpc, get_radec_mpc diff --git a/src/constants.jl b/src/constants.jl index 93cb7e74..07ebb23c 100644 --- a/src/constants.jl +++ b/src/constants.jl @@ -7,8 +7,6 @@ const scratch_path = Ref{String}("") # URLs -# MPC observatories file url -const mpc_observatories_url = "https://minorplanetcenter.net/iau/lists/ObsCodes.html" # MPC database search url const search_mpc_url = "https://www.minorplanetcenter.net/db_search/show_object?utf8=%E2%9C%93&object_id=" # MPC observations url diff --git a/src/init.jl b/src/init.jl index f4ee76b8..6bfb3053 100644 --- a/src/init.jl +++ b/src/init.jl @@ -11,7 +11,7 @@ function __init__() # Load observatories ObsCodes_path = joinpath(scratch_path[], "ObsCodes.txt") if isfile(ObsCodes_path) - global mpc_observatories[] = read_observatories_mpc(ObsCodes_path) + global OBSERVATORIES_MPC[] = read_observatories_mpc(ObsCodes_path) else update_observatories_mpc() end diff --git a/src/observations/catalogue_mpc.jl b/src/observations/catalogue_mpc.jl index a0b45c88..66c6a2a6 100644 --- a/src/observations/catalogue_mpc.jl +++ b/src/observations/catalogue_mpc.jl @@ -57,7 +57,7 @@ const CATALOGUES_MPC_HEADER = "Char Catalogue" @doc raw""" CatalogueMPC(m::RegexMatch) -Convert a match of `NEOs.mpc_catalogue_regex` to `CatalogueMPC`. +Convert a match of `NEOs.CATALOGUE_MPC_REGEX` to `CatalogueMPC`. """ function CatalogueMPC(m::RegexMatch) # Check that matched regex is correct diff --git a/src/observations/observatory_mpc.jl b/src/observations/observatory_mpc.jl index df1a2392..06ee8cf8 100644 --- a/src/observations/observatory_mpc.jl +++ b/src/observations/observatory_mpc.jl @@ -11,21 +11,47 @@ An observatory in MPC format. The format is described in https://minorplanetcent - `sin::T`: `ρ*sin(ϕ')`, where `ϕ'` is the geocentric latitude and `ρ` is the geocentric distance in earth radii. - `name::String`: observatory's name. """ -@auto_hash_equals struct ObservatoryMPC{T <: AbstractFloat} +struct ObservatoryMPC{T <: AbstractFloat} code::String long::T cos::T sin::T name::String + date::DateTime + type::Symbol + units::Int # Inner constructor - function ObservatoryMPC{T}(code::String, long::T, cos::T, sin::T, name::String) where {T <: AbstractFloat} - return new{T}(code, long, cos, sin, name) + function ObservatoryMPC{T}(code::String, long::T, cos::T, sin::T, name::String, date::DateTime = DateTime(2000, 1, 1), + type::Symbol = :ground, units::Int = 0) where {T <: AbstractFloat} + return new{T}(code, long, cos, sin, name, date, type, units) end end # Outer constructor -function ObservatoryMPC(code::String, long::T, cos::T, sin::T, name::String) where {T <: AbstractFloat} - return ObservatoryMPC{T}(code, long, cos, sin, name) +function ObservatoryMPC(code::String, long::T, cos::T, sin::T, name::String, date::DateTime = DateTime(2000, 1, 1), + type::Symbol = :ground, units::Int = 0) where {T <: AbstractFloat} + return ObservatoryMPC{T}(code, long, cos, sin, name, date, type, units) +end + +# TO DO: This could be done with a more recent version of AutoHasEquals +function Base.hash(x::ObservatoryMPC{T}, h::UInt) where {T <: AbstractFloat} + Base.hash(x.code, Base.hash(:(ObservatoryMPC{T}), h)) +end +function Base.isequal(a::ObservatoryMPC{T}, b::ObservatoryMPC{T}) where {T <: AbstractFloat} + Base.isequal(a.code, b.code) +end +# Returns `false` if any two fields compare as false; otherwise, `missing` if at least +# one comparison is missing. Otherwise `true`. +# This matches the semantics of `==` for Tuple's and NamedTuple's. +function Base.:(==)(a::ObservatoryMPC{T}, b::ObservatoryMPC{T}) where {T <: AbstractFloat} + found_missing = false + cmp = a.code == b.code + cmp === false && return false + if ismissing(cmp) + found_missing = true + end + found_missing && return missing + return true end @doc raw""" @@ -44,6 +70,9 @@ function isunknown(m::ObservatoryMPC{T}) where {T <: AbstractFloat} return m == unknownobs() end +isground(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :ground +issatellite(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :sattelite + @doc raw""" hascoord(m::ObservatoryMPC{T}) where {T <: AbstractFloat} @@ -61,112 +90,79 @@ end function show(io::IO, m::ObservatoryMPC{T}) where {T <: AbstractFloat} if isunknown(m) print(io, "Unknown observatory") - elseif hascoord(m) + elseif isground(m) print(io, m.name, " [", m.code, "] long: ", m.long, " cos: ", m.cos, " sin: ", m.sin) else print(io, m.name, " [", m.code, "]") end end -# Regular expression to parse an observatory in MPC format -const mpc_observatory_regex = Regex(join( - [ - # Code regex + space (columns 1-4) - raw"(?P.{3}) ", - # Longitude regex (columns 5-13) - raw"(?P.{9})", - # Cosine regex + space (column 14-21) - raw"(?P.{8})", - # Sine regex (column 22-30) - raw"(?P.{9})", - # Name regex (columns 31-80) - raw"(?P.*)", - ] -)) - -@doc raw""" - parse_observatory_float(x::String) - -Parse `x`; if the result is not a `Float64`, returns `NaN`. -""" -function parse_observatory_float(x::String) - # Try parsing x - p = tryparse(Float64, x) - # The result is not a float - if isnothing(p) +function neoparse(x::RegexMatch, i::Int, ::Type{Float64}) + y = tryparse(Float64, x[i]) + if isnothing(y) return NaN - # The result is a float else - return p + return y end end +# Regular expression to parse an observatory in MPC format +const OBSERVATORY_MPC_REGEX = Regex(string( + # Code regex + space (columns 1-3) + raw"(?P[A-Z\d]{3})", + # Longitude regex (columns 4-13) + raw"(?P[\.\d\s]{10})", + # Cosine regex + space (column 14-21) + raw"(?P[\.\d\s]{8})", + # Sine regex (column 22-30) + raw"(?P[\+\-\.\d\s]{9})", + # Name regex (columns 31-80) + raw"(?P.*)", +)) +# Header of MPC observatories file +const OBSERVATORIES_MPC_HEADER = "Code Long. cos sin Name" + @doc raw""" ObservatoryMPC(m::RegexMatch) -Convert a match of `NEOs.mpc_observatory_regex` to `ObservatoryMPC`. +Convert a match of `NEOs.OBSERVATORY_MPC_REGEX` to `ObservatoryMPC`. """ function ObservatoryMPC(m::RegexMatch) - - @assert m.regex == mpc_observatory_regex "Only matches of `NEOs.mpc_observatory_regex` can be converted to `ObservatoryMPC`." - - long_ = parse_observatory_float(string(m["long"])) - cos_ = parse_observatory_float(string(m["cos"])) - sin_ = parse_observatory_float(string(m["sin"])) - - return ObservatoryMPC( - string(m["code"]), - long_, - cos_, - sin_, - string(m["name"]), - ) - + # Check that matched regex is correct + @assert m.regex == OBSERVATORY_MPC_REGEX "Only matches of `NEOs.OBSERVATORY_MPC_REGEX` can be converted to `ObservatoryMPC`." + # Field types + types = fieldtypes(ObservatoryMPC{Float64}) + # ObservatoryMPC{Float64} fields + args = map(i -> neoparse(m, i, types[i]), 1:5) + + if isnan(args[2]) && isnan(args[3]) && isnan(args[4]) + ObservatoryMPC(args..., DateTime(2000, 1, 1), :satellite, 0) + else + ObservatoryMPC(args...) + end end @doc raw""" - read_observatories_mpc(filename::String) + read_observatories_mpc(s::String) -Return the matches of `NEOs.mpc_observatory_regex` in `filename` as `ObservatoryMPC`. +Return the matches of `NEOs.OBSERVATORY_MPC_REGEX` in `s` as `ObservatoryMPC`. """ -function read_observatories_mpc(filename::String) - # Check that file exists - @assert isfile(filename) "Invalid filename" - # Read lines of mpc formatted file (except header) - lines = readlines(filename)[2:end] - # Apply regular expressions - matches = match.(mpc_observatory_regex, lines) - # Eliminate nothings - filter!(!isnothing, matches) - # Convert matches to ObservatoryMPC - obs = ObservatoryMPC.(matches) - # Eliminate repeated entries - unique!(obs) - - return obs -end - -# Header of MPC observatories file -const mpc_observatories_header = "Code Long. cos sin Name" - -@doc raw""" - parse_observatories_mpc(text::String) - -Return de matches of `NEOs.mpc_observatory_regex` in `text` as `ObservatoryMPC`. -""" -function parse_observatories_mpc(text::String) - # Eliminate observatories file header - text = replace(text, mpc_observatories_header => "") - # Vector of MPC observatories +function read_observatories_mpc(s::String) + if !contains(s, "\n") && isfile(s) + # Read MPC formatted file + s = String(read(s)) + end + # Remove header + s = replace(s, OBSERVATORIES_MPC_HEADER => "") + # Vector of MPC observatories obs = Vector{ObservatoryMPC{Float64}}(undef, 0) - # Iterate over the matches - for m in eachmatch(mpc_observatory_regex, text) + # Iterate over the matches + for m in eachmatch(OBSERVATORY_MPC_REGEX, s) push!(obs, ObservatoryMPC(m)) end - - # Eliminate repeated entries + # Eliminate repeated entries unique!(obs) - + return obs end @@ -178,10 +174,10 @@ Convert `x` to a string according to the `long` field in MPC format. function mpc_long_str(x::T) where {T <: AbstractFloat} # NaN => empty string if isnan(x) - long_s = repeat(" ", 9) + long_s = repeat(" ", 10) else long_s = @sprintf("%3.5f", x) - long_s = lpad(long_s, 9) + long_s = lpad(long_s, 10) end return long_s end @@ -213,21 +209,17 @@ function mpc_sin_str(x::T) where {T <: AbstractFloat} else sin_s = @sprintf("%1.6f", abs(x)) if x ≥ 0 - sin_s = join(["+", sin_s]) + sin_s = string("+", sin_s) else - sin_s = join(["-", sin_s]) + sin_s = string("-", sin_s) end end return sin_s end -@doc raw""" - mpc_observatory_str(obs::ObservatoryMPC{T}) where {T <: AbstractFloat} - -Convert `obs` to a string acoording to MPC format. -""" -function mpc_observatory_str(obs::ObservatoryMPC{T}) where {T <: AbstractFloat} +# Convert `obs` to a string according to MPC format. +function string(obs::ObservatoryMPC{T}) where {T <: AbstractFloat} if isunknown(obs) return "" else @@ -238,14 +230,7 @@ function mpc_observatory_str(obs::ObservatoryMPC{T}) where {T <: AbstractFloat} # Sine string string sin_s = mpc_sin_str(obs.sin) # Join everything - obs_s = join([ - obs.code, - " ", - long_s, - cos_s, - sin_s, - obs.name - ]) + obs_s = string(obs.code, long_s, cos_s, sin_s, obs.name) end return obs_s @@ -259,17 +244,19 @@ Write `obs` to `filename` in MPC format. function write_observatories_mpc(obs::Vector{ObservatoryMPC{T}}, filename::String) where {T <: AbstractFloat} open(filename, "w") do file # Header - write(file, mpc_observatories_header, "\n") + write(file, OBSERVATORIES_MPC_HEADER, "\n") # Write observatories for i in eachindex(obs) - line = mpc_observatory_str(obs[i]) + line = string(obs[i]) write(file, line, "\n") end end end +# MPC observatories file url +const OBSERVATORIES_MPC_URL = "https://minorplanetcenter.net/iau/lists/ObsCodes.html" # List of mpc observatories -const mpc_observatories = Ref{Vector{ObservatoryMPC{Float64}}}([unknownobs()]) +const OBSERVATORIES_MPC = Ref{Vector{ObservatoryMPC{Float64}}}([unknownobs()]) @doc raw""" update_observatories_mpc() @@ -278,13 +265,13 @@ Update the local observatories file. """ function update_observatories_mpc() # Download and read observatories file - ObsCodes_path, txt = download_scratch(mpc_observatories_url, "ObsCodes.txt") + ObsCodes_path, txt = download_scratch(OBSERVATORIES_MPC_URL, "ObsCodes.txt") # Parse observatories - obs = parse_observatories_mpc(txt) + obs = read_observatories_mpc(txt) # Write observatories to local file write_observatories_mpc(obs, ObsCodes_path) # Update global variable - global mpc_observatories[] = read_observatories_mpc(ObsCodes_path) + global OBSERVATORIES_MPC[] = read_observatories_mpc(ObsCodes_path) return nothing end @@ -292,12 +279,12 @@ end @doc raw""" search_obs_code(obscode::String) -Return the observatory in `NEOs.mpc_observatories` that matches `obscode`. +Return the observatory in `NEOs.OBSERVATORIES_MPC` that matches `obscode`. """ function search_obs_code(obscode::String) - # Find indexes in mpc_observatories that match obscode - idxs = findall(x -> x.code == obscode, mpc_observatories[]) + # Find indexes in OBSERVATORIES_MPC that match obscode + idxs = findall(x -> x.code == obscode, OBSERVATORIES_MPC[]) L_i = length(idxs) # No observatory matches obscode @@ -305,10 +292,10 @@ function search_obs_code(obscode::String) observatory = unknownobs() # At least one observatory matches obscode else - observatory = mpc_observatories[][idxs[1]] + observatory = OBSERVATORIES_MPC[][idxs[1]] # More than one observatory matches obscode if L_i > 1 - @warn("""More than one observatory $(mpc_observatories[][idxs]) has code $obscode, + @warn("""More than one observatory $(OBSERVATORIES_MPC[][idxs]) has code $obscode, selecting first: $(observatory.name)""") end end diff --git a/src/observations/radec_mpc.jl b/src/observations/radec_mpc.jl index c4ca321a..bac3b314 100644 --- a/src/observations/radec_mpc.jl +++ b/src/observations/radec_mpc.jl @@ -224,7 +224,7 @@ function RadecMPC(m::RegexMatch) ) # Find catalogue in mpc_catalogues[] that matches catalogue catalogue = search_cat_code(string(m["catalogue"])) - # Find observatory in mpc_observatories[] that matches obscode + # Find observatory in OBSERVATORIES_MPC[] that matches obscode observatory = search_obs_code(string(m["obscode"])) return RadecMPC( diff --git a/test/observations.jl b/test/observations.jl index 57d28315..a7a827e6 100644 --- a/test/observations.jl +++ b/test/observations.jl @@ -51,15 +51,15 @@ using NEOs: src_path @testset "ObservatoryMPC" begin - using NEOs: mpc_observatory_regex, ObservatoryMPC + using NEOs: OBSERVATORY_MPC_REGEX, ObservatoryMPC - # Check global variable NEOs.mpc_observatories[] - @test allunique(NEOs.mpc_observatories[]) - @test isa(NEOs.mpc_observatories[], Vector{ObservatoryMPC{Float64}}) + # Check global variable NEOs.OBSERVATORIES_MPC[] + @test allunique(NEOs.OBSERVATORIES_MPC[]) + @test isa(NEOs.OBSERVATORIES_MPC[], Vector{ObservatoryMPC{Float64}}) # Parse ObservatoryMPC arecibo_s = "251 293.246920.949577+0.312734Arecibo" - arecibo_m = match(mpc_observatory_regex, arecibo_s) + arecibo_m = match(OBSERVATORY_MPC_REGEX, arecibo_s) arecibo = ObservatoryMPC(arecibo_m) @test arecibo.code == "251" @test arecibo.long == 293.24692 @@ -68,7 +68,7 @@ using NEOs: src_path @test arecibo.name == "Arecibo" hubble_s = "250 Hubble Space Telescope" - hubble_m = match(mpc_observatory_regex, hubble_s) + hubble_m = match(OBSERVATORY_MPC_REGEX, hubble_s) hubble = ObservatoryMPC(hubble_m) @test hubble.code == "250" @test isnan(hubble.long) @@ -97,15 +97,15 @@ using NEOs: src_path # Read/write observatories file check_file = joinpath(dirname(src_path), "test", "data", "ObsCodes.txt") - write_observatories_mpc(NEOs.mpc_observatories[], check_file) + write_observatories_mpc(NEOs.OBSERVATORIES_MPC[], check_file) check_obs = read_observatories_mpc(check_file) rm(check_file) - @test NEOs.mpc_observatories[] == check_obs + @test NEOs.OBSERVATORIES_MPC[] == check_obs # Update observatories file update_observatories_mpc() - @test allunique(NEOs.mpc_observatories[]) - @test isa(NEOs.mpc_observatories[], Vector{ObservatoryMPC{Float64}}) + @test allunique(NEOs.OBSERVATORIES_MPC[]) + @test isa(NEOs.OBSERVATORIES_MPC[], Vector{ObservatoryMPC{Float64}}) # Search observatory code obs = search_obs_code("250") From 43c4fbd8d3bd81bc66c44ce242827dd1e52a8d3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 7 Sep 2023 18:10:39 -0600 Subject: [PATCH 048/173] Minor fix --- src/observations/catalogue_mpc.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/observations/catalogue_mpc.jl b/src/observations/catalogue_mpc.jl index 66c6a2a6..73bf2bf7 100644 --- a/src/observations/catalogue_mpc.jl +++ b/src/observations/catalogue_mpc.jl @@ -76,7 +76,7 @@ end Return the matches of `NEOs.CATALOGUE_MPC_REGEX` in `s` as `CatalogueMPC`. `s` can be either a filename or a text. """ function read_catalogues_mpc(s::String) - if isfile(s) + if !contains(s, "\n") && isfile(s) # Read MPC formatted file s = String(read(s)) end From 2dfa5d11019c9ee9e86cae5a0c69b296595cf5f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 8 Sep 2023 11:26:07 -0600 Subject: [PATCH 049/173] Update RadecMPC to new observations API --- src/NEOs.jl | 4 +- src/observations/observatory_mpc.jl | 8 +- src/observations/radec_mpc.jl | 429 +++++++++++++--------------- src/observations/topocentric.jl | 144 ++++++---- test/observations.jl | 18 +- 5 files changed, 309 insertions(+), 294 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index 8b752ef9..399a3f18 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -36,7 +36,7 @@ export unknowncat, isunknown, read_catalogues_mpc, write_catalogues_mpc, update_ export unknownobs, hascoord, read_observatories_mpc, write_observatories_mpc, update_observatories_mpc, search_obs_code # RadecMPC export num, tmpdesig, discovery, publishnote, obstech, ra, dec, info1, mag, band, catalogue, info2, observatory, - read_radec_mpc, parse_radec_mpc, search_circulars_mpc, write_radec_mpc, get_radec_mpc + read_radec_mpc, search_circulars_mpc, write_radec_mpc, get_radec_mpc # RadarJPL export hasdelay, hasdoppler, ismonostatic, date, delay, delay_sigma, delay_units, doppler, doppler_sigma, doppler_units, freq, rcvr, xmit, bouncepoint, read_radar_jpl, write_radar_jpl @@ -49,7 +49,7 @@ export loadjpleph, sunposvel, earthposvel, moonposvel, apophisposvel197, apophis # Osculating export pv2kep, yarkp2adot # Topocentric -export obs_pos_ECEF, obsposvelECI +export obsposECEF, obsposvelECI # Process radec export compute_radec, select_debiasing_table, debiasing, w8sveres17, residuals # Process radar diff --git a/src/observations/observatory_mpc.jl b/src/observations/observatory_mpc.jl index 06ee8cf8..4df6078f 100644 --- a/src/observations/observatory_mpc.jl +++ b/src/observations/observatory_mpc.jl @@ -71,7 +71,7 @@ function isunknown(m::ObservatoryMPC{T}) where {T <: AbstractFloat} end isground(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :ground -issatellite(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :sattelite +issatellite(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :satellite @doc raw""" hascoord(m::ObservatoryMPC{T}) where {T <: AbstractFloat} @@ -98,7 +98,7 @@ function show(io::IO, m::ObservatoryMPC{T}) where {T <: AbstractFloat} end function neoparse(x::RegexMatch, i::Int, ::Type{Float64}) - y = tryparse(Float64, x[i]) + y = tryparse(Float64, replace(x[i], " " => "")) if isnothing(y) return NaN else @@ -136,9 +136,9 @@ function ObservatoryMPC(m::RegexMatch) args = map(i -> neoparse(m, i, types[i]), 1:5) if isnan(args[2]) && isnan(args[3]) && isnan(args[4]) - ObservatoryMPC(args..., DateTime(2000, 1, 1), :satellite, 0) + return ObservatoryMPC(args..., DateTime(2000, 1, 1), :satellite, 0) else - ObservatoryMPC(args...) + return ObservatoryMPC(args...) end end diff --git a/src/observations/radec_mpc.jl b/src/observations/radec_mpc.jl index bac3b314..54827744 100644 --- a/src/observations/radec_mpc.jl +++ b/src/observations/radec_mpc.jl @@ -1,4 +1,6 @@ abstract type AbstractAstrometry end +struct RightAscension <: AbstractAstrometry end +struct Declination <: AbstractAstrometry end @doc raw""" RadecMPC{T <: AbstractFloat} <: AbstractAstrometry @@ -17,7 +19,7 @@ and discussed thoroughly in pages 158-181 of https://doi.org/10.1016/j.icarus.20 - `α::T`: right ascension [rad]. - `δ::T`: declination [rad]. - `info1::String`: additional information. -- `mag::String`: observed magnitude. +- `mag::T`: observed magnitude. - `band::String`: magnitude band. - `catalogue::CatalogueMPC`: catalogue. - `info2::String`: additional information. @@ -33,14 +35,14 @@ and discussed thoroughly in pages 158-181 of https://doi.org/10.1016/j.icarus.20 α::T δ::T info1::String - mag::String + mag::T band::String catalogue::CatalogueMPC info2::String observatory::ObservatoryMPC{T} # Inner constructor function RadecMPC{T}(num::String, tmpdesig::String, discovery::String, publishnote::String, - obstech::String, date::DateTime, α::T, δ::T, info1::String, mag::String, + obstech::String, date::DateTime, α::T, δ::T, info1::String, mag::T, band::String, catalogue::CatalogueMPC, info2::String, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} new{T}(num, tmpdesig, discovery, publishnote, obstech, date, α, δ, info1, mag, band, catalogue, info2, observatory) @@ -49,7 +51,7 @@ end # Outer constructor function RadecMPC(num::String, tmpdesig::String, discovery::String, publishnote::String, - obstech::String, date::DateTime, α::T, δ::T, info1::String, mag::String, + obstech::String, date::DateTime, α::T, δ::T, info1::String, mag::T, band::String, catalogue::CatalogueMPC, info2::String, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} RadecMPC{T}(num, tmpdesig, discovery, publishnote, obstech, date, α, δ, info1, mag, band, catalogue, info2, observatory) @@ -86,91 +88,26 @@ catalogue(r::RadecMPC{T}) where {T <: AbstractFloat} = r.catalogue info2(r::RadecMPC{T}) where {T <: AbstractFloat} = r.info2 observatory(r::RadecMPC{T}) where {T <: AbstractFloat} = r.observatory -# Regular expression to parse an optical measurement in MPC format -const mpc_radec_regex = Regex(join( - [ - # Number regex (columns 1-5) - raw"(?P.{5})", - # Temporary designation regex (columns 6-12) - raw"(?P.{7})", - # Discovery asterisk regex (column 13) - raw"(?P.{1})", - # Publishable note regex (column 14) - raw"(?P.{1})", - # Observation technique regex (column 15) - raw"(?P.{1})", - # Year regex + space (columns 16-20) - raw"(?P\d{4}) ", - # Month regex + space (columns 21-23) - raw"(?P\d{2}) ", - # Day regex (columns 24-25) - raw"(?P\d{2})", - # Fraction of days regex (columns 26-32) - raw"(?P\.[\d\s]{6})", - # α hours regex + space (columns 33-35) - raw"(?P<α_hrs>\d{2}) ", - # α minutes regex + space (columns 36-38) - raw"(?P<α_min>\d{2}) ", - # α seconds regex (columns 39-44) - raw"(?P<α_sec>\d{2}\.[\d\s]{3})", - # δ sign regex (column 45) - raw"(?P<δ_sgn>\+|\-)", - # δ degrees regex + space (columns 46-48) - raw"(?P<δ_deg>\d{2}) ", - # δ minutes regex + space (columns 49-51) - raw"(?P<δ_min>\d{2}) ", - # δ seconds regex (columns 52-56) - raw"(?P<δ_sec>\d{2}\.[\d\s]{2})", - # Info 1 regex (columns 57-65) - raw"(?P.{9})", - # Magnitude regex (columns 66-70) - raw"(?P.{5})", - # Band regex (column 71) - raw"(?P.{1})", - # Catalogue regex (column 72) - raw"(?P.{1})", - # Info 2 regex (columns 73-77) - raw"(?P.{5})", - # Observatory code regex (columns 78-80) - raw"(?P.{3})" - ] -)) -#= -re = NEOs.mpc_radec_regex * Regex(string( - raw"(?:\n)?", - raw"(?P<_num_>.{5})?", - raw"(?P<_tmpdesig_>.{7})?", - raw"(?P<_discovery_>.{1})?", - raw"(?P<_publishnote_>.{1})?", - raw"(?P<_obstech_>.{1})?", - raw"(?P<_year_>\d{4})?(?:\s)?", - raw"(?P<_month_>\d{2})?(?:\s)?", - raw"(?P<_day_>\d{2})?", - raw"(?P<_utc_>\.[\d\s]{6})?", - raw"(?P<_sep_>1\s)?", - raw"(?P[\-\+]{1}[\.\d\s]{11})?", - raw"(?P[\-\+]{1}[\.\d\s]{11})?", - raw"(?P[\-\+]{1}[\.\d\s]{11})?" -)) - -=# - -@doc raw""" - datetime(year::Int, month::Int, day::Int, utc::T) where {T <: Real} - -Construct a `DateTime` type by parts. `utc` is the fraction of day. -""" -function datetime(year::Int, month::Int, day::Int, utc::T) where {T <: Real} - return DateTime(year, month, day) + Microsecond( round(1e6*86_400*utc) ) +function neoparse(x::RegexMatch, i::Int, ::Type{Int64}) + y = tryparse(Int64, x[i]) + if isnothing(y) + return 0 + else + return y + end end -@doc raw""" - ra(hrs::Int, min::Int, sec::T) where {T <: Real} - ra(obs::RadecMPC{T}) where {T <: AbstractFloat} +function neoparse(x::RegexMatch, i::Int, ::Type{DateTime}) + date = DateTime(x[i][1:10], "yyyy mm dd") + utc = parse(Float64, x[i][11:end]) + return date + Microsecond( round(1e6*86_400*utc) ) +end -Return the right ascension in rad. -""" -function ra(hrs::Int, min::Int, sec::T) where {T <: Real} +function neoparse(x::RegexMatch, i::Int, ::Type{RightAscension}) + # Unfold + hrs = parse(Int, x[i][1:2]) + min = parse(Int, x[i][4:5]) + sec = parse(Float64, x[i][7:end]) # Convert hours minutes seconds to deg α_deg = 15*(hrs + min/60 + sec/3_600) # Convert deg to rad @@ -180,17 +117,16 @@ function ra(hrs::Int, min::Int, sec::T) where {T <: Real} end -@doc raw""" - dec(sgn::String, deg::Int, min::Int, sec::T) where {T <: Real} - dec(obs::RadecMPC{T}) where {T <: AbstractFloat} - -Return the declination in rad. -""" -function dec(sgn::String, deg::Int, min::Int, sec::T) where {T <: Real} +function neoparse(x::RegexMatch, i::Int, ::Type{Declination}) + # Unfold + sgn = Char(x[i][1]) + deg = parse(Int, x[i][2:3]) + min = parse(Int, x[i][5:6]) + sec = parse(Float64, x[i][8:end]) # Convert degrees minutes seconds to degrees - if sgn == "+" + if sgn == '+' δ_deg = +(deg + min/60 + sec/3_600) - elseif sgn == "-" + elseif sgn == '-' δ_deg = -(deg + min/60 + sec/3_600) end @@ -199,105 +135,137 @@ function dec(sgn::String, deg::Int, min::Int, sec::T) where {T <: Real} return δ_rad end -@doc raw""" - RadecMPC(m::RegexMatch) - -Convert a match of `NEOs.mpc_radec_regex` to `RadecMPC`. -""" -function RadecMPC(m::RegexMatch) - date = datetime( - Meta.parse(m["year"]), - Meta.parse(m["month"]), - Meta.parse(m["day"]), - Meta.parse(m["utc"]) - ) - α = ra( - Meta.parse(m["α_hrs"]), - Meta.parse(m["α_min"]), - Meta.parse(m["α_sec"]) - ) - δ = dec( - string(m["δ_sgn"]), - Meta.parse(m["δ_deg"]), - Meta.parse(m["δ_min"]), - Meta.parse(m["δ_sec"]) - ) - # Find catalogue in mpc_catalogues[] that matches catalogue - catalogue = search_cat_code(string(m["catalogue"])) - # Find observatory in OBSERVATORIES_MPC[] that matches obscode - observatory = search_obs_code(string(m["obscode"])) - - return RadecMPC( - string(m["num"]), - string(m["tmpdesig"]), - string(m["discovery"]), - string(m["publishnote"]), - string(m["obstech"]), - date, - α, - δ, - string(m["info1"]), - string(m["mag"]), - string(m["band"]), - catalogue, - string(m["info2"]), - observatory - ) +neoparse(x::RegexMatch, i::Int, ::Type{CatalogueMPC}) = search_cat_code(String(x[i])) + +function neoparse(m::RegexMatch, i::Int, ::Type{ObservatoryMPC{Float64}}) + _observatory_ = search_obs_code(String(m[i])) + if isnothing(m["optional"]) + return _observatory_ + else + units = neoparse(m, 22, Int64) + x = neoparse(m, 23, Float64) + y = neoparse(m, 24, Float64) + z = neoparse(m, 25, Float64) + date = neoparse(m, 6, DateTime) + if units == 2 + x *= au + y *= au + z *= au + end + return ObservatoryMPC(_observatory_.code, x, y, z, _observatory_.name, date, :satellite, units) + end end +# Regular expression to parse an optical measurement in MPC format +const RADEC_MPC_REGEX = Regex(string( + # Number regex (columns 1-5) + raw"(?P.{5})", + # Temporary designation regex (columns 6-12) + raw"(?P.{7})", + # Discovery asterisk regex (column 13) + raw"(?P[\*\s]{1})", + # Publishable note regex (column 14) + raw"(?P.{1})", + # Observation technique regex (column 15) + raw"(?P.{1})", + # Date of observation regex (columns 16-32) + raw"(?P\d{4}\s\d{2}\s\d{2}\.[\d\s]{6})", + # Right ascension regex (columns 33-44) + raw"(?P<α>\d{2}\s\d{2}\s\d{2}\.[\d\s]{3})", + # Declination regex (columns 45-56) + raw"(?P<δ>[\+|\-]{1}\d{2}\s\d{2}\s\d{2}\.[\d\s]{2})", + # Info 1 regex (columns 57-65) + raw"(?P.{9})", + # Magnitude regex (columns 66-70) + raw"(?P[\.\s\d]{5})", + # Band regex (column 71) + raw"(?P[\w\s]{1})", + # Catalogue regex (column 72) + raw"(?P[\w\s]{1})", + # Info 2 regex (columns 73-77) + raw"(?P.{5})", + # Observatory code regex (columns 78-80) + raw"(?P\w{3})", + # Optional fields (in case of satellite observations) + # Breakline regex + raw"(?:\n)?", + # Number regex (columns 1-5) + raw"(?(?P<_num_>.{5})?", + # Temporary designation regex (columns 6-12) + raw"(?P<_tmpdesig_>.{7})?", + # Blank space regex (column 13) + raw"(?P<_discovery_>\s)?", + # Publishable note regex (column 14) + raw"(?P<_publishnote_>.{1})?", + # s regex (column 15) + raw"(?P<_obstech_>s)?", + # Date of observation regex (columns 16-32) + raw"(?P<_date_>\d{4}\s\d{2}\s\d{2}\.[\d\s]{6})", + # Units + space regex (columns 33-34) + raw"(?P<_units_>\d\s)", + # X component of geocentric vector (columns 35-46) + raw"(?P<_x_>[\-\+]{1}[\.\d\s]{11})", + # Y component of geocentric vector (columns 47-58) + raw"(?P<_y_>[\-\+]{1}[\.\d\s]{11})", + # Z component of geocentric vector (columns 59-70) + raw"(?P<_z_>[\-\+]{1}[\.\d\s]{11})", + # Band regex (column 71) + raw"(?P<_band_>[\w\s]{1})?", + # Catalogue regex (column 72) + raw"(?P<_catalogue_>[\w\s]{1})?", + # Info 2 regex (columns 73-77) + raw"(?P<_info2_>.{5})?", + # Observatory code regex (columns 78-80) + raw"(?P<_obscode_>\w{3})?)?", +)) + @doc raw""" - read_radec_mpc(filename::String) + RadecMPC(m::RegexMatch) -Return the matches of `NEOs.mpc_radec_regex` in `filename` as `RadecMPC`. +Convert a match of `NEOs.RADEC_MPC_REGEX` to `RadecMPC`. """ -function read_radec_mpc(filename::String) - # Check that filename is a file - @assert isfile(filename) "Cannot open file: $filename" - # Read lines of mpc formatted file - lines = readlines(filename) - # Apply regular expressions - matches = match.(mpc_radec_regex, lines) - # Eliminate nothings - filter!(!isnothing, matches) - # Convert matches to RadecMPC - obs = RadecMPC.(matches) - # Sort observations by date - sort!(obs) - # Eliminate repeated observations - unique!(obs) +function RadecMPC(m::RegexMatch) + # Check that matched regex is correct + @assert m.regex == RADEC_MPC_REGEX "Only matches of `NEOs.RADEC_MPC_REGEX` can be converted to `RadecMPC`." + # Field types + types = fieldtypes(RadecMPC{Float64}) + # RadecMPC{Float64} fields + args = map(i -> begin + if i == 7 + neoparse(m, i, RightAscension) + elseif i == 8 + neoparse(m, i, Declination) + else + neoparse(m, i, types[i]) + end + end, 1:length(types)) - return obs + return RadecMPC(args...) end @doc raw""" - parse_radec_mpc(text::String) - parse_radec_mpc(f::F, text::String) where F + read_radec_mpc(s::String) -Return the matches of `NEOs.mpc_radec_regex` in `text`. A function `f(m::RegexMatch) -> Bool` -can be passed to filter the matches. +Return the matches of `NEOs.RADEC_MPC_REGEX` in `s` as `RadecMPC`. """ -function parse_radec_mpc(f::F, text::String) where F - +function read_radec_mpc(s::String) + if !contains(s, "\n") && isfile(s) + # Read MPC formatted file + s = String(read(s)) + end # Vector of observations - radecs = Vector{RadecMPC{Float64}}(undef, 0) + radec = Vector{RadecMPC{Float64}}(undef, 0) # Iterate over the matches - for m in eachmatch(mpc_radec_regex, text) - # Filter by f - if f(m) - push!(radecs, RadecMPC(m)) - end - end - # If there is at least one observation - if length(radecs) > 0 - # Sort observations by date - sort!(radecs) - # Eliminate repeated observations - unique!(radecs) + for m in eachmatch(RADEC_MPC_REGEX, s) + push!(radec, RadecMPC(m)) end + # Eliminate repeated entries + unique!(radec) + # Sort observations by date + sort!(radec) - return radecs + return radec end -parse_radec_mpc(text::String) = parse_radec_mpc(t -> true, text) @doc raw""" mpc_date_str(date::DateTime) @@ -323,13 +291,7 @@ function mpc_date_str(date::DateTime) # Days string day_s = @sprintf("%09.6f", day_val) # Join everything - date_s = join([ - year_s, - " ", - month_s, - " ", - day_s, - ]) + date_s = string(year_s, " ", month_s, " ", day_s) return date_s end @@ -357,13 +319,7 @@ function mpc_α_str(α::T) where {T <: Number} # Seconds string sec_s = @sprintf("%06.3f", sec) # Join everything - α_s = join([ - hrs_s, - " ", - min_s, - " ", - sec_s, - ]) + α_s = string(hrs_s, " ", min_s, " ", sec_s) return α_s end @@ -393,52 +349,75 @@ function mpc_δ_str(δ::T) where {T <: Number} # Seconds string sec_s = @sprintf("%05.2f", sec) # Join everything - δ_s = join([ - sgn_s, - deg_s, - " ", - min_s, - " ", - sec_s, - ]) + δ_s = string(sgn_s, deg_s, " ", min_s, " ", sec_s) return δ_s end -@doc raw""" - mpc_radec_str(obs::RadecMPC{T}) where {T <: AbstractFloat} +function mpc_x_str(x::T) where {T <: AbstractFloat} + sgn = x > 0 ? "+" : "-" + y = @sprintf("%.5f", abs(x)) + y = lpad(y, 11) + return string(sgn, y) +end -Return an observation in MPC format. -""" -function mpc_radec_str(obs::RadecMPC{T}) where {T <: AbstractFloat} +# Convert `obs` to a string according to MPC format. +function string(obs::RadecMPC{T}) where {T <: AbstractFloat} + # Number string + num_s = rpad(obs.num, 5) + # Temporary designation string + tmpdesig_s = rpad(obs.tmpdesig, 7) + # Discovery asterisk string + discovery_s = rpad(obs.discovery, 1) + # Publishable note string + publishnote_s = rpad(obs.publishnote, 1) + # Observation technique string + obstech_s = rpad(obs.obstech, 1) # Date string date_s = mpc_date_str(obs.date) # Right ascension string α_s = mpc_α_str(obs.α) # Declination string δ_s = mpc_δ_str(obs.δ) + # Info 1 string + info1_s = rpad(obs.info1, 9) + # Magnitude string + mag_s = isnan(obs.mag) ? repeat(" ", 5) : @sprintf("%.2f", obs.mag) + # Band string + band_s = rpad(obs.band, 1) + # Info 2 string + info2_s = rpad(obs.info2, 5) # Catalogue string catalogue_s = isunknown(obs.catalogue) ? " " : obs.catalogue.code # Observatory string obscode_s = isunknown(obs.observatory) ? " " : obs.observatory.code # Join everything - obs_s = join([ - obs.num, - obs.tmpdesig, - obs.discovery, - obs.publishnote, - obs.obstech, - date_s, - α_s, - δ_s, - obs.info1, - obs.mag, - obs.band, - catalogue_s, - obs.info2, - obscode_s, - "\n" - ]) + obs_s = string(num_s, tmpdesig_s, discovery_s, publishnote_s, obstech_s, date_s, α_s, δ_s, + info1_s, mag_s, band_s, catalogue_s, info2_s, obscode_s) + + if issatellite(obs.observatory) + # Units string + units = obs.observatory.units + units_s = rpad(units, 1) + + x = obs.observatory.long + y = obs.observatory.cos + z = obs.observatory.sin + if units == 2 + x /= au + y /= au + z /= au + end + + # X component string + x_s = mpc_x_str(x) + # Y component string + y_s = mpc_x_str(y) + # Z component string + z_s = mpc_x_str(z) + obs_s = string(obs_s, "\n", num_s, tmpdesig_s, " ", publishnote_s, "s", date_s, + units_s, " ", x_s, y_s, z_s, " ", info2_s, obscode_s) + end return obs_s end @@ -451,8 +430,8 @@ Write `obs` to `filename` in MPC format. function write_radec_mpc(obs::Vector{RadecMPC{T}}, filename::String) where {T <: AbstractFloat} open(filename, "w") do file for i in eachindex(obs) - line = mpc_radec_str(obs[i]) - write(file, line) + line = string(obs[i]) + write(file, line, "\n") end end end @@ -474,7 +453,7 @@ function get_radec_mpc(id::Pair{String, String}, filename::String = replace(id[2 matches = Vector{RegexMatch}(undef, length(obs)) for i in eachindex(obs) s = obs[i]["original_record"] - matches[i] = match(mpc_radec_regex, s) + matches[i] = match(RADEC_MPC_REGEX, s) end filter!(!isnothing, matches) # Parse RadecMPC diff --git a/src/observations/topocentric.jl b/src/observations/topocentric.jl index c70257fa..6949f3ef 100644 --- a/src/observations/topocentric.jl +++ b/src/observations/topocentric.jl @@ -69,7 +69,7 @@ Return longitude and latitude (both in rad) of an observatory. """ function lonlat(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} # ECEF [km] - p_ECEF = obs_pos_ECEF(observatory) + p_ECEF = obsposECEF(observatory) # ECEF [m] -> Geodetic [m] lat_geodetic, lon, altitude = ecef_to_geodetic(1_000 * p_ECEF) # Geodetic [m] -> Geocentric [m] @@ -115,42 +115,67 @@ end sunriseset(radec::RadecMPC{T}) where {T <: AbstractFloat} = sunriseset(date(radec), observatory(radec)) @doc raw""" - obs_pos_ECEF(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - obs_pos_ECEF(x::RadecMPC{T}) where {T <: AbstractFloat} - obs_pos_ECEF(x::RadarJPL{T}) where {T <: AbstractFloat} + obsposECEF(observatory::ObservatoryMPC{T}; kwarg) where {T <: AbstractFloat} + obsposECEF(x::RadecMPC{T}; kwarg) where {T <: AbstractFloat} + obsposECEF(x::RadarJPL{T}; kwarg) where {T <: AbstractFloat} Return the observer's geocentric `[x, y, z]` position vector in Earth-Centered Earth-Fixed (ECEF) reference frame. + +# Keyword argument +- `eop::Union{EopIau1980, EopIau2000A}`: Earth Orientation Parameters (eop). """ -function obs_pos_ECEF(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} +function obsposECEF(observatory::ObservatoryMPC{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} # Make sure observatory has coordinates - @assert !isunknown(observatory) "Cannot compute position for unknown observatory." @assert hascoord(observatory) "Cannot compute position for observatory [$(observatory.code)] without coordinates" - # λ_deg: longitude [degrees east of Greenwich] - # u: distance from spin axis [km], u = ρ*cos(ϕ') - # v: height above equatorial plane [km], v = ρ*sin(ϕ'), - # where ϕ' is the geocentric latitude and ρ is the geocentric distance in km - - # Cilindrical components of Earth-Centered Earth-Fixed position of observer - λ_deg = observatory.long # deg - u = observatory.cos * RE # km - v = observatory.sin * RE # km - - # Cartesian components of Earth-Centered Earth-Fixed position of observer - λ_rad = deg2rad(λ_deg) # rad - x_gc = u * cos(λ_rad) # km - y_gc = u * sin(λ_rad) # km - z_gc = v # km - - # Earth-Centered Earth-Fixed position position of observer - pos_ECEF = [x_gc, y_gc, z_gc] # km - - return pos_ECEF + if issatellite(observatory) + # Ephemeris seconds since J2000 + et = datetime2et(observatory.date) + # Earth-Centered Inertial position position of observer + posvel_ECI = obsposvelECI(observatory, et; eop) + # UTC seconds + utc_secs = et - tdb_utc(et) + # Julian days UTC + jd_utc = JD_J2000 + utc_secs/daysec + # State vector + pv_ECI = OrbitStateVector(jd_utc, posvel_ECI[1:3], posvel_ECI[4:6], zeros(3)) + + # Transform position/velocity from Earth-Centered Inertial (ECI) fraom to Earth-Centered Earth-fixed (ECEF) frame + # ITRF: International Terrestrial Reference Frame + # GCRF: Geocentric Celestial Reference Frame + pv_ECEF = sv_eci_to_ecef(pv_ECI, Val(:GCRF), Val(:ITRF), jd_utc, eop) + + # ECEF position + pos_ECEF = convert(Vector{eltype(pv_ECEF.r)}, pv_ECEF.r) + + return pos_ECEF + else + # λ_deg: longitude [degrees east of Greenwich] + # u: distance from spin axis [km], u = ρ*cos(ϕ') + # v: height above equatorial plane [km], v = ρ*sin(ϕ'), + # where ϕ' is the geocentric latitude and ρ is the geocentric distance in km + + # Cilindrical components of Earth-Centered Earth-Fixed position of observer + λ_deg = observatory.long # deg + u = observatory.cos * RE # km + v = observatory.sin * RE # km + + # Cartesian components of Earth-Centered Earth-Fixed position of observer + λ_rad = deg2rad(λ_deg) # rad + x_gc = u * cos(λ_rad) # km + y_gc = u * sin(λ_rad) # km + z_gc = v # km + + # Earth-Centered Earth-Fixed position position of observer + pos_ECEF = [x_gc, y_gc, z_gc] # km + + return pos_ECEF + end end -obs_pos_ECEF(x::RadecMPC{T}) where {T <: AbstractFloat} = obs_pos_ECEF(x.observatory) -obs_pos_ECEF(x::RadarJPL{T}) where {T <: AbstractFloat} = obs_pos_ECEF(x.rcvr) +obsposECEF(x::RadecMPC{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} = obsposECEF(x.observatory; eop) +obsposECEF(x::RadarJPL{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} = obsposECEF(x.rcvr; eop) # TODO: avoid sv_ecef_to_ecef overload by defining proper product between DCMs and Taylor1/TaylorN # method below has been adapted from SatelliteToolboxTransformations.jl, MIT-licensed @@ -210,10 +235,9 @@ function sv_ecef_to_eci( end @doc raw""" - obsposvelECI(observatory::ObservatoryMPC{T}, et::T; - eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} - obsposvelECI(x::RadecMPC{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} - obsposvelECI(x::RadarJPL{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} + obsposvelECI(observatory::ObservatoryMPC{T}, et::T; kwarg) where {T <: AbstractFloat} + obsposvelECI(x::RadecMPC{T}; kwarg) where {T <: AbstractFloat} + obsposvelECI(x::RadarJPL{T}; kwarg) where {T <: AbstractFloat} Return the observer's geocentric `[x, y, z, v_x, v_y, v_z]` "state" vector in Earth-Centered Inertial (ECI) reference frame. By default, the IAU200A Earth orientation model is used to @@ -228,32 +252,44 @@ See also [`SatelliteToolboxBase.OrbitStateVector`](@ref) and [`SatelliteToolboxT - `observatory::ObservatoryMPC{T}`: observation site. - `et::T`: ephemeris time (TDB seconds since J2000.0 epoch). + +# Keyword argument + - `eop::Union{EopIau1980, EopIau2000A}`: Earth Orientation Parameters (eop). """ function obsposvelECI(observatory::ObservatoryMPC{T}, et::ET; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat, ET<:Union{T,Taylor1{T},Taylor1{TaylorN{T}}}} - # Earth-Centered Earth-Fixed position position of observer - pos_ECEF = obs_pos_ECEF(observatory) - - # UTC seconds - utc_secs = et - tdb_utc(et) - # Julian days UTC - jd_utc = JD_J2000 + utc_secs/daysec - # State vector - pv_ECEF = OrbitStateVector(jd_utc, pos_ECEF, zeros(3), zeros(3)) - - # Transform position/velocity from Earth-Centered Earth-fixed (ECEF) frame to Earth-Centered Inertial (ECI) frame - # ITRF: International Terrestrial Reference Frame - # GCRF: Geocentric Celestial Reference Frame - pv_ECI = sv_ecef_to_eci(pv_ECEF, Val(:ITRF), Val(:GCRF), jd_utc, eop) - - # Inertial position - p_ECI = convert(Vector{eltype(pv_ECI.r)}, pv_ECI.r) - # Inertial velocity - v_ECI = convert(Vector{eltype(pv_ECI.v)}, pv_ECI.v) - - # Concat position and velocity - return vcat(p_ECI, v_ECI) + + # Make sure observatory has coordinates + @assert hascoord(observatory) "Cannot compute position for observatory [$(observatory.code)] without coordinates" + + if issatellite(observatory) + #@assert datetime2et(observatory.date) == cte(et) + return [observatory.long, observatory.cos, observatory.sin, zero(T), zero(T), zero(T)] + else + # Earth-Centered Earth-Fixed position position of observer + pos_ECEF = obsposECEF(observatory) + + # UTC seconds + utc_secs = et - tdb_utc(et) + # Julian days UTC + jd_utc = JD_J2000 + utc_secs/daysec + # State vector + pv_ECEF = OrbitStateVector(jd_utc, pos_ECEF, zeros(3), zeros(3)) + + # Transform position/velocity from Earth-Centered Earth-fixed (ECEF) frame to Earth-Centered Inertial (ECI) frame + # ITRF: International Terrestrial Reference Frame + # GCRF: Geocentric Celestial Reference Frame + pv_ECI = sv_ecef_to_eci(pv_ECEF, Val(:ITRF), Val(:GCRF), jd_utc, eop) + + # Inertial position + p_ECI = convert(Vector{eltype(pv_ECI.r)}, pv_ECI.r) + # Inertial velocity + v_ECI = convert(Vector{eltype(pv_ECI.v)}, pv_ECI.v) + + # Concat position and velocity + return vcat(p_ECI, v_ECI) + end end function obsposvelECI(x::RadecMPC{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} diff --git a/test/observations.jl b/test/observations.jl index a7a827e6..b2c370f2 100644 --- a/test/observations.jl +++ b/test/observations.jl @@ -116,24 +116,24 @@ using NEOs: src_path @testset "RadecMPC" begin - using NEOs: mpc_radec_regex, RadecMPC, mpc_radec_str + using NEOs: RADEC_MPC_REGEX, RadecMPC using Dates # Parse RadecMPC apophis_s = "99942K04M04N C2004 03 15.10789 04 06 08.08 +16 55 04.6 om6394691" - apophis_m = match(mpc_radec_regex, apophis_s) + apophis_m = match(RADEC_MPC_REGEX, apophis_s) apophis = RadecMPC(apophis_m) @test apophis.num == "99942" @test apophis.tmpdesig == "K04M04N" - @test apophis.discovery == " " - @test apophis.publishnote == " " + @test apophis.discovery == "" + @test apophis.publishnote == "" @test apophis.obstech == "C" @test apophis.date == DateTime("2004-03-15T02:35:21.696") @test apophis.α == 1.0739650841580173 @test apophis.δ == 0.2952738332250385 - @test apophis.info1 == " " - @test apophis.mag == " " - @test apophis.band == " " + @test apophis.info1 == "" + @test isnan(apophis.mag) + @test apophis.band == "" @test apophis.catalogue == search_cat_code("o") @test apophis.info2 == "m6394" @test apophis.observatory == search_obs_code("691") @@ -148,7 +148,7 @@ using NEOs: src_path @test isa(source_radec, Vector{RadecMPC{Float64}}) @test issorted(source_radec) @test allunique(source_radec) - @test all( length.(mpc_radec_str.(source_radec)) .== 81) + @test all( length.(string.(source_radec)) .== 80) check_file = joinpath("data", "RADEC_2023_DW_.dat") write_radec_mpc(source_radec, check_file) @@ -169,7 +169,7 @@ using NEOs: src_path @test isa(source_radec, Vector{RadecMPC{Float64}}) @test issorted(source_radec) @test allunique(source_radec) - @test all( length.(mpc_radec_str.(source_radec)) .== 81) + @test all( map(x -> length(string(x)) ∈ [80, 161], source_radec)) check_file = joinpath("data", "99942_.txt") write_radec_mpc(source_radec, check_file) From a867ede70ebed789a82335d8ffe92ee3f4a04a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 8 Sep 2023 15:15:21 -0600 Subject: [PATCH 050/173] Minor fixes --- src/observations/radec_mpc.jl | 6 +++--- src/observations/topocentric.jl | 4 ++++ src/postprocessing/least_squares.jl | 5 +++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/observations/radec_mpc.jl b/src/observations/radec_mpc.jl index 54827744..c08cc8c8 100644 --- a/src/observations/radec_mpc.jl +++ b/src/observations/radec_mpc.jl @@ -356,9 +356,9 @@ end function mpc_x_str(x::T) where {T <: AbstractFloat} sgn = x > 0 ? "+" : "-" - y = @sprintf("%.5f", abs(x)) - y = lpad(y, 11) - return string(sgn, y) + y = string(abs(x)) + y = lpad(y, 10) + return string(sgn, y, " ") end # Convert `obs` to a string according to MPC format. diff --git a/src/observations/topocentric.jl b/src/observations/topocentric.jl index 6949f3ef..e49711ff 100644 --- a/src/observations/topocentric.jl +++ b/src/observations/topocentric.jl @@ -18,6 +18,10 @@ Day/night at a particular timezone. stop::Date utc::Int function TimeOfDay(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + if issatellite(observatory) + today = Date(date) + return new(:day, today - Day(1), today + Day(1), 0) + end # Hours from UTC utc = hours_from_UTC(observatory) # Today's sunrise / sunset diff --git a/src/postprocessing/least_squares.jl b/src/postprocessing/least_squares.jl index f6fd0143..a9026aa5 100644 --- a/src/postprocessing/least_squares.jl +++ b/src/postprocessing/least_squares.jl @@ -361,6 +361,11 @@ See also [`chi2`](@ref). function newtonls(ξs::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, niters::Int = 5) where {T <: Real} # Unfold residuals and weights res, w = unfold(ξs) + + return newtonls(res, w, x0, niters) +end + +function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, niters::Int = 5) where {T <: Real} # Number of observations nobs = length(res) # Degrees of freedom From 9ba35131385a07edee8ccb893174541a1775fae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 9 Sep 2023 16:50:33 -0600 Subject: [PATCH 051/173] Try previous maxsteps --- src/orbit_determination/gauss_method.jl | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index ec9fd13f..0a735eff 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -400,11 +400,7 @@ function adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFlo # Time difference [days] Δ_day = Δ_ms / 86_400_000 # Adaptative maxsteps - if Δ_day <= 30 - return ceil(Int, -7*Δ_day/3) + 100 - else - return ceil(Int, (Δ_day + 360)/13) - end + return 35 + ceil(Int, 5*Δ_day/160) end for i in 1:2 From 09bc1419d0dab054c1dcd62d3acfd58f197b2a03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 9 Sep 2023 19:34:14 -0600 Subject: [PATCH 052/173] Fix reduce_nights --- src/observations/process_radec.jl | 7 ++++++- src/orbit_determination/gauss_method.jl | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index f783a2e3..dddf4eb4 100644 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -592,6 +592,11 @@ end Special method of [`extrapolation`](@ref) to be used by [`gaussinitcond`](@ref). """ function extrapolation(df::AbstractDataFrame) + if !allunique(df.date) + gdf = groupby(df, :date) + df = combine(gdf, [:α, :δ] .=> x -> sum(x)/length(x), :observatory => identity, renamecols = false) + end + if isone(nrow(df)) return (observatory = df.observatory[1], date = df.date[1], α = df.α[1], δ = df.δ[1]) end @@ -619,7 +624,7 @@ function extrapolation(df::AbstractDataFrame) # Evaluate polynomials at mean date α_mean = mod2pi(α_p(t_mean)) - δ_mean = mod2pi(δ_p(t_mean)) + δ_mean = δ_p(t_mean) return (observatory = df.observatory[1], date = julian2datetime(t_julian[1] + t_mean), α = α_mean, δ = δ_mean) end diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 0a735eff..5fc17c59 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -466,13 +466,13 @@ for i in 1:2 # Backward propagation bwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_bwd, q0; order = order, abstol = abstol, parse_eqs = parse_eqs) - if length(bwd.t) == maxsteps + 1 + if bwd.t[end] > t0 - jd0 continue end # Forward propagation fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_fwd, q0; order = order, abstol = abstol, parse_eqs = parse_eqs) - if length(fwd.t) == maxsteps + 1 + if fwd.t[end] < tf - jd0 continue end # O-C residuals From 5444d6490d5acf3686e7423677bc899ac258e8b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 10 Sep 2023 16:32:42 -0600 Subject: [PATCH 053/173] Yet another adaptative maxsteps --- src/orbit_determination/gauss_method.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 5fc17c59..1f6554c2 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -400,7 +400,11 @@ function adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFlo # Time difference [days] Δ_day = Δ_ms / 86_400_000 # Adaptative maxsteps - return 35 + ceil(Int, 5*Δ_day/160) + if Δ_day <= 30 + return 50 - floor(Int, 2*Δ_day/3) + else + return ceil(Int, (Δ_day + 360)/13) + end end for i in 1:2 From 5a414e8501a636ba02ce0c5842cd7c9953846149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 10 Sep 2023 18:19:55 -0600 Subject: [PATCH 054/173] Fix tests --- src/propagation/propagation.jl | 2 +- test/propagation.jl | 52 +++++++++++++++++++--------------- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/propagation/propagation.jl b/src/propagation/propagation.jl index e4db6cc1..c5a4e7f4 100644 --- a/src/propagation/propagation.jl +++ b/src/propagation/propagation.jl @@ -178,7 +178,7 @@ function propagate_root(dynamics::D, maxsteps::Int, jd0::T, tspan::T, q0::Vector _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast = μ_ast, order = order, abstol = abstol) # Propagate orbit - @time tv, xv, psol, tvS, xvS, gvS = taylorinteg(dynamics, rvelea, _q0, _t0, _tmax, order, abstol, val(true), _params; + @time tv, xv, psol, tvS, xvS, gvS = taylorinteg(dynamics, rvelea, _q0, _t0, _tmax, order, abstol, Val(true), _params; maxsteps, parse_eqs, eventorder, newtoniter, nrabstol) return TaylorInterpolant(jd0 - JD_J2000, tv .- tv[1], psol), tvS, xvS, gvS diff --git a/test/propagation.jl b/test/propagation.jl index 44c966d3..50b49183 100644 --- a/test/propagation.jl +++ b/test/propagation.jl @@ -43,29 +43,35 @@ using InteractiveUtils: methodswith # Earth's ephemeris eph_ea = selecteph(sseph, ea) - # warmup propagation (backward and forward) + # warmup propagation (forward) NEOs.propagate( dynamics, 1, jd0, - -nyears, nyears, q0, - Val(true), order = 25, abstol = 1e-20, parse_eqs = true ) # propagate orbit - sol_bwd, sol = NEOs.propagate( + sol_bwd = NEOs.propagate( dynamics, maxsteps, jd0, -nyears, + q0, + order = 25, + abstol = 1e-20, + parse_eqs = true + ) + sol = NEOs.propagate( + dynamics, + maxsteps, + jd0, nyears, q0, - Val(true), order = 25, abstol = 1e-20, parse_eqs = true @@ -94,19 +100,20 @@ using InteractiveUtils: methodswith obs_radec_mpc_2023DW = NEOs.read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) # Compute residuals - res, _ = NEOs.residuals( + _res_ = NEOs.residuals( obs_radec_mpc_2023DW, xve=t->auday2kmsec(eph_ea(t/daysec)), xvs=t->auday2kmsec(eph_su(t/daysec)), xva=t->auday2kmsec(sol(t/daysec)) ) + res, w = NEOs.unfold(_res_) mean_radec0 = mean(res) std_radec0 = std(res) rms_radec0 = nrms(res,ones(length(res))) # un-normalized RMS - @test mean_radec0 ≈ -0.667 atol=1e-2 - @test std_radec0 ≈ 0.736 atol=1e-2 - @test rms_radec0 ≈ 0.992 atol=1e-2 + @test mean_radec0 ≈ -0.009 atol=1e-3 + @test std_radec0 ≈ 0.697 atol=1e-3 + @test rms_radec0 ≈ 0.696 atol=1e-3 # propagate orbit with perturbed initial conditions q1 = q0 + vcat(1e-3randn(3), 1e-5randn(3)) @@ -116,7 +123,6 @@ using InteractiveUtils: methodswith jd0, nyears, q1, - Val(true), order = 25, abstol = 1e-20, parse_eqs = true @@ -129,12 +135,13 @@ using InteractiveUtils: methodswith rm("test.jld2") # compute residuals for orbit with perturbed initial conditions - res1, _ = NEOs.residuals( + _res1_ = NEOs.residuals( obs_radec_mpc_2023DW, xve=t->auday2kmsec(eph_ea(t/daysec)), xvs=t->auday2kmsec(eph_su(t/daysec)), xva=t->auday2kmsec(sol1(t/daysec)) ) + res1, _ = NEOs.unfold(_res1_) mean_radec1 = mean(res1) std_radec1 = std(res1) rms_radec1 = nrms(res1,ones(length(res1))) @@ -171,7 +178,6 @@ using InteractiveUtils: methodswith jd0, nyears, q0, - Val(true), order = 25, abstol = 1e-20, parse_eqs = true @@ -184,7 +190,6 @@ using InteractiveUtils: methodswith jd0, nyears, q0, - Val(true), order = 25, abstol = 1e-20, parse_eqs = true @@ -200,12 +205,13 @@ using InteractiveUtils: methodswith obs_radec_mpc_apophis = NEOs.read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) # Compute optical astrometry residuals - res_radec, w_radec = NEOs.residuals( + _res_radec_ = NEOs.residuals( obs_radec_mpc_apophis, xve=t->auday2kmsec(eph_ea(t/daysec)), xvs=t->auday2kmsec(eph_su(t/daysec)), xva=t->auday2kmsec(sol(t/daysec)) ) + res_radec, w_radec = NEOs.unfold(_res_radec_) nobsopt = round(Int, length(res_radec)) # Compute mean optical astrometric residual (right ascension and declination) @@ -217,8 +223,8 @@ using InteractiveUtils: methodswith std_dec = std(res_dec) rms_ra = nrms(res_ra,ones(length(res_ra))) rms_dec = nrms(res_dec,ones(length(res_dec))) - @test mean_ra ≈ 0.0224 atol=1e-2 - @test std_ra ≈ 0.136 atol=1e-2 + @test mean_ra ≈ -0.0467 atol=1e-4 + @test std_ra ≈ 0.121 atol=1e-3 @test rms_ra ≈ std_ra atol=1e-2 @test mean_dec ≈ -0.0124 atol=1e-2 @test std_dec ≈ 0.0714 atol=1e-2 @@ -251,7 +257,7 @@ using InteractiveUtils: methodswith w = vcat(w_radec, w_del, w_dop) # Total normalized RMS - @test nrms(res, w) ≈ 0.375 atol=1e-2 + @test nrms(res, w) ≈ 0.364 atol=1e-3 end @testset "Jet transport propagation and TaylorN serialization" begin @@ -274,13 +280,13 @@ using InteractiveUtils: methodswith local q0 = [-0.9170913888342959, -0.37154308794738056, -0.1610606989484252, 0.009701519087787077, -0.012766026792868212, -0.0043488589639194275] .+ dq - sol = NEOs.propagate(dynamics, 10, jd0, 0.02, q0, Val(true); order, abstol, parse_eqs) + sol = NEOs.propagate(dynamics, 10, jd0, 0.02, q0; order, abstol, parse_eqs) jldsave("test.jld2"; sol) recovered_sol = JLD2.load("test.jld2", "sol") @test sol == recovered_sol rm("test.jld2") - sol, tvS, xvS, gvS = NEOs.propagate_root(dynamics, 1, jd0, 0.02, q0, Val(true); order, abstol, parse_eqs) + sol, tvS, xvS, gvS = NEOs.propagate_root(dynamics, 1, jd0, 0.02, q0; order, abstol, parse_eqs) jldsave("test.jld2"; sol, tvS, xvS, gvS) recovered_sol = JLD2.load("test.jld2", "sol") @@ -324,7 +330,6 @@ using InteractiveUtils: methodswith jd0, nyears, q0, - Val(true), order = 25, abstol = 1e-20, parse_eqs = true @@ -340,12 +345,13 @@ using InteractiveUtils: methodswith obs_radec_mpc_apophis = NEOs.read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) # Compute optical astrometry residuals - res_radec, w_radec = NEOs.residuals( + _res_radec_ = NEOs.residuals( obs_radec_mpc_apophis, xve=t->auday2kmsec(eph_ea(t/daysec)), xvs=t->auday2kmsec(eph_su(t/daysec)), xva=t->auday2kmsec(sol(t/daysec)) ) + res_radec, w_radec = NEOs.unfold(_res_radec_) nobsopt = round(Int, length(res_radec)) # Compute mean optical astrometric residual (right ascension and declination) @@ -357,8 +363,8 @@ using InteractiveUtils: methodswith std_dec = std(res_dec) rms_ra = nrms(res_ra,ones(length(res_ra))) rms_dec = nrms(res_dec,ones(length(res_dec))) - @test mean_ra ≈ 0.00574 atol=1e-2 - @test std_ra ≈ 0.136 atol=1e-2 + @test mean_ra ≈ -0.0463 atol=1e-4 + @test std_ra ≈ 0.118 atol=1e-3 @test rms_ra ≈ std_ra atol=1e-2 @test mean_dec ≈ -0.0124 atol=1e-2 @test std_dec ≈ 0.0714 atol=1e-2 From 230c9a8ca98b6436a4a9a95fe478aa919227674c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 12 Sep 2023 18:39:53 -0600 Subject: [PATCH 055/173] Fix obstech --- src/observations/radec_mpc.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/observations/radec_mpc.jl b/src/observations/radec_mpc.jl index c08cc8c8..022705b7 100644 --- a/src/observations/radec_mpc.jl +++ b/src/observations/radec_mpc.jl @@ -167,7 +167,7 @@ const RADEC_MPC_REGEX = Regex(string( # Publishable note regex (column 14) raw"(?P.{1})", # Observation technique regex (column 15) - raw"(?P.{1})", + raw"(?P[^xX]{1})", # Date of observation regex (columns 16-32) raw"(?P\d{4}\s\d{2}\s\d{2}\.[\d\s]{6})", # Right ascension regex (columns 33-44) @@ -450,7 +450,7 @@ function get_radec_mpc(id::Pair{String, String}, filename::String = replace(id[2 # Parse JSON obs = JSON.parse(text) # Find matches - matches = Vector{RegexMatch}(undef, length(obs)) + matches = Vector{Union{RegexMatch, Nothing}}(undef, length(obs)) for i in eachindex(obs) s = obs[i]["original_record"] matches[i] = match(RADEC_MPC_REGEX, s) From 505355858d7acd1838c9ff683a9b16b2e65c8865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Mon, 18 Sep 2023 08:12:21 -0600 Subject: [PATCH 056/173] Fix reduce_nights --- src/observations/process_radec.jl | 9 +++++---- src/orbit_determination/gauss_method.jl | 2 +- src/postprocessing/least_squares.jl | 5 +++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index dddf4eb4..b2a5f8bf 100644 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -610,15 +610,16 @@ function extrapolation(df::AbstractDataFrame) α_p = extrapolation([0., 1.], [0., 1.]) - # Extrapolate - if issorted(df.α) || issorted(df.α, rev = true) - α_p = extrapolation(t_rel, df.α) - elseif df.α[1] > π && df.α[end] < π + # Discontinuity 2π -> 0 + if df.α[1] > π && df.α[end] < π α = map(x -> x < π ? x + 2π : x, df.α) α_p = extrapolation(t_rel, α) + # Discontinuity 0 -> 2π elseif df.α[1] < π && df.α[end] > π α = map(x -> x > π ? x - 2π : x, df.α) α_p = extrapolation(t_rel, α) + else + α_p = extrapolation(t_rel, df.α) end δ_p = extrapolation(t_rel, df.δ) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 1f6554c2..16e5293c 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -401,7 +401,7 @@ function adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFlo Δ_day = Δ_ms / 86_400_000 # Adaptative maxsteps if Δ_day <= 30 - return 50 - floor(Int, 2*Δ_day/3) + return 55 - floor(Int, 5*Δ_day/6) else return ceil(Int, (Δ_day + 360)/13) end diff --git a/src/postprocessing/least_squares.jl b/src/postprocessing/least_squares.jl index a9026aa5..cfcbcbca 100644 --- a/src/postprocessing/least_squares.jl +++ b/src/postprocessing/least_squares.jl @@ -283,6 +283,11 @@ See also [`BHC`](@ref). function diffcorr(ξs::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, niters::Int = 5) where {T <: Real} # Unfold residuals and weights res, w = unfold(ξs) + + return diffcorr(res, w, x0, niters) +end + +function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, niters::Int = 5) where {T <: Real} # Degrees of freedom npar = length(x0) # Design matrix B, H array and normal matrix C From 22d72350ed0cfb26c2dbe5b647c1734a4e806c0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Mon, 18 Sep 2023 18:12:59 -0600 Subject: [PATCH 057/173] Fix discontinuity in reduce_nights --- src/observations/process_radec.jl | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index b2a5f8bf..655613a7 100644 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -610,16 +610,17 @@ function extrapolation(df::AbstractDataFrame) α_p = extrapolation([0., 1.], [0., 1.]) - # Discontinuity 2π -> 0 - if df.α[1] > π && df.α[end] < π + # Points in top quarter + N_top = count(x -> x > 3π/2, df.α) + # Points in bottom quarter + N_bottom = count(x -> x < π/2, df.α) + # No discontinuity + if iszero(N_top) || iszero(N_bottom) + α_p = extrapolation(t_rel, df.α) + # Discontinuity + else α = map(x -> x < π ? x + 2π : x, df.α) α_p = extrapolation(t_rel, α) - # Discontinuity 0 -> 2π - elseif df.α[1] < π && df.α[end] > π - α = map(x -> x > π ? x - 2π : x, df.α) - α_p = extrapolation(t_rel, α) - else - α_p = extrapolation(t_rel, df.α) end δ_p = extrapolation(t_rel, df.δ) From a9638627dd9327ec353d1f092f2729c80570c819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 19 Sep 2023 18:11:13 -0600 Subject: [PATCH 058/173] Fix residuals computation --- src/observations/process_radec.jl | 2 +- src/orbit_determination/gauss_method.jl | 13 +++++-------- src/postprocessing/neosolution.jl | 11 +++++++++++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index 655613a7..05a83fdc 100644 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -557,7 +557,7 @@ function residuals(obs::Vector{RadecMPC{T}}, mpc_catalogue_codes_201X::Vector{St # O-C residual ra/dec # Note: ra is multiplied by a metric factor cos(dec) to match the format of debiasing corrections res[i] = OpticalResidual( - anglediff(α_obs, α_comp) * cos(δ_obs) - α_corr, + anglediff(α_obs, α_comp) * cos(dec(obs[i])) - α_corr, δ_obs - δ_comp - δ_corr, 1 / w8^2, 1 / w8^2, diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 16e5293c..4f97d381 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -335,7 +335,11 @@ end Return a measure of how evenly distributed in time a triplet is; used within [`gauss_triplets`](@ref) to sort triplets for Gauss method. The function assumes `dates` is sorted. """ -gauss_norm(dates::Vector{DateTime}) = abs( (dates[2] - dates[1]).value - (dates[3] - dates[2]).value ) +gauss_evenness(dates::Vector{DateTime}) = abs( (dates[2] - dates[1]).value - (dates[3] - dates[2]).value ) / 86_400_000 + +gauss_optimal_span(dates::Vector{DateTime}) = abs( (dates[3] - dates[1]).value/86_400_000 - 1) + +gauss_norm(dates::Vector{DateTime}) = gauss_evenness(dates) + gauss_optimal_span(dates) @doc raw""" gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_iter::Int = 100) @@ -387,13 +391,6 @@ function gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_ite return triplets[1:n] end -function numberofdays(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - t0 = date(radec[1]) - tf = date(radec[end]) - Δ = (tf - t0).value / 86_400_000 - return Δ -end - function adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} # Time difference [ms] Δ_ms = getfield(date(radec[end]) - date(radec[1]), :value) diff --git a/src/postprocessing/neosolution.jl b/src/postprocessing/neosolution.jl index 84b0739e..cf20b872 100644 --- a/src/postprocessing/neosolution.jl +++ b/src/postprocessing/neosolution.jl @@ -116,14 +116,25 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::I eph_su = selecteph(sseph, su) # Earth's ephemeris eph_ea = selecteph(sseph, ea) + # Julian day of first (last) observation + t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) # Backward integration bwd = propagate(dynamics, maxsteps, jd0, nyears_bwd, q0; μ_ast = μ_ast, order = order, abstol = abstol, parse_eqs = parse_eqs) + + if bwd.t[end] > t0 - jd0 + return zero(NEOSolution{T, T}) + end + # Forward integration fwd = propagate(dynamics, maxsteps, jd0, nyears_fwd, q0; μ_ast = μ_ast, order = order, abstol = abstol, parse_eqs = parse_eqs) + if fwd.t[end] < tf - jd0 + return zero(NEOSolution{T, T}) + end + # Residuals res = residuals(radec, mpc_catalogue_codes_201X, truth, resol, bias_matrix; xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), From a6955848a16726cfb1e55599b597d2aebea9e3db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 20 Sep 2023 09:37:05 -0600 Subject: [PATCH 059/173] Try adaptative triplets --- src/orbit_determination/gauss_method.jl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 4f97d381..877d2fd9 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -329,6 +329,8 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da end +numberofdays(dates::Vector{DateTime}) = (dates[end] - dates[1]).value / 86_400_000 + @doc raw""" gauss_norm(dates::Vector{DateTime}) @@ -362,7 +364,11 @@ function gauss_triplets(dates::Vector{DateTime}, Δ_min::Period, Δ_max::Period, end end - sort!(triplets, by = x -> gauss_norm(dates[x])) + if numberofdays(dates) <= 1 + sort!(triplets, by = x -> gauss_norm(dates[x])) + else + sort!(triplets, by = x -> gauss_evenness(dates[x])) + end n = min(length(triplets), max_triplets) From 9cb184cbb0bb31951855f4d796c35565e7c81fae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 22 Sep 2023 17:09:42 -0600 Subject: [PATCH 060/173] Fix tests --- src/observations/topocentric.jl | 21 ++++----- src/postprocessing/least_squares.jl | 2 - test/observations.jl | 66 +++++++++++++++++++++++++++++ test/propagation.jl | 16 +++---- 4 files changed, 85 insertions(+), 20 deletions(-) diff --git a/src/observations/topocentric.jl b/src/observations/topocentric.jl index e49711ff..113f0e06 100644 --- a/src/observations/topocentric.jl +++ b/src/observations/topocentric.jl @@ -7,20 +7,21 @@ const eop_IAU2000A::EopIau2000A = fetch_iers_eop(Val(:IAU2000A)) Day/night at a particular timezone. # Fields -- `light::Symbol`: `:day` or `:night`. -- `start::Date`. -- `stop::Date`. +- `light::Symbol`: + - for ground observatories: `:day` or `:night`, + - for space observatories: `:space`. +- `start::DateTime`. +- `stop::DateTime`. - `utc::Int`: hours from UTC. """ @auto_hash_equals struct TimeOfDay light::Symbol - start::Date - stop::Date + start::DateTime + stop::DateTime utc::Int function TimeOfDay(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} if issatellite(observatory) - today = Date(date) - return new(:day, today - Day(1), today + Day(1), 0) + return new(:space, date, date, 0) end # Hours from UTC utc = hours_from_UTC(observatory) @@ -32,11 +33,11 @@ Day/night at a particular timezone. tomorrow = sunriseset(date + Day(1), observatory) # Selection if yesterday[2] <= date <= today[1] - return new(:night, yesterday[2], today[1], utc) + return new(:night, Date(yesterday[2]), Date(today[1]), utc) elseif today[1] <= date <= today[2] - return new(:day, today[1], today[2], utc) + return new(:day, Date(today[1]), Date(today[2]), utc) elseif today[2] <= date <= tomorrow[1] - return new(:night, today[2], tomorrow[1], utc) + return new(:night, Date(today[2]), Date(tomorrow[1]), utc) end end diff --git a/src/postprocessing/least_squares.jl b/src/postprocessing/least_squares.jl index cfcbcbca..22524b0f 100644 --- a/src/postprocessing/least_squares.jl +++ b/src/postprocessing/least_squares.jl @@ -130,8 +130,6 @@ function chi2(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} return sum(w .* (res.^2)) end -nms(res, w) = chi2(res, w) / length(res) - @doc raw""" nrms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} nrms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} diff --git a/test/observations.jl b/test/observations.jl index b2c370f2..ccd5327b 100644 --- a/test/observations.jl +++ b/test/observations.jl @@ -1,6 +1,7 @@ # This file is part of the NEOs.jl package; MIT licensed using NEOs +using Dates using Test using NEOs: src_path @@ -217,4 +218,69 @@ using NEOs: src_path @test source_radar == check_radar end + @testset "Topocentric" begin + using NEOs: TimeOfDay, sunriseset, obsposECEF, obsposvelECI + + # Ground observation + radec_1 = read_radec_mpc(""" + 99942 |C2012 12 12.33230011 28 40.300-26 29 32.10 17.70Vu~0mfl807 + 99942 |C2012 12 12.33730011 28 38.970-26 29 34.80 17.60Vu~0mfl807 + 99942 |C2012 12 12.34221011 28 37.640-26 29 37.50 17.50Vu~0mfl807 + 99942 |C2012 12 12.34712011 28 36.330-26 29 40.00 17.50Vu~0mfl807 + 99942 |C2012 12 12.35054011 28 35.400-26 29 41.80 17.50Vu~0mfl807 + """) + # Sattellite observation + radec_2 = read_radec_mpc(""" + 99942 S2020 12 18.97667011 30 15.530-10 46 20.20 19.00RL~4ROFC51 + 99942 s2020 12 18.9766701 - 5634.1734 - 2466.2657 - 3038.3924 ~4ROFC51 + 99942 S2020 12 19.10732011 30 22.510-10 48 20.00 L~4ROFC51 + 99942 s2020 12 19.1073201 - 5654.1816 - 2501.9465 - 2971.1902 ~4ROFC51 + 99942 S2020 12 19.23810011 30 29.500-10 50 19.60 L~4ROFC51 + 99942 s2020 12 19.2381001 - 5645.7831 - 2512.1036 - 2978.6411 ~4ROFC51 + 99942 S2020 12 19.23822011 30 29.570-10 50 19.20 L~4ROFC51 + 99942 s2020 12 19.2382201 - 5617.3465 - 2486.4031 - 3053.2209 ~4ROFC51 + """) + + # Check parsing + @test length(radec_1) == 5 + @test all( map(x -> x.observatory.code, radec_1) .== "807") + @test length(radec_2) == 4 + @test all( map(x -> x.observatory.code, radec_2) .== "C51") + + # TimeOfDay + tod_1 = TimeOfDay.(radec_1) + tod_2 = TimeOfDay.(radec_2) + # Check + @test allequal(tod_1) + @test tod_1[1].light == :night + @test tod_1[1].start == Date(2012, 12, 11) + @test tod_1[1].stop == Date(2012, 12, 12) + @test tod_1[1].utc == -5 + @test allunique(tod_2) + @test all( getfield.(tod_2, :light) .== :space ) + @test all( date.(radec_2) .== getfield.(tod_2, :start) .== getfield.(tod_2, :start) ) + @test all( getfield.(tod_2, :utc) .== 0 ) + + # Sunrise and sunset + radec = read_radec_mpc("99942 8C2020 12 08.15001011 20 07.510-08 02 54.20 18.50GV~4ROF094") + sun = sunriseset(radec[1]) + @test sun[1] == DateTime("2020-12-08T05:05:59.384") + @test sun[2] == DateTime("2020-12-08T14:05:49.386") + + # obsposECEF + ecef_2 = obsposECEF.(radec_2) + @test ecef_2[1] == [-3462.643557087632, 5076.197661798687, -3049.6756672719907] + @test ecef_2[2] == [1351.315736765706, 6027.937408384214, -2982.5146167937583] + @test ecef_2[3] == [5332.067839021762, 3112.403799578623, -2989.9547254809945] + @test ecef_2[4] == [5308.786202404402, 3079.725220466387, -3064.4773721684687] + + # obsposvelECI + eci_2 = obsposvelECI.(radec_2) + @test eci_2[1] == [-5634.1734, -2466.2657, -3038.3924, 0.0, 0.0, 0.0] + @test eci_2[2] == [-5654.1816, -2501.9465, -2971.1902, 0.0, 0.0, 0.0] + @test eci_2[3] == [-5645.7831, -2512.1036, -2978.6411, 0.0, 0.0, 0.0] + @test eci_2[4] == [-5617.3465, -2486.4031, -3053.2209, 0.0, 0.0, 0.0] + + end + end diff --git a/test/propagation.jl b/test/propagation.jl index 50b49183..fee3d4d7 100644 --- a/test/propagation.jl +++ b/test/propagation.jl @@ -111,9 +111,9 @@ using InteractiveUtils: methodswith mean_radec0 = mean(res) std_radec0 = std(res) rms_radec0 = nrms(res,ones(length(res))) # un-normalized RMS - @test mean_radec0 ≈ -0.009 atol=1e-3 - @test std_radec0 ≈ 0.697 atol=1e-3 - @test rms_radec0 ≈ 0.696 atol=1e-3 + @test mean_radec0 ≈ -0.667 atol=1e-3 + @test std_radec0 ≈ 0.736 atol=1e-3 + @test rms_radec0 ≈ 0.992 atol=1e-3 # propagate orbit with perturbed initial conditions q1 = q0 + vcat(1e-3randn(3), 1e-5randn(3)) @@ -223,8 +223,8 @@ using InteractiveUtils: methodswith std_dec = std(res_dec) rms_ra = nrms(res_ra,ones(length(res_ra))) rms_dec = nrms(res_dec,ones(length(res_dec))) - @test mean_ra ≈ -0.0467 atol=1e-4 - @test std_ra ≈ 0.121 atol=1e-3 + @test mean_ra ≈ 0.0224 atol=1e-4 + @test std_ra ≈ 0.136 atol=1e-3 @test rms_ra ≈ std_ra atol=1e-2 @test mean_dec ≈ -0.0124 atol=1e-2 @test std_dec ≈ 0.0714 atol=1e-2 @@ -257,7 +257,7 @@ using InteractiveUtils: methodswith w = vcat(w_radec, w_del, w_dop) # Total normalized RMS - @test nrms(res, w) ≈ 0.364 atol=1e-3 + @test nrms(res, w) ≈ 0.366 atol=1e-3 end @testset "Jet transport propagation and TaylorN serialization" begin @@ -363,8 +363,8 @@ using InteractiveUtils: methodswith std_dec = std(res_dec) rms_ra = nrms(res_ra,ones(length(res_ra))) rms_dec = nrms(res_dec,ones(length(res_dec))) - @test mean_ra ≈ -0.0463 atol=1e-4 - @test std_ra ≈ 0.118 atol=1e-3 + @test mean_ra ≈ 0.0083 atol=1e-4 + @test std_ra ≈ 0.136 atol=1e-3 @test rms_ra ≈ std_ra atol=1e-2 @test mean_dec ≈ -0.0124 atol=1e-2 @test std_dec ≈ 0.0714 atol=1e-2 From 50411b2536d2d6cacf66356077145cbfcee1f6ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 27 Sep 2023 17:41:44 -0600 Subject: [PATCH 061/173] Add residual rejection --- src/observations/observatory_mpc.jl | 1 + src/observations/process_radec.jl | 33 +++++++--- src/observations/topocentric.jl | 4 +- src/postprocessing/least_squares.jl | 97 ++++++++++++++++++++++------- src/postprocessing/neosolution.jl | 21 ++++++- 5 files changed, 123 insertions(+), 33 deletions(-) diff --git a/src/observations/observatory_mpc.jl b/src/observations/observatory_mpc.jl index 4df6078f..8269fa84 100644 --- a/src/observations/observatory_mpc.jl +++ b/src/observations/observatory_mpc.jl @@ -72,6 +72,7 @@ end isground(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :ground issatellite(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :satellite +isoccultation(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :occultation @doc raw""" hascoord(m::ObservatoryMPC{T}) where {T <: AbstractFloat} diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index 05a83fdc..22a6f531 100644 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -58,22 +58,39 @@ end Concatenate right ascension and declination residuals for an orbit fit. """ -function unfold(ξs::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} - L = length(ξs) - +function unfold(ξs::AbstractVector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + # Number of non outliers + L = count(x -> !x.outlier, ξs) + # Vector of residuals res = Vector{U}(undef, 2*L) + # Vector of weights w = Vector{T}(undef, 2*L) - + # Global counter + k = 1 + # Fill residuals and weights for i in eachindex(ξs) - res[i] = ξs[i].ξ_α - res[i+L] = ξs[i].ξ_δ - w[i] = ξs[i].w_α / ξs[i].relax_factor - w[i+L] = ξs[i].w_δ / ξs[i].relax_factor + if !ξs[i].outlier + # Right ascension + res[k] = ξs[i].ξ_α + w[k] = ξs[i].w_α / ξs[i].relax_factor + # Declination + res[k+L] = ξs[i].ξ_δ + w[k+L] = ξs[i].w_δ / ξs[i].relax_factor + # Update global counter + k += 1 + end end return res, w end +ra(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.ξ_α +dec(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.ξ_δ +weight_ra(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.w_α +weight_dec(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.w_δ +relax_factor(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.relax_factor +outlier(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.outlier + @doc raw""" compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter::Int = 5, xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} diff --git a/src/observations/topocentric.jl b/src/observations/topocentric.jl index 113f0e06..dbb25c3b 100644 --- a/src/observations/topocentric.jl +++ b/src/observations/topocentric.jl @@ -134,7 +134,7 @@ function obsposECEF(observatory::ObservatoryMPC{T}; eop::Union{EopIau1980, EopIa # Make sure observatory has coordinates @assert hascoord(observatory) "Cannot compute position for observatory [$(observatory.code)] without coordinates" - if issatellite(observatory) + if issatellite(observatory) || isoccultation(observatory) # Ephemeris seconds since J2000 et = datetime2et(observatory.date) # Earth-Centered Inertial position position of observer @@ -268,7 +268,7 @@ function obsposvelECI(observatory::ObservatoryMPC{T}, et::ET; # Make sure observatory has coordinates @assert hascoord(observatory) "Cannot compute position for observatory [$(observatory.code)] without coordinates" - if issatellite(observatory) + if issatellite(observatory) || isoccultation(observatory) #@assert datetime2et(observatory.date) == cte(et) return [observatory.long, observatory.cos, observatory.sin, zero(T), zero(T), zero(T)] else diff --git a/src/postprocessing/least_squares.jl b/src/postprocessing/least_squares.jl index 22524b0f..97b604c4 100644 --- a/src/postprocessing/least_squares.jl +++ b/src/postprocessing/least_squares.jl @@ -56,43 +56,96 @@ Outlier rejection algorithm. !!! reference See https://doi.org/10.1016/S0019-1035(03)00051-4. """ -function outlier_rejection(ξs::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}; χ2_rec::T = 7., χ2_rej::T = 8., - α::T = 0.25) where {T <: Real} - # Number of residuals - N = length(ξs) - # Vector of chi2s - χ2s = Vector{T}(undef, N) +function outlier_rejection(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}; + χ2_rec::T = 7., χ2_rej::T = 8., α::T = 0.25, max_per::T = 10.) where {T <: Real} + # Number of residuals + L = length(res) + # Evaluate residuals + eval_res = res(fit.x) + # Vector of χ2 + χ2s = Vector{T}(undef, L) + # Maximum χ2 (over non outliers) + χ2_max = zero(T) + # Number of non outliers + N_sel = 0 + + # Compute χ2s for i in eachindex(χ2s) + # Weights of current residual + w_α, w_δ = res[i].w_α/res[i].relax_factor, res[i].w_δ/res[i].relax_factor # Current observation covariance matrix - γ = diagm([ξs[i].w_α/ξs[i].relax_factor, ξs[i].w_δ/ξs[i].relax_factor]) + γ = [w_α zero(T); zero(T) w_δ] # Current model matrix - A = hcat(TS.gradient(ξs[i].ξ_α)(fit.x), TS.gradient(ξs[i].ξ_δ)(fit.x)) + A = hcat(TS.gradient(res[i].ξ_α)(fit.x), TS.gradient(res[i].ξ_δ)(fit.x)) # Outlier sign - outlier_sign = ξs[i].outlier*2-1 + outlier_sign = res[i].outlier*2-1 # Current residual covariance matrix γ_ξ = γ + outlier_sign*(A')*fit.Γ*A # Current residual - ξ = [ξs[i].ξ_α(fit.x), ξs[i].ξ_δ(fit.x)] + ξ = [eval_res[i].ξ_α, eval_res[i].ξ_δ] # Current chi2 χ2s[i] = ξ' * inv(γ_ξ) * ξ + # Update N_sel + if !res[i].outlier + N_sel += 1 + # Update maximum χ2 + if χ2s[i] > χ2_max + χ2_max = χ2s[i] + end + end end - χ2_max = maximum(χ2s) - new_ξs = Vector{OpticalResidual{T, TaylorN{T}}}(undef, N) - N_sel = count(x -> !x.outlier, ξs) - - for i in eachindex(χ2s) - if χ2s[i] > max(χ2_rej + carpino_smoothing(N_sel), α*χ2_max) - new_ξs[i] = OpticalResidual(ξs[i].ξ_α, ξs[i].ξ_δ, ξs[i].w_α, ξs[i].w_δ, ξs[i].relax_factor, true) + # Maximum allowed drops + max_drop = ceil(Int, max_per * L / 100) + # Number of dropped residuals + N_drop = 0 + # New outliers + new_outliers = outlier.(res) + # Sort χ2s + idxs = sortperm(χ2s, rev = true) + # Rejection threshold + χ2_rej = max(χ2_rej + carpino_smoothing(N_sel), α*χ2_max) + + for i in idxs + if χ2s[i] > χ2_rej && N_drop < max_drop + new_outliers[i] = true + N_drop += 1 elseif χ2s[i] < χ2_rec - new_ξs[i] = OpticalResidual(ξs[i].ξ_α, ξs[i].ξ_δ, ξs[i].w_α, ξs[i].w_δ, ξs[i].relax_factor, false) - else - new_ξs[i] = ξs[i] + new_outliers[i] = false + end + end + + if N_drop == max_drop + return OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) + end + + # Residuals norm + norms = map(x -> x.w_α * x.ξ_α^2 + x.w_δ * x.ξ_δ^2, eval_res) + # Residuals included in fit + new_outliers = .!new_outliers + # Initial NRMS + Q = nrms(view(eval_res, new_outliers)) + # Sort norms + idxs = sortperm(norms, rev = true) + + for i in view(idxs, 1:(max_drop - N_drop)) + if new_outliers[i] + # Try removing i-th residual + new_outliers[i] = false + # NRMS without i-th residual + _Q_ = nrms(view(eval_res, new_outliers)) + if _Q_ < 1 + break + elseif _Q_ < Q + Q = _Q_ + else + new_outliers[i] = true + end end end - return new_ξs + return OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), .!new_outliers) end @doc raw""" @@ -158,7 +211,7 @@ function nrms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} return sqrt( chi2(res, w)/length(res) ) end -function nrms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} +function nrms(res::AbstractVector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} res_, w = unfold(res) return nrms(res_, w) end diff --git a/src/postprocessing/neosolution.jl b/src/postprocessing/neosolution.jl index cf20b872..694acb2b 100644 --- a/src/postprocessing/neosolution.jl +++ b/src/postprocessing/neosolution.jl @@ -142,7 +142,26 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::I # Orbit fit fit = tryls(res, zeros(get_numvars()), niter) - # Return NEOs solution + if nrms(res, fit) < 1 + return evalfit(NEOSolution(bwd, fwd, res, fit)) + end + + # Orbit fit / outlier rejection loop + mask, _mask_ = outlier.(res), outlier.(res) + for i in 1:10 + # Update outliers + res = outlier_rejection(res, fit) + # Update fit + fit = tryls(res, zeros(get_numvars()), niter) + + _mask_ = outlier.(res) + if all( mask .== _mask_ ) + break + else + mask = _mask_ + end + end + return evalfit(NEOSolution(bwd, fwd, res, fit)) end From 7efb86fe3ef2de8568013bb1ddd12b4a88516b50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 28 Sep 2023 07:23:24 -0600 Subject: [PATCH 062/173] Remove nyears as orbitdet args --- src/NEOs.jl | 7 ++++--- src/postprocessing/neosolution.jl | 19 +++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index 399a3f18..1d308d54 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -33,7 +33,8 @@ export d_EM_km, d_EM_au export unknowncat, isunknown, read_catalogues_mpc, write_catalogues_mpc, update_catalogues_mpc, search_cat_code # ObservatoryMPC -export unknownobs, hascoord, read_observatories_mpc, write_observatories_mpc, update_observatories_mpc, search_obs_code +export unknownobs, hascoord, read_observatories_mpc, write_observatories_mpc, update_observatories_mpc, search_obs_code, + issatellite # RadecMPC export num, tmpdesig, discovery, publishnote, obstech, ra, dec, info1, mag, band, catalogue, info2, observatory, read_radec_mpc, search_circulars_mpc, write_radec_mpc, get_radec_mpc @@ -51,7 +52,7 @@ export pv2kep, yarkp2adot # Topocentric export obsposECEF, obsposvelECI # Process radec -export compute_radec, select_debiasing_table, debiasing, w8sveres17, residuals +export compute_radec, select_debiasing_table, debiasing, w8sveres17, residuals, unfold, relax_factor, outlier # Process radar export compute_delay, radar_astrometry # Gauss method @@ -62,7 +63,7 @@ export RNp1BP_pN_A_J23E_J2S_ng_eph_threads!, RNp1BP_pN_A_J23E_J2S_eph_threads! export propagate, propagate_lyap, propagate_root # Post processing export valsecchi_circle, nrms, chi2, newtonls, newtonls_6v, diffcorr, newtonls_Q, bopik, tryls, project, - orbitdetermination + orbitdetermination, outlier_rejection include("constants.jl") include("observations/process_radar.jl") diff --git a/src/postprocessing/neosolution.jl b/src/postprocessing/neosolution.jl index 694acb2b..5da3b776 100644 --- a/src/postprocessing/neosolution.jl +++ b/src/postprocessing/neosolution.jl @@ -99,18 +99,17 @@ end iszero(x::NEOSolution{T, U}) where {T <: Real, U <: Number} = x == zero(NEOSolution{T, U}) -function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::Int, jd0::T, nyears_bwd::T, nyears_fwd::T, - q0::Vector{U}; debias_table::String = "2018", kwargs...) where {T <: Real, U <: Number, D} +function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::Int, jd0::T, q0::Vector{U}; + debias_table::String = "2018", kwargs...) where {T <: Real, U <: Number, D} mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) - return orbitdetermination(radec, dynamics, maxsteps, jd0, nyears_bwd, nyears_fwd, q0, + return orbitdetermination(radec, dynamics, maxsteps, jd0, q0, mpc_catalogue_codes_201X, truth, resol, bias_matrix; kwargs...) end -function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::Int, jd0::T, nyears_bwd::T, - nyears_fwd::T, q0::Vector{U}, mpc_catalogue_codes_201X::Vector{String}, truth::String, - resol::Resolution, bias_matrix::Matrix{T}; niter::Int = 5, order::Int = order, - abstol::T = abstol, parse_eqs::Bool = true, - μ_ast::Vector = μ_ast343_DE430[1:end], ) where {T <: Real, U <: Number, D} +function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::Int, jd0::T, q0::Vector{U}, + mpc_catalogue_codes_201X::Vector{String}, truth::String, resol::Resolution, + bias_matrix::Matrix{T}; niter::Int = 5, order::Int = order, abstol::T = abstol, + parse_eqs::Bool = true, μ_ast::Vector = μ_ast343_DE430[1:end]) where {T <: Real, U <: Number, D} # Sun's ephemeris eph_su = selecteph(sseph, su) @@ -118,6 +117,10 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::I eph_ea = selecteph(sseph, ea) # Julian day of first (last) observation t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) + # Number of years in forward integration + nyears_fwd = (tf - jd0 + 2) / yr + # Number of years in backward integration + nyears_bwd = -(jd0 - t0 + 2) / yr # Backward integration bwd = propagate(dynamics, maxsteps, jd0, nyears_bwd, q0; μ_ast = μ_ast, order = order, From c0c5f92ae4347062fbe8bb46501574a61ef2e633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 29 Sep 2023 11:01:14 -0600 Subject: [PATCH 063/173] Retry residual rejection --- src/NEOs.jl | 1 + src/postprocessing/least_squares.jl | 35 +++-------------------------- src/postprocessing/neosolution.jl | 32 ++++++++++++++++++++++++-- test/observations.jl | 2 +- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index 1d308d54..339e24bb 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -26,6 +26,7 @@ using DataFrames: AbstractDataFrame, GroupedDataFrame, DataFrame, nrow, eachcol, using HTTP: get using IntervalRootFinding: roots, interval, Interval, mid using Interpolations: Flat, Gridded, Linear, interpolate, extrapolate +using StatsBase: quantile # Constants export d_EM_km, d_EM_au diff --git a/src/postprocessing/least_squares.jl b/src/postprocessing/least_squares.jl index 97b604c4..0af7e223 100644 --- a/src/postprocessing/least_squares.jl +++ b/src/postprocessing/least_squares.jl @@ -4,7 +4,7 @@ A least squares fit. # Fields -- `success::Bool`: wheter the routine converged or not. +- `success::Bool`: whether the routine converged or not. - `x::Vector{T}`: deltas that minimize the objective function. - `Γ::Matrix{T}`: covariance matrix. - `routine::Symbol`: minimization routine (`:newton` or `:diffcorr`). @@ -73,7 +73,7 @@ function outlier_rejection(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::Orb # Compute χ2s for i in eachindex(χ2s) # Weights of current residual - w_α, w_δ = res[i].w_α/res[i].relax_factor, res[i].w_δ/res[i].relax_factor + w_α, w_δ = res[i].w_α / res[i].relax_factor, res[i].w_δ / res[i].relax_factor # Current observation covariance matrix γ = [w_α zero(T); zero(T) w_δ] # Current model matrix @@ -116,36 +116,7 @@ function outlier_rejection(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::Orb end end - if N_drop == max_drop - return OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) - end - - # Residuals norm - norms = map(x -> x.w_α * x.ξ_α^2 + x.w_δ * x.ξ_δ^2, eval_res) - # Residuals included in fit - new_outliers = .!new_outliers - # Initial NRMS - Q = nrms(view(eval_res, new_outliers)) - # Sort norms - idxs = sortperm(norms, rev = true) - - for i in view(idxs, 1:(max_drop - N_drop)) - if new_outliers[i] - # Try removing i-th residual - new_outliers[i] = false - # NRMS without i-th residual - _Q_ = nrms(view(eval_res, new_outliers)) - if _Q_ < 1 - break - elseif _Q_ < Q - Q = _Q_ - else - new_outliers[i] = true - end - end - end - - return OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), .!new_outliers) + return OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) end @doc raw""" diff --git a/src/postprocessing/neosolution.jl b/src/postprocessing/neosolution.jl index 5da3b776..8c4a46dc 100644 --- a/src/postprocessing/neosolution.jl +++ b/src/postprocessing/neosolution.jl @@ -99,6 +99,34 @@ end iszero(x::NEOSolution{T, U}) where {T <: Real, U <: Number} = x == zero(NEOSolution{T, U}) +function residual_rejection(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}; + max_per::T = 10., quan::T = 0.95) where {T <: Real} + + @assert zero(T) <= quan <= one(T) "Quantile must be between 0 and 1 (got $quan)" + # Number of residuals + L = length(res) + # Maximum allowed drops + max_drop = ceil(Int, max_per * L / 100) + # Evaluate residuals + eval_res = res(fit.x) + # Residuals norm + norms = map(x -> x.w_α * x.ξ_α^2 / x.relax_factor + x.w_δ * x.ξ_δ^2 / x.relax_factor, eval_res) + # Residuals included in fit + new_outliers = .!outlier.(res) + # Initial NRMS + Q = quantile(norms, quan) + # Sort norms + idxs = sortperm(norms, rev = true) + + for i in view(idxs, 1:max_drop) + if new_outliers[i] && norms[i] >= Q + new_outliers[i] = false + end + end + + return OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), .!new_outliers) +end + function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::Int, jd0::T, q0::Vector{U}; debias_table::String = "2018", kwargs...) where {T <: Real, U <: Number, D} mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) @@ -154,6 +182,7 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::I for i in 1:10 # Update outliers res = outlier_rejection(res, fit) + res = residual_rejection(res, fit) # Update fit fit = tryls(res, zeros(get_numvars()), niter) @@ -164,9 +193,8 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::I mask = _mask_ end end - - return evalfit(NEOSolution(bwd, fwd, res, fit)) + return evalfit(NEOSolution(bwd, fwd, res, fit)) end function nrms(sol::NEOSolution{T, T}) where {T <: Real} diff --git a/test/observations.jl b/test/observations.jl index ccd5327b..2b56afe1 100644 --- a/test/observations.jl +++ b/test/observations.jl @@ -270,7 +270,7 @@ using NEOs: src_path # obsposECEF ecef_2 = obsposECEF.(radec_2) @test ecef_2[1] == [-3462.643557087632, 5076.197661798687, -3049.6756672719907] - @test ecef_2[2] == [1351.315736765706, 6027.937408384214, -2982.5146167937583] + @test ecef_2[2] ≈ [1351.315736765706, 6027.937408384214, -2982.5146167937583] @test ecef_2[3] == [5332.067839021762, 3112.403799578623, -2989.9547254809945] @test ecef_2[4] == [5308.786202404402, 3079.725220466387, -3064.4773721684687] From 0cb68d2de5e9f5b765b8feb35471fa85fbb3cd2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 29 Sep 2023 16:36:34 -0600 Subject: [PATCH 064/173] Fix tests --- src/NEOs.jl | 2 +- test/observations.jl | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index 339e24bb..5a694f08 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -64,7 +64,7 @@ export RNp1BP_pN_A_J23E_J2S_ng_eph_threads!, RNp1BP_pN_A_J23E_J2S_eph_threads! export propagate, propagate_lyap, propagate_root # Post processing export valsecchi_circle, nrms, chi2, newtonls, newtonls_6v, diffcorr, newtonls_Q, bopik, tryls, project, - orbitdetermination, outlier_rejection + orbitdetermination, outlier_rejection, residual_rejection include("constants.jl") include("observations/process_radar.jl") diff --git a/test/observations.jl b/test/observations.jl index 2b56afe1..b480bdc0 100644 --- a/test/observations.jl +++ b/test/observations.jl @@ -269,10 +269,10 @@ using NEOs: src_path # obsposECEF ecef_2 = obsposECEF.(radec_2) - @test ecef_2[1] == [-3462.643557087632, 5076.197661798687, -3049.6756672719907] + @test ecef_2[1] ≈ [-3462.643557087632, 5076.197661798687, -3049.6756672719907] @test ecef_2[2] ≈ [1351.315736765706, 6027.937408384214, -2982.5146167937583] - @test ecef_2[3] == [5332.067839021762, 3112.403799578623, -2989.9547254809945] - @test ecef_2[4] == [5308.786202404402, 3079.725220466387, -3064.4773721684687] + @test ecef_2[3] ≈ [5332.067839021762, 3112.403799578623, -2989.9547254809945] + @test ecef_2[4] ≈ [5308.786202404402, 3079.725220466387, -3064.4773721684687] # obsposvelECI eci_2 = obsposvelECI.(radec_2) From 44b20f6f1083efd6d42178be35d3520919a61db6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 29 Sep 2023 16:48:19 -0600 Subject: [PATCH 065/173] Fix more tests --- test/observations.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/observations.jl b/test/observations.jl index b480bdc0..f66c2f06 100644 --- a/test/observations.jl +++ b/test/observations.jl @@ -264,8 +264,8 @@ using NEOs: src_path # Sunrise and sunset radec = read_radec_mpc("99942 8C2020 12 08.15001011 20 07.510-08 02 54.20 18.50GV~4ROF094") sun = sunriseset(radec[1]) - @test sun[1] == DateTime("2020-12-08T05:05:59.384") - @test sun[2] == DateTime("2020-12-08T14:05:49.386") + @test datetime2julian(sun[1]) ≈ datetime2julian(DateTime("2020-12-08T05:05:59.384")) + @test datetime2julian(sun[2]) ≈ datetime2julian(DateTime("2020-12-08T14:05:49.386")) # obsposECEF ecef_2 = obsposECEF.(radec_2) From 46d2526e611d547a05e877533c7b35b1973d29bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 29 Sep 2023 18:36:36 -0600 Subject: [PATCH 066/173] Add preliminary gauss tests --- test/gauss.jl | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ test/runtests.jl | 1 + 2 files changed, 66 insertions(+) create mode 100644 test/gauss.jl diff --git a/test/gauss.jl b/test/gauss.jl new file mode 100644 index 00000000..23939678 --- /dev/null +++ b/test/gauss.jl @@ -0,0 +1,65 @@ +# This file is part of the NEOs.jl package; MIT licensed + +using NEOs +using PlanetaryEphemeris +using LinearAlgebra +using Test + +using NEOs: NEOSolution, adaptative_maxsteps, scaled_variables +@testset "Gauss initial conditions" begin + # Load observations + radec = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) + # Abstolute tolerance + abstol = 1e-20 + # Order (wrt time) + order = 25 + + # Gauss initial conditions + sol = gaussinitcond(radec; order = order, abstol = abstol) + + @test isa(sol, NEOSolution{Float64, Float64}) + @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] + @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] + @test all( norm.(sol.bwd.x, Inf) .< 2 ) + @test all( norm.(sol.fwd.x, Inf) .< 2 ) + @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) + @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) + @test length(sol.res) == 123 + @test string(sol.fit.routine) == "diffcorr" + @test sol.fit.success + @test all( sqrt.(diag(sol.fit.Γ)) .< 10 ) + @test nrms(sol) < 0.4 + + # Dynamical function + dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! + # Use @taylorize + parse_eqs = true + # Maximum number of steps + maxsteps = adaptative_maxsteps(radec) + # Initil time of integration + jd0 = sol.bwd.t0 + PE.J2000 + # Initial conditions (Float64) + q00 = sol(sol.bwd.t0) + # Jet transport perturbation + dq = scaled_variables("δx", fill(1e-6, 6); order = 5) + # Initial conditions (Jet transport) + q0 = q00 .+ dq + + # Orbit determination (with outlier rejection) + sol = orbitdetermination(radec, dynamics, maxsteps, jd0, q0; + order = order, abstol = abstol, parse_eqs = parse_eqs) + + @test isa(sol, NEOSolution{Float64, Float64}) + @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] + @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] + @test all( norm.(sol.bwd.x, Inf) .< 2 ) + @test all( norm.(sol.fwd.x, Inf) .< 2 ) + @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) + @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) + @test length(sol.res) == 123 + @test string(sol.fit.routine) == "newton" + @test sol.fit.success + @test all( sqrt.(diag(sol.fit.Γ)) .< 100 ) + @test nrms(sol) < 0.4 + @test count(outlier.(sol.res)) == 0 +end \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index 148d198e..97c6dc72 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,6 +4,7 @@ testfiles = ( "osculating.jl", "observations.jl", "propagation.jl", + "gauss.jl", "extensions.jl" ) From 6d0b20e5b0b78304c46c9980c0eec3f7806f03da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 30 Sep 2023 09:49:51 -0600 Subject: [PATCH 067/173] Fix Gauss tests --- test/gauss.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/gauss.jl b/test/gauss.jl index 23939678..197bb0d3 100644 --- a/test/gauss.jl +++ b/test/gauss.jl @@ -25,7 +25,6 @@ using NEOs: NEOSolution, adaptative_maxsteps, scaled_variables @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) @test length(sol.res) == 123 - @test string(sol.fit.routine) == "diffcorr" @test sol.fit.success @test all( sqrt.(diag(sol.fit.Γ)) .< 10 ) @test nrms(sol) < 0.4 @@ -57,7 +56,6 @@ using NEOs: NEOSolution, adaptative_maxsteps, scaled_variables @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) @test length(sol.res) == 123 - @test string(sol.fit.routine) == "newton" @test sol.fit.success @test all( sqrt.(diag(sol.fit.Γ)) .< 100 ) @test nrms(sol) < 0.4 From d5f3983cfbd6215ca4b8570c3907cb229f907377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 1 Oct 2023 09:56:11 -0600 Subject: [PATCH 068/173] Comment out residual rejection --- src/postprocessing/neosolution.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/postprocessing/neosolution.jl b/src/postprocessing/neosolution.jl index 8c4a46dc..fdaf407e 100644 --- a/src/postprocessing/neosolution.jl +++ b/src/postprocessing/neosolution.jl @@ -182,7 +182,7 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::I for i in 1:10 # Update outliers res = outlier_rejection(res, fit) - res = residual_rejection(res, fit) + # res = residual_rejection(res, fit) # Update fit fit = tryls(res, zeros(get_numvars()), niter) From 5222eec1c14129c01c9da9ec720d89adf32207d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 3 Oct 2023 14:42:06 -0600 Subject: [PATCH 069/173] Outlier rejection by mean point --- src/postprocessing/neosolution.jl | 155 +++++++++++++++++++++--------- test/gauss.jl | 18 +--- 2 files changed, 108 insertions(+), 65 deletions(-) diff --git a/src/postprocessing/neosolution.jl b/src/postprocessing/neosolution.jl index fdaf407e..80c63680 100644 --- a/src/postprocessing/neosolution.jl +++ b/src/postprocessing/neosolution.jl @@ -99,56 +99,46 @@ end iszero(x::NEOSolution{T, U}) where {T <: Real, U <: Number} = x == zero(NEOSolution{T, U}) -function residual_rejection(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}; - max_per::T = 10., quan::T = 0.95) where {T <: Real} - - @assert zero(T) <= quan <= one(T) "Quantile must be between 0 and 1 (got $quan)" - # Number of residuals - L = length(res) - # Maximum allowed drops - max_drop = ceil(Int, max_per * L / 100) - # Evaluate residuals - eval_res = res(fit.x) - # Residuals norm - norms = map(x -> x.w_α * x.ξ_α^2 / x.relax_factor + x.w_δ * x.ξ_δ^2 / x.relax_factor, eval_res) - # Residuals included in fit - new_outliers = .!outlier.(res) - # Initial NRMS - Q = quantile(norms, quan) - # Sort norms - idxs = sortperm(norms, rev = true) - - for i in view(idxs, 1:max_drop) - if new_outliers[i] && norms[i] >= Q - new_outliers[i] = false - end - end +@doc raw""" + residual_norm(x::OpticalResidual{T, T}) where {T <: Real} - return OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), .!new_outliers) -end +Return the contribution of `x` to the nrms. +""" +residual_norm(x::OpticalResidual{T, T}) where {T <: Real} = x.w_α * x.ξ_α^2 / x.relax_factor + x.w_δ * x.ξ_δ^2 / x.relax_factor -function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::Int, jd0::T, q0::Vector{U}; - debias_table::String = "2018", kwargs...) where {T <: Real, U <: Number, D} +function orbitdetermination(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}; + debias_table::String = "2018", kwargs...) where {T <: Real} mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) - return orbitdetermination(radec, dynamics, maxsteps, jd0, q0, - mpc_catalogue_codes_201X, truth, resol, bias_matrix; kwargs...) + return orbitdetermination(radec, sol, mpc_catalogue_codes_201X, truth, resol, bias_matrix; kwargs...) end -function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::Int, jd0::T, q0::Vector{U}, - mpc_catalogue_codes_201X::Vector{String}, truth::String, resol::Resolution, - bias_matrix::Matrix{T}; niter::Int = 5, order::Int = order, abstol::T = abstol, - parse_eqs::Bool = true, μ_ast::Vector = μ_ast343_DE430[1:end]) where {T <: Real, U <: Number, D} +function orbitdetermination(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, mpc_catalogue_codes_201X::Vector{String}, + truth::String, resol::Resolution, bias_matrix::Matrix{T}; max_per = 18., niter::Int = 5, + order::Int = order, varorder::Int = 5, abstol::T = abstol, parse_eqs::Bool = true, + μ_ast::Vector = μ_ast343_DE430[1:end]) where {T <: Real} # Sun's ephemeris eph_su = selecteph(sseph, su) # Earth's ephemeris eph_ea = selecteph(sseph, ea) + # Julian day to start propagation + jd0 = sol.bwd.t0 + PE.J2000 # Julian day of first (last) observation t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) # Number of years in forward integration nyears_fwd = (tf - jd0 + 2) / yr # Number of years in backward integration nyears_bwd = -(jd0 - t0 + 2) / yr + # Dynamical function + dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! + # Maximum number of steps + maxsteps = adaptative_maxsteps(radec) + # Initial conditions (T) + q00 = sol(sol.bwd.t0) + # Jet transport perturbation + dq = scaled_variables("δx", fill(1e-6, 6); order = varorder) + # Initial conditions (jet transport) + q0 = q00 .+ dq # Backward integration bwd = propagate(dynamics, maxsteps, jd0, nyears_bwd, q0; μ_ast = μ_ast, order = order, @@ -176,24 +166,93 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, dynamics::D, maxsteps::I if nrms(res, fit) < 1 return evalfit(NEOSolution(bwd, fwd, res, fit)) end - - # Orbit fit / outlier rejection loop - mask, _mask_ = outlier.(res), outlier.(res) - for i in 1:10 - # Update outliers - res = outlier_rejection(res, fit) - # res = residual_rejection(res, fit) - # Update fit - fit = tryls(res, zeros(get_numvars()), niter) - _mask_ = outlier.(res) - if all( mask .== _mask_ ) - break - else - mask = _mask_ + # Number of observations + N_radec = length(radec) + # Maximum allowed outliers + max_drop = ceil(Int, N_radec * max_per / 100) + # Boolean mask (0: included in fit, 1: outlier) + new_outliers = BitVector(zeros(N_radec)) + + # Drop loop + for i in 1:max_drop + # Contribution of each residual to nrms + norms = residual_norm.(res(fit.x)) + # Iterate norms from largest to smallest + idxs = sortperm(norms, rev = true) + + for j in idxs + if !new_outliers[j] + # Drop residual + new_outliers[j] = true + # Update residuals + res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) + # Update fit + fit = newtonls(res, zeros(get_numvars()), niter) + break + end end end + # Outliers + idxs = Vector{Int}(undef, max_drop) + # NRMS + Qs = Vector{T}(undef, max_drop) + # Number of outliers + N_outliers = Vector{T}(undef, max_drop) + + # Recovery loop + for i in 1:max_drop + # NRMS of current fit + Qs[i] = nrms(res, fit) + # Number of outliers in current fit + N_outliers[i] = float(max_drop - i + 1) + # Contribution of each residual to nrms + norms = residual_norm.(res(fit.x)) + # Minimum norm among outliers + j = findmin(norms[new_outliers])[2] + # Find residual with minimum norm + j = findall(new_outliers)[j] + # Add j-th residual to outliers list + idxs[i] = j + # Recover residual + new_outliers[j] = false + # Update residuals + res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) + # Update fit + fit = newtonls(res, zeros(get_numvars()), niter) + end + + # Assemble points + points = [[Qs[i], N_outliers[i]] for i in 1:max_drop] + # Remove points with Q > 1 + filter!(x -> x[1] < 1., points) + @show points + # Mean point + avg = sum(points) ./ length(points) + # Number of remaining points + N_points = length(points) + # Find optimal fit + if N_points == 0 + idxs = Vector{Int}(undef, 0) + elseif N_points <= 2 + idxs = idxs[N_points:end] + else + # Distance from each point to mean points + diff = [norm([Qs[i], N_outliers[i]] .- avg) for i in 1:max_drop] + # Find pair closest to mean point + i = findmin(diff)[2] + end + + # Reset boolean mask + new_outliers[1:end] .= false + # Outliers + new_outliers[idxs[i:end]] .= true + # Update residuals + res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) + # Update fit + fit = newtonls(res, zeros(get_numvars()), niter) + return evalfit(NEOSolution(bwd, fwd, res, fit)) end diff --git a/test/gauss.jl b/test/gauss.jl index 197bb0d3..1ddb858e 100644 --- a/test/gauss.jl +++ b/test/gauss.jl @@ -29,24 +29,8 @@ using NEOs: NEOSolution, adaptative_maxsteps, scaled_variables @test all( sqrt.(diag(sol.fit.Γ)) .< 10 ) @test nrms(sol) < 0.4 - # Dynamical function - dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! - # Use @taylorize - parse_eqs = true - # Maximum number of steps - maxsteps = adaptative_maxsteps(radec) - # Initil time of integration - jd0 = sol.bwd.t0 + PE.J2000 - # Initial conditions (Float64) - q00 = sol(sol.bwd.t0) - # Jet transport perturbation - dq = scaled_variables("δx", fill(1e-6, 6); order = 5) - # Initial conditions (Jet transport) - q0 = q00 .+ dq - # Orbit determination (with outlier rejection) - sol = orbitdetermination(radec, dynamics, maxsteps, jd0, q0; - order = order, abstol = abstol, parse_eqs = parse_eqs) + sol = orbitdetermination(radec, sol; order = order, abstol = abstol, parse_eqs = parse_eqs) @test isa(sol, NEOSolution{Float64, Float64}) @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] From 5b5ae2a50b3a6beb6770eb608384fd8a2b4c101d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 3 Oct 2023 15:15:51 -0600 Subject: [PATCH 070/173] Minor fixes --- src/postprocessing/neosolution.jl | 4 ++-- test/gauss.jl | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/postprocessing/neosolution.jl b/src/postprocessing/neosolution.jl index 80c63680..8ee045d7 100644 --- a/src/postprocessing/neosolution.jl +++ b/src/postprocessing/neosolution.jl @@ -227,7 +227,6 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, points = [[Qs[i], N_outliers[i]] for i in 1:max_drop] # Remove points with Q > 1 filter!(x -> x[1] < 1., points) - @show points # Mean point avg = sum(points) ./ length(points) # Number of remaining points @@ -242,12 +241,13 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, diff = [norm([Qs[i], N_outliers[i]] .- avg) for i in 1:max_drop] # Find pair closest to mean point i = findmin(diff)[2] + idxs = idxs[i:end] end # Reset boolean mask new_outliers[1:end] .= false # Outliers - new_outliers[idxs[i:end]] .= true + new_outliers[idxs] .= true # Update residuals res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) # Update fit diff --git a/test/gauss.jl b/test/gauss.jl index 1ddb858e..e0fac79c 100644 --- a/test/gauss.jl +++ b/test/gauss.jl @@ -13,6 +13,8 @@ using NEOs: NEOSolution, adaptative_maxsteps, scaled_variables abstol = 1e-20 # Order (wrt time) order = 25 + # Use @taylorize + parse_eqs = true # Gauss initial conditions sol = gaussinitcond(radec; order = order, abstol = abstol) From e110ce8ede8a0b736d5d5f7ad575625a9e8f84de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 3 Oct 2023 18:24:09 -0600 Subject: [PATCH 071/173] Another minor fix --- src/postprocessing/neosolution.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/postprocessing/neosolution.jl b/src/postprocessing/neosolution.jl index 8ee045d7..6a8fade6 100644 --- a/src/postprocessing/neosolution.jl +++ b/src/postprocessing/neosolution.jl @@ -188,7 +188,7 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, # Update residuals res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) # Update fit - fit = newtonls(res, zeros(get_numvars()), niter) + fit = tryls(res, zeros(get_numvars()), niter) break end end @@ -220,15 +220,13 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, # Update residuals res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) # Update fit - fit = newtonls(res, zeros(get_numvars()), niter) + fit = tryls(res, zeros(get_numvars()), niter) end # Assemble points points = [[Qs[i], N_outliers[i]] for i in 1:max_drop] # Remove points with Q > 1 filter!(x -> x[1] < 1., points) - # Mean point - avg = sum(points) ./ length(points) # Number of remaining points N_points = length(points) # Find optimal fit @@ -237,6 +235,8 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, elseif N_points <= 2 idxs = idxs[N_points:end] else + # Mean point + avg = sum(points) ./ length(points) # Distance from each point to mean points diff = [norm([Qs[i], N_outliers[i]] .- avg) for i in 1:max_drop] # Find pair closest to mean point @@ -251,7 +251,7 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, # Update residuals res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) # Update fit - fit = newtonls(res, zeros(get_numvars()), niter) + fit = tryls(res, zeros(get_numvars()), niter) return evalfit(NEOSolution(bwd, fwd, res, fit)) end From b2ea7e8db8a29e6470e5c32ffa520e5506761e70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 8 Oct 2023 11:36:36 -0600 Subject: [PATCH 072/173] Clustering outlier rejection criteria --- src/NEOs.jl | 2 +- src/observations/process_radec.jl | 2 +- src/postprocessing/neosolution.jl | 60 ++++++++++++++++++++++++------- 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index 5a694f08..850328b2 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -26,7 +26,7 @@ using DataFrames: AbstractDataFrame, GroupedDataFrame, DataFrame, nrow, eachcol, using HTTP: get using IntervalRootFinding: roots, interval, Interval, mid using Interpolations: Flat, Gridded, Linear, interpolate, extrapolate -using StatsBase: quantile +using StatsBase: mean, std # Constants export d_EM_km, d_EM_au diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index 22a6f531..9848f4da 100644 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -264,7 +264,7 @@ function compute_radec(obs::Vector{RadecMPC{T}}; xva::AstEph, kwargs...) where { # Iterate over the number of observations for i in 1:n_optical_obs - vra[i], vdec[i] = compute_radec(obs[i]; kwargs...) + vra[i], vdec[i] = compute_radec(obs[i]; xva = xva, kwargs...) end return vra, vdec # arcsec, arcsec diff --git a/src/postprocessing/neosolution.jl b/src/postprocessing/neosolution.jl index 6a8fade6..17eba27e 100644 --- a/src/postprocessing/neosolution.jl +++ b/src/postprocessing/neosolution.jl @@ -163,7 +163,10 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, # Orbit fit fit = tryls(res, zeros(get_numvars()), niter) - if nrms(res, fit) < 1 + # NRMS (with 0 outliers) + Q_0 = nrms(res, fit) + + if Q_0 < 1 return evalfit(NEOSolution(bwd, fwd, res, fit)) end @@ -197,9 +200,9 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, # Outliers idxs = Vector{Int}(undef, max_drop) # NRMS - Qs = Vector{T}(undef, max_drop) + Qs = Vector{T}(undef, max_drop + 1) # Number of outliers - N_outliers = Vector{T}(undef, max_drop) + N_outliers = Vector{T}(undef, max_drop + 1) # Recovery loop for i in 1:max_drop @@ -222,11 +225,27 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, # Update fit fit = tryls(res, zeros(get_numvars()), niter) end + # Add 0 outliers fit + Qs[end] = Q_0 + N_outliers[end] = zero(T) + + # Outlier rejection cannot reduce Q + if all(Qs .> 1.) + # Reset boolean mask + new_outliers[1:end] .= false + # Update residuals + res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) + # Update fit + fit = tryls(res, zeros(get_numvars()), niter) + + return evalfit(NEOSolution(bwd, fwd, res, fit)) + end # Assemble points - points = [[Qs[i], N_outliers[i]] for i in 1:max_drop] - # Remove points with Q > 1 - filter!(x -> x[1] < 1., points) + points = [[Qs[i], N_outliers[i]] for i in eachindex(Qs)] + # Leave only first point with Q > 1 + i_1 = findfirst(x -> x[1] > 1, points) + points = points[1:i_1] # Number of remaining points N_points = length(points) # Find optimal fit @@ -235,13 +254,28 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, elseif N_points <= 2 idxs = idxs[N_points:end] else - # Mean point - avg = sum(points) ./ length(points) - # Distance from each point to mean points - diff = [norm([Qs[i], N_outliers[i]] .- avg) for i in 1:max_drop] - # Find pair closest to mean point - i = findmin(diff)[2] - idxs = idxs[i:end] + # Difference in NRMS + dQ = Base.diff(first.(points)) + # Mean difference + mQ = mean(dQ) + # Standard deviation of difference + sQ = std(dQ) + # Maximum difference + dQ_max, i_max = findmax(dQ) + + if dQ_max > mQ + sQ + idxs = idxs[i_max:end] + else + # Remove points with Q < 1 + filter!(x -> x[1] < 1, points) + # Mean point + avg = sum(points) ./ length(points) + # Distance from each point to mean points + diff = [norm([Qs[i], N_outliers[i]] .- avg) for i in 1:max_drop] + # Find pair closest to mean point + i = findmin(diff)[2] + idxs = idxs[i:end] + end end # Reset boolean mask From 5babc957df6b2f5b6459e2d35452d9f0bebd556f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 8 Oct 2023 15:10:11 -0600 Subject: [PATCH 073/173] K-means clustering --- Project.toml | 1 + src/NEOs.jl | 1 + src/postprocessing/neosolution.jl | 46 ++++++++----------------------- 3 files changed, 14 insertions(+), 34 deletions(-) diff --git a/Project.toml b/Project.toml index 5c3ec794..d41207c7 100644 --- a/Project.toml +++ b/Project.toml @@ -6,6 +6,7 @@ version = "0.7.2" [deps] Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" AutoHashEquals = "15f4f7f2-30c1-5605-9d31-71845cf9641f" +Clustering = "aaaa29a8-35af-508c-8bc3-b662a17a0fe5" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" diff --git a/src/NEOs.jl b/src/NEOs.jl index 850328b2..f9dee90d 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -27,6 +27,7 @@ using HTTP: get using IntervalRootFinding: roots, interval, Interval, mid using Interpolations: Flat, Gridded, Linear, interpolate, extrapolate using StatsBase: mean, std +using Clustering: kmeans # Constants export d_EM_km, d_EM_au diff --git a/src/postprocessing/neosolution.jl b/src/postprocessing/neosolution.jl index 17eba27e..d8b0a92e 100644 --- a/src/postprocessing/neosolution.jl +++ b/src/postprocessing/neosolution.jl @@ -241,41 +241,19 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, return evalfit(NEOSolution(bwd, fwd, res, fit)) end - # Assemble points - points = [[Qs[i], N_outliers[i]] for i in eachindex(Qs)] - # Leave only first point with Q > 1 - i_1 = findfirst(x -> x[1] > 1, points) - points = points[1:i_1] - # Number of remaining points - N_points = length(points) - # Find optimal fit - if N_points == 0 - idxs = Vector{Int}(undef, 0) - elseif N_points <= 2 - idxs = idxs[N_points:end] - else - # Difference in NRMS - dQ = Base.diff(first.(points)) - # Mean difference - mQ = mean(dQ) - # Standard deviation of difference - sQ = std(dQ) - # Maximum difference - dQ_max, i_max = findmax(dQ) - - if dQ_max > mQ + sQ - idxs = idxs[i_max:end] - else - # Remove points with Q < 1 - filter!(x -> x[1] < 1, points) - # Mean point - avg = sum(points) ./ length(points) - # Distance from each point to mean points - diff = [norm([Qs[i], N_outliers[i]] .- avg) for i in 1:max_drop] - # Find pair closest to mean point - i = findmin(diff)[2] - idxs = idxs[i:end] + if max_drop > 1 + # Assemble points + points = Matrix{T}(undef, 2, max_drop + 1) + for i in eachindex(Qs) + points[1, i] = Qs[i] + points[2, i] = N_outliers[i] end + # K-means clustering + cluster = kmeans(points, 2) + # Find last fit of smallest cluster + i = findfirst(isone, cluster.assignments) - 1 + # Update outliers indexes + idxs = idxs[i:end] end # Reset boolean mask From 8f75b600e5e5f929be50e82a82a783ec4c386405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 8 Oct 2023 15:28:13 -0600 Subject: [PATCH 074/173] Minor fix --- Project.toml | 1 + src/postprocessing/neosolution.jl | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index d41207c7..c5fafe07 100644 --- a/Project.toml +++ b/Project.toml @@ -37,6 +37,7 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [compat] AutoHashEquals = "0.2" +Clustering = "0.15" DataFrames = "1.5" DelimitedFiles = "1" HORIZONS = "0.3" diff --git a/src/postprocessing/neosolution.jl b/src/postprocessing/neosolution.jl index d8b0a92e..7bdd6604 100644 --- a/src/postprocessing/neosolution.jl +++ b/src/postprocessing/neosolution.jl @@ -250,8 +250,10 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, end # K-means clustering cluster = kmeans(points, 2) + # Index of smallest cluster + i_0 = cluster.assignments[1] # Find last fit of smallest cluster - i = findfirst(isone, cluster.assignments) - 1 + i = findfirst(x -> x != i_0, cluster.assignments) - 1 # Update outliers indexes idxs = idxs[i:end] end From 5a1f3b92a277b702b349a18de4b6bea5046218f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 25 Nov 2023 15:40:22 -0600 Subject: [PATCH 075/173] Too Short Arc --- .codecov.yml | 2 +- .github/workflows/CI.yml | 102 +- .github/workflows/CompatHelper.yml | 32 +- .github/workflows/TagBot.yml | 30 +- .gitignore | 20 +- Artifacts.toml | 142 +- CITATION.cff | 0 LICENSE.md | 0 Project.toml | 8 +- README.md | 124 +- data/101955_OPTICAL_1999_2006.dat | 0 data/101955_OPTICAL_2011_2018.dat | 0 data/101955_RADAR_1999_2005.dat | 0 data/101955_RADAR_2011.dat | 0 data/99942.dat | 0 data/99942_2004_2020.dat | 0 data/99942_2020_2021.dat | 0 data/99942_RADAR_2005_2013.dat | 0 data/99942_RADAR_2021.dat | 0 data/Apophis_JPL_data.dat | 0 data/mpec_2014-R71.dat | 0 data/mps_375184.dat | 0 data/panstarrs-1.dat | 0 data/tholenetal2013_opterror.dat | 0 data/vokr15_mpc_formatted.dat | 0 dev/generate_artifacts.jl | 200 +- notebooks/Apophis.ipynb | 2262 +++---- notebooks/B-plane-jt-o5v7.ipynb | 0 notebooks/Plots-paper.ipynb | 0 notebooks/gnuplot.cfg | 0 pha/.DS_Store | Bin 0 -> 6148 bytes pha/Project.toml | 36 +- pha/apophis.jl | 665 +- pha/bennu.jl | 0 scripts/distributed.jl | 106 +- scripts/main.jl | 124 +- scripts/main.lsf | 0 scripts/setup.jl | 0 scripts/setup.lsf | 0 src/NEOs.jl | 156 +- src/constants.jl | 274 +- src/init.jl | 39 +- src/observations/catalogue_mpc.jl | 380 +- src/observations/jpl_eph.jl | 326 +- src/observations/observatory_mpc.jl | 598 +- src/observations/process_radar.jl | 1221 ++-- src/observations/process_radec.jl | 1335 ++-- src/observations/radar_jpl.jl | 729 +- src/observations/radec_mpc.jl | 915 ++- src/observations/topocentric.jl | 614 +- src/observations/units.jl | 359 +- src/orbit_determination/gauss_method.jl | 1367 ++-- .../orbit_determination.jl | 44 + src/orbit_determination/osculating.jl | 367 +- src/orbit_determination/tooshortarc.jl | 628 ++ src/postprocessing/b_plane.jl | 426 +- src/postprocessing/least_squares.jl | 1297 ++-- src/postprocessing/neosolution.jl | 402 +- src/propagation/asteroid_dynamical_models.jl | 2350 +++---- src/propagation/jetcoeffs.jl | 5984 ++++++++--------- src/propagation/propagation.jl | 504 +- src/propagation/serialization.jl | 406 +- test/Project.toml | 32 +- test/data/99942_RADAR_2005_2013.dat | 92 +- test/data/99942_Tholen_etal_2013.dat | 864 +-- test/data/RADEC_2023_DW.dat | 246 +- test/extensions.jl | 102 +- test/gauss.jl | 94 +- test/observations.jl | 572 +- test/osculating.jl | 30 +- test/propagation.jl | 806 +-- test/runtests.jl | 24 +- 72 files changed, 14148 insertions(+), 13288 deletions(-) mode change 100644 => 100755 .codecov.yml mode change 100644 => 100755 .github/workflows/CI.yml mode change 100644 => 100755 .github/workflows/CompatHelper.yml mode change 100644 => 100755 .github/workflows/TagBot.yml mode change 100644 => 100755 .gitignore mode change 100644 => 100755 Artifacts.toml mode change 100644 => 100755 CITATION.cff mode change 100644 => 100755 LICENSE.md mode change 100644 => 100755 Project.toml mode change 100644 => 100755 README.md mode change 100644 => 100755 data/101955_OPTICAL_1999_2006.dat mode change 100644 => 100755 data/101955_OPTICAL_2011_2018.dat mode change 100644 => 100755 data/101955_RADAR_1999_2005.dat mode change 100644 => 100755 data/101955_RADAR_2011.dat mode change 100644 => 100755 data/99942.dat mode change 100644 => 100755 data/99942_2004_2020.dat mode change 100644 => 100755 data/99942_2020_2021.dat mode change 100644 => 100755 data/99942_RADAR_2005_2013.dat mode change 100644 => 100755 data/99942_RADAR_2021.dat mode change 100644 => 100755 data/Apophis_JPL_data.dat mode change 100644 => 100755 data/mpec_2014-R71.dat mode change 100644 => 100755 data/mps_375184.dat mode change 100644 => 100755 data/panstarrs-1.dat mode change 100644 => 100755 data/tholenetal2013_opterror.dat mode change 100644 => 100755 data/vokr15_mpc_formatted.dat mode change 100644 => 100755 dev/generate_artifacts.jl mode change 100644 => 100755 notebooks/Apophis.ipynb mode change 100644 => 100755 notebooks/B-plane-jt-o5v7.ipynb mode change 100644 => 100755 notebooks/Plots-paper.ipynb mode change 100644 => 100755 notebooks/gnuplot.cfg create mode 100644 pha/.DS_Store mode change 100644 => 100755 pha/Project.toml mode change 100644 => 100755 pha/apophis.jl mode change 100644 => 100755 pha/bennu.jl mode change 100644 => 100755 scripts/distributed.jl mode change 100644 => 100755 scripts/main.jl mode change 100644 => 100755 scripts/main.lsf mode change 100644 => 100755 scripts/setup.jl mode change 100644 => 100755 scripts/setup.lsf mode change 100644 => 100755 src/NEOs.jl mode change 100644 => 100755 src/constants.jl mode change 100644 => 100755 src/init.jl mode change 100644 => 100755 src/observations/catalogue_mpc.jl mode change 100644 => 100755 src/observations/jpl_eph.jl mode change 100644 => 100755 src/observations/observatory_mpc.jl mode change 100644 => 100755 src/observations/process_radar.jl mode change 100644 => 100755 src/observations/process_radec.jl mode change 100644 => 100755 src/observations/radar_jpl.jl mode change 100644 => 100755 src/observations/radec_mpc.jl mode change 100644 => 100755 src/observations/topocentric.jl mode change 100644 => 100755 src/observations/units.jl mode change 100644 => 100755 src/orbit_determination/gauss_method.jl create mode 100644 src/orbit_determination/orbit_determination.jl mode change 100644 => 100755 src/orbit_determination/osculating.jl create mode 100644 src/orbit_determination/tooshortarc.jl mode change 100644 => 100755 src/postprocessing/b_plane.jl mode change 100644 => 100755 src/postprocessing/least_squares.jl mode change 100644 => 100755 src/postprocessing/neosolution.jl mode change 100644 => 100755 src/propagation/asteroid_dynamical_models.jl mode change 100644 => 100755 src/propagation/jetcoeffs.jl mode change 100644 => 100755 src/propagation/propagation.jl mode change 100644 => 100755 src/propagation/serialization.jl mode change 100644 => 100755 test/Project.toml mode change 100644 => 100755 test/data/99942_RADAR_2005_2013.dat mode change 100644 => 100755 test/data/99942_Tholen_etal_2013.dat mode change 100644 => 100755 test/data/RADEC_2023_DW.dat mode change 100644 => 100755 test/extensions.jl mode change 100644 => 100755 test/gauss.jl mode change 100644 => 100755 test/observations.jl mode change 100644 => 100755 test/osculating.jl mode change 100644 => 100755 test/propagation.jl mode change 100644 => 100755 test/runtests.jl diff --git a/.codecov.yml b/.codecov.yml old mode 100644 new mode 100755 index 69cb7601..d6c6c1ae --- a/.codecov.yml +++ b/.codecov.yml @@ -1 +1 @@ -comment: false +comment: false diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml old mode 100644 new mode 100755 index ce1a4a14..f402e19a --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -1,51 +1,51 @@ -name: CI -on: - push: - paths-ignore: - - 'LICENSE.md' - - 'README.md' - pull_request: - branches: - - main - tags: '*' -concurrency: - # Skip intermediate builds: always. - # Cancel intermediate builds: only if it is a pull request build. - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} -jobs: - test: - name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} - runs-on: ${{ matrix.os }} - continue-on-error: ${{ matrix.version == 'nightly' }} - strategy: - fail-fast: false - matrix: - version: - - '1.9' - # - '1' - - 'nightly' - os: - - ubuntu-latest - - macos-latest - - windows-latest - arch: - - x64 - steps: - - uses: actions/checkout@v3 - - uses: julia-actions/setup-julia@v1 - with: - version: ${{ matrix.version }} - arch: ${{ matrix.arch }} - - uses: julia-actions/cache@v1 - - uses: julia-actions/julia-buildpkg@v1 - - uses: julia-actions/julia-runtest@v1 - env: - JULIA_NUM_THREADS: 2 - - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v3 - with: - files: lcov.info - - uses: julia-actions/julia-uploadcoveralls@v1 - env: - COVERALLS_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} +name: CI +on: + push: + paths-ignore: + - 'LICENSE.md' + - 'README.md' + pull_request: + branches: + - main + tags: '*' +concurrency: + # Skip intermediate builds: always. + # Cancel intermediate builds: only if it is a pull request build. + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} +jobs: + test: + name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} + runs-on: ${{ matrix.os }} + continue-on-error: ${{ matrix.version == 'nightly' }} + strategy: + fail-fast: false + matrix: + version: + - '1.9' + # - '1' + - 'nightly' + os: + - ubuntu-latest + - macos-latest + - windows-latest + arch: + - x64 + steps: + - uses: actions/checkout@v3 + - uses: julia-actions/setup-julia@v1 + with: + version: ${{ matrix.version }} + arch: ${{ matrix.arch }} + - uses: julia-actions/cache@v1 + - uses: julia-actions/julia-buildpkg@v1 + - uses: julia-actions/julia-runtest@v1 + env: + JULIA_NUM_THREADS: 2 + - uses: julia-actions/julia-processcoverage@v1 + - uses: codecov/codecov-action@v3 + with: + files: lcov.info + - uses: julia-actions/julia-uploadcoveralls@v1 + env: + COVERALLS_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} diff --git a/.github/workflows/CompatHelper.yml b/.github/workflows/CompatHelper.yml old mode 100644 new mode 100755 index cba9134c..4e822131 --- a/.github/workflows/CompatHelper.yml +++ b/.github/workflows/CompatHelper.yml @@ -1,16 +1,16 @@ -name: CompatHelper -on: - schedule: - - cron: 0 0 * * * - workflow_dispatch: -jobs: - CompatHelper: - runs-on: ubuntu-latest - steps: - - name: Pkg.add("CompatHelper") - run: julia -e 'using Pkg; Pkg.add("CompatHelper")' - - name: CompatHelper.main() - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - COMPATHELPER_PRIV: ${{ secrets.DOCUMENTER_KEY }} - run: julia -e 'using CompatHelper; CompatHelper.main()' +name: CompatHelper +on: + schedule: + - cron: 0 0 * * * + workflow_dispatch: +jobs: + CompatHelper: + runs-on: ubuntu-latest + steps: + - name: Pkg.add("CompatHelper") + run: julia -e 'using Pkg; Pkg.add("CompatHelper")' + - name: CompatHelper.main() + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COMPATHELPER_PRIV: ${{ secrets.DOCUMENTER_KEY }} + run: julia -e 'using CompatHelper; CompatHelper.main()' diff --git a/.github/workflows/TagBot.yml b/.github/workflows/TagBot.yml old mode 100644 new mode 100755 index f49313b6..083baf95 --- a/.github/workflows/TagBot.yml +++ b/.github/workflows/TagBot.yml @@ -1,15 +1,15 @@ -name: TagBot -on: - issue_comment: - types: - - created - workflow_dispatch: -jobs: - TagBot: - if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' - runs-on: ubuntu-latest - steps: - - uses: JuliaRegistries/TagBot@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - ssh: ${{ secrets.DOCUMENTER_KEY }} +name: TagBot +on: + issue_comment: + types: + - created + workflow_dispatch: +jobs: + TagBot: + if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' + runs-on: ubuntu-latest + steps: + - uses: JuliaRegistries/TagBot@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + ssh: ${{ secrets.DOCUMENTER_KEY }} diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 index df74e796..adaa2e71 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,10 @@ -*.jld -*.jld2 -*.bsp -*.out -*.err -notebooks/.ipynb_checkpoints -jldeph/ -notebooks/figs -EOP_IAU*.TXT -Manifest.toml +*.jld +*.jld2 +*.bsp +*.out +*.err +notebooks/.ipynb_checkpoints +jldeph/ +notebooks/figs +EOP_IAU*.TXT +Manifest.toml diff --git a/Artifacts.toml b/Artifacts.toml old mode 100644 new mode 100755 index 5187ed24..bce6b6ee --- a/Artifacts.toml +++ b/Artifacts.toml @@ -1,71 +1,71 @@ -[TTmTDBde430] -git-tree-sha1 = "de3fba2237359dc941a057d492c305afeccba133" -lazy = true - - [[TTmTDBde430.download]] - sha256 = "a8e09c3d2f68f77c641eed0b41d2441b11a7b4f12daed8144638fdca02eb4d5d" - url = "https://ssd.jpl.nasa.gov/ftp/eph/planets/bsp/TTmTDB.de430.19feb2015.bsp" - -[a99942] -git-tree-sha1 = "7cdf1265a22c52329651c4a71a9835d1b90f568e" -lazy = true - - [[a99942.download]] - sha256 = "d1cdcad22c8060e98d7ca116973b64bc65cdb5e62fb045637701b57aa146a434" - url = "https://raw.githubusercontent.com/PerezHz/jpleph/main/a99942.tar.gz" - -[de430] -git-tree-sha1 = "db3e3a765712a792a7f4a73634213d53fc0561ec" -lazy = true - - [[de430.download]] - sha256 = "b70b72fde86923475fac6cec1e0887040bb80ffe159f153aab647cdfdf897351" - url = "https://ssd.jpl.nasa.gov/ftp/eph/planets/bsp/de430_1850-2150.bsp" - -[debias] -git-tree-sha1 = "cfd0d2615770087d3c564b7f6143f01930ccb45e" -lazy = true - - [[debias.download]] - sha256 = "8b107db9506ec45c8cad78d0981c48693c6e5957912df95f4a3df826c7736227" - url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias.tgz" - -[debias_2014] -git-tree-sha1 = "1b6a82575ac74386b893f8c51361d19d350bd234" -lazy = true - - [[debias_2014.download]] - sha256 = "1d44c6443d08f83c79017afd218c3b4e326c573d84842c88713e4b6c8d6d5b03" - url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias_2014.tgz" - -[debias_2018] -git-tree-sha1 = "ea7915a243ea4c8e0960817f50677598076beeaa" -lazy = true - - [[debias_2018.download]] - sha256 = "288132cefea7f1bdf0989782db1173948dd7dfef7da31910be90b16b73cfea6c" - url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias_2018.tgz" - -[debias_hires2018] -git-tree-sha1 = "cebf83360f68870a628805aea9b4261d0d6b4545" -lazy = true - - [[debias_hires2018.download]] - sha256 = "2b292fc79c202d38dfab386783fee10d422f6919afc58348c72059710dd6cd92" - url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias_hires2018.tgz" - -[naif0012] -git-tree-sha1 = "8fa307fe9da2a63ed0cf9d681540d94a619a0995" -lazy = true - - [[naif0012.download]] - sha256 = "678e32bdb5a744117a467cd9601cd6b373f0e9bc9bbde1371d5eee39600a039b" - url = "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/lsk/naif0012.tls" - -[sseph_p100] -git-tree-sha1 = "d4d91f0045063719c9bf581bf20bbc212327b2d0" -lazy = true - - [[sseph_p100.download]] - sha256 = "25b525ffef5c05cc51ee554760ae83107b9bd163577439470b60c2d4c7153a21" - url = "https://github.com/LuEdRaMo/sseph/raw/main/sseph343ast016_p100y_et.tar.gz" +[TTmTDBde430] +git-tree-sha1 = "de3fba2237359dc941a057d492c305afeccba133" +lazy = true + + [[TTmTDBde430.download]] + sha256 = "a8e09c3d2f68f77c641eed0b41d2441b11a7b4f12daed8144638fdca02eb4d5d" + url = "https://ssd.jpl.nasa.gov/ftp/eph/planets/bsp/TTmTDB.de430.19feb2015.bsp" + +[a99942] +git-tree-sha1 = "7cdf1265a22c52329651c4a71a9835d1b90f568e" +lazy = true + + [[a99942.download]] + sha256 = "d1cdcad22c8060e98d7ca116973b64bc65cdb5e62fb045637701b57aa146a434" + url = "https://raw.githubusercontent.com/PerezHz/jpleph/main/a99942.tar.gz" + +[de430] +git-tree-sha1 = "db3e3a765712a792a7f4a73634213d53fc0561ec" +lazy = true + + [[de430.download]] + sha256 = "b70b72fde86923475fac6cec1e0887040bb80ffe159f153aab647cdfdf897351" + url = "https://ssd.jpl.nasa.gov/ftp/eph/planets/bsp/de430_1850-2150.bsp" + +[debias] +git-tree-sha1 = "cfd0d2615770087d3c564b7f6143f01930ccb45e" +lazy = true + + [[debias.download]] + sha256 = "8b107db9506ec45c8cad78d0981c48693c6e5957912df95f4a3df826c7736227" + url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias.tgz" + +[debias_2014] +git-tree-sha1 = "1b6a82575ac74386b893f8c51361d19d350bd234" +lazy = true + + [[debias_2014.download]] + sha256 = "1d44c6443d08f83c79017afd218c3b4e326c573d84842c88713e4b6c8d6d5b03" + url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias_2014.tgz" + +[debias_2018] +git-tree-sha1 = "ea7915a243ea4c8e0960817f50677598076beeaa" +lazy = true + + [[debias_2018.download]] + sha256 = "288132cefea7f1bdf0989782db1173948dd7dfef7da31910be90b16b73cfea6c" + url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias_2018.tgz" + +[debias_hires2018] +git-tree-sha1 = "cebf83360f68870a628805aea9b4261d0d6b4545" +lazy = true + + [[debias_hires2018.download]] + sha256 = "2b292fc79c202d38dfab386783fee10d422f6919afc58348c72059710dd6cd92" + url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias_hires2018.tgz" + +[naif0012] +git-tree-sha1 = "8fa307fe9da2a63ed0cf9d681540d94a619a0995" +lazy = true + + [[naif0012.download]] + sha256 = "678e32bdb5a744117a467cd9601cd6b373f0e9bc9bbde1371d5eee39600a039b" + url = "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/lsk/naif0012.tls" + +[sseph_p100] +git-tree-sha1 = "d4d91f0045063719c9bf581bf20bbc212327b2d0" +lazy = true + + [[sseph_p100.download]] + sha256 = "25b525ffef5c05cc51ee554760ae83107b9bd163577439470b60c2d4c7153a21" + url = "https://github.com/LuEdRaMo/sseph/raw/main/sseph343ast016_p100y_et.tar.gz" diff --git a/CITATION.cff b/CITATION.cff old mode 100644 new mode 100755 diff --git a/LICENSE.md b/LICENSE.md old mode 100644 new mode 100755 diff --git a/Project.toml b/Project.toml old mode 100644 new mode 100755 index c5fafe07..5b800100 --- a/Project.toml +++ b/Project.toml @@ -12,13 +12,11 @@ Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" +GLM = "38e38edf-8417-5370-95a0-9cbb8c7f171a" HORIZONS = "5a3ac768-beb4-554a-9c98-3342fe3377f5" HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" Healpix = "9f4e344d-96bc-545a-84a3-ae6b9e1b672b" InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" -Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59" -IntervalArithmetic = "d1acc4aa-44c8-5952-acd4-ba5d80a2a253" -IntervalRootFinding = "d2bf35a9-74e0-55ec-b149-d360ff49b807" JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" LazyArtifacts = "4af54fe1-eca0-43a8-85a7-787d91b784e3" @@ -26,6 +24,7 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" PlanetaryEphemeris = "d83715d0-7e5f-11e9-1a59-4137b20d8363" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Quadmath = "be4d8f0f-7fa4-5f49-b795-2f01399ab2dd" +Roots = "f2b01f46-fcfa-551c-844a-d8ac1e96c665" SPICE = "5bab7191-041a-5c2e-a744-024b9c3a5062" SatelliteToolboxTransformations = "6b019ec1-7a1e-4f04-96c7-a9db1ca5514d" Scratch = "6c6a2e73-6563-6170-7368-637461726353" @@ -43,9 +42,6 @@ DelimitedFiles = "1" HORIZONS = "0.3" HTTP = "1.9.5" Healpix = "4" -Interpolations = "0.14" -IntervalArithmetic = "0.20" -IntervalRootFinding = "0.5.11" JLD2 = "0.4" JSON = "0.21" PlanetaryEphemeris = "0.7" diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 7b2a8fc4..0ffd83ce --- a/README.md +++ b/README.md @@ -1,62 +1,62 @@ -# NEOs.jl - -[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5152449.svg)](https://doi.org/10.5281/zenodo.5152449) -[![CI](https://github.com/PerezHz/NEOs.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/PerezHz/NEOs.jl/actions/workflows/CI.yml) -[![Coverage Status](https://coveralls.io/repos/github/PerezHz/NEOs.jl/badge.svg?branch=main)](https://coveralls.io/github/PerezHz/NEOs.jl?branch=main) -[![codecov](https://codecov.io/gh/PerezHz/NEOs.jl/branch/main/graph/badge.svg?token=F1IY79YP3J)](https://codecov.io/gh/PerezHz/NEOs.jl) - -`NEOs.jl` is a Julia package for high-accuracy orbit determination and propagation of -Near-Earth Objects. `NEOs.jl` exploits jet transport techniques via -[TaylorIntegration.jl](https://github.com/PerezHz/TaylorIntegration.jl). - -## Authors - -- [Jorge A. Pérez](https://github.com/PerezHz), -Instituto de Ciencias Físicas, Universidad Nacional Autónoma de México (UNAM) -- [Luis Benet](http://www.cicc.unam.mx/~benet/), -Instituto de Ciencias Físicas, Universidad Nacional Autónoma de México (UNAM) -- [Luis Eduardo Ramírez Montoya](https://github.com/LuEdRaMo), -Facultad de Ciencias, Universidad Nacional Autónoma de México (UNAM) - -## Installation - -The current version of this package may be installed in Julia pkg manager via: -``` -] add NEOs -``` - -## Usage - -The `pha` directory contains the `apophis.jl` script which performs an -orbit determination for asteroid (99942) Apophis from optical and radar astrometry. In order -to run this script, the environment corresponding to the `Project.toml` contained in the -`pha` directory has to be active and instantiated. This can be done, for example, by running -the following command from the `pha` directory: - -``julia -e `import Pkg; Pkg.activate(); Pkg.instantiate()` # run this from the `pha` directory `` - -Once the `pha` environment is active, this script may be called from the `pha` directory -with the default settings as: - -`julia --project apophis.jl` - -The `--help` option can be passed to see a list of the customizable settings - -`julia --project apophis.jl --help` - -`NEOs.propagate` also supports multi-threading: - -`julia -t --project apophis.jl --help` - -## Acknowledgments - -We acknowledge financial support from UNAM-PAPIIT grant IG100819 and computing -resources provided by LANCAD-UNAM-DGTIC-284. - -## References - -- Pérez-Hernández, J.A., Benet, L. Non-zero Yarkovsky acceleration for near-Earth asteroid - (99942) Apophis. Commun Earth Environ 3, 10 (2022). https://doi.org/10.1038/s43247-021-00337-x -- Pérez-Hernández, Jorge A., & Benet, Luis. (2023). - [PerezHz/TaylorIntegration.jl](https://github.com/PerezHzTaylorIntegration.jl): - v0.14.2 (Version v0.14.2). Zenodo. https://doi.org/10.5281/zenodo.8104080 +# NEOs.jl + +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5152449.svg)](https://doi.org/10.5281/zenodo.5152449) +[![CI](https://github.com/PerezHz/NEOs.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/PerezHz/NEOs.jl/actions/workflows/CI.yml) +[![Coverage Status](https://coveralls.io/repos/github/PerezHz/NEOs.jl/badge.svg?branch=main)](https://coveralls.io/github/PerezHz/NEOs.jl?branch=main) +[![codecov](https://codecov.io/gh/PerezHz/NEOs.jl/branch/main/graph/badge.svg?token=F1IY79YP3J)](https://codecov.io/gh/PerezHz/NEOs.jl) + +`NEOs.jl` is a Julia package for high-accuracy orbit determination and propagation of +Near-Earth Objects. `NEOs.jl` exploits jet transport techniques via +[TaylorIntegration.jl](https://github.com/PerezHz/TaylorIntegration.jl). + +## Authors + +- [Jorge A. Pérez](https://github.com/PerezHz), +Instituto de Ciencias Físicas, Universidad Nacional Autónoma de México (UNAM) +- [Luis Benet](http://www.cicc.unam.mx/~benet/), +Instituto de Ciencias Físicas, Universidad Nacional Autónoma de México (UNAM) +- [Luis Eduardo Ramírez Montoya](https://github.com/LuEdRaMo), +Facultad de Ciencias, Universidad Nacional Autónoma de México (UNAM) + +## Installation + +The current version of this package may be installed in Julia pkg manager via: +``` +] add NEOs +``` + +## Usage + +The `pha` directory contains the `apophis.jl` script which performs an +orbit determination for asteroid (99942) Apophis from optical and radar astrometry. In order +to run this script, the environment corresponding to the `Project.toml` contained in the +`pha` directory has to be active and instantiated. This can be done, for example, by running +the following command from the `pha` directory: + +``julia -e `import Pkg; Pkg.activate(); Pkg.instantiate()` # run this from the `pha` directory `` + +Once the `pha` environment is active, this script may be called from the `pha` directory +with the default settings as: + +`julia --project apophis.jl` + +The `--help` option can be passed to see a list of the customizable settings + +`julia --project apophis.jl --help` + +`NEOs.propagate` also supports multi-threading: + +`julia -t --project apophis.jl --help` + +## Acknowledgments + +We acknowledge financial support from UNAM-PAPIIT grant IG100819 and computing +resources provided by LANCAD-UNAM-DGTIC-284. + +## References + +- Pérez-Hernández, J.A., Benet, L. Non-zero Yarkovsky acceleration for near-Earth asteroid + (99942) Apophis. Commun Earth Environ 3, 10 (2022). https://doi.org/10.1038/s43247-021-00337-x +- Pérez-Hernández, Jorge A., & Benet, Luis. (2023). + [PerezHz/TaylorIntegration.jl](https://github.com/PerezHzTaylorIntegration.jl): + v0.14.2 (Version v0.14.2). Zenodo. https://doi.org/10.5281/zenodo.8104080 diff --git a/data/101955_OPTICAL_1999_2006.dat b/data/101955_OPTICAL_1999_2006.dat old mode 100644 new mode 100755 diff --git a/data/101955_OPTICAL_2011_2018.dat b/data/101955_OPTICAL_2011_2018.dat old mode 100644 new mode 100755 diff --git a/data/101955_RADAR_1999_2005.dat b/data/101955_RADAR_1999_2005.dat old mode 100644 new mode 100755 diff --git a/data/101955_RADAR_2011.dat b/data/101955_RADAR_2011.dat old mode 100644 new mode 100755 diff --git a/data/99942.dat b/data/99942.dat old mode 100644 new mode 100755 diff --git a/data/99942_2004_2020.dat b/data/99942_2004_2020.dat old mode 100644 new mode 100755 diff --git a/data/99942_2020_2021.dat b/data/99942_2020_2021.dat old mode 100644 new mode 100755 diff --git a/data/99942_RADAR_2005_2013.dat b/data/99942_RADAR_2005_2013.dat old mode 100644 new mode 100755 diff --git a/data/99942_RADAR_2021.dat b/data/99942_RADAR_2021.dat old mode 100644 new mode 100755 diff --git a/data/Apophis_JPL_data.dat b/data/Apophis_JPL_data.dat old mode 100644 new mode 100755 diff --git a/data/mpec_2014-R71.dat b/data/mpec_2014-R71.dat old mode 100644 new mode 100755 diff --git a/data/mps_375184.dat b/data/mps_375184.dat old mode 100644 new mode 100755 diff --git a/data/panstarrs-1.dat b/data/panstarrs-1.dat old mode 100644 new mode 100755 diff --git a/data/tholenetal2013_opterror.dat b/data/tholenetal2013_opterror.dat old mode 100644 new mode 100755 diff --git a/data/vokr15_mpc_formatted.dat b/data/vokr15_mpc_formatted.dat old mode 100644 new mode 100755 diff --git a/dev/generate_artifacts.jl b/dev/generate_artifacts.jl old mode 100644 new mode 100755 index f901ea8d..770bf545 --- a/dev/generate_artifacts.jl +++ b/dev/generate_artifacts.jl @@ -1,100 +1,100 @@ -# This script generates Julia artifacts for NEOs.jl, including -# - debiasing tables from Chesley et al. (2010), Farnocchia et al. (2015) and Eggl et al. (2020) -# - JPL lsk and spk -# - PlanetaryEphemeris.jl Solar System ephemeris -# TODO: adapt script for 2010 debiasing tables (requires extra unpacking) -# -# This script can be run from NEOs.jl root directory with: -# julia --project dev/generate_artifacts.jl - -using Pkg.Artifacts -using Pkg.PlatformEngines: sha256, unpack -using Downloads - -# This is the path to the Artifacts.toml we will manipulate -const artifact_toml = joinpath(dirname(@__DIR__), "Artifacts.toml") - -# JPL FTP URL -const ftp_jpl = "https://ssd.jpl.nasa.gov/ftp/" - -# Debiasing tables names and URLs -const names_debias = ["debias", "debias_2014", "debias_2018", "debias_hires2018"] -const urls_debias = ftp_jpl .* "ssd/debias/" .* names_debias .* ".tgz" - -# JPL lsk and spk names and URLs -const names_lsk_spk = ["naif0012", "de430", "TTmTDBde430", "a99942"] -const urls_lsk_spk = [ - "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/lsk/naif0012.tls", - ftp_jpl*"eph/planets/bsp/de430_1850-2150.bsp", - ftp_jpl*"eph/planets/bsp/TTmTDB.de430.19feb2015.bsp", - "https://raw.githubusercontent.com/PerezHz/jpleph/main/a99942.tar.gz", -] - -# PlanetaryEphemeris.jl Solar System ephemeris name and URL -const name_sseph = "sseph_p100" -const url_sseph = "https://github.com/LuEdRaMo/sseph/raw/main/sseph343ast016_p100y_et.tar.gz" - -# Collect names and URLs -const urls = vcat(urls_lsk_spk, urls_debias, url_sseph) -const names = vcat(names_lsk_spk, names_debias, name_sseph) - -for (url, name) in zip(urls, names) - # Query the `Artifacts.toml` file for the hash bound to the name - # (returns `nothing` if no such binding exists) - artfct_hash = artifact_hash(name, artifact_toml) - # If the name was not bound, or the hash it was bound to does not exist, create it! - if isnothing(artfct_hash) || !artifact_exists(artfct_hash) - tb = Tuple[] - # create_artifact() returns the content-hash of the artifact directory once we're finished creating it - artfct_hash = create_artifact() do artifact_dir - # We create the artifact by simply downloading a few files into the new artifact directory - @show url name - tmp_dir = mktempdir() - basename_url = basename(url) - @show basename_url - dot_idx = findlast(isequal('.'), basename_url) - ext = basename_url[dot_idx+1:end] - if ext in ["gz", "tgz"] # If artifact is a tarball with many files - # the following code block was adapted from PlatformEngines.jl, MIT licensed - # https://github.com/JuliaLang/Pkg.jl/blob/048b0e86deba0c5f491eb1a3af2f3c97cac675b3/src/PlatformEngines.jl#L348 - dest = joinpath(tmp_dir, basename(url)) - tarball = "" - f = retry(delays = fill(1.0, 3)) do - try - tarball = Downloads.download(url, dest) - catch err - @debug "download and verify failed" url dest err - rethrow() - end - end - f() - try - tarball_hash = open(tarball) do file - bytes2hex(sha256(file)) - end - unpack(tarball, artifact_dir) - tb = [(url, tarball_hash)] - finally - rm(tarball) - end - else # url containing a single non-tarball file - fpath = Downloads.download(url, joinpath(artifact_dir, basename(url))) - file_hash = open(fpath) do file - bytes2hex(sha256(file)) - end - tb = [(url, file_hash)] - end - end - @show artfct_hash typeof(artfct_hash) - # Now bind that hash within our `Artifacts.toml`. `force = true` means that if it already exists, - # just overwrite the corresponding entry in `Artifacts.toml` with the new content-hash. - # Unless the source files change, we do not expect the content hash to - # change, so this should not cause unnecessary version control churn. - bind_artifact!(artifact_toml, name, artfct_hash, lazy=true, force=true, download_info=tb) - end - - # Get the path of the artifact, either newly created or previously generated. - # this should be something like `~/.julia/artifacts/dbd04e28be047a54fbe9bf67e934be5b5e0d357a` - artfct_path = artifact_path(artfct_hash) - println(name, " artifact saved to ", artfct_path) -end +# This script generates Julia artifacts for NEOs.jl, including +# - debiasing tables from Chesley et al. (2010), Farnocchia et al. (2015) and Eggl et al. (2020) +# - JPL lsk and spk +# - PlanetaryEphemeris.jl Solar System ephemeris +# TODO: adapt script for 2010 debiasing tables (requires extra unpacking) +# +# This script can be run from NEOs.jl root directory with: +# julia --project dev/generate_artifacts.jl + +using Pkg.Artifacts +using Pkg.PlatformEngines: sha256, unpack +using Downloads + +# This is the path to the Artifacts.toml we will manipulate +const artifact_toml = joinpath(dirname(@__DIR__), "Artifacts.toml") + +# JPL FTP URL +const ftp_jpl = "https://ssd.jpl.nasa.gov/ftp/" + +# Debiasing tables names and URLs +const names_debias = ["debias", "debias_2014", "debias_2018", "debias_hires2018"] +const urls_debias = ftp_jpl .* "ssd/debias/" .* names_debias .* ".tgz" + +# JPL lsk and spk names and URLs +const names_lsk_spk = ["naif0012", "de430", "TTmTDBde430", "a99942"] +const urls_lsk_spk = [ + "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/lsk/naif0012.tls", + ftp_jpl*"eph/planets/bsp/de430_1850-2150.bsp", + ftp_jpl*"eph/planets/bsp/TTmTDB.de430.19feb2015.bsp", + "https://raw.githubusercontent.com/PerezHz/jpleph/main/a99942.tar.gz", +] + +# PlanetaryEphemeris.jl Solar System ephemeris name and URL +const name_sseph = "sseph_p100" +const url_sseph = "https://github.com/LuEdRaMo/sseph/raw/main/sseph343ast016_p100y_et.tar.gz" + +# Collect names and URLs +const urls = vcat(urls_lsk_spk, urls_debias, url_sseph) +const names = vcat(names_lsk_spk, names_debias, name_sseph) + +for (url, name) in zip(urls, names) + # Query the `Artifacts.toml` file for the hash bound to the name + # (returns `nothing` if no such binding exists) + artfct_hash = artifact_hash(name, artifact_toml) + # If the name was not bound, or the hash it was bound to does not exist, create it! + if isnothing(artfct_hash) || !artifact_exists(artfct_hash) + tb = Tuple[] + # create_artifact() returns the content-hash of the artifact directory once we're finished creating it + artfct_hash = create_artifact() do artifact_dir + # We create the artifact by simply downloading a few files into the new artifact directory + @show url name + tmp_dir = mktempdir() + basename_url = basename(url) + @show basename_url + dot_idx = findlast(isequal('.'), basename_url) + ext = basename_url[dot_idx+1:end] + if ext in ["gz", "tgz"] # If artifact is a tarball with many files + # the following code block was adapted from PlatformEngines.jl, MIT licensed + # https://github.com/JuliaLang/Pkg.jl/blob/048b0e86deba0c5f491eb1a3af2f3c97cac675b3/src/PlatformEngines.jl#L348 + dest = joinpath(tmp_dir, basename(url)) + tarball = "" + f = retry(delays = fill(1.0, 3)) do + try + tarball = Downloads.download(url, dest) + catch err + @debug "download and verify failed" url dest err + rethrow() + end + end + f() + try + tarball_hash = open(tarball) do file + bytes2hex(sha256(file)) + end + unpack(tarball, artifact_dir) + tb = [(url, tarball_hash)] + finally + rm(tarball) + end + else # url containing a single non-tarball file + fpath = Downloads.download(url, joinpath(artifact_dir, basename(url))) + file_hash = open(fpath) do file + bytes2hex(sha256(file)) + end + tb = [(url, file_hash)] + end + end + @show artfct_hash typeof(artfct_hash) + # Now bind that hash within our `Artifacts.toml`. `force = true` means that if it already exists, + # just overwrite the corresponding entry in `Artifacts.toml` with the new content-hash. + # Unless the source files change, we do not expect the content hash to + # change, so this should not cause unnecessary version control churn. + bind_artifact!(artifact_toml, name, artfct_hash, lazy=true, force=true, download_info=tb) + end + + # Get the path of the artifact, either newly created or previously generated. + # this should be something like `~/.julia/artifacts/dbd04e28be047a54fbe9bf67e934be5b5e0d357a` + artfct_path = artifact_path(artfct_hash) + println(name, " artifact saved to ", artfct_path) +end diff --git a/notebooks/Apophis.ipynb b/notebooks/Apophis.ipynb old mode 100644 new mode 100755 index 59f9c9a7..1249db69 --- a/notebooks/Apophis.ipynb +++ b/notebooks/Apophis.ipynb @@ -1,1131 +1,1131 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true, - "tags": [] - }, - "outputs": [], - "source": [ - "import Pkg\n", - "Pkg.activate(\"../pha\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "using Revise" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "using NEOs\n", - "using DataFrames\n", - "using TaylorIntegration\n", - "using PlanetaryEphemeris\n", - "using JLD2\n", - "using Statistics\n", - "using LinearAlgebra\n", - "using Dates\n", - "using StatsBase\n", - "using Gaston\n", - "using DelimitedFiles" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dq = set_variables(\"δx\", order=5, numvars=7)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Load Sun, Earth and Apophis ephemeris" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sol_bwd = JLD2.load(\"Apophis_bwd.jld2\", \"asteph\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sol_fwd = JLD2.load(\"Apophis_fwd.jld2\", \"asteph\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sseph::TaylorInterpolant{Float64,Float64,2} = loadpeeph(NEOs.sseph, sol_bwd.t0+sol_bwd.t[end], sol_fwd.t0+sol_fwd.t[end])\n", - "eph_su::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, su)\n", - "eph_ea::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, ea)\n", - "\n", - "# NEO\n", - "# Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec\n", - "xva_bwd(et) = auday2kmsec(sol_bwd(et/daysec)[1:6])\n", - "xva_fwd(et) = auday2kmsec(sol_fwd(et/daysec)[1:6])\n", - "xva(et) = bwdfwdeph(et, sol_bwd, sol_fwd)\n", - "# Earth\n", - "# Change x, v units, resp., from au, au/day to km, km/sec\n", - "xve(et) = auday2kmsec(eph_ea(et/daysec))\n", - "# Sun\n", - "# Change x, v units, resp., from au, au/day to km, km/sec\n", - "xvs(et) = auday2kmsec(eph_su(et/daysec))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "# get optical observations\n", - "radec_2004_2020 = read_radec_mpc(joinpath(pkgdir(NEOs), \"data\", \"99942_2004_2020.dat\"))\n", - "radec_2020_2021 = read_radec_mpc(joinpath(pkgdir(NEOs), \"data\", \"99942_2020_2021.dat\"))\n", - "radec = vcat(radec_2004_2020,radec_2020_2021)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "# get radar observations\n", - "deldop_2005_2013 = read_radar_jpl(joinpath(pkgdir(NEOs), \"data\", \"99942_RADAR_2005_2013.dat\"))\n", - "deldop_2021 = read_radar_jpl(joinpath(pkgdir(NEOs), \"data\", \"99942_RADAR_2021.dat\"))\n", - "deldop = vcat(deldop_2005_2013,deldop_2021)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "# Compute optical residuals\n", - "@time res_radec_all, w_radec_all = NEOs.residuals(radec; xvs, xve, xva);" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Compute radar residuals\n", - "@time res_del, w_del, res_dop, w_dop = NEOs.residuals(deldop; xvs, xve, xva, niter=10, tord=10);" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Process optical data (filter, weight, debias)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "# filter out biased observations from observatory 217 on 28-Jan-2021\n", - "df_radec = DataFrame(radec)\n", - "# add residuals and weights to optical astrometry DataFrame\n", - "df_radec[!, :res_α] .= res_radec_all[1:round(Int,length(res_radec_all)/2)]\n", - "df_radec[!, :res_δ] .= res_radec_all[1+round(Int,length(res_radec_all)/2):end]\n", - "df_radec[!, :w_α] .= w_radec_all[1:round(Int,length(res_radec_all)/2)]\n", - "df_radec[!, :w_δ] .= w_radec_all[1+round(Int,length(res_radec_all)/2):end]\n", - "filter!(\n", - " x->(Date(x.date) != Date(2021, 1, 28)),\n", - " df_radec\n", - ")\n", - "\n", - "# read astrometric errors from Tholen et al. (2013)\n", - "tho13_errors = readdlm(joinpath(pkgdir(NEOs), \"data\", \"tholenetal2013_opterror.dat\"), ',')\n", - "# compute weights\n", - "w_α_tho13 = 1 ./ (tho13_errors[:,1].^2 .+ tho13_errors[:,3].^2 .+ tho13_errors[:,5].^2)\n", - "w_δ_tho13 = 1 ./ (tho13_errors[:,2].^2 .+ tho13_errors[:,4].^2 .+ tho13_errors[:,6].^2)\n", - "# Tholen et al. (2013) obs table\n", - "radec_tho13 = DataFrame(read_radec_mpc(joinpath(pkgdir(NEOs), \"test\", \"data\", \"99942_Tholen_etal_2013.dat\")))\n", - "# vector of RA values from Tholen et al. (2013) observations (used for filtering)\n", - "tho13_α = radec_tho13[!,:α]\n", - "# set weights in Tholen et al. (2013) astrometry corresponding to associated uncertainties\n", - "df_radec[in.(df_radec.α, Ref(tho13_α)),:w_α] = w_α_tho13\n", - "df_radec[in.(df_radec.α, Ref(tho13_α)),:w_δ] = w_δ_tho13\n", - "\n", - "# Relaxation factor (account for correlations in optical astrometry data)\n", - "# for each observation batch, count the number of observations made in\n", - "# the same night by the same observatory\n", - "# Ref: Veres et al. (2017)\n", - "date_site_v = select(df_radec, :date => ByRow(Date), :observatory)\n", - "Nv = [count(x->x.date_Date==i.date_Date && x.observatory==i.observatory, eachrow(date_site_v)) for i in eachrow(date_site_v)]\n", - "relax_factor = map(x->x>4.0 ? x/4.0 : 1.0, Nv)\n", - "# inflate uncertainties (i.e., relax weights) by relaxation factor\n", - "df_radec[!, :w_α] .= (df_radec.w_α)./relax_factor\n", - "df_radec[!, :w_δ] .= (df_radec.w_δ)./relax_factor\n", - "\n", - "# update optical residuals and weights\n", - "res_radec = vcat(df_radec.res_α, df_radec.res_δ)\n", - "w_radec = vcat(df_radec.w_α, df_radec.w_δ)\n", - ";" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# check if all RA/Dec observations are CCD:\n", - "\n", - "all(\n", - " select(\n", - " df_radec, \n", - " :obstech => ByRow(x->x == \"C\" || x == \"X\")\n", - " )[!,1]\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# there are 512 RA/Dec obs without catalog info\n", - "\n", - "length(df_radec[isunknown.(df_radec.catalogue),:catalogue])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Construct vector of residuals and weights\n", - "\n", - "res = vcat(res_radec, res_del, res_dop)\n", - "w = vcat(w_radec, w_del, w_dop)\n", - ";" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "### Perform 7-DOF orbital fit to optical and radar astrometry data\n", - "\n", - "@show success, δx_OR7, Γ_OR7 = newtonls(res, w, zeros(get_numvars()), 10)\n", - "x_OR7 = sol_fwd(sol_fwd.t0)(δx_OR7);" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "### Perform 6-DOF orbital fit (i.e., without Yarkovsky effect) to optical and radar astrometry data\n", - "\n", - "δx_OR6, Γ_OR6 = newtonls_6v(res, w, zeros(get_numvars()), 10)\n", - "x_OR6 = sol_fwd(sol_fwd.t0)(δx_OR6);" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "### Print results\n", - "\n", - "# orbital fit\n", - "@show success\n", - "@show x_OR7 # cartesian state vector at solution reference epoch\n", - "@show sqrt.(diag(Γ_OR7)).*vcat(1e-8ones(6),1e-14) # uncertainties at solution reference epoch (1-sigma)\n", - ";" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Fit quality statistics: $\\chi^2$, normalized RMS" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The results below correspond to Table 1 of Pérez-Hernández and Benet (2022)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# post-fit statistics\n", - "\n", - "nradec = length(res_radec)\n", - "res_α = view(res_radec, 1:nradec÷2)\n", - "res_δ = view(res_radec, 1+nradec÷2:nradec)\n", - "res_τ = res_del\n", - "res_ν = res_dop\n", - "w_α = view(w_radec, 1:nradec÷2)\n", - "w_δ = view(w_radec, 1+nradec÷2:nradec)\n", - "res_α_OR6 = res_α(δx_OR6)\n", - "res_δ_OR6 = res_δ(δx_OR6)\n", - "res_α_OR7 = res_α(δx_OR7)\n", - "res_δ_OR7 = res_δ(δx_OR7)\n", - "\n", - "@show nrms_radec = nrms(res_radec(δx_OR7),w_radec)\n", - "@show nrms_radec = nrms(vcat(res_del,res_dop)(δx_OR7),vcat(w_del,w_dop))\n", - "@show nrms_optrad = nrms(res(δx_OR7),w)\n", - "@show mean_ra = mean(res_ra(δx_OR7), weights(w_ra))\n", - "@show mean_dec = mean(res_dec(δx_OR7), weights(w_dec))\n", - "@show mean_del = mean(res_del(δx_OR7), weights(w_del))\n", - "@show mean_dop = mean(res_dop(δx_OR7), weights(w_dop))\n", - "@show chi2_optrad = chi2(res(δx_OR7),w)\n", - ";" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Semimajor axis drift" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "jd0 = J2000 + sol_fwd.t0 #Julian date (TDB) of integration initial time\n", - "et0 = (jd0 - J2000)*daysec" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Apophis heliocentric position and velocity at solution reference epoch (plus autodiff perturbations)\n", - "xas = sol_fwd(sol_fwd.t0)[1:6] .- eph_su(jd0-J2000)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Orbital elements of new solution (ecliptic frame at J2000.0 epoch)\n", - "pv2kep(xas(δx_OR7), jd=jd0, frame=:ecliptic)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# JPL solution #216 for Apophis\n", - "kep_JPL216 = [\n", - " 0.1914347568286823, \n", - " 0.7460634895090179, \n", - " 2459424.558511739019, \n", - " 203.9662692226386, \n", - " 126.5900238507279, \n", - " 3.338874353538208, \n", - " -2.901085583204654E-14, \n", - " 5.E-13\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "kep_JT = pv2kep(xas, jd=jd0, frame=:ecliptic) # Orbital elements of JT solution at ref. epoch\n", - "kep_OR7 = pv2kep(xas(δx_OR7), jd=jd0, frame=:ecliptic) # Orbital elements of new solution at ref. epoch" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "# Jacobian of transformation: cartesian state -> Keplerian elements\n", - "t_car2kep(x) = hcat(\n", - " TaylorSeries.gradient(kep_JT.e), \n", - " TaylorSeries.gradient(kep_JT.q),\n", - " TaylorSeries.gradient(kep_JT.tp),\n", - " TaylorSeries.gradient(kep_JT.Ω),\n", - " TaylorSeries.gradient(kep_JT.ω),\n", - " TaylorSeries.gradient(kep_JT.i),\n", - " TaylorSeries.gradient(kep_JT.M),\n", - " TaylorSeries.gradient(kep_JT.a),\n", - " )(x)\n", - "\n", - "# semimajor axis drift \\dot{a} due to Yarkovsky effect in units of au per day, as a function of initial condition\n", - "ady_kep = yarkp2adot(sol_fwd(sol_fwd.t0)[7], kep_JT.a, kep_JT.e)\n", - "\n", - "# semimajor axis drift, au per million years\n", - "ady_kep_au_My = 1e6yr*ady_kep\n", - "\n", - "# semimajor axis drift, meters per year\n", - "ady_kep_m_y = 1e3au*yr*ady_kep\n", - "\n", - "# Jacobian of transformation: cartesian state -> semimajor axis drift in au per million years\n", - "t_kep2ady_au_My(x) = TaylorSeries.gradient(ady_kep_au_My)(x)\n", - "\n", - "# Jacobian of transformation: cartesian state -> semimajor axis drift in meters per year\n", - "t_kep2ady_m_y(x) = TaylorSeries.gradient(ady_kep_m_y)(x)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# mean semimajor axis drift, au per million years\n", - "ady_kep_au_My_OR7 = ady_kep_au_My(δx_OR7) # au/Myr" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# mean semimajor axis drift, meters per year\n", - "ady_kep_m_y_OR7 = 1e3au*yr*ady_kep(δx_OR7) # m/yr" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# uncertainty in semimajor axis drift, au per million years\n", - "sqrt( t_kep2ady_m_y(δx_OR7)'*Γ*t_kep2ady_m_y(δx_OR7) )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# uncertainty in semimajor axis drift, au per million years\n", - "sqrt( t_kep2ady_au_My(δx_OR7)'*Γ*t_kep2ady_au_My(δx_OR7) )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# covariance matrix of Keplerian elements\n", - "Γ_kep = t_car2kep(δx_OR7)'*Γ*t_car2kep(δx_OR7)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#formal uncertainties in Keplerian elements (1-sigma)\n", - "\n", - "sqrt.(diag(Γ_kep))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Plots: optical astrometry post-fit residuals" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#bins_hist = -2.0:0.1:2.0\n", - "nbins_plot = 100\n", - "\n", - "#h_a = fit(Histogram, res_α_OR6, bins_hist)\n", - "h_a = fit(Histogram, res_α_OR6, nbins=nbins_plot)\n", - "bc_a = midpoints(h_a.edges[1]) # bin centers\n", - "bs_a = fill(h_a.edges[1].step.hi, length(bc_a)) # bin sizes\n", - ";\n", - "\n", - "#h_b = fit(Histogram, res_δ_OR6, bins_hist)\n", - "h_b = fit(Histogram, res_δ_OR6, nbins=nbins_plot)\n", - "bc_b = midpoints(h_b.edges[1]) # bin centers\n", - "bs_b = fill(h_b.edges[1].step.hi, length(bc_b)) # bin sizes\n", - "\n", - "#h_c = fit(Histogram, res_α_OR7, bins_hist)\n", - "h_c = fit(Histogram, res_α_OR7, nbins=nbins_plot)\n", - "bc_c = midpoints(h_c.edges[1]) # bin centers\n", - "bs_c = fill(h_c.edges[1].step.hi, length(bc_c)) # bin sizes\n", - "\n", - "#h_d = fit(Histogram, res_δ_OR7, bins_hist)\n", - "h_d = fit(Histogram, res_δ_OR7, nbins=nbins_plot)\n", - "bc_d = midpoints(h_d.edges[1]) # bin centers\n", - "bs_d = fill(h_d.edges[1].step.hi, length(bc_d)) # bin sizes\n", - ";" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "minimum(res_α_OR6), maximum(res_α_OR6)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "minimum(res_δ_OR6), maximum(res_δ_OR6)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "minimum(res_α_OR7), maximum(res_α_OR7)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "minimum(res_δ_OR7), maximum(res_δ_OR7)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "mean(res_α_OR6), mean(res_δ_OR6)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "mean(res_α_OR7), mean(res_δ_OR7)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "angv = vcat(range(0, length=1000, stop=prevfloat(2pi)), 0)\n", - "sigma_factor = 3.0\n", - "σ_cos_ang = sigma_factor*cos.(angv)\n", - "σ_sin_ang = sigma_factor*sin.(angv)\n", - "\n", - "cov_αδ_cholf_OR6 = cholesky(cov(hcat(res_α_OR6, res_δ_OR6)))\n", - "cov_αδ_cholf_OR7 = cholesky(cov(hcat(res_α_OR7, res_δ_OR7)))\n", - "\n", - "ell_3σ_x_OR6 = mean(res_α_OR6) .+ cov_αδ_cholf_OR6.L[1,1].*σ_cos_ang .+ cov_αδ_cholf_OR6.L[1,2].*σ_sin_ang\n", - "ell_3σ_y_OR6 = mean(res_δ_OR6) .+ cov_αδ_cholf_OR6.L[2,1].*σ_cos_ang .+ cov_αδ_cholf_OR6.L[2,2].*σ_sin_ang\n", - "\n", - "ell_3σ_x_OR7 = mean(res_α_OR7) .+ cov_αδ_cholf_OR7.L[1,1].*σ_cos_ang .+ cov_αδ_cholf_OR7.L[1,2].*σ_sin_ang\n", - "ell_3σ_y_OR7 = mean(res_δ_OR7) .+ cov_αδ_cholf_OR7.L[2,1].*σ_cos_ang .+ cov_αδ_cholf_OR7.L[2,2].*σ_sin_ang\n", - ";" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "gap = 0.01\n", - "xlim_plt = 3.5\n", - "ymin_plt = -5.0\n", - "ymax_plt = 5.0\n", - "\n", - "Gaston.set(preamble=\"set grid; set style circle radius 0.02\")\n", - "\n", - "p1 = Gaston.plot(\n", - " bc_a,\n", - " h_a.weights./2, \n", - " supp=[bs_a./2 h_a.weights./2], \n", - " curveconf=\"w boxxy notit fs transparent solid 0.4\", \n", - " Axes(\n", - " #linetype = :tab10,\n", - " axesconf=\"set lmargin at screen 0.1; set rmargin at screen 0.85; set tmargin at screen 0.99; set bmargin at screen 0.8+$gap\",\n", - " xrange = (-xlim_plt, xlim_plt),\n", - " format = \"''\",\n", - " label=\"1 '(b)' at graph 0.05,0.8\"\n", - " ),\n", - " handle = 1\n", - ")\n", - "Gaston.plot!(\n", - " bc_c,\n", - " h_c.weights./2, \n", - " supp=[bs_c./2 h_c.weights./2], \n", - " curveconf=\"w boxxy notit fs transparent solid 0.4\"\n", - ")\n", - "\n", - "p2 = Gaston.plot(\n", - " res_α_OR6, \n", - " res_δ_OR6, \n", - " curveconf=\"w circles fill transparent solid 0.4 noborder tit 'gravity-only'\",\n", - " Axes(\n", - " #linetype = :tab10,\n", - " key=\"at screen 0.835, screen 0.78 box spacing 1.2 height 0.4\", #\"outside top right box spacing 1.2 height 1\",\n", - " axesconf=\"set lmargin at screen 0.1; set rmargin at screen 0.85; set tmargin at screen 0.8; set bmargin at screen 0.1\",\n", - " xrange = (-xlim_plt, xlim_plt),\n", - " yrange = (ymin_plt, ymax_plt),\n", - " format = \"\\\"%g\\\"\",\n", - " xlabel=\"'\\$\\\\alpha\\\\cos(\\\\delta)\\$ \\$[\\$arcsec\\$]\\$'\",\n", - " ylabel=\"'\\$\\\\delta\\$ \\$[\\$arcsec\\$]\\$'\",\n", - " label=\"1 '(a)' at graph 0.05,0.925\"\n", - " ), \n", - " handle = 2\n", - ")\n", - "Gaston.plot!(res_α_OR7, res_δ_OR7, \n", - " curveconf=\"w circles fill transparent solid 0.4 noborder tit 'non-grav.'\"\n", - ")\n", - "Gaston.plot!([mean(res_α_OR6)], [mean(res_δ_OR6)], curveconf=\"w p pt 4 ps 1.5 lw 8\") # tit 'mean R.A./Dec (OR6)'\n", - "Gaston.plot!([mean(res_α_OR7)], [mean(res_δ_OR7)], curveconf=\"w p pt 6 ps 1.5 lw 8\") # tit 'mean R.A./Dec (OR7)'\n", - "Gaston.plot!(ell_3σ_x_OR6, ell_3σ_y_OR6, curveconf=\"w l lw 8 lc 3\")\n", - "Gaston.plot!(ell_3σ_x_OR7, ell_3σ_y_OR7, curveconf=\"w l lw 8 lc 4\")\n", - "\n", - "p4 = Gaston.plot(\n", - " h_b.weights./2,\n", - " bc_b,\n", - " supp=[h_b.weights./2 bs_b./2],\n", - " curveconf=\"w boxxy notit fs transparent solid 0.4\",\n", - " Axes(\n", - " #linetype = :tab10,\n", - " axesconf=\"set lmargin at screen 0.85+$gap; set rmargin at screen 0.99; set tmargin at screen 0.8; set bmargin at screen 0.1\",\n", - " yrange = (ymin_plt, ymax_plt),\n", - " format = \"''\",\n", - " label=\"1 '(c)' at graph 0.15,0.925\"\n", - " ),\n", - " handle = 4\n", - ")\n", - "Gaston.plot!(\n", - " h_d.weights./2,\n", - " bc_d,\n", - " supp=[h_d.weights./2 bs_d./2],\n", - " curveconf=\"w boxxy notit fs transparent solid 0.4\"\n", - ")\n", - "\n", - "Gaston.plot([p1 nothing ; p2 p4])\n", - "\n", - "#Gaston.save(term = \"cairolatex\", output = \"radec_hist.tex\", saveopts = \"pdf standalone color dashed transparent size 7in,5in font ',12'\")\n", - "#run(`lualatex radec_hist.tex`)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Plots: radar astrometry post-fit residuals" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "del_index = findall(x->x.Δτ_units==\"us\", deldop)\n", - "dop_index = findall(x->x.Δν_units==\"Hz\", deldop)\n", - "length(del_index), length(dop_index)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "length(deldop)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "del_dates_plot_ = date.(deldop[del_index])\n", - "dop_dates_plot_ = date.(deldop[dop_index])\n", - "\n", - "del_dates_plot = Dates.format.(del_dates_plot_, \"dd/mm/yy HHMM\")\n", - "dop_dates_plot = Dates.format.(dop_dates_plot_, \"dd/mm/yy HHMM\")\n", - "\n", - "σ_del_all = delay_sigma.(deldop[del_index])\n", - "σ_dop_all = doppler_sigma.(deldop[dop_index])\n", - ";" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "p1 = Gaston.plot(\n", - " del_index,\n", - " res_τ(δx_OR6),\n", - " supp = σ_del_all,\n", - " key=\"box spacing 1.2 height 0.4\", #at screen 0.835, screen 0.78 \n", - " curveconf = \"u 1:2:3 w errorbars pt 6 lw 4 tit 'gravity-only'\",\n", - " Axes(\n", - " #axesconf=\"set lmargin at screen 0.15; set rmargin at screen 0.95; set bmargin at screen 0.5\",\n", - " axesconf=\"set lmargin at screen 0.11\",\n", - " #linetype = :tab10,\n", - " bars = 2,\n", - " ylabel = \"'Time-delay resid. \\$[\\$us\\$]\\$'\",\n", - " xrange = (0,39),\n", - " xtics = \"1,2,40\",\n", - " format = \"y '%1.1f'\",\n", - " yrange=(-7,8),\n", - " label=\"1 '(a)' at graph 0.05,0.9\"#,\n", - " #title = \"'gravity-only'\"\n", - " ),\n", - " handle = 1\n", - ")\n", - "Gaston.plot!(\n", - " del_index,\n", - " res_τ(δx_OR7),\n", - " supp = σ_del_all,\n", - " curveconf = \"u 1:2:3 w errorbars pt 4 lw 4 tit 'non-gravitational'\",\n", - " lc = 2\n", - ")\n", - "\n", - "p2 = Gaston.plot(\n", - " dop_index,\n", - " res_ν(δx_OR6),\n", - " supp = σ_dop_all,\n", - " curveconf = \"u 1:2:3 w errorbars pt 6 lw 4 tit 'gravity-only'\",\n", - " key=\"box spacing 1.2 height 0.4\",\n", - " Axes(\n", - " #axesconf=\"set lmargin at screen 0.15; set rmargin at screen 0.95; set tmargin at screen 0.5\",\n", - " axesconf=\"set lmargin at screen 0.11\",\n", - " #linetype = :tab10,\n", - " bars = 2,\n", - " ylabel = \"'Doppler shift resid. \\$[\\$Hz\\$]\\$'\",\n", - " xrange = (0,39),\n", - " xtics = \"1,2,40\",\n", - " format = \"y '%1.1f'\",\n", - " yrange=(-0.6,0.8),\n", - " label=\"1 '(b)' at graph 0.05,0.9\" #,\n", - " # title = \"'non-gravitational'\"\n", - " ),\n", - " handle = 2\n", - ")\n", - "Gaston.plot!(\n", - " dop_index,\n", - " res_ν(δx_OR7),\n", - " supp = σ_dop_all,\n", - " curveconf = \"u 1:2:3 w errorbars pt 4 lw 4 tit 'non-gravitational'\",\n", - " lc = 2\n", - ")\n", - "\n", - "\n", - "Gaston.plot([p1; p2])\n", - "\n", - "#Gaston.save(term = \"cairolatex\", output = \"deldop_residuals.tex\", saveopts = \"pdf standalone color dashed transparent size 10in,7in font ',14'\")\n", - "#run(`pdflatex deldop_residuals.tex`)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "deldop_dates_plot_xaxis = vcat(\"01/06/04 0000\", del_dates_plot, \"31/03/21 2359\");" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "tmargin_bmargin_gap = 0.03\n", - "bmargin_ths_plt = 0.5 + tmargin_bmargin_gap\n", - "tmargin_ths_plt = 0.965\n", - "axsbrk_v = 1.25*0.01\n", - "axsbrk_h = 1.25*0.005\n", - "lw_ths_plt = 3\n", - "rmargin_ths_plt = 0.3\n", - "\n", - "p1 = Gaston.plot(\n", - " del_dates_plot,\n", - " res_τ(δx_OR6),\n", - " supp = σ_del_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", - " Axes(\n", - " #linetype = :tab10,\n", - " axesconf = \"set rmargin at screen 0.3; set tmargin at screen $tmargin_ths_plt; set bmargin at screen $bmargin_ths_plt\",\n", - " xdata = \"time\",\n", - " timefmt = \"'%d/%m/%y %H%M'\",\n", - " xtics = false, #\"format '' time (\\\"01/01/05\\\",\\\"01/01/06\\\")\", # '%d/%b/%y'\n", - " xrange = \"[\\\"01/12/04\\\":\\\"30/05/06\\\"]\",\n", - " #xlabel = \"\\\"Date\\\"\",\n", - " bars = false, #2,\n", - " ylabel = \"'Time-delay resid. (O-C) [\\$\\\\mu\\$s]'\",\n", - " border = \"1+2+4\",\n", - " ytics = [\"nomirror\", \"format '%1.1f'\"],\n", - " yrange = \"[-8.0:6.0]\",\n", - " arrow = [\n", - " \"from screen 0.3-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.3+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.3-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.3+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\"\n", - " ],\n", - " label=\"1 '(a)' at graph 0.2,0.9\",\n", - " grid=false\n", - " #arrow = \"from screen 0.3-0.01,1.0-0.01 to screen 0.3+0.01,1.0+0.01 nohead\"\n", - " #format = \"x ''\"\n", - " #title = \"'Time-delay resid. (O-C)'\"\n", - " ),\n", - " handle = 1\n", - ")\n", - "Gaston.plot!(\n", - " del_dates_plot,\n", - " res_τ(δx_OR7),\n", - " supp = σ_del_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", - " lc = 2\n", - ")\n", - "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", - "\n", - "p2 = Gaston.plot(\n", - " del_dates_plot,\n", - " res_τ(δx_OR6),\n", - " supp = σ_del_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", - " Axes(\n", - " #linetype = :tab10,\n", - " xdata = \"time\",\n", - " timefmt = \"'%d/%m/%y %H%M'\",\n", - " axesconf = \"set lmargin at screen 0.35; set tmargin at screen $tmargin_ths_plt; set rmargin at screen 0.8; set bmargin at screen $bmargin_ths_plt\",\n", - " xtics = false, #\"format '' time (\\\"01/01/13\\\",\\\"01/02/13\\\",\\\"01/03/13\\\")\", # '%d/%b/%y'\n", - " xrange = \"[\\\"15/12/12\\\":\\\"20/03/13\\\"]\",\n", - " #xlabel = \"\\\"Date\\\"\",\n", - " bars = false, #2,\n", - " #tics=\"scale 0\",\n", - " ytics = false, #[false, \"(\\\"\\\" 0)\"], #\"nomirror\",\n", - " border = \"1+4\",\n", - " yrange = \"[-8.0:6.0]\",\n", - " format = [\"x ''\", \"y ''\"], #%1.1f\n", - " arrow = [\n", - " \"from screen 0.35-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.35+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.35-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.35+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.80-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.80+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.80-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.80+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\"\n", - " ],\n", - " #ylabel = \"'[us]'\"\n", - " ),\n", - " handle = 2\n", - ")\n", - "Gaston.plot!(\n", - " del_dates_plot,\n", - " res_τ(δx_OR7),\n", - " supp = σ_del_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", - " lc = 2\n", - ")\n", - "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", - "\n", - "p3 = Gaston.plot(\n", - " del_dates_plot,\n", - " res_τ(δx_OR6),\n", - " supp = σ_del_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", - " Axes(\n", - " #linetype = :tab10,\n", - " xdata = \"time\",\n", - " timefmt = \"'%d/%m/%y %H%M'\",\n", - " axesconf = \"set lmargin at screen 0.85; set tmargin at screen 0.965; set bmargin at screen $bmargin_ths_plt\",\n", - " xtics = false, #\"format '' time (\\\"03/03/21\\\",\\\"11/03/21\\\")\", #'%d/%b/%y'\n", - " xrange = \"[\\\"02/03/21\\\":\\\"15/03/21\\\"]\",\n", - " #xlabel = \"\\\"Date\\\"\",\n", - " bars = false, #2,\n", - " #tics=\"scale 0\",\n", - " ytics = false, #[false, \"(\\\"\\\" 0)\"], #\"nomirror\",\n", - " border = \"1+4+8\",\n", - " yrange = \"[-8.0:6.0]\",\n", - " format = [\"x ''\", \"y ''\"], #%1.1f\n", - " arrow = [\n", - " \"from screen 0.85-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.85+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.85-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.85+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\"\n", - " ],\n", - " #ylabel = \"'[us]'\"\n", - " ),\n", - " handle = 3\n", - ")\n", - "Gaston.plot!(\n", - " del_dates_plot,\n", - " res_τ(δx_OR7),\n", - " supp = σ_del_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", - " lc = 2\n", - ")\n", - "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", - "\n", - "Gaston.plot([p1 p2 p3])\n", - "\n", - "#Gaston.save(term = \"cairolatex\", output = \"del_resids.tex\", saveopts = \"pdf standalone color dashed transparent size 10in,7in font ',14'\")\n", - "#run(`pdflatex del_resids.tex`)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "jupyter": { - "source_hidden": true - } - }, - "outputs": [], - "source": [ - "tmargin_ths_plt = 0.5 - tmargin_bmargin_gap\n", - "bmargin_ths_plt = 0.05\n", - "\n", - "Gaston.set(preamble=\"unset grid\")\n", - "p4 = Gaston.plot(\n", - " dop_dates_plot,\n", - " res_ν(δx_OR6),\n", - " supp = σ_dop_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", - " Axes(\n", - " #linetype = :tab10,\n", - " axesconf=\"set rmargin at screen $rmargin_ths_plt; set tmargin at screen $tmargin_ths_plt; set bmargin at screen $bmargin_ths_plt\",\n", - " xdata = \"time\",\n", - " timefmt = \"'%d/%m/%y %H%M'\",\n", - " xtics = \"format '%d/%b/%y' time (\\\"01/01/05\\\",\\\"01/01/06\\\")\",\n", - " xrange = \"[\\\"01/12/04\\\":\\\"30/05/06\\\"]\",\n", - " #xlabel = \"\\\"Date\\\"\",\n", - " bars = false,#2,\n", - " ylabel = \"'Doppler shift resid. (O-C) [Hz]'\",\n", - " border=\"1+2+4\",\n", - " ytics = [\"nomirror\", \"format '%1.1f'\"],\n", - " yrange=\"[-0.5:0.5]\",\n", - " arrow = [\n", - " \"from screen 0.3-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.3+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.3-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.3+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\"\n", - " ],\n", - " label=\"1 '(b)' at graph 0.2,0.9\"\n", - " #title = \"'Doppler shift resid. (O-C)'\"\n", - " ),\n", - " handle = 4\n", - ")\n", - "Gaston.plot!(\n", - " dop_dates_plot,\n", - " res_ν(δx_OR7),\n", - " supp = σ_dop_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", - " lc = 2\n", - ")\n", - "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", - "\n", - "p5 = Gaston.plot(\n", - " dop_dates_plot,\n", - " res_ν(δx_OR6),\n", - " supp = σ_dop_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", - " Axes(\n", - " #linetype = :tab10,\n", - " xdata = \"time\",\n", - " timefmt = \"'%d/%m/%y %H%M'\",\n", - " axesconf=\"set lmargin at screen $rmargin_ths_plt+0.05; set rmargin at screen 0.8; set tmargin at screen $tmargin_ths_plt; set bmargin at screen $bmargin_ths_plt\",\n", - " xtics=\"format '%d/%b/%y' time (\\\"01/01/13\\\",\\\"01/02/13\\\",\\\"01/03/13\\\")\",\n", - " xrange=\"[\\\"15/12/12\\\":\\\"20/03/13\\\"]\",\n", - " #xlabel = \"\\\"Date\\\"\",\n", - " bars = false, #2,\n", - " ytics=false,\n", - " border=\"1+4\",\n", - " yrange=\"[-0.5:0.5]\",\n", - " arrow = [\n", - " \"from screen 0.35-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.35+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.35-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.35+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.8-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.8+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.8-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.8+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\"\n", - " ],\n", - " #ylabel = \"'[Hz]'\"\n", - " ),\n", - " handle = 5\n", - ")\n", - "Gaston.plot!(\n", - " dop_dates_plot,\n", - " res_ν(δx_OR7),\n", - " supp = σ_dop_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", - " lc = 2\n", - ")\n", - "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", - "\n", - "p6 = Gaston.plot(\n", - " dop_dates_plot,\n", - " res_ν(δx_OR6),\n", - " supp = σ_dop_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", - " Axes(\n", - " #linetype = :tab10,\n", - " xdata = \"time\",\n", - " timefmt = \"'%d/%m/%y %H%M'\",\n", - " axesconf=\"set lmargin at screen 0.85; set tmargin at screen $tmargin_ths_plt; set bmargin at screen $bmargin_ths_plt\",\n", - " xtics=\"format '%d/%b/%y' time (\\\"03/03/21\\\",\\\"13/03/21\\\")\",\n", - " xrange=\"[\\\"02/03/21\\\":\\\"15/03/21\\\"]\",\n", - " #xlabel = \"\\\"Date\\\"\",\n", - " bars = false, #2,\n", - " #format=\"y ''\",\n", - " ytics=false,\n", - " border=\"1+4+8\",\n", - " yrange=\"[-0.5:0.5]\",\n", - " arrow = [\n", - " \"from screen 0.85-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.85+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.85-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.85+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\"\n", - " ],\n", - " #ylabel = \"'[Hz]'\"\n", - " ),\n", - " handle = 6\n", - ")\n", - "Gaston.plot!(\n", - " dop_dates_plot,\n", - " res_ν(δx_OR7),\n", - " supp = σ_dop_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", - " lc = 2\n", - ")\n", - "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", - "\n", - "Gaston.plot([p4 p5 p6])\n", - "\n", - "#Gaston.save(term = \"cairolatex\", output = \"dop_resids.tex\", saveopts = \"pdf standalone color dashed transparent size 10in,7in font ',14'\")\n", - "#run(`pdflatex dop_resids.tex`)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Gaston.plot([p1 p2 p3; p4 p5 p6])\n", - "\n", - "#Gaston.save(term = \"cairolatex\", output = \"deldop_residuals_dates.tex\", saveopts = \"pdf standalone color dashed transparent size 10in,7in font ',14'\")\n", - "#run(`lualatex deldop_residuals_dates.tex`)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Julia-4-threads 1.9.1", - "language": "julia", - "name": "julia-4-threads-1.9" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.9.2" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "import Pkg\n", + "Pkg.activate(\"../pha\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "using Revise" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "using NEOs\n", + "using DataFrames\n", + "using TaylorIntegration\n", + "using PlanetaryEphemeris\n", + "using JLD2\n", + "using Statistics\n", + "using LinearAlgebra\n", + "using Dates\n", + "using StatsBase\n", + "using Gaston\n", + "using DelimitedFiles" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dq = set_variables(\"δx\", order=5, numvars=7)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load Sun, Earth and Apophis ephemeris" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sol_bwd = JLD2.load(\"Apophis_bwd.jld2\", \"asteph\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sol_fwd = JLD2.load(\"Apophis_fwd.jld2\", \"asteph\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sseph::TaylorInterpolant{Float64,Float64,2} = loadpeeph(NEOs.sseph, sol_bwd.t0+sol_bwd.t[end], sol_fwd.t0+sol_fwd.t[end])\n", + "eph_su::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, su)\n", + "eph_ea::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, ea)\n", + "\n", + "# NEO\n", + "# Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec\n", + "xva_bwd(et) = auday2kmsec(sol_bwd(et/daysec)[1:6])\n", + "xva_fwd(et) = auday2kmsec(sol_fwd(et/daysec)[1:6])\n", + "xva(et) = bwdfwdeph(et, sol_bwd, sol_fwd)\n", + "# Earth\n", + "# Change x, v units, resp., from au, au/day to km, km/sec\n", + "xve(et) = auday2kmsec(eph_ea(et/daysec))\n", + "# Sun\n", + "# Change x, v units, resp., from au, au/day to km, km/sec\n", + "xvs(et) = auday2kmsec(eph_su(et/daysec))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# get optical observations\n", + "radec_2004_2020 = read_radec_mpc(joinpath(pkgdir(NEOs), \"data\", \"99942_2004_2020.dat\"))\n", + "radec_2020_2021 = read_radec_mpc(joinpath(pkgdir(NEOs), \"data\", \"99942_2020_2021.dat\"))\n", + "radec = vcat(radec_2004_2020,radec_2020_2021)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# get radar observations\n", + "deldop_2005_2013 = read_radar_jpl(joinpath(pkgdir(NEOs), \"data\", \"99942_RADAR_2005_2013.dat\"))\n", + "deldop_2021 = read_radar_jpl(joinpath(pkgdir(NEOs), \"data\", \"99942_RADAR_2021.dat\"))\n", + "deldop = vcat(deldop_2005_2013,deldop_2021)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# Compute optical residuals\n", + "@time res_radec_all, w_radec_all = NEOs.residuals(radec; xvs, xve, xva);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Compute radar residuals\n", + "@time res_del, w_del, res_dop, w_dop = NEOs.residuals(deldop; xvs, xve, xva, niter=10, tord=10);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Process optical data (filter, weight, debias)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# filter out biased observations from observatory 217 on 28-Jan-2021\n", + "df_radec = DataFrame(radec)\n", + "# add residuals and weights to optical astrometry DataFrame\n", + "df_radec[!, :res_α] .= res_radec_all[1:round(Int,length(res_radec_all)/2)]\n", + "df_radec[!, :res_δ] .= res_radec_all[1+round(Int,length(res_radec_all)/2):end]\n", + "df_radec[!, :w_α] .= w_radec_all[1:round(Int,length(res_radec_all)/2)]\n", + "df_radec[!, :w_δ] .= w_radec_all[1+round(Int,length(res_radec_all)/2):end]\n", + "filter!(\n", + " x->(Date(x.date) != Date(2021, 1, 28)),\n", + " df_radec\n", + ")\n", + "\n", + "# read astrometric errors from Tholen et al. (2013)\n", + "tho13_errors = readdlm(joinpath(pkgdir(NEOs), \"data\", \"tholenetal2013_opterror.dat\"), ',')\n", + "# compute weights\n", + "w_α_tho13 = 1 ./ (tho13_errors[:,1].^2 .+ tho13_errors[:,3].^2 .+ tho13_errors[:,5].^2)\n", + "w_δ_tho13 = 1 ./ (tho13_errors[:,2].^2 .+ tho13_errors[:,4].^2 .+ tho13_errors[:,6].^2)\n", + "# Tholen et al. (2013) obs table\n", + "radec_tho13 = DataFrame(read_radec_mpc(joinpath(pkgdir(NEOs), \"test\", \"data\", \"99942_Tholen_etal_2013.dat\")))\n", + "# vector of RA values from Tholen et al. (2013) observations (used for filtering)\n", + "tho13_α = radec_tho13[!,:α]\n", + "# set weights in Tholen et al. (2013) astrometry corresponding to associated uncertainties\n", + "df_radec[in.(df_radec.α, Ref(tho13_α)),:w_α] = w_α_tho13\n", + "df_radec[in.(df_radec.α, Ref(tho13_α)),:w_δ] = w_δ_tho13\n", + "\n", + "# Relaxation factor (account for correlations in optical astrometry data)\n", + "# for each observation batch, count the number of observations made in\n", + "# the same night by the same observatory\n", + "# Ref: Veres et al. (2017)\n", + "date_site_v = select(df_radec, :date => ByRow(Date), :observatory)\n", + "Nv = [count(x->x.date_Date==i.date_Date && x.observatory==i.observatory, eachrow(date_site_v)) for i in eachrow(date_site_v)]\n", + "relax_factor = map(x->x>4.0 ? x/4.0 : 1.0, Nv)\n", + "# inflate uncertainties (i.e., relax weights) by relaxation factor\n", + "df_radec[!, :w_α] .= (df_radec.w_α)./relax_factor\n", + "df_radec[!, :w_δ] .= (df_radec.w_δ)./relax_factor\n", + "\n", + "# update optical residuals and weights\n", + "res_radec = vcat(df_radec.res_α, df_radec.res_δ)\n", + "w_radec = vcat(df_radec.w_α, df_radec.w_δ)\n", + ";" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# check if all RA/Dec observations are CCD:\n", + "\n", + "all(\n", + " select(\n", + " df_radec, \n", + " :obstech => ByRow(x->x == \"C\" || x == \"X\")\n", + " )[!,1]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# there are 512 RA/Dec obs without catalog info\n", + "\n", + "length(df_radec[isunknown.(df_radec.catalogue),:catalogue])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Construct vector of residuals and weights\n", + "\n", + "res = vcat(res_radec, res_del, res_dop)\n", + "w = vcat(w_radec, w_del, w_dop)\n", + ";" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "### Perform 7-DOF orbital fit to optical and radar astrometry data\n", + "\n", + "@show success, δx_OR7, Γ_OR7 = newtonls(res, w, zeros(get_numvars()), 10)\n", + "x_OR7 = sol_fwd(sol_fwd.t0)(δx_OR7);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "### Perform 6-DOF orbital fit (i.e., without Yarkovsky effect) to optical and radar astrometry data\n", + "\n", + "δx_OR6, Γ_OR6 = newtonls_6v(res, w, zeros(get_numvars()), 10)\n", + "x_OR6 = sol_fwd(sol_fwd.t0)(δx_OR6);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "### Print results\n", + "\n", + "# orbital fit\n", + "@show success\n", + "@show x_OR7 # cartesian state vector at solution reference epoch\n", + "@show sqrt.(diag(Γ_OR7)).*vcat(1e-8ones(6),1e-14) # uncertainties at solution reference epoch (1-sigma)\n", + ";" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Fit quality statistics: $\\chi^2$, normalized RMS" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The results below correspond to Table 1 of Pérez-Hernández and Benet (2022)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# post-fit statistics\n", + "\n", + "nradec = length(res_radec)\n", + "res_α = view(res_radec, 1:nradec÷2)\n", + "res_δ = view(res_radec, 1+nradec÷2:nradec)\n", + "res_τ = res_del\n", + "res_ν = res_dop\n", + "w_α = view(w_radec, 1:nradec÷2)\n", + "w_δ = view(w_radec, 1+nradec÷2:nradec)\n", + "res_α_OR6 = res_α(δx_OR6)\n", + "res_δ_OR6 = res_δ(δx_OR6)\n", + "res_α_OR7 = res_α(δx_OR7)\n", + "res_δ_OR7 = res_δ(δx_OR7)\n", + "\n", + "@show nrms_radec = nrms(res_radec(δx_OR7),w_radec)\n", + "@show nrms_radec = nrms(vcat(res_del,res_dop)(δx_OR7),vcat(w_del,w_dop))\n", + "@show nrms_optrad = nrms(res(δx_OR7),w)\n", + "@show mean_ra = mean(res_ra(δx_OR7), weights(w_ra))\n", + "@show mean_dec = mean(res_dec(δx_OR7), weights(w_dec))\n", + "@show mean_del = mean(res_del(δx_OR7), weights(w_del))\n", + "@show mean_dop = mean(res_dop(δx_OR7), weights(w_dop))\n", + "@show chi2_optrad = chi2(res(δx_OR7),w)\n", + ";" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Semimajor axis drift" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "jd0 = J2000 + sol_fwd.t0 #Julian date (TDB) of integration initial time\n", + "et0 = (jd0 - J2000)*daysec" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Apophis heliocentric position and velocity at solution reference epoch (plus autodiff perturbations)\n", + "xas = sol_fwd(sol_fwd.t0)[1:6] .- eph_su(jd0-J2000)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Orbital elements of new solution (ecliptic frame at J2000.0 epoch)\n", + "pv2kep(xas(δx_OR7), jd=jd0, frame=:ecliptic)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# JPL solution #216 for Apophis\n", + "kep_JPL216 = [\n", + " 0.1914347568286823, \n", + " 0.7460634895090179, \n", + " 2459424.558511739019, \n", + " 203.9662692226386, \n", + " 126.5900238507279, \n", + " 3.338874353538208, \n", + " -2.901085583204654E-14, \n", + " 5.E-13\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "kep_JT = pv2kep(xas, jd=jd0, frame=:ecliptic) # Orbital elements of JT solution at ref. epoch\n", + "kep_OR7 = pv2kep(xas(δx_OR7), jd=jd0, frame=:ecliptic) # Orbital elements of new solution at ref. epoch" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# Jacobian of transformation: cartesian state -> Keplerian elements\n", + "t_car2kep(x) = hcat(\n", + " TaylorSeries.gradient(kep_JT.e), \n", + " TaylorSeries.gradient(kep_JT.q),\n", + " TaylorSeries.gradient(kep_JT.tp),\n", + " TaylorSeries.gradient(kep_JT.Ω),\n", + " TaylorSeries.gradient(kep_JT.ω),\n", + " TaylorSeries.gradient(kep_JT.i),\n", + " TaylorSeries.gradient(kep_JT.M),\n", + " TaylorSeries.gradient(kep_JT.a),\n", + " )(x)\n", + "\n", + "# semimajor axis drift \\dot{a} due to Yarkovsky effect in units of au per day, as a function of initial condition\n", + "ady_kep = yarkp2adot(sol_fwd(sol_fwd.t0)[7], kep_JT.a, kep_JT.e)\n", + "\n", + "# semimajor axis drift, au per million years\n", + "ady_kep_au_My = 1e6yr*ady_kep\n", + "\n", + "# semimajor axis drift, meters per year\n", + "ady_kep_m_y = 1e3au*yr*ady_kep\n", + "\n", + "# Jacobian of transformation: cartesian state -> semimajor axis drift in au per million years\n", + "t_kep2ady_au_My(x) = TaylorSeries.gradient(ady_kep_au_My)(x)\n", + "\n", + "# Jacobian of transformation: cartesian state -> semimajor axis drift in meters per year\n", + "t_kep2ady_m_y(x) = TaylorSeries.gradient(ady_kep_m_y)(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# mean semimajor axis drift, au per million years\n", + "ady_kep_au_My_OR7 = ady_kep_au_My(δx_OR7) # au/Myr" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# mean semimajor axis drift, meters per year\n", + "ady_kep_m_y_OR7 = 1e3au*yr*ady_kep(δx_OR7) # m/yr" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# uncertainty in semimajor axis drift, au per million years\n", + "sqrt( t_kep2ady_m_y(δx_OR7)'*Γ*t_kep2ady_m_y(δx_OR7) )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# uncertainty in semimajor axis drift, au per million years\n", + "sqrt( t_kep2ady_au_My(δx_OR7)'*Γ*t_kep2ady_au_My(δx_OR7) )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# covariance matrix of Keplerian elements\n", + "Γ_kep = t_car2kep(δx_OR7)'*Γ*t_car2kep(δx_OR7)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#formal uncertainties in Keplerian elements (1-sigma)\n", + "\n", + "sqrt.(diag(Γ_kep))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plots: optical astrometry post-fit residuals" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#bins_hist = -2.0:0.1:2.0\n", + "nbins_plot = 100\n", + "\n", + "#h_a = fit(Histogram, res_α_OR6, bins_hist)\n", + "h_a = fit(Histogram, res_α_OR6, nbins=nbins_plot)\n", + "bc_a = midpoints(h_a.edges[1]) # bin centers\n", + "bs_a = fill(h_a.edges[1].step.hi, length(bc_a)) # bin sizes\n", + ";\n", + "\n", + "#h_b = fit(Histogram, res_δ_OR6, bins_hist)\n", + "h_b = fit(Histogram, res_δ_OR6, nbins=nbins_plot)\n", + "bc_b = midpoints(h_b.edges[1]) # bin centers\n", + "bs_b = fill(h_b.edges[1].step.hi, length(bc_b)) # bin sizes\n", + "\n", + "#h_c = fit(Histogram, res_α_OR7, bins_hist)\n", + "h_c = fit(Histogram, res_α_OR7, nbins=nbins_plot)\n", + "bc_c = midpoints(h_c.edges[1]) # bin centers\n", + "bs_c = fill(h_c.edges[1].step.hi, length(bc_c)) # bin sizes\n", + "\n", + "#h_d = fit(Histogram, res_δ_OR7, bins_hist)\n", + "h_d = fit(Histogram, res_δ_OR7, nbins=nbins_plot)\n", + "bc_d = midpoints(h_d.edges[1]) # bin centers\n", + "bs_d = fill(h_d.edges[1].step.hi, length(bc_d)) # bin sizes\n", + ";" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "minimum(res_α_OR6), maximum(res_α_OR6)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "minimum(res_δ_OR6), maximum(res_δ_OR6)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "minimum(res_α_OR7), maximum(res_α_OR7)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "minimum(res_δ_OR7), maximum(res_δ_OR7)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mean(res_α_OR6), mean(res_δ_OR6)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mean(res_α_OR7), mean(res_δ_OR7)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "angv = vcat(range(0, length=1000, stop=prevfloat(2pi)), 0)\n", + "sigma_factor = 3.0\n", + "σ_cos_ang = sigma_factor*cos.(angv)\n", + "σ_sin_ang = sigma_factor*sin.(angv)\n", + "\n", + "cov_αδ_cholf_OR6 = cholesky(cov(hcat(res_α_OR6, res_δ_OR6)))\n", + "cov_αδ_cholf_OR7 = cholesky(cov(hcat(res_α_OR7, res_δ_OR7)))\n", + "\n", + "ell_3σ_x_OR6 = mean(res_α_OR6) .+ cov_αδ_cholf_OR6.L[1,1].*σ_cos_ang .+ cov_αδ_cholf_OR6.L[1,2].*σ_sin_ang\n", + "ell_3σ_y_OR6 = mean(res_δ_OR6) .+ cov_αδ_cholf_OR6.L[2,1].*σ_cos_ang .+ cov_αδ_cholf_OR6.L[2,2].*σ_sin_ang\n", + "\n", + "ell_3σ_x_OR7 = mean(res_α_OR7) .+ cov_αδ_cholf_OR7.L[1,1].*σ_cos_ang .+ cov_αδ_cholf_OR7.L[1,2].*σ_sin_ang\n", + "ell_3σ_y_OR7 = mean(res_δ_OR7) .+ cov_αδ_cholf_OR7.L[2,1].*σ_cos_ang .+ cov_αδ_cholf_OR7.L[2,2].*σ_sin_ang\n", + ";" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gap = 0.01\n", + "xlim_plt = 3.5\n", + "ymin_plt = -5.0\n", + "ymax_plt = 5.0\n", + "\n", + "Gaston.set(preamble=\"set grid; set style circle radius 0.02\")\n", + "\n", + "p1 = Gaston.plot(\n", + " bc_a,\n", + " h_a.weights./2, \n", + " supp=[bs_a./2 h_a.weights./2], \n", + " curveconf=\"w boxxy notit fs transparent solid 0.4\", \n", + " Axes(\n", + " #linetype = :tab10,\n", + " axesconf=\"set lmargin at screen 0.1; set rmargin at screen 0.85; set tmargin at screen 0.99; set bmargin at screen 0.8+$gap\",\n", + " xrange = (-xlim_plt, xlim_plt),\n", + " format = \"''\",\n", + " label=\"1 '(b)' at graph 0.05,0.8\"\n", + " ),\n", + " handle = 1\n", + ")\n", + "Gaston.plot!(\n", + " bc_c,\n", + " h_c.weights./2, \n", + " supp=[bs_c./2 h_c.weights./2], \n", + " curveconf=\"w boxxy notit fs transparent solid 0.4\"\n", + ")\n", + "\n", + "p2 = Gaston.plot(\n", + " res_α_OR6, \n", + " res_δ_OR6, \n", + " curveconf=\"w circles fill transparent solid 0.4 noborder tit 'gravity-only'\",\n", + " Axes(\n", + " #linetype = :tab10,\n", + " key=\"at screen 0.835, screen 0.78 box spacing 1.2 height 0.4\", #\"outside top right box spacing 1.2 height 1\",\n", + " axesconf=\"set lmargin at screen 0.1; set rmargin at screen 0.85; set tmargin at screen 0.8; set bmargin at screen 0.1\",\n", + " xrange = (-xlim_plt, xlim_plt),\n", + " yrange = (ymin_plt, ymax_plt),\n", + " format = \"\\\"%g\\\"\",\n", + " xlabel=\"'\\$\\\\alpha\\\\cos(\\\\delta)\\$ \\$[\\$arcsec\\$]\\$'\",\n", + " ylabel=\"'\\$\\\\delta\\$ \\$[\\$arcsec\\$]\\$'\",\n", + " label=\"1 '(a)' at graph 0.05,0.925\"\n", + " ), \n", + " handle = 2\n", + ")\n", + "Gaston.plot!(res_α_OR7, res_δ_OR7, \n", + " curveconf=\"w circles fill transparent solid 0.4 noborder tit 'non-grav.'\"\n", + ")\n", + "Gaston.plot!([mean(res_α_OR6)], [mean(res_δ_OR6)], curveconf=\"w p pt 4 ps 1.5 lw 8\") # tit 'mean R.A./Dec (OR6)'\n", + "Gaston.plot!([mean(res_α_OR7)], [mean(res_δ_OR7)], curveconf=\"w p pt 6 ps 1.5 lw 8\") # tit 'mean R.A./Dec (OR7)'\n", + "Gaston.plot!(ell_3σ_x_OR6, ell_3σ_y_OR6, curveconf=\"w l lw 8 lc 3\")\n", + "Gaston.plot!(ell_3σ_x_OR7, ell_3σ_y_OR7, curveconf=\"w l lw 8 lc 4\")\n", + "\n", + "p4 = Gaston.plot(\n", + " h_b.weights./2,\n", + " bc_b,\n", + " supp=[h_b.weights./2 bs_b./2],\n", + " curveconf=\"w boxxy notit fs transparent solid 0.4\",\n", + " Axes(\n", + " #linetype = :tab10,\n", + " axesconf=\"set lmargin at screen 0.85+$gap; set rmargin at screen 0.99; set tmargin at screen 0.8; set bmargin at screen 0.1\",\n", + " yrange = (ymin_plt, ymax_plt),\n", + " format = \"''\",\n", + " label=\"1 '(c)' at graph 0.15,0.925\"\n", + " ),\n", + " handle = 4\n", + ")\n", + "Gaston.plot!(\n", + " h_d.weights./2,\n", + " bc_d,\n", + " supp=[h_d.weights./2 bs_d./2],\n", + " curveconf=\"w boxxy notit fs transparent solid 0.4\"\n", + ")\n", + "\n", + "Gaston.plot([p1 nothing ; p2 p4])\n", + "\n", + "#Gaston.save(term = \"cairolatex\", output = \"radec_hist.tex\", saveopts = \"pdf standalone color dashed transparent size 7in,5in font ',12'\")\n", + "#run(`lualatex radec_hist.tex`)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plots: radar astrometry post-fit residuals" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "del_index = findall(x->x.Δτ_units==\"us\", deldop)\n", + "dop_index = findall(x->x.Δν_units==\"Hz\", deldop)\n", + "length(del_index), length(dop_index)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "length(deldop)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "del_dates_plot_ = date.(deldop[del_index])\n", + "dop_dates_plot_ = date.(deldop[dop_index])\n", + "\n", + "del_dates_plot = Dates.format.(del_dates_plot_, \"dd/mm/yy HHMM\")\n", + "dop_dates_plot = Dates.format.(dop_dates_plot_, \"dd/mm/yy HHMM\")\n", + "\n", + "σ_del_all = delay_sigma.(deldop[del_index])\n", + "σ_dop_all = doppler_sigma.(deldop[dop_index])\n", + ";" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p1 = Gaston.plot(\n", + " del_index,\n", + " res_τ(δx_OR6),\n", + " supp = σ_del_all,\n", + " key=\"box spacing 1.2 height 0.4\", #at screen 0.835, screen 0.78 \n", + " curveconf = \"u 1:2:3 w errorbars pt 6 lw 4 tit 'gravity-only'\",\n", + " Axes(\n", + " #axesconf=\"set lmargin at screen 0.15; set rmargin at screen 0.95; set bmargin at screen 0.5\",\n", + " axesconf=\"set lmargin at screen 0.11\",\n", + " #linetype = :tab10,\n", + " bars = 2,\n", + " ylabel = \"'Time-delay resid. \\$[\\$us\\$]\\$'\",\n", + " xrange = (0,39),\n", + " xtics = \"1,2,40\",\n", + " format = \"y '%1.1f'\",\n", + " yrange=(-7,8),\n", + " label=\"1 '(a)' at graph 0.05,0.9\"#,\n", + " #title = \"'gravity-only'\"\n", + " ),\n", + " handle = 1\n", + ")\n", + "Gaston.plot!(\n", + " del_index,\n", + " res_τ(δx_OR7),\n", + " supp = σ_del_all,\n", + " curveconf = \"u 1:2:3 w errorbars pt 4 lw 4 tit 'non-gravitational'\",\n", + " lc = 2\n", + ")\n", + "\n", + "p2 = Gaston.plot(\n", + " dop_index,\n", + " res_ν(δx_OR6),\n", + " supp = σ_dop_all,\n", + " curveconf = \"u 1:2:3 w errorbars pt 6 lw 4 tit 'gravity-only'\",\n", + " key=\"box spacing 1.2 height 0.4\",\n", + " Axes(\n", + " #axesconf=\"set lmargin at screen 0.15; set rmargin at screen 0.95; set tmargin at screen 0.5\",\n", + " axesconf=\"set lmargin at screen 0.11\",\n", + " #linetype = :tab10,\n", + " bars = 2,\n", + " ylabel = \"'Doppler shift resid. \\$[\\$Hz\\$]\\$'\",\n", + " xrange = (0,39),\n", + " xtics = \"1,2,40\",\n", + " format = \"y '%1.1f'\",\n", + " yrange=(-0.6,0.8),\n", + " label=\"1 '(b)' at graph 0.05,0.9\" #,\n", + " # title = \"'non-gravitational'\"\n", + " ),\n", + " handle = 2\n", + ")\n", + "Gaston.plot!(\n", + " dop_index,\n", + " res_ν(δx_OR7),\n", + " supp = σ_dop_all,\n", + " curveconf = \"u 1:2:3 w errorbars pt 4 lw 4 tit 'non-gravitational'\",\n", + " lc = 2\n", + ")\n", + "\n", + "\n", + "Gaston.plot([p1; p2])\n", + "\n", + "#Gaston.save(term = \"cairolatex\", output = \"deldop_residuals.tex\", saveopts = \"pdf standalone color dashed transparent size 10in,7in font ',14'\")\n", + "#run(`pdflatex deldop_residuals.tex`)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "deldop_dates_plot_xaxis = vcat(\"01/06/04 0000\", del_dates_plot, \"31/03/21 2359\");" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "tmargin_bmargin_gap = 0.03\n", + "bmargin_ths_plt = 0.5 + tmargin_bmargin_gap\n", + "tmargin_ths_plt = 0.965\n", + "axsbrk_v = 1.25*0.01\n", + "axsbrk_h = 1.25*0.005\n", + "lw_ths_plt = 3\n", + "rmargin_ths_plt = 0.3\n", + "\n", + "p1 = Gaston.plot(\n", + " del_dates_plot,\n", + " res_τ(δx_OR6),\n", + " supp = σ_del_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", + " Axes(\n", + " #linetype = :tab10,\n", + " axesconf = \"set rmargin at screen 0.3; set tmargin at screen $tmargin_ths_plt; set bmargin at screen $bmargin_ths_plt\",\n", + " xdata = \"time\",\n", + " timefmt = \"'%d/%m/%y %H%M'\",\n", + " xtics = false, #\"format '' time (\\\"01/01/05\\\",\\\"01/01/06\\\")\", # '%d/%b/%y'\n", + " xrange = \"[\\\"01/12/04\\\":\\\"30/05/06\\\"]\",\n", + " #xlabel = \"\\\"Date\\\"\",\n", + " bars = false, #2,\n", + " ylabel = \"'Time-delay resid. (O-C) [\\$\\\\mu\\$s]'\",\n", + " border = \"1+2+4\",\n", + " ytics = [\"nomirror\", \"format '%1.1f'\"],\n", + " yrange = \"[-8.0:6.0]\",\n", + " arrow = [\n", + " \"from screen 0.3-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.3+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.3-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.3+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\"\n", + " ],\n", + " label=\"1 '(a)' at graph 0.2,0.9\",\n", + " grid=false\n", + " #arrow = \"from screen 0.3-0.01,1.0-0.01 to screen 0.3+0.01,1.0+0.01 nohead\"\n", + " #format = \"x ''\"\n", + " #title = \"'Time-delay resid. (O-C)'\"\n", + " ),\n", + " handle = 1\n", + ")\n", + "Gaston.plot!(\n", + " del_dates_plot,\n", + " res_τ(δx_OR7),\n", + " supp = σ_del_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", + " lc = 2\n", + ")\n", + "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", + "\n", + "p2 = Gaston.plot(\n", + " del_dates_plot,\n", + " res_τ(δx_OR6),\n", + " supp = σ_del_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", + " Axes(\n", + " #linetype = :tab10,\n", + " xdata = \"time\",\n", + " timefmt = \"'%d/%m/%y %H%M'\",\n", + " axesconf = \"set lmargin at screen 0.35; set tmargin at screen $tmargin_ths_plt; set rmargin at screen 0.8; set bmargin at screen $bmargin_ths_plt\",\n", + " xtics = false, #\"format '' time (\\\"01/01/13\\\",\\\"01/02/13\\\",\\\"01/03/13\\\")\", # '%d/%b/%y'\n", + " xrange = \"[\\\"15/12/12\\\":\\\"20/03/13\\\"]\",\n", + " #xlabel = \"\\\"Date\\\"\",\n", + " bars = false, #2,\n", + " #tics=\"scale 0\",\n", + " ytics = false, #[false, \"(\\\"\\\" 0)\"], #\"nomirror\",\n", + " border = \"1+4\",\n", + " yrange = \"[-8.0:6.0]\",\n", + " format = [\"x ''\", \"y ''\"], #%1.1f\n", + " arrow = [\n", + " \"from screen 0.35-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.35+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.35-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.35+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.80-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.80+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.80-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.80+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\"\n", + " ],\n", + " #ylabel = \"'[us]'\"\n", + " ),\n", + " handle = 2\n", + ")\n", + "Gaston.plot!(\n", + " del_dates_plot,\n", + " res_τ(δx_OR7),\n", + " supp = σ_del_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", + " lc = 2\n", + ")\n", + "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", + "\n", + "p3 = Gaston.plot(\n", + " del_dates_plot,\n", + " res_τ(δx_OR6),\n", + " supp = σ_del_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", + " Axes(\n", + " #linetype = :tab10,\n", + " xdata = \"time\",\n", + " timefmt = \"'%d/%m/%y %H%M'\",\n", + " axesconf = \"set lmargin at screen 0.85; set tmargin at screen 0.965; set bmargin at screen $bmargin_ths_plt\",\n", + " xtics = false, #\"format '' time (\\\"03/03/21\\\",\\\"11/03/21\\\")\", #'%d/%b/%y'\n", + " xrange = \"[\\\"02/03/21\\\":\\\"15/03/21\\\"]\",\n", + " #xlabel = \"\\\"Date\\\"\",\n", + " bars = false, #2,\n", + " #tics=\"scale 0\",\n", + " ytics = false, #[false, \"(\\\"\\\" 0)\"], #\"nomirror\",\n", + " border = \"1+4+8\",\n", + " yrange = \"[-8.0:6.0]\",\n", + " format = [\"x ''\", \"y ''\"], #%1.1f\n", + " arrow = [\n", + " \"from screen 0.85-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.85+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.85-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.85+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\"\n", + " ],\n", + " #ylabel = \"'[us]'\"\n", + " ),\n", + " handle = 3\n", + ")\n", + "Gaston.plot!(\n", + " del_dates_plot,\n", + " res_τ(δx_OR7),\n", + " supp = σ_del_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", + " lc = 2\n", + ")\n", + "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", + "\n", + "Gaston.plot([p1 p2 p3])\n", + "\n", + "#Gaston.save(term = \"cairolatex\", output = \"del_resids.tex\", saveopts = \"pdf standalone color dashed transparent size 10in,7in font ',14'\")\n", + "#run(`pdflatex del_resids.tex`)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "jupyter": { + "source_hidden": true + } + }, + "outputs": [], + "source": [ + "tmargin_ths_plt = 0.5 - tmargin_bmargin_gap\n", + "bmargin_ths_plt = 0.05\n", + "\n", + "Gaston.set(preamble=\"unset grid\")\n", + "p4 = Gaston.plot(\n", + " dop_dates_plot,\n", + " res_ν(δx_OR6),\n", + " supp = σ_dop_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", + " Axes(\n", + " #linetype = :tab10,\n", + " axesconf=\"set rmargin at screen $rmargin_ths_plt; set tmargin at screen $tmargin_ths_plt; set bmargin at screen $bmargin_ths_plt\",\n", + " xdata = \"time\",\n", + " timefmt = \"'%d/%m/%y %H%M'\",\n", + " xtics = \"format '%d/%b/%y' time (\\\"01/01/05\\\",\\\"01/01/06\\\")\",\n", + " xrange = \"[\\\"01/12/04\\\":\\\"30/05/06\\\"]\",\n", + " #xlabel = \"\\\"Date\\\"\",\n", + " bars = false,#2,\n", + " ylabel = \"'Doppler shift resid. (O-C) [Hz]'\",\n", + " border=\"1+2+4\",\n", + " ytics = [\"nomirror\", \"format '%1.1f'\"],\n", + " yrange=\"[-0.5:0.5]\",\n", + " arrow = [\n", + " \"from screen 0.3-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.3+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.3-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.3+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\"\n", + " ],\n", + " label=\"1 '(b)' at graph 0.2,0.9\"\n", + " #title = \"'Doppler shift resid. (O-C)'\"\n", + " ),\n", + " handle = 4\n", + ")\n", + "Gaston.plot!(\n", + " dop_dates_plot,\n", + " res_ν(δx_OR7),\n", + " supp = σ_dop_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", + " lc = 2\n", + ")\n", + "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", + "\n", + "p5 = Gaston.plot(\n", + " dop_dates_plot,\n", + " res_ν(δx_OR6),\n", + " supp = σ_dop_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", + " Axes(\n", + " #linetype = :tab10,\n", + " xdata = \"time\",\n", + " timefmt = \"'%d/%m/%y %H%M'\",\n", + " axesconf=\"set lmargin at screen $rmargin_ths_plt+0.05; set rmargin at screen 0.8; set tmargin at screen $tmargin_ths_plt; set bmargin at screen $bmargin_ths_plt\",\n", + " xtics=\"format '%d/%b/%y' time (\\\"01/01/13\\\",\\\"01/02/13\\\",\\\"01/03/13\\\")\",\n", + " xrange=\"[\\\"15/12/12\\\":\\\"20/03/13\\\"]\",\n", + " #xlabel = \"\\\"Date\\\"\",\n", + " bars = false, #2,\n", + " ytics=false,\n", + " border=\"1+4\",\n", + " yrange=\"[-0.5:0.5]\",\n", + " arrow = [\n", + " \"from screen 0.35-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.35+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.35-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.35+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.8-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.8+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.8-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.8+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\"\n", + " ],\n", + " #ylabel = \"'[Hz]'\"\n", + " ),\n", + " handle = 5\n", + ")\n", + "Gaston.plot!(\n", + " dop_dates_plot,\n", + " res_ν(δx_OR7),\n", + " supp = σ_dop_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", + " lc = 2\n", + ")\n", + "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", + "\n", + "p6 = Gaston.plot(\n", + " dop_dates_plot,\n", + " res_ν(δx_OR6),\n", + " supp = σ_dop_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", + " Axes(\n", + " #linetype = :tab10,\n", + " xdata = \"time\",\n", + " timefmt = \"'%d/%m/%y %H%M'\",\n", + " axesconf=\"set lmargin at screen 0.85; set tmargin at screen $tmargin_ths_plt; set bmargin at screen $bmargin_ths_plt\",\n", + " xtics=\"format '%d/%b/%y' time (\\\"03/03/21\\\",\\\"13/03/21\\\")\",\n", + " xrange=\"[\\\"02/03/21\\\":\\\"15/03/21\\\"]\",\n", + " #xlabel = \"\\\"Date\\\"\",\n", + " bars = false, #2,\n", + " #format=\"y ''\",\n", + " ytics=false,\n", + " border=\"1+4+8\",\n", + " yrange=\"[-0.5:0.5]\",\n", + " arrow = [\n", + " \"from screen 0.85-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.85+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.85-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.85+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\"\n", + " ],\n", + " #ylabel = \"'[Hz]'\"\n", + " ),\n", + " handle = 6\n", + ")\n", + "Gaston.plot!(\n", + " dop_dates_plot,\n", + " res_ν(δx_OR7),\n", + " supp = σ_dop_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", + " lc = 2\n", + ")\n", + "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", + "\n", + "Gaston.plot([p4 p5 p6])\n", + "\n", + "#Gaston.save(term = \"cairolatex\", output = \"dop_resids.tex\", saveopts = \"pdf standalone color dashed transparent size 10in,7in font ',14'\")\n", + "#run(`pdflatex dop_resids.tex`)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Gaston.plot([p1 p2 p3; p4 p5 p6])\n", + "\n", + "#Gaston.save(term = \"cairolatex\", output = \"deldop_residuals_dates.tex\", saveopts = \"pdf standalone color dashed transparent size 10in,7in font ',14'\")\n", + "#run(`lualatex deldop_residuals_dates.tex`)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Julia-4-threads 1.9.1", + "language": "julia", + "name": "julia-4-threads-1.9" + }, + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/notebooks/B-plane-jt-o5v7.ipynb b/notebooks/B-plane-jt-o5v7.ipynb old mode 100644 new mode 100755 diff --git a/notebooks/Plots-paper.ipynb b/notebooks/Plots-paper.ipynb old mode 100644 new mode 100755 diff --git a/notebooks/gnuplot.cfg b/notebooks/gnuplot.cfg old mode 100644 new mode 100755 diff --git a/pha/.DS_Store b/pha/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ec740ebd5536b6621b1631b3707134d3820b1c7f GIT binary patch literal 6148 zcmeHK%}T>S5dKDcDC(g{FTy@S!8Zt{9=r*@fTjvsQX|^lbN69FGk(n^_ zO?GE?vma!42Y@VgH>bc1z?7;e>Wqjsk9O@v@IFy&j62-p8FQ@Bj12S_oAlccaE(W_ z)GyzE-n6T_X>0Z?Ij_|Dn+ZK7q{b~C`0RYW{dhSU#2?`TPn=`TtQEG*+460JW{~$X z$kVw}l7VC(8At|_fuCf6XST}p&@pW?kPIXPpA6{!P^gMkVCQIC2aS~g#0i^C=<9V^ zb4p+p*g3L?BA!b0REZKpJe}<&;;O*T(bFMOd`QgvQM`!F&hd+dLn_C#$v`sDXFzLT z%1qDyGyXE8MZSfkNd}UE|H^<&mY2%~R~KjNw{_}STc}r56^-lEq0sML0{Ei)$gy>L be^H-tRbc0+qiDOO6Z0ZqgrrFZeu05^L^(DD literal 0 HcmV?d00001 diff --git a/pha/Project.toml b/pha/Project.toml old mode 100644 new mode 100755 index ad9456c0..804d696e --- a/pha/Project.toml +++ b/pha/Project.toml @@ -1,19 +1,19 @@ -[deps] - -ArgParse = "c7e460c6-2fb9-53a9-8c5b-16f535851c63" -DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" -Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" -DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" -Gaston = "4b11ee91-296f-5714-9832-002c20994614" -JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" -LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" -NEOs = "b41c07a2-2abb-11e9-070a-c3c1b239e7df" -Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" -PlanetaryEphemeris = "d83715d0-7e5f-11e9-1a59-4137b20d8363" -Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" -StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" -TaylorIntegration = "92b13dbe-c966-51a2-8445-caca9f8a7d42" - -[compat] - +[deps] + +ArgParse = "c7e460c6-2fb9-53a9-8c5b-16f535851c63" +DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" +Gaston = "4b11ee91-296f-5714-9832-002c20994614" +JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +NEOs = "b41c07a2-2abb-11e9-070a-c3c1b239e7df" +Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +PlanetaryEphemeris = "d83715d0-7e5f-11e9-1a59-4137b20d8363" +Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" +TaylorIntegration = "92b13dbe-c966-51a2-8445-caca9f8a7d42" + +[compat] + NEOs = "0.7" \ No newline at end of file diff --git a/pha/apophis.jl b/pha/apophis.jl old mode 100644 new mode 100755 index e7442acb..ae504421 --- a/pha/apophis.jl +++ b/pha/apophis.jl @@ -1,316 +1,349 @@ -# This file is part of the NEOs.jl package; MIT licensed - -### This script can be run either as a standalone script or via ArgParse. In any case, -### this folder's Project.toml environment has to be already active and instantiated -### before running this script. Uncomment the following three lines to activate and -### instantiate this folder's environment: - -# import Pkg -# Pkg.activate(".") -# Pkg.instantiate() - -### If ran as a standalone and the environment defined in this folder's Project.toml is -### already active and instantiated, then this script can be run from this folder with the -### default settings simply as: -### $ julia -t --project=. apophis.jl -### Finally, this script can be run via the ArgParse mechanism. Help can be displayed doing: -### $ julia --project=. apophis.jl --help - -using ArgParse -using NEOs -using Dates -using TaylorIntegration -using JLD2 -using PlanetaryEphemeris -using DataFrames -using DelimitedFiles -using LinearAlgebra: diag -using Statistics -using StatsBase - -# Load JPL ephemeris -loadjpleph() - -function parse_commandline() - s = ArgParseSettings() - - # Program name (for usage & help screen) - s.prog = "apophis.jl" - # Desciption (for help screen) - s.description = "Propagates Apophis orbit via jet transport" - - @add_arg_table! s begin - "--jd0" - help = "Initial date" - arg_type = DateTime - default = DateTime(2020, 12, 17) - "--varorder" - help = "Order of the jet transport perturbation" - arg_type = Int - default = 5 - "--maxsteps" - help = "Maximum number of steps during integration" - arg_type = Int - default = 10_000 - "--nyears_bwd" - help = "Years in backward integration" - arg_type = Float64 - default = -17.0 - "--nyears_fwd" - help = "Years in forward integration" - arg_type = Float64 - default = 9.0 - "--order" - help = "Order of Taylor polynomials expansions during integration" - arg_type = Int - default = 25 - "--abstol" - help = "Absolute tolerance" - arg_type = Float64 - default = 1.0E-20 - "--parse_eqs" - help = "Whether to use the taylorized method of jetcoeffs or not" - arg_type = Bool - default = true - end - - s.epilog = """ - Examples (run from the `pha` folder):\n - \n - # Multi-threaded\n - julia -t 4 --project=. apophis.jl --maxsteps 100 --nyears_bwd -0.02 --nyears_fwd 0.02 --parse_eqs true\n - \n - # Single-threaded\n - julia --project=. apophis.jl --maxsteps 100 --nyears_bwd -0.02 --nyears_fwd 0.02 --parse_eqs true\n - \n - """ - - return parse_args(s) -end - -function print_header(header::String, level::Int = 1) - L = length(header) - if level == 1 - c = "=" - else - c = "-" - end - println(repeat(c, L)) - println(header) - println(repeat(c, L)) -end - -function main(dynamics::D, maxsteps::Int, jd0_datetime::DateTime, nyears_bwd::T, nyears_fwd::T, order::Int, varorder::Int, - abstol::T, parse_eqs::Bool) where {T <: Real, D} - - # Initial conditions from Apophis JPL solution #197 - q00 = kmsec2auday(apophisposvel197(datetime2et(jd0_datetime))) - - # Perturbation to nominal initial condition (Taylor1 jet transport) - # vcat(fill(1e-8, 6), 1e-14, 1e-15) are the scaling factors for jet transport perturbation, - # these are needed to ensure expansion coefficients remain small. - # The magnitudes correspond to the typical order of magnitude of errors in - # position/velocity (1e-8), Yarkovsky (1e-14) and radiation pressure (1e-15) - scalings = vcat(fill(1e-8, 6), 1e-14, 1e-15) - if varorder == 0 - dq = zeros(8) - else - dq = NEOs.scaled_variables("δx", scalings, order = varorder) - end - - q0 = vcat(q00, 0.0, 0.0) .+ dq - - # Initial date (in Julian days) - jd0 = datetime2julian(jd0_datetime) - - print_header("Integrator warmup", 2) - _ = NEOs.propagate(dynamics, 1, jd0, nyears_fwd, q0, Val(true); - order = order, abstol = abstol, parse_eqs = parse_eqs) - println() - - print_header("Main integration", 2) - tmax = nyears_bwd*yr - println("• Initial time of integration: ", string(jd0_datetime)) - println("• Final time of integration: ", julian2datetime(jd0 + tmax)) - - sol_bwd = NEOs.propagate(dynamics, maxsteps, jd0, nyears_bwd, q0, Val(true); - order, abstol, parse_eqs) - jldsave("Apophis_bwd.jld2"; sol_bwd) - # sol_bwd = JLD2.load("Apophis_bwd.jld2", "asteph") - - tmax = nyears_fwd*yr - println("• Initial time of integration: ", string(jd0_datetime)) - println("• Final time of integration: ", julian2datetime(jd0 + tmax)) - - sol_fwd = NEOs.propagate(dynamics, maxsteps, jd0, nyears_fwd, q0, Val(true); - order, abstol, parse_eqs) - jldsave("Apophis_fwd.jld2"; sol_fwd) - # sol_fwd = JLD2.load("Apophis_fwd.jld2", "asteph") - println() - - # load Solar System ephemeris - sseph::TaylorInterpolant{Float64,Float64,2} = loadpeeph(NEOs.sseph, sol_bwd.t0+sol_bwd.t[end], sol_fwd.t0+sol_fwd.t[end]) - eph_su::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, su) - eph_ea::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, ea) - - # NEO - # Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec - xva_bwd(et) = auday2kmsec(sol_bwd(et/daysec)[1:6]) - xva_fwd(et) = auday2kmsec(sol_fwd(et/daysec)[1:6]) - xva(et) = bwdfwdeph(et, sol_bwd, sol_fwd) - # Earth - # Change x, v units, resp., from au, au/day to km, km/sec - xve(et) = auday2kmsec(eph_ea(et/daysec)) - # Sun - # Change x, v units, resp., from au, au/day to km, km/sec - xvs(et) = auday2kmsec(eph_su(et/daysec)) - - - radec_2004_2020 = read_radec_mpc(joinpath(pkgdir(NEOs), "data", "99942_2004_2020.dat")) - radec_2020_2021 = read_radec_mpc(joinpath(pkgdir(NEOs), "data", "99942_2020_2021.dat")) - radec = vcat(radec_2004_2020,radec_2020_2021) - - deldop_2005_2013 = read_radar_jpl(joinpath(pkgdir(NEOs), "data", "99942_RADAR_2005_2013.dat")) - deldop_2021 = read_radar_jpl(joinpath(pkgdir(NEOs), "data", "99942_RADAR_2021.dat")) - deldop = vcat(deldop_2005_2013,deldop_2021) - - # Compute optical residuals - res_radec_all, w_radec_all = NEOs.residuals(radec; xvs, xve, xva) - jldsave("Apophis_res_w_radec.jld2"; res_radec_all, w_radec_all) - # JLD2.@load "Apophis_res_w_radec.jld2" - - # Compute radar residuals - res_del, w_del, res_dop, w_dop = NEOs.residuals(deldop; xvs, xve, xva, niter=10, tord=10) - jldsave("Apophis_res_w_radec.jld2"; res_del, w_del, res_dop, w_dop) - # JLD2.@load "Apophis_res_w_deldop.jld2" - - ### Process optical astrometry (filter, weight, debias) - - # filter out biased observations from observatory 217 on 28-Jan-2021 - df_radec = DataFrame(radec) - # add residuals and weights to optical astrometry DataFrame - df_radec[!, :res_α] .= res_radec_all[1:round(Int,length(res_radec_all)/2)] - df_radec[!, :res_δ] .= res_radec_all[1+round(Int,length(res_radec_all)/2):end] - df_radec[!, :w_α] .= w_radec_all[1:round(Int,length(res_radec_all)/2)] - df_radec[!, :w_δ] .= w_radec_all[1+round(Int,length(res_radec_all)/2):end] - filter!( - x->(Date(x.date) != Date(2021, 1, 28)), - df_radec - ) - - # read astrometric errors from Tholen et al. (2013) - tho13_errors = readdlm(joinpath(pkgdir(NEOs), "data", "tholenetal2013_opterror.dat"), ',') - # compute weights - w_α_tho13 = 1 ./ (tho13_errors[:,1].^2 .+ tho13_errors[:,3].^2 .+ tho13_errors[:,5].^2) - w_δ_tho13 = 1 ./ (tho13_errors[:,2].^2 .+ tho13_errors[:,4].^2 .+ tho13_errors[:,6].^2) - # Tholen et al. (2013) obs table - radec_tho13 = DataFrame(read_radec_mpc(joinpath(pkgdir(NEOs), "test", "data", "99942_Tholen_etal_2013.dat"))) - # vector of RA values from Tholen et al. (2013) observations (used for filtering) - tho13_α = radec_tho13[!,:α] - # set weights in Tholen et al. (2013) astrometry corresponding to associated uncertainties - df_radec[in.(df_radec.α, Ref(tho13_α)),:w_α] = w_α_tho13 - df_radec[in.(df_radec.α, Ref(tho13_α)),:w_δ] = w_δ_tho13 - - # Relaxation factor (account for correlations in optical astrometry data) - # for each observation batch, count the number of observations made in - # the same night by the same observatory - # Ref: Veres et al. (2017) - date_site_v = select(df_radec, :date => ByRow(Date), :observatory) - Nv = [count(x->x.date_Date==i.date_Date && x.observatory==i.observatory, eachrow(date_site_v)) for i in eachrow(date_site_v)] - relax_factor = map(x->x>4.0 ? x/4.0 : 1.0, Nv) - # inflate uncertainties (i.e., relax weights) by relaxation factor - df_radec[!, :w_α] .= (df_radec.w_α)./relax_factor - df_radec[!, :w_δ] .= (df_radec.w_δ)./relax_factor - - # update optical residuals and weights - res_radec = vcat(df_radec.res_α, df_radec.res_δ) - w_radec = vcat(df_radec.w_α, df_radec.w_δ) - - ### Perform orbital fit to optical and radar astrometry data - - res = vcat(res_radec, res_del, res_dop) - w = vcat(w_radec, w_del, w_dop) - - fit_OR8 = newtonls(res, w, zeros(get_numvars()), 10) - x_OR8 = sol_fwd(sol_fwd.t0)(fit_OR8.x) - σ_OR8 = sqrt.(diag(fit_OR8.Γ)).*scalings - - nradec = length(res_radec) - res_ra = view(res_radec, 1:nradec÷2) - res_dec = view(res_radec, 1+nradec÷2:nradec) - w_ra = view(w_radec, 1:nradec÷2) - w_dec = view(w_radec, 1+nradec÷2:nradec) - - ### Print results - - print_header("Orbital fit (8-DOF) and post-fit statistics", 2) - - # orbital fit - println("Success flag : ", fit_OR8.success, "\n") - println("Nominal solution [au,au,au,au/d,au/d,au/d,au/d²,au/d²]: ", x_OR8, "\n") - println("1-sigma formal uncertainties [au,au,au,au/d,au/d,au/d,au/d²,au/d²]: ", σ_OR8, "\n") - - # post-fit statistics - println("Normalized RMS (optical-only) [adimensional] : ", nrms(res_radec(fit_OR8.x),w_radec)) - println("Normalized RMS (radar-only) [adimensional] : ", nrms(vcat(res_del,res_dop)(fit_OR8.x),vcat(w_del,w_dop))) - println("Normalized RMS (combined optical and radar) [adimensional] : ", nrms(res(fit_OR8.x),w), "\n") - println("Mean weighted right-ascension residual [arcseconds] : ", mean(res_ra(fit_OR8.x), weights(w_ra))) - println("Mean weighted declination residual [arcseconds] : ", mean(res_dec(fit_OR8.x), weights(w_dec))) - println("Mean weighted time-delay residual [micro-seconds]: ", mean(res_del(fit_OR8.x), weights(w_del))) - println("Mean weighted Doppler-shift residual [Hz] : ", mean(res_dop(fit_OR8.x), weights(w_dop)), "\n") - println("Chi-squared statistic (χ²): [adimensional] : ", chi2(res(fit_OR8.x),w)) - - return sol_bwd, sol_fwd, res_radec, res_del, res_dop, w_radec, w_del, w_dop -end - -function main() - - # Parse arguments from commandline - parsed_args = parse_commandline() - - print_header("Asteroid Apophis") - println() - print_header("General parameters", 2) - - # Number of threads - N_threads = Threads.nthreads() - println("• Number of threads: ", N_threads) - - # Dynamical function - dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! - - println("• Dynamical function: ", dynamics) - - # Maximum number of steps - maxsteps = parsed_args["maxsteps"] - println("• Maximum number of steps: ", maxsteps) - - # Initial date - jd0_datetime = parsed_args["jd0"] - - # Number of years in backward integration - nyears_bwd = parsed_args["nyears_bwd"] - - # Number of years in forward integration - nyears_fwd = parsed_args["nyears_fwd"] - - # Order of Taylor polynomials - order = parsed_args["order"] - println("• Order of Taylor polynomials: ", order) - - # Order of jet transport perturbation - varorder = parsed_args["varorder"] - println("• Order of jet transport perturbation: ", varorder) - - # Absolute tolerance - abstol = parsed_args["abstol"] - println("• Absolute tolerance: ", abstol) - - # Whether to use @taylorize or not - parse_eqs = parsed_args["parse_eqs"] - println("• Use @taylorize: ", parse_eqs, "\n") - - main(dynamics, maxsteps, jd0_datetime, nyears_bwd, nyears_fwd, order, varorder, abstol, parse_eqs) -end - -main() +# This file is part of the NEOs.jl package; MIT licensed + +### This script can be run either as a standalone script or via ArgParse. In any case, +### this folder's Project.toml environment has to be already active and instantiated +### before running this script. Uncomment the following three lines to activate and +### instantiate this folder's environment: + +# import Pkg +# Pkg.activate(".") +# Pkg.instantiate() + +### If ran as a standalone and the environment defined in this folder's Project.toml is +### already active and instantiated, then this script can be run from this folder with the +### default settings simply as: +### $ julia -t --project=. apophis.jl +### Finally, this script can be run via the ArgParse mechanism. Help can be displayed doing: +### $ julia --project=. apophis.jl --help + +using ArgParse +using NEOs +using Dates +using TaylorIntegration +using JLD2 +using PlanetaryEphemeris +using DataFrames +using DelimitedFiles +using LinearAlgebra: diag +using Statistics +using StatsBase + +# Load JPL ephemeris +loadjpleph() + +function parse_commandline() + s = ArgParseSettings() + + # Program name (for usage & help screen) + s.prog = "apophis.jl" + # Desciption (for help screen) + s.description = "Propagates Apophis orbit via jet transport" + + @add_arg_table! s begin + "--jd0" + help = "Initial date" + arg_type = DateTime + default = DateTime(2020, 12, 17) + "--varorder" + help = "Order of the jet transport perturbation" + arg_type = Int + default = 5 + "--maxsteps" + help = "Maximum number of steps during integration" + arg_type = Int + default = 10_000 + "--nyears_bwd" + help = "Years in backward integration" + arg_type = Float64 + default = -17.0 + "--nyears_fwd" + help = "Years in forward integration" + arg_type = Float64 + default = 9.0 + "--order" + help = "Order of Taylor polynomials expansions during integration" + arg_type = Int + default = 25 + "--abstol" + help = "Absolute tolerance" + arg_type = Float64 + default = 1.0E-20 + "--parse_eqs" + help = "Whether to use the taylorized method of jetcoeffs or not" + arg_type = Bool + default = true + end + + s.epilog = """ + Examples (run from the `pha` folder):\n + \n + # Multi-threaded\n + julia -t 4 --project=. apophis.jl --maxsteps 100 --nyears_bwd -0.02 --nyears_fwd 0.02 --parse_eqs true\n + \n + # Single-threaded\n + julia --project=. apophis.jl --maxsteps 100 --nyears_bwd -0.02 --nyears_fwd 0.02 --parse_eqs true\n + \n + """ + + return parse_args(s) +end + +function print_header(header::String, level::Int = 1) + L = length(header) + if level == 1 + c = "=" + else + c = "-" + end + println(repeat(c, L)) + println(header) + println(repeat(c, L)) +end + +function main(dynamics::D, maxsteps::Int, jd0_datetime::DateTime, nyears_bwd::T, nyears_fwd::T, order::Int, varorder::Int, + abstol::T, parse_eqs::Bool) where {T <: Real, D} + + # Initial conditions from Apophis JPL solution #197 + q00 = kmsec2auday(apophisposvel197(datetime2et(jd0_datetime))) + + # Perturbation to nominal initial condition (Taylor1 jet transport) + # vcat(fill(1e-8, 6), 1e-14, 1e-15) are the scaling factors for jet transport perturbation, + # these are needed to ensure expansion coefficients remain small. + # The magnitudes correspond to the typical order of magnitude of errors in + # position/velocity (1e-8), Yarkovsky (1e-14) and radiation pressure (1e-15) + scalings = vcat(fill(1e-8, 6), 1e-14, 1e-15) + if varorder == 0 + dq = zeros(8) + else + dq = NEOs.scaled_variables("δx", scalings, order = varorder) + end + + q0 = vcat(q00, 0.0, 0.0) .+ dq + + # Initial date (in Julian days) + jd0 = datetime2julian(jd0_datetime) + + print_header("Integrator warmup", 2) + _ = NEOs.propagate(dynamics, 1, jd0, nyears_fwd, q0, Val(true); + order = order, abstol = abstol, parse_eqs = parse_eqs) + println() + + print_header("Main integration", 2) + tmax = nyears_bwd*yr + println("• Initial time of integration: ", string(jd0_datetime)) + println("• Final time of integration: ", julian2datetime(jd0 + tmax)) + + sol_bwd = NEOs.propagate(dynamics, maxsteps, jd0, nyears_bwd, q0, Val(true); + order, abstol, parse_eqs) + jldsave("Apophis_bwd.jld2"; sol_bwd) + # sol_bwd = JLD2.load("Apophis_bwd.jld2", "asteph") + + tmax = nyears_fwd*yr + println("• Initial time of integration: ", string(jd0_datetime)) + println("• Final time of integration: ", julian2datetime(jd0 + tmax)) + + sol_fwd = NEOs.propagate(dynamics, maxsteps, jd0, nyears_fwd, q0, Val(true); + order, abstol, parse_eqs) + jldsave("Apophis_fwd.jld2"; sol_fwd) + # sol_fwd = JLD2.load("Apophis_fwd.jld2", "asteph") + println() + + # load Solar System ephemeris + sseph::TaylorInterpolant{Float64,Float64,2} = loadpeeph(NEOs.sseph, sol_bwd.t0+sol_bwd.t[end], sol_fwd.t0+sol_fwd.t[end]) + eph_su::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, su) + eph_ea::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, ea) + + # NEO + # Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec + xva_bwd(et) = auday2kmsec(sol_bwd(et/daysec)[1:6]) + xva_fwd(et) = auday2kmsec(sol_fwd(et/daysec)[1:6]) + xva(et) = bwdfwdeph(et, sol_bwd, sol_fwd) + # Earth + # Change x, v units, resp., from au, au/day to km, km/sec + xve(et) = auday2kmsec(eph_ea(et/daysec)) + # Sun + # Change x, v units, resp., from au, au/day to km, km/sec + xvs(et) = auday2kmsec(eph_su(et/daysec)) + + + radec_2004_2020 = read_radec_mpc(joinpath(pkgdir(NEOs), "data", "99942_2004_2020.dat")) + radec_2020_2021 = read_radec_mpc(joinpath(pkgdir(NEOs), "data", "99942_2020_2021.dat")) + radec = vcat(radec_2004_2020,radec_2020_2021) + + deldop_2005_2013 = read_radar_jpl(joinpath(pkgdir(NEOs), "data", "99942_RADAR_2005_2013.dat")) + deldop_2021 = read_radar_jpl(joinpath(pkgdir(NEOs), "data", "99942_RADAR_2021.dat")) + deldop = vcat(deldop_2005_2013,deldop_2021) + + # Compute optical residuals + res_radec_all, w_radec_all = NEOs.residuals(radec; xvs, xve, xva) + jldsave("Apophis_res_w_radec.jld2"; res_radec_all, w_radec_all) + # JLD2.@load "Apophis_res_w_radec.jld2" + + # Compute radar residuals + res_del, w_del, res_dop, w_dop = NEOs.residuals(deldop; xvs, xve, xva, niter=10, tord=10) + jldsave("Apophis_res_w_radec.jld2"; res_del, w_del, res_dop, w_dop) + # JLD2.@load "Apophis_res_w_deldop.jld2" + + ### Process optical astrometry (filter, weight, debias) + + # filter out biased observations from observatory 217 on 28-Jan-2021 + df_radec = DataFrame(radec) + # add residuals and weights to optical astrometry DataFrame + df_radec[!, :res_α] .= res_radec_all[1:round(Int,length(res_radec_all)/2)] + df_radec[!, :res_δ] .= res_radec_all[1+round(Int,length(res_radec_all)/2):end] + df_radec[!, :w_α] .= w_radec_all[1:round(Int,length(res_radec_all)/2)] + df_radec[!, :w_δ] .= w_radec_all[1+round(Int,length(res_radec_all)/2):end] + filter!( + x->(Date(x.date) != Date(2021, 1, 28)), + df_radec + ) + + # read astrometric errors from Tholen et al. (2013) + tho13_errors = readdlm(joinpath(pkgdir(NEOs), "data", "tholenetal2013_opterror.dat"), ',') + # compute weights + w_α_tho13 = 1 ./ (tho13_errors[:,1].^2 .+ tho13_errors[:,3].^2 .+ tho13_errors[:,5].^2) + w_δ_tho13 = 1 ./ (tho13_errors[:,2].^2 .+ tho13_errors[:,4].^2 .+ tho13_errors[:,6].^2) + # Tholen et al. (2013) obs table + radec_tho13 = DataFrame(read_radec_mpc(joinpath(pkgdir(NEOs), "test", "data", "99942_Tholen_etal_2013.dat"))) + # vector of RA values from Tholen et al. (2013) observations (used for filtering) + tho13_α = radec_tho13[!,:α] + # set weights in Tholen et al. (2013) astrometry corresponding to associated uncertainties + df_radec[in.(df_radec.α, Ref(tho13_α)),:w_α] = w_α_tho13 + df_radec[in.(df_radec.α, Ref(tho13_α)),:w_δ] = w_δ_tho13 + + # Relaxation factor (account for correlations in optical astrometry data) + # for each observation batch, count the number of observations made in + # the same night by the same observatory + # Ref: Veres et al. (2017) + date_site_v = select(df_radec, :date => ByRow(Date), :observatory) + Nv = [count(x->x.date_Date==i.date_Date && x.observatory==i.observatory, eachrow(date_site_v)) for i in eachrow(date_site_v)] + relax_factor = map(x->x>4.0 ? x/4.0 : 1.0, Nv) + # inflate uncertainties (i.e., relax weights) by relaxation factor + df_radec[!, :w_α] .= (df_radec.w_α)./relax_factor + df_radec[!, :w_δ] .= (df_radec.w_δ)./relax_factor + + # update optical residuals and weights + res_radec = vcat(df_radec.res_α, df_radec.res_δ) + w_radec = vcat(df_radec.w_α, df_radec.w_δ) + + ### Perform orbital fit to optical and radar astrometry data + + res = vcat(res_radec, res_del, res_dop) + w = vcat(w_radec, w_del, w_dop) + + fit_OR8 = newtonls(res, w, zeros(get_numvars()), 10) + x_OR8 = sol_fwd(sol_fwd.t0)(fit_OR8.x) + σ_OR8 = sqrt.(diag(fit_OR8.Γ)).*scalings + + nradec = length(res_radec) + res_ra = view(res_radec, 1:nradec÷2) + res_dec = view(res_radec, 1+nradec÷2:nradec) + w_ra = view(w_radec, 1:nradec÷2) + w_dec = view(w_radec, 1+nradec÷2:nradec) + + ### Print results + + print_header("Orbital fit (8-DOF) and post-fit statistics", 2) + + # orbital fit + println("Success flag : ", fit_OR8.success, "\n") + println("Nominal solution [au,au,au,au/d,au/d,au/d,au/d²,au/d²]: ", x_OR8, "\n") + println("1-sigma formal uncertainties [au,au,au,au/d,au/d,au/d,au/d²,au/d²]: ", σ_OR8, "\n") + + # post-fit statistics + println("Normalized RMS (optical-only) [adimensional] : ", nrms(res_radec(fit_OR8.x),w_radec)) + println("Normalized RMS (radar-only) [adimensional] : ", nrms(vcat(res_del,res_dop)(fit_OR8.x),vcat(w_del,w_dop))) + println("Normalized RMS (combined optical and radar) [adimensional] : ", nrms(res(fit_OR8.x),w), "\n") + println("Mean weighted right-ascension residual [arcseconds] : ", mean(res_ra(fit_OR8.x), weights(w_ra))) + println("Mean weighted declination residual [arcseconds] : ", mean(res_dec(fit_OR8.x), weights(w_dec))) + println("Mean weighted time-delay residual [micro-seconds]: ", mean(res_del(fit_OR8.x), weights(w_del))) + println("Mean weighted Doppler-shift residual [Hz] : ", mean(res_dop(fit_OR8.x), weights(w_dop)), "\n") + println("Chi-squared statistic (χ²): [adimensional] : ", chi2(res(fit_OR8.x),w)) + + return sol_bwd, sol_fwd, res_radec, res_del, res_dop, w_radec, w_del, w_dop +end + +function main() + + # Parse arguments from commandline + parsed_args = parse_commandline() + + print_header("Asteroid Apophis") + println() + print_header("General parameters", 2) + + # Number of threads + N_threads = Threads.nthreads() + println("• Number of threads: ", N_threads) + + # Dynamical function + dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! + + println("• Dynamical function: ", dynamics) + + # Maximum number of steps + maxsteps = parsed_args["maxsteps"] + println("• Maximum number of steps: ", maxsteps) + + # Initial date + jd0_datetime = parsed_args["jd0"] + + # Number of years in backward integration + nyears_bwd = parsed_args["nyears_bwd"] + + # Number of years in forward integration + nyears_fwd = parsed_args["nyears_fwd"] + + # Order of Taylor polynomials + order = parsed_args["order"] + println("• Order of Taylor polynomials: ", order) + + # Order of jet transport perturbation + varorder = parsed_args["varorder"] + println("• Order of jet transport perturbation: ", varorder) + + # Absolute tolerance + abstol = parsed_args["abstol"] + println("• Absolute tolerance: ", abstol) + + # Whether to use @taylorize or not + parse_eqs = parsed_args["parse_eqs"] + println("• Use @taylorize: ", parse_eqs, "\n") + + main(dynamics, maxsteps, jd0_datetime, nyears_bwd, nyears_fwd, order, varorder, abstol, parse_eqs) +end + +main() + +#= +-0.18034827489412805 +0.9406910783153754 +0.3457360118643932 +-0.016265940057745887 +4.3915296805381036e-5 +-0.0003952032399008921 +-2.883842658925719e-14 +-1.6977850502837174e-11 + + +6.991681792970175e-9 +3.3210758500485412e-9 +8.763895947794195e-9 +5.485729074188412e-11 +9.846074910774499e-11 +1.3782767177665416e-10 +2.525644870489942e-16 +3.2193289354129716e-12 + +Normalized RMS (optical-only) [adimensional] : 0.4365429773707507 +Normalized RMS (radar-only) [adimensional] : 0.5421268387032326 +Normalized RMS (combined optical and radar) [adimensional] : 0.43685679642513925 + +Mean weighted right-ascension residual [arcseconds] : -0.002787272519210798 +Mean weighted declination residual [arcseconds] : -0.003376099885054764 +Mean weighted time-delay residual [micro-seconds]: -0.0007329351962194035 +Mean weighted Doppler-shift residual [Hz] : -0.03025601266756564 + +Chi-squared statistic (χ²): [adimensional] : 3597.4067719864497 + +=# \ No newline at end of file diff --git a/pha/bennu.jl b/pha/bennu.jl old mode 100644 new mode 100755 diff --git a/scripts/distributed.jl b/scripts/distributed.jl old mode 100644 new mode 100755 index da6ac270..88cb8640 --- a/scripts/distributed.jl +++ b/scripts/distributed.jl @@ -1,53 +1,53 @@ -###julia --machine-file distributed.jl -###julia -p distributed.jl - -# using Distributed # not necessary when doing `julia -p ...` or `julia --machine-file...` -@everywhere begin - import Pkg - Pkg.activate("../") - # Pkg.instantiate() -end -@everywhere begin - using Apophis - using Dates - using TaylorSeries - - #script parameters (TODO: use ArgParse.jl instead) - const objname = "Apophis" - const maxsteps = 10000 - const nyears = 5.0 - const dense = true#false - const apophisjlpath = pkgdir(Apophis) - const radarobsfile = joinpath(apophisjlpath, "Apophis_JPL_data_2012_2013.dat") - const dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! - const t0 = datetime2julian(DateTime(2008,9,24,0,0,0)) #starting time of integration - const tmax = t0+365.25nyears #final time of integration - @show t0 == 2454733.5 - @show tmax - - function earth_et(et) - return ss16asteph( Apophis.etsecs2julian(et) )[union(3*4-2:3*4,3*(27+4)-2:3*(27+4))] - end - function sun_et(et) - return ss16asteph( Apophis.etsecs2julian(et) )[union(3*1-2:3*1,3*(27+1)-2:3*(27+1))] - end -end - -# path to local Solar System ephemeris file -# ss_eph_file = joinpath(pkgdir(Apophis), "jldeph", "ss16ast343_eph_24yr_tx.jld") -ss_eph_file = joinpath(pkgdir(Apophis), "jldeph", "ss16ast343_eph_5yr_tx.jld") - -ss16asteph, acc_eph, newtonianNb_Potential = Apophis.loadeph(ss_eph_file) - -aux = (ss16asteph, acc_eph, newtonianNb_Potential, earth_et, sun_et) -for i in 1:nworkers() - @spawnat i+1 aux = (ss16asteph, acc_eph, newtonianNb_Potential, earth_et, sun_et) -end - -#warmup (compilation) short run on all processes -parallel_run(objname, dynamics, 1, t0, tmax, aux, output=false) -println("*** Finished warmup") - -#Full jet transport integration until ~2038: about 8,000 steps -# parallel_run(objname, dynamics, maxsteps, t0, tmax, aux, radarobsfile=radarobsfile) -# println("*** Finished full jet transport integration") +###julia --machine-file distributed.jl +###julia -p distributed.jl + +# using Distributed # not necessary when doing `julia -p ...` or `julia --machine-file...` +@everywhere begin + import Pkg + Pkg.activate("../") + # Pkg.instantiate() +end +@everywhere begin + using Apophis + using Dates + using TaylorSeries + + #script parameters (TODO: use ArgParse.jl instead) + const objname = "Apophis" + const maxsteps = 10000 + const nyears = 5.0 + const dense = true#false + const apophisjlpath = pkgdir(Apophis) + const radarobsfile = joinpath(apophisjlpath, "Apophis_JPL_data_2012_2013.dat") + const dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! + const t0 = datetime2julian(DateTime(2008,9,24,0,0,0)) #starting time of integration + const tmax = t0+365.25nyears #final time of integration + @show t0 == 2454733.5 + @show tmax + + function earth_et(et) + return ss16asteph( Apophis.etsecs2julian(et) )[union(3*4-2:3*4,3*(27+4)-2:3*(27+4))] + end + function sun_et(et) + return ss16asteph( Apophis.etsecs2julian(et) )[union(3*1-2:3*1,3*(27+1)-2:3*(27+1))] + end +end + +# path to local Solar System ephemeris file +# ss_eph_file = joinpath(pkgdir(Apophis), "jldeph", "ss16ast343_eph_24yr_tx.jld") +ss_eph_file = joinpath(pkgdir(Apophis), "jldeph", "ss16ast343_eph_5yr_tx.jld") + +ss16asteph, acc_eph, newtonianNb_Potential = Apophis.loadeph(ss_eph_file) + +aux = (ss16asteph, acc_eph, newtonianNb_Potential, earth_et, sun_et) +for i in 1:nworkers() + @spawnat i+1 aux = (ss16asteph, acc_eph, newtonianNb_Potential, earth_et, sun_et) +end + +#warmup (compilation) short run on all processes +parallel_run(objname, dynamics, 1, t0, tmax, aux, output=false) +println("*** Finished warmup") + +#Full jet transport integration until ~2038: about 8,000 steps +# parallel_run(objname, dynamics, maxsteps, t0, tmax, aux, radarobsfile=radarobsfile) +# println("*** Finished full jet transport integration") diff --git a/scripts/main.jl b/scripts/main.jl old mode 100644 new mode 100755 index 8d518ca4..ed497d1a --- a/scripts/main.jl +++ b/scripts/main.jl @@ -1,62 +1,62 @@ -#Multi-threaded: -#julia -t --project=@. main.jl -#Single thread: -#julia --project=@. main.jl -using NEOs -using Dates -using TaylorIntegration -using JLD2 -using SPICE: furnsh -@show Threads.nthreads() - -#script parameters (TODO: use ArgParse.jl instead) -const varorder = 5 # 1 # varorder is the order corresponding to the jet transport perturbation -const nv = 7 #number of TaylorN variables -const objname = "Apophis" -const maxsteps = 10000 -const nyears = 6.0 #-5.0 #21.0 -const dense = false #true -const quadmath = false # use quadruple precision -const debias_table = "2018" # "2014", "hires2018" -const apophisjlpath = pkgdir(NEOs) -const dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! -const jd0 = datetime2julian(DateTime(2008,9,24,0,0,0)) #Julian date of integration initial time -@show jd0 == 2454733.5 -const t0 = 0.0 # integration initial time - -#### observation data files (ra/dec, del/dop) -const opticalobsfile = "" -const radarobsfile = "" -#const opticalobsfile = joinpath(apophisjlpath, "data", "tholen13_mpc_formatted.dat") -#const radarobsfile = joinpath(apophisjlpath, "data", "Apophis_JPL_data_2005_2006.dat") -#const opticalobsfile = joinpath(apophisjlpath, "data", "vokr15_mpc_formatted.dat") -#const radarobsfile = joinpath(apophisjlpath, "data", "Apophis_JPL_data_2012_2013.dat") - -# path to local Solar System ephemeris file -#ss_eph_file = joinpath(apophisjlpath, "jldeph", "ss16ast343_eph_m5y_et.jld") -ss_eph_file = joinpath(apophisjlpath, "jldeph", "ss16ast343_eph_p6y_et.jld") - -#### dq: perturbation to nominal initial condition (Taylor1 jet transport) -#dq = Taylor1.(zeros(7), varorder) -#dq[end][1] = 1e-14 - -#### dq: perturbation to nominal initial condition (TaylorN jet transport) -dq = set_variables("δx", order=varorder, numvars=nv) -for i in 1:6 - dq[i][1][i] = 1e-8 -end -if get_numvars() == 7 - dq[7][1][7] = 1e-14 -end - -####integrator warmup -propagate(objname, dynamics, 1, t0, nyears, ss_eph_file, output=false, dense=dense, dq=dq, quadmath=quadmath) -println("*** Finished warmup") - -#propagate(objname, dynamics, 300 #=5=#, t0, nyears, ss_eph_file, dense=dense, dq=dq, quadmath=quadmath) -#println("*** Finished 5 steps") - -######Full jet transport integration until ~2038: about 8,000 steps -###propagate(objname, dynamics, maxsteps, t0, nyears, ss_eph_file, dense=dense, dq=dq) # no obs ephemeris computation -propagate(objname, dynamics, maxsteps, t0, nyears, ss_eph_file, dense=dense, dq=dq, quadmath=quadmath, radarobsfile=radarobsfile, opticalobsfile=opticalobsfile, debias_table=debias_table) -println("*** Finished full jet transport integration") +#Multi-threaded: +#julia -t --project=@. main.jl +#Single thread: +#julia --project=@. main.jl +using NEOs +using Dates +using TaylorIntegration +using JLD2 +using SPICE: furnsh +@show Threads.nthreads() + +#script parameters (TODO: use ArgParse.jl instead) +const varorder = 5 # 1 # varorder is the order corresponding to the jet transport perturbation +const nv = 7 #number of TaylorN variables +const objname = "Apophis" +const maxsteps = 10000 +const nyears = 6.0 #-5.0 #21.0 +const dense = false #true +const quadmath = false # use quadruple precision +const debias_table = "2018" # "2014", "hires2018" +const apophisjlpath = pkgdir(NEOs) +const dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! +const jd0 = datetime2julian(DateTime(2008,9,24,0,0,0)) #Julian date of integration initial time +@show jd0 == 2454733.5 +const t0 = 0.0 # integration initial time + +#### observation data files (ra/dec, del/dop) +const opticalobsfile = "" +const radarobsfile = "" +#const opticalobsfile = joinpath(apophisjlpath, "data", "tholen13_mpc_formatted.dat") +#const radarobsfile = joinpath(apophisjlpath, "data", "Apophis_JPL_data_2005_2006.dat") +#const opticalobsfile = joinpath(apophisjlpath, "data", "vokr15_mpc_formatted.dat") +#const radarobsfile = joinpath(apophisjlpath, "data", "Apophis_JPL_data_2012_2013.dat") + +# path to local Solar System ephemeris file +#ss_eph_file = joinpath(apophisjlpath, "jldeph", "ss16ast343_eph_m5y_et.jld") +ss_eph_file = joinpath(apophisjlpath, "jldeph", "ss16ast343_eph_p6y_et.jld") + +#### dq: perturbation to nominal initial condition (Taylor1 jet transport) +#dq = Taylor1.(zeros(7), varorder) +#dq[end][1] = 1e-14 + +#### dq: perturbation to nominal initial condition (TaylorN jet transport) +dq = set_variables("δx", order=varorder, numvars=nv) +for i in 1:6 + dq[i][1][i] = 1e-8 +end +if get_numvars() == 7 + dq[7][1][7] = 1e-14 +end + +####integrator warmup +propagate(objname, dynamics, 1, t0, nyears, ss_eph_file, output=false, dense=dense, dq=dq, quadmath=quadmath) +println("*** Finished warmup") + +#propagate(objname, dynamics, 300 #=5=#, t0, nyears, ss_eph_file, dense=dense, dq=dq, quadmath=quadmath) +#println("*** Finished 5 steps") + +######Full jet transport integration until ~2038: about 8,000 steps +###propagate(objname, dynamics, maxsteps, t0, nyears, ss_eph_file, dense=dense, dq=dq) # no obs ephemeris computation +propagate(objname, dynamics, maxsteps, t0, nyears, ss_eph_file, dense=dense, dq=dq, quadmath=quadmath, radarobsfile=radarobsfile, opticalobsfile=opticalobsfile, debias_table=debias_table) +println("*** Finished full jet transport integration") diff --git a/scripts/main.lsf b/scripts/main.lsf old mode 100644 new mode 100755 diff --git a/scripts/setup.jl b/scripts/setup.jl old mode 100644 new mode 100755 diff --git a/scripts/setup.lsf b/scripts/setup.lsf old mode 100644 new mode 100755 diff --git a/src/NEOs.jl b/src/NEOs.jl old mode 100644 new mode 100755 index f9dee90d..083265a7 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -1,77 +1,81 @@ -module NEOs - -# __precompile__(false) - -import Base: hash, ==, show, isless, isnan, convert, zero, iszero, string -import PlanetaryEphemeris as PE -import JLD2: writeas -import Tables: istable, rowaccess, rows, schema, Schema -import SatelliteToolboxTransformations.sv_ecef_to_eci -import SatelliteToolboxTransformations.sv_ecef_to_ecef -import Downloads - -using Distributed, JLD2, TaylorIntegration, Printf, DelimitedFiles, Test, LinearAlgebra, - Dates, SPICE, Quadmath, LazyArtifacts, TaylorSeries, JSON, - InteractiveUtils, AutoHashEquals, Scratch -using PlanetaryEphemeris: daysec, su, ea, α_p_sun, δ_p_sun, t2c_jpl_de430, pole_rotation, - au, c_au_per_day, R_sun, c_cm_per_sec, c_au_per_sec, yr, RE, TaylorInterpolant, Rx, - Ry, Rz, semimajoraxis, eccentricity, inclination, longascnode, argperi, timeperipass, - nbodyind, ordpres_differentiate, numberofbodies, kmsec2auday, auday2kmsec, meanmotion, - meananomaly, selecteph -using Healpix: ang2pixRing, Resolution -using SatelliteToolboxTransformations -using Dates: format -using Downloads: download -using DataFrames: AbstractDataFrame, GroupedDataFrame, DataFrame, nrow, eachcol, eachrow, groupby, combine -using HTTP: get -using IntervalRootFinding: roots, interval, Interval, mid -using Interpolations: Flat, Gridded, Linear, interpolate, extrapolate -using StatsBase: mean, std -using Clustering: kmeans - -# Constants -export d_EM_km, d_EM_au -# CatalogueMPC -export unknowncat, isunknown, read_catalogues_mpc, write_catalogues_mpc, update_catalogues_mpc, - search_cat_code -# ObservatoryMPC -export unknownobs, hascoord, read_observatories_mpc, write_observatories_mpc, update_observatories_mpc, search_obs_code, - issatellite -# RadecMPC -export num, tmpdesig, discovery, publishnote, obstech, ra, dec, info1, mag, band, catalogue, info2, observatory, - read_radec_mpc, search_circulars_mpc, write_radec_mpc, get_radec_mpc -# RadarJPL -export hasdelay, hasdoppler, ismonostatic, date, delay, delay_sigma, delay_units, doppler, doppler_sigma, - doppler_units, freq, rcvr, xmit, bouncepoint, read_radar_jpl, write_radar_jpl -# Units -export julian2etsecs, etsecs2julian, datetime2et, et_to_200X, days_to_200X, datetime_to_200X, - datetime2days, days2datetime, rad2arcsec, arcsec2rad, mas2rad -# JPL Ephemerides -export loadjpleph, sunposvel, earthposvel, moonposvel, apophisposvel197, apophisposvel199, - loadpeeph, bwdfwdeph -# Osculating -export pv2kep, yarkp2adot -# Topocentric -export obsposECEF, obsposvelECI -# Process radec -export compute_radec, select_debiasing_table, debiasing, w8sveres17, residuals, unfold, relax_factor, outlier -# Process radar -export compute_delay, radar_astrometry -# Gauss method -export gauss_method, gaussinitcond -# Asteroid dynamical models -export RNp1BP_pN_A_J23E_J2S_ng_eph_threads!, RNp1BP_pN_A_J23E_J2S_eph_threads! -# Propagate -export propagate, propagate_lyap, propagate_root -# Post processing -export valsecchi_circle, nrms, chi2, newtonls, newtonls_6v, diffcorr, newtonls_Q, bopik, tryls, project, - orbitdetermination, outlier_rejection, residual_rejection - -include("constants.jl") -include("observations/process_radar.jl") -include("orbit_determination/gauss_method.jl") -include("propagation/propagation.jl") -include("postprocessing/neosolution.jl") -include("init.jl") - +module NEOs + +# __precompile__(false) + +import Base: show, string, hash, isequal, ==, isless, convert, zero, iszero, isnan, in +import Tables: istable, rowaccess, rows, schema, Schema +import SatelliteToolboxTransformations: sv_ecef_to_eci, sv_ecef_to_ecef +import JLD2: writeas +import PlanetaryEphemeris as PE + +import Downloads + +using AutoHashEquals, Dates, Printf, JSON, SatelliteToolboxTransformations, TaylorSeries, + TaylorIntegration, SPICE, JLD2, LazyArtifacts, LinearAlgebra, LinearAlgebra, + DelimitedFiles, Scratch, Quadmath, Test, InteractiveUtils, Distributed +using HTTP: get +using DataFrames: DataFrame, nrow, eachcol, eachrow, groupby, combine, AbstractDataFrame, + DataFrameRow, GroupedDataFrame +using PlanetaryEphemeris: daysec, yr, TaylorInterpolant, auday2kmsec, su, ea, au, + c_au_per_day, α_p_sun, δ_p_sun, pole_rotation, c_cm_per_sec, c_au_per_sec, + t2c_jpl_de430, R_sun, RE, Rx, Ry, Rz, semimajoraxis, eccentricity, inclination, + longascnode, argperi, timeperipass, nbodyind, numberofbodies, kmsec2auday, + meanmotion, meananomaly, selecteph +using Healpix: ang2pixRing, Resolution +using StatsBase: mean, std +using GLM: @formula, lm, coef +using Roots: find_zeros +using Clustering: kmeans + +using Downloads: download + +# Constants +export d_EM_km, d_EM_au +# CatalogueMPC +export unknowncat, read_catalogues_mpc, write_catalogues_mpc, update_catalogues_mpc, + search_cat_code +# ObservatoryMPC +export unknownobs, hascoord, read_observatories_mpc, write_observatories_mpc, + update_observatories_mpc, search_obs_code +# RadecMPC +export ra, dec, date, observatory, read_radec_mpc, write_radec_mpc, get_radec_mpc +# RadarJPL +export hasdelay, hasdoppler, delay, doppler, rcvr, xmit, read_radar_jpl, write_radar_jpl +# Units +export julian2etsecs, etsecs2julian, datetime2et, et_to_200X, days_to_200X, datetime_to_200X, + datetime2days, days2datetime, rad2arcsec, arcsec2rad, mas2rad +# JPL Ephemerides +export loadjpleph, sunposvel, earthposvel, moonposvel, apophisposvel197, apophisposvel199, + loadpeeph, bwdfwdeph +# Topocentric +export obsposECEF, obsposvelECI +# Process radec +export compute_radec, select_debiasing_table, debiasing, w8sveres17, residuals, unfold, + relax_factor, outlier +# Process radar +export compute_delay, radar_astrometry +# Asteroid dynamical models +export RNp1BP_pN_A_J23E_J2S_ng_eph_threads!, RNp1BP_pN_A_J23E_J2S_eph_threads! +# Propagate +export Parameters, propagate, propagate_lyap, propagate_root +# B plane +export valsecchi_circle, bopik +# Least squares +export outlier_rejection, project, chi2, nms, nrms, diffcorr, newtonls, tryls +# Osculating +export pv2kep, yarkp2adot +# Too Short Arc +export tooshortarc +# Gauss method +export gauss_method, gaussinitcond, gauss_refinement +# Orbit determination +export orbitdetermination + +include("constants.jl") +include("observations/process_radar.jl") +include("propagation/propagation.jl") +include("postprocessing/neosolution.jl") +include("orbit_determination/orbit_determination.jl") +include("init.jl") + end \ No newline at end of file diff --git a/src/constants.jl b/src/constants.jl old mode 100644 new mode 100755 index 07ebb23c..df14e463 --- a/src/constants.jl +++ b/src/constants.jl @@ -1,71 +1,203 @@ -# Internal paths - -# Path to NEOs src directory -const src_path = dirname(pathof(NEOs)) -# Path to scratch space -const scratch_path = Ref{String}("") - -# URLs - -# MPC database search url -const search_mpc_url = "https://www.minorplanetcenter.net/db_search/show_object?utf8=%E2%9C%93&object_id=" -# MPC observations url -const obs_mpc_url = "https://www.minorplanetcenter.net/tmp/" - -# Abbreviations -const cte = constant_term - -# Integration parameters -const order = 30 -const abstol = 1.0E-30 - -# Vector of GM's (DE430 values) [au^2 / day^3] -const μ_DE430 = PE.μ -const μ_B16_DE430 = μ_DE430[12:27] # DE430 GM's of 16 most massive asteroids -const μ_ast343_DE430 = μ_DE430[12:end] # DE430 GM's of 343 main belt asteroids included in DE430 integration -# Gravitational parameter of the Sun [au^2 / day^3] -const μ_S = PE.GMS - -# Standard value of nominal mean angular velocity of Earth (rad/sec) -# See Explanatory Supplement to the Astronomical Almanac 2014 Sec 7.4.3.3 p. 296 -const ω = 7.2921151467e-5 # 7.292115e-5 rad/sec - -# Solar corona parameters -# See Table 8.5 in page 329 of Explanatory Supplement to the Astronomical Almanac 2014 -const A_sun = 1.06e8 # [cm^-3] -const a_sun = 4.89e5 # [cm^-3] -const b_sun = 3.91e5 # [cm^-3] - -# Sun radiated power intensity at photosphere surface, Watt/meter^2 -const S0_sun = 63.15E6 -# Conversion factor from m^2/sec^3 to au^2/day^3 -const m2_s3_to_au2_day3 = 1e-6daysec^3/au^2 - -# Vector of J_2*R^2 values -# J_2: second zonal harmonic coefficient -# R: radius of the body -const Λ2 = zeros(11) -Λ2[ea] = 1.9679542578489185e-12 # Earth -# Vector of J_3*R^3 values -# J_3: third zonal harmonic coefficient -# R: radius of the body -const Λ3 = zeros(11) -Λ3[ea] = -1.962633335678878e-19 # Earth - -# Speed of light -const clightkms = 2.99792458E5 # km/sec -# Parameters related to speed of light, c -const c_p2 = 29979.063823897606 # c^2 = 29979.063823897606 au^2/d^2 -const c_m2 = 3.3356611996764786e-5 # c^-2 = 3.3356611996764786e-5 d^2/au^2 - -# Earth-Moon distance in [km] -const d_EM_km = 384_400 -# Earth-Moon distance in [au] -const d_EM_au = 384_400 / au - -# Zeroth order obliquity of the ecliptic in degrees -# See equation (5-153) in page 5-61 of https://doi.org/10.1002/0471728470. -const ϵ0_deg = 84381.448/3_600 - -# Gauss gravitational constant -const k_gauss = 0.017_202_098_95 \ No newline at end of file +# Internal paths + +# Path to NEOs src directory +const src_path = dirname(pathof(NEOs)) +# Path to scratch space +const scratch_path = Ref{String}("") + +# Load Solar System, accelerations, newtonian potentials and TT-TDB 2000-2100 ephemeris +const sseph_artifact_path = joinpath(artifact"sseph_p100", "sseph343ast016_p100y_et.jld2") +const sseph::TaylorInterpolant{Float64, Float64, 2} = JLD2.load(sseph_artifact_path, "ss16ast_eph") +const acceph::TaylorInterpolant{Float64, Float64, 2} = JLD2.load(sseph_artifact_path, "acc_eph") +const poteph::TaylorInterpolant{Float64, Float64, 2} = JLD2.load(sseph_artifact_path, "pot_eph") +const ttmtdb::TaylorInterpolant{Float64, Float64, 1} = TaylorInterpolant(sseph.t0, sseph.t, sseph.x[:,end]) + +# Earth orientation parameters (eop) 2000 +const eop_IAU2000A::EopIau2000A = fetch_iers_eop(Val(:IAU2000A)) + +# Parsing + +# Regular expression to parse a catalogue in MPC format +const CATALOGUE_MPC_REGEX = r"\s{2}(?P\w{1})\s{4}(?P.*)" +# Header of MPC catalogues file +const CATALOGUES_MPC_HEADER = "Char Catalogue" +# Regular expression to parse an observatory in MPC format +const OBSERVATORY_MPC_REGEX = Regex(string( + # Code regex + space (columns 1-3) + raw"(?P[A-Z\d]{3})", + # Longitude regex (columns 4-13) + raw"(?P[\.\d\s]{10})", + # Cosine regex + space (column 14-21) + raw"(?P[\.\d\s]{8})", + # Sine regex (column 22-30) + raw"(?P[\+\-\.\d\s]{9})", + # Name regex (columns 31-80) + raw"(?P.*)", +)) +# Header of MPC observatories file +const OBSERVATORIES_MPC_HEADER = "Code Long. cos sin Name" +# Regular expression to parse an optical measurement in MPC format +const RADEC_MPC_REGEX = Regex(string( + # Number regex (columns 1-5) + raw"(?P.{5})", + # Temporary designation regex (columns 6-12) + raw"(?P.{7})", + # Discovery asterisk regex (column 13) + raw"(?P[\*\s]{1})", + # Publishable note regex (column 14) + raw"(?P.{1})", + # Observation technique regex (column 15) + raw"(?P[^xX]{1})", + # Date of observation regex (columns 16-32) + raw"(?P\d{4}\s\d{2}\s\d{2}\.[\d\s]{6})", + # Right ascension regex (columns 33-44) + raw"(?P<α>\d{2}\s\d{2}\s\d{2}\.[\d\s]{3})", + # Declination regex (columns 45-56) + raw"(?P<δ>[\+|\-]{1}\d{2}\s\d{2}\s\d{2}\.[\d\s]{2})", + # Info 1 regex (columns 57-65) + raw"(?P.{9})", + # Magnitude regex (columns 66-70) + raw"(?P[\.\s\d]{5})", + # Band regex (column 71) + raw"(?P[\w\s]{1})", + # Catalogue regex (column 72) + raw"(?P[\w\s]{1})", + # Info 2 regex (columns 73-77) + raw"(?P.{5})", + # Observatory code regex (columns 78-80) + raw"(?P\w{3})", + # Optional fields (in case of satellite observations) + # Breakline regex + raw"(?:\n)?", + # Number regex (columns 1-5) + raw"(?(?P<_num_>.{5})?", + # Temporary designation regex (columns 6-12) + raw"(?P<_tmpdesig_>.{7})?", + # Blank space regex (column 13) + raw"(?P<_discovery_>\s)?", + # Publishable note regex (column 14) + raw"(?P<_publishnote_>.{1})?", + # s regex (column 15) + raw"(?P<_obstech_>s)?", + # Date of observation regex (columns 16-32) + raw"(?P<_date_>\d{4}\s\d{2}\s\d{2}\.[\d\s]{6})", + # Units + space regex (columns 33-34) + raw"(?P<_units_>\d\s)", + # X component of geocentric vector (columns 35-46) + raw"(?P<_x_>[\-\+]{1}[\.\d\s]{11})", + # Y component of geocentric vector (columns 47-58) + raw"(?P<_y_>[\-\+]{1}[\.\d\s]{11})", + # Z component of geocentric vector (columns 59-70) + raw"(?P<_z_>[\-\+]{1}[\.\d\s]{11})", + # Band regex (column 71) + raw"(?P<_band_>[\w\s]{1})?", + # Catalogue regex (column 72) + raw"(?P<_catalogue_>[\w\s]{1})?", + # Info 2 regex (columns 73-77) + raw"(?P<_info2_>.{5})?", + # Observatory code regex (columns 78-80) + raw"(?P<_obscode_>\w{3})?)?", +)) +# Regular expression to parse a radar measurement in JPL format +const RADAR_JPL_REGEX = Regex(string( + # ID regex + tab + raw"(?P.*)\t", + # Date regex + tab + raw"(?P.*)\t", + # Measurement regex + tab + raw"(?P.*)\t", + # Uncertainty regex + tab + raw"(?P.*)\t", + # Units regex + tab + raw"(?P.*)\t", + # Frequency regex + tab + raw"(?P.*)\t", + # Reciever regex + tab + raw"(?P.*)\t", + # Emitter regex + tab + raw"(?P.*)\t", + # Bouncepoint regex + end of line + raw"(?P.*)" +)) +# Format of date in JPL radar data files +const RADAR_JPL_DATEFORMAT = "yyyy-mm-dd HH:MM:SS" + +# MPC catalogues corresponding to debiasing tables included in https://doi.org/10.1016/j.icarus.2014.07.033 +const mpc_catalogue_codes_2014 = ["a", "b", "c", "d", "e", "g", "i", "j", "l", "m", "o", "p", "q", "r", + "u", "v", "w", "L", "N"] + +# MPC catalogues corresponding to debiasing tables included in https://doi.org/10.1016/j.icarus.2019.113596 +const mpc_catalogue_codes_2018 = ["a", "b", "c", "d", "e", "g", "i", "j", "l", "m", "n", "o", "p", "q", + "r", "t", "u", "v", "w", "L", "N", "Q", "R", "S", "U", "W"] + +# URLs + +# MPC catalogues file url +const CATALOGUES_MPC_URL = "https://minorplanetcenter.net/iau/info/CatalogueCodes.html" +# MPC observatories file url +const OBSERVATORIES_MPC_URL = "https://minorplanetcenter.net/iau/lists/ObsCodes.html" + +# MPC database search url +const search_mpc_url = "https://www.minorplanetcenter.net/db_search/show_object?utf8=%E2%9C%93&object_id=" +# MPC observations url +const obs_mpc_url = "https://www.minorplanetcenter.net/tmp/" + +# Abbreviations +const cte = constant_term + +# Integration parameters +const order = 30 +const abstol = 1.0E-30 + +# Vector of GM's (DE430 values) [au^2 / day^3] +const μ_DE430 = PE.μ +const μ_B16_DE430 = μ_DE430[12:27] # DE430 GM's of 16 most massive asteroids +const μ_ast343_DE430 = μ_DE430[12:end] # DE430 GM's of 343 main belt asteroids included in DE430 integration +# Gravitational parameter of the Sun [au^2 / day^3] +const μ_S = PE.GMS + +# Standard value of nominal mean angular velocity of Earth (rad/sec) +# See Explanatory Supplement to the Astronomical Almanac 2014 Sec 7.4.3.3 p. 296 +const ω = 7.2921151467e-5 # 7.292115e-5 rad/sec + +# Solar corona parameters +# See Table 8.5 in page 329 of Explanatory Supplement to the Astronomical Almanac 2014 +const A_sun = 1.06e8 # [cm^-3] +const a_sun = 4.89e5 # [cm^-3] +const b_sun = 3.91e5 # [cm^-3] + +# Sun radiated power intensity at photosphere surface, Watt/meter^2 +const S0_sun = 63.15E6 +# Conversion factor from m^2/sec^3 to au^2/day^3 +const m2_s3_to_au2_day3 = 1e-6daysec^3/au^2 + +# Vector of J_2*R^2 values +# J_2: second zonal harmonic coefficient +# R: radius of the body +const Λ2 = zeros(11) +Λ2[ea] = 1.9679542578489185e-12 # Earth +# Vector of J_3*R^3 values +# J_3: third zonal harmonic coefficient +# R: radius of the body +const Λ3 = zeros(11) +Λ3[ea] = -1.962633335678878e-19 # Earth + +# Speed of light +const clightkms = 2.99792458E5 # km/sec +# Parameters related to speed of light, c +const c_p2 = 29979.063823897606 # c^2 = 29979.063823897606 au^2/d^2 +const c_m2 = 3.3356611996764786e-5 # c^-2 = 3.3356611996764786e-5 d^2/au^2 + +# Earth-Moon distance in [km] +const d_EM_km = 384_400 +# Earth-Moon distance in [au] +const d_EM_au = 384_400 / au + +# Zeroth order obliquity of the ecliptic in degrees +# See equation (5-153) in page 5-61 of https://doi.org/10.1002/0471728470. +const ϵ0_deg = 84381.448/3_600 + +# Gauss gravitational constant +const k_gauss = 0.017_202_098_95 +# Earth's sphere of influence radius [AU] +const R_SI = 0.010044 diff --git a/src/init.jl b/src/init.jl old mode 100644 new mode 100755 index 6bfb3053..8f3e57e9 --- a/src/init.jl +++ b/src/init.jl @@ -1,18 +1,23 @@ -function __init__() - # Initialize scratch space - global scratch_path[] = @get_scratch!("NEOsScratch") - # Load catalogues - CatalogueCodes_path = joinpath(scratch_path[], "CatalogueCodes.txt") - if isfile(CatalogueCodes_path) - global CATALOGUES_MPC[] = read_catalogues_mpc(CatalogueCodes_path) - else - update_catalogues_mpc() - end - # Load observatories - ObsCodes_path = joinpath(scratch_path[], "ObsCodes.txt") - if isfile(ObsCodes_path) - global OBSERVATORIES_MPC[] = read_observatories_mpc(ObsCodes_path) - else - update_observatories_mpc() - end +# List of MPC catalogues +const CATALOGUES_MPC = Ref{Vector{CatalogueMPC}}([unknowncat()]) +# List of MPC observatories +const OBSERVATORIES_MPC = Ref{Vector{ObservatoryMPC{Float64}}}([unknownobs()]) + +function __init__() + # Initialize scratch space + global scratch_path[] = @get_scratch!("NEOsScratch") + # Load catalogues + CatalogueCodes_path = joinpath(scratch_path[], "CatalogueCodes.txt") + if isfile(CatalogueCodes_path) + global CATALOGUES_MPC[] = read_catalogues_mpc(CatalogueCodes_path) + else + update_catalogues_mpc() + end + # Load observatories + ObsCodes_path = joinpath(scratch_path[], "ObsCodes.txt") + if isfile(ObsCodes_path) + global OBSERVATORIES_MPC[] = read_observatories_mpc(ObsCodes_path) + else + update_observatories_mpc() + end end \ No newline at end of file diff --git a/src/observations/catalogue_mpc.jl b/src/observations/catalogue_mpc.jl old mode 100644 new mode 100755 index 73bf2bf7..1e5a43b7 --- a/src/observations/catalogue_mpc.jl +++ b/src/observations/catalogue_mpc.jl @@ -1,194 +1,188 @@ -@doc raw""" - CatalogueMPC - -An astrometric reference catalogue in MPC format. The format is described in https://minorplanetcenter.net/iau/info/CatalogueCodes.html. - -# Fields - -- `code::String`: catalogue's identifier. -- `name::String`: catalogue's name. -""" -@auto_hash_equals struct CatalogueMPC - code::String - name::String - # Inner constructor - function CatalogueMPC(code::String, name::String) - return new(code, name) - end -end - -@doc raw""" - unknowncat() - -Return a `CatalogueMPC` with no code or name. -""" -function unknowncat() - return CatalogueMPC("", "") -end - -@doc raw""" - isunknown(m::CatalogueMPC) - -Check whether `m` equals `unknowncat()`. -""" -function isunknown(m::CatalogueMPC) - return m == unknowncat() -end - -# Print method for CatalogueMPC -# Examples: -# Unknown catalogue -# USNO-A1.0 [a] -function show(io::IO, m::CatalogueMPC) - if isunknown(m) - print(io, "Unknown catalogue") - else - print(io, m.name, " [", m.code, "]") - end -end - -neoparse(x::RegexMatch, i::Int, ::Type{String}) = String(strip(x[i])) - -# Regular expression to parse a catalogue in MPC format -const CATALOGUE_MPC_REGEX = r"\s{2}(?P\w{1})\s{4}(?P.*)" -# Header of MPC catalogues file -const CATALOGUES_MPC_HEADER = "Char Catalogue" - -@doc raw""" - CatalogueMPC(m::RegexMatch) - -Convert a match of `NEOs.CATALOGUE_MPC_REGEX` to `CatalogueMPC`. -""" -function CatalogueMPC(m::RegexMatch) - # Check that matched regex is correct - @assert m.regex == CATALOGUE_MPC_REGEX "Only matches of `NEOs.CATALOGUE_MPC_REGEX` can be converted to `CatalogueMPC`." - # Field types - types = fieldtypes(CatalogueMPC) - # CatalogueMPC fields - args = map(i -> neoparse(m, i, types[i]), 1:length(types)) - - return CatalogueMPC(args...) -end - -@doc raw""" - read_catalogues_mpc(s::String) - -Return the matches of `NEOs.CATALOGUE_MPC_REGEX` in `s` as `CatalogueMPC`. `s` can be either a filename or a text. -""" -function read_catalogues_mpc(s::String) - if !contains(s, "\n") && isfile(s) - # Read MPC formatted file - s = String(read(s)) - end - # Remove header - s = replace(s, CATALOGUES_MPC_HEADER => "") - # Vector of MPC catalogues - cats = Vector{CatalogueMPC}(undef, 0) - # Iterate over the matches - for m in eachmatch(CATALOGUE_MPC_REGEX, s) - push!(cats, CatalogueMPC(m)) - end - # Eliminate repeated entries - unique!(cats) - - return cats -end - -# Convert `cat` to a string according to MPC format. -function string(cat::CatalogueMPC) - if isunknown(cat) - return "" - else - # Code string - code_s = string(" ", cat.code, " ") - # Join everything - cat_s = string(code_s, cat.name) - - return cat_s - end -end - -@doc raw""" - write_catalogues_mpc(cats::Vector{CatalogueMPC}, filename::String) - -Write `cats` to `filename` in MPC format. -""" -function write_catalogues_mpc(cats::Vector{CatalogueMPC}, filename::String) - open(filename, "w") do file - # Header - write(file, CATALOGUES_MPC_HEADER, "\n") - # Write observatories - for i in eachindex(cats) - line = string(cats[i]) - write(file, line, "\n") - end - end -end - -# MPC catalogues file url -const CATALOGUES_MPC_URL = "https://minorplanetcenter.net/iau/info/CatalogueCodes.html" - -@doc raw""" - download_scratch(url::String, filename::String; connect_timeout=180, readtimeout=180) - -Download `url` and save the output to NEOs scratch space as `filename`. Return the local path and the contents of the file as a `String`. -""" -function download_scratch(url::String, filename::String; connect_timeout=180, readtimeout=180) - # Local file - path = joinpath(scratch_path[], filename) - # Get raw html (HTTP.get retries four times by default) - resp = get(url; connect_timeout, readtimeout) - # Read local file - txt = String(resp.body) - - return path, txt -end - -# List of MPC catalogues -const CATALOGUES_MPC = Ref{Vector{CatalogueMPC}}([unknowncat()]) - -@doc raw""" - update_catalogues_mpc() - -Update the local catalogues file. -""" -function update_catalogues_mpc() - # Download and read catalogues file - CatalogueCodes_path, txt = download_scratch(CATALOGUES_MPC_URL, "CatalogueCodes.txt") - # Parse catalogues - cats = read_catalogues_mpc(txt) - # Write catalogues to local file - write_catalogues_mpc(cats, CatalogueCodes_path) - # Update global variable - global CATALOGUES_MPC[] = read_catalogues_mpc(CatalogueCodes_path) - - return nothing -end - -@doc raw""" - search_cat_code(catcode::String) - -Return the catalogue in `NEOs.mpc_catalogues` that matches `catcode`. -""" -function search_cat_code(catcode::String) - - # Find indexes in mpc_catalogues that match catcode - idxs = findall(x -> x.code == catcode, CATALOGUES_MPC[]) - L_i = length(idxs) - - # No catalog matches catcode - if L_i == 0 - catalogue = unknowncat() - # Exactly one catalogue matches catcode - else - catalogue = CATALOGUES_MPC[][idxs[1]] - # More than one catalogue matches catcode - if L_i > 1 - @warn("""More than one catalogue $(CATALOGUES_MPC[][idxs]) has code $catcode, - selecting first: $(catalogue.name)""") - end - end - - return catalogue - +@doc raw""" + CatalogueMPC + +An astrometric reference catalogue in MPC format. + +# Fields + +- `code::String`: catalogue's single character identifier. +- `name::String`: catalogue's name. + +!!! reference + The format is described in https://minorplanetcenter.net/iau/info/CatalogueCodes.html. +""" +@auto_hash_equals struct CatalogueMPC + code::String + name::String + # Inner constructor + function CatalogueMPC(code::String, name::String) + return new(code, name) + end +end + +@doc raw""" + unknowncat() + +Return a `CatalogueMPC` with no code or name. +""" +function unknowncat() + return CatalogueMPC("", "") +end + +@doc raw""" + isunknown(m::CatalogueMPC) + +Check whether `m` equals `unknowncat()`. +""" +function isunknown(m::CatalogueMPC) + return m == unknowncat() +end + +# Print method for CatalogueMPC +# Examples: +# Unknown catalogue +# USNO-A1.0 [a] +function show(io::IO, m::CatalogueMPC) + if isunknown(m) + print(io, "Unknown catalogue") + else + print(io, m.name, " [", m.code, "]") + end +end + +neoparse(x::RegexMatch, i::Int, ::Type{String}) = String(strip(x[i])) + +@doc raw""" + CatalogueMPC(m::RegexMatch) + +Convert a match of `NEOs.CATALOGUE_MPC_REGEX` to `CatalogueMPC`. +""" +function CatalogueMPC(m::RegexMatch) + # Check that matched regex is correct + @assert m.regex == CATALOGUE_MPC_REGEX "Only matches of `NEOs.CATALOGUE_MPC_REGEX` can be converted to `CatalogueMPC`." + # Field types + types = fieldtypes(CatalogueMPC) + # CatalogueMPC fields + args = map(i -> neoparse(m, i, types[i]), 1:length(types)) + + return CatalogueMPC(args...) +end + +@doc raw""" + read_catalogues_mpc(s::String) + +Return the matches of `NEOs.CATALOGUE_MPC_REGEX` in `s` as `Vector{CatalogueMPC}`. +`s` can be either a filename or a text. +""" +function read_catalogues_mpc(s::String) + if !contains(s, "\n") && isfile(s) + # Read MPC formatted file + s = String(read(s)) + end + # Remove header + s = replace(s, CATALOGUES_MPC_HEADER => "") + # Vector of MPC catalogues + cats = Vector{CatalogueMPC}(undef, 0) + # Iterate over the matches + for m in eachmatch(CATALOGUE_MPC_REGEX, s) + push!(cats, CatalogueMPC(m)) + end + # Eliminate repeated entries + unique!(cats) + + return cats +end + +# Convert `cat` to a string according to MPC format. +function string(cat::CatalogueMPC) + if isunknown(cat) + return "" + else + # Code string + code_s = string(" ", cat.code, " ") + # Join everything + cat_s = string(code_s, cat.name) + + return cat_s + end +end + +@doc raw""" + write_catalogues_mpc(cats::Vector{CatalogueMPC}, filename::String) + +Write `cats` to `filename` in MPC format. +""" +function write_catalogues_mpc(cats::Vector{CatalogueMPC}, filename::String) + open(filename, "w") do file + # Header + write(file, CATALOGUES_MPC_HEADER, "\n") + # Write observatories + for i in eachindex(cats) + line = string(cats[i]) + write(file, line, "\n") + end + end +end + +@doc raw""" + download_scratch(url::String, filename::String; connect_timeout = 180, readtimeout = 180) + +Download `url` and save the output to NEOs scratch space as `filename`. Return the local +path and the contents of the file as a `String`. +""" +function download_scratch(url::String, filename::String; connect_timeout = 180, readtimeout = 180) + # Local file + path = joinpath(scratch_path[], filename) + # Get raw html (HTTP.get retries four times by default) + resp = get(url; connect_timeout, readtimeout) + # Read local file + txt = String(resp.body) + + return path, txt +end + +@doc raw""" + update_catalogues_mpc() + +Update the local catalogues file. +""" +function update_catalogues_mpc() + # Download and read catalogues file + CatalogueCodes_path, txt = download_scratch(CATALOGUES_MPC_URL, "CatalogueCodes.txt") + # Parse catalogues + cats = read_catalogues_mpc(txt) + # Write catalogues to local file + write_catalogues_mpc(cats, CatalogueCodes_path) + # Update global variable + global CATALOGUES_MPC[] = read_catalogues_mpc(CatalogueCodes_path) + + return nothing +end + +@doc raw""" + search_cat_code(catcode::String) + +Return the catalogue in `NEOs.CATALOGUES_MPC` that matches `catcode`. +""" +function search_cat_code(catcode::String) + + # Find indexes in mpc_catalogues that match catcode + idxs = findall(x -> x.code == catcode, CATALOGUES_MPC[]) + L_i = length(idxs) + + # No catalog matches catcode + if L_i == 0 + catalogue = unknowncat() + # Exactly one catalogue matches catcode + else + catalogue = CATALOGUES_MPC[][idxs[1]] + # More than one catalogue matches catcode + if L_i > 1 + @warn("""More than one catalogue $(CATALOGUES_MPC[][idxs]) has code $catcode, + selecting first: $(catalogue.name)""") + end + end + + return catalogue + end \ No newline at end of file diff --git a/src/observations/jpl_eph.jl b/src/observations/jpl_eph.jl old mode 100644 new mode 100755 index bba0c18f..17ad9beb --- a/src/observations/jpl_eph.jl +++ b/src/observations/jpl_eph.jl @@ -1,163 +1,163 @@ -# Load TT-TDB (ttmtdb) from jld2 file -@doc raw""" - loadjpleph() - -Load JPL ephemerides (NAIF IDs, DE430 TT-TDB and ephemerides, #197 and #199 solutions for Apophis). - -See also [`SPICE.furnsh`](@ref). -""" -function loadjpleph() - furnsh( - # JPL DE430 TT-TDB - joinpath(artifact"TTmTDBde430", "TTmTDB.de430.19feb2015.bsp"), - # JPL DE430 ephemerides - joinpath(artifact"de430", "de430_1850-2150.bsp"), - # JPL #197 solution for Apophis - joinpath(artifact"a99942", "a99942_s197.bsp"), - # JPL #199 solution for Apophis - joinpath(artifact"a99942", "a99942_s199.bsp"), - ) -end - -@doc raw""" - getposvel(target::Int, observer::Int, et) - -Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) at -TDB instant `et` from SPK-formatted ephemeris file with respect to J2000 frame. - -See also [`SPICE.spkgeo`](@ref). -""" -function getposvel(target::Int, observer::Int, et) - return spkgeo(target, et, "J2000", observer)[1] # units: km,km/sec -end - -# NAIF IDs: -# 0: Solar System Barycenter -# 10: Sun (heliocenter) -# 2099942: Apophis -# 399: Earth (geocenter) -# 301: Moon -# 1000000001 from body 1000000000: TT-TDB -# Here, we follow the convention from the CSPICE, library, that the ephemeris -# time is referred to the J2000 frame epoch: -# https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/spk.html#Terminology -# argument `et` represents "ephemeris seconds" (TDB seconds) since J2000.0 TDB epoch -# position and velocity are assumed to be returned in km, km/sec, resp., by spkgeo -# https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/spkgeo_c.html (see: Detailed ouput section) - -@doc raw""" - sunposvel(et) - -Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) -of the Sun at TDB instant `et` with respect to J2000 frame. - -See also [`getposvel`](@ref). -""" -sunposvel(et) = getposvel(10, 0, cte(et)) # units: km, km/second - -@doc raw""" - earthposvel(et) - -Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) -of the Earth at TDB instant `et` with respect to J2000 frame. - -See also [`getposvel`](@ref). -""" -earthposvel(et) = getposvel(399, 0, cte(et)) # units: km, km/second - -@doc raw""" - moonposvel(et) - -Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) -of the Moon at TDB instant `et` with respect to J2000 frame. - -See also [`getposvel`](@ref). -""" -moonposvel(et) = getposvel(301, 0, cte(et)) # units: km, km/second - -@doc raw""" - apophisposvel197(et) - -Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) -of Apophis at TDB instant `et` from JPL #197 solution with respect to J2000 frame. - -See also [`getposvel`](@ref). -""" -apophisposvel197(et) = getposvel(9904406, 0, cte(et)) # units: km, km/second - -@doc raw""" - apophisposvel199(et) - -Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) -of Apophis at TDB instant `et` from JPL #199 solution with respect to J2000 frame. - -See also [`getposvel`](@ref). -""" -apophisposvel199(et) = getposvel(2099942, 0, cte(et)) # units: km, km/second - -@doc raw""" - tt_tdb(et) - -Return the difference TT-TDB (in units of sec) at TDB instant `et` with respect to J2000 -frame. - -See also [`getposvel`](@ref). -""" -tt_tdb(et) = getposvel(1000000001, 1000000000, cte(et))[1] # units: seconds - -@doc raw""" - dtt_tdb(et) - -Return the rate of change of TT-TDB (in units of sec/sec) at TDB instant `et` with respect -to J2000 frame. - -See also [`getposvel`](@ref). -""" -dtt_tdb(et) = getposvel(1000000001, 1000000000, cte(et))[4] # units: seconds/seconds - -# Load Solar System, accelerations, newtonian potentials and TT-TDB 2000-2100 ephemeris -const sseph_artifact_path = joinpath(artifact"sseph_p100", "sseph343ast016_p100y_et.jld2") -const sseph::TaylorInterpolant{Float64, Float64, 2} = JLD2.load(sseph_artifact_path, "ss16ast_eph") -const acceph::TaylorInterpolant{Float64, Float64, 2} = JLD2.load(sseph_artifact_path, "acc_eph") -const poteph::TaylorInterpolant{Float64, Float64, 2} = JLD2.load(sseph_artifact_path, "pot_eph") -const ttmtdb::TaylorInterpolant{Float64, Float64, 1} = TaylorInterpolant(sseph.t0, sseph.t, sseph.x[:,end]) - -@doc raw""" - loadpeeph(eph::TaylorInterpolant{Float64, Float64, 2} = sseph, t_0::Real = 0.0, t_f::Real = 36525.0) - -Load ephemeris produced by `PlanetaryEphemeris.jl` in timerange `[t_0, t_f] ⊆ [0.0, 36525.0]` where `t` must have units of TDB -days since J2000. The available options for `eph` are: - -- `NEOs.sseph`: Solar system ephemeris. -- `NEOs.acceph`: accelerations ephemeris. -- `NEOs.poteph`: newtonian potentials ephemeris. - -!!! warning - Running this function for the first time will download the `sseph_p100` artifact (885 MB) which can take several minutes. -""" -function loadpeeph(eph::TaylorInterpolant{Float64, Float64, 2} = sseph, t_0::Real = sseph.t0, t_f::Real = sseph.t0 + sseph.t[end]) - @assert 0.0 ≤ t_0 ≤ t_f ≤ 36525.0 - i_0 = searchsortedlast(eph.t, t_0) - i_f = searchsortedfirst(eph.t, t_f) - return TaylorInterpolant(eph.t0, eph.t[i_0:i_f], eph.x[i_0:i_f-1, :]) -end - -@doc raw""" - bwdfwdeph(et::Union{T,Taylor1{T},TaylorN{T},Taylor1{TaylorN{T}}}, bwd::TaylorInterpolant{T, U, 2}, - fwd::TaylorInterpolant{T, U, 2}) where {T <: AbstractFloat, U <: Union{T, TaylorN{T}}} - -Paste a backward and a forward integration, evaluate at `et` and convert from [au, au/day] -> [km, km/sec]. -""" -function bwdfwdeph(et::Union{T,Taylor1{T},TaylorN{T},Taylor1{TaylorN{T}}}, - bwd::TaylorInterpolant{T,U,2}, - fwd::TaylorInterpolant{T,U,2} - ) where {T<:AbstractFloat, U<:Union{T,TaylorN{T}}} - @assert bwd.t0 == fwd.t0 "Backward and forward TaylorInterpolant initial times must match" - t = et/daysec - t0 = bwd.t0 - if t <= t0 - return auday2kmsec(bwd(t)) - else - return auday2kmsec(fwd(t)) - end -end +# Load TT-TDB (ttmtdb) from jld2 file +@doc raw""" + loadjpleph() + +Load JPL ephemerides (NAIF IDs, DE430 TT-TDB and ephemerides, #197 and #199 solutions for +Apophis). + +See also [`SPICE.furnsh`](@ref). +""" +function loadjpleph() + furnsh( + # JPL DE430 TT-TDB + joinpath(artifact"TTmTDBde430", "TTmTDB.de430.19feb2015.bsp"), + # JPL DE430 ephemerides + joinpath(artifact"de430", "de430_1850-2150.bsp"), + # JPL #197 solution for Apophis + joinpath(artifact"a99942", "a99942_s197.bsp"), + # JPL #199 solution for Apophis + joinpath(artifact"a99942", "a99942_s199.bsp"), + ) +end + +@doc raw""" + getposvel(target::Int, observer::Int, et) + +Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) at +TDB instant `et` from SPK-formatted ephemeris file with respect to J2000 frame. + +See also [`SPICE.spkgeo`](@ref). +""" +function getposvel(target::Int, observer::Int, et) + return spkgeo(target, et, "J2000", observer)[1] # units: km,km/sec +end + +# NAIF IDs: +# 0: Solar System Barycenter +# 10: Sun (heliocenter) +# 2099942: Apophis +# 399: Earth (geocenter) +# 301: Moon +# 1000000001 from body 1000000000: TT-TDB +# Here, we follow the convention from the CSPICE, library, that the ephemeris +# time is referred to the J2000 frame epoch: +# https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/spk.html#Terminology +# argument `et` represents "ephemeris seconds" (TDB seconds) since J2000.0 TDB epoch +# position and velocity are assumed to be returned in km, km/sec, resp., by spkgeo +# https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/spkgeo_c.html (see: Detailed ouput section) + +@doc raw""" + sunposvel(et) + +Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) +of the Sun at TDB instant `et` with respect to J2000 frame. + +See also [`getposvel`](@ref). +""" +sunposvel(et) = getposvel(10, 0, cte(et)) # units: km, km/second + +@doc raw""" + earthposvel(et) + +Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) +of the Earth at TDB instant `et` with respect to J2000 frame. + +See also [`getposvel`](@ref). +""" +earthposvel(et) = getposvel(399, 0, cte(et)) # units: km, km/second + +@doc raw""" + moonposvel(et) + +Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) +of the Moon at TDB instant `et` with respect to J2000 frame. + +See also [`getposvel`](@ref). +""" +moonposvel(et) = getposvel(301, 0, cte(et)) # units: km, km/second + +@doc raw""" + apophisposvel197(et) + +Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) +of Apophis at TDB instant `et` from JPL #197 solution with respect to J2000 frame. + +See also [`getposvel`](@ref). +""" +apophisposvel197(et) = getposvel(9904406, 0, cte(et)) # units: km, km/second + +@doc raw""" + apophisposvel199(et) + +Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) +of Apophis at TDB instant `et` from JPL #199 solution with respect to J2000 frame. + +See also [`getposvel`](@ref). +""" +apophisposvel199(et) = getposvel(2099942, 0, cte(et)) # units: km, km/second + +@doc raw""" + tt_tdb(et) + +Return the difference TT-TDB (in units of sec) at TDB instant `et` with respect to J2000 +frame. + +See also [`getposvel`](@ref). +""" +tt_tdb(et) = getposvel(1000000001, 1000000000, cte(et))[1] # units: seconds + +@doc raw""" + dtt_tdb(et) + +Return the rate of change of TT-TDB (in units of sec/sec) at TDB instant `et` with respect +to J2000 frame. + +See also [`getposvel`](@ref). +""" +dtt_tdb(et) = getposvel(1000000001, 1000000000, cte(et))[4] # units: seconds/seconds + +@doc raw""" + loadpeeph(eph::TaylorInterpolant{Float64, Float64, 2} = sseph, t_0::T = sseph.t0, + t_f::S = sseph.t0 + sseph.t[end]) where {T, S <: Real} + +Load ephemeris produced by `PlanetaryEphemeris.jl` in timerange `[t_0, t_f] ⊆ [0.0, 36525.0]` +where `t` must have units of TDB days since J2000. The available options for `eph` are: + +- `NEOs.sseph`: Solar system ephemeris. +- `NEOs.acceph`: accelerations ephemeris. +- `NEOs.poteph`: newtonian potentials ephemeris. + +!!! warning + Running this function for the first time will download the `sseph_p100` artifact (885 MB) + which can take several minutes. +""" +function loadpeeph(eph::TaylorInterpolant{Float64, Float64, 2} = sseph, t_0::T = sseph.t0, + t_f::S = sseph.t0 + sseph.t[end]) where {T, S <: Real} + @assert 0.0 ≤ t_0 ≤ t_f ≤ 36525.0 + i_0 = searchsortedlast(eph.t, t_0) + i_f = searchsortedfirst(eph.t, t_f) + return TaylorInterpolant(eph.t0, eph.t[i_0:i_f], eph.x[i_0:i_f-1, :]) +end + +@doc raw""" + bwdfwdeph(et::Union{T, Taylor1{T}, TaylorN{T}, Taylor1{TaylorN{T}}}, + bwd::TaylorInterpolant{T, U, 2}, + fwd::TaylorInterpolant{T, U, 2} + ) where {T <: AbstractFloat, U <: Union{T, TaylorN{T}}} + +Paste a backward and a forward integration, evaluate at `et` and convert from +[au, au/day] -> [km, km/sec]. +""" +function bwdfwdeph(et::Union{T, Taylor1{T}, TaylorN{T}, Taylor1{TaylorN{T}}}, + bwd::TaylorInterpolant{T,U,2}, + fwd::TaylorInterpolant{T,U,2} + ) where {T <: AbstractFloat, U <: Union{T, TaylorN{T}}} + @assert bwd.t0 == fwd.t0 "Backward and forward TaylorInterpolant initial times must match" + t = et/daysec + t0 = bwd.t0 + if t <= t0 + return auday2kmsec(bwd(t)) + else + return auday2kmsec(fwd(t)) + end +end diff --git a/src/observations/observatory_mpc.jl b/src/observations/observatory_mpc.jl old mode 100644 new mode 100755 index 8269fa84..89ef2932 --- a/src/observations/observatory_mpc.jl +++ b/src/observations/observatory_mpc.jl @@ -1,306 +1,294 @@ -@doc raw""" - ObservatoryMPC{T <: AbstractFloat} - -An observatory in MPC format. The format is described in https://minorplanetcenter.net/iau/lists/ObsCodesF.html. - -# Fields - -- `code::String`: observatory's identifier. -- `long::T`: longitude [degrees east of Greenwich]. -- `cos::T`: `ρ*cos(ϕ')`, -- `sin::T`: `ρ*sin(ϕ')`, where `ϕ'` is the geocentric latitude and `ρ` is the geocentric distance in earth radii. -- `name::String`: observatory's name. -""" -struct ObservatoryMPC{T <: AbstractFloat} - code::String - long::T - cos::T - sin::T - name::String - date::DateTime - type::Symbol - units::Int - # Inner constructor - function ObservatoryMPC{T}(code::String, long::T, cos::T, sin::T, name::String, date::DateTime = DateTime(2000, 1, 1), - type::Symbol = :ground, units::Int = 0) where {T <: AbstractFloat} - return new{T}(code, long, cos, sin, name, date, type, units) - end -end - -# Outer constructor -function ObservatoryMPC(code::String, long::T, cos::T, sin::T, name::String, date::DateTime = DateTime(2000, 1, 1), - type::Symbol = :ground, units::Int = 0) where {T <: AbstractFloat} - return ObservatoryMPC{T}(code, long, cos, sin, name, date, type, units) -end - -# TO DO: This could be done with a more recent version of AutoHasEquals -function Base.hash(x::ObservatoryMPC{T}, h::UInt) where {T <: AbstractFloat} - Base.hash(x.code, Base.hash(:(ObservatoryMPC{T}), h)) -end -function Base.isequal(a::ObservatoryMPC{T}, b::ObservatoryMPC{T}) where {T <: AbstractFloat} - Base.isequal(a.code, b.code) -end -# Returns `false` if any two fields compare as false; otherwise, `missing` if at least -# one comparison is missing. Otherwise `true`. -# This matches the semantics of `==` for Tuple's and NamedTuple's. -function Base.:(==)(a::ObservatoryMPC{T}, b::ObservatoryMPC{T}) where {T <: AbstractFloat} - found_missing = false - cmp = a.code == b.code - cmp === false && return false - if ismissing(cmp) - found_missing = true - end - found_missing && return missing - return true -end - -@doc raw""" - unknownobs() - -Return a `ObservatoryMPC` with no code, coordinates or name. -""" -unknownobs() = ObservatoryMPC("", NaN, NaN, NaN, "") - -@doc raw""" - isunknown(m::ObservatoryMPC{T}) where {T <: AbstractFloat} - -Check whether `m` equals `unknownobs()`. -""" -function isunknown(m::ObservatoryMPC{T}) where {T <: AbstractFloat} - return m == unknownobs() -end - -isground(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :ground -issatellite(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :satellite -isoccultation(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :occultation - -@doc raw""" - hascoord(m::ObservatoryMPC{T}) where {T <: AbstractFloat} - -Check whether `m` has non `NaN` coordinates. -""" -function hascoord(m::ObservatoryMPC{T}) where {T <: AbstractFloat} - return !isnan(m.long) && !isnan(m.cos) && !isnan(m.sin) -end - -# Print method for ObservatoryMPC -# Examples: -# Unknown observatory -# Spitzer Space Telescope [245] -# Greenwich [000] long: 0.0 cos: 0.62411 sin: 0.77873 -function show(io::IO, m::ObservatoryMPC{T}) where {T <: AbstractFloat} - if isunknown(m) - print(io, "Unknown observatory") - elseif isground(m) - print(io, m.name, " [", m.code, "] long: ", m.long, " cos: ", m.cos, " sin: ", m.sin) - else - print(io, m.name, " [", m.code, "]") - end -end - -function neoparse(x::RegexMatch, i::Int, ::Type{Float64}) - y = tryparse(Float64, replace(x[i], " " => "")) - if isnothing(y) - return NaN - else - return y - end -end - -# Regular expression to parse an observatory in MPC format -const OBSERVATORY_MPC_REGEX = Regex(string( - # Code regex + space (columns 1-3) - raw"(?P[A-Z\d]{3})", - # Longitude regex (columns 4-13) - raw"(?P[\.\d\s]{10})", - # Cosine regex + space (column 14-21) - raw"(?P[\.\d\s]{8})", - # Sine regex (column 22-30) - raw"(?P[\+\-\.\d\s]{9})", - # Name regex (columns 31-80) - raw"(?P.*)", -)) -# Header of MPC observatories file -const OBSERVATORIES_MPC_HEADER = "Code Long. cos sin Name" - -@doc raw""" - ObservatoryMPC(m::RegexMatch) - -Convert a match of `NEOs.OBSERVATORY_MPC_REGEX` to `ObservatoryMPC`. -""" -function ObservatoryMPC(m::RegexMatch) - # Check that matched regex is correct - @assert m.regex == OBSERVATORY_MPC_REGEX "Only matches of `NEOs.OBSERVATORY_MPC_REGEX` can be converted to `ObservatoryMPC`." - # Field types - types = fieldtypes(ObservatoryMPC{Float64}) - # ObservatoryMPC{Float64} fields - args = map(i -> neoparse(m, i, types[i]), 1:5) - - if isnan(args[2]) && isnan(args[3]) && isnan(args[4]) - return ObservatoryMPC(args..., DateTime(2000, 1, 1), :satellite, 0) - else - return ObservatoryMPC(args...) - end -end - -@doc raw""" - read_observatories_mpc(s::String) - -Return the matches of `NEOs.OBSERVATORY_MPC_REGEX` in `s` as `ObservatoryMPC`. -""" -function read_observatories_mpc(s::String) - if !contains(s, "\n") && isfile(s) - # Read MPC formatted file - s = String(read(s)) - end - # Remove header - s = replace(s, OBSERVATORIES_MPC_HEADER => "") - # Vector of MPC observatories - obs = Vector{ObservatoryMPC{Float64}}(undef, 0) - # Iterate over the matches - for m in eachmatch(OBSERVATORY_MPC_REGEX, s) - push!(obs, ObservatoryMPC(m)) - end - # Eliminate repeated entries - unique!(obs) - - return obs -end - -@doc raw""" - mpc_long_str(x::T) where {T <: AbstractFloat} - -Convert `x` to a string according to the `long` field in MPC format. -""" -function mpc_long_str(x::T) where {T <: AbstractFloat} - # NaN => empty string - if isnan(x) - long_s = repeat(" ", 10) - else - long_s = @sprintf("%3.5f", x) - long_s = lpad(long_s, 10) - end - return long_s -end - -@doc raw""" - mpc_cos_str(x::T) where {T <: AbstractFloat} - -Convert `x` to a string according to the `cos` field in MPC format. -""" -function mpc_cos_str(x::T) where {T <: AbstractFloat} - # NaN => empty string - if isnan(x) - cos_s = repeat(" ", 8) - else - cos_s = @sprintf("%1.6f", x) - end - return cos_s -end - -@doc raw""" - mpc_sin_str(x::T) where {T <: AbstractFloat} - -Convert `x` to a string according to the `sin` field in MPC format. -""" -function mpc_sin_str(x::T) where {T <: AbstractFloat} - # NaN => empty string - if isnan(x) - sin_s = repeat(" ", 9) - else - sin_s = @sprintf("%1.6f", abs(x)) - if x ≥ 0 - sin_s = string("+", sin_s) - else - sin_s = string("-", sin_s) - end - end - - return sin_s -end - -# Convert `obs` to a string according to MPC format. -function string(obs::ObservatoryMPC{T}) where {T <: AbstractFloat} - if isunknown(obs) - return "" - else - # Longitude string - long_s = mpc_long_str(obs.long) - # Cosine string - cos_s = mpc_cos_str(obs.cos) - # Sine string string - sin_s = mpc_sin_str(obs.sin) - # Join everything - obs_s = string(obs.code, long_s, cos_s, sin_s, obs.name) - end - - return obs_s -end - -@doc raw""" - write_observatories_mpc(obs::Vector{ObservatoryMPC{T}}, filename::String) where {T <: AbstractFloat} - -Write `obs` to `filename` in MPC format. -""" -function write_observatories_mpc(obs::Vector{ObservatoryMPC{T}}, filename::String) where {T <: AbstractFloat} - open(filename, "w") do file - # Header - write(file, OBSERVATORIES_MPC_HEADER, "\n") - # Write observatories - for i in eachindex(obs) - line = string(obs[i]) - write(file, line, "\n") - end - end -end - -# MPC observatories file url -const OBSERVATORIES_MPC_URL = "https://minorplanetcenter.net/iau/lists/ObsCodes.html" -# List of mpc observatories -const OBSERVATORIES_MPC = Ref{Vector{ObservatoryMPC{Float64}}}([unknownobs()]) - -@doc raw""" - update_observatories_mpc() - -Update the local observatories file. -""" -function update_observatories_mpc() - # Download and read observatories file - ObsCodes_path, txt = download_scratch(OBSERVATORIES_MPC_URL, "ObsCodes.txt") - # Parse observatories - obs = read_observatories_mpc(txt) - # Write observatories to local file - write_observatories_mpc(obs, ObsCodes_path) - # Update global variable - global OBSERVATORIES_MPC[] = read_observatories_mpc(ObsCodes_path) - - return nothing -end - -@doc raw""" - search_obs_code(obscode::String) - -Return the observatory in `NEOs.OBSERVATORIES_MPC` that matches `obscode`. -""" -function search_obs_code(obscode::String) - - # Find indexes in OBSERVATORIES_MPC that match obscode - idxs = findall(x -> x.code == obscode, OBSERVATORIES_MPC[]) - L_i = length(idxs) - - # No observatory matches obscode - if L_i == 0 - observatory = unknownobs() - # At least one observatory matches obscode - else - observatory = OBSERVATORIES_MPC[][idxs[1]] - # More than one observatory matches obscode - if L_i > 1 - @warn("""More than one observatory $(OBSERVATORIES_MPC[][idxs]) has code $obscode, - selecting first: $(observatory.name)""") - end - end - - return observatory - +@doc raw""" + ObservatoryMPC{T <: AbstractFloat} + +An observatory in MPC format. + +# Fields + +- `code::String`: observatory's three character identifier. +- `long::T`, `cos::T`, `sin::T`: + - For ground-based observatories: longitude [degrees east of Greenwich], + `ρ*cos(ϕ')` and `ρ*sin(ϕ')`, where `ϕ'` is the geocentric latitude and + `ρ` is the geocentric distance in earth radii. + - For space-based observatories: `x`, `y` and `z` geocentric coordinates. +- `name::String`: observatory's name. +- `date::DateTime`: time of observation (for `:satellite`/`:occultation` observatories). +- `type::Symbol`: `:ground`, `:satellite` or `:occultation`. +- `units::Int`: whether position is encrypted in AU (1) or KM (2). + +!!! reference + The format is described in https://minorplanetcenter.net/iau/lists/ObsCodesF.html. +""" +struct ObservatoryMPC{T <: AbstractFloat} + code::String + long::T + cos::T + sin::T + name::String + date::DateTime + type::Symbol + units::Int + # Inner constructor + function ObservatoryMPC{T}(code::String, long::T, cos::T, sin::T, name::String, date::DateTime = DateTime(2000, 1, 1), + type::Symbol = :ground, units::Int = 0) where {T <: AbstractFloat} + return new{T}(code, long, cos, sin, name, date, type, units) + end +end + +# Outer constructor +function ObservatoryMPC(code::String, long::T, cos::T, sin::T, name::String, date::DateTime = DateTime(2000, 1, 1), + type::Symbol = :ground, units::Int = 0) where {T <: AbstractFloat} + return ObservatoryMPC{T}(code, long, cos, sin, name, date, type, units) +end + +# TO DO: This could be done with a more recent version of AutoHasEquals +function Base.hash(x::ObservatoryMPC{T}, h::UInt) where {T <: AbstractFloat} + Base.hash(x.code, Base.hash(:(ObservatoryMPC{T}), h)) +end +function Base.isequal(a::ObservatoryMPC{T}, b::ObservatoryMPC{T}) where {T <: AbstractFloat} + Base.isequal(a.code, b.code) +end +# Returns `false` if any two fields compare as false; otherwise, `missing` if at least +# one comparison is missing. Otherwise `true`. +# This matches the semantics of `==` for Tuple's and NamedTuple's. +function Base.:(==)(a::ObservatoryMPC{T}, b::ObservatoryMPC{T}) where {T <: AbstractFloat} + found_missing = false + cmp = a.code == b.code + cmp === false && return false + if ismissing(cmp) + found_missing = true + end + found_missing && return missing + return true +end + +@doc raw""" + unknownobs() + +Return a `ObservatoryMPC` with no code, coordinates or name. +""" +unknownobs() = ObservatoryMPC("", NaN, NaN, NaN, "") + +@doc raw""" + isunknown(m::ObservatoryMPC{T}) where {T <: AbstractFloat} + +Check whether `m` equals `unknownobs()`. +""" +function isunknown(m::ObservatoryMPC{T}) where {T <: AbstractFloat} + return m == unknownobs() +end + +isground(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :ground +issatellite(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :satellite +isoccultation(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :occultation + +@doc raw""" + hascoord(m::ObservatoryMPC{T}) where {T <: AbstractFloat} + +Check whether `m` has non `NaN` coordinates. +""" +function hascoord(m::ObservatoryMPC{T}) where {T <: AbstractFloat} + return !isnan(m.long) && !isnan(m.cos) && !isnan(m.sin) +end + +# Print method for ObservatoryMPC +# Examples: +# Unknown observatory +# Spitzer Space Telescope [245] +# Greenwich [000] long: 0.0 cos: 0.62411 sin: 0.77873 +function show(io::IO, m::ObservatoryMPC{T}) where {T <: AbstractFloat} + if isunknown(m) + print(io, "Unknown observatory") + elseif isground(m) + print(io, m.name, " [", m.code, "] long: ", m.long, " cos: ", m.cos, " sin: ", m.sin) + else + print(io, m.name, " [", m.code, "]") + end +end + +function neoparse(x::RegexMatch, i::Int, ::Type{Float64}) + y = tryparse(Float64, replace(x[i], " " => "")) + if isnothing(y) + return NaN + else + return y + end +end + +@doc raw""" + ObservatoryMPC(m::RegexMatch) + +Convert a match of `NEOs.OBSERVATORY_MPC_REGEX` to `ObservatoryMPC`. +""" +function ObservatoryMPC(m::RegexMatch) + # Check that matched regex is correct + @assert m.regex == OBSERVATORY_MPC_REGEX "Only matches of `NEOs.OBSERVATORY_MPC_REGEX` can be converted to `ObservatoryMPC`." + # Field types + types = fieldtypes(ObservatoryMPC{Float64}) + # ObservatoryMPC{Float64} fields + args = map(i -> neoparse(m, i, types[i]), 1:5) + + if isnan(args[2]) && isnan(args[3]) && isnan(args[4]) + return ObservatoryMPC(args..., DateTime(2000, 1, 1), :satellite, 0) + else + return ObservatoryMPC(args...) + end +end + +@doc raw""" + read_observatories_mpc(s::String) + +Return the matches of `NEOs.OBSERVATORY_MPC_REGEX` in `s` as `Vector{ObservatoryMPC{Float64}}`. +`s` can be either a filename or a text. +""" +function read_observatories_mpc(s::String) + if !contains(s, "\n") && isfile(s) + # Read MPC formatted file + s = String(read(s)) + end + # Remove header + s = replace(s, OBSERVATORIES_MPC_HEADER => "") + # Vector of MPC observatories + obs = Vector{ObservatoryMPC{Float64}}(undef, 0) + # Iterate over the matches + for m in eachmatch(OBSERVATORY_MPC_REGEX, s) + push!(obs, ObservatoryMPC(m)) + end + # Eliminate repeated entries + unique!(obs) + + return obs +end + +@doc raw""" + mpc_long_str(x::T) where {T <: AbstractFloat} + +Convert `x` to a string according to the `long` field in MPC format. +""" +function mpc_long_str(x::T) where {T <: AbstractFloat} + # NaN => empty string + if isnan(x) + long_s = repeat(" ", 10) + else + long_s = @sprintf("%3.5f", x) + long_s = lpad(long_s, 10) + end + return long_s +end + +@doc raw""" + mpc_cos_str(x::T) where {T <: AbstractFloat} + +Convert `x` to a string according to the `cos` field in MPC format. +""" +function mpc_cos_str(x::T) where {T <: AbstractFloat} + # NaN => empty string + if isnan(x) + cos_s = repeat(" ", 8) + else + cos_s = @sprintf("%1.6f", x) + end + return cos_s +end + +@doc raw""" + mpc_sin_str(x::T) where {T <: AbstractFloat} + +Convert `x` to a string according to the `sin` field in MPC format. +""" +function mpc_sin_str(x::T) where {T <: AbstractFloat} + # NaN => empty string + if isnan(x) + sin_s = repeat(" ", 9) + else + sin_s = @sprintf("%1.6f", abs(x)) + if x ≥ 0 + sin_s = string("+", sin_s) + else + sin_s = string("-", sin_s) + end + end + + return sin_s +end + +# Convert `obs` to a string according to MPC format. +function string(obs::ObservatoryMPC{T}) where {T <: AbstractFloat} + if isunknown(obs) + return "" + else + # Longitude string + long_s = mpc_long_str(obs.long) + # Cosine string + cos_s = mpc_cos_str(obs.cos) + # Sine string string + sin_s = mpc_sin_str(obs.sin) + # Join everything + obs_s = string(obs.code, long_s, cos_s, sin_s, obs.name) + end + + return obs_s +end + +@doc raw""" + write_observatories_mpc(obs::Vector{ObservatoryMPC{T}}, filename::String) where {T <: AbstractFloat} + +Write `obs` to `filename` in MPC format. +""" +function write_observatories_mpc(obs::Vector{ObservatoryMPC{T}}, filename::String) where {T <: AbstractFloat} + open(filename, "w") do file + # Header + write(file, OBSERVATORIES_MPC_HEADER, "\n") + # Write observatories + for i in eachindex(obs) + line = string(obs[i]) + write(file, line, "\n") + end + end +end + +@doc raw""" + update_observatories_mpc() + +Update the local observatories file. +""" +function update_observatories_mpc() + # Download and read observatories file + ObsCodes_path, txt = download_scratch(OBSERVATORIES_MPC_URL, "ObsCodes.txt") + # Parse observatories + obs = read_observatories_mpc(txt) + # Write observatories to local file + write_observatories_mpc(obs, ObsCodes_path) + # Update global variable + global OBSERVATORIES_MPC[] = read_observatories_mpc(ObsCodes_path) + + return nothing +end + +@doc raw""" + search_obs_code(obscode::String) + +Return the observatory in `NEOs.OBSERVATORIES_MPC` that matches `obscode`. +""" +function search_obs_code(obscode::String) + + # Find indexes in OBSERVATORIES_MPC that match obscode + idxs = findall(x -> x.code == obscode, OBSERVATORIES_MPC[]) + L_i = length(idxs) + + # No observatory matches obscode + if L_i == 0 + observatory = unknownobs() + # At least one observatory matches obscode + else + observatory = OBSERVATORIES_MPC[][idxs[1]] + # More than one observatory matches obscode + if L_i > 1 + @warn("""More than one observatory $(OBSERVATORIES_MPC[][idxs]) has code $obscode, + selecting first: $(observatory.name)""") + end + end + + return observatory + end \ No newline at end of file diff --git a/src/observations/process_radar.jl b/src/observations/process_radar.jl old mode 100644 new mode 100755 index a5536117..7cd4eb0d --- a/src/observations/process_radar.jl +++ b/src/observations/process_radar.jl @@ -1,602 +1,619 @@ -include("catalogue_mpc.jl") -include("observatory_mpc.jl") -include("radec_mpc.jl") -include("radar_jpl.jl") -include("units.jl") -include("jpl_eph.jl") -include("topocentric.jl") -include("process_radec.jl") - -@doc raw""" - shapiro_delay(e, p, q) - -Return the relativistic (Shapiro) time-delay in seconds -```math -\Delta\tau[\text{rel}] = \frac{2\mu_\odot}{c^3}\log\left|\frac{d_{E,S} + d_{A,S} + d_{A,E}}{d_{E,S}+d_{A,S}-d_{A, E}}\right|, -``` -where ``\mu_\odot = GM_\odot`` is the gravitational parameter of the sun, and ``d_{E,S}``, ``d_{A,S}`` -and ``d_{A,E}`` are the heliocentric distance of the Earth, the asteroid's heliocentric -distance, and the asteroid's geocentric distance, respectively. - -See https://doi.org/10.1103/PhysRevLett.13.789. - -# Arguments - -- `e`: heliocentric distance of the Earth. -- `p`: asteroid's heliocentric distance. -- `q`: asteroid's geocentric distance. -""" -function shapiro_delay(e, p, q) - shap = 0.0 # 2μ[1]/(c_au_per_day^2) - shap_del_days = (2μ_DE430[su]/(c_au_per_day^3))*log( (e+p+q+shap)/(e+p-q+shap) ) # days - return shap_del_days*daysec # seconds -end - -@doc raw""" - shapiro_doppler(e, de, p, dp, q, dq, F_tx) - -Return the Doppler shift (in units of `F_tx`) -```math -\Delta\nu = -\nu\frac{d\Delta\tau}{dt}, -``` -where ``\nu`` is the frequency and ``\frac{d\Delta\tau}{dt}`` is the differential of the -Shapiro delay. See also [`shapiro_delay`](@ref). - -See https://doi.org/10.1103/PhysRevLett.17.933. - -# Arguments - -- `e`: heliocentric distance of the Earth. -- `de`: differential of `e`. -- `p`: asteroid's heliocentric distance. -- `dp`: differential of `p`. -- `q`: asteroid's geocentric distance. -- `dq`: differential of `q`. -- `F_tx`: transmitter frequency (MHz). -""" -function shapiro_doppler(e, de, p, dp, q, dq, F_tx) - # shap_del_diff = 2μ[1]*( (de+dp+dq)/(e+p+q) - (de+dp-dq)/(e+p-q) )/(c_au_per_day^3) # (adim.) - shap_del_diff = (4μ_DE430[su]/(c_au_per_day^3))*( ( dq*(e+p) - q*(de+dp) )/( (e+p)^2 - q^2 ) ) # differential of Shapiro delay (adim.) - # ν = -F_tx*dτ/dt (units of F_tx) - # See footnote 10 of https://doi.org/10.1103/PhysRevLett.17.933 - shap_dop = -F_tx*shap_del_diff - return shap_dop # (units of F_tx) -end - -@doc raw""" - Ne(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}, ds::U, ΔS::Real) where {S<:Number, U<:Number} - -Return the density of ionized electrons (in electrons/cm^3) in interplanetary medium -```math -N_e = \frac{A}{r^6} + \frac{ab/\sqrt{a^2\sin^2\beta + b^2\cos^2\beta}}{r^2}, -``` -where ``r`` is the heliocentric distance expressed in units of the solar radius, ``\beta`` is -the solar latitude, and ``A``, ``a``, ``b`` are the solar corona parameters. - -See (Explanatory Supplement to the Astronomical Almanac 2014, p. 323, Sec. 8.7.5, Eq. 8.22). -ESAA 2014 in turn refers to Muhleman and Anderson (1981). Ostro (1993) gives a reference to -Anderson (1978), where this model is fitted to Mariner 9 ranging data. Reading https://gssc.esa.int/navipedia/index.php/Ionospheric_Delay -helped a lot to clarify things, especially the 40.3, although they talk about Earth's -ionosphere. Another valuable source is Standish, E.M., Astron. Astrophys. 233, 252-271 (1990). - -# Arguments -- `p1::Vector{S}`: signal departure point (transmitter/bounce) (au). -- `p2::Vector{S}`: signal arrival point (bounce/receiver) (au). -- `r_s_t0::Vector{S}`: Barycentric position (au) of Sun at initial time of propagation of signal path (bounce time for down-leg; transmit time for up-leg). -- `ds::U`: current distance travelled by ray from emission point (au). -- `ΔS::Real`: total distance between p1 and p2 (au). -""" -function Ne(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}, ds::U, ΔS::Real) where {S<:Number, U<:Number} - # s: linear parametrization of ray path, such that - # s = 0 -> point on ray path is at p1; s = 1 -> point on ray path is at p2 - s = ds/ΔS - # Rescale Taylor polynomial - s_p2_p1 = map(x->s*x, Taylor1.(p2-p1, s.order)) - # Heliocentric position (au) of point on ray path at time t_tdb_jul (Julian days) - r_vec = Taylor1.(p1, s.order) + s_p2_p1 - Taylor1.(r_s_t0, s.order) - # Heliocentric distance (au) of point on ray path at time t_tdb_jul (Julian days) - r = sqrt( r_vec[1]^2 + r_vec[2]^2 + r_vec[3]^2 ) - # Compute heliocentric position vector of point on ray path wrt Sun's rotation pole - # and equator (i.e., heliographic) - α_p_sun_rad = deg2rad(α_p_sun) - δ_p_sun_rad = deg2rad(δ_p_sun) - r_vec_heliographic = inv( pole_rotation(α_p_sun_rad, δ_p_sun_rad) )*r_vec - # Compute heliographic solar latitude (Anderson, 1978) of point on ray path - β = asin( r_vec_heliographic[3]/r ) # Ecliptic solar latitude of point on ray path (rad) - # Heliocentric distance - r_sr = r/R_sun - # First term of Ne - Ne_t1 = (A_sun/r_sr^6) - # Second term of Ne - Ne_t2 = ( (a_sun*b_sun)/sqrt((a_sun*sin(β))^2 + (b_sun*cos(β))^2) )/(r_sr^2) - # Density of ionized electrons - Ne_val = Ne_t1 + Ne_t2 - return Ne_val -end - -# TODO: @taylorize! -@doc raw""" - Ne_path_integral(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}) where {S<:Number} - -Return the path integral of the density of ionized electrons in interplanetary medium ``N_e`` -in units of electrons/cm^2, evaluated with `TaylorIntegration`. - -# Arguments - -- `p1::Vector{S}`: signal departure point (transmitter/bounce) (au). -- `p2::Vector{S}`: signal arrival point (bounce/receiver) (au). -- `r_s_t0::Vector{S}`: Barycentric position (au) of Sun at initial time of propagation of signal path (bounce time for down-leg; transmit time for up-leg). -""" -function Ne_path_integral(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}) where {S<:Number} - # Total distance between p1 and p2, in centimeters - ΔS = (100_000au)*norm(p2-p1) - # Kernel of path integral; distance parameter `s` and total distance `ΔS` is in cm - function int_kernel(x, params, s) - return Ne(p1, p2, r_s_t0, s, ΔS) - end - # Do path integral - - # Initial condition - i0 = zero(p1[1]) - iT = Taylor1(i0, 24) - # Independent variable - tT = Taylor1(24) - # Integration - TaylorIntegration.jetcoeffs!(int_kernel, tT, iT, nothing) - # Evaluate path integral in total distance ΔS - return iT(ΔS) -end - -@doc raw""" - corona_delay(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}, F_tx::U) where {S<:Number, U<:Real} - -Return the time-delay (in sec) due to thin plasma of solar corona -```math -\Delta\tau_\text{cor} = \frac{40.3}{cf^2}\int_{P_1}^{P_2}N_e \ ds, -```math -where ``c`` is the speed of light (cm/sec), ``f`` is the frequency (Hz), ``N_e`` is the density -of ionized electrons in interplanetary medium (electrons/cm^3), and ``s`` is the linear -distance (cm). ``N_e`` is computed by [`Ne`](@ref) and integrated via `TaylorIntegration` in -[`Ne_path_integral`](@ref). - -From [Ionospheric Delay](https://gssc.esa.int/navipedia/index.php/Ionospheric_Delay) it seems -that ESAA 2014 text probably should say that in the formula for ``\Delta\tau_\text{cor}``, -the expression ``40.3 N_e/f^2`` is adimensional, where ``Ne`` is in electrons/cm^3 and ``f`` is -in Hz therefore, the integral ``(40.3/f^2)\int Ne \ ds`` is in centimeters, where ``ds`` is in -cm and the expression ``(40.3/(cf^2))\int Ne \ ds``, with ``c`` in cm/sec, is in seconds. - -# Arguments - -- `p1::Vector{S}`: signal departure point (transmitter/bounce for up/down-link, resp.) (au). -- `p2::Vector{S}`: signal arrival point (bounce/receiver for up/down-link, resp.) (au). -- `r_s_t0::Vector{S}`: Barycentric position (au) of Sun at initial time of propagation of signal path (bounce time for down-leg; transmit time for up-leg). -- `F_tx::U`: transmitter frequency (MHz). -""" -function corona_delay(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}, F_tx::U) where {S<:Number, U<:Real} - # For the time being, we're removing the terms associated with higher-order terms in the - # variationals (ie, Yarkovsky) - int_path = Ne_path_integral(p1, p2, r_s_t0) # (electrons/cm^2) - # Time delay due to solar corona - Δτ_corona = 40.3e-6int_path/(c_cm_per_sec*(F_tx)^2) # seconds - return Δτ_corona # seconds -end - -@doc raw""" - zenith_distance(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Number, S<:Number} - -**VERY** elementary computation of zenith distance. - -# Arguments - -- `r_antenna::Vector{T}`: position of antenna at receive/transmit time in celestial frame wrt geocenter. -- `ρ_vec_ae::Vector{S}`: slant-range vector from antenna to asteroid. -""" -function zenith_distance(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Number, S<:Number} - # Magnitude of geocentric antenna position - norm_r_antenna = sqrt(r_antenna[1]^2 + r_antenna[2]^2 + r_antenna[3]^2) - # Magnitude of slant-range vector from antenna to asteroid - norm_ρ_vec_ae = sqrt(ρ_vec_ae[1]^2 + ρ_vec_ae[2]^2 + ρ_vec_ae[3]^2) - # cos( angle between r_antenna and ρ_vec_ae) - cos_antenna_slant = dot(r_antenna, ρ_vec_ae)/(norm_r_antenna*norm_ρ_vec_ae) - # zenith distance - return acos(cos_antenna_slant) -end - -@doc raw""" - tropo_delay(z) - -Return the time delay (in sec) due to Earth's troposphere for radio frequencies -```math -\Delta\tau_\text{tropo} = \frac{7 \ \text{nsec}}{\cos z + \frac{0.0014}{0.045 + \cot z}}, -``` -where ``z`` is the zenith distance at the antenna. This time delay oscillates between -0.007``\mu``s and 0.225``\mu``s for ``z`` between 0 and ``\pi/2`` rad. - -See also [`zenith_distance`](@doc). - -# Arguments - -- `z`: zenith distance (radians). -""" -tropo_delay(z) = (7e-9)/( cos(z) + 0.0014/(0.045+cot(z)) ) # seconds - -@doc raw""" - tropo_delay(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Number, S<:Number} - -Return the time delay (in sec) due to Earth's troposphere for radio frequencies. The function -first computes the zenith distance ``z`` via [`zenith_distance`](@ref) and then substitutes -into the first method of [`tropo_delay`](@ref). - -# Arguments - -- `r_antenna::Vector{T}`: position of antenna at receive/transmit time in celestial frame wrt geocenter. -- `ρ_vec_ae::Vector{S}`: slant-range vector from antenna to asteroid. -""" -function tropo_delay(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Number, S<:Number} - # zenith distance - zd = zenith_distance(r_antenna, ρ_vec_ae) # rad - # Time delay due to Earth's troposphere - return tropo_delay(zd) # seconds -end - -@doc raw""" - compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; tord::Int = 5, niter::Int = 10, - xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} - -Compute Taylor series expansion of time-delay observable around echo reception time. This -allows to compute dopplers via automatic differentiation using -```math -\nu = -f\frac{d\tau}{dt}, -``` -where ``f`` is the transmitter frequency (MHz) and ``\tau`` is the time-delay at reception -time ``t``. Computed values include corrections due to Earth orientation, LOD and polar -motion. - -See https://doi.org/10.1086/116062. - -**Note:** Works only with `TaylorInterpolant` ephemeris. See [`PlanetaryEphemeris.TaylorInterpolant`](@ref). - -# Arguments - -- `observatory::ObservatoryMPC{T}`: observing station. -- `t_r_utc::DateTime`: UTC time of echo reception. -- `tord::Int`: order of Taylor expansions. -- `niter::Int`: number of light-time solution iterations. -- `xve::TaylorInterpolant`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xvs::TaylorInterpolant`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xva::TaylorInterpolant`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -""" -function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; tord::Int = 5, niter::Int = 10, - xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} - - # Transform receiving time from UTC to TDB seconds since j2000 - et_r_secs_0 = datetime2et(t_r_utc) - # Auxiliary to evaluate JT ephemeris - xva1et0 = xva(et_r_secs_0)[1] - # et_r_secs_0 as a Taylor polynomial - et_r_secs = Taylor1([et_r_secs_0,one(et_r_secs_0)].*one(xva1et0), tord) - # Compute geocentric position/velocity of receiving antenna in inertial frame (km, km/sec) - RV_r = obsposvelECI(observatory, et_r_secs) - R_r = RV_r[1:3] - # Earth's barycentric position and velocity at receive time - r_e_t_r = xve(et_r_secs)[1:3] - # Receiver barycentric position and velocity at receive time - r_r_t_r = r_e_t_r + R_r - # Asteroid barycentric position and velocity at receive time - r_a_t_r = xva(et_r_secs)[1:3] - # Sun barycentric position and velocity at receive time - r_s_t_r = xvs(et_r_secs)[1:3] - - # Down-leg iteration - # τ_D first approximation - # See equation (1) of https://doi.org/10.1086/116062 - ρ_vec_r = r_a_t_r - r_r_t_r - ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) - # -R_b/c, but delay is wrt asteroid Center (Brozovic et al., 2018) - τ_D = ρ_r/clightkms # (seconds) - # Bounce time, new estimate - # See equation (2) of https://doi.org/10.1086/116062 - et_b_secs = et_r_secs - τ_D - - # Allocate memmory for time delays - Δτ_D = zero(τ_D) # Total time delay - Δτ_rel_D = zero(τ_D) # Shapiro delay - # Δτ_corona_D = zero(τ_D) # Delay due to Solar corona - Δτ_tropo_D = zero(τ_D) # Delay due to Earth's troposphere - - for i in 1:niter - # Asteroid barycentric position (in au) at bounce time (TDB) - rv_a_t_b = xva(et_b_secs) - r_a_t_b = rv_a_t_b[1:3] - v_a_t_b = rv_a_t_b[4:6] - # Estimated position of the asteroid's center of mass relative to the recieve point - # See equation (3) of https://doi.org/10.1086/116062. - ρ_vec_r = r_a_t_b - r_r_t_r - # Magnitude of ρ_vec_r - # See equation (4) of https://doi.org/10.1086/116062. - ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) - - # Compute down-leg Shapiro delay - # NOTE: when using PPN, substitute 2 -> 1+γ in expressions for Shapiro delay, - # Δτ_rel_[D|U] - - # Earth's position at t_r - e_D_vec = r_r_t_r - r_s_t_r - # Heliocentric distance of Earth at t_r - e_D = sqrt(e_D_vec[1]^2 + e_D_vec[2]^2 + e_D_vec[3]^2) - # Barycentric position of Sun at estimated bounce time - r_s_t_b = xvs(et_b_secs)[1:3] - # Heliocentric position of asteroid at t_b - p_D_vec = r_a_t_b - r_s_t_b - # Heliocentric distance of asteroid at t_b - p_D = sqrt(p_D_vec[1]^2 + p_D_vec[2]^2 + p_D_vec[3]^2) - # Signal path distance (down-leg) - q_D = ρ_r - - # Shapiro correction to time-delay - Δτ_rel_D = shapiro_delay(e_D, p_D, q_D) # seconds - # Troposphere correction to time-delay - Δτ_tropo_D = tropo_delay(R_r, ρ_vec_r) # seconds - # Solar corona correction to time-delay - # Δτ_corona_D = corona_delay(constant_term.(r_a_t_b), r_r_t_r, r_s_t_r, F_tx, station_code) # seconds - # Total time-delay - Δτ_D = Δτ_rel_D # + Δτ_tropo_D #+ Δτ_corona_D # seconds - - # New estimate - p_dot_23 = dot(ρ_vec_r, v_a_t_b)/ρ_r - # Time delay correction - Δt_2 = (τ_D - ρ_r/clightkms - Δτ_rel_D)/(1.0-p_dot_23/clightkms) - # Time delay new estimate - τ_D = τ_D - Δt_2 - # Bounce time, new estimate - # See equation (2) of https://doi.org/10.1086/116062 - et_b_secs = et_r_secs - τ_D - - end - - # Asteroid's barycentric position and velocity at bounce time t_b - rv_a_t_b = xva(et_b_secs) - r_a_t_b = rv_a_t_b[1:3] - v_a_t_b = rv_a_t_b[4:6] - - # Up-leg iteration - # τ_U first estimation - # See equation (5) of https://doi.org/10.1086/116062 - τ_U = τ_D - # Transmit time, 1st estimate - # See equation (6) of https://doi.org/10.1086/116062 - et_t_secs = et_b_secs - τ_U - # Geocentric position and velocity of transmitting antenna in inertial frame (km, km/sec) - RV_t = RV_r(et_t_secs-et_r_secs_0) - R_t = RV_t[1:3] - V_t = RV_t[4:6] - # Barycentric position and velocity of the Earth at transmit time - rv_e_t_t = xve(et_t_secs) - r_e_t_t = rv_e_t_t[1:3] - v_e_t_t = rv_e_t_t[4:6] - # Transmitter barycentric position and velocity of at transmit time - r_t_t_t = r_e_t_t + R_t - # Up-leg vector at transmit time - # See equation (7) of https://doi.org/10.1086/116062 - ρ_vec_t = r_a_t_b - r_t_t_t - # Magnitude of up-leg vector - ρ_t = sqrt(ρ_vec_t[1]^2 + ρ_vec_t[2]^2 + ρ_vec_t[3]^2) - - # Allocate memmory for time delays - Δτ_U = zero(τ_U) # Total time delay - Δτ_rel_U = zero(τ_U) # Shapiro delay - # Δτ_corona_U = zero(τ_U) # Delay due to Solar corona - Δτ_tropo_U = zero(τ_U) # Delay due to Earth's troposphere - - for i in 1:niter - # Geocentric position and velocity of transmitting antenna in inertial frame (km, km/sec) - RV_t = RV_r(et_t_secs-et_r_secs_0) - R_t = RV_t[1:3] - V_t = RV_t[4:6] - # Earth's barycentric position and velocity at transmit time - rv_e_t_t = xve(et_t_secs) - r_e_t_t = rv_e_t_t[1:3] - v_e_t_t = rv_e_t_t[4:6] - # Barycentric position and velocity of the transmitter at the transmit time - r_t_t_t = r_e_t_t + R_t - v_t_t_t = v_e_t_t + V_t - # Up-leg vector and its magnitude at transmit time - # See equation (7) of https://doi.org/10.1086/116062 - ρ_vec_t = r_a_t_b - r_t_t_t - ρ_t = sqrt(ρ_vec_t[1]^2 + ρ_vec_t[2]^2 + ρ_vec_t[3]^2) - - - # Compute up-leg Shapiro delay - - # Sun barycentric position and velocity (in km, km/sec) at transmit time (TDB) - r_s_t_t = xvs(et_t_secs)[1:3] - # Heliocentric position of Earth at t_t - e_U_vec = r_t_t_t - r_s_t_t - # Heliocentric distance of Earth at t_t - e_U = sqrt(e_U_vec[1]^2 + e_U_vec[2]^2 + e_U_vec[3]^2) - # Barycentric position/velocity of Sun at bounce time - r_s_t_b = xvs(et_b_secs)[1:3] - # Heliocentric position of asteroid at t_b - p_U_vec = r_a_t_b - r_s_t_b - # Heliocentric distance of asteroid at t_b - p_U = sqrt(p_U_vec[1]^2 + p_U_vec[2]^2 + p_U_vec[3]^2) - # Signal path distance (up-leg) - q_U = ρ_t - - # Shapiro correction to time-delay - Δτ_rel_U = shapiro_delay(e_U, p_U, q_U) # seconds - # Troposphere correction to time-delay - Δτ_tropo_U = tropo_delay(R_t, ρ_vec_t) # seconds - # Delay due to Solar corona - # Δτ_corona_U = corona_delay(constant_term.(r_t_t_t), constant_term.(r_a_t_b), constant_term.(r_s_t_b), F_tx, station_code) # seconds - # Total time delay - Δτ_U = Δτ_rel_U # + Δτ_tropo_U #+ Δτ_corona_U # seconds - - # New estimate - p_dot_12 = -dot(ρ_vec_t, v_t_t_t)/ρ_t - # Time-delay correction - Δt_1 = (τ_U - ρ_t/clightkms - Δτ_rel_U)/(1.0-p_dot_12/clightkms) - # Time delay new estimate - τ_U = τ_U - Δt_1 - # Transmit time, new estimate - # See equation (6) of https://doi.org/10.1086/116062 - et_t_secs = et_b_secs - τ_U - end - - # Compute TDB-UTC at transmit time - # Corrections to TT-TDB from Moyer (2003) / Folkner et al. (2014) due to position - # of measurement station on Earth are of order 0.01μs - # Δtt_tdb_station_t = - dot(v_e_t_t, r_t_t_t-r_e_t_t)/clightkms^2 - tdb_utc_t = tdb_utc(et_t_secs) # + Δtt_tdb_station_t - - # Compute TDB-UTC at receive time - # Corrections to TT-TDB from Moyer (2003) / Folkner et al. (2014) due to position - # of measurement station on Earth are of order 0.01μs - # Δtt_tdb_station_r = - dot(v_e_t_r, r_r_t_r-r_e_t_r)/clightkms^2 - tdb_utc_r = tdb_utc(et_r_secs) # + Δtt_tdb_station_r - - # Compute total time delay (UTC seconds); relativistic delay is already included in τ_D, τ_U - # See equation (9) of https://doi.org/10.1086/116062 - τ = (τ_D + τ_U) + (Δτ_tropo_D + Δτ_tropo_U) + (tdb_utc_t - tdb_utc_r) # seconds - - # Total signal delay (μs) - return 1e6τ -end - -@doc raw""" - radar_astrometry(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real; tord::Int = 5, niter::Int = 10, tc::Real = 1.0, - xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph, autodiff::Bool = true) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} - radar_astrometry(radar::RadarJPL{T}; tord::Int = 5, niter::Int = 10, tc::Real = 1.0, xve::EarthEph = earthposvel, - xvs::SunEph = sunposvel, xva::AstEph, autodiff::Bool = true) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} - radar_astrometry(astradarfile::String; tord::Int = 5, niter::Int = 10, tc::Real = 1.0, xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, - xva::AstEph, autodiff::Bool = true) where {EarthEph, SunEph, AstEph} - radar_astrometry(astradardata::Vector{RadarJPL}; tord::Int = 5, niter::Int = 10, tc::Real = 1.0, - xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph, autodiff::Bool = true) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} - -Return time-delay and Doppler shift. - -# Arguments - -- `observatory::ObservatoryMPC{T}`: observing station. -- `t_r_utc::DateTime`: UTC time of echo reception. -- `radar::RadarJPL{T}`: radar observation. -- `astradarfile/radarobsfile::String`: file where to retrieve radar observations. -- `outfilename::String`: file where to save radar observations. -- `F_tx::Real`: transmitter frequency (MHz). -- `niter::Int`: number of light-time solution iterations. -- `tc::Real`: time offset wrt echo reception time, to compute Doppler shifts by range differences (seconds). Offsets will be rounded to the nearest millisecond. -- `xve`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xvs`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xva`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `asteph::TaylorInterpolant`: asteroid's ephemeris. -- `ss16asteph::TaylorInterpolant`: Solar System ephemeris. -- `autodiff::Bool`: whether to compute Doppler shift via automatic diff of [`compute_delay`](@ref) or not. -- `tord::Int`: order of Taylor expansions. -""" -function radar_astrometry(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real; tc::Real = 1.0, autodiff::Bool=true, kwargs...) where {T <: AbstractFloat} - # Compute Doppler shift via automatic differentiation of time-delay - if autodiff - # Time delay - τ = compute_delay(observatory, t_r_utc; kwargs...) - # Time delay, Doppler shift - return τ[0], -F_tx*τ[1] - # Compute Doppler shift via numerical differentiation of time-delay - else - offset = Dates.Millisecond(1000round(tc/2, digits=3)) - τe = compute_delay(observatory, t_r_utc+offset; kwargs...) - τn = compute_delay(observatory, t_r_utc ; kwargs...) - τs = compute_delay(observatory, t_r_utc-offset; kwargs...) - # Time delay, Doppler shift - return τn[0], -F_tx*((τe[0]-τs[0])/tc) - end - -end - -function radar_astrometry(radar::RadarJPL{T}; kwargs...) where {T <: AbstractFloat} - return radar_astrometry(radar.rcvr, radar.date, radar.freq; kwargs...) -end - -function radar_astrometry(astradarfile::String; kwargs...) - # Check that astradarfile is a file - @assert isfile(astradarfile) "Cannot open file: $astradarfile" - # Read radar measurements - astradardata = read_radar_jpl(astradarfile) - return radar_astrometry(astradardata; kwargs...) -end - -function radar_astrometry(astradardata::Vector{RadarJPL{T}}; xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} - - # UTC time of first radar observation - utc1 = astradardata[1].date - # TDB seconds since J2000.0 for first astrometric observation - et1 = datetime2et(utc1) - # Asteroid ephemeris at et1 - a1_et1 = xva(et1)[1] - # Type of asteroid ephemeris - S = typeof(a1_et1) - - # Time delays - vdelay = Array{S}(undef, length(astradardata)) - # Doppler shifts - vdoppler = Array{S}(undef, length(astradardata)) - - # Iterate over the measurements - Threads.@threads for i in eachindex(astradardata) - # Compute time delay and doppler shift - vdelay[i], vdoppler[i] = radar_astrometry(astradardata[i]; xva, kwargs...) - end - # Rows with time delays - delay_index = map(x-> x.Δτ_units == "us", astradardata) - # Rows with Doppler shifts - doppler_index = map(x -> x.Δν_units == "Hz", astradardata) - - dt_utc_obs = date.(astradardata) # UTC time - Δτ_obs = delay.(astradardata) # Observed time delay - Δν_obs = doppler.(astradardata) # Observed Doppler shift - Δτ_σ = delay_sigma.(astradardata) # Observed time delay uncertainty - Δν_σ = doppler_sigma.(astradardata) # Observed Doppler shift uncertainty - τ_units = delay_units.(astradardata) # Time delay units - ν_units = doppler_units.(astradardata) # Doppler shift units - freq_ = freq.(astradardata) # Frequency - rcvr_ = rcvr.(astradardata) # Receiver antenna - xmit_ = xmit.(astradardata) # Emission antenna - bouncepoint_ = bouncepoint.(astradardata) # Bounce point - - # Return time delays / Doppler shifts table - return dt_utc_obs, Δτ_obs, Δν_obs, vdelay, vdoppler, Δτ_σ, Δν_σ, τ_units, ν_units, freq_, rcvr_, xmit_, bouncepoint_, delay_index, - doppler_index -end - -@doc raw""" - residuals(obs::Vector{RadarJPL{T}}, niter::Int = 10; debias_table::String = "2018", - xvs = sunposvel, xve = earthposvel, xva) where {T <: AbstractFloat} - -Compute O-C residuals for radar astrometry, including corrections due to Earth orientation, -LOD and polar motion. - -See also [`compute_delay`](@ref) and [`radar_astrometry`](@ref). - -# Arguments - -- `obs::Vector{RadarJPL{T}}`: vector of observations. -- `niter::Int`: number of light-time solution iterations. -- `tc::Real`: time offset wrt echo reception time, to compute Doppler shifts by range differences (seconds). -- `autodiff::Bool`: whether to use the automatic differentiation method of [`compute_delay`](@ref) or not. -- `tord::Int`: order of Taylor expansions. -- `xvs::`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xve::`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xva::`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -""" -function residuals(obs::Vector{RadarJPL{T}}; kwargs...) where {T <: AbstractFloat} - # Radar delay/Doppler astrometric data - x_jt = radar_astrometry(obs; kwargs...) - # Time-delay residuals - res_τ = x_jt[2][x_jt[14]] .- x_jt[4][x_jt[14]] - # Doppler-shift residuals - res_ν = x_jt[3][x_jt[15]] .- x_jt[5][x_jt[15]] - # Weights - w_τ = 1 ./ (x_jt[6][x_jt[14]].^2) - w_ν = 1 ./ (x_jt[7][x_jt[15]].^2) - - return res_τ, w_τ, res_ν, w_ν -end +include("catalogue_mpc.jl") +include("observatory_mpc.jl") +include("radec_mpc.jl") +include("radar_jpl.jl") +include("units.jl") +include("jpl_eph.jl") +include("topocentric.jl") +include("process_radec.jl") + +@doc raw""" + shapiro_delay(e, p, q) + +Return the relativistic (Shapiro) time-delay in seconds +```math +\Delta\tau[\text{rel}] = \frac{2\mu_\odot}{c^3}\log\left|\frac{d_{E,S} + d_{A,S} + d_{A,E}}{d_{E,S}+d_{A,S}-d_{A, E}}\right|, +``` +where ``\mu_\odot = GM_\odot`` is the gravitational parameter of the sun, and ``d_{E,S}``, ``d_{A,S}`` +and ``d_{A,E}`` are the heliocentric distance of the Earth, the asteroid's heliocentric +distance, and the asteroid's geocentric distance, respectively. + +# Arguments + +- `e`: heliocentric distance of the Earth. +- `p`: asteroid's heliocentric distance. +- `q`: asteroid's geocentric distance. + +!!! reference + See https://doi.org/10.1103/PhysRevLett.13.789. +""" +function shapiro_delay(e, p, q) + shap = 0.0 # 2μ[1]/(c_au_per_day^2) + shap_del_days = (2μ_DE430[su]/(c_au_per_day^3))*log( (e+p+q+shap)/(e+p-q+shap) ) # days + return shap_del_days*daysec # seconds +end + +@doc raw""" + shapiro_doppler(e, de, p, dp, q, dq, F_tx) + +Return the Doppler shift (in units of `F_tx`) +```math +\Delta\nu = -\nu\frac{d\Delta\tau}{dt}, +``` +where ``\nu`` is the frequency and ``\frac{d\Delta\tau}{dt}`` is the differential of the +Shapiro delay. See also [`shapiro_delay`](@ref). + +# Arguments + +- `e`: heliocentric distance of the Earth. +- `de`: differential of `e`. +- `p`: asteroid's heliocentric distance. +- `dp`: differential of `p`. +- `q`: asteroid's geocentric distance. +- `dq`: differential of `q`. +- `F_tx`: transmitter frequency (MHz). + +!!! reference + See https://doi.org/10.1103/PhysRevLett.17.933. +""" +function shapiro_doppler(e, de, p, dp, q, dq, F_tx) + # shap_del_diff = 2μ[1]*( (de+dp+dq)/(e+p+q) - (de+dp-dq)/(e+p-q) )/(c_au_per_day^3) # (adim.) + shap_del_diff = (4μ_DE430[su]/(c_au_per_day^3))*( ( dq*(e+p) - q*(de+dp) )/( (e+p)^2 - q^2 ) ) # differential of Shapiro delay (adim.) + # ν = -F_tx*dτ/dt (units of F_tx) + # See footnote 10 of https://doi.org/10.1103/PhysRevLett.17.933 + shap_dop = -F_tx*shap_del_diff + return shap_dop # (units of F_tx) +end + +@doc raw""" + Ne(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}, ds::U, ΔS::Real) where {S<:Number, U<:Number} + +Return the density of ionized electrons (in electrons/cm^3) in interplanetary medium +```math +N_e = \frac{A}{r^6} + \frac{ab/\sqrt{a^2\sin^2\beta + b^2\cos^2\beta}}{r^2}, +``` +where ``r`` is the heliocentric distance expressed in units of the solar radius, ``\beta`` is +the solar latitude, and ``A``, ``a``, ``b`` are the solar corona parameters. + +# Arguments +- `p1::Vector{S}`: signal departure point (transmitter/bounce) (au). +- `p2::Vector{S}`: signal arrival point (bounce/receiver) (au). +- `r_s_t0::Vector{S}`: Barycentric position (au) of Sun at initial time of propagation of signal path (bounce time for down-leg; transmit time for up-leg). +- `ds::U`: current distance travelled by ray from emission point (au). +- `ΔS::Real`: total distance between p1 and p2 (au). + +!!! reference + See (Explanatory Supplement to the Astronomical Almanac 2014, p. 323, Sec. 8.7.5, Eq. 8.22). + ESAA 2014 in turn refers to Muhleman and Anderson (1981). Ostro (1993) gives a reference to + Anderson (1978), where this model is fitted to Mariner 9 ranging data. Reading + https://gssc.esa.int/navipedia/index.php/Ionospheric_Delay helped a lot to clarify things, + especially the 40.3, although they talk about Earth's ionosphere. Another valuable source is + Standish, E.M., Astron. Astrophys. 233, 252-271 (1990). +""" +function Ne(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}, ds::U, ΔS::Real) where {S<:Number, U<:Number} + # s: linear parametrization of ray path, such that + # s = 0 -> point on ray path is at p1; s = 1 -> point on ray path is at p2 + s = ds/ΔS + # Rescale Taylor polynomial + s_p2_p1 = map(x->s*x, Taylor1.(p2-p1, s.order)) + # Heliocentric position (au) of point on ray path at time t_tdb_jul (Julian days) + r_vec = Taylor1.(p1, s.order) + s_p2_p1 - Taylor1.(r_s_t0, s.order) + # Heliocentric distance (au) of point on ray path at time t_tdb_jul (Julian days) + r = sqrt( r_vec[1]^2 + r_vec[2]^2 + r_vec[3]^2 ) + # Compute heliocentric position vector of point on ray path wrt Sun's rotation pole + # and equator (i.e., heliographic) + α_p_sun_rad = deg2rad(α_p_sun) + δ_p_sun_rad = deg2rad(δ_p_sun) + r_vec_heliographic = inv( pole_rotation(α_p_sun_rad, δ_p_sun_rad) )*r_vec + # Compute heliographic solar latitude (Anderson, 1978) of point on ray path + β = asin( r_vec_heliographic[3]/r ) # Ecliptic solar latitude of point on ray path (rad) + # Heliocentric distance + r_sr = r/R_sun + # First term of Ne + Ne_t1 = (A_sun/r_sr^6) + # Second term of Ne + Ne_t2 = ( (a_sun*b_sun)/sqrt((a_sun*sin(β))^2 + (b_sun*cos(β))^2) )/(r_sr^2) + # Density of ionized electrons + Ne_val = Ne_t1 + Ne_t2 + return Ne_val +end + +# TODO: @taylorize! +@doc raw""" + Ne_path_integral(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}) where {S<:Number} + +Return the path integral of the density of ionized electrons in interplanetary medium ``N_e`` +in units of electrons/cm^2, evaluated with `TaylorIntegration`. + +# Arguments + +- `p1::Vector{S}`: signal departure point (transmitter/bounce) (au). +- `p2::Vector{S}`: signal arrival point (bounce/receiver) (au). +- `r_s_t0::Vector{S}`: Barycentric position (au) of Sun at initial time of propagation of signal path (bounce time for down-leg; transmit time for up-leg). +""" +function Ne_path_integral(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}) where {S<:Number} + # Total distance between p1 and p2, in centimeters + ΔS = (100_000au)*norm(p2-p1) + # Kernel of path integral; distance parameter `s` and total distance `ΔS` is in cm + function int_kernel(x, params, s) + return Ne(p1, p2, r_s_t0, s, ΔS) + end + # Do path integral + + # Initial condition + i0 = zero(p1[1]) + iT = Taylor1(i0, 24) + # Independent variable + tT = Taylor1(24) + # Integration + TaylorIntegration.jetcoeffs!(int_kernel, tT, iT, nothing) + # Evaluate path integral in total distance ΔS + return iT(ΔS) +end + +@doc raw""" + corona_delay(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}, F_tx::U) where {S<:Number, U<:Real} + +Return the time-delay (in sec) due to thin plasma of solar corona +```math +\Delta\tau_\text{cor} = \frac{40.3}{cf^2}\int_{P_1}^{P_2}N_e \ ds, +```math +where ``c`` is the speed of light (cm/sec), ``f`` is the frequency (Hz), ``N_e`` is the density +of ionized electrons in interplanetary medium (electrons/cm^3), and ``s`` is the linear +distance (cm). ``N_e`` is computed by [`Ne`](@ref) and integrated via `TaylorIntegration` in +[`Ne_path_integral`](@ref). + +# Arguments + +- `p1::Vector{S}`: signal departure point (transmitter/bounce for up/down-link, resp.) (au). +- `p2::Vector{S}`: signal arrival point (bounce/receiver for up/down-link, resp.) (au). +- `r_s_t0::Vector{S}`: Barycentric position (au) of Sun at initial time of propagation of signal path (bounce time for down-leg; transmit time for up-leg). +- `F_tx::U`: transmitter frequency (MHz). + +!!! reference + From [Ionospheric Delay](https://gssc.esa.int/navipedia/index.php/Ionospheric_Delay) it seems + that ESAA 2014 text probably should say that in the formula for ``\Delta\tau_\text{cor}``, + the expression ``40.3 N_e/f^2`` is adimensional, where ``Ne`` is in electrons/cm^3 and ``f`` is + in Hz therefore, the integral ``(40.3/f^2)\int Ne \ ds`` is in centimeters, where ``ds`` is in + cm and the expression ``(40.3/(cf^2))\int Ne \ ds``, with ``c`` in cm/sec, is in seconds. +""" +function corona_delay(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}, F_tx::U) where {S<:Number, U<:Real} + # For the time being, we're removing the terms associated with higher-order terms in the + # variationals (ie, Yarkovsky) + int_path = Ne_path_integral(p1, p2, r_s_t0) # (electrons/cm^2) + # Time delay due to solar corona + Δτ_corona = 40.3e-6int_path/(c_cm_per_sec*(F_tx)^2) # seconds + return Δτ_corona # seconds +end + +@doc raw""" + zenith_distance(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Number, S<:Number} + +**VERY** elementary computation of zenith distance. + +# Arguments + +- `r_antenna::Vector{T}`: position of antenna at receive/transmit time in celestial frame wrt geocenter. +- `ρ_vec_ae::Vector{S}`: slant-range vector from antenna to asteroid. +""" +function zenith_distance(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Number, S<:Number} + # Magnitude of geocentric antenna position + norm_r_antenna = sqrt(r_antenna[1]^2 + r_antenna[2]^2 + r_antenna[3]^2) + # Magnitude of slant-range vector from antenna to asteroid + norm_ρ_vec_ae = sqrt(ρ_vec_ae[1]^2 + ρ_vec_ae[2]^2 + ρ_vec_ae[3]^2) + # cos( angle between r_antenna and ρ_vec_ae) + cos_antenna_slant = dot(r_antenna, ρ_vec_ae)/(norm_r_antenna*norm_ρ_vec_ae) + # zenith distance + return acos(cos_antenna_slant) +end + +@doc raw""" + tropo_delay(z) + +Return the time delay (in sec) due to Earth's troposphere for radio frequencies +```math +\Delta\tau_\text{tropo} = \frac{7 \ \text{nsec}}{\cos z + \frac{0.0014}{0.045 + \cot z}}, +``` +where ``z`` is the zenith distance at the antenna. This time delay oscillates between +0.007``\mu``s and 0.225``\mu``s for ``z`` between 0 and ``\pi/2`` rad. + +See also [`zenith_distance`](@doc). + +# Arguments + +- `z`: zenith distance (radians). +""" +tropo_delay(z) = (7e-9)/( cos(z) + 0.0014/(0.045+cot(z)) ) # seconds + +@doc raw""" + tropo_delay(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Number, S<:Number} + +Return the time delay (in sec) due to Earth's troposphere for radio frequencies. The function +first computes the zenith distance ``z`` via [`zenith_distance`](@ref) and then substitutes +into the first method of [`tropo_delay`](@ref). + +# Arguments + +- `r_antenna::Vector{T}`: position of antenna at receive/transmit time in celestial frame wrt geocenter. +- `ρ_vec_ae::Vector{S}`: slant-range vector from antenna to asteroid. +""" +function tropo_delay(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Number, S<:Number} + # zenith distance + zd = zenith_distance(r_antenna, ρ_vec_ae) # rad + # Time delay due to Earth's troposphere + return tropo_delay(zd) # seconds +end + +@doc raw""" + compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; kwargs...) where {T <: AbstractFloat} + +Compute Taylor series expansion of time-delay observable around echo reception time. This +allows to compute dopplers via automatic differentiation using +```math +\nu = -f\frac{d\tau}{dt}, +``` +where ``f`` is the transmitter frequency (MHz) and ``\tau`` is the time-delay at reception +time ``t``. Computed values include corrections due to Earth orientation, LOD and polar +motion. + +**Note:** Works only with `TaylorInterpolant` ephemeris. See [`PlanetaryEphemeris.TaylorInterpolant`](@ref). + +# Arguments + +- `observatory::ObservatoryMPC{T}`: observing station. +- `t_r_utc::DateTime`: UTC time of echo reception. + +# Keyword arguments + +- `tord::Int = 5`: order of Taylor expansions. +- `niter::Int = 10`: number of light-time solution iterations. +- `xve::EarthEph = earthposvel`: Earth ephemeris. +- `xvs::SunEph = sunposvel`: Sun ephemeris. +- `xva::AstEph`: asteroid ephemeris. + +All ephemeris must take [et seconds since J2000] and return [barycentric position in km +and velocity in km/sec]. + +!!! reference + See https://doi.org/10.1086/116062. +""" +function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; tord::Int = 5, + niter::Int = 10, xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, + xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} + + # Transform receiving time from UTC to TDB seconds since j2000 + et_r_secs_0 = datetime2et(t_r_utc) + # Auxiliary to evaluate JT ephemeris + xva1et0 = xva(et_r_secs_0)[1] + # et_r_secs_0 as a Taylor polynomial + et_r_secs = Taylor1([et_r_secs_0,one(et_r_secs_0)].*one(xva1et0), tord) + # Compute geocentric position/velocity of receiving antenna in inertial frame (km, km/sec) + RV_r = obsposvelECI(observatory, et_r_secs) + R_r = RV_r[1:3] + # Earth's barycentric position and velocity at receive time + r_e_t_r = xve(et_r_secs)[1:3] + # Receiver barycentric position and velocity at receive time + r_r_t_r = r_e_t_r + R_r + # Asteroid barycentric position and velocity at receive time + r_a_t_r = xva(et_r_secs)[1:3] + # Sun barycentric position and velocity at receive time + r_s_t_r = xvs(et_r_secs)[1:3] + + # Down-leg iteration + # τ_D first approximation + # See equation (1) of https://doi.org/10.1086/116062 + ρ_vec_r = r_a_t_r - r_r_t_r + ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) + # -R_b/c, but delay is wrt asteroid Center (Brozovic et al., 2018) + τ_D = ρ_r/clightkms # (seconds) + # Bounce time, new estimate + # See equation (2) of https://doi.org/10.1086/116062 + et_b_secs = et_r_secs - τ_D + + # Allocate memmory for time delays + Δτ_D = zero(τ_D) # Total time delay + Δτ_rel_D = zero(τ_D) # Shapiro delay + # Δτ_corona_D = zero(τ_D) # Delay due to Solar corona + Δτ_tropo_D = zero(τ_D) # Delay due to Earth's troposphere + + for i in 1:niter + # Asteroid barycentric position (in au) at bounce time (TDB) + rv_a_t_b = xva(et_b_secs) + r_a_t_b = rv_a_t_b[1:3] + v_a_t_b = rv_a_t_b[4:6] + # Estimated position of the asteroid's center of mass relative to the recieve point + # See equation (3) of https://doi.org/10.1086/116062. + ρ_vec_r = r_a_t_b - r_r_t_r + # Magnitude of ρ_vec_r + # See equation (4) of https://doi.org/10.1086/116062. + ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) + + # Compute down-leg Shapiro delay + # NOTE: when using PPN, substitute 2 -> 1+γ in expressions for Shapiro delay, + # Δτ_rel_[D|U] + + # Earth's position at t_r + e_D_vec = r_r_t_r - r_s_t_r + # Heliocentric distance of Earth at t_r + e_D = sqrt(e_D_vec[1]^2 + e_D_vec[2]^2 + e_D_vec[3]^2) + # Barycentric position of Sun at estimated bounce time + r_s_t_b = xvs(et_b_secs)[1:3] + # Heliocentric position of asteroid at t_b + p_D_vec = r_a_t_b - r_s_t_b + # Heliocentric distance of asteroid at t_b + p_D = sqrt(p_D_vec[1]^2 + p_D_vec[2]^2 + p_D_vec[3]^2) + # Signal path distance (down-leg) + q_D = ρ_r + + # Shapiro correction to time-delay + Δτ_rel_D = shapiro_delay(e_D, p_D, q_D) # seconds + # Troposphere correction to time-delay + Δτ_tropo_D = tropo_delay(R_r, ρ_vec_r) # seconds + # Solar corona correction to time-delay + # Δτ_corona_D = corona_delay(constant_term.(r_a_t_b), r_r_t_r, r_s_t_r, F_tx, station_code) # seconds + # Total time-delay + Δτ_D = Δτ_rel_D # + Δτ_tropo_D #+ Δτ_corona_D # seconds + + # New estimate + p_dot_23 = dot(ρ_vec_r, v_a_t_b)/ρ_r + # Time delay correction + Δt_2 = (τ_D - ρ_r/clightkms - Δτ_rel_D)/(1.0-p_dot_23/clightkms) + # Time delay new estimate + τ_D = τ_D - Δt_2 + # Bounce time, new estimate + # See equation (2) of https://doi.org/10.1086/116062 + et_b_secs = et_r_secs - τ_D + + end + + # Asteroid's barycentric position and velocity at bounce time t_b + rv_a_t_b = xva(et_b_secs) + r_a_t_b = rv_a_t_b[1:3] + v_a_t_b = rv_a_t_b[4:6] + + # Up-leg iteration + # τ_U first estimation + # See equation (5) of https://doi.org/10.1086/116062 + τ_U = τ_D + # Transmit time, 1st estimate + # See equation (6) of https://doi.org/10.1086/116062 + et_t_secs = et_b_secs - τ_U + # Geocentric position and velocity of transmitting antenna in inertial frame (km, km/sec) + RV_t = RV_r(et_t_secs-et_r_secs_0) + R_t = RV_t[1:3] + V_t = RV_t[4:6] + # Barycentric position and velocity of the Earth at transmit time + rv_e_t_t = xve(et_t_secs) + r_e_t_t = rv_e_t_t[1:3] + v_e_t_t = rv_e_t_t[4:6] + # Transmitter barycentric position and velocity of at transmit time + r_t_t_t = r_e_t_t + R_t + # Up-leg vector at transmit time + # See equation (7) of https://doi.org/10.1086/116062 + ρ_vec_t = r_a_t_b - r_t_t_t + # Magnitude of up-leg vector + ρ_t = sqrt(ρ_vec_t[1]^2 + ρ_vec_t[2]^2 + ρ_vec_t[3]^2) + + # Allocate memmory for time delays + Δτ_U = zero(τ_U) # Total time delay + Δτ_rel_U = zero(τ_U) # Shapiro delay + # Δτ_corona_U = zero(τ_U) # Delay due to Solar corona + Δτ_tropo_U = zero(τ_U) # Delay due to Earth's troposphere + + for i in 1:niter + # Geocentric position and velocity of transmitting antenna in inertial frame (km, km/sec) + RV_t = RV_r(et_t_secs-et_r_secs_0) + R_t = RV_t[1:3] + V_t = RV_t[4:6] + # Earth's barycentric position and velocity at transmit time + rv_e_t_t = xve(et_t_secs) + r_e_t_t = rv_e_t_t[1:3] + v_e_t_t = rv_e_t_t[4:6] + # Barycentric position and velocity of the transmitter at the transmit time + r_t_t_t = r_e_t_t + R_t + v_t_t_t = v_e_t_t + V_t + # Up-leg vector and its magnitude at transmit time + # See equation (7) of https://doi.org/10.1086/116062 + ρ_vec_t = r_a_t_b - r_t_t_t + ρ_t = sqrt(ρ_vec_t[1]^2 + ρ_vec_t[2]^2 + ρ_vec_t[3]^2) + + + # Compute up-leg Shapiro delay + + # Sun barycentric position and velocity (in km, km/sec) at transmit time (TDB) + r_s_t_t = xvs(et_t_secs)[1:3] + # Heliocentric position of Earth at t_t + e_U_vec = r_t_t_t - r_s_t_t + # Heliocentric distance of Earth at t_t + e_U = sqrt(e_U_vec[1]^2 + e_U_vec[2]^2 + e_U_vec[3]^2) + # Barycentric position/velocity of Sun at bounce time + r_s_t_b = xvs(et_b_secs)[1:3] + # Heliocentric position of asteroid at t_b + p_U_vec = r_a_t_b - r_s_t_b + # Heliocentric distance of asteroid at t_b + p_U = sqrt(p_U_vec[1]^2 + p_U_vec[2]^2 + p_U_vec[3]^2) + # Signal path distance (up-leg) + q_U = ρ_t + + # Shapiro correction to time-delay + Δτ_rel_U = shapiro_delay(e_U, p_U, q_U) # seconds + # Troposphere correction to time-delay + Δτ_tropo_U = tropo_delay(R_t, ρ_vec_t) # seconds + # Delay due to Solar corona + # Δτ_corona_U = corona_delay(constant_term.(r_t_t_t), constant_term.(r_a_t_b), constant_term.(r_s_t_b), F_tx, station_code) # seconds + # Total time delay + Δτ_U = Δτ_rel_U # + Δτ_tropo_U #+ Δτ_corona_U # seconds + + # New estimate + p_dot_12 = -dot(ρ_vec_t, v_t_t_t)/ρ_t + # Time-delay correction + Δt_1 = (τ_U - ρ_t/clightkms - Δτ_rel_U)/(1.0-p_dot_12/clightkms) + # Time delay new estimate + τ_U = τ_U - Δt_1 + # Transmit time, new estimate + # See equation (6) of https://doi.org/10.1086/116062 + et_t_secs = et_b_secs - τ_U + end + + # Compute TDB-UTC at transmit time + # Corrections to TT-TDB from Moyer (2003) / Folkner et al. (2014) due to position + # of measurement station on Earth are of order 0.01μs + # Δtt_tdb_station_t = - dot(v_e_t_t, r_t_t_t-r_e_t_t)/clightkms^2 + tdb_utc_t = tdb_utc(et_t_secs) # + Δtt_tdb_station_t + + # Compute TDB-UTC at receive time + # Corrections to TT-TDB from Moyer (2003) / Folkner et al. (2014) due to position + # of measurement station on Earth are of order 0.01μs + # Δtt_tdb_station_r = - dot(v_e_t_r, r_r_t_r-r_e_t_r)/clightkms^2 + tdb_utc_r = tdb_utc(et_r_secs) # + Δtt_tdb_station_r + + # Compute total time delay (UTC seconds); relativistic delay is already included in τ_D, τ_U + # See equation (9) of https://doi.org/10.1086/116062 + τ = (τ_D + τ_U) + (Δτ_tropo_D + Δτ_tropo_U) + (tdb_utc_t - tdb_utc_r) # seconds + + # Total signal delay (μs) + return 1e6τ +end + +@doc raw""" + radar_astrometry(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real; kwargs...) where {T <: AbstractFloat} + radar_astrometry(radar::RadarJPL{T}; kwargs...) where {T <: AbstractFloat} + radar_astrometry(astradarfile::String; kwargs...) + radar_astrometry(astradardata::Vector{RadarJPL}; kwargs...) where {T <: AbstractFloat} + +Return time-delay and Doppler shift. + +# Arguments + +- `observatory::ObservatoryMPC{T}`: observing station. +- `t_r_utc::DateTime`: UTC time of echo reception. +- `F_tx::Real`: transmitter frequency (MHz). +- `radar::RadarJPL{T}` / `astradardata::Vector{RadarJPL{T}}`: radar observation(s). +- `astradarfile::String`: file where to retrieve radar observations. + +# Keyword arguments + +- `tc::Real = 1.0`: time offset wrt echo reception time, to compute Doppler shifts by range differences (seconds). Offsets will be rounded to the nearest millisecond. +- `autodiff::Bool = true`: whether to compute Doppler shift via automatic diff of [`compute_delay`](@ref) or not. +- `tord::Int = 5`: order of Taylor expansions. +- `niter::Int = 10`: number of light-time solution iterations. +- `xve::EarthEph = earthposvel`: Earth ephemeris. +- `xvs::SunEph = sunposvel`: Sun ephemeris. +- `xva::AstEph`: asteroid ephemeris. + +All ephemeris must take [et seconds since J2000] and return [barycentric position in km +and velocity in km/sec]. +""" +function radar_astrometry(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real; + tc::Real = 1.0, autodiff::Bool = true, kwargs...) where {T <: AbstractFloat} + # Compute Doppler shift via automatic differentiation of time-delay + if autodiff + # Time delay + τ = compute_delay(observatory, t_r_utc; kwargs...) + # Time delay, Doppler shift + return τ[0], -F_tx*τ[1] + # Compute Doppler shift via numerical differentiation of time-delay + else + offset = Dates.Millisecond(1000round(tc/2, digits=3)) + τe = compute_delay(observatory, t_r_utc+offset; kwargs...) + τn = compute_delay(observatory, t_r_utc ; kwargs...) + τs = compute_delay(observatory, t_r_utc-offset; kwargs...) + # Time delay, Doppler shift + return τn[0], -F_tx*((τe[0]-τs[0])/tc) + end + +end + +function radar_astrometry(radar::RadarJPL{T}; kwargs...) where {T <: AbstractFloat} + return radar_astrometry(radar.rcvr, radar.date, radar.freq; kwargs...) +end + +function radar_astrometry(astradarfile::String; kwargs...) + # Check that astradarfile is a file + @assert isfile(astradarfile) "Cannot open file: $astradarfile" + # Read radar measurements + astradardata = read_radar_jpl(astradarfile) + return radar_astrometry(astradardata; kwargs...) +end + +function radar_astrometry(astradardata::Vector{RadarJPL{T}}; xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} + + # UTC time of first radar observation + utc1 = astradardata[1].date + # TDB seconds since J2000.0 for first astrometric observation + et1 = datetime2et(utc1) + # Asteroid ephemeris at et1 + a1_et1 = xva(et1)[1] + # Type of asteroid ephemeris + S = typeof(a1_et1) + + # Time delays + vdelay = Array{S}(undef, length(astradardata)) + # Doppler shifts + vdoppler = Array{S}(undef, length(astradardata)) + + # Iterate over the measurements + Threads.@threads for i in eachindex(astradardata) + # Compute time delay and doppler shift + vdelay[i], vdoppler[i] = radar_astrometry(astradardata[i]; xva, kwargs...) + end + # Rows with time delays + delay_index = map(x-> x.Δτ_units == "us", astradardata) + # Rows with Doppler shifts + doppler_index = map(x -> x.Δν_units == "Hz", astradardata) + + dt_utc_obs = date.(astradardata) # UTC time + Δτ_obs = delay.(astradardata) # Observed time delay + Δν_obs = doppler.(astradardata) # Observed Doppler shift + Δτ_σ = delay_sigma.(astradardata) # Observed time delay uncertainty + Δν_σ = doppler_sigma.(astradardata) # Observed Doppler shift uncertainty + τ_units = delay_units.(astradardata) # Time delay units + ν_units = doppler_units.(astradardata) # Doppler shift units + freq_ = freq.(astradardata) # Frequency + rcvr_ = rcvr.(astradardata) # Receiver antenna + xmit_ = xmit.(astradardata) # Emission antenna + bouncepoint_ = bouncepoint.(astradardata) # Bounce point + + # Return time delays / Doppler shifts table + return dt_utc_obs, Δτ_obs, Δν_obs, vdelay, vdoppler, Δτ_σ, Δν_σ, τ_units, ν_units, freq_, rcvr_, xmit_, bouncepoint_, delay_index, + doppler_index +end + +@doc raw""" + residuals(obs::Vector{RadarJPL{T}}; kwargs...) where {T <: AbstractFloat} + +Compute O-C residuals for radar astrometry, including corrections due to Earth orientation, +LOD and polar motion. + +See also [`compute_delay`](@ref) and [`radar_astrometry`](@ref). + +# Arguments + +- `obs::Vector{RadarJPL{T}}`: vector of observations. + +# Keyword arguments + +- `tc::Real = 1.0`: time offset wrt echo reception time, to compute Doppler shifts by range differences (seconds). Offsets will be rounded to the nearest millisecond. +- `autodiff::Bool = true`: whether to compute Doppler shift via automatic diff of [`compute_delay`](@ref) or not. +- `tord::Int = 5`: order of Taylor expansions. +- `niter::Int = 10`: number of light-time solution iterations. +- `xve::EarthEph = earthposvel`: Earth ephemeris. +- `xvs::SunEph = sunposvel`: Sun ephemeris. +- `xva::AstEph`: asteroid ephemeris. + +All ephemeris must take [et seconds since J2000] and return [barycentric position in km +and velocity in km/sec]. +""" +function residuals(obs::Vector{RadarJPL{T}}; kwargs...) where {T <: AbstractFloat} + # Radar delay/Doppler astrometric data + x_jt = radar_astrometry(obs; kwargs...) + # Time-delay residuals + res_τ = x_jt[2][x_jt[14]] .- x_jt[4][x_jt[14]] + # Doppler-shift residuals + res_ν = x_jt[3][x_jt[15]] .- x_jt[5][x_jt[15]] + # Weights + w_τ = 1 ./ (x_jt[6][x_jt[14]].^2) + w_ν = 1 ./ (x_jt[7][x_jt[15]].^2) + + return res_τ, w_τ, res_ν, w_ν +end diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl old mode 100644 new mode 100755 index 9848f4da..b46c537c --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -1,673 +1,664 @@ -@doc raw""" - OpticalResidual{T <: Real, U <: Number} - -An astrometric optical observed minus computed residual. - -# Fields - -- `ξ_α::U`: right ascension residual. -- `ξ_δ::U`: declination residual. -- `w_α::T`: right ascension weight. -- `w_δ::T`: declination weight. -- `relax_factor::T`: relaxation factor. -- `outlier::Bool`: whether the residual is an outlier or not. -""" -@auto_hash_equals struct OpticalResidual{T <: Real, U <: Number} - ξ_α::U - ξ_δ::U - w_α::T - w_δ::T - relax_factor::T - outlier::Bool - function OpticalResidual{T, U}(ξ_α::U, ξ_δ::U, w_α::T, w_δ::T, relax_factor::T = one(T), - outlier::Bool = false) where {T <: Real, U <: Number} - new{T, U}(ξ_α, ξ_δ, w_α, w_δ, relax_factor, outlier) - end -end - -function OpticalResidual(ξ_α::U, ξ_δ::U, w_α::T, w_δ::T, relax_factor::T = one(T), - outlier::Bool = false) where {T <: Real, U <: Number} - return OpticalResidual{T, U}(ξ_α, ξ_δ, w_α, w_δ, relax_factor, outlier) -end - -# Evaluate methods -function evaluate(res::OpticalResidual{T, TaylorN{T}}, x::Vector{T}) where {T <: Real} - return OpticalResidual(res.ξ_α(x), res.ξ_δ(x), res.w_α, res.w_δ, res.relax_factor, res.outlier) -end -(res::OpticalResidual{T, TaylorN{T}})(x::Vector{T}) where {T <: Real} = evaluate(res, x) - -function evaluate(res::Vector{OpticalResidual{T, TaylorN{T}}}, x::Vector{T}) where {T <: Real} - res_new = Vector{OpticalResidual{T, T}}(undef, length(res)) - for i in eachindex(res) - res_new[i] = evaluate(res[i], x) - end - return res_new -end -(res::AbstractVector{OpticalResidual{T, TaylorN{T}}})(x::Vector{T}) where {T <: Real} = evaluate(res, x) - -# Print method for OpticalResidual -# Examples: -# α: -138.7980136773549 δ: -89.8002527255012 -# α: -134.79449984291568 δ: -91.42509376643284 -function show(io::IO, x::OpticalResidual{T, U}) where {T <: Real, U <: Number} - print(io, "α: ", cte(x.ξ_α), " δ: ", cte(x.ξ_δ)) -end - -@doc raw""" - unfold(ξs::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} - -Concatenate right ascension and declination residuals for an orbit fit. -""" -function unfold(ξs::AbstractVector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} - # Number of non outliers - L = count(x -> !x.outlier, ξs) - # Vector of residuals - res = Vector{U}(undef, 2*L) - # Vector of weights - w = Vector{T}(undef, 2*L) - # Global counter - k = 1 - # Fill residuals and weights - for i in eachindex(ξs) - if !ξs[i].outlier - # Right ascension - res[k] = ξs[i].ξ_α - w[k] = ξs[i].w_α / ξs[i].relax_factor - # Declination - res[k+L] = ξs[i].ξ_δ - w[k+L] = ξs[i].w_δ / ξs[i].relax_factor - # Update global counter - k += 1 - end - end - - return res, w -end - -ra(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.ξ_α -dec(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.ξ_δ -weight_ra(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.w_α -weight_dec(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.w_δ -relax_factor(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.relax_factor -outlier(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.outlier - -@doc raw""" - compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter::Int = 5, - xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} - compute_radec(obs::RadecMPC{T}; niter::Int = 5, xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, - xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} - compute_radec(obs::Vector{RadecMPC{T}}; niter::Int=5, xve::EarthEph=earthposvel, xvs::SunEph=sunposvel, - xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} - -Compute astrometric right ascension and declination (both in arcsec) for a set of MPC-formatted observations. -Corrections due to Earth orientation, LOD, polar motion are considered in computations. - -# Arguments - -- `observatory::ObservatoryMPC{T}`: observation site. -- `t_r_utc::DateTime`: UTC time of astrometric observation. -- `niter::Int`: number of light-time solution iterations. -- `xve`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xvs`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xva`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -""" -function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter::Int = 5, - xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} - # Transform receiving time from UTC to TDB seconds since J2000 - et_r_secs = datetime2et(t_r_utc) - # Compute geocentric position/velocity of receiving antenna in inertial frame [km, km/s] - RV_r = obsposvelECI(observatory, et_r_secs) - R_r = RV_r[1:3] - # Earth's barycentric position and velocity at receive time - rv_e_t_r = xve(et_r_secs) - r_e_t_r = rv_e_t_r[1:3] - # Receiver barycentric position and velocity at receive time - r_r_t_r = r_e_t_r + R_r - # Asteroid barycentric position and velocity at receive time - rv_a_t_r = xva(et_r_secs) - r_a_t_r = rv_a_t_r[1:3] - # Sun barycentric position and velocity at receive time - rv_s_t_r = xvs(et_r_secs) - r_s_t_r = rv_s_t_r[1:3] - - # Down-leg iteration - # τ_D first approximation - # See equation (1) of https://doi.org/10.1086/116062 - ρ_vec_r = r_a_t_r - r_r_t_r - ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) - # -R_b/c, but delay is wrt asteroid Center (Brozovic et al., 2018) - τ_D = ρ_r/clightkms # (seconds) - # Bounce time, new estimate - # See equation (2) of https://doi.org/10.1086/116062 - et_b_secs = et_r_secs - τ_D - - # Allocate memmory for time-delays - Δτ_D = zero(τ_D) # Total time delay - Δτ_rel_D = zero(τ_D) # Shapiro delay - # Δτ_corona_D = zero(τ_D) # Delay due to Solar corona - Δτ_tropo_D = zero(τ_D) # Delay due to Earth's troposphere - - for i in 1:niter - # Asteroid barycentric position (in km) and velocity (in km/s) at bounce time (TDB) - rv_a_t_b = xva(et_b_secs) - r_a_t_b = rv_a_t_b[1:3] - v_a_t_b = rv_a_t_b[4:6] - # Estimated position of the asteroid's center of mass relative to the recieve point - # See equation (3) of https://doi.org/10.1086/116062 - ρ_vec_r = r_a_t_b - r_r_t_r - # Magnitude of ρ_vec_r - # See equation (4) of https://doi.org/10.1086/116062 - ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) - - # Compute down-leg Shapiro delay - # NOTE: when using PPN, substitute 2 -> 1+γ in expressions for Shapiro delay, - # Δτ_rel_[D|U] - - # Earth's position at t_r - e_D_vec = r_r_t_r - r_s_t_r - # Heliocentric distance of Earth at t_r - e_D = sqrt(e_D_vec[1]^2 + e_D_vec[2]^2 + e_D_vec[3]^2) - # Barycentric position of Sun at estimated bounce time - rv_s_t_b = xvs(et_b_secs) - r_s_t_b = rv_s_t_b[1:3] - # Heliocentric position of asteroid at t_b - p_D_vec = r_a_t_b - r_s_t_b - # Heliocentric distance of asteroid at t_b - p_D = sqrt(p_D_vec[1]^2 + p_D_vec[2]^2 + p_D_vec[3]^2) - # Signal path distance (down-leg) - q_D = ρ_r - - # Shapiro correction to time-delay - Δτ_rel_D = shapiro_delay(e_D, p_D, q_D) # seconds - # Troposphere correction to time-delay - # Δτ_tropo_D = tropo_delay(R_r, ρ_vec_r) # seconds - # Solar corona correction to time-delay - # Δτ_corona_D = corona_delay(constant_term.(r_a_t_b), r_r_t_r, r_s_t_r, F_tx, station_code) # seconds - # Total time-delay - Δτ_D = Δτ_rel_D # + Δτ_tropo_D #+ Δτ_corona_D # seconds - - # New estimate - p_dot_23 = dot(ρ_vec_r, v_a_t_b)/ρ_r - # Time delay correction - Δt_2 = (τ_D - ρ_r/clightkms - Δτ_rel_D)/(1.0-p_dot_23/clightkms) - # Time delay new estimate - τ_D = τ_D - Δt_2 - # Bounce time, new estimate - # See equation (2) of https://doi.org/10.1086/116062 - et_b_secs = et_r_secs - τ_D - end - # Asteroid barycentric position (in km) and velocity (in km/s) at bounce time (TDB) - rv_a_t_b = xva(et_b_secs) - r_a_t_b = rv_a_t_b[1:3] - v_a_t_b = rv_a_t_b[4:6] - # Estimated position of the asteroid's center of mass relative to the recieve point - # See equation (3) of https://doi.org/10.1086/116062 - ρ_vec_r = r_a_t_b - r_r_t_r - # Magnitude of ρ_vec_r - # See equation (4) of https://doi.org/10.1086/116062 - ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) - - # TODO: add aberration and atmospheric refraction corrections - - # Compute gravitational deflection of light - # See Explanatory Supplement to the Astronomical Almanac (ESAA) 2014 Section 7.4.1.4 - E_H_vec = r_r_t_r -r_s_t_r # ESAA 2014, equation (7.104) - U_vec = ρ_vec_r # r_a_t_b - r_e_t_r, ESAA 2014, equation (7.112) - U_norm = ρ_r # sqrt(U_vec[1]^2 + U_vec[2]^2 + U_vec[3]^2) - u_vec = U_vec/U_norm - # Barycentric position and velocity of Sun at converged bounce time - rv_s_t_b = xvs(et_b_secs) - r_s_t_b = rv_s_t_b[1:3] - Q_vec = r_a_t_b - r_s_t_b # ESAA 2014, equation (7.113) - q_vec = Q_vec/sqrt(Q_vec[1]^2 + Q_vec[2]^2 + Q_vec[3]^2) - E_H = sqrt(E_H_vec[1]^2 + E_H_vec[2]^2 + E_H_vec[3]^2) - e_vec = E_H_vec/E_H - # See ESAA 2014, equation (7.115) - g1 = (2μ_DE430[su]/(c_au_per_day^2))/(E_H/au) - g2 = 1 + dot(q_vec, e_vec) - # See ESAA 2014, equation (7.116) - u1_vec = U_norm*( u_vec + (g1/g2)*( dot(u_vec,q_vec)*e_vec - dot(e_vec,u_vec)*q_vec ) ) - u1_norm = sqrt(u1_vec[1]^2 + u1_vec[2]^2 + u1_vec[3]^2) - - # Compute right ascension, declination angles - α_rad_ = mod2pi(atan(u1_vec[2], u1_vec[1])) - α_rad = mod2pi(α_rad_) # right ascension (rad) - δ_rad = asin(u1_vec[3]/u1_norm) # declination (rad) - - δ_as = rad2arcsec(δ_rad) # rad -> arcsec + debiasing - α_as = rad2arcsec(α_rad) # rad -> arcsec + debiasing - - return α_as, δ_as # right ascension, declination both in arcsec -end - -function compute_radec(obs::RadecMPC{T}; kwargs...) where {T <: AbstractFloat} - return compute_radec(obs.observatory, obs.date; kwargs...) -end - -function compute_radec(obs::Vector{RadecMPC{T}}; xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} - - # Number of observations - n_optical_obs = length(obs) - # UTC time of first astrometric observation - utc1 = obs[1].date - # TDB seconds since J2000.0 for first astrometric observation - et1 = datetime2et(utc1) - # Asteroid ephemeris at et1 - a1_et1 = xva(et1)[1] - # Type of asteroid ephemeris - S = typeof(a1_et1) - - # Right ascension - vra = Array{S}(undef, n_optical_obs) - # Declination - vdec = Array{S}(undef, n_optical_obs) - - # Iterate over the number of observations - for i in 1:n_optical_obs - vra[i], vdec[i] = compute_radec(obs[i]; xva = xva, kwargs...) - end - - return vra, vdec # arcsec, arcsec -end - -# MPC catalogues corresponding to debiasing tables included in https://doi.org/10.1016/j.icarus.2014.07.033 -const mpc_catalogue_codes_2014 = ["a", "b", "c", "d", "e", "g", "i", "j", "l", "m", "o", "p", "q", "r", - "u", "v", "w", "L", "N"] - -# MPC catalogues corresponding to debiasing tables included in https://doi.org/10.1016/j.icarus.2019.113596 -const mpc_catalogue_codes_2018 = ["a", "b", "c", "d", "e", "g", "i", "j", "l", "m", "n", "o", "p", "q", - "r", "t", "u", "v", "w", "L", "N", "Q", "R", "S", "U", "W"] - -@doc raw""" - select_debiasing_table(debias_table::String = "2018") - -Return the catalogue codes, truth catalogue, resolution and bias matrix of the corresponding debias table. The possible values -for `debias_table` are: -- `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, -- `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, -- `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. -""" -function select_debiasing_table(debias_table::String = "2018") - # Debiasing tables are loaded "lazily" via Julia artifacts, according to rules in Artifacts.toml - if debias_table == "2018" - debias_path = artifact"debias_2018" - mpc_catalogue_codes_201X = mpc_catalogue_codes_2018 - # The healpix tesselation resolution of the bias map from https://doi.org/10.1016/j.icarus.2019.113596 - NSIDE = 64 - # In 2018 debias table Gaia DR2 catalogue is regarded as the truth - truth = "V" - elseif debias_table == "hires2018" - debias_path = artifact"debias_hires2018" - mpc_catalogue_codes_201X = mpc_catalogue_codes_2018 - # The healpix tesselation resolution of the high-resolution bias map from https://doi.org/10.1016/j.icarus.2019.113596 - NSIDE = 256 - # In 2018 debias table Gaia DR2 catalogue is regarded as the truth - truth = "V" - elseif debias_table == "2014" - debias_path = artifact"debias_2014" - mpc_catalogue_codes_201X = mpc_catalogue_codes_2014 - # The healpix tesselation resolution of the bias map from https://doi.org/10.1016/j.icarus.2014.07.033 - NSIDE= 64 - # In 2014 debias table PPMXL catalogue is regarded as the truth - truth = "t" - else - @error "Unknown bias map: $(debias_table). Possible values are `2014`, `2018` and `hires2018`." - end - - # Debias table file - bias_file = joinpath(debias_path, "bias.dat") - # Read bias matrix - bias_matrix = readdlm(bias_file, comment_char='!', comments=true) - # Initialize healpix Resolution variable - resol = Resolution(NSIDE) - # Compatibility between bias matrix and resolution - @assert size(bias_matrix) == (resol.numOfPixels, 4length(mpc_catalogue_codes_201X)) "Bias table file $bias_file dimensions do not match expected parameter NSIDE=$NSIDE and/or number of catalogs in table." - - return mpc_catalogue_codes_201X, truth, resol, bias_matrix -end - -@doc raw""" - debiasing(obs::RadecMPC{T}, mpc_catalogue_codes_201X::Vector{String}, truth::String, resol::Resolution, - bias_matrix::Matrix{T}) where {T <: AbstractFloat} - -Return total debiasing correction in right ascension and declination (both in arcsec). - -# Arguments - -- `obs::RadecMPC{T}`: optical observation. -- `mpc_catalogue_codes_201X::Vector{String}`: catalogues present in debiasing table. -- `truth::String`: truth catalogue of debiasing table. -- `resol::Resolution`: resolution. -- `bias_matrix::Matrix{T}`: debiasing table. -""" -function debiasing(obs::RadecMPC{T}, mpc_catalogue_codes_201X::Vector{String}, truth::String, resol::Resolution, - bias_matrix::Matrix{T}) where {T <: AbstractFloat} - - # Catalogue code - catcode = obs.catalogue.code - - # If star catalogue is not present in debiasing table, then set corrections equal to zero - if (catcode ∉ mpc_catalogue_codes_201X) && catcode != "Y" - # Catalogue exists in mpc_catalogues[] - if !isunknown(obs.catalogue) - # Truth catalogue is not present in debiasing table but it does not send a warning - if catcode != truth - @warn "Catalogue $(obs.catalogue.name) not found in debiasing table. Setting debiasing corrections equal to zero." - end - # Unknown catalogue - elseif catcode == "" - @warn "Catalog information not available in observation record. Setting debiasing corrections equal to zero." - # Catalogue code is not empty but it does not match an MPC catalogue code either - else - @warn "Catalog code $catcode does not correspond to MPC catalogue code. Setting debiasing corrections equal to zero." - end - α_corr = zero(T) - δ_corr = zero(T) - # If star catalogue is present in debiasing table, then compute corrections - else - # Get pixel tile index, assuming iso-latitude rings indexing, which is the formatting in `tiles.dat`. - # Substracting 1 from the returned value of `ang2pixRing` corresponds to 0-based indexing, as in `tiles.dat`; - # not substracting 1 from the returned value of `ang2pixRing` corresponds to 1-based indexing, as in Julia. - # Since we use pix_ind to get the corresponding row number in `bias.dat`, it's not necessary to substract 1. - pix_ind = ang2pixRing(resol, π/2 - obs.δ, obs.α) - - # Handle edge case: in new MPC catalogue nomenclature, "UCAC-5"->"Y"; but in debias tables "UCAC-5"->"W" - if catcode == "Y" - cat_ind = findfirst(x -> x == "W", mpc_catalogue_codes_201X) - else - cat_ind = findfirst(x -> x == catcode, mpc_catalogue_codes_201X) - end - - # Read dRA, pmRA, dDEC, pmDEC data from bias.dat - # dRA: position correction in RA * cos(DEC) at epoch J2000.0 [arcsec] - # dDEC: position correction in DEC at epoch J2000.0 [arcsec] - # pmRA: proper motion correction in RA*cos(DEC) [mas/yr] - # pmDEC: proper motion correction in DEC [mas/yr] - dRA, dDEC, pmRA, pmDEC = bias_matrix[pix_ind, 4*cat_ind-3:4*cat_ind] - # Seconds since J2000 (TDB) - et_secs_i = datetime2et(obs.date) - # Seconds sinde J2000 (TT) - tt_secs_i = et_secs_i - ttmtdb(et_secs_i/daysec) - # Years since J2000 - yrs_J2000_tt = tt_secs_i/(daysec*yr) - # Total debiasing correction in right ascension (arcsec) - α_corr = dRA + yrs_J2000_tt*pmRA/1_000 - # Total debiasing correction in declination (arcsec) - δ_corr = dDEC + yrs_J2000_tt*pmDEC/1_000 - end - - return α_corr, δ_corr -end - -@doc raw""" - w8sveres17(obs::RadecMPC{T}) where {T <: AbstractFloat} - -Return the statistical weight from Veres et al. (2017) corresponding to `obs`. -""" -function w8sveres17(obs::RadecMPC{T}) where {T <: AbstractFloat} - - obscode = obs.observatory.code - dt_utc_obs = obs.date - catalogue = obs.catalogue.code - - # Unit weight (arcseconds) - w = 1.0 - # Table 2: epoch-dependent astrometric residuals - if obscode == "703" - return Date(dt_utc_obs) < Date(2014,1,1) ? w : 0.8w - elseif obscode == "691" - return Date(dt_utc_obs) < Date(2003,1,1) ? 0.6w : 0.5w - elseif obscode == "644" - return Date(dt_utc_obs) < Date(2003,9,1) ? 0.6w : 0.4w - # Table 3: most active CCD asteroid observers - elseif obscode ∈ ("704", "C51", "J75") - return w - elseif obscode == "G96" - return 0.5w - elseif obscode == "F51" - return 0.2w - elseif obscode ∈ ("G45", "608") - return 0.6w - elseif obscode == "699" - return 0.8w - elseif obscode ∈ ("D29", "E12") - return 0.75w - # Table 4: - elseif obscode ∈ ("645", "673", "H01") - return 0.3w - elseif obscode ∈ ("J04", "K92", "K93", "Q63", "Q64", "V37", "W85", "W86", "W87", "K91", "E10", "F65") #Tenerife + Las Cumbres - return 0.4w - elseif obscode ∈ ("689", "950", "W84") - return 0.5w - #elseif obscode ∈ ("G83", "309") # Applies only to program code assigned to M. Micheli - # if catalogue ∈ ("q", "t") # "q"=>"UCAC-4", "t"=>"PPMXL" - # return 0.3w - # elseif catalogue ∈ ("U", "V") # Gaia-DR1, Gaia-DR2 - # return 0.2w - # end - elseif obscode ∈ ("Y28",) - if catalogue ∈ ("t", "U", "V") - return 0.3w - else - return w - end - elseif obscode ∈ ("568",) - if catalogue ∈ ("o", "s") # "o"=>"USNO-B1.0", "s"=>"USNO-B2.0" - return 0.5w - elseif catalogue ∈ ("U", "V") # Gaia DR1, DR2 - return 0.1w - elseif catalogue ∈ ("t",) #"t"=>"PPMXL" - return 0.2w - else - return w - end - elseif obscode ∈ ("T09", "T12", "T14") && catalogue ∈ ("U", "V") # Gaia DR1, DR2 - return 0.1w - elseif catalogue == "" - return 1.5w - elseif catalogue != "" - return w - else - return w - end -end - -@doc raw""" - relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - -Return a relax factor for each element of `radec` quantifying the correlation between observations taken on -the same night by the same observatory. - -!!! reference - See https://doi.org/10.1016/j.icarus.2017.05.021. -""" -function relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - # Convert to DataFrame - df = DataFrame(radec) - # Group by observatory and TimeOfDay - df.TimeOfDay = TimeOfDay.(df.date, df.observatory) - gdf = groupby(df, [:observatory, :TimeOfDay]) - # Interpolate observation nights - cdf = combine(gdf, nrow) - # Count observations in each group - Nv = cdf[gdf.groups, :nrow] - # Relaxation factor - return map(x -> x > 4.0 ? x/4.0 : 1.0, Nv) -end - -function anglediff(x::T, y::S) where {T, S <: Number} - # Signed difference - Δ = x - y - # Absolute difference - Δ_abs = abs(Δ) - # Reflection - if Δ_abs > 648_000 # Half circle in arcsec - return -sign(cte(Δ)) * (1_296_000 - Δ_abs) - else - return Δ - end -end - -@doc raw""" - residuals(obs::Vector{RadecMPC{T}}; debias_table::String = "2018", xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} - -Compute O-C residuals for optical astrometry. Corrections due to Earth orientation, LOD, polar motion are computed by default. - -See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and [`Healpix.ang2pixRing`](@ref). - -# Arguments - -- `obs::Vector{RadecMPC{T}}`: vector of observations. - -# Keyword arguments - -- `niter::Int`: number of light-time solution iterations. -- `debias_table::String`: possible values are: - - `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, - - `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, - - `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. -- `xve`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xvs`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xva`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -""" -function residuals(obs::Vector{RadecMPC{T}}; debias_table::String = "2018", xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} - mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) - return residuals(obs, mpc_catalogue_codes_201X, truth, resol, bias_matrix; xva, kwargs...) -end -function residuals(obs::Vector{RadecMPC{T}}, mpc_catalogue_codes_201X::Vector{String}, truth::String, resol::Resolution, - bias_matrix::Matrix{T}; xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} - - # Number of observations - N_obs = length(obs) - - # UTC time of first astrometric observation - utc1 = date(obs[1]) - # TDB seconds since J2000.0 for first astrometric observation - et1 = datetime2et(utc1) - # Asteroid ephemeris at et1 - a1_et1 = xva(et1)[1] - # Type of asteroid ephemeris - S = typeof(a1_et1) - - # Relax factors - rex = relax_factor(obs) - - # Vector of residuals - res = Vector{OpticalResidual{T, S}}(undef, N_obs) - - # Iterate over the observations - Threads.@threads for i in 1:N_obs - - # Observed ra/dec - α_obs = rad2arcsec(ra(obs[i])) # arcsec - δ_obs = rad2arcsec(dec(obs[i])) # arcsec - - # Computed ra/dec - α_comp, δ_comp = compute_radec(obs[i]; xva, kwargs...) # arcsec - - # Debiasing corrections - α_corr, δ_corr = debiasing(obs[i], mpc_catalogue_codes_201X, truth, resol, bias_matrix) - - # Statistical weights from Veres et al. (2017) - w8 = w8sveres17(obs[i]) - - # O-C residual ra/dec - # Note: ra is multiplied by a metric factor cos(dec) to match the format of debiasing corrections - res[i] = OpticalResidual( - anglediff(α_obs, α_comp) * cos(dec(obs[i])) - α_corr, - δ_obs - δ_comp - δ_corr, - 1 / w8^2, - 1 / w8^2, - rex[i], - false - ) - - end - - return res -end - -@doc raw""" - extrapolation(x::AbstractVector{T}, y::AbstractVector{T}) where {T <: Real} - -Return an extrapolation of points `(x, y)`. -""" -function extrapolation(x::AbstractVector{T}, y::AbstractVector{T}) where {T <: Real} - # Check we have as many x as y - @assert length(x) == length(y) - # Interpolation - itp = interpolate((x,), y, Gridded(Linear())) - # Extrapolation - etpf = extrapolate(itp, Flat()) - - return etpf -end - -@doc raw""" - extrapolation(df::AbstractDataFrame) - -Special method of [`extrapolation`](@ref) to be used by [`gaussinitcond`](@ref). -""" -function extrapolation(df::AbstractDataFrame) - if !allunique(df.date) - gdf = groupby(df, :date) - df = combine(gdf, [:α, :δ] .=> x -> sum(x)/length(x), :observatory => identity, renamecols = false) - end - - if isone(nrow(df)) - return (observatory = df.observatory[1], date = df.date[1], α = df.α[1], δ = df.δ[1]) - end - - # Julian days of observation - t_julian = datetime2julian.(df.date) - # Days of observation [relative to first observation] - t_rel = t_julian .- t_julian[1] - # Mean date - t_mean = sum(t_rel) / length(t_rel) - - α_p = extrapolation([0., 1.], [0., 1.]) - - # Points in top quarter - N_top = count(x -> x > 3π/2, df.α) - # Points in bottom quarter - N_bottom = count(x -> x < π/2, df.α) - # No discontinuity - if iszero(N_top) || iszero(N_bottom) - α_p = extrapolation(t_rel, df.α) - # Discontinuity - else - α = map(x -> x < π ? x + 2π : x, df.α) - α_p = extrapolation(t_rel, α) - end - δ_p = extrapolation(t_rel, df.δ) - - # Evaluate polynomials at mean date - α_mean = mod2pi(α_p(t_mean)) - δ_mean = δ_p(t_mean) - - return (observatory = df.observatory[1], date = julian2datetime(t_julian[1] + t_mean), α = α_mean, δ = δ_mean) -end - -@doc raw""" - reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - -Return one observatory, date, right ascension and declination per observation night in `radec`. The reduction is performed -via polynomial interpolation. -""" -function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - # Convert to DataFrame - df = DataFrame(radec) - # Compute TimeOfDay - df.TimeOfDay = TimeOfDay.(df.date, df.observatory) - # Group by observatory and TimeOfDay - gdf = groupby(df, [:observatory, :TimeOfDay]) - # Interpolate observation nights - cdf = combine(gdf, extrapolation, keepkeys = false) - # Eliminate unsuccesful interpolations - filter!(:α => !isnan, cdf) - filter!(:δ => !isnan, cdf) - # Sort by date - idxs = sortperm(cdf, :date) - - return gdf[idxs], cdf[idxs, :] +@doc raw""" + OpticalResidual{T <: Real, U <: Number} + +An astrometric optical observed minus computed residual. + +# Fields + +- `ξ_α::U`: right ascension residual. +- `ξ_δ::U`: declination residual. +- `w_α::T`: right ascension weight. +- `w_δ::T`: declination weight. +- `relax_factor::T`: relaxation factor. +- `outlier::Bool`: whether the residual is an outlier or not. +""" +@auto_hash_equals struct OpticalResidual{T <: Real, U <: Number} + ξ_α::U + ξ_δ::U + w_α::T + w_δ::T + relax_factor::T + outlier::Bool + # Inner constructor + function OpticalResidual{T, U}(ξ_α::U, ξ_δ::U, w_α::T, w_δ::T, relax_factor::T = one(T), + outlier::Bool = false) where {T <: Real, U <: Number} + new{T, U}(ξ_α, ξ_δ, w_α, w_δ, relax_factor, outlier) + end +end +# Outer constructor +function OpticalResidual(ξ_α::U, ξ_δ::U, w_α::T, w_δ::T, relax_factor::T = one(T), + outlier::Bool = false) where {T <: Real, U <: Number} + return OpticalResidual{T, U}(ξ_α, ξ_δ, w_α, w_δ, relax_factor, outlier) +end + +# Evaluate methods +function evaluate(res::OpticalResidual{T, TaylorN{T}}, x::Vector{T}) where {T <: Real} + return OpticalResidual(res.ξ_α(x), res.ξ_δ(x), res.w_α, res.w_δ, res.relax_factor, res.outlier) +end +(res::OpticalResidual{T, TaylorN{T}})(x::Vector{T}) where {T <: Real} = evaluate(res, x) + +function evaluate(res::AbstractVector{OpticalResidual{T, TaylorN{T}}}, x::Vector{T}) where {T <: Real} + res_new = Vector{OpticalResidual{T, T}}(undef, length(res)) + for i in eachindex(res) + res_new[i] = evaluate(res[i], x) + end + return res_new +end +(res::AbstractVector{OpticalResidual{T, TaylorN{T}}})(x::Vector{T}) where {T <: Real} = evaluate(res, x) + +# Print method for OpticalResidual +# Examples: +# α: -138.79801 δ: -89.80025 +# α: -134.79450 δ: -91.42509 +function show(io::IO, x::OpticalResidual{T, U}) where {T <: Real, U <: Number} + print(io, "α: ", @sprintf("%+.5f", cte(x.ξ_α)), " δ: ", @sprintf("%+.5f", cte(x.ξ_δ))) +end + +@doc raw""" + unfold(ξs::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + +Concatenate right ascension and declination residuals for an orbit fit. +""" +function unfold(ξs::AbstractVector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + # Number of non outliers + L = count(x -> !x.outlier, ξs) + # Vector of residuals + res = Vector{U}(undef, 2*L) + # Vector of weights + w = Vector{T}(undef, 2*L) + # Global counter + k = 1 + # Fill residuals and weights + for i in eachindex(ξs) + if !ξs[i].outlier + # Right ascension + res[k] = ξs[i].ξ_α + w[k] = ξs[i].w_α / ξs[i].relax_factor + # Declination + res[k+L] = ξs[i].ξ_δ + w[k+L] = ξs[i].w_δ / ξs[i].relax_factor + # Update global counter + k += 1 + end + end + + return res, w +end + +# Functions to get specific fields of a OpticalResidual object +ra(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.ξ_α +dec(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.ξ_δ +weight_ra(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.w_α +weight_dec(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.w_δ +relax_factor(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.relax_factor +outlier(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.outlier + +@doc raw""" + compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; kwargs...) where {T <: AbstractFloat} + compute_radec(obs::RadecMPC{T}; kwargs...) where {T <: AbstractFloat} + compute_radec(obs::Vector{RadecMPC{T}}; kwargs...) where {T <: AbstractFloat} + +Compute astrometric right ascension and declination (both in arcsec) for a set of MPC-formatted +observations. Corrections due to Earth orientation, LOD, polar motion are considered in +computations. + +# Arguments + +- `observatory::ObservatoryMPC{T}`: observation site. +- `t_r_utc::DateTime`: UTC time of astrometric observation. +- `obs::Vector{RadecMPC{T}}`: optical observation(s). + +# Keyword arguments + +- `niter::Int = 5`: number of light-time solution iterations. +- `xve::EarthEph = earthposvel`: Earth ephemeris. +- `xvs::SunEph = sunposvel`: Sun ephemeris. +- `xva::AstEph`: asteroid ephemeris. + +All ephemeris must take [et seconds since J2000] and return [barycentric position in km +and velocity in km/sec]. +""" +function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter::Int = 5, + xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} + # Transform receiving time from UTC to TDB seconds since J2000 + et_r_secs = datetime2et(t_r_utc) + # Compute geocentric position/velocity of receiving antenna in inertial frame [km, km/s] + RV_r = obsposvelECI(observatory, et_r_secs) + R_r = RV_r[1:3] + # Earth's barycentric position and velocity at receive time + rv_e_t_r = xve(et_r_secs) + r_e_t_r = rv_e_t_r[1:3] + # Receiver barycentric position and velocity at receive time + r_r_t_r = r_e_t_r + R_r + # Asteroid barycentric position and velocity at receive time + rv_a_t_r = xva(et_r_secs) + r_a_t_r = rv_a_t_r[1:3] + # Sun barycentric position and velocity at receive time + rv_s_t_r = xvs(et_r_secs) + r_s_t_r = rv_s_t_r[1:3] + + # Down-leg iteration + # τ_D first approximation + # See equation (1) of https://doi.org/10.1086/116062 + ρ_vec_r = r_a_t_r - r_r_t_r + ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) + # -R_b/c, but delay is wrt asteroid Center (Brozovic et al., 2018) + τ_D = ρ_r/clightkms # (seconds) + # Bounce time, new estimate + # See equation (2) of https://doi.org/10.1086/116062 + et_b_secs = et_r_secs - τ_D + + # Allocate memmory for time-delays + Δτ_D = zero(τ_D) # Total time delay + Δτ_rel_D = zero(τ_D) # Shapiro delay + # Δτ_corona_D = zero(τ_D) # Delay due to Solar corona + Δτ_tropo_D = zero(τ_D) # Delay due to Earth's troposphere + + for i in 1:niter + # Asteroid barycentric position (in km) and velocity (in km/s) at bounce time (TDB) + rv_a_t_b = xva(et_b_secs) + r_a_t_b = rv_a_t_b[1:3] + v_a_t_b = rv_a_t_b[4:6] + # Estimated position of the asteroid's center of mass relative to the recieve point + # See equation (3) of https://doi.org/10.1086/116062 + ρ_vec_r = r_a_t_b - r_r_t_r + # Magnitude of ρ_vec_r + # See equation (4) of https://doi.org/10.1086/116062 + ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) + + # Compute down-leg Shapiro delay + # NOTE: when using PPN, substitute 2 -> 1+γ in expressions for Shapiro delay, + # Δτ_rel_[D|U] + + # Earth's position at t_r + e_D_vec = r_r_t_r - r_s_t_r + # Heliocentric distance of Earth at t_r + e_D = sqrt(e_D_vec[1]^2 + e_D_vec[2]^2 + e_D_vec[3]^2) + # Barycentric position of Sun at estimated bounce time + rv_s_t_b = xvs(et_b_secs) + r_s_t_b = rv_s_t_b[1:3] + # Heliocentric position of asteroid at t_b + p_D_vec = r_a_t_b - r_s_t_b + # Heliocentric distance of asteroid at t_b + p_D = sqrt(p_D_vec[1]^2 + p_D_vec[2]^2 + p_D_vec[3]^2) + # Signal path distance (down-leg) + q_D = ρ_r + + # Shapiro correction to time-delay + Δτ_rel_D = shapiro_delay(e_D, p_D, q_D) # seconds + # Troposphere correction to time-delay + # Δτ_tropo_D = tropo_delay(R_r, ρ_vec_r) # seconds + # Solar corona correction to time-delay + # Δτ_corona_D = corona_delay(constant_term.(r_a_t_b), r_r_t_r, r_s_t_r, F_tx, station_code) # seconds + # Total time-delay + Δτ_D = Δτ_rel_D # + Δτ_tropo_D #+ Δτ_corona_D # seconds + + # New estimate + p_dot_23 = dot(ρ_vec_r, v_a_t_b)/ρ_r + # Time delay correction + Δt_2 = (τ_D - ρ_r/clightkms - Δτ_rel_D)/(1.0-p_dot_23/clightkms) + # Time delay new estimate + τ_D = τ_D - Δt_2 + # Bounce time, new estimate + # See equation (2) of https://doi.org/10.1086/116062 + et_b_secs = et_r_secs - τ_D + end + # Asteroid barycentric position (in km) and velocity (in km/s) at bounce time (TDB) + rv_a_t_b = xva(et_b_secs) + r_a_t_b = rv_a_t_b[1:3] + v_a_t_b = rv_a_t_b[4:6] + # Estimated position of the asteroid's center of mass relative to the recieve point + # See equation (3) of https://doi.org/10.1086/116062 + ρ_vec_r = r_a_t_b - r_r_t_r + # Magnitude of ρ_vec_r + # See equation (4) of https://doi.org/10.1086/116062 + ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) + + # TODO: add aberration and atmospheric refraction corrections + + # Compute gravitational deflection of light + # See Explanatory Supplement to the Astronomical Almanac (ESAA) 2014 Section 7.4.1.4 + E_H_vec = r_r_t_r -r_s_t_r # ESAA 2014, equation (7.104) + U_vec = ρ_vec_r # r_a_t_b - r_e_t_r, ESAA 2014, equation (7.112) + U_norm = ρ_r # sqrt(U_vec[1]^2 + U_vec[2]^2 + U_vec[3]^2) + u_vec = U_vec/U_norm + # Barycentric position and velocity of Sun at converged bounce time + rv_s_t_b = xvs(et_b_secs) + r_s_t_b = rv_s_t_b[1:3] + Q_vec = r_a_t_b - r_s_t_b # ESAA 2014, equation (7.113) + q_vec = Q_vec/sqrt(Q_vec[1]^2 + Q_vec[2]^2 + Q_vec[3]^2) + E_H = sqrt(E_H_vec[1]^2 + E_H_vec[2]^2 + E_H_vec[3]^2) + e_vec = E_H_vec/E_H + # See ESAA 2014, equation (7.115) + g1 = (2μ_DE430[su]/(c_au_per_day^2))/(E_H/au) + g2 = 1 + dot(q_vec, e_vec) + # See ESAA 2014, equation (7.116) + u1_vec = U_norm*( u_vec + (g1/g2)*( dot(u_vec,q_vec)*e_vec - dot(e_vec,u_vec)*q_vec ) ) + u1_norm = sqrt(u1_vec[1]^2 + u1_vec[2]^2 + u1_vec[3]^2) + + # Compute right ascension, declination angles + α_rad_ = mod2pi(atan(u1_vec[2], u1_vec[1])) + α_rad = mod2pi(α_rad_) # right ascension (rad) + δ_rad = asin(u1_vec[3]/u1_norm) # declination (rad) + + δ_as = rad2arcsec(δ_rad) # rad -> arcsec + debiasing + α_as = rad2arcsec(α_rad) # rad -> arcsec + debiasing + + return α_as, δ_as # right ascension, declination both in arcsec +end + +function compute_radec(obs::RadecMPC{T}; kwargs...) where {T <: AbstractFloat} + return compute_radec(obs.observatory, obs.date; kwargs...) +end + +function compute_radec(obs::Vector{RadecMPC{T}}; xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} + + # Number of observations + n_optical_obs = length(obs) + # UTC time of first astrometric observation + utc1 = obs[1].date + # TDB seconds since J2000.0 for first astrometric observation + et1 = datetime2et(utc1) + # Asteroid ephemeris at et1 + a1_et1 = xva(et1)[1] + # Type of asteroid ephemeris + S = typeof(a1_et1) + + # Right ascension + vra = Array{S}(undef, n_optical_obs) + # Declination + vdec = Array{S}(undef, n_optical_obs) + + # Iterate over the number of observations + for i in 1:n_optical_obs + vra[i], vdec[i] = compute_radec(obs[i]; xva = xva, kwargs...) + end + + return vra, vdec # arcsec, arcsec +end + +@doc raw""" + select_debiasing_table(debias_table::String = "2018") + +Return the catalogue codes, truth catalogue, resolution and bias matrix of the corresponding +debias table. The possible values for `debias_table` are: +- `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, +- `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, +- `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. +""" +function select_debiasing_table(debias_table::String = "2018") + # Debiasing tables are loaded "lazily" via Julia artifacts, according to rules in Artifacts.toml + if debias_table == "2018" + debias_path = artifact"debias_2018" + mpc_catalogue_codes_201X = mpc_catalogue_codes_2018 + # The healpix tesselation resolution of the bias map from https://doi.org/10.1016/j.icarus.2019.113596 + NSIDE = 64 + # In 2018 debias table Gaia DR2 catalogue is regarded as the truth + truth = "V" + elseif debias_table == "hires2018" + debias_path = artifact"debias_hires2018" + mpc_catalogue_codes_201X = mpc_catalogue_codes_2018 + # The healpix tesselation resolution of the high-resolution bias map from https://doi.org/10.1016/j.icarus.2019.113596 + NSIDE = 256 + # In 2018 debias table Gaia DR2 catalogue is regarded as the truth + truth = "V" + elseif debias_table == "2014" + debias_path = artifact"debias_2014" + mpc_catalogue_codes_201X = mpc_catalogue_codes_2014 + # The healpix tesselation resolution of the bias map from https://doi.org/10.1016/j.icarus.2014.07.033 + NSIDE= 64 + # In 2014 debias table PPMXL catalogue is regarded as the truth + truth = "t" + else + @error "Unknown bias map: $(debias_table). Possible values are `2014`, `2018` and `hires2018`." + end + + # Debias table file + bias_file = joinpath(debias_path, "bias.dat") + # Read bias matrix + bias_matrix = readdlm(bias_file, comment_char='!', comments=true) + # Initialize healpix Resolution variable + resol = Resolution(NSIDE) + # Compatibility between bias matrix and resolution + @assert size(bias_matrix) == (resol.numOfPixels, 4length(mpc_catalogue_codes_201X)) "Bias table file $bias_file dimensions do not match expected parameter NSIDE=$NSIDE and/or number of catalogs in table." + + return mpc_catalogue_codes_201X, truth, resol, bias_matrix +end + +@doc raw""" + debiasing(obs::RadecMPC{T}, mpc_catalogue_codes_201X::Vector{String}, truth::String, + resol::Resolution, bias_matrix::Matrix{T}) where {T <: AbstractFloat} + +Return total debiasing correction in right ascension and declination (both in arcsec). + +# Arguments + +- `obs::RadecMPC{T}`: optical observation. +- `mpc_catalogue_codes_201X::Vector{String}`: catalogues present in debiasing table. +- `truth::String`: truth catalogue of debiasing table. +- `resol::Resolution`: resolution. +- `bias_matrix::Matrix{T}`: debiasing table. +""" +function debiasing(obs::RadecMPC{T}, mpc_catalogue_codes_201X::Vector{String}, truth::String, + resol::Resolution, bias_matrix::Matrix{T}) where {T <: AbstractFloat} + + # Catalogue code + catcode = obs.catalogue.code + + # If star catalogue is not present in debiasing table, then set corrections equal to zero + if (catcode ∉ mpc_catalogue_codes_201X) && catcode != "Y" + # Catalogue exists in mpc_catalogues[] + if !isunknown(obs.catalogue) + # Truth catalogue is not present in debiasing table but it does not send a warning + if catcode != truth + @warn "Catalogue $(obs.catalogue.name) not found in debiasing table. Setting debiasing corrections equal to zero." + end + # Unknown catalogue + elseif catcode == "" + @warn "Catalog information not available in observation record. Setting debiasing corrections equal to zero." + # Catalogue code is not empty but it does not match an MPC catalogue code either + else + @warn "Catalog code $catcode does not correspond to MPC catalogue code. Setting debiasing corrections equal to zero." + end + α_corr = zero(T) + δ_corr = zero(T) + # If star catalogue is present in debiasing table, then compute corrections + else + # Get pixel tile index, assuming iso-latitude rings indexing, which is the formatting in `tiles.dat`. + # Substracting 1 from the returned value of `ang2pixRing` corresponds to 0-based indexing, as in `tiles.dat`; + # not substracting 1 from the returned value of `ang2pixRing` corresponds to 1-based indexing, as in Julia. + # Since we use pix_ind to get the corresponding row number in `bias.dat`, it's not necessary to substract 1. + pix_ind = ang2pixRing(resol, π/2 - obs.δ, obs.α) + + # Handle edge case: in new MPC catalogue nomenclature, "UCAC-5"->"Y"; but in debias tables "UCAC-5"->"W" + if catcode == "Y" + cat_ind = findfirst(x -> x == "W", mpc_catalogue_codes_201X) + else + cat_ind = findfirst(x -> x == catcode, mpc_catalogue_codes_201X) + end + + # Read dRA, pmRA, dDEC, pmDEC data from bias.dat + # dRA: position correction in RA * cos(DEC) at epoch J2000.0 [arcsec] + # dDEC: position correction in DEC at epoch J2000.0 [arcsec] + # pmRA: proper motion correction in RA*cos(DEC) [mas/yr] + # pmDEC: proper motion correction in DEC [mas/yr] + dRA, dDEC, pmRA, pmDEC = bias_matrix[pix_ind, 4*cat_ind-3:4*cat_ind] + # Seconds since J2000 (TDB) + et_secs_i = datetime2et(obs.date) + # Seconds sinde J2000 (TT) + tt_secs_i = et_secs_i - ttmtdb(et_secs_i/daysec) + # Years since J2000 + yrs_J2000_tt = tt_secs_i/(daysec*yr) + # Total debiasing correction in right ascension (arcsec) + α_corr = dRA + yrs_J2000_tt*pmRA/1_000 + # Total debiasing correction in declination (arcsec) + δ_corr = dDEC + yrs_J2000_tt*pmDEC/1_000 + end + + return α_corr, δ_corr +end + +@doc raw""" + w8sveres17(obs::RadecMPC{T}) where {T <: AbstractFloat} + +Return the statistical weight from Veres et al. (2017) corresponding to `obs`. +""" +function w8sveres17(obs::RadecMPC{T}) where {T <: AbstractFloat} + + obscode = obs.observatory.code + dt_utc_obs = obs.date + catalogue = obs.catalogue.code + + # Unit weight (arcseconds) + w = 1.0 + # Table 2: epoch-dependent astrometric residuals + if obscode == "703" + return Date(dt_utc_obs) < Date(2014,1,1) ? w : 0.8w + elseif obscode == "691" + return Date(dt_utc_obs) < Date(2003,1,1) ? 0.6w : 0.5w + elseif obscode == "644" + return Date(dt_utc_obs) < Date(2003,9,1) ? 0.6w : 0.4w + # Table 3: most active CCD asteroid observers + elseif obscode ∈ ("704", "C51", "J75") + return w + elseif obscode == "G96" + return 0.5w + elseif obscode == "F51" + return 0.2w + elseif obscode ∈ ("G45", "608") + return 0.6w + elseif obscode == "699" + return 0.8w + elseif obscode ∈ ("D29", "E12") + return 0.75w + # Table 4: + elseif obscode ∈ ("645", "673", "H01") + return 0.3w + elseif obscode ∈ ("J04", "K92", "K93", "Q63", "Q64", "V37", "W85", "W86", "W87", "K91", "E10", "F65") #Tenerife + Las Cumbres + return 0.4w + elseif obscode ∈ ("689", "950", "W84") + return 0.5w + #elseif obscode ∈ ("G83", "309") # Applies only to program code assigned to M. Micheli + # if catalogue ∈ ("q", "t") # "q"=>"UCAC-4", "t"=>"PPMXL" + # return 0.3w + # elseif catalogue ∈ ("U", "V") # Gaia-DR1, Gaia-DR2 + # return 0.2w + # end + elseif obscode ∈ ("Y28",) + if catalogue ∈ ("t", "U", "V") + return 0.3w + else + return w + end + elseif obscode ∈ ("568",) + if catalogue ∈ ("o", "s") # "o"=>"USNO-B1.0", "s"=>"USNO-B2.0" + return 0.5w + elseif catalogue ∈ ("U", "V") # Gaia DR1, DR2 + return 0.1w + elseif catalogue ∈ ("t",) #"t"=>"PPMXL" + return 0.2w + else + return w + end + elseif obscode ∈ ("T09", "T12", "T14") && catalogue ∈ ("U", "V") # Gaia DR1, DR2 + return 0.1w + elseif catalogue == "" + return 1.5w + elseif catalogue != "" + return w + else + return w + end +end + +@doc raw""" + relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + +Return a relax factor for each element of `radec` quantifying the correlation between +observations taken on the same night by the same observatory. + +!!! reference + See https://doi.org/10.1016/j.icarus.2017.05.021. +""" +function relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + # Convert to DataFrame + df = DataFrame(radec) + # Group by observatory and TimeOfDay + df.TimeOfDay = TimeOfDay.(df.date, df.observatory) + gdf = groupby(df, [:observatory, :TimeOfDay]) + # Interpolate observation nights + cdf = combine(gdf, nrow) + # Count observations in each group + Nv = cdf[gdf.groups, :nrow] + # Relaxation factor + return map(x -> x > 4.0 ? x/4.0 : 1.0, Nv) +end + +# Angle difference taking into account the discontinuity in [0, 2π] -> [0, 2π] +# x and y must be in arcsec +function anglediff(x::T, y::S) where {T, S <: Number} + # Signed difference + Δ = x - y + # Absolute difference + Δ_abs = abs(Δ) + # Reflection + if Δ_abs > 648_000 # Half circle in arcsec + return -sign(cte(Δ)) * (1_296_000 - Δ_abs) + else + return Δ + end +end + +@doc raw""" + residuals(obs::Vector{RadecMPC{T}}; kwargs...) where {T <: AbstractFloat, AstEph} + +Compute O-C residuals for optical astrometry. Corrections due to Earth orientation, LOD, +polar motion are computed by default. + +See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and +[`Healpix.ang2pixRing`](@ref). + +# Arguments + +- `obs::Vector{RadecMPC{T}}`: vector of observations. + +# Keyword arguments + +- `niter::Int = 5`: number of light-time solution iterations. +- `debias_table::String = "2018"`: possible values are: + - `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, + - `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, + - `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. +- `xve::EarthEph = earthposvel`: Earth ephemeris. +- `xvs::SunEph = sunposvel`: Sun ephemeris. +- `xva::AstEph`: asteroid ephemeris. + +All ephemeris must take [et seconds since J2000] and return [barycentric position in km +and velocity in km/sec]. +""" +function residuals(obs::Vector{RadecMPC{T}}; debias_table::String = "2018", xva::AstEph, + kwargs...) where {T <: AbstractFloat, AstEph} + mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) + return residuals(obs, mpc_catalogue_codes_201X, truth, resol, bias_matrix; xva, kwargs...) +end +function residuals(obs::Vector{RadecMPC{T}}, mpc_catalogue_codes_201X::Vector{String}, truth::String, + resol::Resolution, bias_matrix::Matrix{T}; xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} + + # Number of observations + N_obs = length(obs) + + # UTC time of first astrometric observation + utc1 = date(obs[1]) + # TDB seconds since J2000.0 for first astrometric observation + et1 = datetime2et(utc1) + # Asteroid ephemeris at et1 + a1_et1 = xva(et1)[1] + # Type of asteroid ephemeris + S = typeof(a1_et1) + + # Relax factors + rex = relax_factor(obs) + + # Vector of residuals + res = Vector{OpticalResidual{T, S}}(undef, N_obs) + + # Iterate over the observations + Threads.@threads for i in 1:N_obs + + # Observed ra/dec + α_obs = rad2arcsec(ra(obs[i])) # arcsec + δ_obs = rad2arcsec(dec(obs[i])) # arcsec + + # Computed ra/dec + α_comp, δ_comp = compute_radec(obs[i]; xva, kwargs...) # arcsec + + # Debiasing corrections + α_corr, δ_corr = debiasing(obs[i], mpc_catalogue_codes_201X, truth, resol, bias_matrix) + + # Statistical weights from Veres et al. (2017) + w8 = w8sveres17(obs[i]) + + # O-C residual ra/dec + # Note: ra is multiplied by a metric factor cos(dec) to match the format of debiasing corrections + res[i] = OpticalResidual( + anglediff(α_obs, α_comp) * cos(dec(obs[i])) - α_corr, + δ_obs - δ_comp - δ_corr, + 1 / w8^2, + 1 / w8^2, + rex[i], + false + ) + + end + + return res +end + +@doc raw""" + extrapolation(df::AbstractDataFrame) + +Special method of [`extrapolation`](@ref) to be used by [`gaussinitcond`](@ref). +""" +function extrapolation(df::AbstractDataFrame) + # Only one observation + if isone(nrow(df)) + return (observatory = df.observatory[1], date = df.date[1], α = df.α[1], + δ = df.δ[1], v_α = 0.0, v_δ = 0.0) + end + + # Make sure there are no repeated dates + gdf = groupby(df, :date) + df = combine(gdf, [:α, :δ] .=> mean, :observatory => identity, renamecols = false) + + # Julian days of observation + df.t_julian = datetime2julian.(df.date) + # Days of observation [relative to first observation] + df.t_rel = df.t_julian .- df.t_julian[1] + # Mean date + t_mean = mean(df.t_rel) + + # Points in top quarter + N_top = count(x -> x > 3π/2, df.α) + # Points in bottom quarter + N_bottom = count(x -> x < π/2, df.α) + # Discontinuity + if !iszero(N_top) && !iszero(N_bottom) + df.α = map(x -> x < π ? x + 2π : x, df.α) + end + # Linear regression + α_p = lm(@formula(α ~ t_rel), df) + α_coef = coef(α_p) + δ_p = lm(@formula(δ ~ t_rel), df) + δ_coef = coef(δ_p) + + # Evaluate polynomials at mean date + α_mean = mod2pi(α_coef[1] + α_coef[2] * t_mean) + δ_mean = δ_coef[1] + δ_coef[2] * t_mean + + return (observatory = df.observatory[1], date = julian2datetime(df.t_julian[1] + t_mean), + α = α_mean, δ = δ_mean, v_α = α_coef[2], v_δ = δ_coef[2]) +end + +@doc raw""" + reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + +Return one observatory, date, right ascension and declination per observation night in `radec`. The reduction is performed +via polynomial interpolation. +""" +function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + # Convert to DataFrame + df = DataFrame(radec) + # Compute TimeOfDay + df.TimeOfDay = TimeOfDay.(df.date, df.observatory) + # Group by observatory and TimeOfDay + gdf = groupby(df, [:observatory, :TimeOfDay]) + # Interpolate observation nights + cdf = combine(gdf, extrapolation, keepkeys = false) + # Eliminate unsuccesful interpolations + filter!(:α => !isnan, cdf) + filter!(:δ => !isnan, cdf) + # Sort by date + idxs = sortperm(cdf, :date) + + return gdf[idxs], cdf[idxs, :] end \ No newline at end of file diff --git a/src/observations/radar_jpl.jl b/src/observations/radar_jpl.jl old mode 100644 new mode 100755 index 293511f7..58746f39 --- a/src/observations/radar_jpl.jl +++ b/src/observations/radar_jpl.jl @@ -1,380 +1,349 @@ -@doc raw""" - RadarJPL{T <: AbstractFloat} <: AbstractAstrometry - -A radar measurement in JPL format. - -# Fields - -- `id::String`: object's name and number. -- `date::DateTime`: date of observation. -- `τ::T`: time-delay. -- `τ_σ::T`: time-delay uncertainty. -- `τ_units::String`: units of time delay. -- `Δν::T`: Doppler shift. -- `Δν_σ::T`: Doppler shift uncertainty. -- `Δν_units::String`: units of Doppler shift. -- `freq::T`: frequency of the measurement. -- `rcvr::ObservatoryMPC{T}`: reciever antenna. -- `xmit::ObservatoryMPC{T}`: emission antenna. -- `bouncepoint::String`: bounce point. - ---- - - RadarJPL(delay::RegexMatch, doppler::RegexMatch) - RadarJPL(delay::RegexMatch, doppler::Val{false}) - RadarJPL(delay::Val{false}, doppler::RegexMatch) - RadarJPL(delay::Val{false}, doppler::Val{false}) - -Convert a match of `NEOs.jpl_radar_regex` to `RadarJPL`. A `Val{false}` indicates that one or both of the measurements -(time delay or Doppler shift) are missing. -""" -@auto_hash_equals struct RadarJPL{T <: AbstractFloat} <: AbstractAstrometry - id::String - date::DateTime - Δτ::T - Δτ_σ::T - Δτ_units::String - Δν::T - Δν_σ::T - Δν_units::String - freq::T - rcvr::ObservatoryMPC{T} - xmit::ObservatoryMPC{T} - bouncepoint::String - # Inner constructor - function RadarJPL{T}(id::String, date::DateTime, Δτ::T, Δτ_σ::T, Δτ_units::String, Δν::T, Δν_σ::T, Δν_units::String, - freq::T, rcvr::ObservatoryMPC{T}, xmit::ObservatoryMPC{T}, bouncepoint::String) where {T <: AbstractFloat} - return new{T}(id, date, Δτ, Δτ_σ, Δτ_units, Δν, Δν_σ, Δν_units, freq, rcvr, xmit, bouncepoint) - end -end - -# Outer constructor -function RadarJPL(id::String, date::DateTime, Δτ::T, Δτ_σ::T, Δτ_units::String, Δν::T, Δν_σ::T, Δν_units::String, freq::T, - rcvr::ObservatoryMPC{T}, xmit::ObservatoryMPC{T}, bouncepoint::String) where {T <: AbstractFloat} - return RadarJPL{T}(id, date, Δτ, Δτ_σ, Δτ_units, Δν, Δν_σ, Δν_units, freq, rcvr, xmit, bouncepoint) -end - -@doc raw""" - hasdelay(r::RadarJPL{T}) where {T <: AbstractFloat} - -Check whether `r` has a non `NaN` time delay. -""" -hasdelay(r::RadarJPL{T}) where {T <: AbstractFloat} = !isnan(r.Δτ) - -@doc raw""" - hasdoppler(r::RadarJPL{T}) where {T <: AbstractFloat} - -Check whether `r` has a non `NaN` Doppler shift. -""" -hasdoppler(r::RadarJPL{T}) where {T <: AbstractFloat} = !isnan(r.Δν) - -# Order in RadecMPC and RadarJPL is given by date -isless(a::T, b::T) where {T <: AbstractAstrometry} = a.date < b.date - -# Print method for RadarJPL -# Examples: -# 99942 Apophis (2004 MN4) Δτ: 1.9202850713e8 us Δν: -102512.9059 Hz t: 2005-01-29T00:00:00 -# 99942 Apophis (2004 MN4) Δν: -100849.1434 Hz t: 2005-01-27T23:31:00 -# 99942 Apophis (2004 MN4) Δτ: 9.743930871e7 us t: 2013-01-03T10:00:00 -function show(io::IO, r::RadarJPL{T}) where {T <: AbstractFloat} - - delay = hasdelay(r) - doppler = hasdoppler(r) - - if delay && doppler - measurement_s = join([" Δτ: ", string(r.Δτ), " ", r.Δτ_units, " Δν: ", string(r.Δν), " ", r.Δν_units]) - elseif delay - measurement_s = join([" Δτ: ", string(r.Δτ), " ", r.Δτ_units]) - elseif doppler - measurement_s = join([" Δν: ", string(r.Δν), " ", r.Δν_units]) - else - measurement_s = " No measurements " - end - - print(io, r.id, measurement_s, " t: ", r.date, " obs: ", r.rcvr.name) - -end - -# Functions to get specific fields of a RadarJPL object -date(r::T) where {T <: AbstractAstrometry} = r.date -delay(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δτ -delay_sigma(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δτ_σ -delay_units(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δτ_units -doppler(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δν -doppler_sigma(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δν_σ -doppler_units(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δν_units -freq(r::RadarJPL{T}) where {T <: AbstractFloat} = r.freq -rcvr(r::RadarJPL{T}) where {T <: AbstractFloat} = r.rcvr -xmit(r::RadarJPL{T}) where {T <: AbstractFloat} = r.xmit -bouncepoint(r::RadarJPL{T}) where {T <: AbstractFloat} = r.bouncepoint - -@doc raw""" - ismonostatic(rdata::RadarJPL) - -Check whether a radar astrometric observation is monostatic, i.e., receiver and transmitter are the same. -""" -ismonostatic(r::RadarJPL{T}) where {T <: AbstractFloat} = r.rcvr == r.xmit - -@doc raw""" - issband(f_MHz::T) where {T<:Real} - -Check whether the transmission frequency `f_MHz` (in MHz) belongs to the S band -(IEEE nomenclature). -""" -issband(f_MHz::T) where {T<:Real} = 2000.0 ≤ f_MHz ≤ 4000.0 - -@doc raw""" - isxband(f_MHz::T) where {T<:Real} - -Check whether the transmission frequency `f_MHz` (in MHz) belongs to the X band -(IEEE nomenclature). -""" -isxband(f_MHz::T) where {T<:Real} = 8000.0 ≤ f_MHz ≤ 12000.0 - -# Regular expression to parse a radar measurement in JPL format -const jpl_radar_regex = Regex(join( - [ - # ID regex + tab - raw"(?P.*)\t", - # Date regex + tab - raw"(?P.*)\t", - # Measurement regex + tab - raw"(?P.*)\t", - # Uncertainty regex + tab - raw"(?P.*)\t", - # Units regex + tab - raw"(?P.*)\t", - # Frequency regex + tab - raw"(?P.*)\t", - # Reciever regex + tab - raw"(?P.*)\t", - # Emitter regex + tab - raw"(?P.*)\t", - # Bouncepoint regex + end of line - raw"(?P.*)" - ] -)) - -# Format of date in JPL radar data files -const jpl_radar_dateformat = "yyyy-mm-dd HH:MM:SS" - -for (X, Y) in Iterators.product( (:(Val{false}), :(RegexMatch)), (:(Val{false}), :(RegexMatch)) ) - @eval begin - function RadarJPL(delay::$X, doppler::$Y) - - if $X == RegexMatch - id = string(delay["id"]) - elseif $Y == RegexMatch - id = string(doppler["id"]) - else - id = "" - end - - if $X == RegexMatch - date = DateTime(delay["date"], jpl_radar_dateformat) - elseif $Y == RegexMatch - date = DateTime(doppler["date"], jpl_radar_dateformat) - else - date = DateTime(2000, 1, 1) - end - - if $X == RegexMatch - Δτ = Meta.parse(delay["measurement"]) - Δτ_σ = Meta.parse(delay["uncertainty"]) - Δτ_units = string(delay["units"]) - else - Δτ = NaN - Δτ_σ = NaN - Δτ_units = "" - end - - if $Y == RegexMatch - Δν = Meta.parse(doppler["measurement"]) - Δν_σ = Meta.parse(doppler["uncertainty"]) - Δν_units = string(doppler["units"]) - else - Δν = NaN - Δν_σ = NaN - Δν_units = "" - end - - if $X == RegexMatch - freq = Float64(Meta.parse(delay["freq"])) - elseif $Y == RegexMatch - freq = Float64(Meta.parse(doppler["freq"])) - else - freq = NaN - end - - if $X == RegexMatch - rcvr = search_obs_code(string(delay["rcvr"])) - elseif $Y == RegexMatch - rcvr = search_obs_code(string(doppler["rcvr"])) - else - rcvr = unknownobs() - end - - if $X == RegexMatch - xmit = search_obs_code(string(delay["xmit"])) - elseif $Y == RegexMatch - xmit = search_obs_code(string(doppler["xmit"])) - else - xmit = unknownobs() - end - - if $X == RegexMatch - bouncepoint = string(delay["bouncepoint"]) - elseif $Y == RegexMatch - bouncepoint = string(doppler["bouncepoint"]) - else - bouncepoint = "" - end - - return RadarJPL(id, date, Δτ, Δτ_σ, Δτ_units, Δν, Δν_σ, Δν_units, freq, rcvr, xmit, bouncepoint) - end - end -end - -@doc raw""" - read_radar_jpl(filename::String) - -Return the matches of `NEOs.jpl_radar_regex` in `filename` as `Vector{RadarJPL}`. -""" -function read_radar_jpl(filename::String) - - # Read lines of jpl formatted file - lines = readlines(filename) - # Apply regular expressions - matches = match.(jpl_radar_regex, lines) - # Eliminate nothings - filter!(!isnothing, matches) - # Number of matches - m = length(matches) - - # Dates of observation (as string) - dates = getindex.(matches, "date") - # Eliminate repeated dates - unique!(dates) - # Number of dates - m_dates = length(dates) - - # Time delays - delay = filter(x -> x["units"] == "us", matches) - # Number of time delays - m_Δτ = length(delay) - # Doppler shifts - doppler = filter(x -> x["units"] == "Hz", matches) - # Number of Doppler shifts - m_Δν = length(doppler) - - # Check if there were observations with unknown units - if m > m_Δτ + m_Δν - @warn("""$(m - m_Δτ - m_Δν) observations have units other than us (time delay) or Hz (doppler shift)""") - end - - # Vector of radar observations - radar = Vector{RadarJPL{Float64}}(undef, m_dates) - # Time delay index - i_τ = 1 - # Doppler shift index - i_ν = 1 - - # Iterate over the dates - for i in eachindex(dates) - # The i_τ-th time delay has the i-th date - if (i_τ <= m_Δτ) && (delay[i_τ]["date"] == dates[i]) - Δτ = delay[i_τ] - i_τ += 1 - flag_τ = true - else - flag_τ = false - end - - # The i_ν-th Doppler shift has the i-th date - if (i_ν <= m_Δν) && (doppler[i_ν]["date"] == dates[i]) - Δν = doppler[i_ν] - i_ν += 1 - flag_ν = true - else - flag_ν = false - end - - if flag_τ && flag_ν - radar[i] = RadarJPL(Δτ, Δν) - elseif flag_τ - radar[i] = RadarJPL(Δτ, Val(false)) - elseif flag_ν - radar[i] = RadarJPL(Val(false), Δν) - else - @warn("""Date $(dates[i]) has no time delay nor Doppler shift measurements""") - radar[i] = RadarJPL(Val(false), Val(false)) - end - - end - - # Sort radar measurements by date - sort!(radar) - - return radar -end - -@doc raw""" - jpl_radar_str(radar::RadarJPL{T}) where {T <: AbstractFloat} - -Return an observation in JPL format. -""" -function jpl_radar_str(radar::RadarJPL{T}) where {T <: AbstractFloat} - - if hasdelay(radar) - delay_s = join([ - radar.id, - Dates.format(radar.date, jpl_radar_dateformat), - @sprintf("%.2f", radar.Δτ), - @sprintf("%1.3f", radar.Δτ_σ), - radar.Δτ_units, - @sprintf("%.0f", radar.freq), - radar.rcvr.code, - radar.xmit.code, - radar.bouncepoint, - "" - ], "\t", "\n") - else - delay_s = "" - end - - if hasdoppler(radar) - doppler_s = join([ - radar.id, - Dates.format(radar.date, jpl_radar_dateformat), - @sprintf("%.4f", radar.Δν), - @sprintf("%1.3f", radar.Δν_σ), - radar.Δν_units, - @sprintf("%.0f", radar.freq), - radar.rcvr.code, - radar.xmit.code, - radar.bouncepoint, - "" - ], "\t", "\n") - else - doppler_s = "" - end - - # Join everything - radar_s = join([delay_s, doppler_s]) - - return radar_s -end - -@doc raw""" - write_radar_jpl(radar::Vector{RadarJPL{T}}, filename::String) where {T <: AbstractFloat} - -Write `radar` to `filename` in JPL format. -""" -function write_radar_jpl(radar::Vector{RadarJPL{T}}, filename::String) where {T <: AbstractFloat} - open(filename, "w") do file - for i in eachindex(radar) - line = jpl_radar_str(radar[i]) - write(file, line) - end - end -end +@doc raw""" + RadarJPL{T <: AbstractFloat} <: AbstractAstrometry + +A radar measurement in JPL format. + +# Fields + +- `id::String`: object's name and number. +- `date::DateTime`: date of observation. +- `Δτ::T`: time-delay. +- `Δτ_σ::T`: time-delay uncertainty. +- `Δτ_units::String`: units of time delay. +- `Δν::T`: Doppler shift. +- `Δν_σ::T`: Doppler shift uncertainty. +- `Δν_units::String`: units of Doppler shift. +- `freq::T`: frequency of the measurement. +- `rcvr::ObservatoryMPC{T}`: reciever antenna. +- `xmit::ObservatoryMPC{T}`: emission antenna. +- `bouncepoint::String`: bounce point. + +--- + + RadarJPL(delay::RegexMatch, doppler::RegexMatch) + RadarJPL(delay::RegexMatch, doppler::Val{false}) + RadarJPL(delay::Val{false}, doppler::RegexMatch) + RadarJPL(delay::Val{false}, doppler::Val{false}) + +Convert a match of `NEOs.RADAR_JPL_REGEX` to `RadarJPL`. A `Val{false}` indicates +that one or both of the measurements (time delay or Doppler shift) are missing. +""" +@auto_hash_equals struct RadarJPL{T <: AbstractFloat} <: AbstractAstrometry + id::String + date::DateTime + Δτ::T + Δτ_σ::T + Δτ_units::String + Δν::T + Δν_σ::T + Δν_units::String + freq::T + rcvr::ObservatoryMPC{T} + xmit::ObservatoryMPC{T} + bouncepoint::String + # Inner constructor + function RadarJPL{T}(id::String, date::DateTime, Δτ::T, Δτ_σ::T, Δτ_units::String, + Δν::T, Δν_σ::T, Δν_units::String, freq::T, rcvr::ObservatoryMPC{T}, + xmit::ObservatoryMPC{T}, bouncepoint::String) where {T <: AbstractFloat} + return new{T}(id, date, Δτ, Δτ_σ, Δτ_units, Δν, Δν_σ, Δν_units, freq, rcvr, + xmit, bouncepoint) + end +end + +# Outer constructor +function RadarJPL(id::String, date::DateTime, Δτ::T, Δτ_σ::T, Δτ_units::String, Δν::T, + Δν_σ::T, Δν_units::String, freq::T, rcvr::ObservatoryMPC{T}, + xmit::ObservatoryMPC{T}, bouncepoint::String) where {T <: AbstractFloat} + return RadarJPL{T}(id, date, Δτ, Δτ_σ, Δτ_units, Δν, Δν_σ, Δν_units, freq, rcvr, + xmit, bouncepoint) +end + +@doc raw""" + hasdelay(r::RadarJPL{T}) where {T <: AbstractFloat} + +Check whether `r` has a non `NaN` time delay. +""" +hasdelay(r::RadarJPL{T}) where {T <: AbstractFloat} = !isnan(r.Δτ) + +@doc raw""" + hasdoppler(r::RadarJPL{T}) where {T <: AbstractFloat} + +Check whether `r` has a non `NaN` Doppler shift. +""" +hasdoppler(r::RadarJPL{T}) where {T <: AbstractFloat} = !isnan(r.Δν) + +# Print method for RadarJPL +# Examples: +# 99942 Apophis (2004 MN4) Δτ: 1.9202850713e8 us Δν: -102512.9059 Hz t: 2005-01-29T00:00:00 +# 99942 Apophis (2004 MN4) Δν: -100849.1434 Hz t: 2005-01-27T23:31:00 +# 99942 Apophis (2004 MN4) Δτ: 9.743930871e7 us t: 2013-01-03T10:00:00 +function show(io::IO, r::RadarJPL{T}) where {T <: AbstractFloat} + + delay = hasdelay(r) + doppler = hasdoppler(r) + + if delay && doppler + measurement_s = string(" Δτ: ", string(r.Δτ), " ", r.Δτ_units, " Δν: ", + string(r.Δν), " ", r.Δν_units) + elseif delay + measurement_s = string(" Δτ: ", string(r.Δτ), " ", r.Δτ_units) + elseif doppler + measurement_s = string(" Δν: ", string(r.Δν), " ", r.Δν_units) + else + measurement_s = " No measurements " + end + + print(io, r.id, measurement_s, " t: ", r.date, " obs: ", r.rcvr.name) + +end + +# Functions to get specific fields of a RadarJPL object +delay(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δτ +delay_sigma(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δτ_σ +delay_units(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δτ_units +doppler(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δν +doppler_sigma(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δν_σ +doppler_units(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δν_units +freq(r::RadarJPL{T}) where {T <: AbstractFloat} = r.freq +rcvr(r::RadarJPL{T}) where {T <: AbstractFloat} = r.rcvr +xmit(r::RadarJPL{T}) where {T <: AbstractFloat} = r.xmit +bouncepoint(r::RadarJPL{T}) where {T <: AbstractFloat} = r.bouncepoint + +@doc raw""" + ismonostatic(rdata::RadarJPL) + +Check whether a radar astrometric observation is monostatic, i.e., receiver and transmitter are the same. +""" +ismonostatic(r::RadarJPL{T}) where {T <: AbstractFloat} = r.rcvr == r.xmit + +@doc raw""" + issband(f_MHz::T) where {T<:Real} + +Check whether the transmission frequency `f_MHz` (in MHz) belongs to the S band +(IEEE nomenclature). +""" +issband(f_MHz::T) where {T<:Real} = 2000.0 ≤ f_MHz ≤ 4000.0 + +@doc raw""" + isxband(f_MHz::T) where {T<:Real} + +Check whether the transmission frequency `f_MHz` (in MHz) belongs to the X band +(IEEE nomenclature). +""" +isxband(f_MHz::T) where {T<:Real} = 8000.0 ≤ f_MHz ≤ 12000.0 + +for (X, Y) in Iterators.product( (:(Val{false}), :(RegexMatch)), (:(Val{false}), :(RegexMatch)) ) + @eval begin + function RadarJPL(delay::$X, doppler::$Y) + + if $X == RegexMatch + id = string(delay["id"]) + elseif $Y == RegexMatch + id = string(doppler["id"]) + else + id = "" + end + + if $X == RegexMatch + date = DateTime(delay["date"], RADAR_JPL_DATEFORMAT) + elseif $Y == RegexMatch + date = DateTime(doppler["date"], RADAR_JPL_DATEFORMAT) + else + date = DateTime(2000, 1, 1) + end + + if $X == RegexMatch + Δτ = Meta.parse(delay["measurement"]) + Δτ_σ = Meta.parse(delay["uncertainty"]) + Δτ_units = string(delay["units"]) + else + Δτ = NaN + Δτ_σ = NaN + Δτ_units = "" + end + + if $Y == RegexMatch + Δν = Meta.parse(doppler["measurement"]) + Δν_σ = Meta.parse(doppler["uncertainty"]) + Δν_units = string(doppler["units"]) + else + Δν = NaN + Δν_σ = NaN + Δν_units = "" + end + + if $X == RegexMatch + freq = Float64(Meta.parse(delay["freq"])) + elseif $Y == RegexMatch + freq = Float64(Meta.parse(doppler["freq"])) + else + freq = NaN + end + + if $X == RegexMatch + rcvr = search_obs_code(string(delay["rcvr"])) + elseif $Y == RegexMatch + rcvr = search_obs_code(string(doppler["rcvr"])) + else + rcvr = unknownobs() + end + + if $X == RegexMatch + xmit = search_obs_code(string(delay["xmit"])) + elseif $Y == RegexMatch + xmit = search_obs_code(string(doppler["xmit"])) + else + xmit = unknownobs() + end + + if $X == RegexMatch + bouncepoint = string(delay["bouncepoint"]) + elseif $Y == RegexMatch + bouncepoint = string(doppler["bouncepoint"]) + else + bouncepoint = "" + end + + return RadarJPL(id, date, Δτ, Δτ_σ, Δτ_units, Δν, Δν_σ, Δν_units, freq, rcvr, xmit, bouncepoint) + end + end +end + +@doc raw""" + read_radar_jpl(filename::String) + +Return the matches of `NEOs.RADAR_JPL_REGEX` in `filename` as `Vector{RadarJPL{Float64}}`. +""" +function read_radar_jpl(filename::String) + + # Read lines of jpl formatted file + lines = readlines(filename) + # Apply regular expressions + matches = match.(RADAR_JPL_REGEX, lines) + # Eliminate nothings + filter!(!isnothing, matches) + # Number of matches + m = length(matches) + + # Dates of observation (as string) + dates = getindex.(matches, "date") + # Eliminate repeated dates + unique!(dates) + # Number of dates + m_dates = length(dates) + + # Time delays + delay = filter(x -> x["units"] == "us", matches) + # Number of time delays + m_Δτ = length(delay) + # Doppler shifts + doppler = filter(x -> x["units"] == "Hz", matches) + # Number of Doppler shifts + m_Δν = length(doppler) + + # Check if there were observations with unknown units + if m > m_Δτ + m_Δν + @warn("""$(m - m_Δτ - m_Δν) observations have units other than us (time delay) or Hz (doppler shift)""") + end + + # Vector of radar observations + radar = Vector{RadarJPL{Float64}}(undef, m_dates) + # Time delay index + i_τ = 1 + # Doppler shift index + i_ν = 1 + + # Iterate over the dates + for i in eachindex(dates) + # The i_τ-th time delay has the i-th date + if (i_τ <= m_Δτ) && (delay[i_τ]["date"] == dates[i]) + Δτ = delay[i_τ] + i_τ += 1 + flag_τ = true + else + flag_τ = false + end + + # The i_ν-th Doppler shift has the i-th date + if (i_ν <= m_Δν) && (doppler[i_ν]["date"] == dates[i]) + Δν = doppler[i_ν] + i_ν += 1 + flag_ν = true + else + flag_ν = false + end + + if flag_τ && flag_ν + radar[i] = RadarJPL(Δτ, Δν) + elseif flag_τ + radar[i] = RadarJPL(Δτ, Val(false)) + elseif flag_ν + radar[i] = RadarJPL(Val(false), Δν) + else + @warn("""Date $(dates[i]) has no time delay nor Doppler shift measurements""") + radar[i] = RadarJPL(Val(false), Val(false)) + end + + end + + # Sort radar measurements by date + sort!(radar) + + return radar +end + +# Convert `radar` to a string according to JPL format. +function string(radar::RadarJPL{T}) where {T <: AbstractFloat} + if hasdelay(radar) + delay_s = join([ + radar.id, + Dates.format(radar.date, RADAR_JPL_DATEFORMAT), + @sprintf("%.2f", radar.Δτ), + @sprintf("%1.3f", radar.Δτ_σ), + radar.Δτ_units, + @sprintf("%.0f", radar.freq), + radar.rcvr.code, + radar.xmit.code, + radar.bouncepoint, + "" + ], "\t", "\n") + else + delay_s = "" + end + + if hasdoppler(radar) + doppler_s = join([ + radar.id, + Dates.format(radar.date, RADAR_JPL_DATEFORMAT), + @sprintf("%.4f", radar.Δν), + @sprintf("%1.3f", radar.Δν_σ), + radar.Δν_units, + @sprintf("%.0f", radar.freq), + radar.rcvr.code, + radar.xmit.code, + radar.bouncepoint, + "" + ], "\t", "\n") + else + doppler_s = "" + end + + # Join everything + radar_s = string(delay_s, doppler_s) + + return radar_s +end + +@doc raw""" + write_radar_jpl(radar::Vector{RadarJPL{T}}, filename::String) where {T <: AbstractFloat} + +Write `radar` to `filename` in JPL format. +""" +function write_radar_jpl(radar::Vector{RadarJPL{T}}, filename::String) where {T <: AbstractFloat} + open(filename, "w") do file + for i in eachindex(radar) + line = string(radar[i]) + write(file, line) + end + end +end diff --git a/src/observations/radec_mpc.jl b/src/observations/radec_mpc.jl old mode 100644 new mode 100755 index 022705b7..809e3009 --- a/src/observations/radec_mpc.jl +++ b/src/observations/radec_mpc.jl @@ -1,484 +1,431 @@ -abstract type AbstractAstrometry end -struct RightAscension <: AbstractAstrometry end -struct Declination <: AbstractAstrometry end - -@doc raw""" - RadecMPC{T <: AbstractFloat} <: AbstractAstrometry - -An optical (α, δ) measurement in MPC format. The format is described in https://minorplanetcenter.net/iau/info/OpticalObs.html -and discussed thoroughly in pages 158-181 of https://doi.org/10.1016/j.icarus.2010.06.003. - -# Fields - -- `num::String`: object's number. -- `tmpdesig::String`: provisional / temporary designation. -- `discovery::String`: discovery asterisk. -- `publishnote::String`: publishable note. -- `obstech::String`: observation technique. -- `date::DateTime`: date of observation. -- `α::T`: right ascension [rad]. -- `δ::T`: declination [rad]. -- `info1::String`: additional information. -- `mag::T`: observed magnitude. -- `band::String`: magnitude band. -- `catalogue::CatalogueMPC`: catalogue. -- `info2::String`: additional information. -- `observatory::ObservatoryMPC{T}`: observatory. -""" -@auto_hash_equals struct RadecMPC{T <: AbstractFloat} <: AbstractAstrometry - num::String - tmpdesig::String - discovery::String - publishnote::String - obstech::String - date::DateTime - α::T - δ::T - info1::String - mag::T - band::String - catalogue::CatalogueMPC - info2::String - observatory::ObservatoryMPC{T} - # Inner constructor - function RadecMPC{T}(num::String, tmpdesig::String, discovery::String, publishnote::String, - obstech::String, date::DateTime, α::T, δ::T, info1::String, mag::T, - band::String, catalogue::CatalogueMPC, info2::String, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - new{T}(num, tmpdesig, discovery, publishnote, obstech, date, α, δ, info1, mag, band, - catalogue, info2, observatory) - end -end - -# Outer constructor -function RadecMPC(num::String, tmpdesig::String, discovery::String, publishnote::String, - obstech::String, date::DateTime, α::T, δ::T, info1::String, mag::T, - band::String, catalogue::CatalogueMPC, info2::String, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - RadecMPC{T}(num, tmpdesig, discovery, publishnote, obstech, date, α, δ, info1, mag, band, - catalogue, info2, observatory) -end - -function RadecMPC(date::DateTime, α::T, δ::T, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - RadecMPC{T}("", "", "", "", "", date, α, δ, "", "", "", unknowncat(), "", observatory) -end - -# Print method for RadecMPC -# Examples: -# N00hp15 α: 608995.65 δ: -25653.3 t: 2020-12-04T10:41:43.209 obs: 703 -# 99942 α: 422475.3 δ: 97289.49 t: 2021-05-12T06:28:35.904 obs: F51 -function show(io::IO, m::RadecMPC{T}) where {T <: AbstractFloat} - # If there is no number, use temporary designation - id_str = filter(!isspace, m.num) == "" ? m.tmpdesig : m.num - - print(io, id_str, " α: ", @sprintf("%.5f", rad2deg(m.α)), "° δ: ", @sprintf("%.5f", rad2deg(m.δ)), "° t: ", m.date, - " obs: ", m.observatory.name) -end - -# Functions to get specific fields of a RadecMPC object -num(r::RadecMPC{T}) where {T <: AbstractFloat} = r.num -tmpdesig(r::RadecMPC{T}) where {T <: AbstractFloat} = r.tmpdesig -discovery(r::RadecMPC{T}) where {T <: AbstractFloat} = r.discovery -publishnote(r::RadecMPC{T}) where {T <: AbstractFloat} = r.publishnote -obstech(r::RadecMPC{T}) where {T <: AbstractFloat} = r.obstech -ra(r::RadecMPC{T}) where {T <: AbstractFloat} = r.α -dec(r::RadecMPC{T}) where {T <: AbstractFloat} = r.δ -info1(r::RadecMPC{T}) where {T <: AbstractFloat} = r.info1 -mag(r::RadecMPC{T}) where {T <: AbstractFloat} = r.mag -band(r::RadecMPC{T}) where {T <: AbstractFloat} = r.band -catalogue(r::RadecMPC{T}) where {T <: AbstractFloat} = r.catalogue -info2(r::RadecMPC{T}) where {T <: AbstractFloat} = r.info2 -observatory(r::RadecMPC{T}) where {T <: AbstractFloat} = r.observatory - -function neoparse(x::RegexMatch, i::Int, ::Type{Int64}) - y = tryparse(Int64, x[i]) - if isnothing(y) - return 0 - else - return y - end -end - -function neoparse(x::RegexMatch, i::Int, ::Type{DateTime}) - date = DateTime(x[i][1:10], "yyyy mm dd") - utc = parse(Float64, x[i][11:end]) - return date + Microsecond( round(1e6*86_400*utc) ) -end - -function neoparse(x::RegexMatch, i::Int, ::Type{RightAscension}) - # Unfold - hrs = parse(Int, x[i][1:2]) - min = parse(Int, x[i][4:5]) - sec = parse(Float64, x[i][7:end]) - # Convert hours minutes seconds to deg - α_deg = 15*(hrs + min/60 + sec/3_600) - # Convert deg to rad - α_rad = deg2rad(α_deg) - - return α_rad - -end - -function neoparse(x::RegexMatch, i::Int, ::Type{Declination}) - # Unfold - sgn = Char(x[i][1]) - deg = parse(Int, x[i][2:3]) - min = parse(Int, x[i][5:6]) - sec = parse(Float64, x[i][8:end]) - # Convert degrees minutes seconds to degrees - if sgn == '+' - δ_deg = +(deg + min/60 + sec/3_600) - elseif sgn == '-' - δ_deg = -(deg + min/60 + sec/3_600) - end - - δ_rad = deg2rad(δ_deg) - - return δ_rad -end - -neoparse(x::RegexMatch, i::Int, ::Type{CatalogueMPC}) = search_cat_code(String(x[i])) - -function neoparse(m::RegexMatch, i::Int, ::Type{ObservatoryMPC{Float64}}) - _observatory_ = search_obs_code(String(m[i])) - if isnothing(m["optional"]) - return _observatory_ - else - units = neoparse(m, 22, Int64) - x = neoparse(m, 23, Float64) - y = neoparse(m, 24, Float64) - z = neoparse(m, 25, Float64) - date = neoparse(m, 6, DateTime) - if units == 2 - x *= au - y *= au - z *= au - end - return ObservatoryMPC(_observatory_.code, x, y, z, _observatory_.name, date, :satellite, units) - end -end - -# Regular expression to parse an optical measurement in MPC format -const RADEC_MPC_REGEX = Regex(string( - # Number regex (columns 1-5) - raw"(?P.{5})", - # Temporary designation regex (columns 6-12) - raw"(?P.{7})", - # Discovery asterisk regex (column 13) - raw"(?P[\*\s]{1})", - # Publishable note regex (column 14) - raw"(?P.{1})", - # Observation technique regex (column 15) - raw"(?P[^xX]{1})", - # Date of observation regex (columns 16-32) - raw"(?P\d{4}\s\d{2}\s\d{2}\.[\d\s]{6})", - # Right ascension regex (columns 33-44) - raw"(?P<α>\d{2}\s\d{2}\s\d{2}\.[\d\s]{3})", - # Declination regex (columns 45-56) - raw"(?P<δ>[\+|\-]{1}\d{2}\s\d{2}\s\d{2}\.[\d\s]{2})", - # Info 1 regex (columns 57-65) - raw"(?P.{9})", - # Magnitude regex (columns 66-70) - raw"(?P[\.\s\d]{5})", - # Band regex (column 71) - raw"(?P[\w\s]{1})", - # Catalogue regex (column 72) - raw"(?P[\w\s]{1})", - # Info 2 regex (columns 73-77) - raw"(?P.{5})", - # Observatory code regex (columns 78-80) - raw"(?P\w{3})", - # Optional fields (in case of satellite observations) - # Breakline regex - raw"(?:\n)?", - # Number regex (columns 1-5) - raw"(?(?P<_num_>.{5})?", - # Temporary designation regex (columns 6-12) - raw"(?P<_tmpdesig_>.{7})?", - # Blank space regex (column 13) - raw"(?P<_discovery_>\s)?", - # Publishable note regex (column 14) - raw"(?P<_publishnote_>.{1})?", - # s regex (column 15) - raw"(?P<_obstech_>s)?", - # Date of observation regex (columns 16-32) - raw"(?P<_date_>\d{4}\s\d{2}\s\d{2}\.[\d\s]{6})", - # Units + space regex (columns 33-34) - raw"(?P<_units_>\d\s)", - # X component of geocentric vector (columns 35-46) - raw"(?P<_x_>[\-\+]{1}[\.\d\s]{11})", - # Y component of geocentric vector (columns 47-58) - raw"(?P<_y_>[\-\+]{1}[\.\d\s]{11})", - # Z component of geocentric vector (columns 59-70) - raw"(?P<_z_>[\-\+]{1}[\.\d\s]{11})", - # Band regex (column 71) - raw"(?P<_band_>[\w\s]{1})?", - # Catalogue regex (column 72) - raw"(?P<_catalogue_>[\w\s]{1})?", - # Info 2 regex (columns 73-77) - raw"(?P<_info2_>.{5})?", - # Observatory code regex (columns 78-80) - raw"(?P<_obscode_>\w{3})?)?", -)) - -@doc raw""" - RadecMPC(m::RegexMatch) - -Convert a match of `NEOs.RADEC_MPC_REGEX` to `RadecMPC`. -""" -function RadecMPC(m::RegexMatch) - # Check that matched regex is correct - @assert m.regex == RADEC_MPC_REGEX "Only matches of `NEOs.RADEC_MPC_REGEX` can be converted to `RadecMPC`." - # Field types - types = fieldtypes(RadecMPC{Float64}) - # RadecMPC{Float64} fields - args = map(i -> begin - if i == 7 - neoparse(m, i, RightAscension) - elseif i == 8 - neoparse(m, i, Declination) - else - neoparse(m, i, types[i]) - end - end, 1:length(types)) - - return RadecMPC(args...) -end - -@doc raw""" - read_radec_mpc(s::String) - -Return the matches of `NEOs.RADEC_MPC_REGEX` in `s` as `RadecMPC`. -""" -function read_radec_mpc(s::String) - if !contains(s, "\n") && isfile(s) - # Read MPC formatted file - s = String(read(s)) - end - # Vector of observations - radec = Vector{RadecMPC{Float64}}(undef, 0) - # Iterate over the matches - for m in eachmatch(RADEC_MPC_REGEX, s) - push!(radec, RadecMPC(m)) - end - # Eliminate repeated entries - unique!(radec) - # Sort observations by date - sort!(radec) - - return radec -end - -@doc raw""" - mpc_date_str(date::DateTime) - -Return the date in MPC format. -""" -function mpc_date_str(date::DateTime) - - # Year string - year_s = lpad(Dates.year(date), 4) - # Month string - month_s = lpad(Dates.month(date), 2, "0") - # Hours [days] - hrs = Dates.hour(date) / 24 - # Minutes [days] - min = Dates.minute(date) / 24 / 60 - # Seconds [days] - sec = Dates.second(date) / 24 / 60 / 60 - # Milliseconds [days] - mls = Dates.millisecond(date) / 24 / 60 / 60 / 1_000 - # Days - day_val = Dates.day(date) + hrs + min + sec + mls - # Days string - day_s = @sprintf("%09.6f", day_val) - # Join everything - date_s = string(year_s, " ", month_s, " ", day_s) - - return date_s -end - -@doc raw""" - mpc_α_str(α::T) where {T <: Number} - -Return the right ascension [rad] in MPC format. -""" -function mpc_α_str(α::T) where {T <: Number} - # Convert rad to deg - α_deg = rad2deg(α) - # Hours - hrs_, hrs = modf(α_deg / 15) - hrs = Int(hrs) - # Hours string - hrs_s = lpad(hrs, 2, "0") - # Minutes - min_, min = modf(60 * hrs_) - min = Int(min) - # Minutes string - min_s = lpad(min, 2, "0") - # Seconds - sec = 60 * min_ - # Seconds string - sec_s = @sprintf("%06.3f", sec) - # Join everything - α_s = string(hrs_s, " ", min_s, " ", sec_s) - - return α_s -end - -@doc raw""" - mpc_δ_str(δ::T) where {T <: Number} - -Return the declination [rad] in MPC format. -""" -function mpc_δ_str(δ::T) where {T <: Number} - # Sign string - sgn_s = δ >= 0 ? "+" : "-" - # Convert rad to deg - δ_deg = abs(rad2deg(δ)) - # Degrees - deg_, deg = modf(δ_deg) - deg = Int(deg) - # Degrees string - deg_s = lpad(deg, 2, "0") - # Minutes - min_, min = modf(60 * deg_) - min = Int(min) - # Minutes string - min_s = lpad(min, 2, "0") - # Seconds - sec = 60 * min_ - # Seconds string - sec_s = @sprintf("%05.2f", sec) - # Join everything - δ_s = string(sgn_s, deg_s, " ", min_s, " ", sec_s) - - return δ_s -end - -function mpc_x_str(x::T) where {T <: AbstractFloat} - sgn = x > 0 ? "+" : "-" - y = string(abs(x)) - y = lpad(y, 10) - return string(sgn, y, " ") -end - -# Convert `obs` to a string according to MPC format. -function string(obs::RadecMPC{T}) where {T <: AbstractFloat} - # Number string - num_s = rpad(obs.num, 5) - # Temporary designation string - tmpdesig_s = rpad(obs.tmpdesig, 7) - # Discovery asterisk string - discovery_s = rpad(obs.discovery, 1) - # Publishable note string - publishnote_s = rpad(obs.publishnote, 1) - # Observation technique string - obstech_s = rpad(obs.obstech, 1) - # Date string - date_s = mpc_date_str(obs.date) - # Right ascension string - α_s = mpc_α_str(obs.α) - # Declination string - δ_s = mpc_δ_str(obs.δ) - # Info 1 string - info1_s = rpad(obs.info1, 9) - # Magnitude string - mag_s = isnan(obs.mag) ? repeat(" ", 5) : @sprintf("%.2f", obs.mag) - # Band string - band_s = rpad(obs.band, 1) - # Info 2 string - info2_s = rpad(obs.info2, 5) - # Catalogue string - catalogue_s = isunknown(obs.catalogue) ? " " : obs.catalogue.code - # Observatory string - obscode_s = isunknown(obs.observatory) ? " " : obs.observatory.code - # Join everything - obs_s = string(num_s, tmpdesig_s, discovery_s, publishnote_s, obstech_s, date_s, α_s, δ_s, - info1_s, mag_s, band_s, catalogue_s, info2_s, obscode_s) - - if issatellite(obs.observatory) - # Units string - units = obs.observatory.units - units_s = rpad(units, 1) - - x = obs.observatory.long - y = obs.observatory.cos - z = obs.observatory.sin - if units == 2 - x /= au - y /= au - z /= au - end - - # X component string - x_s = mpc_x_str(x) - # Y component string - y_s = mpc_x_str(y) - # Z component string - z_s = mpc_x_str(z) - obs_s = string(obs_s, "\n", num_s, tmpdesig_s, " ", publishnote_s, "s", date_s, - units_s, " ", x_s, y_s, z_s, " ", info2_s, obscode_s) - end - - return obs_s -end - -@doc raw""" - write_radec_mpc(obs::Vector{RadecMPC{T}}, filename::String) where {T <: AbstractFloat} - -Write `obs` to `filename` in MPC format. -""" -function write_radec_mpc(obs::Vector{RadecMPC{T}}, filename::String) where {T <: AbstractFloat} - open(filename, "w") do file - for i in eachindex(obs) - line = string(obs[i]) - write(file, line, "\n") - end - end -end - -@doc raw""" - get_radec_mpc(id::Pair{String, String}, filename::String = replace(id[2], " " => "_") * ".txt") - -Download MPC optical astrometry of NEO `id` and save the output to `filename`. -""" -function get_radec_mpc(id::Pair{String, String}, filename::String = replace(id[2], " " => "_") * ".txt") - # HTTP query - query = ["table" => "observations", id] - resp = get("http://minorplanetcenter.net/search_db"; query = query) - # Converty to String - text = String(resp.body) - # Parse JSON - obs = JSON.parse(text) - # Find matches - matches = Vector{Union{RegexMatch, Nothing}}(undef, length(obs)) - for i in eachindex(obs) - s = obs[i]["original_record"] - matches[i] = match(RADEC_MPC_REGEX, s) - end - filter!(!isnothing, matches) - # Parse RadecMPC - radec = RadecMPC.(matches) - # Write observations to file - write_radec_mpc(radec, filename) - - return filename -end - -# Methods to convert a Vector{<:AbstractAstrometry} to a DataFrame -istable(::Type{Vector{<:AbstractAstrometry}}) = true -rowaccess(::Type{Vector{<:AbstractAstrometry}}) = true -rows(x::Vector{<:AbstractAstrometry}) = x -schema(::Vector{T}) where {T <: AbstractAstrometry} = Schema(fieldnames(T), Tuple{fieldtypes(T)...}) - -# Methods to convert a DataFrame to a Vector{<:AbstractAstrometry} -function Vector{T}(df::DataFrame) where {T <: AbstractAstrometry} - @assert all(String.(fieldnames(T)) .== names(df)) "`DataFrame` column names don't match `$T` fieldnames" - @assert all(fieldtypes(T) .== eltype.(eachcol(df))) "`DataFrame` column types don't match `$T` fieldtypes" - obs = Vector{T}(undef, nrow(df)) - for (i, row) in zip(eachindex(obs), eachrow(df)) - obs[i] = T(values(row)...) - end - return obs -end - -convert(::Type{Vector{T}}, df::DataFrame) where {T <: AbstractAstrometry} = Vector{T}(df) +# Abstract type of RadecMPC and RadarJPL +abstract type AbstractAstrometry end +# Dummy types to parse right ascension and declination +struct RightAscension <: AbstractAstrometry end +struct Declination <: AbstractAstrometry end + +@doc raw""" + RadecMPC{T <: AbstractFloat} <: AbstractAstrometry + +An optical (right ascension, declination) measurement in MPC format. + +# Fields + +- `num::String`: object's number. +- `tmpdesig::String`: provisional / temporary designation. +- `discovery::String`: discovery asterisk. +- `publishnote::String`: publishable note. +- `obstech::String`: observation technique. +- `date::DateTime`: date of observation. +- `α::T`: right ascension [rad]. +- `δ::T`: declination [rad]. +- `info1::String`: additional information. +- `mag::T`: observed magnitude. +- `band::String`: magnitude band. +- `catalogue::CatalogueMPC`: catalogue. +- `info2::String`: additional information. +- `observatory::ObservatoryMPC{T}`: observatory. + +!!! reference + The format is described in https://minorplanetcenter.net/iau/info/OpticalObs.html + and discussed thoroughly in pages 158-181 of https://doi.org/10.1016/j.icarus.2010.06.003. +""" +@auto_hash_equals struct RadecMPC{T <: AbstractFloat} <: AbstractAstrometry + num::String + tmpdesig::String + discovery::String + publishnote::String + obstech::String + date::DateTime + α::T + δ::T + info1::String + mag::T + band::String + catalogue::CatalogueMPC + info2::String + observatory::ObservatoryMPC{T} + # Inner constructor + function RadecMPC{T}(num::String, tmpdesig::String, discovery::String, publishnote::String, + obstech::String, date::DateTime, α::T, δ::T, info1::String, mag::T, + band::String, catalogue::CatalogueMPC, info2::String, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + new{T}(num, tmpdesig, discovery, publishnote, obstech, date, α, δ, info1, mag, band, + catalogue, info2, observatory) + end +end + +# Outer constructor +function RadecMPC(num::String, tmpdesig::String, discovery::String, publishnote::String, + obstech::String, date::DateTime, α::T, δ::T, info1::String, mag::T, + band::String, catalogue::CatalogueMPC, info2::String, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + RadecMPC{T}(num, tmpdesig, discovery, publishnote, obstech, date, α, δ, info1, mag, band, + catalogue, info2, observatory) +end + +function RadecMPC(date::DateTime, α::T, δ::T, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + RadecMPC{T}("", "", "", "", "", date, α, δ, "", "", "", unknowncat(), "", observatory) +end + +# Print method for RadecMPC +# Examples: +# K08E68K α: 166.27754° δ: -0.66325° t: 2008-03-05T10:34:27.840 obs: Mt. Lemmon Survey +# 99942 α: 146.12752° δ: 13.31300° t: 2004-06-19T04:11:47.990 obs: Kitt Peak +function show(io::IO, m::RadecMPC{T}) where {T <: AbstractFloat} + # If there is no number, use temporary designation + id_str = filter(!isspace, m.num) == "" ? m.tmpdesig : m.num + + print(io, id_str, " α: ", @sprintf("%.5f", rad2deg(m.α)), "° δ: ", @sprintf("%.5f", rad2deg(m.δ)), "° t: ", m.date, + " obs: ", m.observatory.name) +end + +# Functions to get specific fields of a RadecMPC object +num(r::RadecMPC{T}) where {T <: AbstractFloat} = r.num +tmpdesig(r::RadecMPC{T}) where {T <: AbstractFloat} = r.tmpdesig +discovery(r::RadecMPC{T}) where {T <: AbstractFloat} = r.discovery +publishnote(r::RadecMPC{T}) where {T <: AbstractFloat} = r.publishnote +obstech(r::RadecMPC{T}) where {T <: AbstractFloat} = r.obstech +date(r::T) where {T <: AbstractAstrometry} = r.date +ra(r::RadecMPC{T}) where {T <: AbstractFloat} = r.α +dec(r::RadecMPC{T}) where {T <: AbstractFloat} = r.δ +info1(r::RadecMPC{T}) where {T <: AbstractFloat} = r.info1 +mag(r::RadecMPC{T}) where {T <: AbstractFloat} = r.mag +band(r::RadecMPC{T}) where {T <: AbstractFloat} = r.band +catalogue(r::RadecMPC{T}) where {T <: AbstractFloat} = r.catalogue +info2(r::RadecMPC{T}) where {T <: AbstractFloat} = r.info2 +observatory(r::RadecMPC{T}) where {T <: AbstractFloat} = r.observatory + +# Order in AbstractAstrometry is given by date +isless(a::T, b::T) where {T <: AbstractAstrometry} = a.date < b.date + +function neoparse(x::RegexMatch, i::Int, ::Type{Int64}) + y = tryparse(Int64, x[i]) + if isnothing(y) + return 0 + else + return y + end +end + +function neoparse(x::RegexMatch, i::Int, ::Type{DateTime}) + date = DateTime(x[i][1:10], "yyyy mm dd") + utc = parse(Float64, x[i][11:end]) + return date + Microsecond( round(1e6*86_400*utc) ) +end + +function neoparse(x::RegexMatch, i::Int, ::Type{RightAscension}) + # Unfold + hrs = parse(Int, x[i][1:2]) + min = parse(Int, x[i][4:5]) + sec = parse(Float64, x[i][7:end]) + # Convert hours minutes seconds to deg + α_deg = 15*(hrs + min/60 + sec/3_600) + # Convert deg to rad + α_rad = deg2rad(α_deg) + + return α_rad + +end + +function neoparse(x::RegexMatch, i::Int, ::Type{Declination}) + # Unfold + sgn = Char(x[i][1]) + deg = parse(Int, x[i][2:3]) + min = parse(Int, x[i][5:6]) + sec = parse(Float64, x[i][8:end]) + # Convert degrees minutes seconds to degrees + if sgn == '+' + δ_deg = +(deg + min/60 + sec/3_600) + elseif sgn == '-' + δ_deg = -(deg + min/60 + sec/3_600) + end + + δ_rad = deg2rad(δ_deg) + + return δ_rad +end + +neoparse(x::RegexMatch, i::Int, ::Type{CatalogueMPC}) = search_cat_code(String(x[i])) + +function neoparse(m::RegexMatch, i::Int, ::Type{ObservatoryMPC{Float64}}) + _observatory_ = search_obs_code(String(m[i])) + if isnothing(m["optional"]) + return _observatory_ + else + units = neoparse(m, 22, Int64) + x = neoparse(m, 23, Float64) + y = neoparse(m, 24, Float64) + z = neoparse(m, 25, Float64) + date = neoparse(m, 6, DateTime) + if units == 2 + x *= au + y *= au + z *= au + end + return ObservatoryMPC(_observatory_.code, x, y, z, _observatory_.name, date, :satellite, units) + end +end + +@doc raw""" + RadecMPC(m::RegexMatch) + +Convert a match of `NEOs.RADEC_MPC_REGEX` to `RadecMPC`. +""" +function RadecMPC(m::RegexMatch) + # Check that matched regex is correct + @assert m.regex == RADEC_MPC_REGEX "Only matches of `NEOs.RADEC_MPC_REGEX` can be converted to `RadecMPC`." + # Field types + types = fieldtypes(RadecMPC{Float64}) + # RadecMPC{Float64} fields + args = map(i -> begin + if i == 7 + neoparse(m, i, RightAscension) + elseif i == 8 + neoparse(m, i, Declination) + else + neoparse(m, i, types[i]) + end + end, 1:length(types)) + + return RadecMPC(args...) +end + +@doc raw""" + read_radec_mpc(s::String) + +Return the matches of `NEOs.RADEC_MPC_REGEX` in `s` as `Vector{RadecMPC{Float64}}`. +`s` can be either a filename or a text. +""" +function read_radec_mpc(s::String) + if !contains(s, "\n") && isfile(s) + # Read MPC formatted file + s = String(read(s)) + end + # Vector of observations + radec = Vector{RadecMPC{Float64}}(undef, 0) + # Iterate over the matches + for m in eachmatch(RADEC_MPC_REGEX, s) + push!(radec, RadecMPC(m)) + end + # Eliminate repeated entries + unique!(radec) + # Sort observations by date + sort!(radec) + + return radec +end + +@doc raw""" + mpc_date_str(date::DateTime) + +Return the date in MPC format. +""" +function mpc_date_str(date::DateTime) + + # Year string + year_s = lpad(Dates.year(date), 4) + # Month string + month_s = lpad(Dates.month(date), 2, "0") + # Hours [days] + hrs = Dates.hour(date) / 24 + # Minutes [days] + min = Dates.minute(date) / 24 / 60 + # Seconds [days] + sec = Dates.second(date) / 24 / 60 / 60 + # Milliseconds [days] + mls = Dates.millisecond(date) / 24 / 60 / 60 / 1_000 + # Days + day_val = Dates.day(date) + hrs + min + sec + mls + # Days string + day_s = @sprintf("%09.6f", day_val) + # Join everything + date_s = string(year_s, " ", month_s, " ", day_s) + + return date_s +end + +@doc raw""" + mpc_α_str(α::T) where {T <: Number} + +Return the right ascension [rad] in MPC format. +""" +function mpc_α_str(α::T) where {T <: Number} + # Convert rad to deg + α_deg = rad2deg(α) + # Hours + hrs_, hrs = modf(α_deg / 15) + hrs = Int(hrs) + # Hours string + hrs_s = lpad(hrs, 2, "0") + # Minutes + min_, min = modf(60 * hrs_) + min = Int(min) + # Minutes string + min_s = lpad(min, 2, "0") + # Seconds + sec = 60 * min_ + # Seconds string + sec_s = @sprintf("%06.3f", sec) + # Join everything + α_s = string(hrs_s, " ", min_s, " ", sec_s) + + return α_s +end + +@doc raw""" + mpc_δ_str(δ::T) where {T <: Number} + +Return the declination [rad] in MPC format. +""" +function mpc_δ_str(δ::T) where {T <: Number} + # Sign string + sgn_s = δ >= 0 ? "+" : "-" + # Convert rad to deg + δ_deg = abs(rad2deg(δ)) + # Degrees + deg_, deg = modf(δ_deg) + deg = Int(deg) + # Degrees string + deg_s = lpad(deg, 2, "0") + # Minutes + min_, min = modf(60 * deg_) + min = Int(min) + # Minutes string + min_s = lpad(min, 2, "0") + # Seconds + sec = 60 * min_ + # Seconds string + sec_s = @sprintf("%05.2f", sec) + # Join everything + δ_s = string(sgn_s, deg_s, " ", min_s, " ", sec_s) + + return δ_s +end + +function mpc_x_str(x::T) where {T <: AbstractFloat} + sgn = x > 0 ? "+" : "-" + y = string(abs(x)) + y = lpad(y, 10) + return string(sgn, y, " ") +end + +# Convert `obs` to a string according to MPC format. +function string(obs::RadecMPC{T}) where {T <: AbstractFloat} + # Number string + num_s = rpad(obs.num, 5) + # Temporary designation string + tmpdesig_s = rpad(obs.tmpdesig, 7) + # Discovery asterisk string + discovery_s = rpad(obs.discovery, 1) + # Publishable note string + publishnote_s = rpad(obs.publishnote, 1) + # Observation technique string + obstech_s = rpad(obs.obstech, 1) + # Date string + date_s = mpc_date_str(obs.date) + # Right ascension string + α_s = mpc_α_str(obs.α) + # Declination string + δ_s = mpc_δ_str(obs.δ) + # Info 1 string + info1_s = rpad(obs.info1, 9) + # Magnitude string + mag_s = isnan(obs.mag) ? repeat(" ", 5) : @sprintf("%.2f", obs.mag) + # Band string + band_s = rpad(obs.band, 1) + # Info 2 string + info2_s = rpad(obs.info2, 5) + # Catalogue string + catalogue_s = isunknown(obs.catalogue) ? " " : obs.catalogue.code + # Observatory string + obscode_s = isunknown(obs.observatory) ? " " : obs.observatory.code + # Join everything + obs_s = string(num_s, tmpdesig_s, discovery_s, publishnote_s, obstech_s, date_s, α_s, δ_s, + info1_s, mag_s, band_s, catalogue_s, info2_s, obscode_s) + + if issatellite(obs.observatory) + # Units string + units = obs.observatory.units + units_s = rpad(units, 1) + + x = obs.observatory.long + y = obs.observatory.cos + z = obs.observatory.sin + if units == 2 + x /= au + y /= au + z /= au + end + + # X component string + x_s = mpc_x_str(x) + # Y component string + y_s = mpc_x_str(y) + # Z component string + z_s = mpc_x_str(z) + obs_s = string(obs_s, "\n", num_s, tmpdesig_s, " ", publishnote_s, "s", date_s, + units_s, " ", x_s, y_s, z_s, " ", info2_s, obscode_s) + end + + return obs_s +end + +@doc raw""" + write_radec_mpc(obs::Vector{RadecMPC{T}}, filename::String) where {T <: AbstractFloat} + +Write `obs` to `filename` in MPC format. +""" +function write_radec_mpc(obs::Vector{RadecMPC{T}}, filename::String) where {T <: AbstractFloat} + open(filename, "w") do file + for i in eachindex(obs) + line = string(obs[i]) + write(file, line, "\n") + end + end +end + +@doc raw""" + get_radec_mpc(id::Pair{String, String}, filename::String = replace(id[2], " " => "_") * ".txt") + +Download MPC optical astrometry of NEO `id` and save the output to `filename`. +""" +function get_radec_mpc(id::Pair{String, String}, filename::String = replace(id[2], " " => "_") * ".txt") + # HTTP query + query = ["table" => "observations", id] + resp = get("http://minorplanetcenter.net/search_db"; query = query) + # Converty to String + text = String(resp.body) + # Parse JSON + obs = JSON.parse(text) + # Find matches + matches = Vector{Union{RegexMatch, Nothing}}(undef, length(obs)) + for i in eachindex(obs) + s = obs[i]["original_record"] + matches[i] = match(RADEC_MPC_REGEX, s) + end + filter!(!isnothing, matches) + # Parse RadecMPC + radec = RadecMPC.(matches) + # Write observations to file + write_radec_mpc(radec, filename) + + return filename +end + +# Methods to convert a Vector{<:AbstractAstrometry} to a DataFrame +istable(::Type{Vector{<:AbstractAstrometry}}) = true +rowaccess(::Type{Vector{<:AbstractAstrometry}}) = true +rows(x::Vector{<:AbstractAstrometry}) = x +schema(::Vector{T}) where {T <: AbstractAstrometry} = Schema(fieldnames(T), Tuple{fieldtypes(T)...}) + +# Methods to convert a DataFrame to a Vector{<:AbstractAstrometry} +function Vector{T}(df::DataFrame) where {T <: AbstractAstrometry} + @assert all(String.(fieldnames(T)) .== names(df)) "`DataFrame` column names don't match `$T` fieldnames" + @assert all(fieldtypes(T) .== eltype.(eachcol(df))) "`DataFrame` column types don't match `$T` fieldtypes" + obs = Vector{T}(undef, nrow(df)) + for (i, row) in zip(eachindex(obs), eachrow(df)) + obs[i] = T(values(row)...) + end + return obs +end + +convert(::Type{Vector{T}}, df::DataFrame) where {T <: AbstractAstrometry} = Vector{T}(df) diff --git a/src/observations/topocentric.jl b/src/observations/topocentric.jl old mode 100644 new mode 100755 index dbb25c3b..a251e583 --- a/src/observations/topocentric.jl +++ b/src/observations/topocentric.jl @@ -1,305 +1,309 @@ -# Earth orientation parameters (eop) 2000 -const eop_IAU2000A::EopIau2000A = fetch_iers_eop(Val(:IAU2000A)) - -@doc raw""" - TimeOfDay - -Day/night at a particular timezone. - -# Fields -- `light::Symbol`: - - for ground observatories: `:day` or `:night`, - - for space observatories: `:space`. -- `start::DateTime`. -- `stop::DateTime`. -- `utc::Int`: hours from UTC. -""" -@auto_hash_equals struct TimeOfDay - light::Symbol - start::DateTime - stop::DateTime - utc::Int - function TimeOfDay(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - if issatellite(observatory) - return new(:space, date, date, 0) - end - # Hours from UTC - utc = hours_from_UTC(observatory) - # Today's sunrise / sunset - today = sunriseset(date, observatory) - # Yesterday's sunrise / sunset - yesterday = sunriseset(date - Day(1), observatory) - # Tomorrow's sunrise / sunset - tomorrow = sunriseset(date + Day(1), observatory) - # Selection - if yesterday[2] <= date <= today[1] - return new(:night, Date(yesterday[2]), Date(today[1]), utc) - elseif today[1] <= date <= today[2] - return new(:day, Date(today[1]), Date(today[2]), utc) - elseif today[2] <= date <= tomorrow[1] - return new(:night, Date(today[2]), Date(tomorrow[1]), utc) - end - - end -end - -TimeOfDay(radec::RadecMPC{T}) where {T <: AbstractFloat} = TimeOfDay(date(radec), observatory(radec)) - -isday(x::TimeOfDay) = x.light == :day -isnight(x::TimeOfDay) = x.light == :night - -# Print method for TimeOfDay -# Examples: -# Night from 2023-06-29 to 2023-06-29 at UTC-7 -# Night from 2023-06-29 to 2023-06-30 at UTC+3 -function show(io::IO, m::TimeOfDay) - print(io, uppercasefirst(string(m.light)), " from ", m.start, " to ", m.stop, " at UTC", @sprintf("%+d", m.utc)) -end - -@doc raw""" - hours_from_UTC(lon::T) where {T <: Real} - -Return the naive hour difference between longitude `lon` [rad] and UTC. -""" -hours_from_UTC(lon::T) where {T <: Real} = ceil(Int, 12*lon/π - 0.5) -function hours_from_UTC(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - lon, _ = lonlat(observatory) - return hours_from_UTC(lon) -end - -@doc raw""" - lonlat(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - -Return longitude and latitude (both in rad) of an observatory. -""" -function lonlat(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - # ECEF [km] - p_ECEF = obsposECEF(observatory) - # ECEF [m] -> Geodetic [m] - lat_geodetic, lon, altitude = ecef_to_geodetic(1_000 * p_ECEF) - # Geodetic [m] -> Geocentric [m] - lat_geocentric, _ = geodetic_to_geocentric(lat_geodetic, altitude) - - return lon, lat_geocentric -end - -@doc raw""" - sunriseset(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - -Return `DateTime` of sunrise and sunset at a particular date and location. - -!!! reference - See "General Solar Position Calculations" by NOAA at https://gml.noaa.gov/grad/solcalc/solareqns.PDF. -""" -function sunriseset(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - # Fractional year [rad] - γ = 2π * (dayofyear(date) - 1 + (hour(date)-12)/24) / daysinyear(date) - # Equation of time [min] - eqtime = 229.18 * (0.000075 + 0.001868*cos(γ) - 0.032077*sin(γ) - 0.014615*cos(2γ) - 0.040849*sin(2γ) ) - # Solar declination angle [rad] - δ = 0.006918 - 0.399912*cos(γ) + 0.070257*sin(γ) - 0.006758*cos(2γ) + 0.000907*sin(2γ) - 0.002697*cos(3γ) + 0.00148*sin(3γ) - # Longitude and latitude [rad] - lon, lat = lonlat(observatory) - # Solar hour angle [deg] - ha_sunrise = acosd(cosd(90.833)/cos(lat)/cos(δ) - tan(lat)*tan(δ)) - ha_sunset = -ha_sunrise - # Day [DateTime] - day = DateTime(Date(date)) - # UTC time of sunrise [min] - sunrise_min = 720 - 4*(rad2deg(lon) + ha_sunrise) - eqtime - # UTC time of sunrise [DateTime] - sunrise = day + Microsecond(round(Int, sunrise_min*6e7)) - # UTC time of sunset [min] - sunset_min = 720 - 4*(rad2deg(lon) + ha_sunset) - eqtime - # UTC time of sunset [DateTime] - sunset = day + Microsecond(round(Int, sunset_min*6e7)) - - return sunrise, sunset -end - -sunriseset(radec::RadecMPC{T}) where {T <: AbstractFloat} = sunriseset(date(radec), observatory(radec)) - -@doc raw""" - obsposECEF(observatory::ObservatoryMPC{T}; kwarg) where {T <: AbstractFloat} - obsposECEF(x::RadecMPC{T}; kwarg) where {T <: AbstractFloat} - obsposECEF(x::RadarJPL{T}; kwarg) where {T <: AbstractFloat} - -Return the observer's geocentric `[x, y, z]` position vector in Earth-Centered Earth-Fixed (ECEF) reference frame. - -# Keyword argument -- `eop::Union{EopIau1980, EopIau2000A}`: Earth Orientation Parameters (eop). -""" -function obsposECEF(observatory::ObservatoryMPC{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} - - # Make sure observatory has coordinates - @assert hascoord(observatory) "Cannot compute position for observatory [$(observatory.code)] without coordinates" - - if issatellite(observatory) || isoccultation(observatory) - # Ephemeris seconds since J2000 - et = datetime2et(observatory.date) - # Earth-Centered Inertial position position of observer - posvel_ECI = obsposvelECI(observatory, et; eop) - # UTC seconds - utc_secs = et - tdb_utc(et) - # Julian days UTC - jd_utc = JD_J2000 + utc_secs/daysec - # State vector - pv_ECI = OrbitStateVector(jd_utc, posvel_ECI[1:3], posvel_ECI[4:6], zeros(3)) - - # Transform position/velocity from Earth-Centered Inertial (ECI) fraom to Earth-Centered Earth-fixed (ECEF) frame - # ITRF: International Terrestrial Reference Frame - # GCRF: Geocentric Celestial Reference Frame - pv_ECEF = sv_eci_to_ecef(pv_ECI, Val(:GCRF), Val(:ITRF), jd_utc, eop) - - # ECEF position - pos_ECEF = convert(Vector{eltype(pv_ECEF.r)}, pv_ECEF.r) - - return pos_ECEF - else - # λ_deg: longitude [degrees east of Greenwich] - # u: distance from spin axis [km], u = ρ*cos(ϕ') - # v: height above equatorial plane [km], v = ρ*sin(ϕ'), - # where ϕ' is the geocentric latitude and ρ is the geocentric distance in km - - # Cilindrical components of Earth-Centered Earth-Fixed position of observer - λ_deg = observatory.long # deg - u = observatory.cos * RE # km - v = observatory.sin * RE # km - - # Cartesian components of Earth-Centered Earth-Fixed position of observer - λ_rad = deg2rad(λ_deg) # rad - x_gc = u * cos(λ_rad) # km - y_gc = u * sin(λ_rad) # km - z_gc = v # km - - # Earth-Centered Earth-Fixed position position of observer - pos_ECEF = [x_gc, y_gc, z_gc] # km - - return pos_ECEF - end -end - -obsposECEF(x::RadecMPC{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} = obsposECEF(x.observatory; eop) -obsposECEF(x::RadarJPL{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} = obsposECEF(x.rcvr; eop) - -# TODO: avoid sv_ecef_to_ecef overload by defining proper product between DCMs and Taylor1/TaylorN -# method below has been adapted from SatelliteToolboxTransformations.jl, MIT-licensed -# https://github.com/JuliaSpace/SatelliteToolboxTransformations.jl -function sv_ecef_to_ecef( - sv::OrbitStateVector, - T_ECEF1::Val{:ITRF}, - T_ECEF2::Val{:TIRS}, - jd_utc::Taylor1{TaylorN{Float64}}, - eop_data::Union{Nothing, EopIau1980, EopIau2000A} = nothing -) - D = r_ecef_to_ecef(DCM, T_ECEF1, T_ECEF2, jd_utc, eop_data) - - # Since both frames does not have a significant angular velocity between - # them, then we just need to convert the representations. - r_ecef::Vector{Taylor1{TaylorN{Float64}}} = D * sv.r - v_ecef::Vector{Taylor1{TaylorN{Float64}}} = D * sv.v - a_ecef::Vector{Taylor1{TaylorN{Float64}}} = D * sv.a - return OrbitStateVector(sv.t, r_ecef, v_ecef, a_ecef) -end - -# TODO: avoid sv_ecef_to_eci overload by defining proper product between DCMs and Taylor1/TaylorN -# method below has been adapted from SatelliteToolboxTransformations.jl, MIT-licensed -# https://github.com/JuliaSpace/SatelliteToolboxTransformations.jl -function sv_ecef_to_eci( - sv::OrbitStateVector, - T_ECEF::Union{Val{:PEF}, Val{:TIRS}}, - T_ECI::Union{T_ECIs, T_ECIs_IAU_2006}, - jd_utc::Taylor1{TaylorN{Float64}}, - eop_data::Union{Nothing, EopIau1980, EopIau2000A} = nothing -) - # Get the matrix that converts the ECEF to the ECI. - if eop_data === nothing - D = r_ecef_to_eci(DCM, T_ECEF, T_ECI, jd_utc) - else - D = r_ecef_to_eci(DCM, T_ECEF, T_ECI, jd_utc, eop_data) - end - - # Since the ECI and ECEF frames have a relative velocity between them, then - # we must account from it when converting the velocity and acceleration. The - # angular velocity between those frames is computed using `we` and corrected - # by the length of day (LOD) parameter of the EOP data, if available. - ω = EARTH_ANGULAR_SPEED * (1 - (eop_data !== nothing ? eop_data.lod(jd_utc) / 86400000 : 0)) - vω = [0, 0, ω] - - # Compute the position in the ECI frame. - r_eci::Vector{Taylor1{TaylorN{Float64}}} = D * sv.r - - # Compute the velocity in the ECI frame. - vω_x_r = vω × sv.r - v_eci::Vector{Taylor1{TaylorN{Float64}}} = D * (sv.v + vω_x_r ) - - # Compute the acceleration in the ECI frame. - a_eci::Vector{Taylor1{TaylorN{Float64}}} = D * (sv.a + vω × vω_x_r + 2vω × sv.v) - - return OrbitStateVector(sv.t, r_eci, v_eci, a_eci) -end - -@doc raw""" - obsposvelECI(observatory::ObservatoryMPC{T}, et::T; kwarg) where {T <: AbstractFloat} - obsposvelECI(x::RadecMPC{T}; kwarg) where {T <: AbstractFloat} - obsposvelECI(x::RadarJPL{T}; kwarg) where {T <: AbstractFloat} - -Return the observer's geocentric `[x, y, z, v_x, v_y, v_z]` "state" vector in Earth-Centered -Inertial (ECI) reference frame. By default, the IAU200A Earth orientation model is used to -transform from Earth-centered, Earth-fixed (ECEF) frame to ECI frame. Other Earth orientation -models, such as the IAU1976/80 model, can be used by importing the -`SatelliteToolboxTransformations.EopIau1980` type and passing it to the `eop` keyword -argument in the function call. - -See also [`SatelliteToolboxBase.OrbitStateVector`](@ref) and [`SatelliteToolboxTransformations.sv_ecef_to_eci`](@ref). - -# Arguments - -- `observatory::ObservatoryMPC{T}`: observation site. -- `et::T`: ephemeris time (TDB seconds since J2000.0 epoch). - -# Keyword argument - -- `eop::Union{EopIau1980, EopIau2000A}`: Earth Orientation Parameters (eop). -""" -function obsposvelECI(observatory::ObservatoryMPC{T}, et::ET; - eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat, ET<:Union{T,Taylor1{T},Taylor1{TaylorN{T}}}} - - # Make sure observatory has coordinates - @assert hascoord(observatory) "Cannot compute position for observatory [$(observatory.code)] without coordinates" - - if issatellite(observatory) || isoccultation(observatory) - #@assert datetime2et(observatory.date) == cte(et) - return [observatory.long, observatory.cos, observatory.sin, zero(T), zero(T), zero(T)] - else - # Earth-Centered Earth-Fixed position position of observer - pos_ECEF = obsposECEF(observatory) - - # UTC seconds - utc_secs = et - tdb_utc(et) - # Julian days UTC - jd_utc = JD_J2000 + utc_secs/daysec - # State vector - pv_ECEF = OrbitStateVector(jd_utc, pos_ECEF, zeros(3), zeros(3)) - - # Transform position/velocity from Earth-Centered Earth-fixed (ECEF) frame to Earth-Centered Inertial (ECI) frame - # ITRF: International Terrestrial Reference Frame - # GCRF: Geocentric Celestial Reference Frame - pv_ECI = sv_ecef_to_eci(pv_ECEF, Val(:ITRF), Val(:GCRF), jd_utc, eop) - - # Inertial position - p_ECI = convert(Vector{eltype(pv_ECI.r)}, pv_ECI.r) - # Inertial velocity - v_ECI = convert(Vector{eltype(pv_ECI.v)}, pv_ECI.v) - - # Concat position and velocity - return vcat(p_ECI, v_ECI) - end -end - -function obsposvelECI(x::RadecMPC{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} - return obsposvelECI(x.observatory, datetime2et(x.date); eop) -end -function obsposvelECI(x::RadarJPL{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} - return obsposvelECI(x.rcvr, datetime2et(x.date); eop) -end +@doc raw""" + TimeOfDay + +Day/night at a particular timezone. + +# Fields +- `light::Symbol`: + - for ground observatories: `:day` or `:night`, + - for space observatories: `:space`. +- `start::DateTime`. +- `stop::DateTime`. +- `utc::Int`: hours from UTC. +""" +@auto_hash_equals struct TimeOfDay + light::Symbol + start::DateTime + stop::DateTime + utc::Int + function TimeOfDay(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + if issatellite(observatory) + return new(:space, date, date, 0) + end + # Hours from UTC + utc = hours_from_UTC(observatory) + # Today's sunrise / sunset + today = sunriseset(date, observatory) + # Yesterday's sunrise / sunset + yesterday = sunriseset(date - Day(1), observatory) + # Tomorrow's sunrise / sunset + tomorrow = sunriseset(date + Day(1), observatory) + # Selection + if yesterday[2] <= date <= today[1] + return new(:night, Date(yesterday[2]), Date(today[1]), utc) + elseif today[1] <= date <= today[2] + return new(:day, Date(today[1]), Date(today[2]), utc) + elseif today[2] <= date <= tomorrow[1] + return new(:night, Date(today[2]), Date(tomorrow[1]), utc) + end + + end +end + +TimeOfDay(radec::RadecMPC{T}) where {T <: AbstractFloat} = TimeOfDay(date(radec), observatory(radec)) + +isday(x::TimeOfDay) = x.light == :day +isnight(x::TimeOfDay) = x.light == :night + +# Print method for TimeOfDay +# Examples: +# Night from 2023-06-29 to 2023-06-29 at UTC-7 +# Night from 2023-06-29 to 2023-06-30 at UTC+3 +function show(io::IO, m::TimeOfDay) + print(io, uppercasefirst(string(m.light)), " from ", m.start, " to ", m.stop, + " at UTC", @sprintf("%+d", m.utc)) +end + +@doc raw""" + hours_from_UTC(lon::T) where {T <: Real} + +Return the naive hour difference between longitude `lon` [rad] and UTC. +""" +hours_from_UTC(lon::T) where {T <: Real} = ceil(Int, 12*lon/π - 0.5) +function hours_from_UTC(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + lon, _ = lonlat(observatory) + return hours_from_UTC(lon) +end + +@doc raw""" + lonlat(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + +Return longitude and latitude (both in rad) of an observatory. +""" +function lonlat(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + # ECEF [km] + p_ECEF = obsposECEF(observatory) + # ECEF [m] -> Geodetic [m] + lat_geodetic, lon, altitude = ecef_to_geodetic(1_000 * p_ECEF) + # Geodetic [m] -> Geocentric [m] + lat_geocentric, _ = geodetic_to_geocentric(lat_geodetic, altitude) + + return lon, lat_geocentric +end + +@doc raw""" + sunriseset(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + sunriseset(radec::RadecMPC{T}) where {T <: AbstractFloat} + +Return `DateTime` of sunrise and sunset at a particular date and location. + +!!! reference + See "General Solar Position Calculations" by NOAA at + https://gml.noaa.gov/grad/solcalc/solareqns.PDF. +""" +function sunriseset(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + # Fractional year [rad] + γ = 2π * (dayofyear(date) - 1 + (hour(date)-12)/24) / daysinyear(date) + # Equation of time [min] + eqtime = 229.18 * (0.000075 + 0.001868*cos(γ) - 0.032077*sin(γ) - 0.014615*cos(2γ) + - 0.040849*sin(2γ) ) + # Solar declination angle [rad] + δ = 0.006918 - 0.399912*cos(γ) + 0.070257*sin(γ) - 0.006758*cos(2γ) + 0.000907*sin(2γ) + - 0.002697*cos(3γ) + 0.00148*sin(3γ) + # Longitude and latitude [rad] + lon, lat = lonlat(observatory) + # Solar hour angle [deg] + ha_sunrise = acosd(cosd(90.833)/cos(lat)/cos(δ) - tan(lat)*tan(δ)) + ha_sunset = -ha_sunrise + # Day [DateTime] + day = DateTime(Date(date)) + # UTC time of sunrise [min] + sunrise_min = 720 - 4*(rad2deg(lon) + ha_sunrise) - eqtime + # UTC time of sunrise [DateTime] + sunrise = day + Microsecond(round(Int, sunrise_min*6e7)) + # UTC time of sunset [min] + sunset_min = 720 - 4*(rad2deg(lon) + ha_sunset) - eqtime + # UTC time of sunset [DateTime] + sunset = day + Microsecond(round(Int, sunset_min*6e7)) + + return sunrise, sunset +end + +sunriseset(radec::RadecMPC{T}) where {T <: AbstractFloat} = sunriseset(date(radec), observatory(radec)) + +@doc raw""" + obsposECEF(observatory::ObservatoryMPC{T}; kwarg) where {T <: AbstractFloat} + obsposECEF(x::RadecMPC{T}; kwarg) where {T <: AbstractFloat} + obsposECEF(x::RadarJPL{T}; kwarg) where {T <: AbstractFloat} + +Return the observer's geocentric `[x, y, z]` position vector in Earth-Centered Earth-Fixed +(ECEF) reference frame. + +# Keyword argument +- `eop::Union{EopIau1980, EopIau2000A}`: Earth Orientation Parameters (eop). +""" +function obsposECEF(observatory::ObservatoryMPC{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} + + # Make sure observatory has coordinates + @assert hascoord(observatory) "Cannot compute position for observatory [$(observatory.code)] without coordinates" + + if issatellite(observatory) || isoccultation(observatory) + # Ephemeris seconds since J2000 + et = datetime2et(observatory.date) + # Earth-Centered Inertial position position of observer + posvel_ECI = obsposvelECI(observatory, et; eop) + # UTC seconds + utc_secs = et - tdb_utc(et) + # Julian days UTC + jd_utc = JD_J2000 + utc_secs/daysec + # State vector + pv_ECI = OrbitStateVector(jd_utc, posvel_ECI[1:3], posvel_ECI[4:6], zeros(3)) + + # Transform position/velocity from Earth-Centered Inertial (ECI) fraom to Earth-Centered Earth-fixed (ECEF) frame + # ITRF: International Terrestrial Reference Frame + # GCRF: Geocentric Celestial Reference Frame + pv_ECEF = sv_eci_to_ecef(pv_ECI, Val(:GCRF), Val(:ITRF), jd_utc, eop) + + # ECEF position + pos_ECEF = convert(Vector{eltype(pv_ECEF.r)}, pv_ECEF.r) + + return pos_ECEF + else + # λ_deg: longitude [degrees east of Greenwich] + # u: distance from spin axis [km], u = ρ*cos(ϕ') + # v: height above equatorial plane [km], v = ρ*sin(ϕ'), + # where ϕ' is the geocentric latitude and ρ is the geocentric distance in km + + # Cilindrical components of Earth-Centered Earth-Fixed position of observer + λ_deg = observatory.long # deg + u = observatory.cos * RE # km + v = observatory.sin * RE # km + + # Cartesian components of Earth-Centered Earth-Fixed position of observer + λ_rad = deg2rad(λ_deg) # rad + x_gc = u * cos(λ_rad) # km + y_gc = u * sin(λ_rad) # km + z_gc = v # km + + # Earth-Centered Earth-Fixed position position of observer + pos_ECEF = [x_gc, y_gc, z_gc] # km + + return pos_ECEF + end +end + +obsposECEF(x::RadecMPC{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} = obsposECEF(x.observatory; eop) +obsposECEF(x::RadarJPL{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} = obsposECEF(x.rcvr; eop) + +# TODO: avoid sv_ecef_to_ecef overload by defining proper product between DCMs and Taylor1/TaylorN +# method below has been adapted from SatelliteToolboxTransformations.jl, MIT-licensed +# https://github.com/JuliaSpace/SatelliteToolboxTransformations.jl +function sv_ecef_to_ecef( + sv::OrbitStateVector, + T_ECEF1::Val{:ITRF}, + T_ECEF2::Val{:TIRS}, + jd_utc::Taylor1{TaylorN{Float64}}, + eop_data::Union{Nothing, EopIau1980, EopIau2000A} = nothing +) + D = r_ecef_to_ecef(DCM, T_ECEF1, T_ECEF2, jd_utc, eop_data) + + # Since both frames does not have a significant angular velocity between + # them, then we just need to convert the representations. + r_ecef::Vector{Taylor1{TaylorN{Float64}}} = D * sv.r + v_ecef::Vector{Taylor1{TaylorN{Float64}}} = D * sv.v + a_ecef::Vector{Taylor1{TaylorN{Float64}}} = D * sv.a + return OrbitStateVector(sv.t, r_ecef, v_ecef, a_ecef) +end + +# TODO: avoid sv_ecef_to_eci overload by defining proper product between DCMs and Taylor1/TaylorN +# method below has been adapted from SatelliteToolboxTransformations.jl, MIT-licensed +# https://github.com/JuliaSpace/SatelliteToolboxTransformations.jl +function sv_ecef_to_eci( + sv::OrbitStateVector, + T_ECEF::Union{Val{:PEF}, Val{:TIRS}}, + T_ECI::Union{T_ECIs, T_ECIs_IAU_2006}, + jd_utc::Taylor1{TaylorN{Float64}}, + eop_data::Union{Nothing, EopIau1980, EopIau2000A} = nothing +) + # Get the matrix that converts the ECEF to the ECI. + if eop_data === nothing + D = r_ecef_to_eci(DCM, T_ECEF, T_ECI, jd_utc) + else + D = r_ecef_to_eci(DCM, T_ECEF, T_ECI, jd_utc, eop_data) + end + + # Since the ECI and ECEF frames have a relative velocity between them, then + # we must account from it when converting the velocity and acceleration. The + # angular velocity between those frames is computed using `we` and corrected + # by the length of day (LOD) parameter of the EOP data, if available. + ω = EARTH_ANGULAR_SPEED * (1 - (eop_data !== nothing ? eop_data.lod(jd_utc) / 86400000 : 0)) + vω = [0, 0, ω] + + # Compute the position in the ECI frame. + r_eci::Vector{Taylor1{TaylorN{Float64}}} = D * sv.r + + # Compute the velocity in the ECI frame. + vω_x_r = vω × sv.r + v_eci::Vector{Taylor1{TaylorN{Float64}}} = D * (sv.v + vω_x_r ) + + # Compute the acceleration in the ECI frame. + a_eci::Vector{Taylor1{TaylorN{Float64}}} = D * (sv.a + vω × vω_x_r + 2vω × sv.v) + + return OrbitStateVector(sv.t, r_eci, v_eci, a_eci) +end + +@doc raw""" + obsposvelECI(observatory::ObservatoryMPC{T}, et::T; kwarg) where {T <: AbstractFloat} + obsposvelECI(x::RadecMPC{T}; kwarg) where {T <: AbstractFloat} + obsposvelECI(x::RadarJPL{T}; kwarg) where {T <: AbstractFloat} + +Return the observer's geocentric `[x, y, z, v_x, v_y, v_z]` "state" vector in Earth-Centered +Inertial (ECI) reference frame. By default, the IAU200A Earth orientation model is used to +transform from Earth-centered, Earth-fixed (ECEF) frame to ECI frame. Other Earth orientation +models, such as the IAU1976/80 model, can be used by importing the +`SatelliteToolboxTransformations.EopIau1980` type and passing it to the `eop` keyword +argument in the function call. + +See also [`SatelliteToolboxBase.OrbitStateVector`](@ref) and +[`SatelliteToolboxTransformations.sv_ecef_to_eci`](@ref). + +# Arguments + +- `observatory::ObservatoryMPC{T}`: observation site. +- `et::T`: ephemeris time (TDB seconds since J2000.0 epoch). + +# Keyword argument + +- `eop::Union{EopIau1980, EopIau2000A}`: Earth Orientation Parameters (eop). +""" +function obsposvelECI(observatory::ObservatoryMPC{T}, et::ET; + eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat, ET<:Union{T,Taylor1{T},Taylor1{TaylorN{T}}}} + + # Make sure observatory has coordinates + @assert hascoord(observatory) "Cannot compute position for observatory [$(observatory.code)] without coordinates" + + if issatellite(observatory) || isoccultation(observatory) + #@assert datetime2et(observatory.date) == cte(et) + return [observatory.long, observatory.cos, observatory.sin, zero(T), zero(T), zero(T)] + else + # Earth-Centered Earth-Fixed position position of observer + pos_ECEF = obsposECEF(observatory) + + # UTC seconds + utc_secs = et - tdb_utc(et) + # Julian days UTC + jd_utc = JD_J2000 + utc_secs/daysec + # State vector + pv_ECEF = OrbitStateVector(jd_utc, pos_ECEF, zeros(3), zeros(3)) + + # Transform position/velocity from Earth-Centered Earth-fixed (ECEF) frame to Earth-Centered Inertial (ECI) frame + # ITRF: International Terrestrial Reference Frame + # GCRF: Geocentric Celestial Reference Frame + pv_ECI = sv_ecef_to_eci(pv_ECEF, Val(:ITRF), Val(:GCRF), jd_utc, eop) + + # Inertial position + p_ECI = convert(Vector{eltype(pv_ECI.r)}, pv_ECI.r) + # Inertial velocity + v_ECI = convert(Vector{eltype(pv_ECI.v)}, pv_ECI.v) + + # Concat position and velocity + return vcat(p_ECI, v_ECI) + end +end + +function obsposvelECI(x::RadecMPC{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} + return obsposvelECI(x.observatory, datetime2et(x.date); eop) +end +function obsposvelECI(x::RadarJPL{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} + return obsposvelECI(x.rcvr, datetime2et(x.date); eop) +end diff --git a/src/observations/units.jl b/src/observations/units.jl old mode 100644 new mode 100755 index 822cede7..5d8931dd --- a/src/observations/units.jl +++ b/src/observations/units.jl @@ -1,178 +1,181 @@ -@doc raw""" - julian2etsecs(jd) - -Convert the Julian date `jd` to ephemeris seconds since J2000. - -See also [`etsecs2julian`](@ref). -""" -function julian2etsecs(jd) - return (jd-JD_J2000)*daysec -end - -@doc raw""" - etsecs2julian(et) - -Convert `et` ephemeris seconds since J2000 to Julian date. - -See also [`julian2etsecs`](@ref). -""" -function etsecs2julian(et) - return JD_J2000 + et/daysec -end - -@doc raw""" - datetime2et(x::DateTime) - datetime2et(x::T) where {T <: AbstractAstrometry} - -Convert a UTC `DateTime` to TDB seconds past the J2000 epoch. -""" -function datetime2et(x::DateTime) - # UTC seconds since J2000.0 epoch - utc_seconds = Millisecond(x - DateTime(2000,1,1,12)).value/1000 - # TAI - UTC - tai_utc = get_Δat(datetime2julian(x)) - # TT - TAI - tt_tai = 32.184 - # TT - UTC = (TT-TAI) + (TAI-UTC) - tt_utc = tt_tai +tai_utc - # TT seconds = UTC seconds + (TT-UTC) - tt_seconds = utc_seconds + tt_utc - # TDB seconds = TT seconds + (TDB-TT) - return tt_seconds - ttmtdb_tt(tt_seconds) -end - -datetime2et(x::AbstractAstrometry) = datetime2et(x.date) - -@doc raw""" - et_to_200X(et::T) where {T <: Number} - -Convert `et` ephemeris seconds since J2000 to years `200X`. -""" -et_to_200X(et::Number) = 2000 + et/daysec/yr - -@doc raw""" - days_to_200X(d::T) where {T <: Number} - -Convert `d` days since J2000 to years `200X`. -""" -days_to_200X(d::Number) = 2000 + d/yr - -@doc raw""" - datetime_to_200X(x::DateTime) - -Convert `DateTime` `x` to years `200X`. -""" -datetime_to_200X(x::DateTime) = et_to_200X(datetime2et(x)) - -@doc raw""" - datetime2days(x::DateTime) - -Convert `DateTime` `x` to days since J2000. -""" -datetime2days(x::DateTime) = datetime2julian(x) - JD_J2000 - -@doc raw""" - days2datetime(d::T) where {T <: Number} - -Convert `d` days since J2000 to `DateTime`. -""" -days2datetime(d::Number) = julian2datetime(d + JD_J2000) - -@doc raw""" - tdb_utc(et::Number) - -Given `et`, a number of TDB seconds past J2000.0 epoch, compute -the difference (TDB-UTC) -```math -\begin{align*} -TDB-UTC & = (TDB-TAI) + (TAI-UTC) \\ - & = (TDB-TT) + (TT-TAI) + (TAI-UTC) \\ - & = (TDB-TT) + 32.184 s + ΔAT, -\end{align*} -``` -where TDB is the Barycentric Dynamical Time (Temps Dynamique Barycentrique), TT is the Terrestrial Time, -TAI is the International Atomic Time, and UTC is the Coordinated Universal Time. - -This function is useful to convert TDB to UTC via UTC + (TDB-UTC) and viceversa. It does -not include the correction due to the position of the measurement station ``v_E.(r_S-r_E)/c^2`` -(Folkner et al. 2014; Moyer, 2003). - -# Arguments - -- `et::Number`: TDB seconds since J2000.0. -""" -function tdb_utc(et::Number) - # TT-TDB - tt_tdb_et = ttmtdb(et/daysec) - # TT-TAI - tt_tai = 32.184 - # TDB - TAI = (TT-TAI) + (TDB-TT) = (TDB-TT) + 32.184 s - tdb_tai = tt_tai - tt_tdb_et - - # TAI seconds since J2000.0; used to determine ΔAT = TAI - UTC - tai_secs = cte(cte(et)) - cte(cte(tdb_tai)) - # Julian date corresponding to tai_secs - jd_tai = JD_J2000 + tai_secs/daysec - # ΔAT = TAI - UTC - tai_utc = get_Δat(jd_tai) - # TDB-UTC = (TDB-TAI) + (TAI-UTC) = (TDB-TT) + 32.184 s + ΔAT - return tdb_tai + tai_utc -end - -@doc raw""" - tt_tdb_tt(tt::Real) - -Given `tt`, a number of TT seconds past J2000.0 epoch, compute -the difference (TT-TDB), where TDB is the Barycentric Dynamical Time (Temps Dynamique -Barycentrique) and TT is the Terrestrial Time. - -This function is useful during the reduction of observations, when the TDB instant is -computed from a known UTC instant. The computed value does not include the -correction due to the position of the measurement station ``v_E.(r_S-r_E)/c^2`` -(Folkner et al. 2014; Moyer, 2003). - -# Arguments - -- `tt::Real`: tt seconds since J2000.0. -""" -function ttmtdb_tt(tt::Real; niter=5) - # Ansatz: TDB - TT = 0 - ttmtdb_order = ttmtdb.x[1].order - tdb = Taylor1([tt,one(tt)], ttmtdb_order) - for _ in 1:niter - ttmtdb_tdb = ttmtdb(tdb/daysec) - # we look for TDB* such that TT-TDB* = (TT-TDB)(TDB*) - y = tt - tdb - ttmtdb_tdb - dy = - 1 - TaylorSeries.differentiate(ttmtdb_tdb) - # perform Newton iteration - tdb[0] -= cte(y/dy) - end - return ttmtdb(tdb[0]/daysec) -end - -@doc raw""" - rad2arcsec(x) - -Convert radians to arcseconds. - -See also [`arcsec2rad`](@ref) and [`mas2rad`](@ref). -""" -rad2arcsec(x) = 3600 * rad2deg(x) # rad2deg(rad) -> deg; 3600 * deg -> arcsec - -@doc raw""" - arcsec2rad(x) - -Convert arcseconds to radians. - -See also [`rad2arcsec`](@ref) and [`mas2rad`](@ref). -""" -arcsec2rad(x) = deg2rad(x / 3600) # arcsec/3600 -> deg; deg2rad(deg) -> rad - -@doc raw""" - mas2rad(x) - -Convert milli-arcseconds to radians. - -See also [`rad2arcsec`](@ref) and [`arcsec2rad`](@ref). -""" -mas2rad(x) = arcsec2rad(x / 1000) # mas/1000 -> arcsec; arcsec2rad(arcsec) -> rad \ No newline at end of file +@doc raw""" + julian2etsecs(jd::T) where {T <: Number} + +Convert the Julian date `jd` to ephemeris seconds since J2000. + +See also [`etsecs2julian`](@ref). +""" +function julian2etsecs(jd::T) where {T <: Number} + return (jd - JD_J2000) * daysec +end + +@doc raw""" + etsecs2julian(et::T) where {T <: Number} + +Convert `et` ephemeris seconds since J2000 to Julian date. + +See also [`julian2etsecs`](@ref). +""" +function etsecs2julian(et::T) where {T <: Number} + return JD_J2000 + et / daysec +end + +@doc raw""" + datetime2et(x::DateTime) + datetime2et(x::T) where {T <: AbstractAstrometry} + +Convert a UTC `DateTime` to TDB seconds past the J2000 epoch. +""" +function datetime2et(x::DateTime) + # UTC seconds since J2000.0 epoch + utc_seconds = Millisecond(x - DateTime(2000,1,1,12)).value/1000 + # TAI - UTC + tai_utc = get_Δat(datetime2julian(x)) + # TT - TAI + tt_tai = 32.184 + # TT - UTC = (TT-TAI) + (TAI-UTC) + tt_utc = tt_tai +tai_utc + # TT seconds = UTC seconds + (TT-UTC) + tt_seconds = utc_seconds + tt_utc + # TDB seconds = TT seconds + (TDB-TT) + return tt_seconds - ttmtdb_tt(tt_seconds) +end + +datetime2et(x::T) where {T <: AbstractAstrometry} = datetime2et(x.date) + +@doc raw""" + et_to_200X(et::T) where {T <: Number} + +Convert `et` ephemeris seconds since J2000 to years `200X`. +""" +et_to_200X(et::T) where {T <: Number} = 2000 + et/daysec/yr + +@doc raw""" + days_to_200X(d::T) where {T <: Number} + +Convert `d` days since J2000 to years `200X`. +""" +days_to_200X(d::T) where {T <: Number} = 2000 + d/yr + +@doc raw""" + datetime_to_200X(x::DateTime) + +Convert `DateTime` `x` to years `200X`. +""" +datetime_to_200X(x::DateTime) = et_to_200X(datetime2et(x)) + +@doc raw""" + datetime2days(x::DateTime) + +Convert `DateTime` `x` to days since J2000. +""" +datetime2days(x::DateTime) = datetime2julian(x) - JD_J2000 + +@doc raw""" + days2datetime(d::T) where {T <: Number} + +Convert `d` days since J2000 to `DateTime`. +""" +days2datetime(d::T) where {T <: Number} = julian2datetime(d + JD_J2000) + +@doc raw""" + tdb_utc(et::T) where {T <: Number} + +Given `et`, a number of TDB seconds past J2000.0 epoch, compute +the difference (TDB-UTC) +```math +\begin{align*} +TDB-UTC & = (TDB-TAI) + (TAI-UTC) \\ + & = (TDB-TT) + (TT-TAI) + (TAI-UTC) \\ + & = (TDB-TT) + 32.184 s + ΔAT, +\end{align*} +``` +where TDB is the Barycentric Dynamical Time (Temps Dynamique Barycentrique), +TT is the Terrestrial Time, TAI is the International Atomic Time, and UTC is +the Coordinated Universal Time. + +# Arguments + +- `et::Number`: TDB seconds since J2000.0. + +!!! reference + This function is useful to convert TDB to UTC via UTC + (TDB-UTC) and viceversa. + It does not include the correction due to the position of the measurement station + ``v_E.(r_S-r_E)/c^2`` (Folkner et al. 2014; Moyer, 2003). +""" +function tdb_utc(et::T) where {T <: Number} + # TT-TDB + tt_tdb_et = ttmtdb(et/daysec) + # TT-TAI + tt_tai = 32.184 + # TDB - TAI = (TT-TAI) + (TDB-TT) = (TDB-TT) + 32.184 s + tdb_tai = tt_tai - tt_tdb_et + + # TAI seconds since J2000.0; used to determine ΔAT = TAI - UTC + tai_secs = cte(cte(et)) - cte(cte(tdb_tai)) + # Julian date corresponding to tai_secs + jd_tai = JD_J2000 + tai_secs/daysec + # ΔAT = TAI - UTC + tai_utc = get_Δat(jd_tai) + # TDB-UTC = (TDB-TAI) + (TAI-UTC) = (TDB-TT) + 32.184 s + ΔAT + return tdb_tai + tai_utc +end + +@doc raw""" + ttmtdb_tt(tt::T; niter::Int = 5) where {T <: Real} + +Given `tt`, a number of TT seconds past J2000.0 epoch, compute +the difference (TT-TDB), where TDB is the Barycentric Dynamical Time (Temps Dynamique +Barycentrique) and TT is the Terrestrial Time. + +# Arguments + +- `tt::T`: tt seconds since J2000.0. + +!!! reference + This function is useful during the reduction of observations, when the TDB instant + is computed from a known UTC instant. The computed value does not include the + correction due to the position of the measurement station ``v_E.(r_S-r_E)/c^2`` + (Folkner et al. 2014; Moyer, 2003). +""" +function ttmtdb_tt(tt::T; niter::Int = 5) where {T <: Real} + # Ansatz: TDB - TT = 0 + ttmtdb_order = ttmtdb.x[1].order + tdb = Taylor1([tt,one(tt)], ttmtdb_order) + for _ in 1:niter + ttmtdb_tdb = ttmtdb(tdb/daysec) + # we look for TDB* such that TT-TDB* = (TT-TDB)(TDB*) + y = tt - tdb - ttmtdb_tdb + dy = - 1 - TaylorSeries.differentiate(ttmtdb_tdb) + # perform Newton iteration + tdb[0] -= cte(y/dy) + end + return ttmtdb(tdb[0]/daysec) +end + +@doc raw""" + rad2arcsec(x::T) where {T <: Number} + +Convert radians to arcseconds. + +See also [`arcsec2rad`](@ref) and [`mas2rad`](@ref). +""" +rad2arcsec(x::T) where {T <: Number} = 3600 * rad2deg(x) # rad2deg(rad) -> deg; 3600 * deg -> arcsec + +@doc raw""" + arcsec2rad(x::T) where {T <: Number} + +Convert arcseconds to radians. + +See also [`rad2arcsec`](@ref) and [`mas2rad`](@ref). +""" +arcsec2rad(x::T) where {T <: Number} = deg2rad(x / 3600) # arcsec/3600 -> deg; deg2rad(deg) -> rad + +@doc raw""" + mas2rad(x::T) where {T <: Number} + +Convert milli-arcseconds to radians. + +See also [`rad2arcsec`](@ref) and [`arcsec2rad`](@ref). +""" +mas2rad(x::T) where {T <: Number} = arcsec2rad(x / 1000) # mas/1000 -> arcsec; arcsec2rad(arcsec) -> rad \ No newline at end of file diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl old mode 100644 new mode 100755 index 877d2fd9..fb40056f --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -1,616 +1,751 @@ -include("osculating.jl") - -@doc raw""" - GaussSolution{T <: Real, U <: Number} - -A preliminary orbit obtained from Gauss method of orbit determination. - -See also [`gauss_method`](@ref). - -# Fields - -- `statevect::Vector{U}`: state vector at middle observation. -- `D::Matrix{U}`: D matrix. -- `R_vec::Matrix{T}`: observer's heliocentric positions. -- `ρ_vec::Matrix{U}`: slant ranges. -- `τ_1::T`: time between first and second observations. -- `τ_3::T`: time between third and second observations. -- `f_1, g_1, f_3, g_3::U`: Lagrange coefficients. -- `status::Symbol`: the status of the solution (`:empty`, `:unkown` or `:unique`) - -!!! reference - See Algorithm 5.5 in page 274 of https://doi.org/10.1016/C2016-0-02107-1. -""" -@auto_hash_equals struct GaussSolution{T <: Real, U <: Number} - statevect::Vector{U} - D::Matrix{U} - R_vec::Matrix{T} - ρ_vec::Matrix{U} - τ_1::T - τ_3::T - f_1::U - g_1::U - f_3::U - g_3::U - status::Symbol - # Internal constructor - function GaussSolution{T, U}(statevect::Vector{U}, D::Matrix{U}, R_vec::Matrix{T}, ρ_vec::Matrix{U}, τ_1::T, τ_3::T, - f_1::U, g_1::U, f_3::U, g_3::U, status::Symbol) where {T <: Real, U <: Number} - return new{T, U}(statevect, D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3, status) - end -end - -# Outer constructor -function GaussSolution(statevect::Vector{U}, D::Matrix{U}, R_vec::Matrix{T}, ρ_vec::Matrix{U}, τ_1::T, τ_3::T, - f_1::U, g_1::U, f_3::U, g_3::U, status::Symbol) where {T <: Real, U <: Number} - return GaussSolution{T, U}(statevect, D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3, status) -end - -# Print method for GaussSolution -# Examples: -# unique Gauss solution (r = 1.0800950907383229 AU) -function show(io::IO, g::GaussSolution{T, U}) where {T <: Real, U <: Number} - print(io, uppercasefirst(string(g.status)), " Gauss solution (r = ", norm(cte.(g.statevect[1:3])), " AU)") -end - -@doc raw""" - topounit(α::T, δ::T) where {T <: Number} - topounit(obs::RadecMPC{T}) where {T <: AbstractFloat} - -Return the topocentric unit vector. -""" -function topounit(α::T, δ::T) where {T <: Number} - - sin_α, cos_α = sincos(α) - sin_δ, cos_δ = sincos(δ) - - pos = [cos_δ * cos_α, cos_δ * sin_α, sin_δ] - - return pos -end - -topounit(obs::RadecMPC{T}) where {T <: AbstractFloat} = topounit(obs.α, obs.δ) - -# TO DO: Should we allow to use other μ? - -@doc raw""" - f_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} - -Return the 1st order approximation to Lagrange's f function. -""" -function f_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} - return 1 - μ_S * (τ^2) / 2 / (r^3) -end - -@doc raw""" - g_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} - -Return the 1st order approximation to Lagrange's g function. -""" -function g_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} - return τ - μ_S * (τ^3) / 6 / (r^3) -end - -@doc raw""" - vectors2matrix(x::T) where {T <: AbstractVector} - -Convert a vector of vectors `x` to a matrix. -""" -vectors2matrix(x::T) where {T <: AbstractVector} = permutedims(reduce(hcat, x)) - -@doc raw""" - _format_Lagrange_equation(a::T, b::T, c::T) where {T <: AbstractFloat} - -Format Lagrange equation as `r⁸ + a r⁶ + b r³ + c = 0`. -""" -function _format_Lagrange_equation(a::T, b::T, c::T) where {T <: AbstractFloat} - a_sgn = a ≥ 0 ? "+" : "-" - b_sgn = b ≥ 0 ? "+" : "-" - c_sgn = c ≥ 0 ? "+" : "-" - - return join(["r⁸ ", a_sgn, " ", abs(a), " r⁶ ", b_sgn, " ", abs(b), " r³ ", c_sgn, " ", abs(c), " = 0"]) -end - -@doc raw""" - lagrange(x::T, a::U, b::U, c::U) where {T, U <: Number} - -Lagrange polynomial to be solved during Gauss method. -""" -lagrange(x::T, a::U, b::U, c::U) where {T, U <: Number} = x^8 + a*x^6 + b*x^3 + c - -@doc raw""" - lagrange_derivative(x::T, a::T, b::T) where {T <: Number} - -Derivative of Lagrange polynomial to be solved during Gauss method. -""" -lagrange_derivative(x::T, a::U, b::U) where {T, U <: Number} = 8*x^7 + 6*a*x^5 + 3*b*x^2 - -# TO DO: Allow to control interval over which to look for solutions -# Currently we look between the radius of the Sun (0.00465047 au) and the radius of the Solar System (40 au) - -@doc raw""" - solve_lagrange(a::T, b::T, c::T; niter::Int = 5) where {T <: Real} - solve_lagrange(a::TaylorN{T}, b::TaylorN{T}, c::TaylorN{T}; niter::Int = 5) where {T <: Real} - -Solve Lagrange polynomial. - -See also [`lagrange`](@ref). -""" -function solve_lagrange(a::T, b::T, c::T; niter::Int = 5) where {T <: Real} - sol = roots(x -> lagrange(x, a, b, c), Interval(0.00465047, 40)) - return mid.(interval.(sol)), getfield.(sol, :status) -end - -function solve_lagrange(a::TaylorN{T}, b::TaylorN{T}, c::TaylorN{T}; niter::Int = 5) where {T <: Real} - # 0-th order solution - sol_0, status = solve_lagrange(cte(a), cte(b), cte(c)) - # Discard empty solutions - idxs = findall(x -> x != :empty, status) - # Vector of solutions - sol = Vector{TaylorN{T}}(undef, length(idxs)) - # Iterate non-empty solutions - for i in eachindex(sol) - # Newton's method - r_0 = sol_0[idxs[i]] - r_2 = sol_0[idxs[i]] - for j in 1:niter - r_2 = r_0 - lagrange(r_0, a, b, c) / lagrange_derivative(r_0, a, b) - r_0 = r_2 - end - sol[i] = r_2 - end - - return sol, status[idxs] -end - -@doc raw""" - heliocentric_energy(r::Vector{T}) where {T <: Number} - -Return the heliocentric energy per unit mass for heliocentric state vector `r` [au, au/day]. -""" -function heliocentric_energy(r::Vector{T}) where {T <: Number} - @assert length(r) == 6 "r must have length 6" - kinetic = 0.5 * (r[4]^2 + r[5]^2 + r[6]^2) - potential = k_gauss^2 / sqrt(r[1]^2 + r[2]^2 + r[3]^2) - return kinetic - potential -end - -@doc raw""" - gauss_method(obs::Vector{RadecMPC{T}}; niter::Int = 5) where {T <: AbstractFloat} - gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{DateTime}, α::Vector{U}, δ::Vector{U}; - niter::Int = 5) where {T <: Real, U <: Number} - -Core Gauss method of Initial Orbit determination (IOD). - -# Arguments - -- `obs::Vector{RadecMPC{T}}`: three observations. -- `observatories::Vector{ObservatoryMPC{T}}`: sites of observation. -- `dates::Vector{DateTime}`: times of observation. -- `α::Vector{U}`: right ascension [rad]. -- `δ::Vector{U}`: declination [rad]. -- `niter::Int`: Number of iterations for Newton's method. - -!!! reference - See Algorithm 5.5 in page 274 https://doi.org/10.1016/C2016-0-02107-1. -""" -function gauss_method(obs::Vector{RadecMPC{T}}; niter::Int = 5) where {T <: AbstractFloat} - - # Make sure observations are in temporal order - sort!(obs) - - # Sites of observation - observatories = observatory.(obs) - - # Dates of observation - dates = date.(obs) - - # Right ascension - α = ra.(obs) - - # Declination - δ = dec.(obs) - - return gauss_method(observatories, dates, α, δ; niter = niter) -end - -function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{DateTime}, α::Vector{U}, δ::Vector{U}; - niter::Int = 5) where {T <: Real, U <: Number} - - # Check we have exactly three observations - @assert length(observatories) == length(dates) == length(α) == length(δ) == 3 "Gauss method requires exactly three observations" - # Check observations are in temporal order - @assert issorted(dates) "Observations must be in temporal order" - - # Times of observation [et] - t_et = datetime2et.(dates) - # Times of observation [days since J2000] - t_days = t_et ./ daysec - - # Time intervals - τ_1 = t_days[1] - t_days[2] - τ_3 = t_days[3] - t_days[2] - τ = τ_3 - τ_1 - - # NEO's topocentric position unit vectors - ρ_vec = vectors2matrix(topounit.(α, δ)) - # Geocentric state vector of the observer [au, au/day] - g_vec = kmsec2auday.(obsposvelECI.(observatories, t_et)) - # Sun's ephemeris - eph_su = selecteph(sseph, su) - # Earth's ephemeris - eph_ea = selecteph(sseph, ea) - # Heliocentric state vector of the Earth [au, au/day] - G_vec = eph_ea.(t_days) - eph_su.(t_days) - # Observer's heliocentric positions [au, au/day] - R_vec = vectors2matrix(G_vec .+ g_vec)[:, 1:3] - - # Cross products - p_vec = zeros(U, 3, 3) - p_vec[1, :] = cross(ρ_vec[2, :], ρ_vec[3, :]) - p_vec[2, :] = cross(ρ_vec[1, :], ρ_vec[3, :]) - p_vec[3, :] = cross(ρ_vec[1, :], ρ_vec[2, :]) - - # Gauss scalar - D_0 = dot(ρ_vec[1, :], p_vec[1, :]) - - # Matrix of triple products - D = zeros(U, 3, 3) - for i in 1:3 - for j in 1:3 - D[i, j] = dot(R_vec[i, :], p_vec[j, :]) - end - end - - # A and B scalars - A = (-D[1, 2]*τ_3/τ + D[2, 2] + D[3, 2]*τ_1/τ) / D_0 - B = (D[1, 2]*(τ_3^2 - τ^2)*τ_3/τ + D[3, 2]*(τ^2 - τ_1^2)*τ_1/τ) / 6 / D_0 - - # E and F scalars - E = dot(R_vec[2, :], ρ_vec[2, :]) - F = dot(R_vec[2, :], R_vec[2, :]) - - # Lagrange equation coefficients - a = -(A^2 + 2*A*E + F) - b = -2*μ_S*B*(A + E) - c = -(μ_S^2)*(B^2) - - # Solve Lagrange equation - sol, status = solve_lagrange(a, b, c; niter = niter) - - # Number of solutions - n_sol = length(sol) - - if iszero(n_sol) - - @warn("""No solutions found for Lagrange equation $(_format_Lagrange_equation(cte(a), cte(b), cte(c)))""") - - return Vector{GaussSolution{T, U}}(undef, 0) - - else - - sol_gauss = Vector{GaussSolution{T, U}}(undef, n_sol) - - for i in eachindex(sol_gauss) - # Heliocentric range - r_2 = sol[i] - # Slant ranges - ρ = zeros(U, 3) - - num_1 = 6*(D[3, 1]*τ_1/τ_3 + D[2, 1]*τ/τ_3)*(r_2^3) + μ_S*D[3, 1]*(τ^2 - τ_1^2)*τ_1/τ_3 - den_1 = 6*(r_2^3) + μ_S*(τ^2 - τ_3^2) - ρ[1] = (num_1 / den_1 - D[1, 1]) / D_0 - - ρ[2] = A + μ_S*B/(r_2^3) - - num_3 = 6*(D[1, 3]*τ_3/τ_1 - D[2, 3]*τ/τ_1)*(r_2^3) + μ_S*D[1, 3]*(τ^2 - τ_3^2)*τ_3/τ_1 - den_3 = 6*(r_2^3) + μ_S*(τ^2 - τ_1^2) - ρ[3] = (num_3 / den_3 - D[3, 3]) / D_0 - - # Heliocentric position of the NEO - r_vec = R_vec .+ ρ.*ρ_vec - - # f, g Lagrange coefficients - f_1 = f_Lagrange(τ_1, r_2) - f_3 = f_Lagrange(τ_3, r_2) - - g_1 = g_Lagrange(τ_1, r_2) - g_3 = g_Lagrange(τ_3, r_2) - - # Heliocentric velocity of the NEO - v_2_vec = (- f_3 * r_vec[1, :] + f_1 * r_vec[3, :]) / (f_1*g_3 - f_3*g_1) - - sol_gauss[i] = GaussSolution{T, U}(vcat(r_vec[2, :], v_2_vec), D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3, status[i]) - end - # Sort solutions by heliocentric range - return sort!(sol_gauss, by = x -> norm(x.statevect[1:3])) - - end - -end - -numberofdays(dates::Vector{DateTime}) = (dates[end] - dates[1]).value / 86_400_000 - -@doc raw""" - gauss_norm(dates::Vector{DateTime}) - -Return a measure of how evenly distributed in time a triplet is; used within [`gauss_triplets`](@ref) to sort triplets -for Gauss method. The function assumes `dates` is sorted. -""" -gauss_evenness(dates::Vector{DateTime}) = abs( (dates[2] - dates[1]).value - (dates[3] - dates[2]).value ) / 86_400_000 - -gauss_optimal_span(dates::Vector{DateTime}) = abs( (dates[3] - dates[1]).value/86_400_000 - 1) - -gauss_norm(dates::Vector{DateTime}) = gauss_evenness(dates) + gauss_optimal_span(dates) - -@doc raw""" - gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_iter::Int = 100) - -Return a vector of `max_triplets` triplets to be used within [`gaussinitcond`](@ref) to select the best observations for Gauss method. -The triplets are sorted by [`gauss_norm`](@ref). -""" -function gauss_triplets(dates::Vector{DateTime}, Δ_min::Period, Δ_max::Period, avoid::Vector{Vector{Int}}, max_triplets::Int) - - triplets = Vector{Vector{Int}}(undef, 0) - L = length(dates) - for i_1 in 1:L-2 - for i_2 in i_1+1:L-1 - for i_3 in i_2+1:L - tmp = [i_1, i_2, i_3] - if (Δ_min <= dates[i_3] - dates[i_1] <= Δ_max) && !(tmp in avoid) - push!(triplets, tmp) - end - end - end - end - - if numberofdays(dates) <= 1 - sort!(triplets, by = x -> gauss_norm(dates[x])) - else - sort!(triplets, by = x -> gauss_evenness(dates[x])) - end - - n = min(length(triplets), max_triplets) - - return triplets[1:n] -end - -function gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_iter::Int = 100) - Δ_min = Hour(20) - Δ_max = Day(7) - - triplets = Vector{Vector{Int}}(undef, 0) - - niter = 0 - - while length(triplets) < max_triplets && niter < max_iter - triplets = vcat(triplets, gauss_triplets(dates, Δ_min, Δ_max, triplets, max_triplets)) - if Δ_min >= Hour(1) - Δ_min -= Hour(1) - end - Δ_max += Day(1) - niter += 1 - end - - n = min(length(triplets), max_triplets) - - return triplets[1:n] -end - -function adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - # Time difference [ms] - Δ_ms = getfield(date(radec[end]) - date(radec[1]), :value) - # Time difference [days] - Δ_day = Δ_ms / 86_400_000 - # Adaptative maxsteps - if Δ_day <= 30 - return 55 - floor(Int, 5*Δ_day/6) - else - return ceil(Int, (Δ_day + 360)/13) - end -end - -for i in 1:2 - @eval begin - function _gaussinitcond(radec::Vector{RadecMPC{T}}, mpc_catalogue_codes_201X::Vector{String}, truth::String, - resol::Resolution, bias_matrix::Matrix{T}, max_triplets::Int, Q_max::T, niter::Int, - varorder::Int, order::Int, abstol::T, parse_eqs::Bool, ::Val{$i}) where {T <: AbstractFloat} - - # Allocate memory for initial conditions - best_sol = zero(NEOSolution{T, T}) - # Reduce nights by interpolation - gdf, cdf = reduce_nights(radec) - if $i == 1 - observatories, dates, α, δ = cdf.observatory, cdf.date, cdf.α, cdf.δ - elseif $i == 2 - # Use plain observations - observatories, dates, α, δ = observatory.(radec), date.(radec), ra.(radec), dec.(radec) - end - # Cannot process less than 3 nights / observations - if length(dates) < 3 - return best_sol - end - # Observations triplets - triplets = gauss_triplets(dates, max_triplets) - # Julian day of first (last) observation - t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) - # Julian day when to start propagation - jd0 = zero(T) - # Maximum number of steps - maxsteps = adaptative_maxsteps(radec) - # Jet transport perturbation (ra/dec) - dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃"; order = varorder) - # Sun's ephemeris - eph_su = selecteph(sseph, su) - # Earth's ephemeris - eph_ea = selecteph(sseph, ea) - # Normalized root mean square error (NRMS) - best_Q = T(Inf) - # Break flag - flag = false - - # Iterate over triplets - for j in eachindex(triplets) - - # Current triplet - triplet = triplets[j] - # Julian day when to start propagation - jd0 = datetime2julian(dates[triplet[2]]) - # Number of years in forward integration - nyears_fwd = (tf - jd0 + 2) / yr - # Number of years in backward integration - nyears_bwd = -(jd0 - t0 + 2) / yr - # Gauss method solution - sol = gauss_method(observatories[triplet], dates[triplet], α[triplet] .+ dq[1:3], δ[triplet] .+ dq[4:6]; niter = niter) - # Filter Gauss solutions by heliocentric energy - filter!(x -> heliocentric_energy(x.statevect) <= 0, sol) - - # Iterate over Gauss solutions - for i in eachindex(sol) - - # Initial conditions (jet transport) - q0 = sol[i].statevect .+ eph_su(jd0 - PE.J2000) - # Backward propagation - bwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_bwd, q0; - order = order, abstol = abstol, parse_eqs = parse_eqs) - if bwd.t[end] > t0 - jd0 - continue - end - # Forward propagation - fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, maxsteps, jd0, nyears_fwd, q0; - order = order, abstol = abstol, parse_eqs = parse_eqs) - if fwd.t[end] < tf - jd0 - continue - end - # O-C residuals - res = residuals(radec, mpc_catalogue_codes_201X, truth, resol, bias_matrix; - xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), - xva = et -> bwdfwdeph(et, bwd, fwd)) - - # Subset of radec for orbit fit - if $i == 1 - g_0 = triplet[1] - g_f = triplet[3] - elseif $i == 2 - g_0 = gdf.groups[triplet[1]] - g_f = gdf.groups[triplet[3]] - end - idxs = findall(x -> g_0 <= x <= g_f, gdf.groups) - sort!(idxs) - # Orbit fit - fit = tryls(res[idxs], zeros(get_numvars()), niter) - !fit.success && continue - - # Right iteration - for k in g_f+1:length(gdf) - extra = findall(x -> x == k, gdf.groups) - fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) - if fit_new.success - fit = fit_new - idxs = vcat(idxs, extra) - sort!(idxs) - else - break - end - end - - # Left iteration - for k in g_0-1:-1:1 - extra = findall(x -> x == k, gdf.groups) - fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) - if fit_new.success - fit = fit_new - idxs = vcat(idxs, extra) - sort!(idxs) - else - break - end - end - - # NRMS - Q = nrms(res, fit) - - # TO DO: check cases where newton converges but diffcorr no - # Update NRMS and initial conditions - if Q < best_Q - best_Q = Q - best_sol = evalfit(NEOSolution(bwd, fwd, res[idxs], fit)) - end - # Break condition - if Q <= Q_max - flag = true - break - end - end - if flag - break - end - end - - # Case: all solutions were unsuccesful - if isinf(best_Q) - return zero(NEOSolution{T, T}) - # Case: at least one solution was succesful - else - return best_sol - end - end - end -end - -@doc raw""" - gaussinitcond(radec::Vector{RadecMPC{T}}; debias_table::String = "2018", kwargs...) where {T <: AbstractFloat} - -Return initial conditions via Gauss method. - -See also [`gauss_method`](@ref). - -# Arguments -- `radec::Vector{RadecMPC{T}}`: vector of observations. - -# Keyword arguments -- `debias_table::String`: possible values are: - - `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, - - `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, - - `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. -- `max_triplets::Int`: maximum number of triplets. -- `Q_max::T`: The maximum nrms that is considered a good enough orbit. -- `niter::Int`: number of iterations for Newton's method. -- `varorder::Int`: order of jet transport perturbation. -- `order::Int`: order of Taylor polynomials w.r.t. time. -- `abstol::T`: absolute tolerance. -- `parse_eqs::Bool`: whether to use the taylorized method of `RNp1BP_pN_A_J23E_J2S_eph_threads!` or not. - -!!! warning - This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. -""" -function gaussinitcond(radec::Vector{RadecMPC{T}}; debias_table::String = "2018", kwargs...) where {T <: AbstractFloat} - mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) - return gaussinitcond(radec, mpc_catalogue_codes_201X, truth, resol, bias_matrix; kwargs...) -end - -function gaussinitcond(radec::Vector{RadecMPC{T}}, mpc_catalogue_codes_201X::Vector{String}, truth::String, - resol::Resolution, bias_matrix::Matrix{T}; max_triplets::Int = 10, Q_max::T = 10., - niter::Int = 5, varorder::Int = 5, order::Int = order, abstol::T = abstol, - parse_eqs::Bool = true) where {T <: AbstractFloat} - - # Eliminate observatories without coordinates - filter!(x -> hascoord(observatory(x)), radec) - - best_sol_1 = _gaussinitcond(radec, mpc_catalogue_codes_201X, truth, resol, bias_matrix, - max_triplets, Q_max, niter, varorder, order, abstol, parse_eqs, Val(1)) - Q_1 = nrms(best_sol_1) - - if Q_1 > Q_max - best_sol_2 = _gaussinitcond(radec, mpc_catalogue_codes_201X, truth, resol, bias_matrix, - max_triplets, Q_max, niter, varorder, order, abstol, parse_eqs, Val(2)) - Q_2 = nrms(best_sol_2) - if Q_2 < Q_1 - return best_sol_2 - else - return best_sol_1 - end - else - return best_sol_1 - end -end \ No newline at end of file +@doc raw""" + GaussSolution{T <: Real, U <: Number} + +A preliminary orbit obtained from Gauss method of orbit determination. + +See also [`gauss_method`](@ref). + +# Fields + +- `statevect::Vector{U}`: state vector at middle observation. +- `D::Matrix{U}`: D matrix. +- `R_vec::Matrix{T}`: observer's heliocentric positions. +- `ρ_vec::Matrix{U}`: slant ranges. +- `τ_1::T`: time between first and second observations. +- `τ_3::T`: time between third and second observations. +- `f_1, g_1, f_3, g_3::U`: Lagrange coefficients. + +!!! reference + See Algorithm 5.5 in page 274 of https://doi.org/10.1016/C2016-0-02107-1. +""" +@auto_hash_equals struct GaussSolution{T <: Real, U <: Number} + statevect::Vector{U} + D::Matrix{U} + R_vec::Matrix{T} + ρ_vec::Matrix{U} + τ_1::T + τ_3::T + f_1::U + g_1::U + f_3::U + g_3::U + # Inner constructor + function GaussSolution{T, U}(statevect::Vector{U}, D::Matrix{U}, R_vec::Matrix{T}, ρ_vec::Matrix{U}, + τ_1::T, τ_3::T, f_1::U, g_1::U, f_3::U, g_3::U) where {T <: Real, U <: Number} + return new{T, U}(statevect, D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3) + end +end + +# Outer constructor +function GaussSolution(statevect::Vector{U}, D::Matrix{U}, R_vec::Matrix{T}, ρ_vec::Matrix{U}, τ_1::T, + τ_3::T, f_1::U, g_1::U, f_3::U, g_3::U) where {T <: Real, U <: Number} + return GaussSolution{T, U}(statevect, D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3) +end + +# Print method for GaussSolution +# Examples: +# Gauss solution (r = 1.0800950907383229 AU) +function show(io::IO, g::GaussSolution{T, U}) where {T <: Real, U <: Number} + print(io, "Gauss solution (r = ", norm(cte.(g.statevect[1:3])), " AU)") +end + +@doc raw""" + topounit(α::T, δ::T) where {T <: Number} + topounit(obs::RadecMPC{T}) where {T <: AbstractFloat} + +Return the topocentric unit vector. +""" +function topounit(α::T, δ::T) where {T <: Number} + + sin_α, cos_α = sincos(α) + sin_δ, cos_δ = sincos(δ) + + pos = [cos_δ * cos_α, cos_δ * sin_α, sin_δ] + + return pos +end + +topounit(obs::RadecMPC{T}) where {T <: AbstractFloat} = topounit(obs.α, obs.δ) + +# TO DO: Should we allow to use other μ? + +@doc raw""" + f_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} + +Return the 1st order approximation to Lagrange's f function. +""" +function f_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} + return 1 - μ_S * (τ^2) / 2 / (r^3) +end + +@doc raw""" + g_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} + +Return the 1st order approximation to Lagrange's g function. +""" +function g_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} + return τ - μ_S * (τ^3) / 6 / (r^3) +end + +@doc raw""" + vectors2matrix(x::T) where {T <: AbstractVector} + +Convert a vector of vectors `x` to a matrix. +""" +vectors2matrix(x::T) where {T <: AbstractVector} = permutedims(reduce(hcat, x)) + +@doc raw""" + _format_Lagrange_equation(a::T, b::T, c::T) where {T <: AbstractFloat} + +Format Lagrange equation as `r⁸ + a r⁶ + b r³ + c = 0`. +""" +function _format_Lagrange_equation(a::T, b::T, c::T) where {T <: AbstractFloat} + a_sgn = a ≥ 0 ? "+" : "-" + b_sgn = b ≥ 0 ? "+" : "-" + c_sgn = c ≥ 0 ? "+" : "-" + + return join(["r⁸ ", a_sgn, " ", abs(a), " r⁶ ", b_sgn, " ", abs(b), " r³ ", c_sgn, " ", abs(c), " = 0"]) +end + +@doc raw""" + lagrange(x::T, a::U, b::U, c::U) where {T, U <: Number} + +Lagrange polynomial to be solved during Gauss method. +""" +lagrange(x::T, a::U, b::U, c::U) where {T, U <: Number} = x^8 + a*x^6 + b*x^3 + c + +@doc raw""" + lagrange_derivative(x::T, a::T, b::T) where {T <: Number} + +Derivative of Lagrange polynomial to be solved during Gauss method. +""" +lagrange_derivative(x::T, a::U, b::U) where {T, U <: Number} = 8*x^7 + 6*a*x^5 + 3*b*x^2 + +# TO DO: Allow to control interval over which to look for solutions +# Currently we look between the radius of the Sun (∼0.00465047 AU) and +# the radius of the Solar System (∼40 AU) + +@doc raw""" + solve_lagrange(a::T, b::T, c::T; niter::Int = 5) where {T <: Real} + solve_lagrange(a::TaylorN{T}, b::TaylorN{T}, c::TaylorN{T}; niter::Int = 5) where {T <: Real} + +Solve Lagrange polynomial. + +See also [`lagrange`](@ref). +""" +function solve_lagrange(a::T, b::T, c::T; niter::Int = 5) where {T <: Real} + return find_zeros(x -> lagrange(x, a, b, c), 0.00465047, 40.0) +end + +function solve_lagrange(a::TaylorN{T}, b::TaylorN{T}, c::TaylorN{T}; niter::Int = 5) where {T <: Real} + # 0-th order solution + sol_0 = solve_lagrange(cte(a), cte(b), cte(c)) + # Vector of solutions + sol = Vector{TaylorN{T}}(undef, length(sol_0)) + # Iterate solutions + for i in eachindex(sol) + # Newton's method + r_0 = sol_0[i] + r_2 = sol_0[i] + for j in 1:niter + r_2 = r_0 - lagrange(r_0, a, b, c) / lagrange_derivative(r_0, a, b) + r_0 = r_2 + end + sol[i] = r_2 + end + + return sol +end + +@doc raw""" + heliocentric_energy(r::Vector{T}) where {T <: Number} + +Return the heliocentric energy per unit mass for heliocentric state vector `r` [au, au/day]. +""" +function heliocentric_energy(r::Vector{T}) where {T <: Number} + @assert length(r) == 6 "r must have length 6" + kinetic = 0.5 * (r[4]^2 + r[5]^2 + r[6]^2) + potential = k_gauss^2 / sqrt(r[1]^2 + r[2]^2 + r[3]^2) + return kinetic - potential +end + +@doc raw""" + gauss_method(obs::Vector{RadecMPC{T}}; niter::Int = 5) where {T <: AbstractFloat} + gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{DateTime}, + α::Vector{U}, δ::Vector{U}; niter::Int = 5) where {T <: Real, U <: Number} + +Core Gauss method of Initial Orbit determination (IOD). + +# Arguments + +- `obs::Vector{RadecMPC{T}}`: three observations. +- `observatories::Vector{ObservatoryMPC{T}}`: sites of observation. +- `dates::Vector{DateTime}`: times of observation. +- `α::Vector{U}`: right ascension [rad]. +- `δ::Vector{U}`: declination [rad]. +- `niter::Int`: number of iterations for Newton's method. + +!!! reference + See Algorithm 5.5 in page 274 https://doi.org/10.1016/C2016-0-02107-1. +""" +function gauss_method(obs::Vector{RadecMPC{T}}; niter::Int = 5) where {T <: AbstractFloat} + + # Make sure observations are in temporal order + sort!(obs) + # Sites of observation + observatories = observatory.(obs) + # Dates of observation + dates = date.(obs) + # Right ascension + α = ra.(obs) + # Declination + δ = dec.(obs) + + return gauss_method(observatories, dates, α, δ; niter = niter) +end + +function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{DateTime}, + α::Vector{U}, δ::Vector{U}; niter::Int = 5) where {T <: Real, U <: Number} + + # Check we have exactly three observations + @assert length(observatories) == length(dates) == length(α) == length(δ) == 3 "Gauss method requires exactly three observations" + # Check observations are in temporal order + @assert issorted(dates) "Observations must be in temporal order" + + # Times of observation [et] + t_et = datetime2et.(dates) + # Times of observation [days since J2000] + t_days = t_et ./ daysec + + # Time intervals + τ_1 = t_days[1] - t_days[2] + τ_3 = t_days[3] - t_days[2] + τ = τ_3 - τ_1 + + # NEO's topocentric position unit vectors + ρ_vec = vectors2matrix(topounit.(α, δ)) + # Geocentric state vector of the observer [au, au/day] + g_vec = kmsec2auday.(obsposvelECI.(observatories, t_et)) + # Sun's ephemeris + eph_su = selecteph(sseph, su) + # Earth's ephemeris + eph_ea = selecteph(sseph, ea) + # Heliocentric state vector of the Earth [au, au/day] + G_vec = eph_ea.(t_days) - eph_su.(t_days) + # Observer's heliocentric positions [au, au/day] + R_vec = vectors2matrix(G_vec .+ g_vec)[:, 1:3] + + # Cross products + p_vec = zeros(U, 3, 3) + p_vec[1, :] = cross(ρ_vec[2, :], ρ_vec[3, :]) + p_vec[2, :] = cross(ρ_vec[1, :], ρ_vec[3, :]) + p_vec[3, :] = cross(ρ_vec[1, :], ρ_vec[2, :]) + + # Gauss scalar + D_0 = dot(ρ_vec[1, :], p_vec[1, :]) + + # Matrix of triple products + D = zeros(U, 3, 3) + for i in 1:3 + for j in 1:3 + D[i, j] = dot(R_vec[i, :], p_vec[j, :]) + end + end + + # A and B scalars + A = (-D[1, 2]*τ_3/τ + D[2, 2] + D[3, 2]*τ_1/τ) / D_0 + B = (D[1, 2]*(τ_3^2 - τ^2)*τ_3/τ + D[3, 2]*(τ^2 - τ_1^2)*τ_1/τ) / 6 / D_0 + + # E and F scalars + E = dot(R_vec[2, :], ρ_vec[2, :]) + F = dot(R_vec[2, :], R_vec[2, :]) + + # Lagrange equation coefficients + a = -(A^2 + 2*A*E + F) + b = -2*μ_S*B*(A + E) + c = -(μ_S^2)*(B^2) + + # Solve Lagrange equation + sol = solve_lagrange(a, b, c; niter = niter) + + # Number of solutions + n_sol = length(sol) + + if iszero(n_sol) + + @warn("""No solutions found for Lagrange equation $(_format_Lagrange_equation(cte(a), cte(b), cte(c)))""") + + return Vector{GaussSolution{T, U}}(undef, 0) + + else + + sol_gauss = Vector{GaussSolution{T, U}}(undef, n_sol) + + for i in eachindex(sol_gauss) + # Heliocentric range + r_2 = sol[i] + # Slant ranges + ρ = zeros(U, 3) + + num_1 = 6*(D[3, 1]*τ_1/τ_3 + D[2, 1]*τ/τ_3)*(r_2^3) + μ_S*D[3, 1]*(τ^2 - τ_1^2)*τ_1/τ_3 + den_1 = 6*(r_2^3) + μ_S*(τ^2 - τ_3^2) + ρ[1] = (num_1 / den_1 - D[1, 1]) / D_0 + + ρ[2] = A + μ_S*B/(r_2^3) + + num_3 = 6*(D[1, 3]*τ_3/τ_1 - D[2, 3]*τ/τ_1)*(r_2^3) + μ_S*D[1, 3]*(τ^2 - τ_3^2)*τ_3/τ_1 + den_3 = 6*(r_2^3) + μ_S*(τ^2 - τ_1^2) + ρ[3] = (num_3 / den_3 - D[3, 3]) / D_0 + + # Heliocentric position of the NEO + r_vec = R_vec .+ ρ.*ρ_vec + + # f, g Lagrange coefficients + f_1 = f_Lagrange(τ_1, r_2) + f_3 = f_Lagrange(τ_3, r_2) + + g_1 = g_Lagrange(τ_1, r_2) + g_3 = g_Lagrange(τ_3, r_2) + + # Heliocentric velocity of the NEO + v_2_vec = (- f_3 * r_vec[1, :] + f_1 * r_vec[3, :]) / (f_1*g_3 - f_3*g_1) + + sol_gauss[i] = GaussSolution{T, U}(vcat(r_vec[2, :], v_2_vec), D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3) + end + # Sort solutions by heliocentric range + return sort!(sol_gauss, by = x -> norm(cte.(x.statevect[1:3]))) + + end + +end + +@doc raw""" + numberofdays(dates::Vector{DateTime}) + numberofdays(dates::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + +Return the time span of `dates` in days. The function assumes `dates` is sorted. +""" +numberofdays(dates::Vector{DateTime}) = (dates[end] - dates[1]).value / 86_400_000 + +function numberofdays(dates::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + return (dates[end].date - dates[1].date).value / 86_400_000 +end + +@doc raw""" + gauss_norm(dates::Vector{DateTime}) + +Return a measure of how evenly distributed in time a triplet is; +used within [`gauss_triplets`](@ref) to sort triplets for Gauss method. +The function assumes `dates` is sorted. +""" +gauss_norm(dates::Vector{DateTime}) = abs( (dates[2] - dates[1]).value - (dates[3] - dates[2]).value ) / 86_400_000 + +@doc raw""" + gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_iter::Int = 100) + +Return a vector of `max_triplets` triplets to be used within [`gaussinitcond`](@ref) +to select the best observations for Gauss method. The triplets are sorted by [`gauss_norm`](@ref). +""" +function gauss_triplets(dates::Vector{DateTime}, Δ_min::Period, Δ_max::Period, + avoid::Vector{Vector{Int}}, max_triplets::Int) + + triplets = Vector{Vector{Int}}(undef, 0) + L = length(dates) + for i_1 in 1:L-2 + for i_2 in i_1+1:L-1 + for i_3 in i_2+1:L + tmp = [i_1, i_2, i_3] + if (Δ_min <= dates[i_3] - dates[i_1] <= Δ_max) && !(tmp in avoid) + push!(triplets, tmp) + end + end + end + end + + sort!(triplets, by = x -> gauss_norm(dates[x])) + + n = min(length(triplets), max_triplets) + + return triplets[1:n] +end + +function gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_iter::Int = 100) + Δ_min = Hour(20) + Δ_max = Day(7) + + triplets = Vector{Vector{Int}}(undef, 0) + + niter = 0 + + while length(triplets) < max_triplets && niter < max_iter + triplets = vcat(triplets, gauss_triplets(dates, Δ_min, Δ_max, triplets, max_triplets)) + if Δ_min >= Hour(1) + Δ_min -= Hour(1) + end + Δ_max += Day(1) + niter += 1 + end + + n = min(length(triplets), max_triplets) + + return triplets[1:n] +end + +@doc raw""" + adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + +Empirical upper bound for the number of steps used for propagation. +""" +function adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + # Time difference [ms] + Δ_ms = getfield(date(radec[end]) - date(radec[1]), :value) + # Time difference [days] + Δ_day = Δ_ms / 86_400_000 + # Adaptative maxsteps + if Δ_day <= 30 + return 55 - floor(Int, 5*Δ_day/6) + else + return ceil(Int, (Δ_day + 360)/13) + end +end + + +@doc raw""" + gaussinitcond(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::DataFrame, + params::Parameters{T}; kwargs...) where {T <: AbstractFloat} + +Return initial conditions via Gauss method. + +See also [`gauss_method`](@ref). + +# Arguments + +- `radec::Vector{RadecMPC{T}}`: vector of observations. +- `gdf::GroupedDataFrame`, `cdf::DataFrame`: output of [`reduce_nights`](@ref). +- `params::Parameters{T}`: see [`Parameters`](@ref). + +# Keyword arguments + +- `varorder::Int`: order of jet transport perturbation. +- `max_triplets::Int`: maximum number of triplets. +- `Q_max::T`: the maximum nrms that is considered a good enough orbit. +- `niter::Int`: number of iterations for Newton's method. + +!!! warning + This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. +""" +function gaussinitcond(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::DataFrame, + params::Parameters{T}; max_triplets::Int = 10, Q_max::T = 10., + niter::Int = 5, varorder::Int = 5) where {T <: AbstractFloat} + + # Allocate memory for initial conditions + best_sol = zero(NEOSolution{T, T}) + # Unfold + observatories, dates, α, δ = cdf.observatory, cdf.date, cdf.α, cdf.δ + # Observations triplets + triplets = gauss_triplets(dates, max_triplets) + # Julian day of first (last) observation + t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) + # Julian day when to start propagation + jd0 = zero(T) + # Maximum number of steps + params = Parameters(params; maxsteps = adaptative_maxsteps(radec)) + # Jet transport perturbation (ra/dec) + dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃"; order = varorder) + # Sun's ephemeris + eph_su = selecteph(sseph, su) + # Earth's ephemeris + eph_ea = selecteph(sseph, ea) + # Normalized root mean square error (NRMS) + best_Q = T(Inf) + # Break flag + flag = false + + # Iterate over triplets + for j in eachindex(triplets) + + # Current triplet + triplet = triplets[j] + # Julian day when to start propagation + jd0 = datetime2julian(dates[triplet[2]]) + # Number of years in forward integration + nyears_fwd = (tf - jd0 + 2) / yr + # Number of years in backward integration + nyears_bwd = -(jd0 - t0 + 2) / yr + # Gauss method solution + sol = gauss_method(observatories[triplet], dates[triplet], α[triplet] .+ dq[1:3], + δ[triplet] .+ dq[4:6]; niter = niter) + # Filter Gauss solutions by heliocentric energy + filter!(x -> heliocentric_energy(x.statevect) <= 0, sol) + + # Iterate over Gauss solutions + for i in eachindex(sol) + + # Initial conditions (jet transport) + q0 = sol[i].statevect .+ eph_su(jd0 - PE.J2000) + # Backward propagation + bwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q0, params) + + if bwd.t[end] > t0 - jd0 + continue + end + # Forward propagation + fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q0, params) + + if fwd.t[end] < tf - jd0 + continue + end + # O-C residuals + res = residuals(radec, params; + xvs = et -> auday2kmsec(eph_su(et/daysec)), + xve = et -> auday2kmsec(eph_ea(et/daysec)), + xva = et -> bwdfwdeph(et, bwd, fwd)) + + # Subset of radec for orbit fit + g_0 = triplet[1] + g_f = triplet[3] + idxs = findall(x -> g_0 <= x <= g_f, gdf.groups) + sort!(idxs) + # Orbit fit + fit = tryls(res[idxs], zeros(get_numvars()), niter) + !fit.success && continue + + # Right iteration + for k in g_f+1:length(gdf) + extra = findall(x -> x == k, gdf.groups) + fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) + if fit_new.success + fit = fit_new + idxs = vcat(idxs, extra) + sort!(idxs) + else + break + end + end + + # Left iteration + for k in g_0-1:-1:1 + extra = findall(x -> x == k, gdf.groups) + fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) + if fit_new.success + fit = fit_new + idxs = vcat(idxs, extra) + sort!(idxs) + else + break + end + end + + # NRMS + Q = nrms(res, fit) + + # TO DO: check cases where newton converges but diffcorr no + # Update NRMS and initial conditions + if Q < best_Q + best_Q = Q + best_sol = evalfit(NEOSolution(bwd, fwd, res[idxs], fit)) + end + # Break condition + if Q <= Q_max + flag = true + break + end + end + if flag + break + end + end + + # Case: all solutions were unsuccesful + if isinf(best_Q) + return zero(NEOSolution{T, T}) + # Case: at least one solution was succesful + else + return best_sol + end + +end + +@doc raw""" + residual_norm(x::OpticalResidual{T, T}) where {T <: Real} + +Return the contribution of `x` to the nrms. +""" +residual_norm(x::OpticalResidual{T, T}) where {T <: Real} = x.w_α * x.ξ_α^2 / x.relax_factor + x.w_δ * x.ξ_δ^2 / x.relax_factor + +@doc raw""" + gauss_refinement(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, params::Parameters{T}; + kwargs...) where {T <: AbstractFloat} + +Refine an orbit computed by [`gaussinitcond`](@ref) via propagation and/or outlier rejection. + +# Arguments + +- `radec::Vector{RadecMPC{T}}`: vector of observations. +- `sol::NEOSolution{T, T}`: orbit to be refined. +- `params::Parameters{T}`: see [`Parameters`](@ref). + +# Keyword arguments + +- `max_per::T = 18.0`: maximum allowed rejection percentage. +- `niter::Int = 5`: number of iterations. +- `varorder::Int`: order of jet transport perturbation. +""" +function gauss_refinement(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, params::Parameters{T}; + max_per::T = 18.0, niter::Int = 5, varorder::Int = 5) where {T <: AbstractFloat} + + # Sun's ephemeris + eph_su = selecteph(sseph, su) + # Earth's ephemeris + eph_ea = selecteph(sseph, ea) + # Julian day to start propagation + jd0 = sol.bwd.t0 + PE.J2000 + # Julian day of first (last) observation + t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) + # Number of years in forward integration + nyears_fwd = (tf - jd0 + 2) / yr + # Number of years in backward integration + nyears_bwd = -(jd0 - t0 + 2) / yr + # Dynamical function + dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! + # Maximum number of steps + params = Parameters(params; maxsteps = adaptative_maxsteps(radec)) + # Initial conditions (T) + q00 = sol(sol.bwd.t0) + # Jet transport perturbation + dq = scaled_variables("δx", fill(1e-6, 6); order = varorder) + # Initial conditions (jet transport) + q0 = q00 .+ dq + + # Backward integration + bwd = propagate(dynamics, jd0, nyears_bwd, q0, params) + + if bwd.t[end] > t0 - jd0 + return zero(NEOSolution{T, T}) + end + + # Forward integration + fwd = propagate(dynamics, jd0, nyears_fwd, q0, params) + + if fwd.t[end] < tf - jd0 + return zero(NEOSolution{T, T}) + end + + # Residuals + res = residuals(radec, params; + xvs = et -> auday2kmsec(eph_su(et/daysec)), + xve = et -> auday2kmsec(eph_ea(et/daysec)), + xva = et -> bwdfwdeph(et, bwd, fwd)) + # Orbit fit + fit = tryls(res, zeros(get_numvars()), niter) + + # NRMS (with 0 outliers) + Q_0 = nrms(res, fit) + + if Q_0 < 1 + return evalfit(NEOSolution(bwd, fwd, res, fit)) + end + + # Number of observations + N_radec = length(radec) + # Maximum allowed outliers + max_drop = ceil(Int, N_radec * max_per / 100) + # Boolean mask (0: included in fit, 1: outlier) + new_outliers = BitVector(zeros(N_radec)) + + # Drop loop + for i in 1:max_drop + # Contribution of each residual to nrms + norms = residual_norm.(res(fit.x)) + # Iterate norms from largest to smallest + idxs = sortperm(norms, rev = true) + + for j in idxs + if !new_outliers[j] + # Drop residual + new_outliers[j] = true + # Update residuals + res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), + relax_factor.(res), new_outliers) + # Update fit + fit = tryls(res, zeros(get_numvars()), niter) + break + end + end + end + + # Outliers + idxs = Vector{Int}(undef, max_drop) + # NRMS + Qs = Vector{T}(undef, max_drop + 1) + # Number of outliers + N_outliers = Vector{T}(undef, max_drop + 1) + + # Recovery loop + for i in 1:max_drop + # NRMS of current fit + Qs[i] = nrms(res, fit) + # Number of outliers in current fit + N_outliers[i] = float(max_drop - i + 1) + # Contribution of each residual to nrms + norms = residual_norm.(res(fit.x)) + # Minimum norm among outliers + j = findmin(norms[new_outliers])[2] + # Find residual with minimum norm + j = findall(new_outliers)[j] + # Add j-th residual to outliers list + idxs[i] = j + # Recover residual + new_outliers[j] = false + # Update residuals + res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), + relax_factor.(res), new_outliers) + # Update fit + fit = tryls(res, zeros(get_numvars()), niter) + end + # Add 0 outliers fit + Qs[end] = Q_0 + N_outliers[end] = zero(T) + + # Outlier rejection cannot reduce Q + if all(Qs .> 1.) + # Reset boolean mask + new_outliers[1:end] .= false + # Update residuals + res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), + relax_factor.(res), new_outliers) + # Update fit + fit = tryls(res, zeros(get_numvars()), niter) + + return evalfit(NEOSolution(bwd, fwd, res, fit)) + end + + if max_drop > 1 + # Assemble points + points = Matrix{T}(undef, 2, max_drop + 1) + for i in eachindex(Qs) + points[1, i] = Qs[i] + points[2, i] = N_outliers[i] + end + # K-means clustering + cluster = kmeans(points, 2) + # Index of smallest cluster + i_0 = cluster.assignments[1] + # Find last fit of smallest cluster + i = findfirst(x -> x != i_0, cluster.assignments) - 1 + # Update outliers indexes + idxs = idxs[i:end] + end + + # Reset boolean mask + new_outliers[1:end] .= false + # Outliers + new_outliers[idxs] .= true + # Update residuals + res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), + relax_factor.(res), new_outliers) + # Update fit + fit = tryls(res, zeros(get_numvars()), niter) + + return evalfit(NEOSolution(bwd, fwd, res, fit)) +end \ No newline at end of file diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl new file mode 100644 index 00000000..9f620d4e --- /dev/null +++ b/src/orbit_determination/orbit_determination.jl @@ -0,0 +1,44 @@ +include("osculating.jl") +include("tooshortarc.jl") +include("gauss_method.jl") + +@doc raw""" + orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}; kwargs...) where {T <: AbstractFloat} + +Initial Orbit Determination (IOD) routine. + +# Arguments + +- `radec::Vector{RadecMPC{T}}`: vector of observations. +- `params::Parameters{T}`: see [`Parameters`](@ref). + +# Keyword arguments + +- `maxiter::Int = 50`: maximum number of iterations. +- `varorder::Int`: order of jet transport perturbation. +- `max_triplets::Int`: maximum number of triplets. +- `Q_max::T`: the maximum nrms that is considered a good enough orbit. +- `niter::Int`: number of iterations for Newton's method. +- `max_per::T = 18.0`: maximum allowed rejection percentage. +""" +function orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}; maxiter::Int = 50, + max_triplets::Int = 10, Q_max::T = 10., niter::Int = 5, + varorder::Int = 5, max_per::T = 18.0) where {T <: AbstractFloat} + # Eliminate observatories without coordinates + filter!(x -> hascoord(observatory(x)), radec) + # Reduce observation nights by linear regression + gdf, cdf = reduce_nights(radec) + + if length(gdf) < 3 || numberofdays(radec) < 1 + sol = tooshortarc(radec, gdf, cdf, params; maxiter) + else + sol = gaussinitcond(radec, gdf, cdf, params; max_triplets, Q_max, niter, + varorder) + if nrms(sol) > 1.0 + sol = gauss_refinement(radec, sol, params; max_per, niter, varorder) + end + end + + return sol +end + \ No newline at end of file diff --git a/src/orbit_determination/osculating.jl b/src/orbit_determination/osculating.jl old mode 100644 new mode 100755 index ac3c370b..683988bd --- a/src/orbit_determination/osculating.jl +++ b/src/orbit_determination/osculating.jl @@ -1,181 +1,186 @@ -@doc raw""" - OsculatingElements{T <: Number} - -Osculating orbital elements of a NEO. - -# Fields - -- `e::T`: eccentricity. -- `q::T`: perihelion distance [au]. -- `tp::T`: time of pericenter passage [jd]. -- `M::T`: mean anomaly [deg]. -- `Ω::T`: longitude of ascending node [deg]. -- `ω::T`: argument of pericentre [deg]. -- `i::T`: inclination [deg]. -- `a::T`: semimajor axis [au]. -""" -@auto_hash_equals struct OsculatingElements{T <: Number} - e::T - q::T - tp::T - Ω::T - ω::T - i::T - M::T - a::T - # Inner constructor - function OsculatingElements{T}(e::T, q::T, tp::T, Ω::T, ω::T, i::T, M::T, a::T) where {T <: Number} - return new{T}(e, q, tp, Ω, ω, i, M, a) - end -end - -# Outer constructors -function OsculatingElements(e::T, q::T, tp::T, Ω::T, ω::T, i::T, M::T, a::T) where {T <: Number} - return OsculatingElements{T}(e, q, tp, Ω, ω, i, M, a) -end - -function OsculatingElements() - return OsculatingElements(NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN) -end - -# A OsculatingElements is NaN if all its fields are NaN -function isnan(osc::OsculatingElements{T}) where {T <: Number} - return isnan(osc.e) && isnan(osc.q) && isnan(osc.tp) && isnan(osc.Ω) && isnan(osc.ω) && isnan(osc.i) && isnan(osc.M) && isnan(osc.a) -end - -# Print method for OsculatingElements -# Example: -# Eccentricity (e): 0.4231715487782969 -# Pericenter distance (q): 0.5028397744678126 au -# Time of pericenter passage (tp): 2021-03-19T03:45:01.293 JDTDB -# Longitude of Ascending Node (Ω): 17.855086873010706 deg -# Argument of pericenter (ω): 194.74654283451 deg -# Inclination (i): 34.81327005431841 deg -# Mean anomaly (M): 118.87965684315387 deg -# Semimajor axis (a): 0.8717319220347314 au -function show(io::IO, m::OsculatingElements{T}) where {T <: Number} - - print(io, rpad("Eccentricity (e): ", 36), cte(m.e), "\n") - print(io, rpad("Pericenter distance (q): ", 36), cte(m.q), " au\n") - if isnan(m.tp) - print(io, rpad("Time of pericenter passage (tp): ", 36), "NaN JDTDB\n") - else - print(io, rpad("Time of pericenter passage (tp): ", 36), julian2datetime(cte(m.tp)), " JDTDB\n") - end - print(io, rpad("Longitude of Ascending Node (Ω): ", 36), cte(m.Ω), " deg\n") - print(io, rpad("Argument of pericenter (ω): ", 36), cte(m.ω), " deg\n") - print(io, rpad("Inclination (i): ", 36), cte(m.i), " deg\n") - print(io, rpad("Mean anomaly (M): ", 36), cte(m.M), " deg\n") - print(io, rpad("Semimajor axis (a): ", 36), cte(m.a), " au\n") - -end - -@doc raw""" - equatorial2ecliptic(xas::Vector{T}) where {T <: Number} - -Rotate state vector `xas` from equatorial plane to the ecliptic. -""" -function equatorial2ecliptic(xas::Vector{T}) where {T <: Number} - # Rotation matrix (only positions) - m_eq2ecl = Rx(deg2rad(ϵ0_deg)) - # Rotational matrix (positions + velocities) - m_xv_eq2ecl = hcat(vcat(m_eq2ecl, zeros(3,3)), vcat(zeros(3,3), m_eq2ecl)) - # Rotated state vector - return m_xv_eq2ecl*xas -end - -@doc raw""" - pv2kep(xas, μ = μ_S, jd = JD_J2000, frame::Symbol = :equatorial) - -Compute the orbital elements of the NEO with state vector `xas`. Return a `OsculatingElements` object. - -See also [`equatorial2ecliptic`](@ref), [`eccentricity`](@ref), [`semimajoraxis`](@ref), [`timeperipass`](@ref), -[`longascnode`](@ref), [`argperi`](@ref) and [`inclination`](@ref). - -# Arguments - -- `xas`: State vector of the asteroid `[x, y, z, v_x, v_y, v_z]`. -- `μ_S`: Mass parameter of the central body (Sun). -- `jd`: Orbit epoch of reference in julian days. -- `frame::Symbol`: plane of reference (`:equatorial` or `:ecliptic`). -""" -function pv2kep(xas; μ = μ_S, jd = JD_J2000, frame::Symbol = :equatorial) - if frame == :ecliptic - xas = equatorial2ecliptic(xas) - end - e = eccentricity(xas..., μ, 0.0) - a = semimajoraxis(xas..., μ, 0.0) - q = a * (1 - e) - tp = timeperipass(jd, xas..., μ, 0.0) - n = meanmotion(μ,a) - M = rad2deg(meananomaly(n, jd, tp)) - Ω = rad2deg(longascnode(xas...)) - ω = rad2deg(argperi(xas..., μ, 0.0)) - i = rad2deg(inclination(xas...)) - return OsculatingElements(e, q, tp, Ω, ω, i, M, a) -end - -@doc raw""" - (osc::OsculatingElements{T})(t::T) where {T <: Number} - -Return cartesian state vector of orbit `osc` at time `t` (Julian day). -""" -function (osc::OsculatingElements{T})(t::U) where {T,U <: Number} - - # Mean motion - n = PE.meanmotion(μ_S, osc.a) - # Mean anomaly - M = PE.meananomaly(n, t, osc.tp) - # Eccentric anomaly - E = PE.eccentricanomaly(osc.e, M) - # True anomaly - f = PE.trueanomaly(osc.e, E) - - # Distance to the central body - r = osc.a * (1 - osc.e^2) / (1 + osc.e * cos(f)) - - # Obtain position and velocity in the orbital frame - r_o = r .* [cos(f), sin(f), 0.0] - v_o = (sqrt(μ_S*osc.a)/r) .* [-sin(E), sqrt(1 - osc.e^2) * cos(E), 0.0] - - # Transform r_o and v_o to the inertial frame - ω = deg2rad(osc.ω) - i = deg2rad(osc.i) - Ω = deg2rad(osc.Ω) - # Rotation from orbital to inertial frame - A = Rz(-Ω) * Rx(-i) * Rz(-ω) - r_i = A * r_o - v_i = A * v_o - - # State vector - pv_i = vcat(r_i, v_i) - - return pv_i -end - -@doc raw""" - yarkp2adot(A2, a, e, μ_S) - -Return the average semimajor axis drift due to the Yarkovsky effect -```math -\begin{align*} - \left\langle\dot{a}\right\rangle & = \frac{2A_2(1-e^2)}{n}\left(\frac{1 \ \text{AU}}{p}\right)^2 \\ - & = \frac{2A_2}{(1-e^2)\sqrt{a\mu_\odot}}(1 \ \text{AU})^2, -\end{align*} -``` -where ``A_2`` is the Yarkovsky parameter, ``\mu_\odot = GM_\odot`` is the Sun's gravitational parameter, -``e`` is the eccentricity, ``n = \sqrt{\mu/a^3}`` is the mean motion, ``p = a(1-e^2)`` is the -semilatus rectum, and ``a`` is the semimajor axis. - -See https://doi.org/10.1016/j.icarus.2013.02.004. - -# Arguments - -- `A2`: Yarkovsky parameter. -- `a`: semimajor axis. -- `e`: eccentricity. -- `μ_S`: mass parameter of the Sun. -""" -function yarkp2adot(A2, a, e; μ = μ_S) - return 2A2/(sqrt(a)*(1-e^2)*sqrt(μ)) -end +@doc raw""" + OsculatingElements{T <: Number} + +Osculating orbital elements of a NEO. + +# Fields + +- `e::T`: eccentricity. +- `q::T`: perihelion distance [au]. +- `tp::T`: time of pericenter passage [jd]. +- `M::T`: mean anomaly [deg]. +- `Ω::T`: longitude of ascending node [deg]. +- `ω::T`: argument of pericentre [deg]. +- `i::T`: inclination [deg]. +- `a::T`: semimajor axis [au]. +""" +@auto_hash_equals struct OsculatingElements{T <: Number} + e::T + q::T + tp::T + Ω::T + ω::T + i::T + M::T + a::T + # Inner constructor + function OsculatingElements{T}(e::T, q::T, tp::T, Ω::T, ω::T, i::T, M::T, a::T) where {T <: Number} + return new{T}(e, q, tp, Ω, ω, i, M, a) + end +end + +# Outer constructors +function OsculatingElements(e::T, q::T, tp::T, Ω::T, ω::T, i::T, M::T, a::T) where {T <: Number} + return OsculatingElements{T}(e, q, tp, Ω, ω, i, M, a) +end + +function OsculatingElements() + return OsculatingElements(NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN) +end + +# A OsculatingElements is NaN if all its fields are NaN +function isnan(osc::OsculatingElements{T}) where {T <: Number} + return isnan(osc.e) && isnan(osc.q) && isnan(osc.tp) && isnan(osc.Ω) && isnan(osc.ω) && + isnan(osc.i) && isnan(osc.M) && isnan(osc.a) +end + +# Print method for OsculatingElements +# Example: +# Eccentricity (e): 0.4231715487782969 +# Pericenter distance (q): 0.5028397744678126 au +# Time of pericenter passage (tp): 2021-03-19T03:45:01.293 JDTDB +# Longitude of Ascending Node (Ω): 17.855086873010706 deg +# Argument of pericenter (ω): 194.74654283451 deg +# Inclination (i): 34.81327005431841 deg +# Mean anomaly (M): 118.87965684315387 deg +# Semimajor axis (a): 0.8717319220347314 au +function show(io::IO, m::OsculatingElements{T}) where {T <: Number} + + print(io, rpad("Eccentricity (e): ", 36), @sprintf("%.5f", cte(m.e)), "\n") + print(io, rpad("Pericenter distance (q): ", 36), @sprintf("%.5f", cte(m.q)), " au\n") + if isnan(m.tp) + print(io, rpad("Time of pericenter passage (tp): ", 36), "NaN JDTDB\n") + else + print(io, rpad("Time of pericenter passage (tp): ", 36), julian2datetime(cte(m.tp)), " JDTDB\n") + end + print(io, rpad("Longitude of Ascending Node (Ω): ", 36), @sprintf("%.5f", cte(m.Ω)), " deg\n") + print(io, rpad("Argument of pericenter (ω): ", 36), @sprintf("%.5f", cte(m.ω)), " deg\n") + print(io, rpad("Inclination (i): ", 36), @sprintf("%.5f", cte(m.i)), " deg\n") + print(io, rpad("Mean anomaly (M): ", 36), @sprintf("%.5f", cte(m.M)), " deg\n") + print(io, rpad("Semimajor axis (a): ", 36), @sprintf("%.5f", cte(m.a)), " au\n") + +end + +@doc raw""" + equatorial2ecliptic(xas::Vector{T}) where {T <: Number} + +Rotate state vector `xas` from equatorial plane to the ecliptic. +""" +function equatorial2ecliptic(xas::Vector{T}) where {T <: Number} + # Rotation matrix (only positions) + m_eq2ecl = Rx(deg2rad(ϵ0_deg)) + # Rotational matrix (positions + velocities) + m_xv_eq2ecl = hcat(vcat(m_eq2ecl, zeros(3,3)), vcat(zeros(3,3), m_eq2ecl)) + # Rotated state vector + return m_xv_eq2ecl*xas +end + +@doc raw""" + pv2kep(xas::Vector{U}; μ::T = μ_S, jd::T = JD_J2000, + frame::Symbol = :equatorial) where {T <: Real, U <: Number} + +Compute the orbital elements of the NEO with state vector `xas`. +Return an `OsculatingElements` object. + +See also [`equatorial2ecliptic`](@ref), [`eccentricity`](@ref), [`semimajoraxis`](@ref), +[`timeperipass`](@ref), [`longascnode`](@ref), [`argperi`](@ref) and [`inclination`](@ref). + +# Arguments + +- `xas::Vector{U}`: state vector of the asteroid `[x, y, z, v_x, v_y, v_z]`. +- `μ_S::T`: mass parameter of the central body (Sun). +- `jd::T`: orbit epoch of reference in julian days. +- `frame::Symbol`: plane of reference (`:equatorial` or `:ecliptic`). +""" +function pv2kep(xas::Vector{U}; μ::T = μ_S, jd::T = JD_J2000, + frame::Symbol = :equatorial) where {T <: Real, U <: Number} + if frame == :ecliptic + xas = equatorial2ecliptic(xas) + end + e = eccentricity(xas..., μ, 0.0) + a = semimajoraxis(xas..., μ, 0.0) + q = a * (1 - e) + tp = timeperipass(jd, xas..., μ, 0.0) + n = meanmotion(μ,a) + M = rad2deg(meananomaly(n, jd, tp)) + Ω = rad2deg(longascnode(xas...)) + ω = rad2deg(argperi(xas..., μ, 0.0)) + i = rad2deg(inclination(xas...)) + return OsculatingElements(e, q, tp, Ω, ω, i, M, a) +end + +@doc raw""" + (osc::OsculatingElements{T})(t::T) where {T <: Number} + +Return cartesian state vector of orbit `osc` at time `t` (Julian day). +""" +function (osc::OsculatingElements{T})(t::U) where {T,U <: Number} + + # Mean motion + n = PE.meanmotion(μ_S, osc.a) + # Mean anomaly + M = PE.meananomaly(n, t, osc.tp) + # Eccentric anomaly + E = PE.eccentricanomaly(osc.e, M) + # True anomaly + f = PE.trueanomaly(osc.e, E) + + # Distance to the central body + r = osc.a * (1 - osc.e^2) / (1 + osc.e * cos(f)) + + # Obtain position and velocity in the orbital frame + r_o = r .* [cos(f), sin(f), 0.0] + v_o = (sqrt(μ_S*osc.a)/r) .* [-sin(E), sqrt(1 - osc.e^2) * cos(E), 0.0] + + # Transform r_o and v_o to the inertial frame + ω = deg2rad(osc.ω) + i = deg2rad(osc.i) + Ω = deg2rad(osc.Ω) + # Rotation from orbital to inertial frame + A = Rz(-Ω) * Rx(-i) * Rz(-ω) + r_i = A * r_o + v_i = A * v_o + + # State vector + pv_i = vcat(r_i, v_i) + + return pv_i +end + +@doc raw""" + yarkp2adot(A2, a, e, μ_S) + +Return the average semimajor axis drift due to the Yarkovsky effect +```math +\begin{align*} + \left\langle\dot{a}\right\rangle & = \frac{2A_2(1-e^2)}{n}\left(\frac{1 \ \text{AU}}{p}\right)^2 \\ + & = \frac{2A_2}{(1-e^2)\sqrt{a\mu_\odot}}(1 \ \text{AU})^2, +\end{align*} +``` +where ``A_2`` is the Yarkovsky parameter, ``\mu_\odot = GM_\odot`` is the Sun's gravitational parameter, +``e`` is the eccentricity, ``n = \sqrt{\mu/a^3}`` is the mean motion, ``p = a(1-e^2)`` is the +semilatus rectum, and ``a`` is the semimajor axis. + +# Arguments + +- `A2`: Yarkovsky parameter. +- `a`: semimajor axis. +- `e`: eccentricity. +- `μ_S`: mass parameter of the Sun. + +!!! reference + See https://doi.org/10.1016/j.icarus.2013.02.004. +""" +function yarkp2adot(A2, a, e; μ = μ_S) + return 2A2/(sqrt(a)*(1-e^2)*sqrt(μ)) +end diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl new file mode 100644 index 00000000..a0917dd6 --- /dev/null +++ b/src/orbit_determination/tooshortarc.jl @@ -0,0 +1,628 @@ +@doc raw""" + AdmissibleRegion{T <: AbstractFloat} + +Subset of `topocentric distance` × `topocentric velocity` space defined by +some dynamical constrainits on a too short arc. + +# Fields + +- `date::DateTime`: time of observation. +- `α::T`: right ascension. +- `δ::T`: declination. +- `v_α::T`: right ascension velocity. +- `v_δ::T`: declination velocity. +- `ρ_unit, ρ_α, _δ::Vector{T}`: topocentric unit vector and its partials. +- `q::Vector{T}`: heliocentric position of observer. +- `coeffs::Vector{T}`: polynomial coefficients. +- `observatory::ObservatoryMPC{T}`: observing station. + +!!! reference + See Chapter 8 of https://doi.org/10.1017/CBO9781139175371. +""" +@auto_hash_equals struct AdmissibleRegion{T <: AbstractFloat} + date::DateTime + α::T + δ::T + v_α::T + v_δ::T + ρ_unit::Vector{T} + ρ_α::Vector{T} + ρ_δ::Vector{T} + q::Vector{T} + coeffs::Vector{T} + observatory::ObservatoryMPC{T} +end + +# Outer constructor +function AdmissibleRegion(cdf::DataFrameRow) + # Unfold + obs, t_datetime, α, δ, v_α, v_δ = cdf + # Topocentric unit vector and partials + ρ, ρ_α, ρ_δ = topounitpdv(α, δ) + # Time of observation [days since J2000] + t_days = datetime2days(t_datetime) + # Time of observation [et seconds] + t_et = datetime2et(t_datetime) + # Sun (Earth) ephemeris + eph_su = selecteph(sseph, su) + eph_ea = selecteph(sseph, ea) + # Heliocentric position of the observer + q = eph_ea(t_days) + kmsec2auday(obsposvelECI(obs, t_et)) - eph_su(t_days) + # Admissible region coefficients + coeffs = admsreg_coeffs(α, δ, v_α, v_δ, ρ, ρ_α, ρ_δ, q) + + return AdmissibleRegion{Float64}(t_datetime, α, δ, v_α, v_δ, ρ, ρ_α, ρ_δ, q, + coeffs, obs) +end + +@doc raw""" + topounitpdv(α::T, δ::T) where {T <: Number} + +Return the topocentric unit vector and its partial derivatives with +respect to `α` and `δ`. +""" +function topounitpdv(α::T, δ::T) where {T <: Number} + sin_α, cos_α = sincos(α) + sin_δ, cos_δ = sincos(δ) + + ρ = [cos_δ * cos_α, cos_δ * sin_α, sin_δ] + ρ_α = [-sin_α * cos_δ, cos_α * cos_δ, zero(T)] + ρ_δ = [-cos_α * sin_δ, -sin_α * sin_δ, cos_δ] + + return ρ, ρ_α, ρ_δ +end + +@doc raw""" + admsreg_coeffs(α::T, δ::T, v_α::T, v_δ::T, ρ::Vector{T}, + ρ_α::Vector{T}, ρ_δ::Vector{T}, q::Vector{T}) where {T <: Number} + +Return the polynomial coefficients for an [`AdmissibleRegioin`](@ref). + +!!! reference + See equation (8.8) of https://doi.org/10.1017/CBO9781139175371. +""" +function admsreg_coeffs(α::T, δ::T, v_α::T, v_δ::T, ρ::Vector{T}, + ρ_α::Vector{T}, ρ_δ::Vector{T}, q::Vector{T}) where {T <: Number} + coeffs = Vector{T}(undef, 6) + coeffs[1] = dot(q[1:3], q[1:3]) + coeffs[2] = 2 * dot(q[4:6], ρ) + coeffs[3] = v_α^2 * cos(δ)^2 + v_δ^2 + coeffs[4] = 2 * v_α * dot(q[4:6], ρ_α) + 2 * v_δ * dot(q[4:6], ρ_δ) + coeffs[5] = dot(q[4:6], q[4:6]) + coeffs[6] = 2*dot(q[1:3], ρ) + return coeffs +end + +@doc raw""" + solve_quadratic(a::T, b::T, c::T) where {T <: AbstractFloat} + +Return real solutions of cuadratic equation `ax² + bx + c = 0`. +""" +function solve_quadratic(a::T, b::T, c::T) where {T <: AbstractFloat} + # Discriminant + Δ = b^2 - 4*a*c + # Cases + if Δ > 0 + x_1 = (-b + sqrt(Δ))/(2*a) + x_2 = (-b - sqrt(Δ))/(2*a) + elseif iszero(Δ) + x_1 = -b / (2*a) + x_2 = T(NaN) + else + x_1 = T(NaN) + x_2 = T(NaN) + end + + return x_1, x_2 +end + +@doc raw""" + admsreg_W(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} + +W function of an [`AdmissibleRegioin`](@ref). + +!!! reference + See equation (8.9) of https://doi.org/10.1017/CBO9781139175371. +""" +function admsreg_W(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} + return A.coeffs[3] * ρ^2 + A.coeffs[4] * ρ + A.coeffs[5] +end + +@doc raw""" + admsreg_S(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} + +S function of an [`AdmissibleRegioin`](@ref). + +!!! reference + See equation (8.9) of https://doi.org/10.1017/CBO9781139175371. +""" +function admsreg_S(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} + return ρ^2 + A.coeffs[6] * ρ + A.coeffs[1] +end + +@doc raw""" + range_rate(A::AdmissibleRegion{T}, ρ::S) where {T, S <: AbstractFloat} + +Return the two possible range rates in the boundary of `A` for a given range `ρ`. +""" +function range_rate(A::AdmissibleRegion{T}, ρ::S) where {T, S <: AbstractFloat} + c = admsreg_W(A, ρ) - 2*k_gauss^2/sqrt(admsreg_S(A, ρ)) + sol = solve_quadratic(one(T), A.coeffs[2], c) + return minmax(sol[1], sol[2]) +end + +@doc raw""" + max_range(A::AdmissibleRegion{T}) where {T <: AbstractFloat} + +Return the maximum range for the left connected component of `A`. +""" +function max_range(A::AdmissibleRegion{T}) where {T <: AbstractFloat} + # Find max_range + ρ = find_zeros(s -> A.coeffs[2]^2/4 - admsreg_W(A, s) + 2*k_gauss^2/sqrt(admsreg_S(A, s)), + R_SI, 1.0)[1] + # Make sure there is no sqrt(negative) + niter = 0 + while admsreg_S(A, ρ) < 0 && niter < 100 + niter += 1 + ρ -= eps() + end + + return ρ +end + +@doc raw""" + boundary(A::AdmissibleRegion{T}, t::S) where {T <: AbstractFloat, S <: Number} + +Parametrization of `A` boundary with `t ∈ [0, 3]`. +""" +function boundary(A::AdmissibleRegion{T}, t::S) where {T <: AbstractFloat, S <: Number} + # Parametrization domain + @assert 0.0 <= t <= 3.0 + # Lower (upper) bounds + y_min, y_max = range_rate(A, R_SI) + # ρ = R_SI + if 0.0 <= t <= 1.0 + return [R_SI, y_min + t * (y_max - y_min)] + else + x_max = max_range(A) + # Upper curve + if 1.0 <= t <= 2.0 + ρ = R_SI + (t-1)*(x_max - R_SI) + _, v_ρ = range_rate(A, ρ) + # Lower curve + elseif 2.0 <= t <= 3.0 + ρ = x_max - (t-2)*(x_max - R_SI) + v_ρ, _ = range_rate(A, ρ) + end + return [ρ, v_ρ] + end +end + +@doc raw""" + boundary_projection(A::AdmissibleRegion{T}, ρ::T, v_ρ::T) where {T <: AbstractFloat} + +Project `[ρ, v_ρ]` into `A`'s boundary. +""" +function boundary_projection(A::AdmissibleRegion{T}, ρ::T, v_ρ::T) where {T <: AbstractFloat} + # Project range + ρ = clamp(ρ, R_SI, max_range(A)) + # Project range-rate + y_min, y_max = range_rate(A, ρ) + v_ρ = clamp(v_ρ, y_min, y_max) + + return ρ, v_ρ +end + +# Check whether P is inside A's boundary +function in(P::Vector{T}, A::AdmissibleRegion{T}) where {T <: AbstractFloat} + @assert length(P) == 2 "Points in admissible region are of dimension 2" + if R_SI <= P[1] <= max_range(A) && boundary(A, 0.0)[2] <= P[2] <= boundary(A, 1.0)[2] + y_min, y_max = range_rate(A, P[1]) + return y_min <= P[2] <= y_max + else + return false + end +end + +@doc raw""" + topo2bary(A::AdmissibleRegion{T}, ρ::U, v_ρ::U) where {T <: AbstractFloat, U <: Number} + +Convert topocentric range/range-rate `[ρ, v_ρ]` to barycentric cartesian coordinates. +`A` fixes the line of sight. +""" +function topo2bary(A::AdmissibleRegion{T}, ρ::U, v_ρ::U) where {T <: AbstractFloat, U <: Number} + # Barycentric position + r = A.q[1:3] + ρ * A.ρ_unit + sseph(su, datetime2days(A.date))[1:3] + # Barycentric velocity + v = A.q[4:6] + v_ρ * A.ρ_unit + ρ * A.v_α * A.ρ_α + ρ * A.v_δ * A.ρ_δ + + sseph(su, datetime2days(A.date))[4:6] + # Barycentric state vector + return vcat(r, v) +end + +@doc raw""" + bary2topo(A::AdmissibleRegion{T}, q0::Vector{U}) where {T <: AbstractFloat, U <: Number} + +Convert barycentric cartesian coordinates `q0` to topocentric range/range-rate. +`A` fixes the line of sight. +""" +function bary2topo(A::AdmissibleRegion{T}, q0::Vector{U}) where {T <: AbstractFloat, U <: Number} + # Heliocentric state vector + r = q0 - sseph(su, datetime2days(A.date)) + # Topocentric range + ρ = norm((r - A.q)[1:3]) + # Topocentric range rate + v_ρ = dot(r[4:6], A.ρ_unit) - dot(A.q[4:6], A.ρ_unit) - ρ * A.v_α * dot(A.ρ_α, A.ρ_unit) + - ρ * A.v_δ * dot(A.ρ_δ, A.ρ_unit) + + return ρ, v_ρ +end + +# Propagate an orbit and compute residuals +function propres(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{U}, + params::Parameters{T}) where {T <: AbstractFloat, U <: Number} + # Time of first (last) observation + t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) + # Years in backward (forward) integration + nyears_bwd = -(jd0 - t0 + 0.5) / yr + nyears_fwd = (tf - jd0 + 0.5) / yr + # Backward (forward) integration + bwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q0, params) + fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q0, params) + # Sun (Earth) ephemeris + eph_su = selecteph(sseph, su) + eph_ea = selecteph(sseph, ea) + # O-C residuals + res = residuals(radec, params; + xvs = et -> auday2kmsec(eph_su(et/daysec)), + xve = et -> auday2kmsec(eph_ea(et/daysec)), + xva = et -> bwdfwdeph(et, bwd, fwd)) + + return bwd, fwd, res +end + +@doc raw""" + gradient_descent(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, + params::Parameters{T}; maxiter::Int = 50) where {T <: AbstractFloat} + +Gradient descent minimizer of root mean square error over `A`. +""" +function gradient_descent(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, + params::Parameters{T}; maxiter::Int = 50) where {T <: AbstractFloat} + # Origin + x0 = zeros(T, 2) + # Jet transport variables + dq = scaled_variables("dρ dvρ", fill(1e-3, 2), order = 1) + # Allocate memory + ρs = Vector{T}(undef, maxiter+1) + v_ρs = Vector{T}(undef, maxiter+1) + Qs = fill(T(Inf), maxiter+1) + # Initial time of integration [julian days] + jd0 = datetime2julian(A.date) + # Initial conditions + ρs[1] = ρ + v_ρs[1] = v_ρ + q0 = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) + _, _, res = propres(radec, jd0, q0, params) + Q = nms(res) + Qs[1] = Q(x0) + # Number of iterations + niter = 0 + # Gradient descent + while niter < maxiter + # Update number of iterations + niter += 1 + # Gradient of objective function + dQ = TaylorSeries.gradient(Q)(x0) + # Step + x1 = x0 - normalize(dQ) + # Update values + ρ, v_ρ = bary2topo(A, q0(x1)) + # Projection + ρ, v_ρ = boundary_projection(A, ρ, v_ρ) + # New initial conditions + q0 = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) + # Update objective function + _, _, res = propres(radec, jd0, q0, params) + Q = nms(res) + # Convergence condition + if Q(x0) > Qs[niter] + break + end + # Save current variables + ρs[niter+1] = ρ + v_ρs[niter+1] = v_ρ + Qs[niter+1] = Q(x0) + end + + niter = argmin(Qs) + + return ρs[1:niter], v_ρs[1:niter], Qs[1:niter] +end + +@doc raw""" + momentum_descent(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, + params::Parameters{T}; maxiter::Int = 50, α::T = 1.0, + β::T = 0.75, Qtol::T = 0.01) where {T <: AbstractFloat} + +Momentum gradient descent minimizer of root mean square error over `A`. +""" +function momentum_descent(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, + params::Parameters{T}; maxiter::Int = 50, α::T = 1.0, + β::T = 0.75, Qtol::T = 0.01) where {T <: AbstractFloat} + # Origin + x0 = zeros(T, 2) + # Jet transport variables + dq = scaled_variables("dρ dvρ", fill(1e-3, 2), order = 1) + # Allocate memory + ρs = Vector{T}(undef, maxiter+1) + v_ρs = Vector{T}(undef, maxiter+1) + Qs = fill(T(Inf), maxiter+1) + # Initial time of integration [julian days] + jd0 = datetime2julian(A.date) + # Initial conditions + ρs[1] = ρ + v_ρs[1] = v_ρ + q0 = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) + _, _, res = propres(radec, jd0, q0, params) + Q = nms(res) + Qs[1] = Q(x0) + m = zeros(T, 2) + # Number of iterations + niter = 0 + # Gradient descent + while niter < maxiter + # Update number of iterations + niter += 1 + # Gradient of objective function + dQ = TaylorSeries.gradient(Q)(x0) + # Momentum + m = β * m + (1 - β) * dQ + # Step + x1 = x0 - α * m + # Update values + ρ, v_ρ = bary2topo(A, q0(x1)) + # Projection + ρ, v_ρ = boundary_projection(A, ρ, v_ρ) + # New initial conditions + q0 = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) + # Update obbjective function + _, _, res = propres(radec, jd0, q0, params) + Q = nms(res) + # Convergence condition + if abs(Q(x0) - Qs[niter]) < Qtol + break + end + # Save current variables + ρs[niter+1] = ρ + v_ρs[niter+1] = v_ρ + Qs[niter+1] = Q(x0) + end + + niter = argmin(Qs) + + return ρs[1:niter], v_ρs[1:niter], Qs[1:niter] +end + +@doc raw""" + rmsprop(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, + params::Parameters{T}; maxiter::Int = 50, α::T = 1.0, β::T = 0.9, + ϵ::T = 1e-8, Qtol::T = 0.01) where {T <: AbstractFloat} + +RMSPROP minimizer of root mean square error over `A`. +""" +function rmsprop(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, + params::Parameters{T}; maxiter::Int = 50, α::T = 1.0, β::T = 0.9, + ϵ::T = 1e-8, Qtol::T = 0.01) where {T <: AbstractFloat} + # Origin + x0 = zeros(T, 2) + # Jet transport variables + dq = scaled_variables("dρ dvρ", fill(1e-3, 2), order = 1) + # Allocate memory + ρs = Vector{T}(undef, maxiter+1) + v_ρs = Vector{T}(undef, maxiter+1) + Qs = fill(T(Inf), maxiter+1) + # Initial time of integration [julian days] + jd0 = datetime2julian(A.date) + # Initial conditions + ρs[1] = ρ + v_ρs[1] = v_ρ + q0 = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) + Q, _ = nms6v(radec, q0, jd0, params) + Qs[1] = Q(x0) + v = zeros(T, 2) + # Number of iterations + niter = 0 + # Gradient descent + while niter < maxiter + # Update number of iterations + niter += 1 + # Gradient of objective function + dQ = TaylorSeries.gradient(Q)(x0) + # Sum of square of past gradients + v = β * v + (1 - β) * dQ .^ 2 + # Step + x1 = x0 - α * dQ ./ sqrt.(v .+ ϵ) + # Update values + ρ, v_ρ = bary2topo(A, q0(x1)) + # Projection + ρ, v_ρ = boundary_projection(A, ρ, v_ρ) + # New initial conditions + q0 = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) + # Update obbjective function + _, _, res = propres(radec, jd0, q0, params) + Q = nms(res) + # Convergence condition + if abs(Q(x0) - Qs[niter]) < Qtol + break + end + # Save current variables + ρs[niter+1] = ρ + v_ρs[niter+1] = v_ρ + Qs[niter+1] = Q(x0) + end + + niter = argmin(Qs) + + return ρs[1:niter], v_ρs[1:niter], Qs[1:niter] +end + +@doc raw""" + adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, + params::Parameters{T}; maxiter::Int = 50, α::T = 1.0, β_1::T = 0.75, + β_2::T = 0.85, ϵ::T = 1e-8, Qtol::T = 0.01) where {T <: AbstractFloat} + +ADAM minimizer of root mean square error over `A`. +""" +function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, + params::Parameters{T}; maxiter::Int = 50, α::T = 1.0, β_1::T = 0.75, + β_2::T = 0.85, ϵ::T = 1e-8, Qtol::T = 0.01) where {T <: AbstractFloat} + # Origin + x0 = zeros(T, 2) + # Jet transport variables + dq = scaled_variables("dρ dvρ", fill(1e-3, 2), order = 1) + # Allocate memory + ρs = Vector{T}(undef, maxiter+1) + v_ρs = Vector{T}(undef, maxiter+1) + Qs = fill(T(Inf), maxiter+1) + # Initial time of integration [julian days] + jd0 = datetime2julian(A.date) + # Initial conditions + ρs[1] = ρ + v_ρs[1] = v_ρ + q0 = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) + _, _, res = propres(radec, jd0, q0, params) + Q = nms(res) + Qs[1] = Q(x0) + m = zeros(T, 2) + v = zeros(T, 2) + # Number of iterations + niter = 0 + # Gradient descent + while niter < maxiter + # Update number of iterations + niter += 1 + # Gradient of objective function + dQ = TaylorSeries.gradient(Q)(x0) + # Momentum + m = β_1 * m + (1 - β_1) * dQ + _m_ = m / (1 - β_1^niter) + # Sum of square of past gradients + v = β_2 * v + (1 - β_2) * dQ .^ 2 + _v_ = v / (1 - β_2^niter) + # Step + x1 = x0 - α * _m_ ./ (sqrt.(_v_) .+ ϵ) + # Update values + ρ, v_ρ = bary2topo(A, q0(x1)) + # Projection + ρ, v_ρ = boundary_projection(A, ρ, v_ρ) + # New initial conditions + q0 = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) + # Update obbjective function + _, _, res = propres(radec, jd0, q0, params) + Q = nms(res) + # Convergence condition + if abs(Q(x0) - Qs[niter]) < Qtol + break + end + # Save current variables + ρs[niter+1] = ρ + v_ρs[niter+1] = v_ρ + Qs[niter+1] = Q(x0) + end + + niter = argmin(Qs) + + return ρs[1:niter], v_ρs[1:niter], Qs[1:niter] +end + +function tryls(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{T}, params::Parameters{T}; + maxiter::Int = 5) where {T <: AbstractFloat} + # Origin + x0 = zeros(T, 6) + # Jet transport variables + dq = scaled_variables("dx", fill(1e-6, 6), order = 6) + # Allocate memory + qs = Matrix{T}(undef, 6, maxiter+1) + Qs = Vector{T}(undef, maxiter+1) + # Initial conditions + qs[:, 1] = q0 + q = q0 + dq + bwd, fwd, res = propres(radec, jd0, q, params) + Qs[1] = nms(res(x0)) + # Number of iterations + niter = 1 + # Minimization loop + while niter <= maxiter + # Try fit + fit = tryls(res, x0, 5) + # Temporary Q + _Q_ = nms(res(fit.x)) + if _Q_ < Qs[niter] + # Update values + q0 = q(fit.x) + # Save current variables + qs[:, niter+1] = q0 + Qs[niter+1] = _Q_ + + # Convergence condition + if Qs[niter+1] < 1 + return evalfit(NEOSolution(bwd, fwd, res, fit)) + end + + # New initial conditions + q = q0 + dq + # Update obbjective function + bwd, fwd, res = propres(radec, jd0, q, params) + + niter += 1 + + else + break + end + end + + return zero(NEOSolution{T, T}) +end + +@doc raw""" + tooshortarc(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::DataFrame, + params::Parameters{T}; kwargs...) where {T <: AbstractFloat} + +Return initial conditions by minimizing the normalized root mean square error over +the admissible region. + +# Arguments + +- `radec::Vector{RadecMPC{T}}`: vector of observations. +- `gdf::GroupedDataFrame`, `cdf::DataFrame`: output of [`reduce_nights`](@ref). +- `params::Parameters{T}`: see [`Parameters`](@ref). + +# Keyword arguments + +- `maxiter::Int = 50`: maximum number of iterations. +""" +function tooshortarc(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::DataFrame, + params::Parameters{T}; maxiter::Int = 50) where {T <: AbstractFloat} + # Find indexes corresponding to observatory with the most number of + # observations + frecs = map(i -> nrow(gdf[i]), 1:nrow(cdf)) + obs_max = argmax(frecs) + idxs = getfield(gdf[obs_max], :rows) + # Admissible region + A = AdmissibleRegion(cdf[obs_max, :]) + # Center + ρ = (R_SI + max_range(A)) / 2 + v_ρ = sum(range_rate(A, R_SI)) / 2 + # Minimization over admissible region + ρs, v_ρs, Qs = adam(radec[idxs], A, ρ, v_ρ, params; maxiter = maxiter) + # 6 variables least squares + q0 = topo2bary(A, ρs[end], v_ρs[end]) + sol = tryls(radec[idxs], datetime2julian(A.date), q0, params; maxiter = 5) + if length(idxs) < length(radec) + # 6 variables least squares + sol = tryls(radec, datetime2julian(A.date), sol(), params; maxiter = 5) + end + + return sol +end \ No newline at end of file diff --git a/src/postprocessing/b_plane.jl b/src/postprocessing/b_plane.jl old mode 100644 new mode 100755 index 82ae34f6..252022e3 --- a/src/postprocessing/b_plane.jl +++ b/src/postprocessing/b_plane.jl @@ -1,210 +1,216 @@ -@doc raw""" - crosssection(μ_P, R_P, vinf) - -Returns the "critical" ``B``, derived from conservation of energy and angular momentum -```math -B = \sqrt{1 + \frac{2\mu_P}{R_P v_\infty^2}}, -``` -i.e., what impact parameter ``B`` corresponds to a grazing impact in hyperbolic close -encounter. ``\mu_P`` is the planet's gravitational parameter, ``R_P`` is the planet's -radius and ``v_\infty`` is the asymptotic inbound velocity. If actual ``B`` is equal or -less to this, then impact happens. Output is in planet radii. - -See equations (13)-(14) in pages 4-5 of https://doi.org/10.1007/s10569-019-9914-4. - -# Arguments - -- `μ_P`: planetary gravitational parameter (au^3/day^2). -- `R_P`: planetary radius (au). -- `vinf`: asymptotic inbound velocity (au/day). -""" -function crosssection(μ_P, R_P, vinf) - return sqrt( 1 + (2μ_P)/(R_P*(vinf)^2) ) -end - -@doc raw""" - bopik(xae, xes) - -Computes Öpik's coordinates of impact parameter vector ``\mathbf{B}`` in hyperbolic planetary -close encounter. Returns a named tuple with the following fields: - -- `ξ` = ``\mathbf{B}\cdot\hat{\mathbf{\xi}}/R_E`` and `ζ` = ``\mathbf{B}\cdot\hat{\mathbf{\zeta}}/R_E``, where ``\mathbf{B}`` is the impact parameter vector, ``(\hat{\mathbf{\xi}}, \hat{\mathbf{\zeta}})`` is Öpik's frame and ``R_E`` is the Earth's radius in au. See equations (37)-(38) in page 14 of https://doi.org/10.1007/s10569-019-9914-4. - -- `U` is another named tuple with the following fields: - - `y` = ``U_y``. - - `norm` = ``||\mathbf{U}||`` where ``\mathbf{U}`` is the planetocentric velocity vector in km/s. - -- `b` = ``b_E``, where ``b_E`` is the Earth impact cross section ("critical B"). See [`crosssection`](@ref). - -# Arguments - -- `xae`: asteroid's geocentric position/velocity vector at closest approach in au, au/day. -- `xes`: planet's heliocentric position/velocity vector at asteroid's closest approach in au, au/day. -""" -function bopik(xae, xes) - - # Computation of Öpik's frame (\mathbf{ξ}, \mathbf{ζ}) - # See equations (37)-(38) in page 14 of https://doi.org/10.1007/s10569-019-9914-4 - - # Earth's gravitational parameter - μ_E = PE.μ[ea] - # Asteroid geocentric range at closest approach [au] - rae = sqrt(xae[1]^2 + xae[2]^2 + xae[3]^2) - # Osculating semimajor axis at closest approach (negative since hyperbolic) - a = semimajoraxis(xae..., μ_E, 0.0) - # Asymptotic inbound velocity v_\infty (au/day) - # See equation (1) in page 2 of https://doi.org/10.1007/s10569-019-9914-4 - v_infty = sqrt(μ_E/(-a)) - # Angular momentum per unit mass h = r × v - hvec = cross(xae[1:3], xae[4:6]) - # Magntude of h - h = sqrt(hvec[1]^2 + hvec[2]^2 + hvec[3]^2) - # Laplace-Runge-Lenz (eccentricity) vector - # \vec{e} = (\vec{v} × \vec{h})/μ - \vec{r}/r - evec = cross(xae[4:6], hvec)/μ_E - xae[1:3]/rae - # Osculating eccentricity - e = eccentricity(xae..., μ_E, 0.0) - # Osculating inclination - i = inclination(xae...) - # Periapsis position (unit vector) and periapsis velocity (unit vector) - # See first sentence below equation (3) in page 2 of https://doi.org/10.1007/s10569-019-9914-4 - P_v = evec./e - Q_v = cross(hvec, P_v)./h - # Inbound asymptote direction - # See equation (2) in page 2 of https://doi.org/10.1007/s10569-019-9914-4 - S_v = (P_v + (sqrt(e^2 - 1))Q_v)/e - # Earth's heliocentric velocity at closest approach (CA) - v_pl = xes[4:6] - # ξ-axis is essentially the MOID (Valsecchi et al, 2003) - # See equation (37) in page 14 of https://doi.org/10.1007/s10569-019-9914-4 - ξ_v_unnormalized = cross(v_pl, S_v) - ξ_v_norm = sqrt(ξ_v_unnormalized[1]^2 + ξ_v_unnormalized[2]^2 + ξ_v_unnormalized[3]^2) - ξ_v = ξ_v_unnormalized./ξ_v_norm - # ζ-axis: delay/advance in CA time (Valsecchi et al, 2003) - # See equation (37) in page 14 of https://doi.org/10.1007/s10569-019-9914-4 - ζ_v = -cross(S_v, ξ_v) - - # Computation of Öpik's coordinates of impact parameter vector \mathbf{B} - - # B-vector: "vector from the planet center to the intersection between the B-plane - # and the asymptote". - # See equation (4) in page 3 of https://doi.org/10.1007/s10569-019-9914-4 - Bvec = cross(S_v, hvec)./v_infty - # Impact parameter vector Öpik's coordinates - B_dot_ξ = dot(Bvec, ξ_v) - B_dot_ζ = dot(Bvec, ζ_v) - - # Computation of planetocentric velocity (U) vector - # res = xes[1:3] # Earth's heliocentric position, au - # res_norm = norm(res) # Earth's heliocentric range, au - # res_unit = res/res_norm # Earth's heliocentric radius unit vector - # @show res_norm - ves = v_pl*au/daysec # Earth's velocity, km/s - ves_norm = norm(ves) # Earth's speed, km/s - ves_unit = ves/ves_norm # Earth's velocity unit vector - # X-Y angle (degrees) - # @show rad2deg(acos(dot(ves_unit, res_unit))) - # angle between Y-axis and \vec{U} - cosθ = dot(S_v, ves_unit) - # @show cosθ() - v_infty_kms = v_infty*au/daysec # Asteroid unperturbed speed, km/sec - # @show v_infty_kms() - # The norm of \vec{U} in appropriate units - U_unit = (2pi*au)/(yr*daysec) # 1 U in km/s - U_norm = v_infty_kms/U_unit - # U_y - U_y = U_norm*cosθ - # @show U_y U_norm - - # Earth impact cross section ("critical B") - b_E = crosssection(μ_E, RE/au, v_infty) - # @show b_E - - return (ξ=B_dot_ξ*au/RE, ζ=B_dot_ζ*au/RE, U=(y=U_y, norm=U_norm), b=b_E) -end - -@doc raw""" - valsecchi_circle(a, e, i, k, h; m_pl=3.003489614915764e-6) - -Computes Valsecchi circle associated to a mean motion resonance. Returns radius ``R`` (au) and -``\zeta``-axis coordinate ``D`` (au). This function first computes the Y-component and norm -of the planetocentric velocity vector ``\mathbf{U}`` -```math -U_y = \sqrt{a(1-e^2)}\cos i - 1 \quad \text{and} \quad -U = ||\mathbf{U}|| = \sqrt{3 - \frac{1}{a} - 2\sqrt{a(1-e^2)}\cos i}, -``` -and then substitutes into `valsecchi_circle(U_y, U_norm, k, h; m_pl=3.003489614915764e-6, a_pl=1.0)`. -`a `, `e` and `i` are the asteroid heliocentric semimajor axis (au), eccentricity and -inclination (rad) respectively. - -See section 2.1 in page 1181 of https://doi.org/10.1051/0004-6361:20031039. - -# Arguments - -- `a`: asteroid heliocentric semimajor axis (au). -- `e`: asteroid heliocentric eccentricity. -- `i`: asteroid heliocentric inclination, ecliptic (rad). -- `k/h`: `h` heliocentric revolutions of asteroid per `k` heliocentric revolutions of Earth. -- `m_pl`: planet mass normalized to Sun's mass, equal to Earth mass in solar masses by default. -""" -function valsecchi_circle(a, e, i, k, h; m_pl=3.003489614915764e-6) - # Components and norm of the planetocentric velocity vector - # See section 2.1 in page 1181 of https://doi.org/10.1051/0004-6361:20031039 - # U_x = sqrt( 2 - (1/a) - a*(1-(e^2)) ) # TODO: CHECK SIGN - U_y = sqrt( a*(1-(e^2)) )*cos(i) - 1 - # U_z = sqrt( a*(1-(e^2)) )*sin(i) # TODO: CHECK SIGN - U_norm = sqrt( 3 - (1/a) - 2*sqrt(a*(1-(e^2)))*cos(i) ) - # Expression below should be equal to asteroid heliocentric elliptic semimamajor axis - # in au units - # @show 1/(1-U_^2-2U_y) - return valsecchi_circle(U_y, U_norm, k, h, m_pl=m_pl) -end - -@doc raw""" - valsecchi_circle(U_y, U_norm, k, h; m_pl=3.003489614915764e-6, a_pl=1.0) - -Computes Valsecchi circle associated to a mean motion resonance. Returns radius ``R`` (au) and -``\zeta``-axis coordinate ``D`` (au) -```math -R = \left|\frac{c\sin\theta_0'}{\cos\theta_0' - \cos\theta}\right| \quad \text{and} \quad -D = \frac{c\sin\theta}{\cos\theta_0' - \cos\theta}, -``` -where ``c = m/U^2`` with ``m`` the mass of the planet and ``U = ||\mathbf{U}||`` the norm of -the planetocentric velocity vector; and ``\theta``, ``\theta_0'`` are the angles between Y-axis -and ``\mathbf{U}`` pre and post encounter respectively. - -See pages 1181, 1182 and 1187 of https://doi.org/10.1051/0004-6361:20031039. - -# Arguments -- `U_y`: Y-component of unperturbed planetocentric velocity (Y-axis coincides with the direction of motion of the planet). -- `U_norm`: Euclidean norm of unperturbed planetocentric velocity. Both `U_y`, `U_norm` are in units such that the heliocentric velocity of the planet is 1. -- `k/h`: `h` heliocentric revolutions of asteroid per `k` heliocentric revolutions of Earth. -- `m_pl`: planet mass normalized to Sun's mass, equal to Earth mass in solar masses by default. -- `a_pl`: planetary heliocentric semimajor axis in au; default value is 1. -""" -function valsecchi_circle(U_y, U_norm, k, h; m_pl=3.003489614915764e-6, a_pl=1.0) - # Post-encounter semimajor axis - # See page 1187 of https://doi.org/10.1051/0004-6361:20031039 - a0p = a_pl*(k/h)^(2/3) - - # θ: angle between Y-axis and planetocentric velocity vector \vec{U} - - # Trigonometric functions of pre encounter θ - # See page 1181 of https://doi.org/10.1051/0004-6361:20031039 - cosθ = U_y/U_norm - sinθ = sin(acos(cosθ)) # sqrt(1-cosθ^2) # TODO: CHECK SIGN - # Trigonometric functions of post-encounter θ - # See page 1187 of https://doi.org/10.1051/0004-6361:20031039 - cosθ0p = (1-(U_norm^2)-(1/a0p))/(2U_norm) - sinθ0p = sin(acos(cosθ0p)) - # c = m/U^2 - # See first sentence below equation (3) in section 2.3, page 1182 of - # https://doi.org/10.1051/0004-6361:20031039 - c = m_pl/(U_norm^2) - # Radius of the Valsecchi circle R and its ζ-axis component D - # See page 1187 of https://doi.org/10.1051/0004-6361:20031039 - R0 = abs( c*sinθ0p/(cosθ0p-cosθ) ) - D0 = c*sinθ/(cosθ0p-cosθ) - - return R0, D0 -end +@doc raw""" + crosssection(μ_P, R_P, vinf) + +Returns the "critical" ``B``, derived from conservation of energy and angular momentum +```math +B = \sqrt{1 + \frac{2\mu_P}{R_P v_\infty^2}}, +``` +i.e., what impact parameter ``B`` corresponds to a grazing impact in hyperbolic close +encounter. ``\mu_P`` is the planet's gravitational parameter, ``R_P`` is the planet's +radius and ``v_\infty`` is the asymptotic inbound velocity. If actual ``B`` is equal or +less to this, then impact happens. Output is in planet radii. + +# Arguments + +- `μ_P`: planetary gravitational parameter (au^3/day^2). +- `R_P`: planetary radius (au). +- `vinf`: asymptotic inbound velocity (au/day). + +!!! reference + See equations (13)-(14) in pages 4-5 of https://doi.org/10.1007/s10569-019-9914-4. +""" +function crosssection(μ_P, R_P, vinf) + return sqrt( 1 + (2μ_P)/(R_P*(vinf)^2) ) +end + +@doc raw""" + bopik(xae, xes) + +Computes Öpik's coordinates of impact parameter vector ``\mathbf{B}`` in hyperbolic planetary +close encounter. Returns a named tuple with the following fields: + +- `ξ` = ``\mathbf{B}\cdot\hat{\mathbf{\xi}}/R_E`` and `ζ` = ``\mathbf{B}\cdot\hat{\mathbf{\zeta}}/R_E``, where ``\mathbf{B}`` is the impact parameter vector, ``(\hat{\mathbf{\xi}}, \hat{\mathbf{\zeta}})`` is Öpik's frame and ``R_E`` is the Earth's radius in au. + +- `U` is another named tuple with the following fields: + - `y` = ``U_y``. + - `norm` = ``||\mathbf{U}||`` where ``\mathbf{U}`` is the planetocentric velocity vector in km/s. + +- `b` = ``b_E``, where ``b_E`` is the Earth impact cross section ("critical B"). See [`crosssection`](@ref). + +# Arguments + +- `xae`: asteroid's geocentric position/velocity vector at closest approach in au, au/day. +- `xes`: planet's heliocentric position/velocity vector at asteroid's closest approach in au, au/day. + +!!! reference + See equations (37)-(38) in page 14 of https://doi.org/10.1007/s10569-019-9914-4. +""" +function bopik(xae, xes) + + # Computation of Öpik's frame (\mathbf{ξ}, \mathbf{ζ}) + # See equations (37)-(38) in page 14 of https://doi.org/10.1007/s10569-019-9914-4 + + # Earth's gravitational parameter + μ_E = PE.μ[ea] + # Asteroid geocentric range at closest approach [au] + rae = sqrt(xae[1]^2 + xae[2]^2 + xae[3]^2) + # Osculating semimajor axis at closest approach (negative since hyperbolic) + a = semimajoraxis(xae..., μ_E, 0.0) + # Asymptotic inbound velocity v_\infty (au/day) + # See equation (1) in page 2 of https://doi.org/10.1007/s10569-019-9914-4 + v_infty = sqrt(μ_E/(-a)) + # Angular momentum per unit mass h = r × v + hvec = cross(xae[1:3], xae[4:6]) + # Magntude of h + h = sqrt(hvec[1]^2 + hvec[2]^2 + hvec[3]^2) + # Laplace-Runge-Lenz (eccentricity) vector + # \vec{e} = (\vec{v} × \vec{h})/μ - \vec{r}/r + evec = cross(xae[4:6], hvec)/μ_E - xae[1:3]/rae + # Osculating eccentricity + e = eccentricity(xae..., μ_E, 0.0) + # Osculating inclination + i = inclination(xae...) + # Periapsis position (unit vector) and periapsis velocity (unit vector) + # See first sentence below equation (3) in page 2 of https://doi.org/10.1007/s10569-019-9914-4 + P_v = evec./e + Q_v = cross(hvec, P_v)./h + # Inbound asymptote direction + # See equation (2) in page 2 of https://doi.org/10.1007/s10569-019-9914-4 + S_v = (P_v + (sqrt(e^2 - 1))Q_v)/e + # Earth's heliocentric velocity at closest approach (CA) + v_pl = xes[4:6] + # ξ-axis is essentially the MOID (Valsecchi et al, 2003) + # See equation (37) in page 14 of https://doi.org/10.1007/s10569-019-9914-4 + ξ_v_unnormalized = cross(v_pl, S_v) + ξ_v_norm = sqrt(ξ_v_unnormalized[1]^2 + ξ_v_unnormalized[2]^2 + ξ_v_unnormalized[3]^2) + ξ_v = ξ_v_unnormalized./ξ_v_norm + # ζ-axis: delay/advance in CA time (Valsecchi et al, 2003) + # See equation (37) in page 14 of https://doi.org/10.1007/s10569-019-9914-4 + ζ_v = -cross(S_v, ξ_v) + + # Computation of Öpik's coordinates of impact parameter vector \mathbf{B} + + # B-vector: "vector from the planet center to the intersection between the B-plane + # and the asymptote". + # See equation (4) in page 3 of https://doi.org/10.1007/s10569-019-9914-4 + Bvec = cross(S_v, hvec)./v_infty + # Impact parameter vector Öpik's coordinates + B_dot_ξ = dot(Bvec, ξ_v) + B_dot_ζ = dot(Bvec, ζ_v) + + # Computation of planetocentric velocity (U) vector + # res = xes[1:3] # Earth's heliocentric position, au + # res_norm = norm(res) # Earth's heliocentric range, au + # res_unit = res/res_norm # Earth's heliocentric radius unit vector + # @show res_norm + ves = v_pl*au/daysec # Earth's velocity, km/s + ves_norm = norm(ves) # Earth's speed, km/s + ves_unit = ves/ves_norm # Earth's velocity unit vector + # X-Y angle (degrees) + # @show rad2deg(acos(dot(ves_unit, res_unit))) + # angle between Y-axis and \vec{U} + cosθ = dot(S_v, ves_unit) + # @show cosθ() + v_infty_kms = v_infty*au/daysec # Asteroid unperturbed speed, km/sec + # @show v_infty_kms() + # The norm of \vec{U} in appropriate units + U_unit = (2pi*au)/(yr*daysec) # 1 U in km/s + U_norm = v_infty_kms/U_unit + # U_y + U_y = U_norm*cosθ + # @show U_y U_norm + + # Earth impact cross section ("critical B") + b_E = crosssection(μ_E, RE/au, v_infty) + # @show b_E + + return (ξ=B_dot_ξ*au/RE, ζ=B_dot_ζ*au/RE, U=(y=U_y, norm=U_norm), b=b_E) +end + +@doc raw""" + valsecchi_circle(a, e, i, k, h; m_pl=3.003489614915764e-6) + +Computes Valsecchi circle associated to a mean motion resonance. Returns radius ``R`` (au) and +``\zeta``-axis coordinate ``D`` (au). This function first computes the Y-component and norm +of the planetocentric velocity vector ``\mathbf{U}`` +```math +U_y = \sqrt{a(1-e^2)}\cos i - 1 \quad \text{and} \quad +U = ||\mathbf{U}|| = \sqrt{3 - \frac{1}{a} - 2\sqrt{a(1-e^2)}\cos i}, +``` +and then substitutes into `valsecchi_circle(U_y, U_norm, k, h; m_pl=3.003489614915764e-6, a_pl=1.0)`. +`a `, `e` and `i` are the asteroid heliocentric semimajor axis (au), eccentricity and +inclination (rad) respectively. + +# Arguments + +- `a`: asteroid heliocentric semimajor axis (au). +- `e`: asteroid heliocentric eccentricity. +- `i`: asteroid heliocentric inclination, ecliptic (rad). +- `k/h`: `h` heliocentric revolutions of asteroid per `k` heliocentric revolutions of Earth. +- `m_pl`: planet mass normalized to Sun's mass, equal to Earth mass in solar masses by default. + +!!! reference + See section 2.1 in page 1181 of https://doi.org/10.1051/0004-6361:20031039. +""" +function valsecchi_circle(a, e, i, k, h; m_pl=3.003489614915764e-6) + # Components and norm of the planetocentric velocity vector + # See section 2.1 in page 1181 of https://doi.org/10.1051/0004-6361:20031039 + # U_x = sqrt( 2 - (1/a) - a*(1-(e^2)) ) # TODO: CHECK SIGN + U_y = sqrt( a*(1-(e^2)) )*cos(i) - 1 + # U_z = sqrt( a*(1-(e^2)) )*sin(i) # TODO: CHECK SIGN + U_norm = sqrt( 3 - (1/a) - 2*sqrt(a*(1-(e^2)))*cos(i) ) + # Expression below should be equal to asteroid heliocentric elliptic semimamajor axis + # in au units + # @show 1/(1-U_^2-2U_y) + return valsecchi_circle(U_y, U_norm, k, h, m_pl=m_pl) +end + +@doc raw""" + valsecchi_circle(U_y, U_norm, k, h; m_pl=3.003489614915764e-6, a_pl=1.0) + +Computes Valsecchi circle associated to a mean motion resonance. Returns radius ``R`` (au) and +``\zeta``-axis coordinate ``D`` (au) +```math +R = \left|\frac{c\sin\theta_0'}{\cos\theta_0' - \cos\theta}\right| \quad \text{and} \quad +D = \frac{c\sin\theta}{\cos\theta_0' - \cos\theta}, +``` +where ``c = m/U^2`` with ``m`` the mass of the planet and ``U = ||\mathbf{U}||`` the norm of +the planetocentric velocity vector; and ``\theta``, ``\theta_0'`` are the angles between Y-axis +and ``\mathbf{U}`` pre and post encounter respectively. + +# Arguments +- `U_y`: Y-component of unperturbed planetocentric velocity (Y-axis coincides with the direction of motion of the planet). +- `U_norm`: Euclidean norm of unperturbed planetocentric velocity. Both `U_y`, `U_norm` are in units such that the heliocentric velocity of the planet is 1. +- `k/h`: `h` heliocentric revolutions of asteroid per `k` heliocentric revolutions of Earth. +- `m_pl`: planet mass normalized to Sun's mass, equal to Earth mass in solar masses by default. +- `a_pl`: planetary heliocentric semimajor axis in au; default value is 1. + +!!! reference + See pages 1181, 1182 and 1187 of https://doi.org/10.1051/0004-6361:20031039. +""" +function valsecchi_circle(U_y, U_norm, k, h; m_pl=3.003489614915764e-6, a_pl=1.0) + # Post-encounter semimajor axis + # See page 1187 of https://doi.org/10.1051/0004-6361:20031039 + a0p = a_pl*(k/h)^(2/3) + + # θ: angle between Y-axis and planetocentric velocity vector \vec{U} + + # Trigonometric functions of pre encounter θ + # See page 1181 of https://doi.org/10.1051/0004-6361:20031039 + cosθ = U_y/U_norm + sinθ = sin(acos(cosθ)) # sqrt(1-cosθ^2) # TODO: CHECK SIGN + # Trigonometric functions of post-encounter θ + # See page 1187 of https://doi.org/10.1051/0004-6361:20031039 + cosθ0p = (1-(U_norm^2)-(1/a0p))/(2U_norm) + sinθ0p = sin(acos(cosθ0p)) + # c = m/U^2 + # See first sentence below equation (3) in section 2.3, page 1182 of + # https://doi.org/10.1051/0004-6361:20031039 + c = m_pl/(U_norm^2) + # Radius of the Valsecchi circle R and its ζ-axis component D + # See page 1187 of https://doi.org/10.1051/0004-6361:20031039 + R0 = abs( c*sinθ0p/(cosθ0p-cosθ) ) + D0 = c*sinθ/(cosθ0p-cosθ) + + return R0, D0 +end \ No newline at end of file diff --git a/src/postprocessing/least_squares.jl b/src/postprocessing/least_squares.jl old mode 100644 new mode 100755 index 0af7e223..9a679ebe --- a/src/postprocessing/least_squares.jl +++ b/src/postprocessing/least_squares.jl @@ -1,624 +1,673 @@ -@doc raw""" - OrbitFit{T <: Real} - -A least squares fit. - -# Fields -- `success::Bool`: whether the routine converged or not. -- `x::Vector{T}`: deltas that minimize the objective function. -- `Γ::Matrix{T}`: covariance matrix. -- `routine::Symbol`: minimization routine (`:newton` or `:diffcorr`). -""" -@auto_hash_equals struct OrbitFit{T <: Real} - success::Bool - x::Vector{T} - Γ::Matrix{T} - routine::Symbol - OrbitFit{T}(success::Bool, x::Vector{T}, Γ::Matrix{T}, routine::Symbol) where {T <: Real} = new{T}(success, x, Γ, routine) -end - -OrbitFit(success::Bool, x::Vector{T}, Γ::Matrix{T}, routine::Symbol) where {T <: Real} = OrbitFit{T}(success, x, Γ, routine) - -# Print method for OrbitFit -# Examples: -# Succesful Newton -# Succesful differential corrections -function show(io::IO, fit::OrbitFit{T}) where {T <: Real} - success_s = fit.success ? "Succesful" : "Unsuccesful" - routine_s = fit.routine == :newton ? "Newton" : "differential corrections" - print(io, success_s, " ", routine_s) -end - -@doc raw""" - carpino_smoothing(n::T) where {T <: Real} - -Fudge term for rejection condition in [`outlier_rejection`](@ref). - -!!! reference - See page 253 of https://doi.org/10.1016/S0019-1035(03)00051-4. -""" -carpino_smoothing(n::T) where {T <: Real} = 400*(1.2)^(-n) - -@doc raw""" - outlier_rejection(ξs::Vector{OpticalResidual{T}}, fit::OrbitFit{T}; χ2_rec::T = 7., χ2_rej::T = 8., - α::T = 0.25) where {T <: Real} - -Outlier rejection algorithm. - -# Arguments - -- `ξs::Vector{OpticalResidual{T}}`: vector of residuals. -- `fit::OrbitFit{T}`: least squares fit. -- `χ2_rec::T`: recovery conditions. -- `χ2_rej::T`: rejection condition. -- `α::T`: scaling factor for maximum chi. - -!!! reference - See https://doi.org/10.1016/S0019-1035(03)00051-4. -""" -function outlier_rejection(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}; - χ2_rec::T = 7., χ2_rej::T = 8., α::T = 0.25, max_per::T = 10.) where {T <: Real} - - # Number of residuals - L = length(res) - # Evaluate residuals - eval_res = res(fit.x) - # Vector of χ2 - χ2s = Vector{T}(undef, L) - # Maximum χ2 (over non outliers) - χ2_max = zero(T) - # Number of non outliers - N_sel = 0 - - # Compute χ2s - for i in eachindex(χ2s) - # Weights of current residual - w_α, w_δ = res[i].w_α / res[i].relax_factor, res[i].w_δ / res[i].relax_factor - # Current observation covariance matrix - γ = [w_α zero(T); zero(T) w_δ] - # Current model matrix - A = hcat(TS.gradient(res[i].ξ_α)(fit.x), TS.gradient(res[i].ξ_δ)(fit.x)) - # Outlier sign - outlier_sign = res[i].outlier*2-1 - # Current residual covariance matrix - γ_ξ = γ + outlier_sign*(A')*fit.Γ*A - # Current residual - ξ = [eval_res[i].ξ_α, eval_res[i].ξ_δ] - # Current chi2 - χ2s[i] = ξ' * inv(γ_ξ) * ξ - # Update N_sel - if !res[i].outlier - N_sel += 1 - # Update maximum χ2 - if χ2s[i] > χ2_max - χ2_max = χ2s[i] - end - end - end - - # Maximum allowed drops - max_drop = ceil(Int, max_per * L / 100) - # Number of dropped residuals - N_drop = 0 - # New outliers - new_outliers = outlier.(res) - # Sort χ2s - idxs = sortperm(χ2s, rev = true) - # Rejection threshold - χ2_rej = max(χ2_rej + carpino_smoothing(N_sel), α*χ2_max) - - for i in idxs - if χ2s[i] > χ2_rej && N_drop < max_drop - new_outliers[i] = true - N_drop += 1 - elseif χ2s[i] < χ2_rec - new_outliers[i] = false - end - end - - return OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) -end - -@doc raw""" - project(y::Vector{TaylorN{T}}, fit::OrbitFit{T}) where {T <: Real} - -Project `fit`'s covariance matrix into `y`. -""" -function project(y::Vector{TaylorN{T}}, fit::OrbitFit{T}) where {T <: Real} - J = Matrix{T}(undef, get_numvars(), length(y)) - for i in eachindex(y) - J[:, i] = TS.gradient(y[i])(fit.x) - end - return (J') * fit.Γ * J -end - -@doc raw""" - chi2(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} - -Returns the chi square -```math -\chi^2 = \sum_{i=1}^m \frac{ \xi_i^2}{\sigma_i^2}, -``` -where ``\mathbf{w} = (1/\sigma_1^2,\ldots,1/\sigma_m^2)^T`` and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` -are the vectors of weights and residuals respectively. - -# Arguments - -- `res::Vector{U}`: Vector of residuals. -- `w::Vector{T}`: Vector of weights. -""" -function chi2(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} - # Have as many residuals as weights - @assert length(res) == length(w) - # Chi square - return sum(w .* (res.^2)) -end - -@doc raw""" - nrms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} - nrms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} - nrms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}) where {T <: Real} - -Returns the normalized root mean square error -```math -\texttt{NRMS} = \sqrt{\frac{\chi^2}{m}}, -``` -where ``\chi^2`` is the chi square and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` is the vector -of residuals. - -See also [`chi2`](@ref). - -# Arguments - -- `res`: Vector of residuals. -- `w`: Vector of weights. -- `fit`: least squares fit. - -""" -function nrms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} - # Have as many residuals as weights - @assert length(res) == length(w) - # Normalized root mean square error - return sqrt( chi2(res, w)/length(res) ) -end - -function nrms(res::AbstractVector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} - res_, w = unfold(res) - return nrms(res_, w) -end - -function nrms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}) where {T <: Real} - res_, w = unfold(res) - return nrms(res_(fit.x), w) -end - -@doc raw""" - BHC(res, w, npar) - -Returns the ``\mathbf{B}``, ``\mathbf{H}`` and ``\mathbf{C}`` arrays -```math -\mathbf{B} = \frac{\partial\mathbf{\xi}}{\partial\mathbf{x}_0}(\mathbf{x}_0), \quad -\mathbf{H} = \frac{\partial^2\mathbf{\xi}}{\partial\mathbf{x}_0^2}(\mathbf{x}_0) \quad \text{and} \quad -\mathbf{C} = \mathbf{B}^T\mathbf{W}\mathbf{B}, -``` -where ``\mathbf{x}_0 = (x_1,\ldots,x_n)^T`` and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` -are the vectors of initial conditions and residuals respectively; and ``\mathbf{W} = \text{diag}(1/\sigma_1^2,\ldots,1/\sigma_m^2)`` -is the weights matrix. - -``\mathbf{B}`` is called the design matrix and is of size ``m\times n``, ``\mathbf{H}`` is a three index -array of size ``m\times n\times n`` and ``\mathbf{C}`` is called the normal matrix and is of size ``n\times n``. -See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. - -# Arguments - -- `res`: Vector of residuals. -- `w`: Vector of weights. -- `npar`: Degrees of freedom ``n``. -""" -function BHC(res, w, npar) - # Number of observations - nobs = length(res) - - # Allocate memory for the three arrays - B_mat = Matrix{TaylorN{Float64}}(undef, nobs, npar) - H_mat = Array{TaylorN{Float64}}(undef, nobs, npar, npar) - C_mat = Array{TaylorN{Float64}}(undef, npar, npar) - - # Design matrix B - for i in 1:nobs - # Gradient of the i-th residual with respect to the initial conditions x_0 - B_mat[i,:] .= TaylorSeries.gradient(res[i]) - end - # H matrix - for i in 1:nobs - for j in 1:npar - # Gradient of the (i, j)-th element of B with respect to to the initial - # conditions x_0 - H_mat[i,j,:] .= TaylorSeries.gradient(B_mat[i,j]) - end - end - # Normal matrix C - sqrtw_B = sqrt.(w) .* B_mat - C_mat .= (sqrtw_B') * sqrtw_B - - return B_mat, H_mat, C_mat -end - -@doc raw""" - ξTH(w, res, H_mat, npar) - -Returns ``\mathbf{\xi}^T\mathbf{W}\mathbf{H}``, where ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` -is the vector of residuals, ``\mathbf{W} = \text{diag}(1/\sigma_1^2,\ldots,1/\sigma_m^2)`` is -the weights matrix and ``\mathbf{H}`` is the matrix of second derivatives of ``\mathbf{\xi}`` -with respect to the initial conditions. - -See also [`BHC`](@ref). - -# Arguments - -- `w`: Vector of weights. -- `res`: Vector or residuals. -- `H_mat`: matrix of second derivatives of ``\mathbf{\xi}`` with respect to the initial conditions. -- `npar`: Degrees of freedom ``n``. -""" -function ξTH(w, res, H_mat, npar) - # Allocate memory for output - ξTHv = Array{Float64}(undef, npar, npar) - - for j in 1:npar - for i in 1:npar - # transpose(ξ) * W * H matrix - ξTHv[i,j] = (w .* res)' * (H_mat[:,i,j]) - end - end - - return ξTHv -end - -@doc raw""" - diffcorr(ξs::Vector{OpticalResidual{T}}, x0::Vector{T}, niters::Int = 5) where {T <: Real} - -Differential corrections subroutine for least-squares fitting. Returns the `niters`-th -correction -```math -\mathbf{x}_{k+1} = \mathbf{x}_k - \mathbf{C}^{-1}\mathbf{D}, -``` -and the covariance matrix -```math -\mathbf{\Gamma} = \mathbf{C}^{-1}, -``` -where ``\mathbf{C} = \mathbf{B}^T\mathbf{W}\mathbf{B}`` is the normal matrix and -``\mathbf{D} = \mathbf{B}^T\mathbf{W}\mathbf{\xi}``, with ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` -the vector of residuals, ``\mathbf{B}`` the design matrix and ``\mathbf{W} = \text{diag}(1/\sigma_1^2,\ldots,1/\sigma_m^2)`` -the weights matrix. - -See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. - -See also [`BHC`](@ref). - -# Arguments - -- `ξs::Vector{OpticalResidual{T, TaylorN{T}}}`: Vector of residuals. -- `x_0::Vector{T}`: First guess for the initial conditions. -- `niters::Int`: Number of iterations. -""" -function diffcorr(ξs::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, niters::Int = 5) where {T <: Real} - # Unfold residuals and weights - res, w = unfold(ξs) - - return diffcorr(res, w, x0, niters) -end - -function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, niters::Int = 5) where {T <: Real} - # Degrees of freedom - npar = length(x0) - # Design matrix B, H array and normal matrix C - B_mat, H_mat, C_mat = BHC(res, w, npar) - # D matrix: transpose(B) * W * ξ - D_mat = B_mat' * (w .* res) - # ξTH_mat = ξTH(w, res, H_mat, npar) - # Vector of x - x = Matrix{T}(undef, npar, niters + 1) - # First guess - x[:, 1] = x0 - # Vector of errors - error = Vector{T}(undef, niters + 1) - # Error of first guess - error[1] = T(Inf) - # Iteration - for i in 1:niters - # Current x - xi = x[:, i] - # D matrix evaluated in xi - D = D_mat(xi) - # C matrix evaluated in xi - C = C_mat(xi) #.+ ξTH_mat(xi) - # Update rule - Δx = - inv(C)*D - # New x - x[:, i+1] = xi + Δx - # Error - error2 = ( (Δx') * (C*Δx) ) / npar - if error2 ≥ 0 - error[i+1] = sqrt(error2) - # The method do not converge - else - return OrbitFit(false, x[:, i+1], inv(C), :diffcorr) - end - end - # Index with the lowest error - i = argmin(error) - # x with the lowest error - x_new = x[:, i] - # Normal C matrix evaluated in x_new - C = C_mat(x_new) - # Covariance matrix - Γ = inv(C) - - return OrbitFit(true, x_new, Γ, :diffcorr) -end - -@doc raw""" - newtonls(res, w, x0, niters=5) - -Newton method subroutine for least-squares fitting. Returns the `niters`-th iteration -```math -\mathbf{x}_{k+1} = \mathbf{x}_k - -\left(\frac{\partial^2 Q}{\partial\mathbf{x}_0^2}\right)^{-1} -\frac{\partial Q}{\partial\mathbf{x}_0}, -``` -and the covariance matrix -```math -\mathbf{\Gamma} = \mathbf{C}^{-1}, -``` -where ``\mathbf{C} = \frac{m}{2}\frac{\partial^2 Q}{\partial\mathbf{x}_0^2}`` is the normal -matrix, ``Q = \frac{\chi^2}{m}`` is the mean square residual, ``m`` is the number of -observations and ``\mathbf{x}_0 = (x_1,\ldots,x_n)`` is the vector of initial conditions. - -See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. - -See also [`chi2`](@ref). - -# Arguments - -- `ξs::Vector{OpticalResidual{T, TaylorN{T}}}`: Vector of residuals. -- `x_0::Vector{T}`: First guess for the initial conditions. -- `niters::Int`: Number of iterations. -""" -function newtonls(ξs::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, niters::Int = 5) where {T <: Real} - # Unfold residuals and weights - res, w = unfold(ξs) - - return newtonls(res, w, x0, niters) -end - -function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, niters::Int = 5) where {T <: Real} - # Number of observations - nobs = length(res) - # Degrees of freedom - npar = length(x0) - # Mean square residual - Q = chi2(res, w)/nobs - # Vector of x - x = Matrix{T}(undef, npar, niters + 1) - # First guess - x[:, 1] = x0 - # Vector of errors - error = Vector{T}(undef, niters + 1) - # Error of first guess - error[1] = T(Inf) - # Iteration - for i in 1:niters - # Current x - xi = x[:, i] - # Gradient of Q with respect to x - dQ = TaylorSeries.gradient(Q)(xi) - # Hessian of Q with respect to x - d2Q = TaylorSeries.hessian(Q, xi) - # Newton update rule - Δx = - inv(d2Q)*dQ - # New x - x[:, i+1] = xi + Δx - # Normal matrix - C = d2Q/(2/nobs) # C = d2Q/(2/m) - # Error - error2 = ( (Δx') * (C*Δx) ) / npar - if error2 ≥ 0 - error[i+1] = sqrt(error2) - # The method do not converge - else - return OrbitFit(false, x[:, i+1], inv(C), :newton) - end - end - # TO DO: study Gauss method solution dependence on jt order - # TO DO: try even varorder - # TO DO: study optimal number of iterations - - # Index with the lowest error - i = argmin(error) - # x with the lowest error - x_new = x[:, i] - # Normal matrix - C = TaylorSeries.hessian(Q, x_new)/(2/nobs) # C = d2Q/(2/m) - # Covariance matrix - Γ = inv(C) - - return OrbitFit(true, x_new, Γ, :newton) -end - -@doc raw""" - tryls(ξs::Vector{OpticalResidual{T}}, x0::Vector{T}, niters::Int = 5) where {T <: Real} - -Returns the best least squares fit between two routines: [`newtonls`](@ref) and [`diffcorr`](@ref). - -# Arguments - -- `ξs::Vector{OpticalResidual{T, TaylorN{T}}}`: Vector of residuals. -- `x_0::Vector{T}`: First guess for the initial conditions. -- `niters::Int`: Number of iterations. -""" -function tryls(ξs::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, niters::Int = 5) where {T <: Real} - # Newton's method - fit_1 = newtonls(ξs, x0, niters) - # Differential corrections - fit_2 = diffcorr(ξs, x0, niters) - if fit_1.success && fit_2.success - Q_1 = nrms(ξs, fit_1) - Q_2 = nrms(ξs, fit_2) - if Q_1 <= Q_2 - return fit_1 - else - return fit_2 - end - elseif fit_1.success - return fit_1 - elseif fit_2.success - return fit_2 - else - return fit_1 - end - -end - -@doc raw""" - newtonls_Q(Q, nobs, x0, niters=5) - -Does the same as `newtonls`, but recives ``Q`` as an argument, instead of computing it. -Returns the `niters`-th iteration and the covariance matrix ``\Gamma``. - -See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. - -See also [`newtonls`](@ref). - -# Arguments - -- `Q`: Mean square residual. -- `nobs`: Number of observations. -- `x_0`: First guess for the initial conditions. -- `niters`: Number of iterations. -""" -function newtonls_Q(Q, nobs, x0, niters=5) - # Number of observations - npar = length(x0) - # First guess - x_new = x0 - # Iteration - for i in 1:niters - # Gradient of Q with respect to x_0 - dQ = TaylorSeries.gradient(Q)(x_new) - # Hessian of Q with respect to x_0 - d2Q = TaylorSeries.hessian(Q, x_new) - # Newton update rule - Δx = - inv(d2Q)*dQ - x_new = x_new + Δx - # Normal matrix - C = d2Q/(2/nobs) # C = d2Q/(2/m) - @show sqrt(((Δx')*(C*Δx))/npar) - end - # Normal matrix - C = TaylorSeries.hessian(Q, x_new)/(2/nobs) # C = d2Q/(2/m) - # Covariance matrix - Γ = inv(C) - - return x_new, Γ -end - -@doc raw""" - newtonls_6v(res, w, x0, niters=5) - -Specialized version of `newtonls` on 6 variables for parametrized orbit determination -with respect to ``A_2`` Yarkovsky non-gravitational coefficient. Returns the `niters`-th -iteration and the covariance matrix ``\Gamma``. - -See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. - -See also [`newtonls`](@ref). - -# Arguments - -- `res`: Vector of residuals. -- `w`: Vector of weights. -- `x_0`: First guess for the initial conditions. -- `niters`: Number of iterations. -""" -function newtonls_6v(res, w, x0, niters=5) - # Have as many residuals as weights - @assert length(res) == length(w) - # Number of observations - nobs = length(res) - # Degrees of freedom - npar = 6 # length(x0) - # Mean square residual - Q = chi2(res, w)/nobs - # First guess - x_new = x0 - # Iteration - for i in 1:niters - # Gradient of Q with respect to x_0 - dQ = TaylorSeries.gradient(Q)(x_new)[1:6] - # Hessian of Q with respect to x_0 - d2Q = TaylorSeries.hessian(Q, x_new)[1:6,1:6] - # Newton update rule - Δx = - inv(d2Q)*dQ - x_new[1:6] = x_new[1:6] + Δx - # Normal matrix - C = d2Q/(2/nobs) # C = d2Q/(2/m) - @show sqrt(((Δx')*(C*Δx))/npar) - end - # Normal matrix - C = TaylorSeries.hessian(Q, x_new)/(2/nobs) # C = d2Q/(2/m) - # Covariance matrix - Γ = inv(C[1:6,1:6]) - - return x_new, Γ -end - -@doc raw""" - newtonls_A2(res, w, x0, niters=5) - -Specialized version of `newtonls` with the Newton method only over the seventh degree of -freedom, i.e., with respect to ``A_2`` Yarkovsky non-gravitational coefficient. Returns the -`niters`-th iteration, the covariance matrix ``\Gamma`` and the normal matrix ``C``. - -See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. - -See also [`newtonls`](@ref). - -# Arguments - -- `res`: Vector of residuals. -- `w`: Vector of weights. -- `x_0`: First guess for the initial conditions. -- `niters`: Number of iterations. -""" -function newtonls_A2(res, w, x0, niters=5) - # Have as many residuals as weights - @assert length(res) == length(w) - # Number of observations - nobs = length(res) - # Degrees of freedom - npar = length(x0) - # Mean square residual - Q = chi2(res, w)/nobs - # First guess - x_new = x0 - # Iteration - for i in 1:niters - # Gradient of Q with respect to x_0 - dQ = TaylorSeries.gradient(Q)(x_new) - # Hessian of Q with respect to x_0 - d2Q = TaylorSeries.hessian(Q, x_new) - # Newton update rule - Δx = - inv(d2Q)*dQ - x_new[7] = x_new[7] + Δx[7] - # Normal matrix - C = d2Q/(2/nobs) # C = d2Q/(2/m) - @show sqrt(((Δx')*(C*Δx))/npar) - end - # Normal matrix - C = TaylorSeries.hessian(Q, x_new)/(2/nobs) # C = d2Q/(2/m) - # Covariance matrix - Γ = inv(C) - - return x_new, Γ, C -end +@doc raw""" + OrbitFit{T <: Real} + +A least squares fit. + +# Fields +- `success::Bool`: whether the routine converged or not. +- `x::Vector{T}`: deltas that minimize the objective function. +- `Γ::Matrix{T}`: covariance matrix. +- `routine::Symbol`: minimization routine (`:newton` or `:diffcorr`). +""" +@auto_hash_equals struct OrbitFit{T <: Real} + success::Bool + x::Vector{T} + Γ::Matrix{T} + routine::Symbol + # Inner constructor + function OrbitFit{T}(success::Bool, x::Vector{T}, Γ::Matrix{T}, + routine::Symbol) where {T <: Real} + return new{T}(success, x, Γ, routine) + end +end +# Outer constructor +function OrbitFit(success::Bool, x::Vector{T}, Γ::Matrix{T}, + routine::Symbol) where {T <: Real} + return OrbitFit{T}(success, x, Γ, routine) +end + +# Print method for OrbitFit +# Examples: +# Succesful Newton +# Succesful differential corrections +function show(io::IO, fit::OrbitFit{T}) where {T <: Real} + success_s = fit.success ? "Succesful" : "Unsuccesful" + routine_s = fit.routine == :newton ? "Newton" : "differential corrections" + print(io, success_s, " ", routine_s) +end + +@doc raw""" + carpino_smoothing(n::T) where {T <: Real} + +Fudge term for rejection condition in [`outlier_rejection`](@ref). + +!!! reference + See page 253 of https://doi.org/10.1016/S0019-1035(03)00051-4. +""" +carpino_smoothing(n::T) where {T <: Real} = 400*(1.2)^(-n) + +@doc raw""" + outlier_rejection(ξs::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}; + χ2_rec::T = 7.0, χ2_rej::T = 8.0, α::T = 0.25, max_per::T = 10.) where {T <: Real} + +Outlier rejection algorithm. + +# Arguments + +- `ξs::Vector{OpticalResidual{T}}`: vector of residuals. +- `fit::OrbitFit{T}`: least squares fit. +- `χ2_rec::T`: recovery condition. +- `χ2_rej::T`: rejection condition. +- `α::T`: scaling factor for maximum chi. +- `max_per::T`: maximum allowed drop percentage. + +!!! reference + See https://doi.org/10.1016/S0019-1035(03)00051-4. +""" +function outlier_rejection(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}; + χ2_rec::T = 7., χ2_rej::T = 8., α::T = 0.25, max_per::T = 10.) where {T <: Real} + + # Number of residuals + L = length(res) + # Evaluate residuals + eval_res = res(fit.x) + # Vector of χ2 + χ2s = Vector{T}(undef, L) + # Maximum χ2 (over non outliers) + χ2_max = zero(T) + # Number of non outliers + N_sel = 0 + + # Compute χ2s + for i in eachindex(χ2s) + # Weights of current residual + w_α, w_δ = res[i].w_α / res[i].relax_factor, res[i].w_δ / res[i].relax_factor + # Current observation covariance matrix + γ = [w_α zero(T); zero(T) w_δ] + # Current model matrix + A = hcat(TS.gradient(res[i].ξ_α)(fit.x), TS.gradient(res[i].ξ_δ)(fit.x)) + # Outlier sign + outlier_sign = res[i].outlier*2-1 + # Current residual covariance matrix + γ_ξ = γ + outlier_sign*(A')*fit.Γ*A + # Current residual + ξ = [eval_res[i].ξ_α, eval_res[i].ξ_δ] + # Current chi2 + χ2s[i] = ξ' * inv(γ_ξ) * ξ + # Update N_sel + if !res[i].outlier + N_sel += 1 + # Update maximum χ2 + if χ2s[i] > χ2_max + χ2_max = χ2s[i] + end + end + end + + # Maximum allowed drops + max_drop = ceil(Int, max_per * L / 100) + # Number of dropped residuals + N_drop = 0 + # New outliers + new_outliers = outlier.(res) + # Sort χ2s + idxs = sortperm(χ2s, rev = true) + # Rejection threshold + χ2_rej = max(χ2_rej + carpino_smoothing(N_sel), α*χ2_max) + + for i in idxs + if χ2s[i] > χ2_rej && N_drop < max_drop + new_outliers[i] = true + N_drop += 1 + elseif χ2s[i] < χ2_rec + new_outliers[i] = false + end + end + + return OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), + relax_factor.(res), new_outliers) +end + +@doc raw""" + project(y::Vector{TaylorN{T}}, fit::OrbitFit{T}) where {T <: Real} + +Project `fit`'s covariance matrix into `y`. +""" +function project(y::Vector{TaylorN{T}}, fit::OrbitFit{T}) where {T <: Real} + J = Matrix{T}(undef, get_numvars(), length(y)) + for i in eachindex(y) + J[:, i] = TS.gradient(y[i])(fit.x) + end + return (J') * fit.Γ * J +end + +@doc raw""" + chi2(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} + chi2(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + +Returns the chi square +```math +\chi^2 = \sum_{i=1}^m \frac{ \xi_i^2}{\sigma_i^2}, +``` +where ``\mathbf{w} = (1/\sigma_1^2,\ldots,1/\sigma_m^2)^T`` and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` +are the vectors of weights and residuals respectively. + +# Arguments + +- `res::Vector{U}/Vector{OpticalResidual{T, U}}`: vector of residuals. +- `w::Vector{T}`: vector of weights. +""" +function chi2(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} + # Have as many residuals as weights + @assert length(res) == length(w) + # Chi square + return sum(w .* (res.^2)) +end +function chi2(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + _res_, _w_ = unfold(res) + return chi2(_res_, _w_) +end + +@doc raw""" + nms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} + nms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + +Return the normalized chi square. See [`chi2`](@ref). +""" +nms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} = chi2(res, w) / length(res) +function nms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + _res_, _w_ = unfold(res) + return nms(_res_, _w_) +end + +@doc raw""" + nrms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} + nrms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + nrms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}) where {T <: Real} + +Returns the normalized root mean square error +```math +\texttt{NRMS} = \sqrt{\frac{\chi^2}{m}}, +``` +where ``\chi^2`` is the chi square and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` is the vector +of residuals. + +See also [`chi2`](@ref). + +# Arguments + +- `res::Vector{U}/Vector{OpticalResidual{T, U}}`: Vector of residuals. +- `w::Vector{T}`: Vector of weights. +- `fit::OrbitFit{T}`: least squares fit. + +""" +function nrms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} + # Have as many residuals as weights + @assert length(res) == length(w) + # Normalized root mean square error + return sqrt( chi2(res, w)/length(res) ) +end + +function nrms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + _res_, _w_ = unfold(res) + return nrms(_res_, _w_) +end + +function nrms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}) where {T <: Real} + _res_, _w_ = unfold(res) + return nrms(_res_(fit.x), _w_) +end + +@doc raw""" + BHC(res::Vector{TaylorN{T}}, w::Vector{T}, npar::Int) where {T <: Real} + +Returns the ``\mathbf{B}``, ``\mathbf{H}`` and ``\mathbf{C}`` arrays +```math +\mathbf{B} = \frac{\partial\mathbf{\xi}}{\partial\mathbf{x}_0}(\mathbf{x}_0), \quad +\mathbf{H} = \frac{\partial^2\mathbf{\xi}}{\partial\mathbf{x}_0^2}(\mathbf{x}_0) \quad \text{and} \quad +\mathbf{C} = \mathbf{B}^T\mathbf{W}\mathbf{B}, +``` +where ``\mathbf{x}_0 = (x_1,\ldots,x_n)^T`` and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` +are the vectors of initial conditions and residuals respectively; and +``\mathbf{W} = \text{diag}(1/\sigma_1^2,\ldots,1/\sigma_m^2)`` is the weights matrix. + +``\mathbf{B}`` is called the design matrix and is of size ``m\times n``, ``\mathbf{H}`` is a three index +array of size ``m\times n\times n`` and ``\mathbf{C}`` is called the normal matrix and is of size ``n\times n``. + +# Arguments + +- `res::Vector{TaylorN{T}}`: vector of residuals. +- `w::Vector{T}`: vector of weights. +- `npar::Int`: degrees of freedom ``n``. + +!!! reference + See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. +""" +function BHC(res::Vector{TaylorN{T}}, w::Vector{T}, npar::Int) where {T <: Real} + # Number of observations + nobs = length(res) + + # Allocate memory for the three arrays + B_mat = Matrix{TaylorN{T}}(undef, nobs, npar) + H_mat = Array{TaylorN{T}}(undef, nobs, npar, npar) + C_mat = Array{TaylorN{T}}(undef, npar, npar) + + # Design matrix B + for i in 1:nobs + # Gradient of the i-th residual with respect to the initial conditions x_0 + B_mat[i,:] .= TaylorSeries.gradient(res[i]) + end + # H matrix + for i in 1:nobs + for j in 1:npar + # Gradient of the (i, j)-th element of B with respect to to the initial + # conditions x_0 + H_mat[i,j,:] .= TaylorSeries.gradient(B_mat[i,j]) + end + end + # Normal matrix C + sqrtw_B = sqrt.(w) .* B_mat + C_mat .= (sqrtw_B') * sqrtw_B + + return B_mat, H_mat, C_mat +end + +@doc raw""" + ξTH(w, res, H_mat, npar) + +Returns ``\mathbf{\xi}^T\mathbf{W}\mathbf{H}``, where ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` +is the vector of residuals, ``\mathbf{W} = \text{diag}(1/\sigma_1^2,\ldots,1/\sigma_m^2)`` is +the weights matrix and ``\mathbf{H}`` is the matrix of second derivatives of ``\mathbf{\xi}`` +with respect to the initial conditions. + +See also [`BHC`](@ref). + +# Arguments + +- `w`: Vector of weights. +- `res`: Vector or residuals. +- `H_mat`: matrix of second derivatives of ``\mathbf{\xi}`` with respect to the initial conditions. +- `npar`: Degrees of freedom ``n``. +""" +function ξTH(w, res, H_mat, npar) + # Allocate memory for output + ξTHv = Array{Float64}(undef, npar, npar) + + for j in 1:npar + for i in 1:npar + # transpose(ξ) * W * H matrix + ξTHv[i,j] = (w .* res)' * (H_mat[:,i,j]) + end + end + + return ξTHv +end + +@doc raw""" + diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, + niters::Int = 5) where {T <: Real} + diffcorr(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, + niters::Int = 5) where {T <: Real} + +Differential corrections subroutine for least-squares fitting. Returns an +`OrbitFit` with the `niters`-th +correction +```math +\mathbf{x}_{k+1} = \mathbf{x}_k - \mathbf{C}^{-1}\mathbf{D}, +``` +and the covariance matrix +```math +\mathbf{\Gamma} = \mathbf{C}^{-1}, +``` +where ``\mathbf{C} = \mathbf{B}^T\mathbf{W}\mathbf{B}`` is the normal matrix and +``\mathbf{D} = \mathbf{B}^T\mathbf{W}\mathbf{\xi}``, with ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` +the vector of residuals, ``\mathbf{B}`` the design matrix and ``\mathbf{W} = \text{diag}(1/\sigma_1^2,\ldots,1/\sigma_m^2)`` +the weights matrix. + +See also [`BHC`](@ref). + +# Arguments + +- `res::Vector{TaylorN{T}/Vector{OpticalResidual{T, TaylorN{T}}}`: vector of residuals. +- `w::Vector{T}`: vector of weights. +- `x_0::Vector{T}`: first guess. +- `niters::Int`: number of iterations. + +!!! reference + See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. +""" +function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, + niters::Int = 5) where {T <: Real} + # Degrees of freedom + npar = length(x0) + # Design matrix B, H array and normal matrix C + B_mat, H_mat, C_mat = BHC(res, w, npar) + # D matrix: transpose(B) * W * ξ + D_mat = B_mat' * (w .* res) + # ξTH_mat = ξTH(w, res, H_mat, npar) + # Vector of x + x = Matrix{T}(undef, npar, niters + 1) + # First guess + x[:, 1] = x0 + # Vector of errors + error = Vector{T}(undef, niters + 1) + # Error of first guess + error[1] = T(Inf) + # Iteration + for i in 1:niters + # Current x + xi = x[:, i] + # D matrix evaluated in xi + D = D_mat(xi) + # C matrix evaluated in xi + C = C_mat(xi) #.+ ξTH_mat(xi) + # Update rule + Δx = - inv(C)*D + # New x + x[:, i+1] = xi + Δx + # Error + error2 = ( (Δx') * (C*Δx) ) / npar + if error2 ≥ 0 + error[i+1] = sqrt(error2) + # The method do not converge + else + return OrbitFit(false, x[:, i+1], inv(C), :diffcorr) + end + end + # Index with the lowest error + i = argmin(error) + # x with the lowest error + x_new = x[:, i] + # Normal C matrix evaluated in x_new + C = C_mat(x_new) + # Covariance matrix + Γ = inv(C) + + return OrbitFit(true, x_new, Γ, :diffcorr) +end + +function diffcorr(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, + niters::Int = 5) where {T <: Real} + # Unfold residuals and weights + _res_, _w_ = unfold(res) + + return diffcorr(_res_, _w_, x0, niters) +end + +@doc raw""" + newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, + niters::Int = 5) where {T <: Real} + newtonls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, + niters::Int = 5) where {T <: Real} + +Newton method subroutine for least-squares fitting. Returns an `OrbitFit` +with the `niters`-th iteration +```math +\mathbf{x}_{k+1} = \mathbf{x}_k - +\left(\frac{\partial^2 Q}{\partial\mathbf{x}_0^2}\right)^{-1} +\frac{\partial Q}{\partial\mathbf{x}_0}, +``` +and the covariance matrix +```math +\mathbf{\Gamma} = \mathbf{C}^{-1}, +``` +where ``\mathbf{C} = \frac{m}{2}\frac{\partial^2 Q}{\partial\mathbf{x}_0^2}`` is the normal +matrix, ``Q = \frac{\chi^2}{m}`` is the mean square residual, ``m`` is the number of +observations and ``\mathbf{x}_0 = (x_1,\ldots,x_n)`` is the vector of initial conditions. + +See also [`chi2`](@ref). + +# Arguments + +- `res::Vector{TaylorN{T}/Vector{OpticalResidual{T, TaylorN{T}}}`: vector of residuals. +- `w::Vector{T}`: vector of weights. +- `x_0::Vector{T}`: first guess. +- `niters::Int`: number of iterations. + +!!! reference + See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. +""" +function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, + niters::Int = 5) where {T <: Real} + # Number of observations + nobs = length(res) + # Degrees of freedom + npar = length(x0) + # Mean square residual + Q = chi2(res, w)/nobs + # Vector of x + x = Matrix{T}(undef, npar, niters + 1) + # First guess + x[:, 1] = x0 + # Vector of errors + error = Vector{T}(undef, niters + 1) + # Error of first guess + error[1] = T(Inf) + # Iteration + for i in 1:niters + # Current x + xi = x[:, i] + # Gradient of Q with respect to x + dQ = TaylorSeries.gradient(Q)(xi) + # Hessian of Q with respect to x + d2Q = TaylorSeries.hessian(Q, xi) + # Newton update rule + Δx = - inv(d2Q)*dQ + # New x + x[:, i+1] = xi + Δx + # Normal matrix + C = d2Q/(2/nobs) # C = d2Q/(2/m) + # Error + error2 = ( (Δx') * (C*Δx) ) / npar + if error2 ≥ 0 + error[i+1] = sqrt(error2) + # The method do not converge + else + return OrbitFit(false, x[:, i+1], inv(C), :newton) + end + end + # TO DO: study Gauss method solution dependence on jt order + # TO DO: try even varorder + # TO DO: study optimal number of iterations + + # Index with the lowest error + i = argmin(error) + # x with the lowest error + x_new = x[:, i] + # Normal matrix + C = TaylorSeries.hessian(Q, x_new)/(2/nobs) # C = d2Q/(2/m) + # Covariance matrix + Γ = inv(C) + + return OrbitFit(true, x_new, Γ, :newton) +end + +function newtonls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, + niters::Int = 5) where {T <: Real} + # Unfold residuals and weights + _res_, _w_ = unfold(res) + + return newtonls(_res_, _w_, x0, niters) +end + +@doc raw""" + tryls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, + niters::Int = 5) where {T <: Real} + +Return the best least squares fit between two routines: [`newtonls`](@ref) and +[`diffcorr`](@ref). + +# Arguments + +- `res::Vector{OpticalResidual{T, TaylorN{T}}}`: vector of residuals. +- `x_0::Vector{T}`: first guess. +- `niters::Int`: number of iterations. +""" +function tryls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, + niters::Int = 5) where {T <: Real} + # Newton's method + fit_1 = newtonls(res, x0, niters) + # Differential corrections + fit_2 = diffcorr(res, x0, niters) + if fit_1.success && fit_2.success + Q_1 = nrms(res, fit_1) + Q_2 = nrms(res, fit_2) + if Q_1 <= Q_2 + return fit_1 + else + return fit_2 + end + elseif fit_1.success + return fit_1 + elseif fit_2.success + return fit_2 + else + return fit_1 + end + +end + +# TO DO: update / deprecate the following three functions + +@doc raw""" + newtonls_Q(Q, nobs, x0, niters=5) + +Does the same as `newtonls`, but recives ``Q`` as an argument, instead of computing it. +Returns the `niters`-th iteration and the covariance matrix ``\Gamma``. + +See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. + +See also [`newtonls`](@ref). + +# Arguments + +- `Q`: Mean square residual. +- `nobs`: Number of observations. +- `x_0`: First guess for the initial conditions. +- `niters`: Number of iterations. +""" +function newtonls_Q(Q, nobs, x0, niters=5) + # Number of observations + npar = length(x0) + # First guess + x_new = x0 + # Iteration + for i in 1:niters + # Gradient of Q with respect to x_0 + dQ = TaylorSeries.gradient(Q)(x_new) + # Hessian of Q with respect to x_0 + d2Q = TaylorSeries.hessian(Q, x_new) + # Newton update rule + Δx = - inv(d2Q)*dQ + x_new = x_new + Δx + # Normal matrix + C = d2Q/(2/nobs) # C = d2Q/(2/m) + @show sqrt(((Δx')*(C*Δx))/npar) + end + # Normal matrix + C = TaylorSeries.hessian(Q, x_new)/(2/nobs) # C = d2Q/(2/m) + # Covariance matrix + Γ = inv(C) + + return x_new, Γ +end + +@doc raw""" + newtonls_6v(res, w, x0, niters=5) + +Specialized version of `newtonls` on 6 variables for parametrized orbit determination +with respect to ``A_2`` Yarkovsky non-gravitational coefficient. Returns the `niters`-th +iteration and the covariance matrix ``\Gamma``. + +See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. + +See also [`newtonls`](@ref). + +# Arguments + +- `res`: Vector of residuals. +- `w`: Vector of weights. +- `x_0`: First guess for the initial conditions. +- `niters`: Number of iterations. +""" +function newtonls_6v(res, w, x0, niters=5) + # Have as many residuals as weights + @assert length(res) == length(w) + # Number of observations + nobs = length(res) + # Degrees of freedom + npar = 6 # length(x0) + # Mean square residual + Q = chi2(res, w)/nobs + # First guess + x_new = x0 + # Iteration + for i in 1:niters + # Gradient of Q with respect to x_0 + dQ = TaylorSeries.gradient(Q)(x_new)[1:6] + # Hessian of Q with respect to x_0 + d2Q = TaylorSeries.hessian(Q, x_new)[1:6,1:6] + # Newton update rule + Δx = - inv(d2Q)*dQ + x_new[1:6] = x_new[1:6] + Δx + # Normal matrix + C = d2Q/(2/nobs) # C = d2Q/(2/m) + @show sqrt(((Δx')*(C*Δx))/npar) + end + # Normal matrix + C = TaylorSeries.hessian(Q, x_new)/(2/nobs) # C = d2Q/(2/m) + # Covariance matrix + Γ = inv(C[1:6,1:6]) + + return x_new, Γ +end + +@doc raw""" + newtonls_A2(res, w, x0, niters=5) + +Specialized version of `newtonls` with the Newton method only over the seventh degree of +freedom, i.e., with respect to ``A_2`` Yarkovsky non-gravitational coefficient. Returns the +`niters`-th iteration, the covariance matrix ``\Gamma`` and the normal matrix ``C``. + +See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. + +See also [`newtonls`](@ref). + +# Arguments + +- `res`: Vector of residuals. +- `w`: Vector of weights. +- `x_0`: First guess for the initial conditions. +- `niters`: Number of iterations. +""" +function newtonls_A2(res, w, x0, niters=5) + # Have as many residuals as weights + @assert length(res) == length(w) + # Number of observations + nobs = length(res) + # Degrees of freedom + npar = length(x0) + # Mean square residual + Q = chi2(res, w)/nobs + # First guess + x_new = x0 + # Iteration + for i in 1:niters + # Gradient of Q with respect to x_0 + dQ = TaylorSeries.gradient(Q)(x_new) + # Hessian of Q with respect to x_0 + d2Q = TaylorSeries.hessian(Q, x_new) + # Newton update rule + Δx = - inv(d2Q)*dQ + x_new[7] = x_new[7] + Δx[7] + # Normal matrix + C = d2Q/(2/nobs) # C = d2Q/(2/m) + @show sqrt(((Δx')*(C*Δx))/npar) + end + # Normal matrix + C = TaylorSeries.hessian(Q, x_new)/(2/nobs) # C = d2Q/(2/m) + # Covariance matrix + Γ = inv(C) + + return x_new, Γ, C +end diff --git a/src/postprocessing/neosolution.jl b/src/postprocessing/neosolution.jl old mode 100644 new mode 100755 index 7bdd6604..a085df11 --- a/src/postprocessing/neosolution.jl +++ b/src/postprocessing/neosolution.jl @@ -1,279 +1,125 @@ -include("b_plane.jl") -include("least_squares.jl") - -@auto_hash_equals struct NEOSolution{T <: Real, U <: Number} - bwd::TaylorInterpolant{T, U, 2} - t_bwd::Vector{U} - x_bwd::Vector{U} - g_bwd::Vector{U} - fwd::TaylorInterpolant{T, U, 2} - t_fwd::Vector{U} - x_fwd::Vector{U} - g_fwd::Vector{U} - res::Vector{OpticalResidual{T, U}} - fit::OrbitFit{T} - function NEOSolution{T, U}(bwd::TaylorInterpolant{T, U, 2}, t_bwd::Vector{U}, x_bwd::Vector{U}, g_bwd::Vector{U}, - fwd::TaylorInterpolant{T, U, 2}, t_fwd::Vector{U}, x_fwd::Vector{U}, g_fwd::Vector{U}, - res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}) where {T <: Real, U <: Number} - @assert bwd.t0 == fwd.t0 "Backward and forward propagation initial times must match" - new{T, U}(bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, res, fit) - end -end - -function NEOSolution(bwd::TaylorInterpolant{T, U, 2}, t_bwd::Vector{U}, x_bwd::Vector{U}, g_bwd::Vector{U}, - fwd::TaylorInterpolant{T, U, 2}, t_fwd::Vector{U}, x_fwd::Vector{U}, g_fwd::Vector{U}, - res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}) where {T <: Real, U <: Number} - NEOSolution{T, U}(bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, res, fit) -end - -function NEOSolution(bwd::TaylorInterpolant{T, U, 2}, fwd::TaylorInterpolant{T, U, 2}, - res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}) where {T <: Real, U <: Number} - # Backward roots - t_bwd = Vector{U}(undef, 0) - x_bwd = Vector{U}(undef, 0) - g_bwd = Vector{U}(undef, 0) - # forward roots - t_fwd = Vector{U}(undef, 0) - x_fwd = Vector{U}(undef, 0) - g_fwd = Vector{U}(undef, 0) - - return NEOSolution{T, U}(bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, res, fit) -end - -# Print method for NEOSolution -# Examples: -# NEO solution with 123 residuals -function show(io::IO, x::NEOSolution{T, U}) where {T <: Real, U <: Number} - print(io, "NEO solution with ", length(x.res), " residuals") -end - -# Evaluation in time method -function (sol::NEOSolution{T, U})(t::V) where {T <: Real, U <: Number, V <: Number} - if t <= sol.bwd.t0 - return sol.bwd(t) - else - return sol.fwd(t) - end -end - -# Evaluation in fit δs method -function evalfit(sol::NEOSolution{T, TaylorN{T}}) where {T <: Real} - # Fit δs - δs = sol.fit.x - # Evaluate backward integration - new_bwd_x = map(x -> Taylor1(x.coeffs(δs)), sol.bwd.x); - new_bwd = TaylorInterpolant{T, T, 2}(sol.bwd.t0, sol.bwd.t, new_bwd_x) - # Evaluate backward roots - new_t_bwd = sol.t_bwd(δs) - new_x_bwd = sol.x_bwd(δs) - new_g_bwd = sol.g_bwd(δs) - # Evaluate forward integration - new_fwd_x = map(x -> Taylor1(x.coeffs(δs)), sol.fwd.x); - new_fwd = TaylorInterpolant{T, T, 2}(sol.fwd.t0, sol.fwd.t, new_fwd_x) - # Evaluate forward roots - new_t_fwd = sol.t_fwd(δs) - new_x_fwd = sol.x_fwd(δs) - new_g_fwd = sol.g_fwd(δs) - # Evaluate residuals - new_res = sol.res(δs) - - return NEOSolution{T, T}(new_bwd, new_t_bwd, new_x_bwd, new_g_bwd, - new_fwd, new_t_fwd, new_x_fwd, new_g_fwd, - new_res, sol.fit) -end - -function zero(::Type{NEOSolution{T, U}}) where {T <: Real, U <: Number} - bwd = TaylorInterpolant{T, U, 2}(zero(T), zeros(T, 1), Matrix{Taylor1{U}}(undef, 0, 0)) - t_bwd = Vector{U}(undef, 0) - x_bwd = Vector{U}(undef, 0) - g_bwd = Vector{U}(undef, 0) - fwd = TaylorInterpolant{T, U, 2}(zero(T), zeros(T, 1), Matrix{Taylor1{U}}(undef, 0, 0)) - t_fwd = Vector{U}(undef, 0) - x_fwd = Vector{U}(undef, 0) - g_fwd = Vector{U}(undef, 0) - res = Vector{OpticalResidual{T, U}}(undef, 0) - fit = OrbitFit{T}(false, Vector{T}(undef, 0), Matrix{T}(undef, 0, 0), :newton) - return NEOSolution{T, U}(bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, - res, fit) -end - -iszero(x::NEOSolution{T, U}) where {T <: Real, U <: Number} = x == zero(NEOSolution{T, U}) - -@doc raw""" - residual_norm(x::OpticalResidual{T, T}) where {T <: Real} - -Return the contribution of `x` to the nrms. -""" -residual_norm(x::OpticalResidual{T, T}) where {T <: Real} = x.w_α * x.ξ_α^2 / x.relax_factor + x.w_δ * x.ξ_δ^2 / x.relax_factor - -function orbitdetermination(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}; - debias_table::String = "2018", kwargs...) where {T <: Real} - mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) - return orbitdetermination(radec, sol, mpc_catalogue_codes_201X, truth, resol, bias_matrix; kwargs...) -end - -function orbitdetermination(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, mpc_catalogue_codes_201X::Vector{String}, - truth::String, resol::Resolution, bias_matrix::Matrix{T}; max_per = 18., niter::Int = 5, - order::Int = order, varorder::Int = 5, abstol::T = abstol, parse_eqs::Bool = true, - μ_ast::Vector = μ_ast343_DE430[1:end]) where {T <: Real} - - # Sun's ephemeris - eph_su = selecteph(sseph, su) - # Earth's ephemeris - eph_ea = selecteph(sseph, ea) - # Julian day to start propagation - jd0 = sol.bwd.t0 + PE.J2000 - # Julian day of first (last) observation - t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) - # Number of years in forward integration - nyears_fwd = (tf - jd0 + 2) / yr - # Number of years in backward integration - nyears_bwd = -(jd0 - t0 + 2) / yr - # Dynamical function - dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! - # Maximum number of steps - maxsteps = adaptative_maxsteps(radec) - # Initial conditions (T) - q00 = sol(sol.bwd.t0) - # Jet transport perturbation - dq = scaled_variables("δx", fill(1e-6, 6); order = varorder) - # Initial conditions (jet transport) - q0 = q00 .+ dq - - # Backward integration - bwd = propagate(dynamics, maxsteps, jd0, nyears_bwd, q0; μ_ast = μ_ast, order = order, - abstol = abstol, parse_eqs = parse_eqs) - - if bwd.t[end] > t0 - jd0 - return zero(NEOSolution{T, T}) - end - - # Forward integration - fwd = propagate(dynamics, maxsteps, jd0, nyears_fwd, q0; μ_ast = μ_ast, order = order, - abstol = abstol, parse_eqs = parse_eqs) - - if fwd.t[end] < tf - jd0 - return zero(NEOSolution{T, T}) - end - - # Residuals - res = residuals(radec, mpc_catalogue_codes_201X, truth, resol, bias_matrix; - xvs = et -> auday2kmsec(eph_su(et/daysec)), xve = et -> auday2kmsec(eph_ea(et/daysec)), - xva = et -> bwdfwdeph(et, bwd, fwd)) - # Orbit fit - fit = tryls(res, zeros(get_numvars()), niter) - - # NRMS (with 0 outliers) - Q_0 = nrms(res, fit) - - if Q_0 < 1 - return evalfit(NEOSolution(bwd, fwd, res, fit)) - end - - # Number of observations - N_radec = length(radec) - # Maximum allowed outliers - max_drop = ceil(Int, N_radec * max_per / 100) - # Boolean mask (0: included in fit, 1: outlier) - new_outliers = BitVector(zeros(N_radec)) - - # Drop loop - for i in 1:max_drop - # Contribution of each residual to nrms - norms = residual_norm.(res(fit.x)) - # Iterate norms from largest to smallest - idxs = sortperm(norms, rev = true) - - for j in idxs - if !new_outliers[j] - # Drop residual - new_outliers[j] = true - # Update residuals - res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) - # Update fit - fit = tryls(res, zeros(get_numvars()), niter) - break - end - end - end - - # Outliers - idxs = Vector{Int}(undef, max_drop) - # NRMS - Qs = Vector{T}(undef, max_drop + 1) - # Number of outliers - N_outliers = Vector{T}(undef, max_drop + 1) - - # Recovery loop - for i in 1:max_drop - # NRMS of current fit - Qs[i] = nrms(res, fit) - # Number of outliers in current fit - N_outliers[i] = float(max_drop - i + 1) - # Contribution of each residual to nrms - norms = residual_norm.(res(fit.x)) - # Minimum norm among outliers - j = findmin(norms[new_outliers])[2] - # Find residual with minimum norm - j = findall(new_outliers)[j] - # Add j-th residual to outliers list - idxs[i] = j - # Recover residual - new_outliers[j] = false - # Update residuals - res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) - # Update fit - fit = tryls(res, zeros(get_numvars()), niter) - end - # Add 0 outliers fit - Qs[end] = Q_0 - N_outliers[end] = zero(T) - - # Outlier rejection cannot reduce Q - if all(Qs .> 1.) - # Reset boolean mask - new_outliers[1:end] .= false - # Update residuals - res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) - # Update fit - fit = tryls(res, zeros(get_numvars()), niter) - - return evalfit(NEOSolution(bwd, fwd, res, fit)) - end - - if max_drop > 1 - # Assemble points - points = Matrix{T}(undef, 2, max_drop + 1) - for i in eachindex(Qs) - points[1, i] = Qs[i] - points[2, i] = N_outliers[i] - end - # K-means clustering - cluster = kmeans(points, 2) - # Index of smallest cluster - i_0 = cluster.assignments[1] - # Find last fit of smallest cluster - i = findfirst(x -> x != i_0, cluster.assignments) - 1 - # Update outliers indexes - idxs = idxs[i:end] - end - - # Reset boolean mask - new_outliers[1:end] .= false - # Outliers - new_outliers[idxs] .= true - # Update residuals - res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) - # Update fit - fit = tryls(res, zeros(get_numvars()), niter) - - return evalfit(NEOSolution(bwd, fwd, res, fit)) -end - -function nrms(sol::NEOSolution{T, T}) where {T <: Real} - if iszero(sol) - return T(Inf) - else - return nrms(sol.res) - end +include("b_plane.jl") +include("least_squares.jl") + +@doc raw""" + NEOSolution{T <: Real, U <: Number} + +The outcome of the orbit determination process for a NEO. + +# Fields + +- `bwd/fwd::TaylorInterpolant{T, U, 2}`: backward (forward) integration. +- `t_bwd/t_fwd::Vector{U}`: time of Earth close approach. +- `x_bwd/x_fwd::Vector{U}`: state vector at Earth close approach. +- `g_bwd/g_fwd::Vector{U}`: geocentric distance at close approach. +- `res::Vector{OpticalResidual{T, U}}`: vector of optical residuals. +- `fit::OrbitFit{T}`: least squares fit. +""" +@auto_hash_equals struct NEOSolution{T <: Real, U <: Number} + bwd::TaylorInterpolant{T, U, 2} + t_bwd::Vector{U} + x_bwd::Vector{U} + g_bwd::Vector{U} + fwd::TaylorInterpolant{T, U, 2} + t_fwd::Vector{U} + x_fwd::Vector{U} + g_fwd::Vector{U} + res::Vector{OpticalResidual{T, U}} + fit::OrbitFit{T} + # Inner constructor + function NEOSolution{T, U}(bwd::TaylorInterpolant{T, U, 2}, t_bwd::Vector{U}, x_bwd::Vector{U}, g_bwd::Vector{U}, + fwd::TaylorInterpolant{T, U, 2}, t_fwd::Vector{U}, x_fwd::Vector{U}, g_fwd::Vector{U}, + res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}) where {T <: Real, U <: Number} + @assert bwd.t0 == fwd.t0 "Backward and forward propagation initial times must match" + new{T, U}(bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, res, fit) + end +end +# Outer constructors +function NEOSolution(bwd::TaylorInterpolant{T, U, 2}, t_bwd::Vector{U}, x_bwd::Vector{U}, g_bwd::Vector{U}, + fwd::TaylorInterpolant{T, U, 2}, t_fwd::Vector{U}, x_fwd::Vector{U}, g_fwd::Vector{U}, + res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}) where {T <: Real, U <: Number} + NEOSolution{T, U}(bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, res, fit) +end + +function NEOSolution(bwd::TaylorInterpolant{T, U, 2}, fwd::TaylorInterpolant{T, U, 2}, + res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}) where {T <: Real, U <: Number} + # Backward roots + t_bwd = Vector{U}(undef, 0) + x_bwd = Vector{U}(undef, 0) + g_bwd = Vector{U}(undef, 0) + # Forward roots + t_fwd = Vector{U}(undef, 0) + x_fwd = Vector{U}(undef, 0) + g_fwd = Vector{U}(undef, 0) + + return NEOSolution{T, U}(bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, res, fit) +end + +# Print method for NEOSolution +# Examples: +# NEO solution with 123 residuals +function show(io::IO, x::NEOSolution{T, U}) where {T <: Real, U <: Number} + print(io, "NEO solution with ", length(x.res), " residuals") +end + +# Evaluation in time method +function (sol::NEOSolution{T, U})(t::V = sol.bwd.t0) where {T <: Real, U <: Number, V <: Number} + if t <= sol.bwd.t0 + return sol.bwd(t) + else + return sol.fwd(t) + end +end + +# Evaluation in fit δs method +function evalfit(sol::NEOSolution{T, TaylorN{T}}) where {T <: Real} + # Fit δs + δs = sol.fit.x + # Evaluate backward integration + new_bwd_x = map(x -> Taylor1(x.coeffs(δs)), sol.bwd.x); + new_bwd = TaylorInterpolant{T, T, 2}(sol.bwd.t0, sol.bwd.t, new_bwd_x) + # Evaluate backward roots + new_t_bwd = sol.t_bwd(δs) + new_x_bwd = sol.x_bwd(δs) + new_g_bwd = sol.g_bwd(δs) + # Evaluate forward integration + new_fwd_x = map(x -> Taylor1(x.coeffs(δs)), sol.fwd.x); + new_fwd = TaylorInterpolant{T, T, 2}(sol.fwd.t0, sol.fwd.t, new_fwd_x) + # Evaluate forward roots + new_t_fwd = sol.t_fwd(δs) + new_x_fwd = sol.x_fwd(δs) + new_g_fwd = sol.g_fwd(δs) + # Evaluate residuals + new_res = sol.res(δs) + + return NEOSolution{T, T}(new_bwd, new_t_bwd, new_x_bwd, new_g_bwd, + new_fwd, new_t_fwd, new_x_fwd, new_g_fwd, + new_res, sol.fit) +end + +# Definition of zero NEOSolution +function zero(::Type{NEOSolution{T, U}}) where {T <: Real, U <: Number} + bwd = TaylorInterpolant{T, U, 2}(zero(T), zeros(T, 1), Matrix{Taylor1{U}}(undef, 0, 0)) + t_bwd = Vector{U}(undef, 0) + x_bwd = Vector{U}(undef, 0) + g_bwd = Vector{U}(undef, 0) + fwd = TaylorInterpolant{T, U, 2}(zero(T), zeros(T, 1), Matrix{Taylor1{U}}(undef, 0, 0)) + t_fwd = Vector{U}(undef, 0) + x_fwd = Vector{U}(undef, 0) + g_fwd = Vector{U}(undef, 0) + res = Vector{OpticalResidual{T, U}}(undef, 0) + fit = OrbitFit{T}(false, Vector{T}(undef, 0), Matrix{T}(undef, 0, 0), :newton) + return NEOSolution{T, U}(bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, + res, fit) +end + +iszero(x::NEOSolution{T, U}) where {T <: Real, U <: Number} = x == zero(NEOSolution{T, U}) + +# Normalized Root Mean Square Error +function nrms(sol::NEOSolution{T, T}) where {T <: Real} + if iszero(sol) + return T(Inf) + else + return nrms(sol.res) + end end \ No newline at end of file diff --git a/src/propagation/asteroid_dynamical_models.jl b/src/propagation/asteroid_dynamical_models.jl old mode 100644 new mode 100755 index 89ee8718..aa0c2ac1 --- a/src/propagation/asteroid_dynamical_models.jl +++ b/src/propagation/asteroid_dynamical_models.jl @@ -1,1176 +1,1176 @@ -@doc raw""" - evaleph(eph::TaylorInterpolant, t::Taylor1, q::Taylor1{U}) where {U} - evaleph(eph::TaylorInterpolant, t::Taylor1, q::TaylorN{Taylor1{T}}) where {T<:Real} - -Evaluate planetary ephemeris with type given by `q`. -""" -function evaleph(eph::TaylorInterpolant, t::Taylor1, q::Taylor1{U}) where {U} - return map(x -> Taylor1( x.coeffs*one(q[0]) ), eph(t)) -end - -function evaleph(eph::TaylorInterpolant, t::Taylor1, q::TaylorN{Taylor1{T}}) where {T<:Real} - return one(q)*eph(t) -end - -@doc raw""" - auxzero(a::AbstractSeries) - -Return a zero of the same type as `a`. -""" -function auxzero(a::AbstractSeries) - return zero(a) -end - -@doc raw""" - auxzero(a::TaylorN{Taylor1{T}}) where {T<:Number} - -Return a `TaylorN` with zero coefficients of the same type as `a.coeffs`. -""" -function auxzero(a::TaylorN{Taylor1{T}}) where {T<:Number} - return TaylorN(zero.(a.coeffs)) -end - -# Nearth-Earth asteroid dynamical model (d=2.0) -# Bodies considered in the model are: the Sun, the eight planets, the Moon and Ceres, -# as well as the asteroid of interest as a test particle with null mass. Dynamical -# effects considered are: -# - post-Newtonian point-mass accelerations between all bodies, -# - figure-effects (oblateness) of the Earth (J2 and J3) -# - J2 effect of the Sun -# - J2 and J3 effect of the Moon -# - Kinematic model for the precession and nutation of the Earth's orientation (IAU 1976/1980 Earth orientation model) -# - Kinematic model for the Moons's orientation (Seidelmann et al., 2006) -# - Non-gravitational accelerations acting upon the asteroid -# are included (Yarkovsky effect) a_nongrav = A2*t_vec*(au/r)^d, where t_vec is the -# unit heliocentric transverse vector, au is 1 astronomical unit, r is the -# asteroid's heliocentric range, A2 is a coefficient (with units of au/day^2), -# and d = 2.0 - -@doc raw""" - RNp1BP_pN_A_J23E_J2S_ng_eph_threads!(dq, q, params, t) - -Near-Earth asteroid dynamical model (``d = 2``). Bodies considered in the model are: the Sun, -the eight planets, the Moon and Ceres, as well as the asteroid of interest as a test particle -with null mass. Dynamical effects considered are: - -- Post-Newtonian point-mass accelerations between all bodies: see equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract. - -- Figure-effects (oblateness) of the Earth (``J_2`` and ``J_3``), - -- ``J_2`` effect of the Sun and - -- ``J_2`` and ``J_3`` effect of the Moon: see equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract. - -- Kinematic model for the precession and nutation of the Earth's orientation (IAU 1976/1980 Earth orientation model): see [`PlanetaryEphemeris.c2t_jpl_de430`](@ref). - -- Kinematic model for the Moon's orientation (Seidelmann et al., 2006): see equations (14)-(15) in page 9 and equations (34)-(35) in page 16 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract. - -- Non-gravitational accelerations acting upon the asteroid: are included (Yarkovsky effect) -```math -\mathbf{a}_\text{nongrav} = A_2\left(\frac{1 \ \text{au}}{r}\right)^d*\hat{\mathbf{t}}, -``` -where ``\hat{\mathbf{t}}`` is the unit heliocentric transverse vector, ``r`` is the -asteroid's heliocentric range, ``A_2`` is a coefficient (with units of au/day^2), -and ``d = 2``. - -To improve performance, some internal loops are multi-threaded via `Threads.threads for` - -See also [`PlanetaryEphemeris.NBP_pN_A_J23E_J23M_J2S!`](@ref). -""" RNp1BP_pN_A_J23E_J2S_ng_eph_threads! - -function RNp1BP_pN_A_J23E_J2S_ng_eph_threads!(dq, q, params, t) - # Julian date of start time - local jd0 = params[4] - # Days since J2000.0 = 2.451545e6 - local dsj2k = t + (jd0 - JD_J2000) - # Solar system ephemeris at dsj2k - local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) - # Accelerations at dsj2k - local acceph_t = evaleph(params[2], dsj2k, q[1]) - # Newtonian potentials at dsj2k - local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) - # Type of position / velocity components - local S = eltype(q) - # Interaction matrix with flattened bodies - local UJ_interaction = params[5] - # Number of bodies, including NEA - local N = params[6] - # Number of bodies, except the asteroid - local Nm1 = N-1 - # Vector of mass parameters GM's - local μ = params[7] - - # zero(q[1]) - local zero_q_1 = auxzero(q[1]) - - #= - Point-mass accelerations - See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - - # Position of the i-th body - position of the asteroid - X = Array{S}(undef, N) # X-axis component - Y = Array{S}(undef, N) # Y-axis component - Z = Array{S}(undef, N) # Z-axis component - - # Distance between the i-th body and the asteroid - r_p2 = Array{S}(undef, N) # r_{i,asteroid}^2 - r_p1d2 = Array{S}(undef, N) # sqrt(r_p2) <-> r_{i, asteroid} - r_p3d2 = Array{S}(undef, N) # r_p2^1.5 <-> r_{i, asteroid}^3 - r_p7d2 = Array{S}(undef, N) # r_p2^3.5 <-> r_{i, asteroid}^7 - - # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 - newtonianCoeff = Array{S}(undef, N) - - # Velocity of the i-th body - ui = Array{S}(undef, N-1) # X-axis component - vi = Array{S}(undef, N-1) # Y-axis component - wi = Array{S}(undef, N-1) # Z-axis component - - # Post-Newtonian stuff - - # Velocity of the i-th body - velocity of the asteroid - U = Array{S}(undef, N) # X-axis component - V = Array{S}(undef, N) # Y-axis component - W = Array{S}(undef, N) # Z-axis component - - # 4 * Velocity of the asteroid - 3 * velocity of the i-th body - _4U_m_3X = Array{S}(undef, N) # X-axis component - _4V_m_3Y = Array{S}(undef, N) # Y-axis component - _4W_m_3Z = Array{S}(undef, N) # Z-axis component - - # v_{i,j}v_{asteroid,j} j = x, y, z - UU = Array{S}(undef, N) # v_{i,x}v_{asteroid,x} - VV = Array{S}(undef, N) # v_{i,y}v_{asteroid,y} - WW = Array{S}(undef, N) # v_{i,z}v_{asteroid,z} - - # Newtonian potential of 1 body \mu_i / r_{i, asteroid} - newtonian1b_Potential = Array{S}(undef, N) - # Newtonian potential of N bodies - # \sum_{i\neq l} \frac{\mu_i}{r_{il}} or - # \sum_{j\neq k} \frac{\mu_j}{r_{jk}} - newtonianNb_Potential = Array{S}(undef, N) - - # Newtonian coefficient * difference between two positions, i.e., - # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 - newton_acc_X = Array{S}(undef, N) # X-axis component - newton_acc_Y = Array{S}(undef, N) # Y-axis component - newton_acc_Z = Array{S}(undef, N) # Z-axis component - - # Combinations of velocities - v2 = Array{S}(undef, N) # Velocity magnitude squared ||\mathbf{v}_i||^2 - vi_dot_vj = Array{S}(undef, N) # - - # Second term without (\mathbf{v}_i - \mathbf{v}_j) - pn2 = Array{S}(undef, N) - # Full second term - U_t_pn2 = Array{S}(undef, N) # X-axis component - V_t_pn2 = Array{S}(undef, N) # Y-axis component - W_t_pn2 = Array{S}(undef, N) # Z-axis component - - # Third term without newtonian accelerations \mathbf{a}_i - pn3 = Array{S}(undef, N) - # Full third term of equation (35) - pNX_t_pn3 = Array{S}(undef, N) # X-axis component - pNY_t_pn3 = Array{S}(undef, N) # Y-axis component - pNZ_t_pn3 = Array{S}(undef, N) # Z-axis component - - # First term - _4ϕj = Array{S}(undef, N) # 4*\sum term inside {} - ϕi_plus_4ϕj = Array{S}(undef, N) # 4*\sum + \sum terms inside {} - sj2_plus_2si2_minus_4vivj = Array{S}(undef, N) # \dot{s}_j^2 + 2\dot{s}_i^2 - 4 <, > terms inside {} - ϕs_and_vs = Array{S}(undef, N) # -4\sum - \sum + \dot{s}_j^2 + 2\dot{s}_i^2 - 4<, > terms inside {} - pn1t1_7 = Array{S}(undef, N) # Everything inside the {} in the first term except for the term with accelerations (last) - # Last term inside the {} - pNX_t_X = Array{S}(undef, N) # X-axis component - pNY_t_Y = Array{S}(undef, N) # Y-axis component - pNZ_t_Z = Array{S}(undef, N) # Z-axis component - # Everything inside the {} in the first term - pn1 = Array{S}(undef, N) - # Full first term - X_t_pn1 = Array{S}(undef, N) # X-axis component - Y_t_pn1 = Array{S}(undef, N) # Y-axis component - Z_t_pn1 = Array{S}(undef, N) # Z-axis component - - # Temporary post-Newtonian accelerations - pntempX = zero_q_1 # X-axis component - pntempY = zero_q_1 # Y-axis component - pntempZ = zero_q_1 # Z-axis component - - #= - Extended body accelerations - See equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract - and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - - # J_2 acceleration auxiliaries - - # Auxiliaries to compute body-fixed frame coordinates - t31 = Array{S}(undef, N) - t32 = Array{S}(undef, N) - t33 = Array{S}(undef, N) - # z-coordinate in body-fixed frame - r_sin_ϕ = Array{S}(undef, N) - - # Trigonometric functions of latitude ϕ and longitude λ in the body-fixed coordinate system - # See equations (165)-(168) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - sin_ϕ = Array{S}(undef, N) # sin(latitude ϕ) - ϕ = Array{S}(undef, N) # Latitude ϕ - cos_ϕ = Array{S}(undef, N) # cos(latitude ϕ) - sin2_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^2 - sin3_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^3 - sin4_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^4 - - # Acceleration due to zonal harmonics in inertial frame - F_J2_x = Array{S}(undef, N) - F_J2_y = Array{S}(undef, N) - F_J2_z = Array{S}(undef, N) - # Auxiliaries to compute F_J2_i, i = x, y, z - F_J2_x1 = Array{S}(undef, N) - F_J2_y1 = Array{S}(undef, N) - F_J2_z1 = Array{S}(undef, N) - F_J2_x2 = Array{S}(undef, N) - F_J2_y2 = Array{S}(undef, N) - F_J2_z2 = Array{S}(undef, N) - - # Temporary arrays for the sum of full extended body accelerations - temp_accX_i = Array{S}(undef, N) - temp_accY_i = Array{S}(undef, N) - temp_accZ_i = Array{S}(undef, N) - - # Legendre polynomials - # See equations (176) and (177) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - P_2_sin_ϕ = Array{S}(undef, N) # Second Legendre polynomial P_2(sin ϕ) - ∂P_2_sin_ϕ = Array{S}(undef, N) # dP_2(sin ϕ)/d(sin ϕ) - P_3_sin_ϕ = Array{S}(undef, N) # Third Legendre polynomial P_3(sin ϕ) - ∂P_3_sin_ϕ = Array{S}(undef, N) # dP_3(sin ϕ)/d(sin ϕ) - # -cos ϕ P_n' - m_c_ϕ_∂P_2 = Array{S}(undef, N) # -cos ϕ P_2' - m_c_ϕ_∂P_3 = Array{S}(undef, N) # -cos ϕ P_3' - - # -J_n * R^n / r^m - # J_n: n-th zonal harmonic coefficient - # R: radius of the body - # r: distance between the body and the asteroid - Λ2j_div_r4 = Array{S}(undef, N) # J_2 * R^2 / r^4 - Λ3j_div_r5 = Array{S}(undef, N) # J_3 * R^3 / r^5 - - # Accelerations due to zonal harmonics in body frame - - # Acceleration due to zonal harmonics J_n, n = 2, 3 - F_J_ξ = Array{S}(undef, N) # ξ-axis component - F_J_η = Array{S}(undef, N) # η-axis component - F_J_ζ = Array{S}(undef, N) # ζ-axis component - # Acceleration due to second zonal harmonic J_2 - F_J2_ξ = Array{S}(undef, N) # ξ-axis component - F_J2_η = Array{S}(undef, N) # η-axis component - F_J2_ζ = Array{S}(undef, N) # ζ-axis component - # Acceleration due to third zonal harmonic J_3 - F_J3_ξ = Array{S}(undef, N) # ξ-axis component - F_J3_η = Array{S}(undef, N) # η-axis component - F_J3_ζ = Array{S}(undef, N) # ζ-axis component - - # Unit vectors (ξ, η, ζ) in inertial frame - - # ξ vector - ξx = Array{S}(undef, N) - ξy = Array{S}(undef, N) - ξz = Array{S}(undef, N) - # η vector - ηx = Array{S}(undef, N) - ηy = Array{S}(undef, N) - ηz = Array{S}(undef, N) - # Auxiliaries to compute η vector - ηx1 = Array{S}(undef, N) - ηy1 = Array{S}(undef, N) - ηz1 = Array{S}(undef, N) - ηx2 = Array{S}(undef, N) - ηy2 = Array{S}(undef, N) - ηz2 = Array{S}(undef, N) - # ζ vector - ζx = Array{S}(undef, N) - ζy = Array{S}(undef, N) - ζz = Array{S}(undef, N) - # Auxiliaries to compute ζ vector - ζx1 = Array{S}(undef, N) - ζy1 = Array{S}(undef, N) - ζz1 = Array{S}(undef, N) - ζx2 = Array{S}(undef, N) - ζy2 = Array{S}(undef, N) - ζz2 = Array{S}(undef, N) - - # Full extended-body accelerations - accX = zero_q_1 - accY = zero_q_1 - accZ = zero_q_1 - - # Rotations to and from Earth, Sun and Moon pole-oriented frames - local M_ = Array{S}(undef, 3, 3, N) - local M_ .= zero_q_1 - local M_[:, :, ea] .= t2c_jpl_de430(dsj2k)[:, :] .+ zero_q_1 - - # Fill first 3 elements of dq with velocities - dq[1] = q[4] - dq[2] = q[5] - dq[3] = q[6] - - # Newtonian potential of N bodies - newtonianNb_Potential[N] = zero_q_1 - - #= - Compute point-mass Newtonian accelerations, all bodies - See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - Threads.@threads for i in 1:Nm1 - # Velocity of the i-th body - ui[i] = ss16asteph_t[3(N-1+i)-2] # X-axis component - vi[i] = ss16asteph_t[3(N-1+i)-1] # Y-axis component - wi[i] = ss16asteph_t[3(N-1+i) ] # Z-axis component - - # Position of the i-th body - position of the asteroid - X[i] = ss16asteph_t[3i-2]-q[1] # X-axis component - Y[i] = ss16asteph_t[3i-1]-q[2] # Y-axis component - Z[i] = ss16asteph_t[3i ]-q[3] # Z-axis component - - # Velocity of the i-th body - velocity of the asteroid - U[i] = ui[i]-dq[1] # X-axis component - V[i] = vi[i]-dq[2] # Y-axis component - W[i] = wi[i]-dq[3] # Z-axis component - - # 4 * Velocity of the asteroid - 3 * velocity of the i-th body - _4U_m_3X[i] = (4dq[1]) - (3ui[i]) # X-axis component - _4V_m_3Y[i] = (4dq[2]) - (3vi[i]) # Y-axis component - _4W_m_3Z[i] = (4dq[3]) - (3wi[i]) # Z-axis component - - # Dot product inside the [] in the second term - pn2x = X[i]*_4U_m_3X[i] - pn2y = Y[i]*_4V_m_3Y[i] - pn2z = Z[i]*_4W_m_3Z[i] - - # v_{ij}v_{asteroid} j = x, y, z - UU[i] = ui[i]*dq[1] - VV[i] = vi[i]*dq[2] - WW[i] = wi[i]*dq[3] - - # - vi_dot_vj[i] = ( UU[i]+VV[i] ) + WW[i] - - # Distance between the i-th body and the asteroid - r_p2[i] = ( (X[i]^2)+(Y[i]^2) ) + (Z[i]^2) # r_{i,asteroid}^2 - r_p1d2[i] = sqrt(r_p2[i]) # sqrt(r_p2) <-> r_{i,asteroid} - r_p3d2[i] = r_p2[i]^1.5 # r_p2^1.5 <-> r_{i, asteroid}^3 - r_p7d2[i] = r_p2[i]^3.5 # r_p2^3.5 <-> r_{i, asteroid}^7 - - # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 - newtonianCoeff[i] = μ[i]/r_p3d2[i] - - # Second term without (\mathbf{v}_i - \mathbf{v}_asteroid) - pn2[i] = newtonianCoeff[i]*(( pn2x+pn2y ) + pn2z) - - # Newtonian coefficient * difference between two positions, i.e., - # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 - newton_acc_X[i] = X[i]*newtonianCoeff[i] - newton_acc_Y[i] = Y[i]*newtonianCoeff[i] - newton_acc_Z[i] = Z[i]*newtonianCoeff[i] - - # Newtonian potential of 1 body \mu_i / r_{i, asteroid} - newtonian1b_Potential[i] = μ[i]/r_p1d2[i] - # Third term without newtonian accelerations \mathbf{a}_i - pn3[i] = 3.5newtonian1b_Potential[i] - # Full second term - U_t_pn2[i] = pn2[i]*U[i] # X-axis component - V_t_pn2[i] = pn2[i]*V[i] # Y-axis component - W_t_pn2[i] = pn2[i]*W[i] # Z-axis component - - #= - Extended body accelerations - See equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract - and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - - # J_2 accelerations, if i-th body is flattened - if UJ_interaction[i] - # Rotate from inertial frame to extended-body frame - # Here we are rotating only the Z-coordinate - t31[i] = -X[i]*M_[1,3,i] - t32[i] = -Y[i]*M_[2,3,i] - t33[i] = -Z[i]*M_[3,3,i] - r_sin_ϕ[i] = (t31[i]+t32[i])+t33[i] # z-coordinate in body-fixed frame - - # Trigonometric functions of latitude ϕ and longitude λ in the body-fixed coordinate system - # See equations (165)-(168) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - - sin_ϕ[i] = r_sin_ϕ[i]/r_p1d2[i] # sin(latitude ϕ) - ϕ[i] = asin(sin_ϕ[i]) # Latitude ϕ - cos_ϕ[i] = cos(ϕ[i]) # cos(latitude ϕ) - sin2_ϕ[i] = sin_ϕ[i]^2 # sin(latitude ϕ)^2 - sin3_ϕ[i] = sin_ϕ[i]^3 # sin(latitude ϕ)^3 - - # Legendre polynomials - - # See equations (176) and (177) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - P_2_sin_ϕ[i] = 1.5sin2_ϕ[i] - 0.5 # Second Legendre polynomial P_2(sin ϕ) - ∂P_2_sin_ϕ[i] = 3sin_ϕ[i] # dP_2(sin ϕ)/d(sin ϕ) - P_3_sin_ϕ[i] = (-1.5sin_ϕ[i]) + (2.5sin3_ϕ[i]) # Third Legendre polynomial P_3(sin ϕ) - ∂P_3_sin_ϕ[i] = -1.5 + 7.5sin2_ϕ[i] # dP_3(sin ϕ)/d(sin ϕ) - - # Compute cartesian coordinates of acceleration due to body figure in body frame - - # -J_n * R^n / r^m - # J_n: n-th zonal harmonic coefficient - # R: radius of the body - # r: distance between the body and the asteroid - Λ2j_div_r4[i] = -(Λ2[i]/(r_p2[i]^2)) # J_2 * R^2 / r^4 - Λ3j_div_r5[i] = -(Λ3[i]/(r_p1d2[i]^5)) # J_3 * R^3 / r^5 - - # -cos ϕ P_n' - m_c_ϕ_∂P_2[i] = (-cos_ϕ[i])*∂P_2_sin_ϕ[i] # -cos ϕ P_2' - m_c_ϕ_∂P_3[i] = (-cos_ϕ[i])*∂P_3_sin_ϕ[i] # -cos ϕ P_3' - - # Acceleration due to second zonal harmonic J_2 in body frame - F_J2_ξ[i] = ( Λ2j_div_r4[i]*(3P_2_sin_ϕ[i]) ) # ξ-axis component - # F_J2_η[i] = zero_q_1 # η-axis component - F_J2_ζ[i] = Λ2j_div_r4[i]*m_c_ϕ_∂P_2[i] # ζ-axis component - - # Acceleration due to third zonal harmonic J_3 in body frame - F_J3_ξ[i] = ( Λ3j_div_r5[i]*(4P_3_sin_ϕ[i]) ) # ξ-axis component - #F_J3_η[i] = zero_q_1 # η-axis component - F_J3_ζ[i] = Λ3j_div_r5[i]*m_c_ϕ_∂P_3[i] # ζ-axis component - - # Compute accelerations due to zonal harmonics J_n, n = 2, 3 in body frame - F_J_ξ[i] = F_J2_ξ[i] # + F_J3_ξ[i] # ξ-axis component - # F_J_η[i] = zero_q_1 # η-axis component - F_J_ζ[i] = F_J2_ζ[i] # + F_J3_ζ[i] # ζ-axis component - - # Compute unit vectors (ξ, η, ζ) in inertial frame - - # ξ components in inertial frame - ξx[i] = -X[i]/r_p1d2[i] - ξy[i] = -Y[i]/r_p1d2[i] - ξz[i] = -Z[i]/r_p1d2[i] - - # Compute η = p x ξ - # Auxiliaries - ηx1[i] = M_[2,3,i]*ξz[i] - ηy1[i] = M_[3,3,i]*ξx[i] - ηz1[i] = M_[1,3,i]*ξy[i] - ηx2[i] = M_[3,3,i]*ξy[i] - ηy2[i] = M_[1,3,i]*ξz[i] - ηz2[i] = M_[2,3,i]*ξx[i] - # η components in inertial frame - ηx[i] = ηx1[i] - ηx2[i] - ηy[i] = ηy1[i] - ηy2[i] - ηz[i] = ηz1[i] - ηz2[i] - - # Compute ζ = ξ x η - ζx1[i] = ξy[i]*ηz[i] - ζy1[i] = ξz[i]*ηx[i] - ζz1[i] = ξx[i]*ηy[i] - ζx2[i] = ξz[i]*ηy[i] - ζy2[i] = ξx[i]*ηz[i] - ζz2[i] = ξy[i]*ηx[i] - # ζ components in inertial frame - ζx[i] = ζx1[i] - ζx2[i] - ζy[i] = ζy1[i] - ζy2[i] - ζz[i] = ζz1[i] - ζz2[i] - - # Compute cartesian coordinates of acceleration due to body figure in inertial frame - # Auxiliaries - F_J2_x1[i] = F_J_ξ[i]*ξx[i] - F_J2_y1[i] = F_J_ξ[i]*ξy[i] - F_J2_z1[i] = F_J_ξ[i]*ξz[i] - F_J2_x2[i] = F_J_ζ[i]*ζx[i] - F_J2_y2[i] = F_J_ζ[i]*ζy[i] - F_J2_z2[i] = F_J_ζ[i]*ζz[i] - # Acceleration due to zonal harmonics in inertial frame - F_J2_x[i] = F_J2_x1[i] + F_J2_x2[i] - F_J2_y[i] = F_J2_y1[i] + F_J2_y2[i] - F_J2_z[i] = F_J2_z1[i] + F_J2_z2[i] - end - # Velocity magnitude of the i-th body - v2[i] = ( (ui[i]^2)+(vi[i]^2) ) + (wi[i]^2) - end - # Asteroid velocity magnitude - v2[N] = ( (q[4]^2)+(q[5]^2) ) + (q[6]^2) - - for i in 1:Nm1 - # Newtonian potential of N bodies - # \sum_{i\neq l} \frac{\mu_i}{r_{il}} or - # \sum_{j\neq k} \frac{\mu_j}{r_{jk}} - temp_004 = newtonian1b_Potential[i] + newtonianNb_Potential[N] - newtonianNb_Potential[N] = temp_004 - - # Extended body accelerations - # J_n accelerations, if i-th body is flattened - if UJ_interaction[i] - # Reaction force on i-th body - temp_accX_i[i] = accX - (μ[i]*F_J2_x[i]) - accX = temp_accX_i[i] - temp_accY_i[i] = accY - (μ[i]*F_J2_y[i]) - accY = temp_accY_i[i] - temp_accZ_i[i] = accZ - (μ[i]*F_J2_z[i]) - accZ = temp_accZ_i[i] - end - end - - #= - Post-Newtonian accelerations due to Sun, Moon and planets (Mercury through Neptune) - Post-Newtonian iterative procedure setup and initialization - See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - - # First term - - # 4*\sum term inside {} - _4ϕj[N] = 4newtonianNb_Potential[N] - Threads.@threads for i in 1:10 - # 4*\sum + \sum terms inside {} - ϕi_plus_4ϕj[i] = newtonianNb_Potential_t[i] + _4ϕj[N] - # \dot{s}_j^2 + 2\dot{s}_i^2 - 4 <, > terms inside {} - sj2_plus_2si2_minus_4vivj[i] = ( (2v2[i]) - (4vi_dot_vj[i]) ) + v2[N] - # -4\sum - \sum + \dot{s}_j^2 + 2\dot{s}_i^2 - 4<, > terms inside {} - ϕs_and_vs[i] = sj2_plus_2si2_minus_4vivj[i] - ϕi_plus_4ϕj[i] - # (\mathbf{r}_i - \mathbf{r}_asteroid)\cdot\mathbf{v_i} - Xij_t_Ui = X[i]*ui[i] - Yij_t_Vi = Y[i]*vi[i] - Zij_t_Wi = Z[i]*wi[i] - Rij_dot_Vi = ( Xij_t_Ui+Yij_t_Vi ) + Zij_t_Wi - # The expression below inside the (...)^2 should have a minus sign in front of the - # numerator, but upon squaring it is eliminated, so at the end of the day, it is - # irrelevant ;) - # (\mathbf{r}_i - \mathbf{r}_asteroid)\cdot\mathbf{v_i} / r_{i, asteroid} - pn1t7 = (Rij_dot_Vi^2)/r_p2[i] - # Everything inside the {} except for the first and last terms - pn1t2_7 = ϕs_and_vs[i] - (1.5pn1t7) - # Everything inside the {} except for the last term - pn1t1_7[i] = c_p2 + pn1t2_7 - - # Last term inside the {} - pNX_t_X[i] = acceph_t[3i-2]*X[i] # X-axis component - pNY_t_Y[i] = acceph_t[3i-1]*Y[i] # Y-axis component - pNZ_t_Z[i] = acceph_t[3i ]*Z[i] # Z-axis component - - # Everything inside the {} in the first term - pn1[i] = ( pn1t1_7[i] + (0.5*( (pNX_t_X[i]+pNY_t_Y[i]) + pNZ_t_Z[i] )) ) - - # Full first term - X_t_pn1[i] = newton_acc_X[i]*pn1[i] # X-axis component - Y_t_pn1[i] = newton_acc_Y[i]*pn1[i] # Y-axis component - Z_t_pn1[i] = newton_acc_Z[i]*pn1[i] # Z-axis component - - # Full third term - pNX_t_pn3[i] = acceph_t[3i-2]*pn3[i] # X-axis component - pNY_t_pn3[i] = acceph_t[3i-1]*pn3[i] # Y-axis component - pNZ_t_pn3[i] = acceph_t[3i ]*pn3[i] # Z-axis component - end - # Temporary post-Newtonian accelerations (planets) - for i in 1:10 - termpnx = ( X_t_pn1[i] + (U_t_pn2[i]+pNX_t_pn3[i]) ) # X-axis component - sumpnx = pntempX + termpnx - pntempX = sumpnx - termpny = ( Y_t_pn1[i] + (V_t_pn2[i]+pNY_t_pn3[i]) ) # Y-axis component - sumpny = pntempY + termpny - pntempY = sumpny - termpnz = ( Z_t_pn1[i] + (W_t_pn2[i]+pNZ_t_pn3[i]) ) # Z-axis component - sumpnz = pntempZ + termpnz - pntempZ = sumpnz - end - # Compute Newtonian accelerations due to Pluto and 16 asteroid perturbers - Threads.@threads for i in 11:Nm1 - # Full first term - X_t_pn1[i] = c_p2*newton_acc_X[i] - Y_t_pn1[i] = c_p2*newton_acc_Y[i] - Z_t_pn1[i] = c_p2*newton_acc_Z[i] - end - # Temporary post-Newtonian accelerations (Pluto + 16 asteroid perturbers) - for i in 11:Nm1 - termpnx = X_t_pn1[i] # X-axis component - sumpnx = pntempX + termpnx - pntempX = sumpnx - termpny = Y_t_pn1[i] # Y-axis component - sumpny = pntempY + termpny - pntempY = sumpny - termpnz = Z_t_pn1[i] # Z-axis component - sumpnz = pntempZ + termpnz - pntempZ = sumpnz - end - # Post-Newtonian acelerations - postNewtonX = pntempX*c_m2 # X-axis component - postNewtonY = pntempY*c_m2 # Y-axis component - postNewtonZ = pntempZ*c_m2 # Z-axis component - - #= - Compute non-gravitational acceleration - =# - - # Angular momentum per unit mass - hx = (Y[1]*W[1])-(Z[1]*V[1]) # X-axis component - hy = (Z[1]*U[1])-(X[1]*W[1]) # Y-axis component - hz = (X[1]*V[1])-(Y[1]*U[1]) # Z-axis component - - # Cartesian components of transversal vector t = h × (\mathbf{r}_Sun - \mathbf{r}_asteroid) - t_x = (hz*Y[1]) - (hy*Z[1]) # Note: Y[1] = y_Sun - y_asteroid, etc. - t_y = (hx*Z[1]) - (hz*X[1]) - t_z = (hy*X[1]) - (hx*Y[1]) - # Norm of transversal vector - t_norm = sqrt( ((t_x^2)+(t_y^2))+(t_z^2) ) - # Cartesian components of transversal unit vector - t_x_unit = t_x/t_norm - t_y_unit = t_y/t_norm - t_z_unit = t_z/t_norm - - # Cartesian components of radial unit vector - r_x_unit = -(X[1]/r_p1d2[1]) - r_y_unit = -(Y[1]/r_p1d2[1]) - r_z_unit = -(Z[1]/r_p1d2[1]) - - # Evaluate non-grav acceleration (solar radiation pressure, Yarkovsky) - g_r = r_p2[1] # Distance Sun-asteroid - A2_t_g_r = q[7]/g_r # Yarkovsky effect - A1_t_g_r = q[8]/g_r # Radiation pressure - - # Non gravitational acceleration: Yarkovsky + radiation pressure - NGAx = (A2_t_g_r*t_x_unit) + (A1_t_g_r*r_x_unit) - NGAy = (A2_t_g_r*t_y_unit) + (A1_t_g_r*r_y_unit) - NGAz = (A2_t_g_r*t_z_unit) + (A1_t_g_r*r_z_unit) - - # Fill dq[4:6] with accelerations - # Post-Newton point mass + Extended body + Non-gravitational - dq[4] = ( postNewtonX + accX ) + NGAx - dq[5] = ( postNewtonY + accY ) + NGAy - dq[6] = ( postNewtonZ + accZ ) + NGAz - # Yarkovsky coefficient does not change in time - dq[7] = zero_q_1 - - nothing -end - -function RNp1BP_pN_A_J23E_J2S_eph_threads!(dq, q, params, t) - # Julian date of start time - local jd0 = params[4] - # Days since J2000.0 = 2.451545e6 - local dsj2k = t + (jd0 - JD_J2000) - # Solar system ephemeris at dsj2k - local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) - # Accelerations at dsj2k - local acceph_t = evaleph(params[2], dsj2k, q[1]) - # Newtonian potentials at dsj2k - local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) - # Type of position / velocity components - local S = eltype(q) - # Interaction matrix with flattened bodies - local UJ_interaction = params[5] - # Number of bodies, including NEA - local N = params[6] - # Number of bodies, except the asteroid - local Nm1 = N-1 - # Vector of mass parameters GM's - local μ = params[7] - - # zero(q[1]) - local zero_q_1 = auxzero(q[1]) - - #= - Point-mass accelerations - See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - - # Position of the i-th body - position of the asteroid - X = Array{S}(undef, N) # X-axis component - Y = Array{S}(undef, N) # Y-axis component - Z = Array{S}(undef, N) # Z-axis component - - # Distance between the i-th body and the asteroid - r_p2 = Array{S}(undef, N) # r_{i,asteroid}^2 - r_p1d2 = Array{S}(undef, N) # sqrt(r_p2) <-> r_{i, asteroid} - r_p3d2 = Array{S}(undef, N) # r_p2^1.5 <-> r_{i, asteroid}^3 - r_p7d2 = Array{S}(undef, N) # r_p2^3.5 <-> r_{i, asteroid}^7 - - # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 - newtonianCoeff = Array{S}(undef, N) - - # Velocity of the i-th body - ui = Array{S}(undef, N-1) # X-axis component - vi = Array{S}(undef, N-1) # Y-axis component - wi = Array{S}(undef, N-1) # Z-axis component - - # Post-Newtonian stuff - - # Velocity of the i-th body - velocity of the asteroid - U = Array{S}(undef, N) # X-axis component - V = Array{S}(undef, N) # Y-axis component - W = Array{S}(undef, N) # Z-axis component - - # 4 * Velocity of the asteroid - 3 * velocity of the i-th body - _4U_m_3X = Array{S}(undef, N) # X-axis component - _4V_m_3Y = Array{S}(undef, N) # Y-axis component - _4W_m_3Z = Array{S}(undef, N) # Z-axis component - - # v_{i,j}v_{asteroid,j} j = x, y, z - UU = Array{S}(undef, N) # v_{i,x}v_{asteroid,x} - VV = Array{S}(undef, N) # v_{i,y}v_{asteroid,y} - WW = Array{S}(undef, N) # v_{i,z}v_{asteroid,z} - - # Newtonian potential of 1 body \mu_i / r_{i, asteroid} - newtonian1b_Potential = Array{S}(undef, N) - # Newtonian potential of N bodies - # \sum_{i\neq l} \frac{\mu_i}{r_{il}} or - # \sum_{j\neq k} \frac{\mu_j}{r_{jk}} - newtonianNb_Potential = Array{S}(undef, N) - - # Newtonian coefficient * difference between two positions, i.e., - # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 - newton_acc_X = Array{S}(undef, N) # X-axis component - newton_acc_Y = Array{S}(undef, N) # Y-axis component - newton_acc_Z = Array{S}(undef, N) # Z-axis component - - # Combinations of velocities - v2 = Array{S}(undef, N) # Velocity magnitude squared ||\mathbf{v}_i||^2 - vi_dot_vj = Array{S}(undef, N) # - - # Second term without (\mathbf{v}_i - \mathbf{v}_j) - pn2 = Array{S}(undef, N) - # Full second term - U_t_pn2 = Array{S}(undef, N) # X-axis component - V_t_pn2 = Array{S}(undef, N) # Y-axis component - W_t_pn2 = Array{S}(undef, N) # Z-axis component - - # Third term without newtonian accelerations \mathbf{a}_i - pn3 = Array{S}(undef, N) - # Full third term of equation (35) - pNX_t_pn3 = Array{S}(undef, N) # X-axis component - pNY_t_pn3 = Array{S}(undef, N) # Y-axis component - pNZ_t_pn3 = Array{S}(undef, N) # Z-axis component - - # First term - _4ϕj = Array{S}(undef, N) # 4*\sum term inside {} - ϕi_plus_4ϕj = Array{S}(undef, N) # 4*\sum + \sum terms inside {} - sj2_plus_2si2_minus_4vivj = Array{S}(undef, N) # \dot{s}_j^2 + 2\dot{s}_i^2 - 4 <, > terms inside {} - ϕs_and_vs = Array{S}(undef, N) # -4\sum - \sum + \dot{s}_j^2 + 2\dot{s}_i^2 - 4<, > terms inside {} - pn1t1_7 = Array{S}(undef, N) # Everything inside the {} in the first term except for the term with accelerations (last) - # Last term inside the {} - pNX_t_X = Array{S}(undef, N) # X-axis component - pNY_t_Y = Array{S}(undef, N) # Y-axis component - pNZ_t_Z = Array{S}(undef, N) # Z-axis component - # Everything inside the {} in the first term - pn1 = Array{S}(undef, N) - # Full first term - X_t_pn1 = Array{S}(undef, N) # X-axis component - Y_t_pn1 = Array{S}(undef, N) # Y-axis component - Z_t_pn1 = Array{S}(undef, N) # Z-axis component - - # Temporary post-Newtonian accelerations - pntempX = zero_q_1 # X-axis component - pntempY = zero_q_1 # Y-axis component - pntempZ = zero_q_1 # Z-axis component - - #= - Extended body accelerations - See equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract - and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - - # J_2 acceleration auxiliaries - - # Auxiliaries to compute body-fixed frame coordinates - t31 = Array{S}(undef, N) - t32 = Array{S}(undef, N) - t33 = Array{S}(undef, N) - # z-coordinate in body-fixed frame - r_sin_ϕ = Array{S}(undef, N) - - # Trigonometric functions of latitude ϕ and longitude λ in the body-fixed coordinate system - # See equations (165)-(168) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - sin_ϕ = Array{S}(undef, N) # sin(latitude ϕ) - ϕ = Array{S}(undef, N) # Latitude ϕ - cos_ϕ = Array{S}(undef, N) # cos(latitude ϕ) - sin2_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^2 - sin3_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^3 - sin4_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^4 - - # Acceleration due to zonal harmonics in inertial frame - F_J2_x = Array{S}(undef, N) - F_J2_y = Array{S}(undef, N) - F_J2_z = Array{S}(undef, N) - # Auxiliaries to compute F_J2_i, i = x, y, z - F_J2_x1 = Array{S}(undef, N) - F_J2_y1 = Array{S}(undef, N) - F_J2_z1 = Array{S}(undef, N) - F_J2_x2 = Array{S}(undef, N) - F_J2_y2 = Array{S}(undef, N) - F_J2_z2 = Array{S}(undef, N) - - # Temporary arrays for the sum of full extended body accelerations - temp_accX_i = Array{S}(undef, N) - temp_accY_i = Array{S}(undef, N) - temp_accZ_i = Array{S}(undef, N) - - # Legendre polynomials - # See equations (176) and (177) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - P_2_sin_ϕ = Array{S}(undef, N) # Second Legendre polynomial P_2(sin ϕ) - ∂P_2_sin_ϕ = Array{S}(undef, N) # dP_2(sin ϕ)/d(sin ϕ) - P_3_sin_ϕ = Array{S}(undef, N) # Third Legendre polynomial P_3(sin ϕ) - ∂P_3_sin_ϕ = Array{S}(undef, N) # dP_3(sin ϕ)/d(sin ϕ) - # -cos ϕ P_n' - m_c_ϕ_∂P_2 = Array{S}(undef, N) # -cos ϕ P_2' - m_c_ϕ_∂P_3 = Array{S}(undef, N) # -cos ϕ P_3' - - # -J_n * R^n / r^m - # J_n: n-th zonal harmonic coefficient - # R: radius of the body - # r: distance between the body and the asteroid - Λ2j_div_r4 = Array{S}(undef, N) # J_2 * R^2 / r^4 - Λ3j_div_r5 = Array{S}(undef, N) # J_3 * R^3 / r^5 - - # Accelerations due to zonal harmonics in body frame - - # Acceleration due to zonal harmonics J_n, n = 2, 3 - F_J_ξ = Array{S}(undef, N) # ξ-axis component - F_J_η = Array{S}(undef, N) # η-axis component - F_J_ζ = Array{S}(undef, N) # ζ-axis component - # Acceleration due to second zonal harmonic J_2 - F_J2_ξ = Array{S}(undef, N) # ξ-axis component - F_J2_η = Array{S}(undef, N) # η-axis component - F_J2_ζ = Array{S}(undef, N) # ζ-axis component - # Acceleration due to third zonal harmonic J_3 - F_J3_ξ = Array{S}(undef, N) # ξ-axis component - F_J3_η = Array{S}(undef, N) # η-axis component - F_J3_ζ = Array{S}(undef, N) # ζ-axis component - - # Unit vectors (ξ, η, ζ) in inertial frame - - # ξ vector - ξx = Array{S}(undef, N) - ξy = Array{S}(undef, N) - ξz = Array{S}(undef, N) - # η vector - ηx = Array{S}(undef, N) - ηy = Array{S}(undef, N) - ηz = Array{S}(undef, N) - # Auxiliaries to compute η vector - ηx1 = Array{S}(undef, N) - ηy1 = Array{S}(undef, N) - ηz1 = Array{S}(undef, N) - ηx2 = Array{S}(undef, N) - ηy2 = Array{S}(undef, N) - ηz2 = Array{S}(undef, N) - # ζ vector - ζx = Array{S}(undef, N) - ζy = Array{S}(undef, N) - ζz = Array{S}(undef, N) - # Auxiliaries to compute ζ vector - ζx1 = Array{S}(undef, N) - ζy1 = Array{S}(undef, N) - ζz1 = Array{S}(undef, N) - ζx2 = Array{S}(undef, N) - ζy2 = Array{S}(undef, N) - ζz2 = Array{S}(undef, N) - - # Full extended-body accelerations - accX = zero_q_1 - accY = zero_q_1 - accZ = zero_q_1 - - # Rotations to and from Earth, Sun and Moon pole-oriented frames - local M_ = Array{S}(undef, 3, 3, N) - local M_ .= zero_q_1 - local M_[:, :, ea] .= t2c_jpl_de430(dsj2k)[:, :] .+ zero_q_1 - - # Fill first 3 elements of dq with velocities - dq[1] = q[4] - dq[2] = q[5] - dq[3] = q[6] - - # Newtonian potential of N bodies - newtonianNb_Potential[N] = zero_q_1 - - #= - Compute point-mass Newtonian accelerations, all bodies - See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - Threads.@threads for i in 1:Nm1 - # Velocity of the i-th body - ui[i] = ss16asteph_t[3(N-1+i)-2] # X-axis component - vi[i] = ss16asteph_t[3(N-1+i)-1] # Y-axis component - wi[i] = ss16asteph_t[3(N-1+i) ] # Z-axis component - - # Position of the i-th body - position of the asteroid - X[i] = ss16asteph_t[3i-2]-q[1] # X-axis component - Y[i] = ss16asteph_t[3i-1]-q[2] # Y-axis component - Z[i] = ss16asteph_t[3i ]-q[3] # Z-axis component - - # Velocity of the i-th body - velocity of the asteroid - U[i] = ui[i]-dq[1] # X-axis component - V[i] = vi[i]-dq[2] # Y-axis component - W[i] = wi[i]-dq[3] # Z-axis component - - # 4 * Velocity of the asteroid - 3 * velocity of the i-th body - _4U_m_3X[i] = (4dq[1]) - (3ui[i]) # X-axis component - _4V_m_3Y[i] = (4dq[2]) - (3vi[i]) # Y-axis component - _4W_m_3Z[i] = (4dq[3]) - (3wi[i]) # Z-axis component - - # Dot product inside the [] in the second term - pn2x = X[i]*_4U_m_3X[i] - pn2y = Y[i]*_4V_m_3Y[i] - pn2z = Z[i]*_4W_m_3Z[i] - - # v_{ij}v_{asteroid} j = x, y, z - UU[i] = ui[i]*dq[1] - VV[i] = vi[i]*dq[2] - WW[i] = wi[i]*dq[3] - - # - vi_dot_vj[i] = ( UU[i]+VV[i] ) + WW[i] - - # Distance between the i-th body and the asteroid - r_p2[i] = ( (X[i]^2)+(Y[i]^2) ) + (Z[i]^2) # r_{i,asteroid}^2 - r_p1d2[i] = sqrt(r_p2[i]) # sqrt(r_p2) <-> r_{i,asteroid} - r_p3d2[i] = r_p2[i]^1.5 # r_p2^1.5 <-> r_{i, asteroid}^3 - r_p7d2[i] = r_p2[i]^3.5 # r_p2^3.5 <-> r_{i, asteroid}^7 - - # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 - newtonianCoeff[i] = μ[i]/r_p3d2[i] - - # Second term without (\mathbf{v}_i - \mathbf{v}_asteroid) - pn2[i] = newtonianCoeff[i]*(( pn2x+pn2y ) + pn2z) - - # Newtonian coefficient * difference between two positions, i.e., - # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 - newton_acc_X[i] = X[i]*newtonianCoeff[i] - newton_acc_Y[i] = Y[i]*newtonianCoeff[i] - newton_acc_Z[i] = Z[i]*newtonianCoeff[i] - - # Newtonian potential of 1 body \mu_i / r_{i, asteroid} - newtonian1b_Potential[i] = μ[i]/r_p1d2[i] - # Third term without newtonian accelerations \mathbf{a}_i - pn3[i] = 3.5newtonian1b_Potential[i] - # Full second term - U_t_pn2[i] = pn2[i]*U[i] # X-axis component - V_t_pn2[i] = pn2[i]*V[i] # Y-axis component - W_t_pn2[i] = pn2[i]*W[i] # Z-axis component - - #= - Extended body accelerations - See equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract - and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - - # J_2 accelerations, if i-th body is flattened - if UJ_interaction[i] - # Rotate from inertial frame to extended-body frame - # Here we are rotating only the Z-coordinate - t31[i] = -X[i]*M_[1,3,i] - t32[i] = -Y[i]*M_[2,3,i] - t33[i] = -Z[i]*M_[3,3,i] - r_sin_ϕ[i] = (t31[i]+t32[i])+t33[i] # z-coordinate in body-fixed frame - - # Trigonometric functions of latitude ϕ and longitude λ in the body-fixed coordinate system - # See equations (165)-(168) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - - sin_ϕ[i] = r_sin_ϕ[i]/r_p1d2[i] # sin(latitude ϕ) - ϕ[i] = asin(sin_ϕ[i]) # Latitude ϕ - cos_ϕ[i] = cos(ϕ[i]) # cos(latitude ϕ) - sin2_ϕ[i] = sin_ϕ[i]^2 # sin(latitude ϕ)^2 - sin3_ϕ[i] = sin_ϕ[i]^3 # sin(latitude ϕ)^3 - - # Legendre polynomials - - # See equations (176) and (177) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - P_2_sin_ϕ[i] = 1.5sin2_ϕ[i] - 0.5 # Second Legendre polynomial P_2(sin ϕ) - ∂P_2_sin_ϕ[i] = 3sin_ϕ[i] # dP_2(sin ϕ)/d(sin ϕ) - P_3_sin_ϕ[i] = (-1.5sin_ϕ[i]) + (2.5sin3_ϕ[i]) # Third Legendre polynomial P_3(sin ϕ) - ∂P_3_sin_ϕ[i] = -1.5 + 7.5sin2_ϕ[i] # dP_3(sin ϕ)/d(sin ϕ) - - # Compute cartesian coordinates of acceleration due to body figure in body frame - - # -J_n * R^n / r^m - # J_n: n-th zonal harmonic coefficient - # R: radius of the body - # r: distance between the body and the asteroid - Λ2j_div_r4[i] = -(Λ2[i]/(r_p2[i]^2)) # J_2 * R^2 / r^4 - Λ3j_div_r5[i] = -(Λ3[i]/(r_p1d2[i]^5)) # J_3 * R^3 / r^5 - - # -cos ϕ P_n' - m_c_ϕ_∂P_2[i] = (-cos_ϕ[i])*∂P_2_sin_ϕ[i] # -cos ϕ P_2' - m_c_ϕ_∂P_3[i] = (-cos_ϕ[i])*∂P_3_sin_ϕ[i] # -cos ϕ P_3' - - # Acceleration due to second zonal harmonic J_2 in body frame - F_J2_ξ[i] = ( Λ2j_div_r4[i]*(3P_2_sin_ϕ[i]) ) # ξ-axis component - # F_J2_η[i] = zero_q_1 # η-axis component - F_J2_ζ[i] = Λ2j_div_r4[i]*m_c_ϕ_∂P_2[i] # ζ-axis component - - # Acceleration due to third zonal harmonic J_3 in body frame - F_J3_ξ[i] = ( Λ3j_div_r5[i]*(4P_3_sin_ϕ[i]) ) # ξ-axis component - #F_J3_η[i] = zero_q_1 # η-axis component - F_J3_ζ[i] = Λ3j_div_r5[i]*m_c_ϕ_∂P_3[i] # ζ-axis component - - # Compute accelerations due to zonal harmonics J_n, n = 2, 3 in body frame - F_J_ξ[i] = F_J2_ξ[i] # + F_J3_ξ[i] # ξ-axis component - # F_J_η[i] = zero_q_1 # η-axis component - F_J_ζ[i] = F_J2_ζ[i] # + F_J3_ζ[i] # ζ-axis component - - # Compute unit vectors (ξ, η, ζ) in inertial frame - - # ξ components in inertial frame - ξx[i] = -X[i]/r_p1d2[i] - ξy[i] = -Y[i]/r_p1d2[i] - ξz[i] = -Z[i]/r_p1d2[i] - - # Compute η = p x ξ - # Auxiliaries - ηx1[i] = M_[2,3,i]*ξz[i] - ηy1[i] = M_[3,3,i]*ξx[i] - ηz1[i] = M_[1,3,i]*ξy[i] - ηx2[i] = M_[3,3,i]*ξy[i] - ηy2[i] = M_[1,3,i]*ξz[i] - ηz2[i] = M_[2,3,i]*ξx[i] - # η components in inertial frame - ηx[i] = ηx1[i] - ηx2[i] - ηy[i] = ηy1[i] - ηy2[i] - ηz[i] = ηz1[i] - ηz2[i] - - # Compute ζ = ξ x η - ζx1[i] = ξy[i]*ηz[i] - ζy1[i] = ξz[i]*ηx[i] - ζz1[i] = ξx[i]*ηy[i] - ζx2[i] = ξz[i]*ηy[i] - ζy2[i] = ξx[i]*ηz[i] - ζz2[i] = ξy[i]*ηx[i] - # ζ components in inertial frame - ζx[i] = ζx1[i] - ζx2[i] - ζy[i] = ζy1[i] - ζy2[i] - ζz[i] = ζz1[i] - ζz2[i] - - # Compute cartesian coordinates of acceleration due to body figure in inertial frame - # Auxiliaries - F_J2_x1[i] = F_J_ξ[i]*ξx[i] - F_J2_y1[i] = F_J_ξ[i]*ξy[i] - F_J2_z1[i] = F_J_ξ[i]*ξz[i] - F_J2_x2[i] = F_J_ζ[i]*ζx[i] - F_J2_y2[i] = F_J_ζ[i]*ζy[i] - F_J2_z2[i] = F_J_ζ[i]*ζz[i] - # Acceleration due to zonal harmonics in inertial frame - F_J2_x[i] = F_J2_x1[i] + F_J2_x2[i] - F_J2_y[i] = F_J2_y1[i] + F_J2_y2[i] - F_J2_z[i] = F_J2_z1[i] + F_J2_z2[i] - end - # Velocity magnitude of the i-th body - v2[i] = ( (ui[i]^2)+(vi[i]^2) ) + (wi[i]^2) - end - # Asteroid velocity magnitude - v2[N] = ( (q[4]^2)+(q[5]^2) ) + (q[6]^2) - - for i in 1:Nm1 - # Newtonian potential of N bodies - # \sum_{i\neq l} \frac{\mu_i}{r_{il}} or - # \sum_{j\neq k} \frac{\mu_j}{r_{jk}} - temp_004 = newtonian1b_Potential[i] + newtonianNb_Potential[N] - newtonianNb_Potential[N] = temp_004 - - # Extended body accelerations - # J_n accelerations, if i-th body is flattened - if UJ_interaction[i] - # Reaction force on i-th body - temp_accX_i[i] = accX - (μ[i]*F_J2_x[i]) - accX = temp_accX_i[i] - temp_accY_i[i] = accY - (μ[i]*F_J2_y[i]) - accY = temp_accY_i[i] - temp_accZ_i[i] = accZ - (μ[i]*F_J2_z[i]) - accZ = temp_accZ_i[i] - end - end - - #= - Post-Newtonian accelerations due to Sun, Moon and planets (Mercury through Neptune) - Post-Newtonian iterative procedure setup and initialization - See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - - # First term - - # 4*\sum term inside {} - _4ϕj[N] = 4newtonianNb_Potential[N] - Threads.@threads for i in 1:10 - # 4*\sum + \sum terms inside {} - ϕi_plus_4ϕj[i] = newtonianNb_Potential_t[i] + _4ϕj[N] - # \dot{s}_j^2 + 2\dot{s}_i^2 - 4 <, > terms inside {} - sj2_plus_2si2_minus_4vivj[i] = ( (2v2[i]) - (4vi_dot_vj[i]) ) + v2[N] - # -4\sum - \sum + \dot{s}_j^2 + 2\dot{s}_i^2 - 4<, > terms inside {} - ϕs_and_vs[i] = sj2_plus_2si2_minus_4vivj[i] - ϕi_plus_4ϕj[i] - # (\mathbf{r}_i - \mathbf{r}_asteroid)\cdot\mathbf{v_i} - Xij_t_Ui = X[i]*ui[i] - Yij_t_Vi = Y[i]*vi[i] - Zij_t_Wi = Z[i]*wi[i] - Rij_dot_Vi = ( Xij_t_Ui+Yij_t_Vi ) + Zij_t_Wi - # The expression below inside the (...)^2 should have a minus sign in front of the - # numerator, but upon squaring it is eliminated, so at the end of the day, it is - # irrelevant ;) - # (\mathbf{r}_i - \mathbf{r}_asteroid)\cdot\mathbf{v_i} / r_{i, asteroid} - pn1t7 = (Rij_dot_Vi^2)/r_p2[i] - # Everything inside the {} except for the first and last terms - pn1t2_7 = ϕs_and_vs[i] - (1.5pn1t7) - # Everything inside the {} except for the last term - pn1t1_7[i] = c_p2 + pn1t2_7 - - # Last term inside the {} - pNX_t_X[i] = acceph_t[3i-2]*X[i] # X-axis component - pNY_t_Y[i] = acceph_t[3i-1]*Y[i] # Y-axis component - pNZ_t_Z[i] = acceph_t[3i ]*Z[i] # Z-axis component - - # Everything inside the {} in the first term - pn1[i] = ( pn1t1_7[i] + (0.5*( (pNX_t_X[i]+pNY_t_Y[i]) + pNZ_t_Z[i] )) ) - - # Full first term - X_t_pn1[i] = newton_acc_X[i]*pn1[i] # X-axis component - Y_t_pn1[i] = newton_acc_Y[i]*pn1[i] # Y-axis component - Z_t_pn1[i] = newton_acc_Z[i]*pn1[i] # Z-axis component - - # Full third term - pNX_t_pn3[i] = acceph_t[3i-2]*pn3[i] # X-axis component - pNY_t_pn3[i] = acceph_t[3i-1]*pn3[i] # Y-axis component - pNZ_t_pn3[i] = acceph_t[3i ]*pn3[i] # Z-axis component - end - # Temporary post-Newtonian accelerations (planets) - for i in 1:10 - termpnx = ( X_t_pn1[i] + (U_t_pn2[i]+pNX_t_pn3[i]) ) # X-axis component - sumpnx = pntempX + termpnx - pntempX = sumpnx - termpny = ( Y_t_pn1[i] + (V_t_pn2[i]+pNY_t_pn3[i]) ) # Y-axis component - sumpny = pntempY + termpny - pntempY = sumpny - termpnz = ( Z_t_pn1[i] + (W_t_pn2[i]+pNZ_t_pn3[i]) ) # Z-axis component - sumpnz = pntempZ + termpnz - pntempZ = sumpnz - end - # Compute Newtonian accelerations due to Pluto and 16 asteroid perturbers - Threads.@threads for i in 11:Nm1 - # Full first term - X_t_pn1[i] = c_p2*newton_acc_X[i] - Y_t_pn1[i] = c_p2*newton_acc_Y[i] - Z_t_pn1[i] = c_p2*newton_acc_Z[i] - end - # Temporary post-Newtonian accelerations (Pluto + 16 asteroid perturbers) - for i in 11:Nm1 - termpnx = X_t_pn1[i] # X-axis component - sumpnx = pntempX + termpnx - pntempX = sumpnx - termpny = Y_t_pn1[i] # Y-axis component - sumpny = pntempY + termpny - pntempY = sumpny - termpnz = Z_t_pn1[i] # Z-axis component - sumpnz = pntempZ + termpnz - pntempZ = sumpnz - end - # Post-Newtonian acelerations - postNewtonX = pntempX*c_m2 # X-axis component - postNewtonY = pntempY*c_m2 # Y-axis component - postNewtonZ = pntempZ*c_m2 # Z-axis component - - # Fill dq[4:6] with accelerations - # Post-Newton point mass + Extended body - dq[4] = postNewtonX + accX - dq[5] = postNewtonY + accY - dq[6] = postNewtonZ + accZ - - nothing +@doc raw""" + evaleph(eph::TaylorInterpolant, t::Taylor1, q::Taylor1{U}) where {U} + evaleph(eph::TaylorInterpolant, t::Taylor1, q::TaylorN{Taylor1{T}}) where {T<:Real} + +Evaluate planetary ephemeris with type given by `q`. +""" +function evaleph(eph::TaylorInterpolant, t::Taylor1, q::Taylor1{U}) where {U} + return map(x -> Taylor1( x.coeffs*one(q[0]) ), eph(t)) +end + +function evaleph(eph::TaylorInterpolant, t::Taylor1, q::TaylorN{Taylor1{T}}) where {T<:Real} + return one(q)*eph(t) +end + +@doc raw""" + auxzero(a::AbstractSeries) + +Return a zero of the same type as `a`. +""" +function auxzero(a::AbstractSeries) + return zero(a) +end + +@doc raw""" + auxzero(a::TaylorN{Taylor1{T}}) where {T<:Number} + +Return a `TaylorN` with zero coefficients of the same type as `a.coeffs`. +""" +function auxzero(a::TaylorN{Taylor1{T}}) where {T<:Number} + return TaylorN(zero.(a.coeffs)) +end + +# Nearth-Earth asteroid dynamical model (d=2.0) +# Bodies considered in the model are: the Sun, the eight planets, the Moon and Ceres, +# as well as the asteroid of interest as a test particle with null mass. Dynamical +# effects considered are: +# - post-Newtonian point-mass accelerations between all bodies, +# - figure-effects (oblateness) of the Earth (J2 and J3) +# - J2 effect of the Sun +# - J2 and J3 effect of the Moon +# - Kinematic model for the precession and nutation of the Earth's orientation (IAU 1976/1980 Earth orientation model) +# - Kinematic model for the Moons's orientation (Seidelmann et al., 2006) +# - Non-gravitational accelerations acting upon the asteroid +# are included (Yarkovsky effect) a_nongrav = A2*t_vec*(au/r)^d, where t_vec is the +# unit heliocentric transverse vector, au is 1 astronomical unit, r is the +# asteroid's heliocentric range, A2 is a coefficient (with units of au/day^2), +# and d = 2.0 + +@doc raw""" + RNp1BP_pN_A_J23E_J2S_ng_eph_threads!(dq, q, params, t) + +Near-Earth asteroid dynamical model (``d = 2``). Bodies considered in the model are: the Sun, +the eight planets, the Moon and Ceres, as well as the asteroid of interest as a test particle +with null mass. Dynamical effects considered are: + +- Post-Newtonian point-mass accelerations between all bodies: see equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract. + +- Figure-effects (oblateness) of the Earth (``J_2`` and ``J_3``), + +- ``J_2`` effect of the Sun and + +- ``J_2`` and ``J_3`` effect of the Moon: see equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract. + +- Kinematic model for the precession and nutation of the Earth's orientation (IAU 1976/1980 Earth orientation model): see [`PlanetaryEphemeris.c2t_jpl_de430`](@ref). + +- Kinematic model for the Moon's orientation (Seidelmann et al., 2006): see equations (14)-(15) in page 9 and equations (34)-(35) in page 16 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract. + +- Non-gravitational accelerations acting upon the asteroid: are included (Yarkovsky effect) +```math +\mathbf{a}_\text{nongrav} = A_2\left(\frac{1 \ \text{au}}{r}\right)^d*\hat{\mathbf{t}}, +``` +where ``\hat{\mathbf{t}}`` is the unit heliocentric transverse vector, ``r`` is the +asteroid's heliocentric range, ``A_2`` is a coefficient (with units of au/day^2), +and ``d = 2``. + +To improve performance, some internal loops are multi-threaded via `Threads.threads for` + +See also [`PlanetaryEphemeris.NBP_pN_A_J23E_J23M_J2S!`](@ref). +""" RNp1BP_pN_A_J23E_J2S_ng_eph_threads! + +function RNp1BP_pN_A_J23E_J2S_ng_eph_threads!(dq, q, params, t) + # Julian date of start time + local jd0 = params[4] + # Days since J2000.0 = 2.451545e6 + local dsj2k = t + (jd0 - JD_J2000) + # Solar system ephemeris at dsj2k + local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) + # Accelerations at dsj2k + local acceph_t = evaleph(params[2], dsj2k, q[1]) + # Newtonian potentials at dsj2k + local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) + # Type of position / velocity components + local S = eltype(q) + # Interaction matrix with flattened bodies + local UJ_interaction = params[5] + # Number of bodies, including NEA + local N = params[6] + # Number of bodies, except the asteroid + local Nm1 = N-1 + # Vector of mass parameters GM's + local μ = params[7] + + # zero(q[1]) + local zero_q_1 = auxzero(q[1]) + + #= + Point-mass accelerations + See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + + # Position of the i-th body - position of the asteroid + X = Array{S}(undef, N) # X-axis component + Y = Array{S}(undef, N) # Y-axis component + Z = Array{S}(undef, N) # Z-axis component + + # Distance between the i-th body and the asteroid + r_p2 = Array{S}(undef, N) # r_{i,asteroid}^2 + r_p1d2 = Array{S}(undef, N) # sqrt(r_p2) <-> r_{i, asteroid} + r_p3d2 = Array{S}(undef, N) # r_p2^1.5 <-> r_{i, asteroid}^3 + r_p7d2 = Array{S}(undef, N) # r_p2^3.5 <-> r_{i, asteroid}^7 + + # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 + newtonianCoeff = Array{S}(undef, N) + + # Velocity of the i-th body + ui = Array{S}(undef, N-1) # X-axis component + vi = Array{S}(undef, N-1) # Y-axis component + wi = Array{S}(undef, N-1) # Z-axis component + + # Post-Newtonian stuff + + # Velocity of the i-th body - velocity of the asteroid + U = Array{S}(undef, N) # X-axis component + V = Array{S}(undef, N) # Y-axis component + W = Array{S}(undef, N) # Z-axis component + + # 4 * Velocity of the asteroid - 3 * velocity of the i-th body + _4U_m_3X = Array{S}(undef, N) # X-axis component + _4V_m_3Y = Array{S}(undef, N) # Y-axis component + _4W_m_3Z = Array{S}(undef, N) # Z-axis component + + # v_{i,j}v_{asteroid,j} j = x, y, z + UU = Array{S}(undef, N) # v_{i,x}v_{asteroid,x} + VV = Array{S}(undef, N) # v_{i,y}v_{asteroid,y} + WW = Array{S}(undef, N) # v_{i,z}v_{asteroid,z} + + # Newtonian potential of 1 body \mu_i / r_{i, asteroid} + newtonian1b_Potential = Array{S}(undef, N) + # Newtonian potential of N bodies + # \sum_{i\neq l} \frac{\mu_i}{r_{il}} or + # \sum_{j\neq k} \frac{\mu_j}{r_{jk}} + newtonianNb_Potential = Array{S}(undef, N) + + # Newtonian coefficient * difference between two positions, i.e., + # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 + newton_acc_X = Array{S}(undef, N) # X-axis component + newton_acc_Y = Array{S}(undef, N) # Y-axis component + newton_acc_Z = Array{S}(undef, N) # Z-axis component + + # Combinations of velocities + v2 = Array{S}(undef, N) # Velocity magnitude squared ||\mathbf{v}_i||^2 + vi_dot_vj = Array{S}(undef, N) # + + # Second term without (\mathbf{v}_i - \mathbf{v}_j) + pn2 = Array{S}(undef, N) + # Full second term + U_t_pn2 = Array{S}(undef, N) # X-axis component + V_t_pn2 = Array{S}(undef, N) # Y-axis component + W_t_pn2 = Array{S}(undef, N) # Z-axis component + + # Third term without newtonian accelerations \mathbf{a}_i + pn3 = Array{S}(undef, N) + # Full third term of equation (35) + pNX_t_pn3 = Array{S}(undef, N) # X-axis component + pNY_t_pn3 = Array{S}(undef, N) # Y-axis component + pNZ_t_pn3 = Array{S}(undef, N) # Z-axis component + + # First term + _4ϕj = Array{S}(undef, N) # 4*\sum term inside {} + ϕi_plus_4ϕj = Array{S}(undef, N) # 4*\sum + \sum terms inside {} + sj2_plus_2si2_minus_4vivj = Array{S}(undef, N) # \dot{s}_j^2 + 2\dot{s}_i^2 - 4 <, > terms inside {} + ϕs_and_vs = Array{S}(undef, N) # -4\sum - \sum + \dot{s}_j^2 + 2\dot{s}_i^2 - 4<, > terms inside {} + pn1t1_7 = Array{S}(undef, N) # Everything inside the {} in the first term except for the term with accelerations (last) + # Last term inside the {} + pNX_t_X = Array{S}(undef, N) # X-axis component + pNY_t_Y = Array{S}(undef, N) # Y-axis component + pNZ_t_Z = Array{S}(undef, N) # Z-axis component + # Everything inside the {} in the first term + pn1 = Array{S}(undef, N) + # Full first term + X_t_pn1 = Array{S}(undef, N) # X-axis component + Y_t_pn1 = Array{S}(undef, N) # Y-axis component + Z_t_pn1 = Array{S}(undef, N) # Z-axis component + + # Temporary post-Newtonian accelerations + pntempX = zero_q_1 # X-axis component + pntempY = zero_q_1 # Y-axis component + pntempZ = zero_q_1 # Z-axis component + + #= + Extended body accelerations + See equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract + and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + + # J_2 acceleration auxiliaries + + # Auxiliaries to compute body-fixed frame coordinates + t31 = Array{S}(undef, N) + t32 = Array{S}(undef, N) + t33 = Array{S}(undef, N) + # z-coordinate in body-fixed frame + r_sin_ϕ = Array{S}(undef, N) + + # Trigonometric functions of latitude ϕ and longitude λ in the body-fixed coordinate system + # See equations (165)-(168) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + sin_ϕ = Array{S}(undef, N) # sin(latitude ϕ) + ϕ = Array{S}(undef, N) # Latitude ϕ + cos_ϕ = Array{S}(undef, N) # cos(latitude ϕ) + sin2_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^2 + sin3_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^3 + sin4_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^4 + + # Acceleration due to zonal harmonics in inertial frame + F_J2_x = Array{S}(undef, N) + F_J2_y = Array{S}(undef, N) + F_J2_z = Array{S}(undef, N) + # Auxiliaries to compute F_J2_i, i = x, y, z + F_J2_x1 = Array{S}(undef, N) + F_J2_y1 = Array{S}(undef, N) + F_J2_z1 = Array{S}(undef, N) + F_J2_x2 = Array{S}(undef, N) + F_J2_y2 = Array{S}(undef, N) + F_J2_z2 = Array{S}(undef, N) + + # Temporary arrays for the sum of full extended body accelerations + temp_accX_i = Array{S}(undef, N) + temp_accY_i = Array{S}(undef, N) + temp_accZ_i = Array{S}(undef, N) + + # Legendre polynomials + # See equations (176) and (177) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + P_2_sin_ϕ = Array{S}(undef, N) # Second Legendre polynomial P_2(sin ϕ) + ∂P_2_sin_ϕ = Array{S}(undef, N) # dP_2(sin ϕ)/d(sin ϕ) + P_3_sin_ϕ = Array{S}(undef, N) # Third Legendre polynomial P_3(sin ϕ) + ∂P_3_sin_ϕ = Array{S}(undef, N) # dP_3(sin ϕ)/d(sin ϕ) + # -cos ϕ P_n' + m_c_ϕ_∂P_2 = Array{S}(undef, N) # -cos ϕ P_2' + m_c_ϕ_∂P_3 = Array{S}(undef, N) # -cos ϕ P_3' + + # -J_n * R^n / r^m + # J_n: n-th zonal harmonic coefficient + # R: radius of the body + # r: distance between the body and the asteroid + Λ2j_div_r4 = Array{S}(undef, N) # J_2 * R^2 / r^4 + Λ3j_div_r5 = Array{S}(undef, N) # J_3 * R^3 / r^5 + + # Accelerations due to zonal harmonics in body frame + + # Acceleration due to zonal harmonics J_n, n = 2, 3 + F_J_ξ = Array{S}(undef, N) # ξ-axis component + F_J_η = Array{S}(undef, N) # η-axis component + F_J_ζ = Array{S}(undef, N) # ζ-axis component + # Acceleration due to second zonal harmonic J_2 + F_J2_ξ = Array{S}(undef, N) # ξ-axis component + F_J2_η = Array{S}(undef, N) # η-axis component + F_J2_ζ = Array{S}(undef, N) # ζ-axis component + # Acceleration due to third zonal harmonic J_3 + F_J3_ξ = Array{S}(undef, N) # ξ-axis component + F_J3_η = Array{S}(undef, N) # η-axis component + F_J3_ζ = Array{S}(undef, N) # ζ-axis component + + # Unit vectors (ξ, η, ζ) in inertial frame + + # ξ vector + ξx = Array{S}(undef, N) + ξy = Array{S}(undef, N) + ξz = Array{S}(undef, N) + # η vector + ηx = Array{S}(undef, N) + ηy = Array{S}(undef, N) + ηz = Array{S}(undef, N) + # Auxiliaries to compute η vector + ηx1 = Array{S}(undef, N) + ηy1 = Array{S}(undef, N) + ηz1 = Array{S}(undef, N) + ηx2 = Array{S}(undef, N) + ηy2 = Array{S}(undef, N) + ηz2 = Array{S}(undef, N) + # ζ vector + ζx = Array{S}(undef, N) + ζy = Array{S}(undef, N) + ζz = Array{S}(undef, N) + # Auxiliaries to compute ζ vector + ζx1 = Array{S}(undef, N) + ζy1 = Array{S}(undef, N) + ζz1 = Array{S}(undef, N) + ζx2 = Array{S}(undef, N) + ζy2 = Array{S}(undef, N) + ζz2 = Array{S}(undef, N) + + # Full extended-body accelerations + accX = zero_q_1 + accY = zero_q_1 + accZ = zero_q_1 + + # Rotations to and from Earth, Sun and Moon pole-oriented frames + local M_ = Array{S}(undef, 3, 3, N) + local M_ .= zero_q_1 + local M_[:, :, ea] .= t2c_jpl_de430(dsj2k)[:, :] .+ zero_q_1 + + # Fill first 3 elements of dq with velocities + dq[1] = q[4] + dq[2] = q[5] + dq[3] = q[6] + + # Newtonian potential of N bodies + newtonianNb_Potential[N] = zero_q_1 + + #= + Compute point-mass Newtonian accelerations, all bodies + See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + Threads.@threads for i in 1:Nm1 + # Velocity of the i-th body + ui[i] = ss16asteph_t[3(N-1+i)-2] # X-axis component + vi[i] = ss16asteph_t[3(N-1+i)-1] # Y-axis component + wi[i] = ss16asteph_t[3(N-1+i) ] # Z-axis component + + # Position of the i-th body - position of the asteroid + X[i] = ss16asteph_t[3i-2]-q[1] # X-axis component + Y[i] = ss16asteph_t[3i-1]-q[2] # Y-axis component + Z[i] = ss16asteph_t[3i ]-q[3] # Z-axis component + + # Velocity of the i-th body - velocity of the asteroid + U[i] = ui[i]-dq[1] # X-axis component + V[i] = vi[i]-dq[2] # Y-axis component + W[i] = wi[i]-dq[3] # Z-axis component + + # 4 * Velocity of the asteroid - 3 * velocity of the i-th body + _4U_m_3X[i] = (4dq[1]) - (3ui[i]) # X-axis component + _4V_m_3Y[i] = (4dq[2]) - (3vi[i]) # Y-axis component + _4W_m_3Z[i] = (4dq[3]) - (3wi[i]) # Z-axis component + + # Dot product inside the [] in the second term + pn2x = X[i]*_4U_m_3X[i] + pn2y = Y[i]*_4V_m_3Y[i] + pn2z = Z[i]*_4W_m_3Z[i] + + # v_{ij}v_{asteroid} j = x, y, z + UU[i] = ui[i]*dq[1] + VV[i] = vi[i]*dq[2] + WW[i] = wi[i]*dq[3] + + # + vi_dot_vj[i] = ( UU[i]+VV[i] ) + WW[i] + + # Distance between the i-th body and the asteroid + r_p2[i] = ( (X[i]^2)+(Y[i]^2) ) + (Z[i]^2) # r_{i,asteroid}^2 + r_p1d2[i] = sqrt(r_p2[i]) # sqrt(r_p2) <-> r_{i,asteroid} + r_p3d2[i] = r_p2[i]^1.5 # r_p2^1.5 <-> r_{i, asteroid}^3 + r_p7d2[i] = r_p2[i]^3.5 # r_p2^3.5 <-> r_{i, asteroid}^7 + + # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 + newtonianCoeff[i] = μ[i]/r_p3d2[i] + + # Second term without (\mathbf{v}_i - \mathbf{v}_asteroid) + pn2[i] = newtonianCoeff[i]*(( pn2x+pn2y ) + pn2z) + + # Newtonian coefficient * difference between two positions, i.e., + # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 + newton_acc_X[i] = X[i]*newtonianCoeff[i] + newton_acc_Y[i] = Y[i]*newtonianCoeff[i] + newton_acc_Z[i] = Z[i]*newtonianCoeff[i] + + # Newtonian potential of 1 body \mu_i / r_{i, asteroid} + newtonian1b_Potential[i] = μ[i]/r_p1d2[i] + # Third term without newtonian accelerations \mathbf{a}_i + pn3[i] = 3.5newtonian1b_Potential[i] + # Full second term + U_t_pn2[i] = pn2[i]*U[i] # X-axis component + V_t_pn2[i] = pn2[i]*V[i] # Y-axis component + W_t_pn2[i] = pn2[i]*W[i] # Z-axis component + + #= + Extended body accelerations + See equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract + and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + + # J_2 accelerations, if i-th body is flattened + if UJ_interaction[i] + # Rotate from inertial frame to extended-body frame + # Here we are rotating only the Z-coordinate + t31[i] = -X[i]*M_[1,3,i] + t32[i] = -Y[i]*M_[2,3,i] + t33[i] = -Z[i]*M_[3,3,i] + r_sin_ϕ[i] = (t31[i]+t32[i])+t33[i] # z-coordinate in body-fixed frame + + # Trigonometric functions of latitude ϕ and longitude λ in the body-fixed coordinate system + # See equations (165)-(168) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + + sin_ϕ[i] = r_sin_ϕ[i]/r_p1d2[i] # sin(latitude ϕ) + ϕ[i] = asin(sin_ϕ[i]) # Latitude ϕ + cos_ϕ[i] = cos(ϕ[i]) # cos(latitude ϕ) + sin2_ϕ[i] = sin_ϕ[i]^2 # sin(latitude ϕ)^2 + sin3_ϕ[i] = sin_ϕ[i]^3 # sin(latitude ϕ)^3 + + # Legendre polynomials + + # See equations (176) and (177) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + P_2_sin_ϕ[i] = 1.5sin2_ϕ[i] - 0.5 # Second Legendre polynomial P_2(sin ϕ) + ∂P_2_sin_ϕ[i] = 3sin_ϕ[i] # dP_2(sin ϕ)/d(sin ϕ) + P_3_sin_ϕ[i] = (-1.5sin_ϕ[i]) + (2.5sin3_ϕ[i]) # Third Legendre polynomial P_3(sin ϕ) + ∂P_3_sin_ϕ[i] = -1.5 + 7.5sin2_ϕ[i] # dP_3(sin ϕ)/d(sin ϕ) + + # Compute cartesian coordinates of acceleration due to body figure in body frame + + # -J_n * R^n / r^m + # J_n: n-th zonal harmonic coefficient + # R: radius of the body + # r: distance between the body and the asteroid + Λ2j_div_r4[i] = -(Λ2[i]/(r_p2[i]^2)) # J_2 * R^2 / r^4 + Λ3j_div_r5[i] = -(Λ3[i]/(r_p1d2[i]^5)) # J_3 * R^3 / r^5 + + # -cos ϕ P_n' + m_c_ϕ_∂P_2[i] = (-cos_ϕ[i])*∂P_2_sin_ϕ[i] # -cos ϕ P_2' + m_c_ϕ_∂P_3[i] = (-cos_ϕ[i])*∂P_3_sin_ϕ[i] # -cos ϕ P_3' + + # Acceleration due to second zonal harmonic J_2 in body frame + F_J2_ξ[i] = ( Λ2j_div_r4[i]*(3P_2_sin_ϕ[i]) ) # ξ-axis component + # F_J2_η[i] = zero_q_1 # η-axis component + F_J2_ζ[i] = Λ2j_div_r4[i]*m_c_ϕ_∂P_2[i] # ζ-axis component + + # Acceleration due to third zonal harmonic J_3 in body frame + F_J3_ξ[i] = ( Λ3j_div_r5[i]*(4P_3_sin_ϕ[i]) ) # ξ-axis component + #F_J3_η[i] = zero_q_1 # η-axis component + F_J3_ζ[i] = Λ3j_div_r5[i]*m_c_ϕ_∂P_3[i] # ζ-axis component + + # Compute accelerations due to zonal harmonics J_n, n = 2, 3 in body frame + F_J_ξ[i] = F_J2_ξ[i] # + F_J3_ξ[i] # ξ-axis component + # F_J_η[i] = zero_q_1 # η-axis component + F_J_ζ[i] = F_J2_ζ[i] # + F_J3_ζ[i] # ζ-axis component + + # Compute unit vectors (ξ, η, ζ) in inertial frame + + # ξ components in inertial frame + ξx[i] = -X[i]/r_p1d2[i] + ξy[i] = -Y[i]/r_p1d2[i] + ξz[i] = -Z[i]/r_p1d2[i] + + # Compute η = p x ξ + # Auxiliaries + ηx1[i] = M_[2,3,i]*ξz[i] + ηy1[i] = M_[3,3,i]*ξx[i] + ηz1[i] = M_[1,3,i]*ξy[i] + ηx2[i] = M_[3,3,i]*ξy[i] + ηy2[i] = M_[1,3,i]*ξz[i] + ηz2[i] = M_[2,3,i]*ξx[i] + # η components in inertial frame + ηx[i] = ηx1[i] - ηx2[i] + ηy[i] = ηy1[i] - ηy2[i] + ηz[i] = ηz1[i] - ηz2[i] + + # Compute ζ = ξ x η + ζx1[i] = ξy[i]*ηz[i] + ζy1[i] = ξz[i]*ηx[i] + ζz1[i] = ξx[i]*ηy[i] + ζx2[i] = ξz[i]*ηy[i] + ζy2[i] = ξx[i]*ηz[i] + ζz2[i] = ξy[i]*ηx[i] + # ζ components in inertial frame + ζx[i] = ζx1[i] - ζx2[i] + ζy[i] = ζy1[i] - ζy2[i] + ζz[i] = ζz1[i] - ζz2[i] + + # Compute cartesian coordinates of acceleration due to body figure in inertial frame + # Auxiliaries + F_J2_x1[i] = F_J_ξ[i]*ξx[i] + F_J2_y1[i] = F_J_ξ[i]*ξy[i] + F_J2_z1[i] = F_J_ξ[i]*ξz[i] + F_J2_x2[i] = F_J_ζ[i]*ζx[i] + F_J2_y2[i] = F_J_ζ[i]*ζy[i] + F_J2_z2[i] = F_J_ζ[i]*ζz[i] + # Acceleration due to zonal harmonics in inertial frame + F_J2_x[i] = F_J2_x1[i] + F_J2_x2[i] + F_J2_y[i] = F_J2_y1[i] + F_J2_y2[i] + F_J2_z[i] = F_J2_z1[i] + F_J2_z2[i] + end + # Velocity magnitude of the i-th body + v2[i] = ( (ui[i]^2)+(vi[i]^2) ) + (wi[i]^2) + end + # Asteroid velocity magnitude + v2[N] = ( (q[4]^2)+(q[5]^2) ) + (q[6]^2) + + for i in 1:Nm1 + # Newtonian potential of N bodies + # \sum_{i\neq l} \frac{\mu_i}{r_{il}} or + # \sum_{j\neq k} \frac{\mu_j}{r_{jk}} + temp_004 = newtonian1b_Potential[i] + newtonianNb_Potential[N] + newtonianNb_Potential[N] = temp_004 + + # Extended body accelerations + # J_n accelerations, if i-th body is flattened + if UJ_interaction[i] + # Reaction force on i-th body + temp_accX_i[i] = accX - (μ[i]*F_J2_x[i]) + accX = temp_accX_i[i] + temp_accY_i[i] = accY - (μ[i]*F_J2_y[i]) + accY = temp_accY_i[i] + temp_accZ_i[i] = accZ - (μ[i]*F_J2_z[i]) + accZ = temp_accZ_i[i] + end + end + + #= + Post-Newtonian accelerations due to Sun, Moon and planets (Mercury through Neptune) + Post-Newtonian iterative procedure setup and initialization + See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + + # First term + + # 4*\sum term inside {} + _4ϕj[N] = 4newtonianNb_Potential[N] + Threads.@threads for i in 1:10 + # 4*\sum + \sum terms inside {} + ϕi_plus_4ϕj[i] = newtonianNb_Potential_t[i] + _4ϕj[N] + # \dot{s}_j^2 + 2\dot{s}_i^2 - 4 <, > terms inside {} + sj2_plus_2si2_minus_4vivj[i] = ( (2v2[i]) - (4vi_dot_vj[i]) ) + v2[N] + # -4\sum - \sum + \dot{s}_j^2 + 2\dot{s}_i^2 - 4<, > terms inside {} + ϕs_and_vs[i] = sj2_plus_2si2_minus_4vivj[i] - ϕi_plus_4ϕj[i] + # (\mathbf{r}_i - \mathbf{r}_asteroid)\cdot\mathbf{v_i} + Xij_t_Ui = X[i]*ui[i] + Yij_t_Vi = Y[i]*vi[i] + Zij_t_Wi = Z[i]*wi[i] + Rij_dot_Vi = ( Xij_t_Ui+Yij_t_Vi ) + Zij_t_Wi + # The expression below inside the (...)^2 should have a minus sign in front of the + # numerator, but upon squaring it is eliminated, so at the end of the day, it is + # irrelevant ;) + # (\mathbf{r}_i - \mathbf{r}_asteroid)\cdot\mathbf{v_i} / r_{i, asteroid} + pn1t7 = (Rij_dot_Vi^2)/r_p2[i] + # Everything inside the {} except for the first and last terms + pn1t2_7 = ϕs_and_vs[i] - (1.5pn1t7) + # Everything inside the {} except for the last term + pn1t1_7[i] = c_p2 + pn1t2_7 + + # Last term inside the {} + pNX_t_X[i] = acceph_t[3i-2]*X[i] # X-axis component + pNY_t_Y[i] = acceph_t[3i-1]*Y[i] # Y-axis component + pNZ_t_Z[i] = acceph_t[3i ]*Z[i] # Z-axis component + + # Everything inside the {} in the first term + pn1[i] = ( pn1t1_7[i] + (0.5*( (pNX_t_X[i]+pNY_t_Y[i]) + pNZ_t_Z[i] )) ) + + # Full first term + X_t_pn1[i] = newton_acc_X[i]*pn1[i] # X-axis component + Y_t_pn1[i] = newton_acc_Y[i]*pn1[i] # Y-axis component + Z_t_pn1[i] = newton_acc_Z[i]*pn1[i] # Z-axis component + + # Full third term + pNX_t_pn3[i] = acceph_t[3i-2]*pn3[i] # X-axis component + pNY_t_pn3[i] = acceph_t[3i-1]*pn3[i] # Y-axis component + pNZ_t_pn3[i] = acceph_t[3i ]*pn3[i] # Z-axis component + end + # Temporary post-Newtonian accelerations (planets) + for i in 1:10 + termpnx = ( X_t_pn1[i] + (U_t_pn2[i]+pNX_t_pn3[i]) ) # X-axis component + sumpnx = pntempX + termpnx + pntempX = sumpnx + termpny = ( Y_t_pn1[i] + (V_t_pn2[i]+pNY_t_pn3[i]) ) # Y-axis component + sumpny = pntempY + termpny + pntempY = sumpny + termpnz = ( Z_t_pn1[i] + (W_t_pn2[i]+pNZ_t_pn3[i]) ) # Z-axis component + sumpnz = pntempZ + termpnz + pntempZ = sumpnz + end + # Compute Newtonian accelerations due to Pluto and 16 asteroid perturbers + Threads.@threads for i in 11:Nm1 + # Full first term + X_t_pn1[i] = c_p2*newton_acc_X[i] + Y_t_pn1[i] = c_p2*newton_acc_Y[i] + Z_t_pn1[i] = c_p2*newton_acc_Z[i] + end + # Temporary post-Newtonian accelerations (Pluto + 16 asteroid perturbers) + for i in 11:Nm1 + termpnx = X_t_pn1[i] # X-axis component + sumpnx = pntempX + termpnx + pntempX = sumpnx + termpny = Y_t_pn1[i] # Y-axis component + sumpny = pntempY + termpny + pntempY = sumpny + termpnz = Z_t_pn1[i] # Z-axis component + sumpnz = pntempZ + termpnz + pntempZ = sumpnz + end + # Post-Newtonian acelerations + postNewtonX = pntempX*c_m2 # X-axis component + postNewtonY = pntempY*c_m2 # Y-axis component + postNewtonZ = pntempZ*c_m2 # Z-axis component + + #= + Compute non-gravitational acceleration + =# + + # Angular momentum per unit mass + hx = (Y[1]*W[1])-(Z[1]*V[1]) # X-axis component + hy = (Z[1]*U[1])-(X[1]*W[1]) # Y-axis component + hz = (X[1]*V[1])-(Y[1]*U[1]) # Z-axis component + + # Cartesian components of transversal vector t = h × (\mathbf{r}_Sun - \mathbf{r}_asteroid) + t_x = (hz*Y[1]) - (hy*Z[1]) # Note: Y[1] = y_Sun - y_asteroid, etc. + t_y = (hx*Z[1]) - (hz*X[1]) + t_z = (hy*X[1]) - (hx*Y[1]) + # Norm of transversal vector + t_norm = sqrt( ((t_x^2)+(t_y^2))+(t_z^2) ) + # Cartesian components of transversal unit vector + t_x_unit = t_x/t_norm + t_y_unit = t_y/t_norm + t_z_unit = t_z/t_norm + + # Cartesian components of radial unit vector + r_x_unit = -(X[1]/r_p1d2[1]) + r_y_unit = -(Y[1]/r_p1d2[1]) + r_z_unit = -(Z[1]/r_p1d2[1]) + + # Evaluate non-grav acceleration (solar radiation pressure, Yarkovsky) + g_r = r_p2[1] # Distance Sun-asteroid + A2_t_g_r = q[7]/g_r # Yarkovsky effect + A1_t_g_r = q[8]/g_r # Radiation pressure + + # Non gravitational acceleration: Yarkovsky + radiation pressure + NGAx = (A2_t_g_r*t_x_unit) + (A1_t_g_r*r_x_unit) + NGAy = (A2_t_g_r*t_y_unit) + (A1_t_g_r*r_y_unit) + NGAz = (A2_t_g_r*t_z_unit) + (A1_t_g_r*r_z_unit) + + # Fill dq[4:6] with accelerations + # Post-Newton point mass + Extended body + Non-gravitational + dq[4] = ( postNewtonX + accX ) + NGAx + dq[5] = ( postNewtonY + accY ) + NGAy + dq[6] = ( postNewtonZ + accZ ) + NGAz + # Yarkovsky coefficient does not change in time + dq[7] = zero_q_1 + + nothing +end + +function RNp1BP_pN_A_J23E_J2S_eph_threads!(dq, q, params, t) + # Julian date of start time + local jd0 = params[4] + # Days since J2000.0 = 2.451545e6 + local dsj2k = t + (jd0 - JD_J2000) + # Solar system ephemeris at dsj2k + local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) + # Accelerations at dsj2k + local acceph_t = evaleph(params[2], dsj2k, q[1]) + # Newtonian potentials at dsj2k + local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) + # Type of position / velocity components + local S = eltype(q) + # Interaction matrix with flattened bodies + local UJ_interaction = params[5] + # Number of bodies, including NEA + local N = params[6] + # Number of bodies, except the asteroid + local Nm1 = N-1 + # Vector of mass parameters GM's + local μ = params[7] + + # zero(q[1]) + local zero_q_1 = auxzero(q[1]) + + #= + Point-mass accelerations + See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + + # Position of the i-th body - position of the asteroid + X = Array{S}(undef, N) # X-axis component + Y = Array{S}(undef, N) # Y-axis component + Z = Array{S}(undef, N) # Z-axis component + + # Distance between the i-th body and the asteroid + r_p2 = Array{S}(undef, N) # r_{i,asteroid}^2 + r_p1d2 = Array{S}(undef, N) # sqrt(r_p2) <-> r_{i, asteroid} + r_p3d2 = Array{S}(undef, N) # r_p2^1.5 <-> r_{i, asteroid}^3 + r_p7d2 = Array{S}(undef, N) # r_p2^3.5 <-> r_{i, asteroid}^7 + + # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 + newtonianCoeff = Array{S}(undef, N) + + # Velocity of the i-th body + ui = Array{S}(undef, N-1) # X-axis component + vi = Array{S}(undef, N-1) # Y-axis component + wi = Array{S}(undef, N-1) # Z-axis component + + # Post-Newtonian stuff + + # Velocity of the i-th body - velocity of the asteroid + U = Array{S}(undef, N) # X-axis component + V = Array{S}(undef, N) # Y-axis component + W = Array{S}(undef, N) # Z-axis component + + # 4 * Velocity of the asteroid - 3 * velocity of the i-th body + _4U_m_3X = Array{S}(undef, N) # X-axis component + _4V_m_3Y = Array{S}(undef, N) # Y-axis component + _4W_m_3Z = Array{S}(undef, N) # Z-axis component + + # v_{i,j}v_{asteroid,j} j = x, y, z + UU = Array{S}(undef, N) # v_{i,x}v_{asteroid,x} + VV = Array{S}(undef, N) # v_{i,y}v_{asteroid,y} + WW = Array{S}(undef, N) # v_{i,z}v_{asteroid,z} + + # Newtonian potential of 1 body \mu_i / r_{i, asteroid} + newtonian1b_Potential = Array{S}(undef, N) + # Newtonian potential of N bodies + # \sum_{i\neq l} \frac{\mu_i}{r_{il}} or + # \sum_{j\neq k} \frac{\mu_j}{r_{jk}} + newtonianNb_Potential = Array{S}(undef, N) + + # Newtonian coefficient * difference between two positions, i.e., + # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 + newton_acc_X = Array{S}(undef, N) # X-axis component + newton_acc_Y = Array{S}(undef, N) # Y-axis component + newton_acc_Z = Array{S}(undef, N) # Z-axis component + + # Combinations of velocities + v2 = Array{S}(undef, N) # Velocity magnitude squared ||\mathbf{v}_i||^2 + vi_dot_vj = Array{S}(undef, N) # + + # Second term without (\mathbf{v}_i - \mathbf{v}_j) + pn2 = Array{S}(undef, N) + # Full second term + U_t_pn2 = Array{S}(undef, N) # X-axis component + V_t_pn2 = Array{S}(undef, N) # Y-axis component + W_t_pn2 = Array{S}(undef, N) # Z-axis component + + # Third term without newtonian accelerations \mathbf{a}_i + pn3 = Array{S}(undef, N) + # Full third term of equation (35) + pNX_t_pn3 = Array{S}(undef, N) # X-axis component + pNY_t_pn3 = Array{S}(undef, N) # Y-axis component + pNZ_t_pn3 = Array{S}(undef, N) # Z-axis component + + # First term + _4ϕj = Array{S}(undef, N) # 4*\sum term inside {} + ϕi_plus_4ϕj = Array{S}(undef, N) # 4*\sum + \sum terms inside {} + sj2_plus_2si2_minus_4vivj = Array{S}(undef, N) # \dot{s}_j^2 + 2\dot{s}_i^2 - 4 <, > terms inside {} + ϕs_and_vs = Array{S}(undef, N) # -4\sum - \sum + \dot{s}_j^2 + 2\dot{s}_i^2 - 4<, > terms inside {} + pn1t1_7 = Array{S}(undef, N) # Everything inside the {} in the first term except for the term with accelerations (last) + # Last term inside the {} + pNX_t_X = Array{S}(undef, N) # X-axis component + pNY_t_Y = Array{S}(undef, N) # Y-axis component + pNZ_t_Z = Array{S}(undef, N) # Z-axis component + # Everything inside the {} in the first term + pn1 = Array{S}(undef, N) + # Full first term + X_t_pn1 = Array{S}(undef, N) # X-axis component + Y_t_pn1 = Array{S}(undef, N) # Y-axis component + Z_t_pn1 = Array{S}(undef, N) # Z-axis component + + # Temporary post-Newtonian accelerations + pntempX = zero_q_1 # X-axis component + pntempY = zero_q_1 # Y-axis component + pntempZ = zero_q_1 # Z-axis component + + #= + Extended body accelerations + See equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract + and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + + # J_2 acceleration auxiliaries + + # Auxiliaries to compute body-fixed frame coordinates + t31 = Array{S}(undef, N) + t32 = Array{S}(undef, N) + t33 = Array{S}(undef, N) + # z-coordinate in body-fixed frame + r_sin_ϕ = Array{S}(undef, N) + + # Trigonometric functions of latitude ϕ and longitude λ in the body-fixed coordinate system + # See equations (165)-(168) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + sin_ϕ = Array{S}(undef, N) # sin(latitude ϕ) + ϕ = Array{S}(undef, N) # Latitude ϕ + cos_ϕ = Array{S}(undef, N) # cos(latitude ϕ) + sin2_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^2 + sin3_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^3 + sin4_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^4 + + # Acceleration due to zonal harmonics in inertial frame + F_J2_x = Array{S}(undef, N) + F_J2_y = Array{S}(undef, N) + F_J2_z = Array{S}(undef, N) + # Auxiliaries to compute F_J2_i, i = x, y, z + F_J2_x1 = Array{S}(undef, N) + F_J2_y1 = Array{S}(undef, N) + F_J2_z1 = Array{S}(undef, N) + F_J2_x2 = Array{S}(undef, N) + F_J2_y2 = Array{S}(undef, N) + F_J2_z2 = Array{S}(undef, N) + + # Temporary arrays for the sum of full extended body accelerations + temp_accX_i = Array{S}(undef, N) + temp_accY_i = Array{S}(undef, N) + temp_accZ_i = Array{S}(undef, N) + + # Legendre polynomials + # See equations (176) and (177) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + P_2_sin_ϕ = Array{S}(undef, N) # Second Legendre polynomial P_2(sin ϕ) + ∂P_2_sin_ϕ = Array{S}(undef, N) # dP_2(sin ϕ)/d(sin ϕ) + P_3_sin_ϕ = Array{S}(undef, N) # Third Legendre polynomial P_3(sin ϕ) + ∂P_3_sin_ϕ = Array{S}(undef, N) # dP_3(sin ϕ)/d(sin ϕ) + # -cos ϕ P_n' + m_c_ϕ_∂P_2 = Array{S}(undef, N) # -cos ϕ P_2' + m_c_ϕ_∂P_3 = Array{S}(undef, N) # -cos ϕ P_3' + + # -J_n * R^n / r^m + # J_n: n-th zonal harmonic coefficient + # R: radius of the body + # r: distance between the body and the asteroid + Λ2j_div_r4 = Array{S}(undef, N) # J_2 * R^2 / r^4 + Λ3j_div_r5 = Array{S}(undef, N) # J_3 * R^3 / r^5 + + # Accelerations due to zonal harmonics in body frame + + # Acceleration due to zonal harmonics J_n, n = 2, 3 + F_J_ξ = Array{S}(undef, N) # ξ-axis component + F_J_η = Array{S}(undef, N) # η-axis component + F_J_ζ = Array{S}(undef, N) # ζ-axis component + # Acceleration due to second zonal harmonic J_2 + F_J2_ξ = Array{S}(undef, N) # ξ-axis component + F_J2_η = Array{S}(undef, N) # η-axis component + F_J2_ζ = Array{S}(undef, N) # ζ-axis component + # Acceleration due to third zonal harmonic J_3 + F_J3_ξ = Array{S}(undef, N) # ξ-axis component + F_J3_η = Array{S}(undef, N) # η-axis component + F_J3_ζ = Array{S}(undef, N) # ζ-axis component + + # Unit vectors (ξ, η, ζ) in inertial frame + + # ξ vector + ξx = Array{S}(undef, N) + ξy = Array{S}(undef, N) + ξz = Array{S}(undef, N) + # η vector + ηx = Array{S}(undef, N) + ηy = Array{S}(undef, N) + ηz = Array{S}(undef, N) + # Auxiliaries to compute η vector + ηx1 = Array{S}(undef, N) + ηy1 = Array{S}(undef, N) + ηz1 = Array{S}(undef, N) + ηx2 = Array{S}(undef, N) + ηy2 = Array{S}(undef, N) + ηz2 = Array{S}(undef, N) + # ζ vector + ζx = Array{S}(undef, N) + ζy = Array{S}(undef, N) + ζz = Array{S}(undef, N) + # Auxiliaries to compute ζ vector + ζx1 = Array{S}(undef, N) + ζy1 = Array{S}(undef, N) + ζz1 = Array{S}(undef, N) + ζx2 = Array{S}(undef, N) + ζy2 = Array{S}(undef, N) + ζz2 = Array{S}(undef, N) + + # Full extended-body accelerations + accX = zero_q_1 + accY = zero_q_1 + accZ = zero_q_1 + + # Rotations to and from Earth, Sun and Moon pole-oriented frames + local M_ = Array{S}(undef, 3, 3, N) + local M_ .= zero_q_1 + local M_[:, :, ea] .= t2c_jpl_de430(dsj2k)[:, :] .+ zero_q_1 + + # Fill first 3 elements of dq with velocities + dq[1] = q[4] + dq[2] = q[5] + dq[3] = q[6] + + # Newtonian potential of N bodies + newtonianNb_Potential[N] = zero_q_1 + + #= + Compute point-mass Newtonian accelerations, all bodies + See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + Threads.@threads for i in 1:Nm1 + # Velocity of the i-th body + ui[i] = ss16asteph_t[3(N-1+i)-2] # X-axis component + vi[i] = ss16asteph_t[3(N-1+i)-1] # Y-axis component + wi[i] = ss16asteph_t[3(N-1+i) ] # Z-axis component + + # Position of the i-th body - position of the asteroid + X[i] = ss16asteph_t[3i-2]-q[1] # X-axis component + Y[i] = ss16asteph_t[3i-1]-q[2] # Y-axis component + Z[i] = ss16asteph_t[3i ]-q[3] # Z-axis component + + # Velocity of the i-th body - velocity of the asteroid + U[i] = ui[i]-dq[1] # X-axis component + V[i] = vi[i]-dq[2] # Y-axis component + W[i] = wi[i]-dq[3] # Z-axis component + + # 4 * Velocity of the asteroid - 3 * velocity of the i-th body + _4U_m_3X[i] = (4dq[1]) - (3ui[i]) # X-axis component + _4V_m_3Y[i] = (4dq[2]) - (3vi[i]) # Y-axis component + _4W_m_3Z[i] = (4dq[3]) - (3wi[i]) # Z-axis component + + # Dot product inside the [] in the second term + pn2x = X[i]*_4U_m_3X[i] + pn2y = Y[i]*_4V_m_3Y[i] + pn2z = Z[i]*_4W_m_3Z[i] + + # v_{ij}v_{asteroid} j = x, y, z + UU[i] = ui[i]*dq[1] + VV[i] = vi[i]*dq[2] + WW[i] = wi[i]*dq[3] + + # + vi_dot_vj[i] = ( UU[i]+VV[i] ) + WW[i] + + # Distance between the i-th body and the asteroid + r_p2[i] = ( (X[i]^2)+(Y[i]^2) ) + (Z[i]^2) # r_{i,asteroid}^2 + r_p1d2[i] = sqrt(r_p2[i]) # sqrt(r_p2) <-> r_{i,asteroid} + r_p3d2[i] = r_p2[i]^1.5 # r_p2^1.5 <-> r_{i, asteroid}^3 + r_p7d2[i] = r_p2[i]^3.5 # r_p2^3.5 <-> r_{i, asteroid}^7 + + # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 + newtonianCoeff[i] = μ[i]/r_p3d2[i] + + # Second term without (\mathbf{v}_i - \mathbf{v}_asteroid) + pn2[i] = newtonianCoeff[i]*(( pn2x+pn2y ) + pn2z) + + # Newtonian coefficient * difference between two positions, i.e., + # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 + newton_acc_X[i] = X[i]*newtonianCoeff[i] + newton_acc_Y[i] = Y[i]*newtonianCoeff[i] + newton_acc_Z[i] = Z[i]*newtonianCoeff[i] + + # Newtonian potential of 1 body \mu_i / r_{i, asteroid} + newtonian1b_Potential[i] = μ[i]/r_p1d2[i] + # Third term without newtonian accelerations \mathbf{a}_i + pn3[i] = 3.5newtonian1b_Potential[i] + # Full second term + U_t_pn2[i] = pn2[i]*U[i] # X-axis component + V_t_pn2[i] = pn2[i]*V[i] # Y-axis component + W_t_pn2[i] = pn2[i]*W[i] # Z-axis component + + #= + Extended body accelerations + See equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract + and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + + # J_2 accelerations, if i-th body is flattened + if UJ_interaction[i] + # Rotate from inertial frame to extended-body frame + # Here we are rotating only the Z-coordinate + t31[i] = -X[i]*M_[1,3,i] + t32[i] = -Y[i]*M_[2,3,i] + t33[i] = -Z[i]*M_[3,3,i] + r_sin_ϕ[i] = (t31[i]+t32[i])+t33[i] # z-coordinate in body-fixed frame + + # Trigonometric functions of latitude ϕ and longitude λ in the body-fixed coordinate system + # See equations (165)-(168) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + + sin_ϕ[i] = r_sin_ϕ[i]/r_p1d2[i] # sin(latitude ϕ) + ϕ[i] = asin(sin_ϕ[i]) # Latitude ϕ + cos_ϕ[i] = cos(ϕ[i]) # cos(latitude ϕ) + sin2_ϕ[i] = sin_ϕ[i]^2 # sin(latitude ϕ)^2 + sin3_ϕ[i] = sin_ϕ[i]^3 # sin(latitude ϕ)^3 + + # Legendre polynomials + + # See equations (176) and (177) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + P_2_sin_ϕ[i] = 1.5sin2_ϕ[i] - 0.5 # Second Legendre polynomial P_2(sin ϕ) + ∂P_2_sin_ϕ[i] = 3sin_ϕ[i] # dP_2(sin ϕ)/d(sin ϕ) + P_3_sin_ϕ[i] = (-1.5sin_ϕ[i]) + (2.5sin3_ϕ[i]) # Third Legendre polynomial P_3(sin ϕ) + ∂P_3_sin_ϕ[i] = -1.5 + 7.5sin2_ϕ[i] # dP_3(sin ϕ)/d(sin ϕ) + + # Compute cartesian coordinates of acceleration due to body figure in body frame + + # -J_n * R^n / r^m + # J_n: n-th zonal harmonic coefficient + # R: radius of the body + # r: distance between the body and the asteroid + Λ2j_div_r4[i] = -(Λ2[i]/(r_p2[i]^2)) # J_2 * R^2 / r^4 + Λ3j_div_r5[i] = -(Λ3[i]/(r_p1d2[i]^5)) # J_3 * R^3 / r^5 + + # -cos ϕ P_n' + m_c_ϕ_∂P_2[i] = (-cos_ϕ[i])*∂P_2_sin_ϕ[i] # -cos ϕ P_2' + m_c_ϕ_∂P_3[i] = (-cos_ϕ[i])*∂P_3_sin_ϕ[i] # -cos ϕ P_3' + + # Acceleration due to second zonal harmonic J_2 in body frame + F_J2_ξ[i] = ( Λ2j_div_r4[i]*(3P_2_sin_ϕ[i]) ) # ξ-axis component + # F_J2_η[i] = zero_q_1 # η-axis component + F_J2_ζ[i] = Λ2j_div_r4[i]*m_c_ϕ_∂P_2[i] # ζ-axis component + + # Acceleration due to third zonal harmonic J_3 in body frame + F_J3_ξ[i] = ( Λ3j_div_r5[i]*(4P_3_sin_ϕ[i]) ) # ξ-axis component + #F_J3_η[i] = zero_q_1 # η-axis component + F_J3_ζ[i] = Λ3j_div_r5[i]*m_c_ϕ_∂P_3[i] # ζ-axis component + + # Compute accelerations due to zonal harmonics J_n, n = 2, 3 in body frame + F_J_ξ[i] = F_J2_ξ[i] # + F_J3_ξ[i] # ξ-axis component + # F_J_η[i] = zero_q_1 # η-axis component + F_J_ζ[i] = F_J2_ζ[i] # + F_J3_ζ[i] # ζ-axis component + + # Compute unit vectors (ξ, η, ζ) in inertial frame + + # ξ components in inertial frame + ξx[i] = -X[i]/r_p1d2[i] + ξy[i] = -Y[i]/r_p1d2[i] + ξz[i] = -Z[i]/r_p1d2[i] + + # Compute η = p x ξ + # Auxiliaries + ηx1[i] = M_[2,3,i]*ξz[i] + ηy1[i] = M_[3,3,i]*ξx[i] + ηz1[i] = M_[1,3,i]*ξy[i] + ηx2[i] = M_[3,3,i]*ξy[i] + ηy2[i] = M_[1,3,i]*ξz[i] + ηz2[i] = M_[2,3,i]*ξx[i] + # η components in inertial frame + ηx[i] = ηx1[i] - ηx2[i] + ηy[i] = ηy1[i] - ηy2[i] + ηz[i] = ηz1[i] - ηz2[i] + + # Compute ζ = ξ x η + ζx1[i] = ξy[i]*ηz[i] + ζy1[i] = ξz[i]*ηx[i] + ζz1[i] = ξx[i]*ηy[i] + ζx2[i] = ξz[i]*ηy[i] + ζy2[i] = ξx[i]*ηz[i] + ζz2[i] = ξy[i]*ηx[i] + # ζ components in inertial frame + ζx[i] = ζx1[i] - ζx2[i] + ζy[i] = ζy1[i] - ζy2[i] + ζz[i] = ζz1[i] - ζz2[i] + + # Compute cartesian coordinates of acceleration due to body figure in inertial frame + # Auxiliaries + F_J2_x1[i] = F_J_ξ[i]*ξx[i] + F_J2_y1[i] = F_J_ξ[i]*ξy[i] + F_J2_z1[i] = F_J_ξ[i]*ξz[i] + F_J2_x2[i] = F_J_ζ[i]*ζx[i] + F_J2_y2[i] = F_J_ζ[i]*ζy[i] + F_J2_z2[i] = F_J_ζ[i]*ζz[i] + # Acceleration due to zonal harmonics in inertial frame + F_J2_x[i] = F_J2_x1[i] + F_J2_x2[i] + F_J2_y[i] = F_J2_y1[i] + F_J2_y2[i] + F_J2_z[i] = F_J2_z1[i] + F_J2_z2[i] + end + # Velocity magnitude of the i-th body + v2[i] = ( (ui[i]^2)+(vi[i]^2) ) + (wi[i]^2) + end + # Asteroid velocity magnitude + v2[N] = ( (q[4]^2)+(q[5]^2) ) + (q[6]^2) + + for i in 1:Nm1 + # Newtonian potential of N bodies + # \sum_{i\neq l} \frac{\mu_i}{r_{il}} or + # \sum_{j\neq k} \frac{\mu_j}{r_{jk}} + temp_004 = newtonian1b_Potential[i] + newtonianNb_Potential[N] + newtonianNb_Potential[N] = temp_004 + + # Extended body accelerations + # J_n accelerations, if i-th body is flattened + if UJ_interaction[i] + # Reaction force on i-th body + temp_accX_i[i] = accX - (μ[i]*F_J2_x[i]) + accX = temp_accX_i[i] + temp_accY_i[i] = accY - (μ[i]*F_J2_y[i]) + accY = temp_accY_i[i] + temp_accZ_i[i] = accZ - (μ[i]*F_J2_z[i]) + accZ = temp_accZ_i[i] + end + end + + #= + Post-Newtonian accelerations due to Sun, Moon and planets (Mercury through Neptune) + Post-Newtonian iterative procedure setup and initialization + See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + + # First term + + # 4*\sum term inside {} + _4ϕj[N] = 4newtonianNb_Potential[N] + Threads.@threads for i in 1:10 + # 4*\sum + \sum terms inside {} + ϕi_plus_4ϕj[i] = newtonianNb_Potential_t[i] + _4ϕj[N] + # \dot{s}_j^2 + 2\dot{s}_i^2 - 4 <, > terms inside {} + sj2_plus_2si2_minus_4vivj[i] = ( (2v2[i]) - (4vi_dot_vj[i]) ) + v2[N] + # -4\sum - \sum + \dot{s}_j^2 + 2\dot{s}_i^2 - 4<, > terms inside {} + ϕs_and_vs[i] = sj2_plus_2si2_minus_4vivj[i] - ϕi_plus_4ϕj[i] + # (\mathbf{r}_i - \mathbf{r}_asteroid)\cdot\mathbf{v_i} + Xij_t_Ui = X[i]*ui[i] + Yij_t_Vi = Y[i]*vi[i] + Zij_t_Wi = Z[i]*wi[i] + Rij_dot_Vi = ( Xij_t_Ui+Yij_t_Vi ) + Zij_t_Wi + # The expression below inside the (...)^2 should have a minus sign in front of the + # numerator, but upon squaring it is eliminated, so at the end of the day, it is + # irrelevant ;) + # (\mathbf{r}_i - \mathbf{r}_asteroid)\cdot\mathbf{v_i} / r_{i, asteroid} + pn1t7 = (Rij_dot_Vi^2)/r_p2[i] + # Everything inside the {} except for the first and last terms + pn1t2_7 = ϕs_and_vs[i] - (1.5pn1t7) + # Everything inside the {} except for the last term + pn1t1_7[i] = c_p2 + pn1t2_7 + + # Last term inside the {} + pNX_t_X[i] = acceph_t[3i-2]*X[i] # X-axis component + pNY_t_Y[i] = acceph_t[3i-1]*Y[i] # Y-axis component + pNZ_t_Z[i] = acceph_t[3i ]*Z[i] # Z-axis component + + # Everything inside the {} in the first term + pn1[i] = ( pn1t1_7[i] + (0.5*( (pNX_t_X[i]+pNY_t_Y[i]) + pNZ_t_Z[i] )) ) + + # Full first term + X_t_pn1[i] = newton_acc_X[i]*pn1[i] # X-axis component + Y_t_pn1[i] = newton_acc_Y[i]*pn1[i] # Y-axis component + Z_t_pn1[i] = newton_acc_Z[i]*pn1[i] # Z-axis component + + # Full third term + pNX_t_pn3[i] = acceph_t[3i-2]*pn3[i] # X-axis component + pNY_t_pn3[i] = acceph_t[3i-1]*pn3[i] # Y-axis component + pNZ_t_pn3[i] = acceph_t[3i ]*pn3[i] # Z-axis component + end + # Temporary post-Newtonian accelerations (planets) + for i in 1:10 + termpnx = ( X_t_pn1[i] + (U_t_pn2[i]+pNX_t_pn3[i]) ) # X-axis component + sumpnx = pntempX + termpnx + pntempX = sumpnx + termpny = ( Y_t_pn1[i] + (V_t_pn2[i]+pNY_t_pn3[i]) ) # Y-axis component + sumpny = pntempY + termpny + pntempY = sumpny + termpnz = ( Z_t_pn1[i] + (W_t_pn2[i]+pNZ_t_pn3[i]) ) # Z-axis component + sumpnz = pntempZ + termpnz + pntempZ = sumpnz + end + # Compute Newtonian accelerations due to Pluto and 16 asteroid perturbers + Threads.@threads for i in 11:Nm1 + # Full first term + X_t_pn1[i] = c_p2*newton_acc_X[i] + Y_t_pn1[i] = c_p2*newton_acc_Y[i] + Z_t_pn1[i] = c_p2*newton_acc_Z[i] + end + # Temporary post-Newtonian accelerations (Pluto + 16 asteroid perturbers) + for i in 11:Nm1 + termpnx = X_t_pn1[i] # X-axis component + sumpnx = pntempX + termpnx + pntempX = sumpnx + termpny = Y_t_pn1[i] # Y-axis component + sumpny = pntempY + termpny + pntempY = sumpny + termpnz = Z_t_pn1[i] # Z-axis component + sumpnz = pntempZ + termpnz + pntempZ = sumpnz + end + # Post-Newtonian acelerations + postNewtonX = pntempX*c_m2 # X-axis component + postNewtonY = pntempY*c_m2 # Y-axis component + postNewtonZ = pntempZ*c_m2 # Z-axis component + + # Fill dq[4:6] with accelerations + # Post-Newton point mass + Extended body + dq[4] = postNewtonX + accX + dq[5] = postNewtonY + accY + dq[6] = postNewtonZ + accZ + + nothing end \ No newline at end of file diff --git a/src/propagation/jetcoeffs.jl b/src/propagation/jetcoeffs.jl old mode 100644 new mode 100755 index f4990048..1d9ad5dc --- a/src/propagation/jetcoeffs.jl +++ b/src/propagation/jetcoeffs.jl @@ -1,2993 +1,2993 @@ -# DO NOT MODIFY THIS FILE BY HAND - -# Methods of `TaylorIntegration._allocate_jetcoeffs!` and `TaylorIntegration.jetcoeffs!` generated by @taylorize for the functions -# in src/propagation/asteroid_dynamical_models.jl - -# To update the functions do the following: -# 1.- Update the corresponding function in src/propagation/asteroid_dynamical_models.jl -# 2.- using TaylorIntegration -# 2.- ex = :(paste here the modified function) -# 3.- x, y = TaylorIntegration._make_parsed_coeffs(ex) -# 4.- Paste x and y in this file - -# TaylorIntegration._allocate_jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_ng_eph_threads! -function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params) where {_T <: Real, _S <: Number, _N} - order = t.order - local jd0 = params[4] - local dsj2k = t + (jd0 - JD_J2000) - local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) - local acceph_t = evaleph(params[2], dsj2k, q[1]) - local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) - local S = eltype(q) - local UJ_interaction = params[5] - local N = params[6] - local Nm1 = N - 1 - local μ = params[7] - local zero_q_1 = auxzero(q[1]) - X = Array{S}(undef, N) - Y = Array{S}(undef, N) - Z = Array{S}(undef, N) - r_p2 = Array{S}(undef, N) - r_p1d2 = Array{S}(undef, N) - r_p3d2 = Array{S}(undef, N) - r_p7d2 = Array{S}(undef, N) - newtonianCoeff = Array{S}(undef, N) - ui = Array{S}(undef, N - 1) - vi = Array{S}(undef, N - 1) - wi = Array{S}(undef, N - 1) - U = Array{S}(undef, N) - V = Array{S}(undef, N) - W = Array{S}(undef, N) - _4U_m_3X = Array{S}(undef, N) - _4V_m_3Y = Array{S}(undef, N) - _4W_m_3Z = Array{S}(undef, N) - UU = Array{S}(undef, N) - VV = Array{S}(undef, N) - WW = Array{S}(undef, N) - newtonian1b_Potential = Array{S}(undef, N) - newtonianNb_Potential = Array{S}(undef, N) - newton_acc_X = Array{S}(undef, N) - newton_acc_Y = Array{S}(undef, N) - newton_acc_Z = Array{S}(undef, N) - v2 = Array{S}(undef, N) - vi_dot_vj = Array{S}(undef, N) - pn2 = Array{S}(undef, N) - U_t_pn2 = Array{S}(undef, N) - V_t_pn2 = Array{S}(undef, N) - W_t_pn2 = Array{S}(undef, N) - pn3 = Array{S}(undef, N) - pNX_t_pn3 = Array{S}(undef, N) - pNY_t_pn3 = Array{S}(undef, N) - pNZ_t_pn3 = Array{S}(undef, N) - _4ϕj = Array{S}(undef, N) - ϕi_plus_4ϕj = Array{S}(undef, N) - sj2_plus_2si2_minus_4vivj = Array{S}(undef, N) - ϕs_and_vs = Array{S}(undef, N) - pn1t1_7 = Array{S}(undef, N) - pNX_t_X = Array{S}(undef, N) - pNY_t_Y = Array{S}(undef, N) - pNZ_t_Z = Array{S}(undef, N) - pn1 = Array{S}(undef, N) - X_t_pn1 = Array{S}(undef, N) - Y_t_pn1 = Array{S}(undef, N) - Z_t_pn1 = Array{S}(undef, N) - pntempX = Taylor1(identity(constant_term(zero_q_1)), order) - pntempY = Taylor1(identity(constant_term(zero_q_1)), order) - pntempZ = Taylor1(identity(constant_term(zero_q_1)), order) - t31 = Array{S}(undef, N) - t32 = Array{S}(undef, N) - t33 = Array{S}(undef, N) - r_sin_ϕ = Array{S}(undef, N) - sin_ϕ = Array{S}(undef, N) - ϕ = Array{S}(undef, N) - cos_ϕ = Array{S}(undef, N) - sin2_ϕ = Array{S}(undef, N) - sin3_ϕ = Array{S}(undef, N) - sin4_ϕ = Array{S}(undef, N) - F_J2_x = Array{S}(undef, N) - F_J2_y = Array{S}(undef, N) - F_J2_z = Array{S}(undef, N) - F_J2_x1 = Array{S}(undef, N) - F_J2_y1 = Array{S}(undef, N) - F_J2_z1 = Array{S}(undef, N) - F_J2_x2 = Array{S}(undef, N) - F_J2_y2 = Array{S}(undef, N) - F_J2_z2 = Array{S}(undef, N) - temp_accX_i = Array{S}(undef, N) - temp_accY_i = Array{S}(undef, N) - temp_accZ_i = Array{S}(undef, N) - P_2_sin_ϕ = Array{S}(undef, N) - ∂P_2_sin_ϕ = Array{S}(undef, N) - P_3_sin_ϕ = Array{S}(undef, N) - ∂P_3_sin_ϕ = Array{S}(undef, N) - m_c_ϕ_∂P_2 = Array{S}(undef, N) - m_c_ϕ_∂P_3 = Array{S}(undef, N) - Λ2j_div_r4 = Array{S}(undef, N) - Λ3j_div_r5 = Array{S}(undef, N) - F_J_ξ = Array{S}(undef, N) - F_J_η = Array{S}(undef, N) - F_J_ζ = Array{S}(undef, N) - F_J2_ξ = Array{S}(undef, N) - F_J2_η = Array{S}(undef, N) - F_J2_ζ = Array{S}(undef, N) - F_J3_ξ = Array{S}(undef, N) - F_J3_η = Array{S}(undef, N) - F_J3_ζ = Array{S}(undef, N) - ξx = Array{S}(undef, N) - ξy = Array{S}(undef, N) - ξz = Array{S}(undef, N) - ηx = Array{S}(undef, N) - ηy = Array{S}(undef, N) - ηz = Array{S}(undef, N) - ηx1 = Array{S}(undef, N) - ηy1 = Array{S}(undef, N) - ηz1 = Array{S}(undef, N) - ηx2 = Array{S}(undef, N) - ηy2 = Array{S}(undef, N) - ηz2 = Array{S}(undef, N) - ζx = Array{S}(undef, N) - ζy = Array{S}(undef, N) - ζz = Array{S}(undef, N) - ζx1 = Array{S}(undef, N) - ζy1 = Array{S}(undef, N) - ζz1 = Array{S}(undef, N) - ζx2 = Array{S}(undef, N) - ζy2 = Array{S}(undef, N) - ζz2 = Array{S}(undef, N) - accX = Taylor1(identity(constant_term(zero_q_1)), order) - accY = Taylor1(identity(constant_term(zero_q_1)), order) - accZ = Taylor1(identity(constant_term(zero_q_1)), order) - local M_ = Array{S}(undef, 3, 3, N) - local M_ .= zero_q_1 - local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 - dq[1] = Taylor1(identity(constant_term(q[4])), order) - dq[2] = Taylor1(identity(constant_term(q[5])), order) - dq[3] = Taylor1(identity(constant_term(q[6])), order) - newtonianNb_Potential[N] = Taylor1(identity(constant_term(zero_q_1)), order) - tmp687 = Array{Taylor1{_S}}(undef, size(dq)) - tmp687 .= Taylor1(zero(constant_term(q[1])), order) - tmp689 = Array{Taylor1{_S}}(undef, size(ui)) - tmp689 .= Taylor1(zero(constant_term(q[1])), order) - tmp692 = Array{Taylor1{_S}}(undef, size(dq)) - tmp692 .= Taylor1(zero(constant_term(q[1])), order) - tmp694 = Array{Taylor1{_S}}(undef, size(vi)) - tmp694 .= Taylor1(zero(constant_term(q[1])), order) - tmp697 = Array{Taylor1{_S}}(undef, size(dq)) - tmp697 .= Taylor1(zero(constant_term(q[1])), order) - tmp699 = Array{Taylor1{_S}}(undef, size(wi)) - tmp699 .= Taylor1(zero(constant_term(q[1])), order) - pn2x = Array{Taylor1{_S}}(undef, size(X)) - pn2x .= Taylor1(zero(constant_term(q[1])), order) - pn2y = Array{Taylor1{_S}}(undef, size(Y)) - pn2y .= Taylor1(zero(constant_term(q[1])), order) - pn2z = Array{Taylor1{_S}}(undef, size(Z)) - pn2z .= Taylor1(zero(constant_term(q[1])), order) - tmp707 = Array{Taylor1{_S}}(undef, size(UU)) - tmp707 .= Taylor1(zero(constant_term(q[1])), order) - tmp710 = Array{Taylor1{_S}}(undef, size(X)) - tmp710 .= Taylor1(zero(constant_term(q[1])), order) - tmp712 = Array{Taylor1{_S}}(undef, size(Y)) - tmp712 .= Taylor1(zero(constant_term(q[1])), order) - tmp713 = Array{Taylor1{_S}}(undef, size(tmp710)) - tmp713 .= Taylor1(zero(constant_term(q[1])), order) - tmp715 = Array{Taylor1{_S}}(undef, size(Z)) - tmp715 .= Taylor1(zero(constant_term(q[1])), order) - tmp723 = Array{Taylor1{_S}}(undef, size(pn2x)) - tmp723 .= Taylor1(zero(constant_term(q[1])), order) - tmp724 = Array{Taylor1{_S}}(undef, size(tmp723)) - tmp724 .= Taylor1(zero(constant_term(q[1])), order) - tmp819 = Array{Taylor1{_S}}(undef, size(ui)) - tmp819 .= Taylor1(zero(constant_term(q[1])), order) - tmp821 = Array{Taylor1{_S}}(undef, size(vi)) - tmp821 .= Taylor1(zero(constant_term(q[1])), order) - tmp822 = Array{Taylor1{_S}}(undef, size(tmp819)) - tmp822 .= Taylor1(zero(constant_term(q[1])), order) - tmp824 = Array{Taylor1{_S}}(undef, size(wi)) - tmp824 .= Taylor1(zero(constant_term(q[1])), order) - tmp735 = Array{Taylor1{_S}}(undef, size(X)) - tmp735 .= Taylor1(zero(constant_term(q[1])), order) - tmp737 = Array{Taylor1{_S}}(undef, size(Y)) - tmp737 .= Taylor1(zero(constant_term(q[1])), order) - tmp739 = Array{Taylor1{_S}}(undef, size(Z)) - tmp739 .= Taylor1(zero(constant_term(q[1])), order) - tmp741 = Array{Taylor1{_S}}(undef, size(t31)) - tmp741 .= Taylor1(zero(constant_term(q[1])), order) - tmp948 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp948 .= Taylor1(zero(constant_term(q[1])), order) - tmp949 = Array{Taylor1{_S}}(undef, size(ϕ)) - tmp949 .= Taylor1(zero(constant_term(q[1])), order) - tmp751 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp751 .= Taylor1(zero(constant_term(q[1])), order) - tmp757 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp757 .= Taylor1(zero(constant_term(q[1])), order) - tmp759 = Array{Taylor1{_S}}(undef, size(sin3_ϕ)) - tmp759 .= Taylor1(zero(constant_term(q[1])), order) - tmp763 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp763 .= Taylor1(zero(constant_term(q[1])), order) - tmp766 = Array{Taylor1{_S}}(undef, size(r_p2)) - tmp766 .= Taylor1(zero(constant_term(q[1])), order) - tmp767 = Array{Taylor1{_S}}(undef, size(Λ2)) - tmp767 .= Taylor1(zero(constant_term(q[1])), order) - tmp770 = Array{Taylor1{_S}}(undef, size(r_p1d2)) - tmp770 .= Taylor1(zero(constant_term(q[1])), order) - tmp771 = Array{Taylor1{_S}}(undef, size(Λ3)) - tmp771 .= Taylor1(zero(constant_term(q[1])), order) - tmp773 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp773 .= Taylor1(zero(constant_term(q[1])), order) - tmp775 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp775 .= Taylor1(zero(constant_term(q[1])), order) - tmp778 = Array{Taylor1{_S}}(undef, size(Λ2j_div_r4)) - tmp778 .= Taylor1(zero(constant_term(q[1])), order) - tmp782 = Array{Taylor1{_S}}(undef, size(Λ3j_div_r5)) - tmp782 .= Taylor1(zero(constant_term(q[1])), order) - tmp785 = Array{Taylor1{_S}}(undef, size(X)) - tmp785 .= Taylor1(zero(constant_term(q[1])), order) - tmp787 = Array{Taylor1{_S}}(undef, size(Y)) - tmp787 .= Taylor1(zero(constant_term(q[1])), order) - tmp789 = Array{Taylor1{_S}}(undef, size(Z)) - tmp789 .= Taylor1(zero(constant_term(q[1])), order) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 - ui[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])), order) - vi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])), order) - wi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])), order) - X[i] = Taylor1(constant_term(ss16asteph_t[3i - 2]) - constant_term(q[1]), order) - Y[i] = Taylor1(constant_term(ss16asteph_t[3i - 1]) - constant_term(q[2]), order) - Z[i] = Taylor1(constant_term(ss16asteph_t[3i]) - constant_term(q[3]), order) - U[i] = Taylor1(constant_term(ui[i]) - constant_term(dq[1]), order) - V[i] = Taylor1(constant_term(vi[i]) - constant_term(dq[2]), order) - W[i] = Taylor1(constant_term(wi[i]) - constant_term(dq[3]), order) - tmp687[1] = Taylor1(constant_term(4) * constant_term(dq[1]), order) - tmp689[i] = Taylor1(constant_term(3) * constant_term(ui[i]), order) - _4U_m_3X[i] = Taylor1(constant_term(tmp687[1]) - constant_term(tmp689[i]), order) - tmp692[2] = Taylor1(constant_term(4) * constant_term(dq[2]), order) - tmp694[i] = Taylor1(constant_term(3) * constant_term(vi[i]), order) - _4V_m_3Y[i] = Taylor1(constant_term(tmp692[2]) - constant_term(tmp694[i]), order) - tmp697[3] = Taylor1(constant_term(4) * constant_term(dq[3]), order) - tmp699[i] = Taylor1(constant_term(3) * constant_term(wi[i]), order) - _4W_m_3Z[i] = Taylor1(constant_term(tmp697[3]) - constant_term(tmp699[i]), order) - pn2x[i] = Taylor1(constant_term(X[i]) * constant_term(_4U_m_3X[i]), order) - pn2y[i] = Taylor1(constant_term(Y[i]) * constant_term(_4V_m_3Y[i]), order) - pn2z[i] = Taylor1(constant_term(Z[i]) * constant_term(_4W_m_3Z[i]), order) - UU[i] = Taylor1(constant_term(ui[i]) * constant_term(dq[1]), order) - VV[i] = Taylor1(constant_term(vi[i]) * constant_term(dq[2]), order) - WW[i] = Taylor1(constant_term(wi[i]) * constant_term(dq[3]), order) - tmp707[i] = Taylor1(constant_term(UU[i]) + constant_term(VV[i]), order) - vi_dot_vj[i] = Taylor1(constant_term(tmp707[i]) + constant_term(WW[i]), order) - tmp710[i] = Taylor1(constant_term(X[i]) ^ float(constant_term(2)), order) - tmp712[i] = Taylor1(constant_term(Y[i]) ^ float(constant_term(2)), order) - tmp713[i] = Taylor1(constant_term(tmp710[i]) + constant_term(tmp712[i]), order) - tmp715[i] = Taylor1(constant_term(Z[i]) ^ float(constant_term(2)), order) - r_p2[i] = Taylor1(constant_term(tmp713[i]) + constant_term(tmp715[i]), order) - r_p1d2[i] = Taylor1(sqrt(constant_term(r_p2[i])), order) - r_p3d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(1.5)), order) - r_p7d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(3.5)), order) - newtonianCoeff[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p3d2[i]), order) - tmp723[i] = Taylor1(constant_term(pn2x[i]) + constant_term(pn2y[i]), order) - tmp724[i] = Taylor1(constant_term(tmp723[i]) + constant_term(pn2z[i]), order) - pn2[i] = Taylor1(constant_term(newtonianCoeff[i]) * constant_term(tmp724[i]), order) - newton_acc_X[i] = Taylor1(constant_term(X[i]) * constant_term(newtonianCoeff[i]), order) - newton_acc_Y[i] = Taylor1(constant_term(Y[i]) * constant_term(newtonianCoeff[i]), order) - newton_acc_Z[i] = Taylor1(constant_term(Z[i]) * constant_term(newtonianCoeff[i]), order) - newtonian1b_Potential[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p1d2[i]), order) - pn3[i] = Taylor1(constant_term(3.5) * constant_term(newtonian1b_Potential[i]), order) - U_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(U[i]), order) - V_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(V[i]), order) - W_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(W[i]), order) - if UJ_interaction[i] - tmp735[i] = Taylor1(-(constant_term(X[i])), order) - t31[i] = Taylor1(constant_term(tmp735[i]) * constant_term(M_[1, 3, i]), order) - tmp737[i] = Taylor1(-(constant_term(Y[i])), order) - t32[i] = Taylor1(constant_term(tmp737[i]) * constant_term(M_[2, 3, i]), order) - tmp739[i] = Taylor1(-(constant_term(Z[i])), order) - t33[i] = Taylor1(constant_term(tmp739[i]) * constant_term(M_[3, 3, i]), order) - tmp741[i] = Taylor1(constant_term(t31[i]) + constant_term(t32[i]), order) - r_sin_ϕ[i] = Taylor1(constant_term(tmp741[i]) + constant_term(t33[i]), order) - sin_ϕ[i] = Taylor1(constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]), order) - ϕ[i] = Taylor1(asin(constant_term(sin_ϕ[i])), order) - tmp948[i] = Taylor1(sqrt(1 - constant_term(sin_ϕ[i]) ^ 2), order) - cos_ϕ[i] = Taylor1(cos(constant_term(ϕ[i])), order) - tmp949[i] = Taylor1(sin(constant_term(ϕ[i])), order) - sin2_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(2)), order) - sin3_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(3)), order) - tmp751[i] = Taylor1(constant_term(1.5) * constant_term(sin2_ϕ[i]), order) - P_2_sin_ϕ[i] = Taylor1(constant_term(tmp751[i]) - constant_term(0.5), order) - ∂P_2_sin_ϕ[i] = Taylor1(constant_term(3) * constant_term(sin_ϕ[i]), order) - tmp757[i] = Taylor1(constant_term(-1.5) * constant_term(sin_ϕ[i]), order) - tmp759[i] = Taylor1(constant_term(2.5) * constant_term(sin3_ϕ[i]), order) - P_3_sin_ϕ[i] = Taylor1(constant_term(tmp757[i]) + constant_term(tmp759[i]), order) - tmp763[i] = Taylor1(constant_term(7.5) * constant_term(sin2_ϕ[i]), order) - ∂P_3_sin_ϕ[i] = Taylor1(constant_term(-1.5) + constant_term(tmp763[i]), order) - tmp766[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(2)), order) - tmp767[i] = Taylor1(constant_term(Λ2[i]) / constant_term(tmp766[i]), order) - Λ2j_div_r4[i] = Taylor1(-(constant_term(tmp767[i])), order) - tmp770[i] = Taylor1(constant_term(r_p1d2[i]) ^ float(constant_term(5)), order) - tmp771[i] = Taylor1(constant_term(Λ3[i]) / constant_term(tmp770[i]), order) - Λ3j_div_r5[i] = Taylor1(-(constant_term(tmp771[i])), order) - tmp773[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) - m_c_ϕ_∂P_2[i] = Taylor1(constant_term(tmp773[i]) * constant_term(∂P_2_sin_ϕ[i]), order) - tmp775[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) - m_c_ϕ_∂P_3[i] = Taylor1(constant_term(tmp775[i]) * constant_term(∂P_3_sin_ϕ[i]), order) - tmp778[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(3), order) - F_J2_ξ[i] = Taylor1(constant_term(tmp778[i]) * constant_term(P_2_sin_ϕ[i]), order) - F_J2_ζ[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]), order) - tmp782[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(4), order) - F_J3_ξ[i] = Taylor1(constant_term(tmp782[i]) * constant_term(P_3_sin_ϕ[i]), order) - F_J3_ζ[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]), order) - F_J_ξ[i] = Taylor1(identity(constant_term(F_J2_ξ[i])), order) - F_J_ζ[i] = Taylor1(identity(constant_term(F_J2_ζ[i])), order) - tmp785[i] = Taylor1(-(constant_term(X[i])), order) - ξx[i] = Taylor1(constant_term(tmp785[i]) / constant_term(r_p1d2[i]), order) - tmp787[i] = Taylor1(-(constant_term(Y[i])), order) - ξy[i] = Taylor1(constant_term(tmp787[i]) / constant_term(r_p1d2[i]), order) - tmp789[i] = Taylor1(-(constant_term(Z[i])), order) - ξz[i] = Taylor1(constant_term(tmp789[i]) / constant_term(r_p1d2[i]), order) - ηx1[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξz[i]), order) - ηy1[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξx[i]), order) - ηz1[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξy[i]), order) - ηx2[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξy[i]), order) - ηy2[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξz[i]), order) - ηz2[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξx[i]), order) - ηx[i] = Taylor1(constant_term(ηx1[i]) - constant_term(ηx2[i]), order) - ηy[i] = Taylor1(constant_term(ηy1[i]) - constant_term(ηy2[i]), order) - ηz[i] = Taylor1(constant_term(ηz1[i]) - constant_term(ηz2[i]), order) - ζx1[i] = Taylor1(constant_term(ξy[i]) * constant_term(ηz[i]), order) - ζy1[i] = Taylor1(constant_term(ξz[i]) * constant_term(ηx[i]), order) - ζz1[i] = Taylor1(constant_term(ξx[i]) * constant_term(ηy[i]), order) - ζx2[i] = Taylor1(constant_term(ξz[i]) * constant_term(ηy[i]), order) - ζy2[i] = Taylor1(constant_term(ξx[i]) * constant_term(ηz[i]), order) - ζz2[i] = Taylor1(constant_term(ξy[i]) * constant_term(ηx[i]), order) - ζx[i] = Taylor1(constant_term(ζx1[i]) - constant_term(ζx2[i]), order) - ζy[i] = Taylor1(constant_term(ζy1[i]) - constant_term(ζy2[i]), order) - ζz[i] = Taylor1(constant_term(ζz1[i]) - constant_term(ζz2[i]), order) - F_J2_x1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξx[i]), order) - F_J2_y1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξy[i]), order) - F_J2_z1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξz[i]), order) - F_J2_x2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζx[i]), order) - F_J2_y2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζy[i]), order) - F_J2_z2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζz[i]), order) - F_J2_x[i] = Taylor1(constant_term(F_J2_x1[i]) + constant_term(F_J2_x2[i]), order) - F_J2_y[i] = Taylor1(constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]), order) - F_J2_z[i] = Taylor1(constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]), order) - end - tmp819[i] = Taylor1(constant_term(ui[i]) ^ float(constant_term(2)), order) - tmp821[i] = Taylor1(constant_term(vi[i]) ^ float(constant_term(2)), order) - tmp822[i] = Taylor1(constant_term(tmp819[i]) + constant_term(tmp821[i]), order) - tmp824[i] = Taylor1(constant_term(wi[i]) ^ float(constant_term(2)), order) - v2[i] = Taylor1(constant_term(tmp822[i]) + constant_term(tmp824[i]), order) - end - tmp827 = Taylor1(constant_term(q[4]) ^ float(constant_term(2)), order) - tmp829 = Taylor1(constant_term(q[5]) ^ float(constant_term(2)), order) - tmp830 = Taylor1(constant_term(tmp827) + constant_term(tmp829), order) - tmp832 = Taylor1(constant_term(q[6]) ^ float(constant_term(2)), order) - v2[N] = Taylor1(constant_term(tmp830) + constant_term(tmp832), order) - temp_004 = Array{Taylor1{_S}}(undef, size(newtonian1b_Potential)) - temp_004 .= Taylor1(zero(constant_term(q[1])), order) - tmp835 = Array{Taylor1{_S}}(undef, size(μ)) - tmp835 .= Taylor1(zero(constant_term(q[1])), order) - tmp837 = Array{Taylor1{_S}}(undef, size(μ)) - tmp837 .= Taylor1(zero(constant_term(q[1])), order) - tmp839 = Array{Taylor1{_S}}(undef, size(μ)) - tmp839 .= Taylor1(zero(constant_term(q[1])), order) - for i = 1:Nm1 - temp_004[i] = Taylor1(constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]), order) - newtonianNb_Potential[N] = Taylor1(identity(constant_term(temp_004[i])), order) - if UJ_interaction[i] - tmp835[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_x[i]), order) - temp_accX_i[i] = Taylor1(constant_term(accX) - constant_term(tmp835[i]), order) - accX = Taylor1(identity(constant_term(temp_accX_i[i])), order) - tmp837[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_y[i]), order) - temp_accY_i[i] = Taylor1(constant_term(accY) - constant_term(tmp837[i]), order) - accY = Taylor1(identity(constant_term(temp_accY_i[i])), order) - tmp839[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_z[i]), order) - temp_accZ_i[i] = Taylor1(constant_term(accZ) - constant_term(tmp839[i]), order) - accZ = Taylor1(identity(constant_term(temp_accZ_i[i])), order) - end - end - _4ϕj[N] = Taylor1(constant_term(4) * constant_term(newtonianNb_Potential[N]), order) - tmp845 = Array{Taylor1{_S}}(undef, size(v2)) - tmp845 .= Taylor1(zero(constant_term(q[1])), order) - tmp847 = Array{Taylor1{_S}}(undef, size(vi_dot_vj)) - tmp847 .= Taylor1(zero(constant_term(q[1])), order) - tmp848 = Array{Taylor1{_S}}(undef, size(tmp845)) - tmp848 .= Taylor1(zero(constant_term(q[1])), order) - Xij_t_Ui = Array{Taylor1{_S}}(undef, size(X)) - Xij_t_Ui .= Taylor1(zero(constant_term(q[1])), order) - Yij_t_Vi = Array{Taylor1{_S}}(undef, size(Y)) - Yij_t_Vi .= Taylor1(zero(constant_term(q[1])), order) - Zij_t_Wi = Array{Taylor1{_S}}(undef, size(Z)) - Zij_t_Wi .= Taylor1(zero(constant_term(q[1])), order) - tmp854 = Array{Taylor1{_S}}(undef, size(Xij_t_Ui)) - tmp854 .= Taylor1(zero(constant_term(q[1])), order) - Rij_dot_Vi = Array{Taylor1{_S}}(undef, size(tmp854)) - Rij_dot_Vi .= Taylor1(zero(constant_term(q[1])), order) - tmp857 = Array{Taylor1{_S}}(undef, size(Rij_dot_Vi)) - tmp857 .= Taylor1(zero(constant_term(q[1])), order) - pn1t7 = Array{Taylor1{_S}}(undef, size(tmp857)) - pn1t7 .= Taylor1(zero(constant_term(q[1])), order) - tmp860 = Array{Taylor1{_S}}(undef, size(pn1t7)) - tmp860 .= Taylor1(zero(constant_term(q[1])), order) - pn1t2_7 = Array{Taylor1{_S}}(undef, size(ϕs_and_vs)) - pn1t2_7 .= Taylor1(zero(constant_term(q[1])), order) - tmp867 = Array{Taylor1{_S}}(undef, size(pNX_t_X)) - tmp867 .= Taylor1(zero(constant_term(q[1])), order) - tmp868 = Array{Taylor1{_S}}(undef, size(tmp867)) - tmp868 .= Taylor1(zero(constant_term(q[1])), order) - tmp869 = Array{Taylor1{_S}}(undef, size(tmp868)) - tmp869 .= Taylor1(zero(constant_term(q[1])), order) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 - ϕi_plus_4ϕj[i] = Taylor1(constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]), order) - tmp845[i] = Taylor1(constant_term(2) * constant_term(v2[i]), order) - tmp847[i] = Taylor1(constant_term(4) * constant_term(vi_dot_vj[i]), order) - tmp848[i] = Taylor1(constant_term(tmp845[i]) - constant_term(tmp847[i]), order) - sj2_plus_2si2_minus_4vivj[i] = Taylor1(constant_term(tmp848[i]) + constant_term(v2[N]), order) - ϕs_and_vs[i] = Taylor1(constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]), order) - Xij_t_Ui[i] = Taylor1(constant_term(X[i]) * constant_term(ui[i]), order) - Yij_t_Vi[i] = Taylor1(constant_term(Y[i]) * constant_term(vi[i]), order) - Zij_t_Wi[i] = Taylor1(constant_term(Z[i]) * constant_term(wi[i]), order) - tmp854[i] = Taylor1(constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]), order) - Rij_dot_Vi[i] = Taylor1(constant_term(tmp854[i]) + constant_term(Zij_t_Wi[i]), order) - tmp857[i] = Taylor1(constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)), order) - pn1t7[i] = Taylor1(constant_term(tmp857[i]) / constant_term(r_p2[i]), order) - tmp860[i] = Taylor1(constant_term(1.5) * constant_term(pn1t7[i]), order) - pn1t2_7[i] = Taylor1(constant_term(ϕs_and_vs[i]) - constant_term(tmp860[i]), order) - pn1t1_7[i] = Taylor1(constant_term(c_p2) + constant_term(pn1t2_7[i]), order) - pNX_t_X[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(X[i]), order) - pNY_t_Y[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(Y[i]), order) - pNZ_t_Z[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(Z[i]), order) - tmp867[i] = Taylor1(constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]), order) - tmp868[i] = Taylor1(constant_term(tmp867[i]) + constant_term(pNZ_t_Z[i]), order) - tmp869[i] = Taylor1(constant_term(0.5) * constant_term(tmp868[i]), order) - pn1[i] = Taylor1(constant_term(pn1t1_7[i]) + constant_term(tmp869[i]), order) - X_t_pn1[i] = Taylor1(constant_term(newton_acc_X[i]) * constant_term(pn1[i]), order) - Y_t_pn1[i] = Taylor1(constant_term(newton_acc_Y[i]) * constant_term(pn1[i]), order) - Z_t_pn1[i] = Taylor1(constant_term(newton_acc_Z[i]) * constant_term(pn1[i]), order) - pNX_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(pn3[i]), order) - pNY_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]), order) - pNZ_t_pn3[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(pn3[i]), order) - end - tmp877 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) - tmp877 .= Taylor1(zero(constant_term(q[1])), order) - termpnx = Array{Taylor1{_S}}(undef, size(X_t_pn1)) - termpnx .= Taylor1(zero(constant_term(q[1])), order) - sumpnx = Array{Taylor1{_S}}(undef, size(termpnx)) - sumpnx .= Taylor1(zero(constant_term(q[1])), order) - tmp880 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) - tmp880 .= Taylor1(zero(constant_term(q[1])), order) - termpny = Array{Taylor1{_S}}(undef, size(Y_t_pn1)) - termpny .= Taylor1(zero(constant_term(q[1])), order) - sumpny = Array{Taylor1{_S}}(undef, size(termpny)) - sumpny .= Taylor1(zero(constant_term(q[1])), order) - tmp883 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) - tmp883 .= Taylor1(zero(constant_term(q[1])), order) - termpnz = Array{Taylor1{_S}}(undef, size(Z_t_pn1)) - termpnz .= Taylor1(zero(constant_term(q[1])), order) - sumpnz = Array{Taylor1{_S}}(undef, size(termpnz)) - sumpnz .= Taylor1(zero(constant_term(q[1])), order) - for i = 1:10 - tmp877[i] = Taylor1(constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]), order) - termpnx[i] = Taylor1(constant_term(X_t_pn1[i]) + constant_term(tmp877[i]), order) - sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) - pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) - tmp880[i] = Taylor1(constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]), order) - termpny[i] = Taylor1(constant_term(Y_t_pn1[i]) + constant_term(tmp880[i]), order) - sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) - pntempY = Taylor1(identity(constant_term(sumpny[i])), order) - tmp883[i] = Taylor1(constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]), order) - termpnz[i] = Taylor1(constant_term(Z_t_pn1[i]) + constant_term(tmp883[i]), order) - sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) - pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) - end - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 - X_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_X[i]), order) - Y_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Y[i]), order) - Z_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Z[i]), order) - end - for i = 11:Nm1 - termpnx[i] = Taylor1(identity(constant_term(X_t_pn1[i])), order) - sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) - pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) - termpny[i] = Taylor1(identity(constant_term(Y_t_pn1[i])), order) - sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) - pntempY = Taylor1(identity(constant_term(sumpny[i])), order) - termpnz[i] = Taylor1(identity(constant_term(Z_t_pn1[i])), order) - sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) - pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) - end - postNewtonX = Taylor1(constant_term(pntempX) * constant_term(c_m2), order) - postNewtonY = Taylor1(constant_term(pntempY) * constant_term(c_m2), order) - postNewtonZ = Taylor1(constant_term(pntempZ) * constant_term(c_m2), order) - tmp895 = Taylor1(constant_term(Y[1]) * constant_term(W[1]), order) - tmp896 = Taylor1(constant_term(Z[1]) * constant_term(V[1]), order) - hx = Taylor1(constant_term(tmp895) - constant_term(tmp896), order) - tmp898 = Taylor1(constant_term(Z[1]) * constant_term(U[1]), order) - tmp899 = Taylor1(constant_term(X[1]) * constant_term(W[1]), order) - hy = Taylor1(constant_term(tmp898) - constant_term(tmp899), order) - tmp901 = Taylor1(constant_term(X[1]) * constant_term(V[1]), order) - tmp902 = Taylor1(constant_term(Y[1]) * constant_term(U[1]), order) - hz = Taylor1(constant_term(tmp901) - constant_term(tmp902), order) - tmp904 = Taylor1(constant_term(hz) * constant_term(Y[1]), order) - tmp905 = Taylor1(constant_term(hy) * constant_term(Z[1]), order) - t_x = Taylor1(constant_term(tmp904) - constant_term(tmp905), order) - tmp907 = Taylor1(constant_term(hx) * constant_term(Z[1]), order) - tmp908 = Taylor1(constant_term(hz) * constant_term(X[1]), order) - t_y = Taylor1(constant_term(tmp907) - constant_term(tmp908), order) - tmp910 = Taylor1(constant_term(hy) * constant_term(X[1]), order) - tmp911 = Taylor1(constant_term(hx) * constant_term(Y[1]), order) - t_z = Taylor1(constant_term(tmp910) - constant_term(tmp911), order) - tmp914 = Taylor1(constant_term(t_x) ^ float(constant_term(2)), order) - tmp916 = Taylor1(constant_term(t_y) ^ float(constant_term(2)), order) - tmp917 = Taylor1(constant_term(tmp914) + constant_term(tmp916), order) - tmp919 = Taylor1(constant_term(t_z) ^ float(constant_term(2)), order) - tmp920 = Taylor1(constant_term(tmp917) + constant_term(tmp919), order) - t_norm = Taylor1(sqrt(constant_term(tmp920)), order) - t_x_unit = Taylor1(constant_term(t_x) / constant_term(t_norm), order) - t_y_unit = Taylor1(constant_term(t_y) / constant_term(t_norm), order) - t_z_unit = Taylor1(constant_term(t_z) / constant_term(t_norm), order) - tmp925 = Taylor1(constant_term(X[1]) / constant_term(r_p1d2[1]), order) - r_x_unit = Taylor1(-(constant_term(tmp925)), order) - tmp927 = Taylor1(constant_term(Y[1]) / constant_term(r_p1d2[1]), order) - r_y_unit = Taylor1(-(constant_term(tmp927)), order) - tmp929 = Taylor1(constant_term(Z[1]) / constant_term(r_p1d2[1]), order) - r_z_unit = Taylor1(-(constant_term(tmp929)), order) - g_r = Taylor1(identity(constant_term(r_p2[1])), order) - A2_t_g_r = Taylor1(constant_term(q[7]) / constant_term(g_r), order) - A1_t_g_r = Taylor1(constant_term(q[8]) / constant_term(g_r), order) - tmp933 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_x_unit), order) - tmp934 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_x_unit), order) - NGAx = Taylor1(constant_term(tmp933) + constant_term(tmp934), order) - tmp936 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_y_unit), order) - tmp937 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_y_unit), order) - NGAy = Taylor1(constant_term(tmp936) + constant_term(tmp937), order) - tmp939 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_z_unit), order) - tmp940 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_z_unit), order) - NGAz = Taylor1(constant_term(tmp939) + constant_term(tmp940), order) - tmp942 = Taylor1(constant_term(postNewtonX) + constant_term(accX), order) - dq[4] = Taylor1(constant_term(tmp942) + constant_term(NGAx), order) - tmp944 = Taylor1(constant_term(postNewtonY) + constant_term(accY), order) - dq[5] = Taylor1(constant_term(tmp944) + constant_term(NGAy), order) - tmp946 = Taylor1(constant_term(postNewtonZ) + constant_term(accZ), order) - dq[6] = Taylor1(constant_term(tmp946) + constant_term(NGAz), order) - dq[7] = Taylor1(identity(constant_term(zero_q_1)), order) - return TaylorIntegration.RetAlloc{Taylor1{_S}}([tmp827, tmp829, tmp830, tmp832, tmp895, tmp896, tmp898, tmp899, tmp901, tmp902, tmp904, tmp905, tmp907, tmp908, tmp910, tmp911, tmp914, tmp916, tmp917, tmp919, tmp920, tmp925, tmp927, tmp929, tmp933, tmp934, tmp936, tmp937, tmp939, tmp940, tmp942, tmp944, tmp946, pntempX, pntempY, pntempZ, accX, accY, accZ, postNewtonX, postNewtonY, postNewtonZ, hx, hy, hz, t_x, t_y, t_z, t_norm, t_x_unit, t_y_unit, t_z_unit, r_x_unit, r_y_unit, r_z_unit, g_r, A2_t_g_r, A1_t_g_r, NGAx, NGAy, NGAz], [X, Y, Z, r_p2, r_p1d2, r_p3d2, r_p7d2, newtonianCoeff, ui, vi, wi, U, V, W, _4U_m_3X, _4V_m_3Y, _4W_m_3Z, UU, VV, WW, newtonian1b_Potential, newtonianNb_Potential, newton_acc_X, newton_acc_Y, newton_acc_Z, v2, vi_dot_vj, pn2, U_t_pn2, V_t_pn2, W_t_pn2, pn3, pNX_t_pn3, pNY_t_pn3, pNZ_t_pn3, _4ϕj, ϕi_plus_4ϕj, sj2_plus_2si2_minus_4vivj, ϕs_and_vs, pn1t1_7, pNX_t_X, pNY_t_Y, pNZ_t_Z, pn1, X_t_pn1, Y_t_pn1, Z_t_pn1, t31, t32, t33, r_sin_ϕ, sin_ϕ, ϕ, cos_ϕ, sin2_ϕ, sin3_ϕ, F_J2_x, F_J2_y, F_J2_z, F_J2_x1, F_J2_y1, F_J2_z1, F_J2_x2, F_J2_y2, F_J2_z2, temp_accX_i, temp_accY_i, temp_accZ_i, P_2_sin_ϕ, ∂P_2_sin_ϕ, P_3_sin_ϕ, ∂P_3_sin_ϕ, m_c_ϕ_∂P_2, m_c_ϕ_∂P_3, Λ2j_div_r4, Λ3j_div_r5, F_J_ξ, F_J_ζ, F_J2_ξ, F_J2_ζ, F_J3_ξ, F_J3_ζ, ξx, ξy, ξz, ηx, ηy, ηz, ηx1, ηy1, ηz1, ηx2, ηy2, ηz2, ζx, ζy, ζz, ζx1, ζy1, ζz1, ζx2, ζy2, ζz2, tmp687, tmp689, tmp692, tmp694, tmp697, tmp699, pn2x, pn2y, pn2z, tmp707, tmp710, tmp712, tmp713, tmp715, tmp723, tmp724, tmp735, tmp737, tmp739, tmp741, tmp948, tmp949, tmp751, tmp757, tmp759, tmp763, tmp766, tmp767, tmp770, tmp771, tmp773, tmp775, tmp778, tmp782, tmp785, tmp787, tmp789, tmp819, tmp821, tmp822, tmp824, temp_004, tmp835, tmp837, tmp839, tmp845, tmp847, tmp848, Xij_t_Ui, Yij_t_Vi, Zij_t_Wi, tmp854, Rij_dot_Vi, tmp857, pn1t7, tmp860, pn1t2_7, tmp867, tmp868, tmp869, tmp877, termpnx, sumpnx, tmp880, termpny, sumpny, tmp883, termpnz, sumpnz], [Array{Taylor1{_S}, 2}(undef, 0, 0)], [Array{Taylor1{_S}, 3}(undef, 0, 0, 0)], [Array{Taylor1{_S}, 4}(undef, 0, 0, 0, 0)]) -end - -# TaylorIntegration.jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_ng_eph_threads! -function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params, __ralloc::TaylorIntegration.RetAlloc{Taylor1{_S}}) where {_T <: Real, _S <: Number, _N} - order = t.order - tmp827 = __ralloc.v0[1] - tmp829 = __ralloc.v0[2] - tmp830 = __ralloc.v0[3] - tmp832 = __ralloc.v0[4] - tmp895 = __ralloc.v0[5] - tmp896 = __ralloc.v0[6] - tmp898 = __ralloc.v0[7] - tmp899 = __ralloc.v0[8] - tmp901 = __ralloc.v0[9] - tmp902 = __ralloc.v0[10] - tmp904 = __ralloc.v0[11] - tmp905 = __ralloc.v0[12] - tmp907 = __ralloc.v0[13] - tmp908 = __ralloc.v0[14] - tmp910 = __ralloc.v0[15] - tmp911 = __ralloc.v0[16] - tmp914 = __ralloc.v0[17] - tmp916 = __ralloc.v0[18] - tmp917 = __ralloc.v0[19] - tmp919 = __ralloc.v0[20] - tmp920 = __ralloc.v0[21] - tmp925 = __ralloc.v0[22] - tmp927 = __ralloc.v0[23] - tmp929 = __ralloc.v0[24] - tmp933 = __ralloc.v0[25] - tmp934 = __ralloc.v0[26] - tmp936 = __ralloc.v0[27] - tmp937 = __ralloc.v0[28] - tmp939 = __ralloc.v0[29] - tmp940 = __ralloc.v0[30] - tmp942 = __ralloc.v0[31] - tmp944 = __ralloc.v0[32] - tmp946 = __ralloc.v0[33] - pntempX = __ralloc.v0[34] - pntempY = __ralloc.v0[35] - pntempZ = __ralloc.v0[36] - accX = __ralloc.v0[37] - accY = __ralloc.v0[38] - accZ = __ralloc.v0[39] - postNewtonX = __ralloc.v0[40] - postNewtonY = __ralloc.v0[41] - postNewtonZ = __ralloc.v0[42] - hx = __ralloc.v0[43] - hy = __ralloc.v0[44] - hz = __ralloc.v0[45] - t_x = __ralloc.v0[46] - t_y = __ralloc.v0[47] - t_z = __ralloc.v0[48] - t_norm = __ralloc.v0[49] - t_x_unit = __ralloc.v0[50] - t_y_unit = __ralloc.v0[51] - t_z_unit = __ralloc.v0[52] - r_x_unit = __ralloc.v0[53] - r_y_unit = __ralloc.v0[54] - r_z_unit = __ralloc.v0[55] - g_r = __ralloc.v0[56] - A2_t_g_r = __ralloc.v0[57] - A1_t_g_r = __ralloc.v0[58] - NGAx = __ralloc.v0[59] - NGAy = __ralloc.v0[60] - NGAz = __ralloc.v0[61] - X = __ralloc.v1[1] - Y = __ralloc.v1[2] - Z = __ralloc.v1[3] - r_p2 = __ralloc.v1[4] - r_p1d2 = __ralloc.v1[5] - r_p3d2 = __ralloc.v1[6] - r_p7d2 = __ralloc.v1[7] - newtonianCoeff = __ralloc.v1[8] - ui = __ralloc.v1[9] - vi = __ralloc.v1[10] - wi = __ralloc.v1[11] - U = __ralloc.v1[12] - V = __ralloc.v1[13] - W = __ralloc.v1[14] - _4U_m_3X = __ralloc.v1[15] - _4V_m_3Y = __ralloc.v1[16] - _4W_m_3Z = __ralloc.v1[17] - UU = __ralloc.v1[18] - VV = __ralloc.v1[19] - WW = __ralloc.v1[20] - newtonian1b_Potential = __ralloc.v1[21] - newtonianNb_Potential = __ralloc.v1[22] - newton_acc_X = __ralloc.v1[23] - newton_acc_Y = __ralloc.v1[24] - newton_acc_Z = __ralloc.v1[25] - v2 = __ralloc.v1[26] - vi_dot_vj = __ralloc.v1[27] - pn2 = __ralloc.v1[28] - U_t_pn2 = __ralloc.v1[29] - V_t_pn2 = __ralloc.v1[30] - W_t_pn2 = __ralloc.v1[31] - pn3 = __ralloc.v1[32] - pNX_t_pn3 = __ralloc.v1[33] - pNY_t_pn3 = __ralloc.v1[34] - pNZ_t_pn3 = __ralloc.v1[35] - _4ϕj = __ralloc.v1[36] - ϕi_plus_4ϕj = __ralloc.v1[37] - sj2_plus_2si2_minus_4vivj = __ralloc.v1[38] - ϕs_and_vs = __ralloc.v1[39] - pn1t1_7 = __ralloc.v1[40] - pNX_t_X = __ralloc.v1[41] - pNY_t_Y = __ralloc.v1[42] - pNZ_t_Z = __ralloc.v1[43] - pn1 = __ralloc.v1[44] - X_t_pn1 = __ralloc.v1[45] - Y_t_pn1 = __ralloc.v1[46] - Z_t_pn1 = __ralloc.v1[47] - t31 = __ralloc.v1[48] - t32 = __ralloc.v1[49] - t33 = __ralloc.v1[50] - r_sin_ϕ = __ralloc.v1[51] - sin_ϕ = __ralloc.v1[52] - ϕ = __ralloc.v1[53] - cos_ϕ = __ralloc.v1[54] - sin2_ϕ = __ralloc.v1[55] - sin3_ϕ = __ralloc.v1[56] - F_J2_x = __ralloc.v1[57] - F_J2_y = __ralloc.v1[58] - F_J2_z = __ralloc.v1[59] - F_J2_x1 = __ralloc.v1[60] - F_J2_y1 = __ralloc.v1[61] - F_J2_z1 = __ralloc.v1[62] - F_J2_x2 = __ralloc.v1[63] - F_J2_y2 = __ralloc.v1[64] - F_J2_z2 = __ralloc.v1[65] - temp_accX_i = __ralloc.v1[66] - temp_accY_i = __ralloc.v1[67] - temp_accZ_i = __ralloc.v1[68] - P_2_sin_ϕ = __ralloc.v1[69] - ∂P_2_sin_ϕ = __ralloc.v1[70] - P_3_sin_ϕ = __ralloc.v1[71] - ∂P_3_sin_ϕ = __ralloc.v1[72] - m_c_ϕ_∂P_2 = __ralloc.v1[73] - m_c_ϕ_∂P_3 = __ralloc.v1[74] - Λ2j_div_r4 = __ralloc.v1[75] - Λ3j_div_r5 = __ralloc.v1[76] - F_J_ξ = __ralloc.v1[77] - F_J_ζ = __ralloc.v1[78] - F_J2_ξ = __ralloc.v1[79] - F_J2_ζ = __ralloc.v1[80] - F_J3_ξ = __ralloc.v1[81] - F_J3_ζ = __ralloc.v1[82] - ξx = __ralloc.v1[83] - ξy = __ralloc.v1[84] - ξz = __ralloc.v1[85] - ηx = __ralloc.v1[86] - ηy = __ralloc.v1[87] - ηz = __ralloc.v1[88] - ηx1 = __ralloc.v1[89] - ηy1 = __ralloc.v1[90] - ηz1 = __ralloc.v1[91] - ηx2 = __ralloc.v1[92] - ηy2 = __ralloc.v1[93] - ηz2 = __ralloc.v1[94] - ζx = __ralloc.v1[95] - ζy = __ralloc.v1[96] - ζz = __ralloc.v1[97] - ζx1 = __ralloc.v1[98] - ζy1 = __ralloc.v1[99] - ζz1 = __ralloc.v1[100] - ζx2 = __ralloc.v1[101] - ζy2 = __ralloc.v1[102] - ζz2 = __ralloc.v1[103] - tmp687 = __ralloc.v1[104] - tmp689 = __ralloc.v1[105] - tmp692 = __ralloc.v1[106] - tmp694 = __ralloc.v1[107] - tmp697 = __ralloc.v1[108] - tmp699 = __ralloc.v1[109] - pn2x = __ralloc.v1[110] - pn2y = __ralloc.v1[111] - pn2z = __ralloc.v1[112] - tmp707 = __ralloc.v1[113] - tmp710 = __ralloc.v1[114] - tmp712 = __ralloc.v1[115] - tmp713 = __ralloc.v1[116] - tmp715 = __ralloc.v1[117] - tmp723 = __ralloc.v1[118] - tmp724 = __ralloc.v1[119] - tmp735 = __ralloc.v1[120] - tmp737 = __ralloc.v1[121] - tmp739 = __ralloc.v1[122] - tmp741 = __ralloc.v1[123] - tmp948 = __ralloc.v1[124] - tmp949 = __ralloc.v1[125] - tmp751 = __ralloc.v1[126] - tmp757 = __ralloc.v1[127] - tmp759 = __ralloc.v1[128] - tmp763 = __ralloc.v1[129] - tmp766 = __ralloc.v1[130] - tmp767 = __ralloc.v1[131] - tmp770 = __ralloc.v1[132] - tmp771 = __ralloc.v1[133] - tmp773 = __ralloc.v1[134] - tmp775 = __ralloc.v1[135] - tmp778 = __ralloc.v1[136] - tmp782 = __ralloc.v1[137] - tmp785 = __ralloc.v1[138] - tmp787 = __ralloc.v1[139] - tmp789 = __ralloc.v1[140] - tmp819 = __ralloc.v1[141] - tmp821 = __ralloc.v1[142] - tmp822 = __ralloc.v1[143] - tmp824 = __ralloc.v1[144] - temp_004 = __ralloc.v1[145] - tmp835 = __ralloc.v1[146] - tmp837 = __ralloc.v1[147] - tmp839 = __ralloc.v1[148] - tmp845 = __ralloc.v1[149] - tmp847 = __ralloc.v1[150] - tmp848 = __ralloc.v1[151] - Xij_t_Ui = __ralloc.v1[152] - Yij_t_Vi = __ralloc.v1[153] - Zij_t_Wi = __ralloc.v1[154] - tmp854 = __ralloc.v1[155] - Rij_dot_Vi = __ralloc.v1[156] - tmp857 = __ralloc.v1[157] - pn1t7 = __ralloc.v1[158] - tmp860 = __ralloc.v1[159] - pn1t2_7 = __ralloc.v1[160] - tmp867 = __ralloc.v1[161] - tmp868 = __ralloc.v1[162] - tmp869 = __ralloc.v1[163] - tmp877 = __ralloc.v1[164] - termpnx = __ralloc.v1[165] - sumpnx = __ralloc.v1[166] - tmp880 = __ralloc.v1[167] - termpny = __ralloc.v1[168] - sumpny = __ralloc.v1[169] - tmp883 = __ralloc.v1[170] - termpnz = __ralloc.v1[171] - sumpnz = __ralloc.v1[172] - local jd0 = params[4] - local dsj2k = t + (jd0 - JD_J2000) - local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) - local acceph_t = evaleph(params[2], dsj2k, q[1]) - local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) - local S = eltype(q) - local UJ_interaction = params[5] - local N = params[6] - local Nm1 = N - 1 - local μ = params[7] - local zero_q_1 = auxzero(q[1]) - pntempX.coeffs[1] = identity(constant_term(zero_q_1)) - pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) - pntempY.coeffs[1] = identity(constant_term(zero_q_1)) - pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) - pntempZ.coeffs[1] = identity(constant_term(zero_q_1)) - pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) - accX.coeffs[1] = identity(constant_term(zero_q_1)) - accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) - accY.coeffs[1] = identity(constant_term(zero_q_1)) - accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) - accZ.coeffs[1] = identity(constant_term(zero_q_1)) - accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) - local M_ = Array{S}(undef, 3, 3, N) - local M_ .= zero_q_1 - local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 - (dq[1]).coeffs[1] = identity(constant_term(q[4])) - (dq[1]).coeffs[2:order + 1] .= zero((dq[1]).coeffs[1]) - (dq[2]).coeffs[1] = identity(constant_term(q[5])) - (dq[2]).coeffs[2:order + 1] .= zero((dq[2]).coeffs[1]) - (dq[3]).coeffs[1] = identity(constant_term(q[6])) - (dq[3]).coeffs[2:order + 1] .= zero((dq[3]).coeffs[1]) - (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(zero_q_1)) - (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 - (ui[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])) - (ui[i]).coeffs[2:order + 1] .= zero((ui[i]).coeffs[1]) - (vi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])) - (vi[i]).coeffs[2:order + 1] .= zero((vi[i]).coeffs[1]) - (wi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])) - (wi[i]).coeffs[2:order + 1] .= zero((wi[i]).coeffs[1]) - (X[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 2]) - constant_term(q[1]) - (X[i]).coeffs[2:order + 1] .= zero((X[i]).coeffs[1]) - (Y[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 1]) - constant_term(q[2]) - (Y[i]).coeffs[2:order + 1] .= zero((Y[i]).coeffs[1]) - (Z[i]).coeffs[1] = constant_term(ss16asteph_t[3i]) - constant_term(q[3]) - (Z[i]).coeffs[2:order + 1] .= zero((Z[i]).coeffs[1]) - (U[i]).coeffs[1] = constant_term(ui[i]) - constant_term(dq[1]) - (U[i]).coeffs[2:order + 1] .= zero((U[i]).coeffs[1]) - (V[i]).coeffs[1] = constant_term(vi[i]) - constant_term(dq[2]) - (V[i]).coeffs[2:order + 1] .= zero((V[i]).coeffs[1]) - (W[i]).coeffs[1] = constant_term(wi[i]) - constant_term(dq[3]) - (W[i]).coeffs[2:order + 1] .= zero((W[i]).coeffs[1]) - (tmp687[1]).coeffs[1] = constant_term(4) * constant_term(dq[1]) - (tmp687[1]).coeffs[2:order + 1] .= zero((tmp687[1]).coeffs[1]) - (tmp689[i]).coeffs[1] = constant_term(3) * constant_term(ui[i]) - (tmp689[i]).coeffs[2:order + 1] .= zero((tmp689[i]).coeffs[1]) - (_4U_m_3X[i]).coeffs[1] = constant_term(tmp687[1]) - constant_term(tmp689[i]) - (_4U_m_3X[i]).coeffs[2:order + 1] .= zero((_4U_m_3X[i]).coeffs[1]) - (tmp692[2]).coeffs[1] = constant_term(4) * constant_term(dq[2]) - (tmp692[2]).coeffs[2:order + 1] .= zero((tmp692[2]).coeffs[1]) - (tmp694[i]).coeffs[1] = constant_term(3) * constant_term(vi[i]) - (tmp694[i]).coeffs[2:order + 1] .= zero((tmp694[i]).coeffs[1]) - (_4V_m_3Y[i]).coeffs[1] = constant_term(tmp692[2]) - constant_term(tmp694[i]) - (_4V_m_3Y[i]).coeffs[2:order + 1] .= zero((_4V_m_3Y[i]).coeffs[1]) - (tmp697[3]).coeffs[1] = constant_term(4) * constant_term(dq[3]) - (tmp697[3]).coeffs[2:order + 1] .= zero((tmp697[3]).coeffs[1]) - (tmp699[i]).coeffs[1] = constant_term(3) * constant_term(wi[i]) - (tmp699[i]).coeffs[2:order + 1] .= zero((tmp699[i]).coeffs[1]) - (_4W_m_3Z[i]).coeffs[1] = constant_term(tmp697[3]) - constant_term(tmp699[i]) - (_4W_m_3Z[i]).coeffs[2:order + 1] .= zero((_4W_m_3Z[i]).coeffs[1]) - (pn2x[i]).coeffs[1] = constant_term(X[i]) * constant_term(_4U_m_3X[i]) - (pn2x[i]).coeffs[2:order + 1] .= zero((pn2x[i]).coeffs[1]) - (pn2y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(_4V_m_3Y[i]) - (pn2y[i]).coeffs[2:order + 1] .= zero((pn2y[i]).coeffs[1]) - (pn2z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(_4W_m_3Z[i]) - (pn2z[i]).coeffs[2:order + 1] .= zero((pn2z[i]).coeffs[1]) - (UU[i]).coeffs[1] = constant_term(ui[i]) * constant_term(dq[1]) - (UU[i]).coeffs[2:order + 1] .= zero((UU[i]).coeffs[1]) - (VV[i]).coeffs[1] = constant_term(vi[i]) * constant_term(dq[2]) - (VV[i]).coeffs[2:order + 1] .= zero((VV[i]).coeffs[1]) - (WW[i]).coeffs[1] = constant_term(wi[i]) * constant_term(dq[3]) - (WW[i]).coeffs[2:order + 1] .= zero((WW[i]).coeffs[1]) - (tmp707[i]).coeffs[1] = constant_term(UU[i]) + constant_term(VV[i]) - (tmp707[i]).coeffs[2:order + 1] .= zero((tmp707[i]).coeffs[1]) - (vi_dot_vj[i]).coeffs[1] = constant_term(tmp707[i]) + constant_term(WW[i]) - (vi_dot_vj[i]).coeffs[2:order + 1] .= zero((vi_dot_vj[i]).coeffs[1]) - (tmp710[i]).coeffs[1] = constant_term(X[i]) ^ float(constant_term(2)) - (tmp710[i]).coeffs[2:order + 1] .= zero((tmp710[i]).coeffs[1]) - (tmp712[i]).coeffs[1] = constant_term(Y[i]) ^ float(constant_term(2)) - (tmp712[i]).coeffs[2:order + 1] .= zero((tmp712[i]).coeffs[1]) - (tmp713[i]).coeffs[1] = constant_term(tmp710[i]) + constant_term(tmp712[i]) - (tmp713[i]).coeffs[2:order + 1] .= zero((tmp713[i]).coeffs[1]) - (tmp715[i]).coeffs[1] = constant_term(Z[i]) ^ float(constant_term(2)) - (tmp715[i]).coeffs[2:order + 1] .= zero((tmp715[i]).coeffs[1]) - (r_p2[i]).coeffs[1] = constant_term(tmp713[i]) + constant_term(tmp715[i]) - (r_p2[i]).coeffs[2:order + 1] .= zero((r_p2[i]).coeffs[1]) - (r_p1d2[i]).coeffs[1] = sqrt(constant_term(r_p2[i])) - (r_p1d2[i]).coeffs[2:order + 1] .= zero((r_p1d2[i]).coeffs[1]) - (r_p3d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(1.5)) - (r_p3d2[i]).coeffs[2:order + 1] .= zero((r_p3d2[i]).coeffs[1]) - (r_p7d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(3.5)) - (r_p7d2[i]).coeffs[2:order + 1] .= zero((r_p7d2[i]).coeffs[1]) - (newtonianCoeff[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p3d2[i]) - (newtonianCoeff[i]).coeffs[2:order + 1] .= zero((newtonianCoeff[i]).coeffs[1]) - (tmp723[i]).coeffs[1] = constant_term(pn2x[i]) + constant_term(pn2y[i]) - (tmp723[i]).coeffs[2:order + 1] .= zero((tmp723[i]).coeffs[1]) - (tmp724[i]).coeffs[1] = constant_term(tmp723[i]) + constant_term(pn2z[i]) - (tmp724[i]).coeffs[2:order + 1] .= zero((tmp724[i]).coeffs[1]) - (pn2[i]).coeffs[1] = constant_term(newtonianCoeff[i]) * constant_term(tmp724[i]) - (pn2[i]).coeffs[2:order + 1] .= zero((pn2[i]).coeffs[1]) - (newton_acc_X[i]).coeffs[1] = constant_term(X[i]) * constant_term(newtonianCoeff[i]) - (newton_acc_X[i]).coeffs[2:order + 1] .= zero((newton_acc_X[i]).coeffs[1]) - (newton_acc_Y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(newtonianCoeff[i]) - (newton_acc_Y[i]).coeffs[2:order + 1] .= zero((newton_acc_Y[i]).coeffs[1]) - (newton_acc_Z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(newtonianCoeff[i]) - (newton_acc_Z[i]).coeffs[2:order + 1] .= zero((newton_acc_Z[i]).coeffs[1]) - (newtonian1b_Potential[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p1d2[i]) - (newtonian1b_Potential[i]).coeffs[2:order + 1] .= zero((newtonian1b_Potential[i]).coeffs[1]) - (pn3[i]).coeffs[1] = constant_term(3.5) * constant_term(newtonian1b_Potential[i]) - (pn3[i]).coeffs[2:order + 1] .= zero((pn3[i]).coeffs[1]) - (U_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(U[i]) - (U_t_pn2[i]).coeffs[2:order + 1] .= zero((U_t_pn2[i]).coeffs[1]) - (V_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(V[i]) - (V_t_pn2[i]).coeffs[2:order + 1] .= zero((V_t_pn2[i]).coeffs[1]) - (W_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(W[i]) - (W_t_pn2[i]).coeffs[2:order + 1] .= zero((W_t_pn2[i]).coeffs[1]) - if UJ_interaction[i] - (tmp735[i]).coeffs[1] = -(constant_term(X[i])) - (tmp735[i]).coeffs[2:order + 1] .= zero((tmp735[i]).coeffs[1]) - (t31[i]).coeffs[1] = constant_term(tmp735[i]) * constant_term(M_[1, 3, i]) - (t31[i]).coeffs[2:order + 1] .= zero((t31[i]).coeffs[1]) - (tmp737[i]).coeffs[1] = -(constant_term(Y[i])) - (tmp737[i]).coeffs[2:order + 1] .= zero((tmp737[i]).coeffs[1]) - (t32[i]).coeffs[1] = constant_term(tmp737[i]) * constant_term(M_[2, 3, i]) - (t32[i]).coeffs[2:order + 1] .= zero((t32[i]).coeffs[1]) - (tmp739[i]).coeffs[1] = -(constant_term(Z[i])) - (tmp739[i]).coeffs[2:order + 1] .= zero((tmp739[i]).coeffs[1]) - (t33[i]).coeffs[1] = constant_term(tmp739[i]) * constant_term(M_[3, 3, i]) - (t33[i]).coeffs[2:order + 1] .= zero((t33[i]).coeffs[1]) - (tmp741[i]).coeffs[1] = constant_term(t31[i]) + constant_term(t32[i]) - (tmp741[i]).coeffs[2:order + 1] .= zero((tmp741[i]).coeffs[1]) - (r_sin_ϕ[i]).coeffs[1] = constant_term(tmp741[i]) + constant_term(t33[i]) - (r_sin_ϕ[i]).coeffs[2:order + 1] .= zero((r_sin_ϕ[i]).coeffs[1]) - (sin_ϕ[i]).coeffs[1] = constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]) - (sin_ϕ[i]).coeffs[2:order + 1] .= zero((sin_ϕ[i]).coeffs[1]) - (ϕ[i]).coeffs[1] = asin(constant_term(sin_ϕ[i])) - (ϕ[i]).coeffs[2:order + 1] .= zero((ϕ[i]).coeffs[1]) - (tmp948[i]).coeffs[1] = sqrt(1 - constant_term(sin_ϕ[i]) ^ 2) - (tmp948[i]).coeffs[2:order + 1] .= zero((tmp948[i]).coeffs[1]) - (cos_ϕ[i]).coeffs[1] = cos(constant_term(ϕ[i])) - (cos_ϕ[i]).coeffs[2:order + 1] .= zero((cos_ϕ[i]).coeffs[1]) - (tmp949[i]).coeffs[1] = sin(constant_term(ϕ[i])) - (tmp949[i]).coeffs[2:order + 1] .= zero((tmp949[i]).coeffs[1]) - (sin2_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(2)) - (sin2_ϕ[i]).coeffs[2:order + 1] .= zero((sin2_ϕ[i]).coeffs[1]) - (sin3_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(3)) - (sin3_ϕ[i]).coeffs[2:order + 1] .= zero((sin3_ϕ[i]).coeffs[1]) - (tmp751[i]).coeffs[1] = constant_term(1.5) * constant_term(sin2_ϕ[i]) - (tmp751[i]).coeffs[2:order + 1] .= zero((tmp751[i]).coeffs[1]) - (P_2_sin_ϕ[i]).coeffs[1] = constant_term(tmp751[i]) - constant_term(0.5) - (P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_2_sin_ϕ[i]).coeffs[1]) - (∂P_2_sin_ϕ[i]).coeffs[1] = constant_term(3) * constant_term(sin_ϕ[i]) - (∂P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_2_sin_ϕ[i]).coeffs[1]) - (tmp757[i]).coeffs[1] = constant_term(-1.5) * constant_term(sin_ϕ[i]) - (tmp757[i]).coeffs[2:order + 1] .= zero((tmp757[i]).coeffs[1]) - (tmp759[i]).coeffs[1] = constant_term(2.5) * constant_term(sin3_ϕ[i]) - (tmp759[i]).coeffs[2:order + 1] .= zero((tmp759[i]).coeffs[1]) - (P_3_sin_ϕ[i]).coeffs[1] = constant_term(tmp757[i]) + constant_term(tmp759[i]) - (P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_3_sin_ϕ[i]).coeffs[1]) - (tmp763[i]).coeffs[1] = constant_term(7.5) * constant_term(sin2_ϕ[i]) - (tmp763[i]).coeffs[2:order + 1] .= zero((tmp763[i]).coeffs[1]) - (∂P_3_sin_ϕ[i]).coeffs[1] = constant_term(-1.5) + constant_term(tmp763[i]) - (∂P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_3_sin_ϕ[i]).coeffs[1]) - (tmp766[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(2)) - (tmp766[i]).coeffs[2:order + 1] .= zero((tmp766[i]).coeffs[1]) - (tmp767[i]).coeffs[1] = constant_term(Λ2[i]) / constant_term(tmp766[i]) - (tmp767[i]).coeffs[2:order + 1] .= zero((tmp767[i]).coeffs[1]) - (Λ2j_div_r4[i]).coeffs[1] = -(constant_term(tmp767[i])) - (Λ2j_div_r4[i]).coeffs[2:order + 1] .= zero((Λ2j_div_r4[i]).coeffs[1]) - (tmp770[i]).coeffs[1] = constant_term(r_p1d2[i]) ^ float(constant_term(5)) - (tmp770[i]).coeffs[2:order + 1] .= zero((tmp770[i]).coeffs[1]) - (tmp771[i]).coeffs[1] = constant_term(Λ3[i]) / constant_term(tmp770[i]) - (tmp771[i]).coeffs[2:order + 1] .= zero((tmp771[i]).coeffs[1]) - (Λ3j_div_r5[i]).coeffs[1] = -(constant_term(tmp771[i])) - (Λ3j_div_r5[i]).coeffs[2:order + 1] .= zero((Λ3j_div_r5[i]).coeffs[1]) - (tmp773[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) - (tmp773[i]).coeffs[2:order + 1] .= zero((tmp773[i]).coeffs[1]) - (m_c_ϕ_∂P_2[i]).coeffs[1] = constant_term(tmp773[i]) * constant_term(∂P_2_sin_ϕ[i]) - (m_c_ϕ_∂P_2[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_2[i]).coeffs[1]) - (tmp775[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) - (tmp775[i]).coeffs[2:order + 1] .= zero((tmp775[i]).coeffs[1]) - (m_c_ϕ_∂P_3[i]).coeffs[1] = constant_term(tmp775[i]) * constant_term(∂P_3_sin_ϕ[i]) - (m_c_ϕ_∂P_3[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_3[i]).coeffs[1]) - (tmp778[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(3) - (tmp778[i]).coeffs[2:order + 1] .= zero((tmp778[i]).coeffs[1]) - (F_J2_ξ[i]).coeffs[1] = constant_term(tmp778[i]) * constant_term(P_2_sin_ϕ[i]) - (F_J2_ξ[i]).coeffs[2:order + 1] .= zero((F_J2_ξ[i]).coeffs[1]) - (F_J2_ζ[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]) - (F_J2_ζ[i]).coeffs[2:order + 1] .= zero((F_J2_ζ[i]).coeffs[1]) - (tmp782[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(4) - (tmp782[i]).coeffs[2:order + 1] .= zero((tmp782[i]).coeffs[1]) - (F_J3_ξ[i]).coeffs[1] = constant_term(tmp782[i]) * constant_term(P_3_sin_ϕ[i]) - (F_J3_ξ[i]).coeffs[2:order + 1] .= zero((F_J3_ξ[i]).coeffs[1]) - (F_J3_ζ[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]) - (F_J3_ζ[i]).coeffs[2:order + 1] .= zero((F_J3_ζ[i]).coeffs[1]) - (F_J_ξ[i]).coeffs[1] = identity(constant_term(F_J2_ξ[i])) - (F_J_ξ[i]).coeffs[2:order + 1] .= zero((F_J_ξ[i]).coeffs[1]) - (F_J_ζ[i]).coeffs[1] = identity(constant_term(F_J2_ζ[i])) - (F_J_ζ[i]).coeffs[2:order + 1] .= zero((F_J_ζ[i]).coeffs[1]) - (tmp785[i]).coeffs[1] = -(constant_term(X[i])) - (tmp785[i]).coeffs[2:order + 1] .= zero((tmp785[i]).coeffs[1]) - (ξx[i]).coeffs[1] = constant_term(tmp785[i]) / constant_term(r_p1d2[i]) - (ξx[i]).coeffs[2:order + 1] .= zero((ξx[i]).coeffs[1]) - (tmp787[i]).coeffs[1] = -(constant_term(Y[i])) - (tmp787[i]).coeffs[2:order + 1] .= zero((tmp787[i]).coeffs[1]) - (ξy[i]).coeffs[1] = constant_term(tmp787[i]) / constant_term(r_p1d2[i]) - (ξy[i]).coeffs[2:order + 1] .= zero((ξy[i]).coeffs[1]) - (tmp789[i]).coeffs[1] = -(constant_term(Z[i])) - (tmp789[i]).coeffs[2:order + 1] .= zero((tmp789[i]).coeffs[1]) - (ξz[i]).coeffs[1] = constant_term(tmp789[i]) / constant_term(r_p1d2[i]) - (ξz[i]).coeffs[2:order + 1] .= zero((ξz[i]).coeffs[1]) - (ηx1[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξz[i]) - (ηx1[i]).coeffs[2:order + 1] .= zero((ηx1[i]).coeffs[1]) - (ηy1[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξx[i]) - (ηy1[i]).coeffs[2:order + 1] .= zero((ηy1[i]).coeffs[1]) - (ηz1[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξy[i]) - (ηz1[i]).coeffs[2:order + 1] .= zero((ηz1[i]).coeffs[1]) - (ηx2[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξy[i]) - (ηx2[i]).coeffs[2:order + 1] .= zero((ηx2[i]).coeffs[1]) - (ηy2[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξz[i]) - (ηy2[i]).coeffs[2:order + 1] .= zero((ηy2[i]).coeffs[1]) - (ηz2[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξx[i]) - (ηz2[i]).coeffs[2:order + 1] .= zero((ηz2[i]).coeffs[1]) - (ηx[i]).coeffs[1] = constant_term(ηx1[i]) - constant_term(ηx2[i]) - (ηx[i]).coeffs[2:order + 1] .= zero((ηx[i]).coeffs[1]) - (ηy[i]).coeffs[1] = constant_term(ηy1[i]) - constant_term(ηy2[i]) - (ηy[i]).coeffs[2:order + 1] .= zero((ηy[i]).coeffs[1]) - (ηz[i]).coeffs[1] = constant_term(ηz1[i]) - constant_term(ηz2[i]) - (ηz[i]).coeffs[2:order + 1] .= zero((ηz[i]).coeffs[1]) - (ζx1[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηz[i]) - (ζx1[i]).coeffs[2:order + 1] .= zero((ζx1[i]).coeffs[1]) - (ζy1[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηx[i]) - (ζy1[i]).coeffs[2:order + 1] .= zero((ζy1[i]).coeffs[1]) - (ζz1[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηy[i]) - (ζz1[i]).coeffs[2:order + 1] .= zero((ζz1[i]).coeffs[1]) - (ζx2[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηy[i]) - (ζx2[i]).coeffs[2:order + 1] .= zero((ζx2[i]).coeffs[1]) - (ζy2[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηz[i]) - (ζy2[i]).coeffs[2:order + 1] .= zero((ζy2[i]).coeffs[1]) - (ζz2[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηx[i]) - (ζz2[i]).coeffs[2:order + 1] .= zero((ζz2[i]).coeffs[1]) - (ζx[i]).coeffs[1] = constant_term(ζx1[i]) - constant_term(ζx2[i]) - (ζx[i]).coeffs[2:order + 1] .= zero((ζx[i]).coeffs[1]) - (ζy[i]).coeffs[1] = constant_term(ζy1[i]) - constant_term(ζy2[i]) - (ζy[i]).coeffs[2:order + 1] .= zero((ζy[i]).coeffs[1]) - (ζz[i]).coeffs[1] = constant_term(ζz1[i]) - constant_term(ζz2[i]) - (ζz[i]).coeffs[2:order + 1] .= zero((ζz[i]).coeffs[1]) - (F_J2_x1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξx[i]) - (F_J2_x1[i]).coeffs[2:order + 1] .= zero((F_J2_x1[i]).coeffs[1]) - (F_J2_y1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξy[i]) - (F_J2_y1[i]).coeffs[2:order + 1] .= zero((F_J2_y1[i]).coeffs[1]) - (F_J2_z1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξz[i]) - (F_J2_z1[i]).coeffs[2:order + 1] .= zero((F_J2_z1[i]).coeffs[1]) - (F_J2_x2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζx[i]) - (F_J2_x2[i]).coeffs[2:order + 1] .= zero((F_J2_x2[i]).coeffs[1]) - (F_J2_y2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζy[i]) - (F_J2_y2[i]).coeffs[2:order + 1] .= zero((F_J2_y2[i]).coeffs[1]) - (F_J2_z2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζz[i]) - (F_J2_z2[i]).coeffs[2:order + 1] .= zero((F_J2_z2[i]).coeffs[1]) - (F_J2_x[i]).coeffs[1] = constant_term(F_J2_x1[i]) + constant_term(F_J2_x2[i]) - (F_J2_x[i]).coeffs[2:order + 1] .= zero((F_J2_x[i]).coeffs[1]) - (F_J2_y[i]).coeffs[1] = constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]) - (F_J2_y[i]).coeffs[2:order + 1] .= zero((F_J2_y[i]).coeffs[1]) - (F_J2_z[i]).coeffs[1] = constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]) - (F_J2_z[i]).coeffs[2:order + 1] .= zero((F_J2_z[i]).coeffs[1]) - end - (tmp819[i]).coeffs[1] = constant_term(ui[i]) ^ float(constant_term(2)) - (tmp819[i]).coeffs[2:order + 1] .= zero((tmp819[i]).coeffs[1]) - (tmp821[i]).coeffs[1] = constant_term(vi[i]) ^ float(constant_term(2)) - (tmp821[i]).coeffs[2:order + 1] .= zero((tmp821[i]).coeffs[1]) - (tmp822[i]).coeffs[1] = constant_term(tmp819[i]) + constant_term(tmp821[i]) - (tmp822[i]).coeffs[2:order + 1] .= zero((tmp822[i]).coeffs[1]) - (tmp824[i]).coeffs[1] = constant_term(wi[i]) ^ float(constant_term(2)) - (tmp824[i]).coeffs[2:order + 1] .= zero((tmp824[i]).coeffs[1]) - (v2[i]).coeffs[1] = constant_term(tmp822[i]) + constant_term(tmp824[i]) - (v2[i]).coeffs[2:order + 1] .= zero((v2[i]).coeffs[1]) - end - tmp827.coeffs[1] = constant_term(q[4]) ^ float(constant_term(2)) - tmp827.coeffs[2:order + 1] .= zero(tmp827.coeffs[1]) - tmp829.coeffs[1] = constant_term(q[5]) ^ float(constant_term(2)) - tmp829.coeffs[2:order + 1] .= zero(tmp829.coeffs[1]) - tmp830.coeffs[1] = constant_term(tmp827) + constant_term(tmp829) - tmp830.coeffs[2:order + 1] .= zero(tmp830.coeffs[1]) - tmp832.coeffs[1] = constant_term(q[6]) ^ float(constant_term(2)) - tmp832.coeffs[2:order + 1] .= zero(tmp832.coeffs[1]) - (v2[N]).coeffs[1] = constant_term(tmp830) + constant_term(tmp832) - (v2[N]).coeffs[2:order + 1] .= zero((v2[N]).coeffs[1]) - for i = 1:Nm1 - (temp_004[i]).coeffs[1] = constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]) - (temp_004[i]).coeffs[2:order + 1] .= zero((temp_004[i]).coeffs[1]) - (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(temp_004[i])) - (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) - if UJ_interaction[i] - (tmp835[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_x[i]) - (tmp835[i]).coeffs[2:order + 1] .= zero((tmp835[i]).coeffs[1]) - (temp_accX_i[i]).coeffs[1] = constant_term(accX) - constant_term(tmp835[i]) - (temp_accX_i[i]).coeffs[2:order + 1] .= zero((temp_accX_i[i]).coeffs[1]) - accX.coeffs[1] = identity(constant_term(temp_accX_i[i])) - accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) - (tmp837[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_y[i]) - (tmp837[i]).coeffs[2:order + 1] .= zero((tmp837[i]).coeffs[1]) - (temp_accY_i[i]).coeffs[1] = constant_term(accY) - constant_term(tmp837[i]) - (temp_accY_i[i]).coeffs[2:order + 1] .= zero((temp_accY_i[i]).coeffs[1]) - accY.coeffs[1] = identity(constant_term(temp_accY_i[i])) - accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) - (tmp839[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_z[i]) - (tmp839[i]).coeffs[2:order + 1] .= zero((tmp839[i]).coeffs[1]) - (temp_accZ_i[i]).coeffs[1] = constant_term(accZ) - constant_term(tmp839[i]) - (temp_accZ_i[i]).coeffs[2:order + 1] .= zero((temp_accZ_i[i]).coeffs[1]) - accZ.coeffs[1] = identity(constant_term(temp_accZ_i[i])) - accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) - end - end - (_4ϕj[N]).coeffs[1] = constant_term(4) * constant_term(newtonianNb_Potential[N]) - (_4ϕj[N]).coeffs[2:order + 1] .= zero((_4ϕj[N]).coeffs[1]) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 - (ϕi_plus_4ϕj[i]).coeffs[1] = constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]) - (ϕi_plus_4ϕj[i]).coeffs[2:order + 1] .= zero((ϕi_plus_4ϕj[i]).coeffs[1]) - (tmp845[i]).coeffs[1] = constant_term(2) * constant_term(v2[i]) - (tmp845[i]).coeffs[2:order + 1] .= zero((tmp845[i]).coeffs[1]) - (tmp847[i]).coeffs[1] = constant_term(4) * constant_term(vi_dot_vj[i]) - (tmp847[i]).coeffs[2:order + 1] .= zero((tmp847[i]).coeffs[1]) - (tmp848[i]).coeffs[1] = constant_term(tmp845[i]) - constant_term(tmp847[i]) - (tmp848[i]).coeffs[2:order + 1] .= zero((tmp848[i]).coeffs[1]) - (sj2_plus_2si2_minus_4vivj[i]).coeffs[1] = constant_term(tmp848[i]) + constant_term(v2[N]) - (sj2_plus_2si2_minus_4vivj[i]).coeffs[2:order + 1] .= zero((sj2_plus_2si2_minus_4vivj[i]).coeffs[1]) - (ϕs_and_vs[i]).coeffs[1] = constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]) - (ϕs_and_vs[i]).coeffs[2:order + 1] .= zero((ϕs_and_vs[i]).coeffs[1]) - (Xij_t_Ui[i]).coeffs[1] = constant_term(X[i]) * constant_term(ui[i]) - (Xij_t_Ui[i]).coeffs[2:order + 1] .= zero((Xij_t_Ui[i]).coeffs[1]) - (Yij_t_Vi[i]).coeffs[1] = constant_term(Y[i]) * constant_term(vi[i]) - (Yij_t_Vi[i]).coeffs[2:order + 1] .= zero((Yij_t_Vi[i]).coeffs[1]) - (Zij_t_Wi[i]).coeffs[1] = constant_term(Z[i]) * constant_term(wi[i]) - (Zij_t_Wi[i]).coeffs[2:order + 1] .= zero((Zij_t_Wi[i]).coeffs[1]) - (tmp854[i]).coeffs[1] = constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]) - (tmp854[i]).coeffs[2:order + 1] .= zero((tmp854[i]).coeffs[1]) - (Rij_dot_Vi[i]).coeffs[1] = constant_term(tmp854[i]) + constant_term(Zij_t_Wi[i]) - (Rij_dot_Vi[i]).coeffs[2:order + 1] .= zero((Rij_dot_Vi[i]).coeffs[1]) - (tmp857[i]).coeffs[1] = constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)) - (tmp857[i]).coeffs[2:order + 1] .= zero((tmp857[i]).coeffs[1]) - (pn1t7[i]).coeffs[1] = constant_term(tmp857[i]) / constant_term(r_p2[i]) - (pn1t7[i]).coeffs[2:order + 1] .= zero((pn1t7[i]).coeffs[1]) - (tmp860[i]).coeffs[1] = constant_term(1.5) * constant_term(pn1t7[i]) - (tmp860[i]).coeffs[2:order + 1] .= zero((tmp860[i]).coeffs[1]) - (pn1t2_7[i]).coeffs[1] = constant_term(ϕs_and_vs[i]) - constant_term(tmp860[i]) - (pn1t2_7[i]).coeffs[2:order + 1] .= zero((pn1t2_7[i]).coeffs[1]) - (pn1t1_7[i]).coeffs[1] = constant_term(c_p2) + constant_term(pn1t2_7[i]) - (pn1t1_7[i]).coeffs[2:order + 1] .= zero((pn1t1_7[i]).coeffs[1]) - (pNX_t_X[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(X[i]) - (pNX_t_X[i]).coeffs[2:order + 1] .= zero((pNX_t_X[i]).coeffs[1]) - (pNY_t_Y[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(Y[i]) - (pNY_t_Y[i]).coeffs[2:order + 1] .= zero((pNY_t_Y[i]).coeffs[1]) - (pNZ_t_Z[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(Z[i]) - (pNZ_t_Z[i]).coeffs[2:order + 1] .= zero((pNZ_t_Z[i]).coeffs[1]) - (tmp867[i]).coeffs[1] = constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]) - (tmp867[i]).coeffs[2:order + 1] .= zero((tmp867[i]).coeffs[1]) - (tmp868[i]).coeffs[1] = constant_term(tmp867[i]) + constant_term(pNZ_t_Z[i]) - (tmp868[i]).coeffs[2:order + 1] .= zero((tmp868[i]).coeffs[1]) - (tmp869[i]).coeffs[1] = constant_term(0.5) * constant_term(tmp868[i]) - (tmp869[i]).coeffs[2:order + 1] .= zero((tmp869[i]).coeffs[1]) - (pn1[i]).coeffs[1] = constant_term(pn1t1_7[i]) + constant_term(tmp869[i]) - (pn1[i]).coeffs[2:order + 1] .= zero((pn1[i]).coeffs[1]) - (X_t_pn1[i]).coeffs[1] = constant_term(newton_acc_X[i]) * constant_term(pn1[i]) - (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) - (Y_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Y[i]) * constant_term(pn1[i]) - (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) - (Z_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Z[i]) * constant_term(pn1[i]) - (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) - (pNX_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(pn3[i]) - (pNX_t_pn3[i]).coeffs[2:order + 1] .= zero((pNX_t_pn3[i]).coeffs[1]) - (pNY_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]) - (pNY_t_pn3[i]).coeffs[2:order + 1] .= zero((pNY_t_pn3[i]).coeffs[1]) - (pNZ_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(pn3[i]) - (pNZ_t_pn3[i]).coeffs[2:order + 1] .= zero((pNZ_t_pn3[i]).coeffs[1]) - end - for i = 1:10 - (tmp877[i]).coeffs[1] = constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]) - (tmp877[i]).coeffs[2:order + 1] .= zero((tmp877[i]).coeffs[1]) - (termpnx[i]).coeffs[1] = constant_term(X_t_pn1[i]) + constant_term(tmp877[i]) - (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) - (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) - (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) - pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) - pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) - (tmp880[i]).coeffs[1] = constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]) - (tmp880[i]).coeffs[2:order + 1] .= zero((tmp880[i]).coeffs[1]) - (termpny[i]).coeffs[1] = constant_term(Y_t_pn1[i]) + constant_term(tmp880[i]) - (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) - (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) - (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) - pntempY.coeffs[1] = identity(constant_term(sumpny[i])) - pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) - (tmp883[i]).coeffs[1] = constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]) - (tmp883[i]).coeffs[2:order + 1] .= zero((tmp883[i]).coeffs[1]) - (termpnz[i]).coeffs[1] = constant_term(Z_t_pn1[i]) + constant_term(tmp883[i]) - (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) - (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) - (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) - pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) - pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) - end - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 - (X_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_X[i]) - (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) - (Y_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Y[i]) - (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) - (Z_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Z[i]) - (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) - end - for i = 11:Nm1 - (termpnx[i]).coeffs[1] = identity(constant_term(X_t_pn1[i])) - (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) - (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) - (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) - pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) - pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) - (termpny[i]).coeffs[1] = identity(constant_term(Y_t_pn1[i])) - (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) - (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) - (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) - pntempY.coeffs[1] = identity(constant_term(sumpny[i])) - pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) - (termpnz[i]).coeffs[1] = identity(constant_term(Z_t_pn1[i])) - (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) - (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) - (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) - pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) - pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) - end - postNewtonX.coeffs[1] = constant_term(pntempX) * constant_term(c_m2) - postNewtonX.coeffs[2:order + 1] .= zero(postNewtonX.coeffs[1]) - postNewtonY.coeffs[1] = constant_term(pntempY) * constant_term(c_m2) - postNewtonY.coeffs[2:order + 1] .= zero(postNewtonY.coeffs[1]) - postNewtonZ.coeffs[1] = constant_term(pntempZ) * constant_term(c_m2) - postNewtonZ.coeffs[2:order + 1] .= zero(postNewtonZ.coeffs[1]) - tmp895.coeffs[1] = constant_term(Y[1]) * constant_term(W[1]) - tmp895.coeffs[2:order + 1] .= zero(tmp895.coeffs[1]) - tmp896.coeffs[1] = constant_term(Z[1]) * constant_term(V[1]) - tmp896.coeffs[2:order + 1] .= zero(tmp896.coeffs[1]) - hx.coeffs[1] = constant_term(tmp895) - constant_term(tmp896) - hx.coeffs[2:order + 1] .= zero(hx.coeffs[1]) - tmp898.coeffs[1] = constant_term(Z[1]) * constant_term(U[1]) - tmp898.coeffs[2:order + 1] .= zero(tmp898.coeffs[1]) - tmp899.coeffs[1] = constant_term(X[1]) * constant_term(W[1]) - tmp899.coeffs[2:order + 1] .= zero(tmp899.coeffs[1]) - hy.coeffs[1] = constant_term(tmp898) - constant_term(tmp899) - hy.coeffs[2:order + 1] .= zero(hy.coeffs[1]) - tmp901.coeffs[1] = constant_term(X[1]) * constant_term(V[1]) - tmp901.coeffs[2:order + 1] .= zero(tmp901.coeffs[1]) - tmp902.coeffs[1] = constant_term(Y[1]) * constant_term(U[1]) - tmp902.coeffs[2:order + 1] .= zero(tmp902.coeffs[1]) - hz.coeffs[1] = constant_term(tmp901) - constant_term(tmp902) - hz.coeffs[2:order + 1] .= zero(hz.coeffs[1]) - tmp904.coeffs[1] = constant_term(hz) * constant_term(Y[1]) - tmp904.coeffs[2:order + 1] .= zero(tmp904.coeffs[1]) - tmp905.coeffs[1] = constant_term(hy) * constant_term(Z[1]) - tmp905.coeffs[2:order + 1] .= zero(tmp905.coeffs[1]) - t_x.coeffs[1] = constant_term(tmp904) - constant_term(tmp905) - t_x.coeffs[2:order + 1] .= zero(t_x.coeffs[1]) - tmp907.coeffs[1] = constant_term(hx) * constant_term(Z[1]) - tmp907.coeffs[2:order + 1] .= zero(tmp907.coeffs[1]) - tmp908.coeffs[1] = constant_term(hz) * constant_term(X[1]) - tmp908.coeffs[2:order + 1] .= zero(tmp908.coeffs[1]) - t_y.coeffs[1] = constant_term(tmp907) - constant_term(tmp908) - t_y.coeffs[2:order + 1] .= zero(t_y.coeffs[1]) - tmp910.coeffs[1] = constant_term(hy) * constant_term(X[1]) - tmp910.coeffs[2:order + 1] .= zero(tmp910.coeffs[1]) - tmp911.coeffs[1] = constant_term(hx) * constant_term(Y[1]) - tmp911.coeffs[2:order + 1] .= zero(tmp911.coeffs[1]) - t_z.coeffs[1] = constant_term(tmp910) - constant_term(tmp911) - t_z.coeffs[2:order + 1] .= zero(t_z.coeffs[1]) - tmp914.coeffs[1] = constant_term(t_x) ^ float(constant_term(2)) - tmp914.coeffs[2:order + 1] .= zero(tmp914.coeffs[1]) - tmp916.coeffs[1] = constant_term(t_y) ^ float(constant_term(2)) - tmp916.coeffs[2:order + 1] .= zero(tmp916.coeffs[1]) - tmp917.coeffs[1] = constant_term(tmp914) + constant_term(tmp916) - tmp917.coeffs[2:order + 1] .= zero(tmp917.coeffs[1]) - tmp919.coeffs[1] = constant_term(t_z) ^ float(constant_term(2)) - tmp919.coeffs[2:order + 1] .= zero(tmp919.coeffs[1]) - tmp920.coeffs[1] = constant_term(tmp917) + constant_term(tmp919) - tmp920.coeffs[2:order + 1] .= zero(tmp920.coeffs[1]) - t_norm.coeffs[1] = sqrt(constant_term(tmp920)) - t_norm.coeffs[2:order + 1] .= zero(t_norm.coeffs[1]) - t_x_unit.coeffs[1] = constant_term(t_x) / constant_term(t_norm) - t_x_unit.coeffs[2:order + 1] .= zero(t_x_unit.coeffs[1]) - t_y_unit.coeffs[1] = constant_term(t_y) / constant_term(t_norm) - t_y_unit.coeffs[2:order + 1] .= zero(t_y_unit.coeffs[1]) - t_z_unit.coeffs[1] = constant_term(t_z) / constant_term(t_norm) - t_z_unit.coeffs[2:order + 1] .= zero(t_z_unit.coeffs[1]) - tmp925.coeffs[1] = constant_term(X[1]) / constant_term(r_p1d2[1]) - tmp925.coeffs[2:order + 1] .= zero(tmp925.coeffs[1]) - r_x_unit.coeffs[1] = -(constant_term(tmp925)) - r_x_unit.coeffs[2:order + 1] .= zero(r_x_unit.coeffs[1]) - tmp927.coeffs[1] = constant_term(Y[1]) / constant_term(r_p1d2[1]) - tmp927.coeffs[2:order + 1] .= zero(tmp927.coeffs[1]) - r_y_unit.coeffs[1] = -(constant_term(tmp927)) - r_y_unit.coeffs[2:order + 1] .= zero(r_y_unit.coeffs[1]) - tmp929.coeffs[1] = constant_term(Z[1]) / constant_term(r_p1d2[1]) - tmp929.coeffs[2:order + 1] .= zero(tmp929.coeffs[1]) - r_z_unit.coeffs[1] = -(constant_term(tmp929)) - r_z_unit.coeffs[2:order + 1] .= zero(r_z_unit.coeffs[1]) - g_r.coeffs[1] = identity(constant_term(r_p2[1])) - g_r.coeffs[2:order + 1] .= zero(g_r.coeffs[1]) - A2_t_g_r.coeffs[1] = constant_term(q[7]) / constant_term(g_r) - A2_t_g_r.coeffs[2:order + 1] .= zero(A2_t_g_r.coeffs[1]) - A1_t_g_r.coeffs[1] = constant_term(q[8]) / constant_term(g_r) - A1_t_g_r.coeffs[2:order + 1] .= zero(A1_t_g_r.coeffs[1]) - tmp933.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_x_unit) - tmp933.coeffs[2:order + 1] .= zero(tmp933.coeffs[1]) - tmp934.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_x_unit) - tmp934.coeffs[2:order + 1] .= zero(tmp934.coeffs[1]) - NGAx.coeffs[1] = constant_term(tmp933) + constant_term(tmp934) - NGAx.coeffs[2:order + 1] .= zero(NGAx.coeffs[1]) - tmp936.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_y_unit) - tmp936.coeffs[2:order + 1] .= zero(tmp936.coeffs[1]) - tmp937.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_y_unit) - tmp937.coeffs[2:order + 1] .= zero(tmp937.coeffs[1]) - NGAy.coeffs[1] = constant_term(tmp936) + constant_term(tmp937) - NGAy.coeffs[2:order + 1] .= zero(NGAy.coeffs[1]) - tmp939.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_z_unit) - tmp939.coeffs[2:order + 1] .= zero(tmp939.coeffs[1]) - tmp940.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_z_unit) - tmp940.coeffs[2:order + 1] .= zero(tmp940.coeffs[1]) - NGAz.coeffs[1] = constant_term(tmp939) + constant_term(tmp940) - NGAz.coeffs[2:order + 1] .= zero(NGAz.coeffs[1]) - tmp942.coeffs[1] = constant_term(postNewtonX) + constant_term(accX) - tmp942.coeffs[2:order + 1] .= zero(tmp942.coeffs[1]) - (dq[4]).coeffs[1] = constant_term(tmp942) + constant_term(NGAx) - (dq[4]).coeffs[2:order + 1] .= zero((dq[4]).coeffs[1]) - tmp944.coeffs[1] = constant_term(postNewtonY) + constant_term(accY) - tmp944.coeffs[2:order + 1] .= zero(tmp944.coeffs[1]) - (dq[5]).coeffs[1] = constant_term(tmp944) + constant_term(NGAy) - (dq[5]).coeffs[2:order + 1] .= zero((dq[5]).coeffs[1]) - tmp946.coeffs[1] = constant_term(postNewtonZ) + constant_term(accZ) - tmp946.coeffs[2:order + 1] .= zero(tmp946.coeffs[1]) - (dq[6]).coeffs[1] = constant_term(tmp946) + constant_term(NGAz) - (dq[6]).coeffs[2:order + 1] .= zero((dq[6]).coeffs[1]) - (dq[7]).coeffs[1] = identity(constant_term(zero_q_1)) - (dq[7]).coeffs[2:order + 1] .= zero((dq[7]).coeffs[1]) - for __idx = eachindex(q) - (q[__idx]).coeffs[2] = (dq[__idx]).coeffs[1] - end - for ord = 1:order - 1 - ordnext = ord + 1 - TaylorSeries.identity!(pntempX, zero_q_1, ord) - TaylorSeries.identity!(pntempY, zero_q_1, ord) - TaylorSeries.identity!(pntempZ, zero_q_1, ord) - TaylorSeries.identity!(accX, zero_q_1, ord) - TaylorSeries.identity!(accY, zero_q_1, ord) - TaylorSeries.identity!(accZ, zero_q_1, ord) - TaylorSeries.identity!(dq[1], q[4], ord) - TaylorSeries.identity!(dq[2], q[5], ord) - TaylorSeries.identity!(dq[3], q[6], ord) - TaylorSeries.identity!(newtonianNb_Potential[N], zero_q_1, ord) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 - TaylorSeries.identity!(ui[i], ss16asteph_t[3 * ((N - 1) + i) - 2], ord) - TaylorSeries.identity!(vi[i], ss16asteph_t[3 * ((N - 1) + i) - 1], ord) - TaylorSeries.identity!(wi[i], ss16asteph_t[3 * ((N - 1) + i)], ord) - TaylorSeries.subst!(X[i], ss16asteph_t[3i - 2], q[1], ord) - TaylorSeries.subst!(Y[i], ss16asteph_t[3i - 1], q[2], ord) - TaylorSeries.subst!(Z[i], ss16asteph_t[3i], q[3], ord) - TaylorSeries.subst!(U[i], ui[i], dq[1], ord) - TaylorSeries.subst!(V[i], vi[i], dq[2], ord) - TaylorSeries.subst!(W[i], wi[i], dq[3], ord) - TaylorSeries.mul!(tmp687[1], 4, dq[1], ord) - TaylorSeries.mul!(tmp689[i], 3, ui[i], ord) - TaylorSeries.subst!(_4U_m_3X[i], tmp687[1], tmp689[i], ord) - TaylorSeries.mul!(tmp692[2], 4, dq[2], ord) - TaylorSeries.mul!(tmp694[i], 3, vi[i], ord) - TaylorSeries.subst!(_4V_m_3Y[i], tmp692[2], tmp694[i], ord) - TaylorSeries.mul!(tmp697[3], 4, dq[3], ord) - TaylorSeries.mul!(tmp699[i], 3, wi[i], ord) - TaylorSeries.subst!(_4W_m_3Z[i], tmp697[3], tmp699[i], ord) - TaylorSeries.mul!(pn2x[i], X[i], _4U_m_3X[i], ord) - TaylorSeries.mul!(pn2y[i], Y[i], _4V_m_3Y[i], ord) - TaylorSeries.mul!(pn2z[i], Z[i], _4W_m_3Z[i], ord) - TaylorSeries.mul!(UU[i], ui[i], dq[1], ord) - TaylorSeries.mul!(VV[i], vi[i], dq[2], ord) - TaylorSeries.mul!(WW[i], wi[i], dq[3], ord) - TaylorSeries.add!(tmp707[i], UU[i], VV[i], ord) - TaylorSeries.add!(vi_dot_vj[i], tmp707[i], WW[i], ord) - TaylorSeries.pow!(tmp710[i], X[i], 2, ord) - TaylorSeries.pow!(tmp712[i], Y[i], 2, ord) - TaylorSeries.add!(tmp713[i], tmp710[i], tmp712[i], ord) - TaylorSeries.pow!(tmp715[i], Z[i], 2, ord) - TaylorSeries.add!(r_p2[i], tmp713[i], tmp715[i], ord) - TaylorSeries.sqrt!(r_p1d2[i], r_p2[i], ord) - TaylorSeries.pow!(r_p3d2[i], r_p2[i], 1.5, ord) - TaylorSeries.pow!(r_p7d2[i], r_p2[i], 3.5, ord) - TaylorSeries.div!(newtonianCoeff[i], μ[i], r_p3d2[i], ord) - TaylorSeries.add!(tmp723[i], pn2x[i], pn2y[i], ord) - TaylorSeries.add!(tmp724[i], tmp723[i], pn2z[i], ord) - TaylorSeries.mul!(pn2[i], newtonianCoeff[i], tmp724[i], ord) - TaylorSeries.mul!(newton_acc_X[i], X[i], newtonianCoeff[i], ord) - TaylorSeries.mul!(newton_acc_Y[i], Y[i], newtonianCoeff[i], ord) - TaylorSeries.mul!(newton_acc_Z[i], Z[i], newtonianCoeff[i], ord) - TaylorSeries.div!(newtonian1b_Potential[i], μ[i], r_p1d2[i], ord) - TaylorSeries.mul!(pn3[i], 3.5, newtonian1b_Potential[i], ord) - TaylorSeries.mul!(U_t_pn2[i], pn2[i], U[i], ord) - TaylorSeries.mul!(V_t_pn2[i], pn2[i], V[i], ord) - TaylorSeries.mul!(W_t_pn2[i], pn2[i], W[i], ord) - if UJ_interaction[i] - TaylorSeries.subst!(tmp735[i], X[i], ord) - TaylorSeries.mul!(t31[i], tmp735[i], M_[1, 3, i], ord) - TaylorSeries.subst!(tmp737[i], Y[i], ord) - TaylorSeries.mul!(t32[i], tmp737[i], M_[2, 3, i], ord) - TaylorSeries.subst!(tmp739[i], Z[i], ord) - TaylorSeries.mul!(t33[i], tmp739[i], M_[3, 3, i], ord) - TaylorSeries.add!(tmp741[i], t31[i], t32[i], ord) - TaylorSeries.add!(r_sin_ϕ[i], tmp741[i], t33[i], ord) - TaylorSeries.div!(sin_ϕ[i], r_sin_ϕ[i], r_p1d2[i], ord) - TaylorSeries.asin!(ϕ[i], sin_ϕ[i], tmp948[i], ord) - TaylorSeries.sincos!(tmp949[i], cos_ϕ[i], ϕ[i], ord) - TaylorSeries.pow!(sin2_ϕ[i], sin_ϕ[i], 2, ord) - TaylorSeries.pow!(sin3_ϕ[i], sin_ϕ[i], 3, ord) - TaylorSeries.mul!(tmp751[i], 1.5, sin2_ϕ[i], ord) - TaylorSeries.subst!(P_2_sin_ϕ[i], tmp751[i], 0.5, ord) - TaylorSeries.mul!(∂P_2_sin_ϕ[i], 3, sin_ϕ[i], ord) - TaylorSeries.mul!(tmp757[i], -1.5, sin_ϕ[i], ord) - TaylorSeries.mul!(tmp759[i], 2.5, sin3_ϕ[i], ord) - TaylorSeries.add!(P_3_sin_ϕ[i], tmp757[i], tmp759[i], ord) - TaylorSeries.mul!(tmp763[i], 7.5, sin2_ϕ[i], ord) - TaylorSeries.add!(∂P_3_sin_ϕ[i], -1.5, tmp763[i], ord) - TaylorSeries.pow!(tmp766[i], r_p2[i], 2, ord) - TaylorSeries.div!(tmp767[i], Λ2[i], tmp766[i], ord) - TaylorSeries.subst!(Λ2j_div_r4[i], tmp767[i], ord) - TaylorSeries.pow!(tmp770[i], r_p1d2[i], 5, ord) - TaylorSeries.div!(tmp771[i], Λ3[i], tmp770[i], ord) - TaylorSeries.subst!(Λ3j_div_r5[i], tmp771[i], ord) - TaylorSeries.subst!(tmp773[i], cos_ϕ[i], ord) - TaylorSeries.mul!(m_c_ϕ_∂P_2[i], tmp773[i], ∂P_2_sin_ϕ[i], ord) - TaylorSeries.subst!(tmp775[i], cos_ϕ[i], ord) - TaylorSeries.mul!(m_c_ϕ_∂P_3[i], tmp775[i], ∂P_3_sin_ϕ[i], ord) - TaylorSeries.mul!(tmp778[i], Λ2j_div_r4[i], 3, ord) - TaylorSeries.mul!(F_J2_ξ[i], tmp778[i], P_2_sin_ϕ[i], ord) - TaylorSeries.mul!(F_J2_ζ[i], Λ2j_div_r4[i], m_c_ϕ_∂P_2[i], ord) - TaylorSeries.mul!(tmp782[i], Λ3j_div_r5[i], 4, ord) - TaylorSeries.mul!(F_J3_ξ[i], tmp782[i], P_3_sin_ϕ[i], ord) - TaylorSeries.mul!(F_J3_ζ[i], Λ3j_div_r5[i], m_c_ϕ_∂P_3[i], ord) - TaylorSeries.identity!(F_J_ξ[i], F_J2_ξ[i], ord) - TaylorSeries.identity!(F_J_ζ[i], F_J2_ζ[i], ord) - TaylorSeries.subst!(tmp785[i], X[i], ord) - TaylorSeries.div!(ξx[i], tmp785[i], r_p1d2[i], ord) - TaylorSeries.subst!(tmp787[i], Y[i], ord) - TaylorSeries.div!(ξy[i], tmp787[i], r_p1d2[i], ord) - TaylorSeries.subst!(tmp789[i], Z[i], ord) - TaylorSeries.div!(ξz[i], tmp789[i], r_p1d2[i], ord) - TaylorSeries.mul!(ηx1[i], M_[2, 3, i], ξz[i], ord) - TaylorSeries.mul!(ηy1[i], M_[3, 3, i], ξx[i], ord) - TaylorSeries.mul!(ηz1[i], M_[1, 3, i], ξy[i], ord) - TaylorSeries.mul!(ηx2[i], M_[3, 3, i], ξy[i], ord) - TaylorSeries.mul!(ηy2[i], M_[1, 3, i], ξz[i], ord) - TaylorSeries.mul!(ηz2[i], M_[2, 3, i], ξx[i], ord) - TaylorSeries.subst!(ηx[i], ηx1[i], ηx2[i], ord) - TaylorSeries.subst!(ηy[i], ηy1[i], ηy2[i], ord) - TaylorSeries.subst!(ηz[i], ηz1[i], ηz2[i], ord) - TaylorSeries.mul!(ζx1[i], ξy[i], ηz[i], ord) - TaylorSeries.mul!(ζy1[i], ξz[i], ηx[i], ord) - TaylorSeries.mul!(ζz1[i], ξx[i], ηy[i], ord) - TaylorSeries.mul!(ζx2[i], ξz[i], ηy[i], ord) - TaylorSeries.mul!(ζy2[i], ξx[i], ηz[i], ord) - TaylorSeries.mul!(ζz2[i], ξy[i], ηx[i], ord) - TaylorSeries.subst!(ζx[i], ζx1[i], ζx2[i], ord) - TaylorSeries.subst!(ζy[i], ζy1[i], ζy2[i], ord) - TaylorSeries.subst!(ζz[i], ζz1[i], ζz2[i], ord) - TaylorSeries.mul!(F_J2_x1[i], F_J_ξ[i], ξx[i], ord) - TaylorSeries.mul!(F_J2_y1[i], F_J_ξ[i], ξy[i], ord) - TaylorSeries.mul!(F_J2_z1[i], F_J_ξ[i], ξz[i], ord) - TaylorSeries.mul!(F_J2_x2[i], F_J_ζ[i], ζx[i], ord) - TaylorSeries.mul!(F_J2_y2[i], F_J_ζ[i], ζy[i], ord) - TaylorSeries.mul!(F_J2_z2[i], F_J_ζ[i], ζz[i], ord) - TaylorSeries.add!(F_J2_x[i], F_J2_x1[i], F_J2_x2[i], ord) - TaylorSeries.add!(F_J2_y[i], F_J2_y1[i], F_J2_y2[i], ord) - TaylorSeries.add!(F_J2_z[i], F_J2_z1[i], F_J2_z2[i], ord) - end - TaylorSeries.pow!(tmp819[i], ui[i], 2, ord) - TaylorSeries.pow!(tmp821[i], vi[i], 2, ord) - TaylorSeries.add!(tmp822[i], tmp819[i], tmp821[i], ord) - TaylorSeries.pow!(tmp824[i], wi[i], 2, ord) - TaylorSeries.add!(v2[i], tmp822[i], tmp824[i], ord) - end - TaylorSeries.pow!(tmp827, q[4], 2, ord) - TaylorSeries.pow!(tmp829, q[5], 2, ord) - TaylorSeries.add!(tmp830, tmp827, tmp829, ord) - TaylorSeries.pow!(tmp832, q[6], 2, ord) - TaylorSeries.add!(v2[N], tmp830, tmp832, ord) - for i = 1:Nm1 - TaylorSeries.add!(temp_004[i], newtonian1b_Potential[i], newtonianNb_Potential[N], ord) - TaylorSeries.identity!(newtonianNb_Potential[N], temp_004[i], ord) - if UJ_interaction[i] - TaylorSeries.mul!(tmp835[i], μ[i], F_J2_x[i], ord) - TaylorSeries.subst!(temp_accX_i[i], accX, tmp835[i], ord) - TaylorSeries.identity!(accX, temp_accX_i[i], ord) - TaylorSeries.mul!(tmp837[i], μ[i], F_J2_y[i], ord) - TaylorSeries.subst!(temp_accY_i[i], accY, tmp837[i], ord) - TaylorSeries.identity!(accY, temp_accY_i[i], ord) - TaylorSeries.mul!(tmp839[i], μ[i], F_J2_z[i], ord) - TaylorSeries.subst!(temp_accZ_i[i], accZ, tmp839[i], ord) - TaylorSeries.identity!(accZ, temp_accZ_i[i], ord) - end - end - TaylorSeries.mul!(_4ϕj[N], 4, newtonianNb_Potential[N], ord) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 - TaylorSeries.add!(ϕi_plus_4ϕj[i], newtonianNb_Potential_t[i], _4ϕj[N], ord) - TaylorSeries.mul!(tmp845[i], 2, v2[i], ord) - TaylorSeries.mul!(tmp847[i], 4, vi_dot_vj[i], ord) - TaylorSeries.subst!(tmp848[i], tmp845[i], tmp847[i], ord) - TaylorSeries.add!(sj2_plus_2si2_minus_4vivj[i], tmp848[i], v2[N], ord) - TaylorSeries.subst!(ϕs_and_vs[i], sj2_plus_2si2_minus_4vivj[i], ϕi_plus_4ϕj[i], ord) - TaylorSeries.mul!(Xij_t_Ui[i], X[i], ui[i], ord) - TaylorSeries.mul!(Yij_t_Vi[i], Y[i], vi[i], ord) - TaylorSeries.mul!(Zij_t_Wi[i], Z[i], wi[i], ord) - TaylorSeries.add!(tmp854[i], Xij_t_Ui[i], Yij_t_Vi[i], ord) - TaylorSeries.add!(Rij_dot_Vi[i], tmp854[i], Zij_t_Wi[i], ord) - TaylorSeries.pow!(tmp857[i], Rij_dot_Vi[i], 2, ord) - TaylorSeries.div!(pn1t7[i], tmp857[i], r_p2[i], ord) - TaylorSeries.mul!(tmp860[i], 1.5, pn1t7[i], ord) - TaylorSeries.subst!(pn1t2_7[i], ϕs_and_vs[i], tmp860[i], ord) - TaylorSeries.add!(pn1t1_7[i], c_p2, pn1t2_7[i], ord) - TaylorSeries.mul!(pNX_t_X[i], acceph_t[3i - 2], X[i], ord) - TaylorSeries.mul!(pNY_t_Y[i], acceph_t[3i - 1], Y[i], ord) - TaylorSeries.mul!(pNZ_t_Z[i], acceph_t[3i], Z[i], ord) - TaylorSeries.add!(tmp867[i], pNX_t_X[i], pNY_t_Y[i], ord) - TaylorSeries.add!(tmp868[i], tmp867[i], pNZ_t_Z[i], ord) - TaylorSeries.mul!(tmp869[i], 0.5, tmp868[i], ord) - TaylorSeries.add!(pn1[i], pn1t1_7[i], tmp869[i], ord) - TaylorSeries.mul!(X_t_pn1[i], newton_acc_X[i], pn1[i], ord) - TaylorSeries.mul!(Y_t_pn1[i], newton_acc_Y[i], pn1[i], ord) - TaylorSeries.mul!(Z_t_pn1[i], newton_acc_Z[i], pn1[i], ord) - TaylorSeries.mul!(pNX_t_pn3[i], acceph_t[3i - 2], pn3[i], ord) - TaylorSeries.mul!(pNY_t_pn3[i], acceph_t[3i - 1], pn3[i], ord) - TaylorSeries.mul!(pNZ_t_pn3[i], acceph_t[3i], pn3[i], ord) - end - for i = 1:10 - TaylorSeries.add!(tmp877[i], U_t_pn2[i], pNX_t_pn3[i], ord) - TaylorSeries.add!(termpnx[i], X_t_pn1[i], tmp877[i], ord) - TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) - TaylorSeries.identity!(pntempX, sumpnx[i], ord) - TaylorSeries.add!(tmp880[i], V_t_pn2[i], pNY_t_pn3[i], ord) - TaylorSeries.add!(termpny[i], Y_t_pn1[i], tmp880[i], ord) - TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) - TaylorSeries.identity!(pntempY, sumpny[i], ord) - TaylorSeries.add!(tmp883[i], W_t_pn2[i], pNZ_t_pn3[i], ord) - TaylorSeries.add!(termpnz[i], Z_t_pn1[i], tmp883[i], ord) - TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) - TaylorSeries.identity!(pntempZ, sumpnz[i], ord) - end - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 - TaylorSeries.mul!(X_t_pn1[i], c_p2, newton_acc_X[i], ord) - TaylorSeries.mul!(Y_t_pn1[i], c_p2, newton_acc_Y[i], ord) - TaylorSeries.mul!(Z_t_pn1[i], c_p2, newton_acc_Z[i], ord) - end - for i = 11:Nm1 - TaylorSeries.identity!(termpnx[i], X_t_pn1[i], ord) - TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) - TaylorSeries.identity!(pntempX, sumpnx[i], ord) - TaylorSeries.identity!(termpny[i], Y_t_pn1[i], ord) - TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) - TaylorSeries.identity!(pntempY, sumpny[i], ord) - TaylorSeries.identity!(termpnz[i], Z_t_pn1[i], ord) - TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) - TaylorSeries.identity!(pntempZ, sumpnz[i], ord) - end - TaylorSeries.mul!(postNewtonX, pntempX, c_m2, ord) - TaylorSeries.mul!(postNewtonY, pntempY, c_m2, ord) - TaylorSeries.mul!(postNewtonZ, pntempZ, c_m2, ord) - TaylorSeries.mul!(tmp895, Y[1], W[1], ord) - TaylorSeries.mul!(tmp896, Z[1], V[1], ord) - TaylorSeries.subst!(hx, tmp895, tmp896, ord) - TaylorSeries.mul!(tmp898, Z[1], U[1], ord) - TaylorSeries.mul!(tmp899, X[1], W[1], ord) - TaylorSeries.subst!(hy, tmp898, tmp899, ord) - TaylorSeries.mul!(tmp901, X[1], V[1], ord) - TaylorSeries.mul!(tmp902, Y[1], U[1], ord) - TaylorSeries.subst!(hz, tmp901, tmp902, ord) - TaylorSeries.mul!(tmp904, hz, Y[1], ord) - TaylorSeries.mul!(tmp905, hy, Z[1], ord) - TaylorSeries.subst!(t_x, tmp904, tmp905, ord) - TaylorSeries.mul!(tmp907, hx, Z[1], ord) - TaylorSeries.mul!(tmp908, hz, X[1], ord) - TaylorSeries.subst!(t_y, tmp907, tmp908, ord) - TaylorSeries.mul!(tmp910, hy, X[1], ord) - TaylorSeries.mul!(tmp911, hx, Y[1], ord) - TaylorSeries.subst!(t_z, tmp910, tmp911, ord) - TaylorSeries.pow!(tmp914, t_x, 2, ord) - TaylorSeries.pow!(tmp916, t_y, 2, ord) - TaylorSeries.add!(tmp917, tmp914, tmp916, ord) - TaylorSeries.pow!(tmp919, t_z, 2, ord) - TaylorSeries.add!(tmp920, tmp917, tmp919, ord) - TaylorSeries.sqrt!(t_norm, tmp920, ord) - TaylorSeries.div!(t_x_unit, t_x, t_norm, ord) - TaylorSeries.div!(t_y_unit, t_y, t_norm, ord) - TaylorSeries.div!(t_z_unit, t_z, t_norm, ord) - TaylorSeries.div!(tmp925, X[1], r_p1d2[1], ord) - TaylorSeries.subst!(r_x_unit, tmp925, ord) - TaylorSeries.div!(tmp927, Y[1], r_p1d2[1], ord) - TaylorSeries.subst!(r_y_unit, tmp927, ord) - TaylorSeries.div!(tmp929, Z[1], r_p1d2[1], ord) - TaylorSeries.subst!(r_z_unit, tmp929, ord) - TaylorSeries.identity!(g_r, r_p2[1], ord) - TaylorSeries.div!(A2_t_g_r, q[7], g_r, ord) - TaylorSeries.div!(A1_t_g_r, q[8], g_r, ord) - TaylorSeries.mul!(tmp933, A2_t_g_r, t_x_unit, ord) - TaylorSeries.mul!(tmp934, A1_t_g_r, r_x_unit, ord) - TaylorSeries.add!(NGAx, tmp933, tmp934, ord) - TaylorSeries.mul!(tmp936, A2_t_g_r, t_y_unit, ord) - TaylorSeries.mul!(tmp937, A1_t_g_r, r_y_unit, ord) - TaylorSeries.add!(NGAy, tmp936, tmp937, ord) - TaylorSeries.mul!(tmp939, A2_t_g_r, t_z_unit, ord) - TaylorSeries.mul!(tmp940, A1_t_g_r, r_z_unit, ord) - TaylorSeries.add!(NGAz, tmp939, tmp940, ord) - TaylorSeries.add!(tmp942, postNewtonX, accX, ord) - TaylorSeries.add!(dq[4], tmp942, NGAx, ord) - TaylorSeries.add!(tmp944, postNewtonY, accY, ord) - TaylorSeries.add!(dq[5], tmp944, NGAy, ord) - TaylorSeries.add!(tmp946, postNewtonZ, accZ, ord) - TaylorSeries.add!(dq[6], tmp946, NGAz, ord) - TaylorSeries.identity!(dq[7], zero_q_1, ord) - for __idx = eachindex(q) - (q[__idx]).coeffs[ordnext + 1] = (dq[__idx]).coeffs[ordnext] / ordnext - end - end - return nothing -end - -# TaylorIntegration._allocate_jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_eph_threads! -function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params) where {_T <: Real, _S <: Number, _N} - order = t.order - local jd0 = params[4] - local dsj2k = t + (jd0 - JD_J2000) - local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) - local acceph_t = evaleph(params[2], dsj2k, q[1]) - local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) - local S = eltype(q) - local UJ_interaction = params[5] - local N = params[6] - local Nm1 = N - 1 - local μ = params[7] - local zero_q_1 = auxzero(q[1]) - X = Array{S}(undef, N) - Y = Array{S}(undef, N) - Z = Array{S}(undef, N) - r_p2 = Array{S}(undef, N) - r_p1d2 = Array{S}(undef, N) - r_p3d2 = Array{S}(undef, N) - r_p7d2 = Array{S}(undef, N) - newtonianCoeff = Array{S}(undef, N) - ui = Array{S}(undef, N - 1) - vi = Array{S}(undef, N - 1) - wi = Array{S}(undef, N - 1) - U = Array{S}(undef, N) - V = Array{S}(undef, N) - W = Array{S}(undef, N) - _4U_m_3X = Array{S}(undef, N) - _4V_m_3Y = Array{S}(undef, N) - _4W_m_3Z = Array{S}(undef, N) - UU = Array{S}(undef, N) - VV = Array{S}(undef, N) - WW = Array{S}(undef, N) - newtonian1b_Potential = Array{S}(undef, N) - newtonianNb_Potential = Array{S}(undef, N) - newton_acc_X = Array{S}(undef, N) - newton_acc_Y = Array{S}(undef, N) - newton_acc_Z = Array{S}(undef, N) - v2 = Array{S}(undef, N) - vi_dot_vj = Array{S}(undef, N) - pn2 = Array{S}(undef, N) - U_t_pn2 = Array{S}(undef, N) - V_t_pn2 = Array{S}(undef, N) - W_t_pn2 = Array{S}(undef, N) - pn3 = Array{S}(undef, N) - pNX_t_pn3 = Array{S}(undef, N) - pNY_t_pn3 = Array{S}(undef, N) - pNZ_t_pn3 = Array{S}(undef, N) - _4ϕj = Array{S}(undef, N) - ϕi_plus_4ϕj = Array{S}(undef, N) - sj2_plus_2si2_minus_4vivj = Array{S}(undef, N) - ϕs_and_vs = Array{S}(undef, N) - pn1t1_7 = Array{S}(undef, N) - pNX_t_X = Array{S}(undef, N) - pNY_t_Y = Array{S}(undef, N) - pNZ_t_Z = Array{S}(undef, N) - pn1 = Array{S}(undef, N) - X_t_pn1 = Array{S}(undef, N) - Y_t_pn1 = Array{S}(undef, N) - Z_t_pn1 = Array{S}(undef, N) - pntempX = Taylor1(identity(constant_term(zero_q_1)), order) - pntempY = Taylor1(identity(constant_term(zero_q_1)), order) - pntempZ = Taylor1(identity(constant_term(zero_q_1)), order) - t31 = Array{S}(undef, N) - t32 = Array{S}(undef, N) - t33 = Array{S}(undef, N) - r_sin_ϕ = Array{S}(undef, N) - sin_ϕ = Array{S}(undef, N) - ϕ = Array{S}(undef, N) - cos_ϕ = Array{S}(undef, N) - sin2_ϕ = Array{S}(undef, N) - sin3_ϕ = Array{S}(undef, N) - sin4_ϕ = Array{S}(undef, N) - F_J2_x = Array{S}(undef, N) - F_J2_y = Array{S}(undef, N) - F_J2_z = Array{S}(undef, N) - F_J2_x1 = Array{S}(undef, N) - F_J2_y1 = Array{S}(undef, N) - F_J2_z1 = Array{S}(undef, N) - F_J2_x2 = Array{S}(undef, N) - F_J2_y2 = Array{S}(undef, N) - F_J2_z2 = Array{S}(undef, N) - temp_accX_i = Array{S}(undef, N) - temp_accY_i = Array{S}(undef, N) - temp_accZ_i = Array{S}(undef, N) - P_2_sin_ϕ = Array{S}(undef, N) - ∂P_2_sin_ϕ = Array{S}(undef, N) - P_3_sin_ϕ = Array{S}(undef, N) - ∂P_3_sin_ϕ = Array{S}(undef, N) - m_c_ϕ_∂P_2 = Array{S}(undef, N) - m_c_ϕ_∂P_3 = Array{S}(undef, N) - Λ2j_div_r4 = Array{S}(undef, N) - Λ3j_div_r5 = Array{S}(undef, N) - F_J_ξ = Array{S}(undef, N) - F_J_η = Array{S}(undef, N) - F_J_ζ = Array{S}(undef, N) - F_J2_ξ = Array{S}(undef, N) - F_J2_η = Array{S}(undef, N) - F_J2_ζ = Array{S}(undef, N) - F_J3_ξ = Array{S}(undef, N) - F_J3_η = Array{S}(undef, N) - F_J3_ζ = Array{S}(undef, N) - ξx = Array{S}(undef, N) - ξy = Array{S}(undef, N) - ξz = Array{S}(undef, N) - ηx = Array{S}(undef, N) - ηy = Array{S}(undef, N) - ηz = Array{S}(undef, N) - ηx1 = Array{S}(undef, N) - ηy1 = Array{S}(undef, N) - ηz1 = Array{S}(undef, N) - ηx2 = Array{S}(undef, N) - ηy2 = Array{S}(undef, N) - ηz2 = Array{S}(undef, N) - ζx = Array{S}(undef, N) - ζy = Array{S}(undef, N) - ζz = Array{S}(undef, N) - ζx1 = Array{S}(undef, N) - ζy1 = Array{S}(undef, N) - ζz1 = Array{S}(undef, N) - ζx2 = Array{S}(undef, N) - ζy2 = Array{S}(undef, N) - ζz2 = Array{S}(undef, N) - accX = Taylor1(identity(constant_term(zero_q_1)), order) - accY = Taylor1(identity(constant_term(zero_q_1)), order) - accZ = Taylor1(identity(constant_term(zero_q_1)), order) - local M_ = Array{S}(undef, 3, 3, N) - local M_ .= zero_q_1 - local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 - dq[1] = Taylor1(identity(constant_term(q[4])), order) - dq[2] = Taylor1(identity(constant_term(q[5])), order) - dq[3] = Taylor1(identity(constant_term(q[6])), order) - newtonianNb_Potential[N] = Taylor1(identity(constant_term(zero_q_1)), order) - tmp1317 = Array{Taylor1{_S}}(undef, size(dq)) - tmp1317 .= Taylor1(zero(constant_term(q[1])), order) - tmp1319 = Array{Taylor1{_S}}(undef, size(ui)) - tmp1319 .= Taylor1(zero(constant_term(q[1])), order) - tmp1322 = Array{Taylor1{_S}}(undef, size(dq)) - tmp1322 .= Taylor1(zero(constant_term(q[1])), order) - tmp1324 = Array{Taylor1{_S}}(undef, size(vi)) - tmp1324 .= Taylor1(zero(constant_term(q[1])), order) - tmp1327 = Array{Taylor1{_S}}(undef, size(dq)) - tmp1327 .= Taylor1(zero(constant_term(q[1])), order) - tmp1329 = Array{Taylor1{_S}}(undef, size(wi)) - tmp1329 .= Taylor1(zero(constant_term(q[1])), order) - pn2x = Array{Taylor1{_S}}(undef, size(X)) - pn2x .= Taylor1(zero(constant_term(q[1])), order) - pn2y = Array{Taylor1{_S}}(undef, size(Y)) - pn2y .= Taylor1(zero(constant_term(q[1])), order) - pn2z = Array{Taylor1{_S}}(undef, size(Z)) - pn2z .= Taylor1(zero(constant_term(q[1])), order) - tmp1337 = Array{Taylor1{_S}}(undef, size(UU)) - tmp1337 .= Taylor1(zero(constant_term(q[1])), order) - tmp1340 = Array{Taylor1{_S}}(undef, size(X)) - tmp1340 .= Taylor1(zero(constant_term(q[1])), order) - tmp1342 = Array{Taylor1{_S}}(undef, size(Y)) - tmp1342 .= Taylor1(zero(constant_term(q[1])), order) - tmp1343 = Array{Taylor1{_S}}(undef, size(tmp1340)) - tmp1343 .= Taylor1(zero(constant_term(q[1])), order) - tmp1345 = Array{Taylor1{_S}}(undef, size(Z)) - tmp1345 .= Taylor1(zero(constant_term(q[1])), order) - tmp1353 = Array{Taylor1{_S}}(undef, size(pn2x)) - tmp1353 .= Taylor1(zero(constant_term(q[1])), order) - tmp1354 = Array{Taylor1{_S}}(undef, size(tmp1353)) - tmp1354 .= Taylor1(zero(constant_term(q[1])), order) - tmp1449 = Array{Taylor1{_S}}(undef, size(ui)) - tmp1449 .= Taylor1(zero(constant_term(q[1])), order) - tmp1451 = Array{Taylor1{_S}}(undef, size(vi)) - tmp1451 .= Taylor1(zero(constant_term(q[1])), order) - tmp1452 = Array{Taylor1{_S}}(undef, size(tmp1449)) - tmp1452 .= Taylor1(zero(constant_term(q[1])), order) - tmp1454 = Array{Taylor1{_S}}(undef, size(wi)) - tmp1454 .= Taylor1(zero(constant_term(q[1])), order) - tmp1365 = Array{Taylor1{_S}}(undef, size(X)) - tmp1365 .= Taylor1(zero(constant_term(q[1])), order) - tmp1367 = Array{Taylor1{_S}}(undef, size(Y)) - tmp1367 .= Taylor1(zero(constant_term(q[1])), order) - tmp1369 = Array{Taylor1{_S}}(undef, size(Z)) - tmp1369 .= Taylor1(zero(constant_term(q[1])), order) - tmp1371 = Array{Taylor1{_S}}(undef, size(t31)) - tmp1371 .= Taylor1(zero(constant_term(q[1])), order) - tmp1528 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp1528 .= Taylor1(zero(constant_term(q[1])), order) - tmp1529 = Array{Taylor1{_S}}(undef, size(ϕ)) - tmp1529 .= Taylor1(zero(constant_term(q[1])), order) - tmp1381 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp1381 .= Taylor1(zero(constant_term(q[1])), order) - tmp1387 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp1387 .= Taylor1(zero(constant_term(q[1])), order) - tmp1389 = Array{Taylor1{_S}}(undef, size(sin3_ϕ)) - tmp1389 .= Taylor1(zero(constant_term(q[1])), order) - tmp1393 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp1393 .= Taylor1(zero(constant_term(q[1])), order) - tmp1396 = Array{Taylor1{_S}}(undef, size(r_p2)) - tmp1396 .= Taylor1(zero(constant_term(q[1])), order) - tmp1397 = Array{Taylor1{_S}}(undef, size(Λ2)) - tmp1397 .= Taylor1(zero(constant_term(q[1])), order) - tmp1400 = Array{Taylor1{_S}}(undef, size(r_p1d2)) - tmp1400 .= Taylor1(zero(constant_term(q[1])), order) - tmp1401 = Array{Taylor1{_S}}(undef, size(Λ3)) - tmp1401 .= Taylor1(zero(constant_term(q[1])), order) - tmp1403 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp1403 .= Taylor1(zero(constant_term(q[1])), order) - tmp1405 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp1405 .= Taylor1(zero(constant_term(q[1])), order) - tmp1408 = Array{Taylor1{_S}}(undef, size(Λ2j_div_r4)) - tmp1408 .= Taylor1(zero(constant_term(q[1])), order) - tmp1412 = Array{Taylor1{_S}}(undef, size(Λ3j_div_r5)) - tmp1412 .= Taylor1(zero(constant_term(q[1])), order) - tmp1415 = Array{Taylor1{_S}}(undef, size(X)) - tmp1415 .= Taylor1(zero(constant_term(q[1])), order) - tmp1417 = Array{Taylor1{_S}}(undef, size(Y)) - tmp1417 .= Taylor1(zero(constant_term(q[1])), order) - tmp1419 = Array{Taylor1{_S}}(undef, size(Z)) - tmp1419 .= Taylor1(zero(constant_term(q[1])), order) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 - ui[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])), order) - vi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])), order) - wi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])), order) - X[i] = Taylor1(constant_term(ss16asteph_t[3i - 2]) - constant_term(q[1]), order) - Y[i] = Taylor1(constant_term(ss16asteph_t[3i - 1]) - constant_term(q[2]), order) - Z[i] = Taylor1(constant_term(ss16asteph_t[3i]) - constant_term(q[3]), order) - U[i] = Taylor1(constant_term(ui[i]) - constant_term(dq[1]), order) - V[i] = Taylor1(constant_term(vi[i]) - constant_term(dq[2]), order) - W[i] = Taylor1(constant_term(wi[i]) - constant_term(dq[3]), order) - tmp1317[1] = Taylor1(constant_term(4) * constant_term(dq[1]), order) - tmp1319[i] = Taylor1(constant_term(3) * constant_term(ui[i]), order) - _4U_m_3X[i] = Taylor1(constant_term(tmp1317[1]) - constant_term(tmp1319[i]), order) - tmp1322[2] = Taylor1(constant_term(4) * constant_term(dq[2]), order) - tmp1324[i] = Taylor1(constant_term(3) * constant_term(vi[i]), order) - _4V_m_3Y[i] = Taylor1(constant_term(tmp1322[2]) - constant_term(tmp1324[i]), order) - tmp1327[3] = Taylor1(constant_term(4) * constant_term(dq[3]), order) - tmp1329[i] = Taylor1(constant_term(3) * constant_term(wi[i]), order) - _4W_m_3Z[i] = Taylor1(constant_term(tmp1327[3]) - constant_term(tmp1329[i]), order) - pn2x[i] = Taylor1(constant_term(X[i]) * constant_term(_4U_m_3X[i]), order) - pn2y[i] = Taylor1(constant_term(Y[i]) * constant_term(_4V_m_3Y[i]), order) - pn2z[i] = Taylor1(constant_term(Z[i]) * constant_term(_4W_m_3Z[i]), order) - UU[i] = Taylor1(constant_term(ui[i]) * constant_term(dq[1]), order) - VV[i] = Taylor1(constant_term(vi[i]) * constant_term(dq[2]), order) - WW[i] = Taylor1(constant_term(wi[i]) * constant_term(dq[3]), order) - tmp1337[i] = Taylor1(constant_term(UU[i]) + constant_term(VV[i]), order) - vi_dot_vj[i] = Taylor1(constant_term(tmp1337[i]) + constant_term(WW[i]), order) - tmp1340[i] = Taylor1(constant_term(X[i]) ^ float(constant_term(2)), order) - tmp1342[i] = Taylor1(constant_term(Y[i]) ^ float(constant_term(2)), order) - tmp1343[i] = Taylor1(constant_term(tmp1340[i]) + constant_term(tmp1342[i]), order) - tmp1345[i] = Taylor1(constant_term(Z[i]) ^ float(constant_term(2)), order) - r_p2[i] = Taylor1(constant_term(tmp1343[i]) + constant_term(tmp1345[i]), order) - r_p1d2[i] = Taylor1(sqrt(constant_term(r_p2[i])), order) - r_p3d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(1.5)), order) - r_p7d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(3.5)), order) - newtonianCoeff[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p3d2[i]), order) - tmp1353[i] = Taylor1(constant_term(pn2x[i]) + constant_term(pn2y[i]), order) - tmp1354[i] = Taylor1(constant_term(tmp1353[i]) + constant_term(pn2z[i]), order) - pn2[i] = Taylor1(constant_term(newtonianCoeff[i]) * constant_term(tmp1354[i]), order) - newton_acc_X[i] = Taylor1(constant_term(X[i]) * constant_term(newtonianCoeff[i]), order) - newton_acc_Y[i] = Taylor1(constant_term(Y[i]) * constant_term(newtonianCoeff[i]), order) - newton_acc_Z[i] = Taylor1(constant_term(Z[i]) * constant_term(newtonianCoeff[i]), order) - newtonian1b_Potential[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p1d2[i]), order) - pn3[i] = Taylor1(constant_term(3.5) * constant_term(newtonian1b_Potential[i]), order) - U_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(U[i]), order) - V_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(V[i]), order) - W_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(W[i]), order) - if UJ_interaction[i] - tmp1365[i] = Taylor1(-(constant_term(X[i])), order) - t31[i] = Taylor1(constant_term(tmp1365[i]) * constant_term(M_[1, 3, i]), order) - tmp1367[i] = Taylor1(-(constant_term(Y[i])), order) - t32[i] = Taylor1(constant_term(tmp1367[i]) * constant_term(M_[2, 3, i]), order) - tmp1369[i] = Taylor1(-(constant_term(Z[i])), order) - t33[i] = Taylor1(constant_term(tmp1369[i]) * constant_term(M_[3, 3, i]), order) - tmp1371[i] = Taylor1(constant_term(t31[i]) + constant_term(t32[i]), order) - r_sin_ϕ[i] = Taylor1(constant_term(tmp1371[i]) + constant_term(t33[i]), order) - sin_ϕ[i] = Taylor1(constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]), order) - ϕ[i] = Taylor1(asin(constant_term(sin_ϕ[i])), order) - tmp1528[i] = Taylor1(sqrt(1 - constant_term(sin_ϕ[i]) ^ 2), order) - cos_ϕ[i] = Taylor1(cos(constant_term(ϕ[i])), order) - tmp1529[i] = Taylor1(sin(constant_term(ϕ[i])), order) - sin2_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(2)), order) - sin3_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(3)), order) - tmp1381[i] = Taylor1(constant_term(1.5) * constant_term(sin2_ϕ[i]), order) - P_2_sin_ϕ[i] = Taylor1(constant_term(tmp1381[i]) - constant_term(0.5), order) - ∂P_2_sin_ϕ[i] = Taylor1(constant_term(3) * constant_term(sin_ϕ[i]), order) - tmp1387[i] = Taylor1(constant_term(-1.5) * constant_term(sin_ϕ[i]), order) - tmp1389[i] = Taylor1(constant_term(2.5) * constant_term(sin3_ϕ[i]), order) - P_3_sin_ϕ[i] = Taylor1(constant_term(tmp1387[i]) + constant_term(tmp1389[i]), order) - tmp1393[i] = Taylor1(constant_term(7.5) * constant_term(sin2_ϕ[i]), order) - ∂P_3_sin_ϕ[i] = Taylor1(constant_term(-1.5) + constant_term(tmp1393[i]), order) - tmp1396[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(2)), order) - tmp1397[i] = Taylor1(constant_term(Λ2[i]) / constant_term(tmp1396[i]), order) - Λ2j_div_r4[i] = Taylor1(-(constant_term(tmp1397[i])), order) - tmp1400[i] = Taylor1(constant_term(r_p1d2[i]) ^ float(constant_term(5)), order) - tmp1401[i] = Taylor1(constant_term(Λ3[i]) / constant_term(tmp1400[i]), order) - Λ3j_div_r5[i] = Taylor1(-(constant_term(tmp1401[i])), order) - tmp1403[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) - m_c_ϕ_∂P_2[i] = Taylor1(constant_term(tmp1403[i]) * constant_term(∂P_2_sin_ϕ[i]), order) - tmp1405[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) - m_c_ϕ_∂P_3[i] = Taylor1(constant_term(tmp1405[i]) * constant_term(∂P_3_sin_ϕ[i]), order) - tmp1408[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(3), order) - F_J2_ξ[i] = Taylor1(constant_term(tmp1408[i]) * constant_term(P_2_sin_ϕ[i]), order) - F_J2_ζ[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]), order) - tmp1412[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(4), order) - F_J3_ξ[i] = Taylor1(constant_term(tmp1412[i]) * constant_term(P_3_sin_ϕ[i]), order) - F_J3_ζ[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]), order) - F_J_ξ[i] = Taylor1(identity(constant_term(F_J2_ξ[i])), order) - F_J_ζ[i] = Taylor1(identity(constant_term(F_J2_ζ[i])), order) - tmp1415[i] = Taylor1(-(constant_term(X[i])), order) - ξx[i] = Taylor1(constant_term(tmp1415[i]) / constant_term(r_p1d2[i]), order) - tmp1417[i] = Taylor1(-(constant_term(Y[i])), order) - ξy[i] = Taylor1(constant_term(tmp1417[i]) / constant_term(r_p1d2[i]), order) - tmp1419[i] = Taylor1(-(constant_term(Z[i])), order) - ξz[i] = Taylor1(constant_term(tmp1419[i]) / constant_term(r_p1d2[i]), order) - ηx1[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξz[i]), order) - ηy1[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξx[i]), order) - ηz1[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξy[i]), order) - ηx2[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξy[i]), order) - ηy2[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξz[i]), order) - ηz2[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξx[i]), order) - ηx[i] = Taylor1(constant_term(ηx1[i]) - constant_term(ηx2[i]), order) - ηy[i] = Taylor1(constant_term(ηy1[i]) - constant_term(ηy2[i]), order) - ηz[i] = Taylor1(constant_term(ηz1[i]) - constant_term(ηz2[i]), order) - ζx1[i] = Taylor1(constant_term(ξy[i]) * constant_term(ηz[i]), order) - ζy1[i] = Taylor1(constant_term(ξz[i]) * constant_term(ηx[i]), order) - ζz1[i] = Taylor1(constant_term(ξx[i]) * constant_term(ηy[i]), order) - ζx2[i] = Taylor1(constant_term(ξz[i]) * constant_term(ηy[i]), order) - ζy2[i] = Taylor1(constant_term(ξx[i]) * constant_term(ηz[i]), order) - ζz2[i] = Taylor1(constant_term(ξy[i]) * constant_term(ηx[i]), order) - ζx[i] = Taylor1(constant_term(ζx1[i]) - constant_term(ζx2[i]), order) - ζy[i] = Taylor1(constant_term(ζy1[i]) - constant_term(ζy2[i]), order) - ζz[i] = Taylor1(constant_term(ζz1[i]) - constant_term(ζz2[i]), order) - F_J2_x1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξx[i]), order) - F_J2_y1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξy[i]), order) - F_J2_z1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξz[i]), order) - F_J2_x2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζx[i]), order) - F_J2_y2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζy[i]), order) - F_J2_z2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζz[i]), order) - F_J2_x[i] = Taylor1(constant_term(F_J2_x1[i]) + constant_term(F_J2_x2[i]), order) - F_J2_y[i] = Taylor1(constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]), order) - F_J2_z[i] = Taylor1(constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]), order) - end - tmp1449[i] = Taylor1(constant_term(ui[i]) ^ float(constant_term(2)), order) - tmp1451[i] = Taylor1(constant_term(vi[i]) ^ float(constant_term(2)), order) - tmp1452[i] = Taylor1(constant_term(tmp1449[i]) + constant_term(tmp1451[i]), order) - tmp1454[i] = Taylor1(constant_term(wi[i]) ^ float(constant_term(2)), order) - v2[i] = Taylor1(constant_term(tmp1452[i]) + constant_term(tmp1454[i]), order) - end - tmp1457 = Taylor1(constant_term(q[4]) ^ float(constant_term(2)), order) - tmp1459 = Taylor1(constant_term(q[5]) ^ float(constant_term(2)), order) - tmp1460 = Taylor1(constant_term(tmp1457) + constant_term(tmp1459), order) - tmp1462 = Taylor1(constant_term(q[6]) ^ float(constant_term(2)), order) - v2[N] = Taylor1(constant_term(tmp1460) + constant_term(tmp1462), order) - temp_004 = Array{Taylor1{_S}}(undef, size(newtonian1b_Potential)) - temp_004 .= Taylor1(zero(constant_term(q[1])), order) - tmp1465 = Array{Taylor1{_S}}(undef, size(μ)) - tmp1465 .= Taylor1(zero(constant_term(q[1])), order) - tmp1467 = Array{Taylor1{_S}}(undef, size(μ)) - tmp1467 .= Taylor1(zero(constant_term(q[1])), order) - tmp1469 = Array{Taylor1{_S}}(undef, size(μ)) - tmp1469 .= Taylor1(zero(constant_term(q[1])), order) - for i = 1:Nm1 - temp_004[i] = Taylor1(constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]), order) - newtonianNb_Potential[N] = Taylor1(identity(constant_term(temp_004[i])), order) - if UJ_interaction[i] - tmp1465[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_x[i]), order) - temp_accX_i[i] = Taylor1(constant_term(accX) - constant_term(tmp1465[i]), order) - accX = Taylor1(identity(constant_term(temp_accX_i[i])), order) - tmp1467[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_y[i]), order) - temp_accY_i[i] = Taylor1(constant_term(accY) - constant_term(tmp1467[i]), order) - accY = Taylor1(identity(constant_term(temp_accY_i[i])), order) - tmp1469[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_z[i]), order) - temp_accZ_i[i] = Taylor1(constant_term(accZ) - constant_term(tmp1469[i]), order) - accZ = Taylor1(identity(constant_term(temp_accZ_i[i])), order) - end - end - _4ϕj[N] = Taylor1(constant_term(4) * constant_term(newtonianNb_Potential[N]), order) - tmp1475 = Array{Taylor1{_S}}(undef, size(v2)) - tmp1475 .= Taylor1(zero(constant_term(q[1])), order) - tmp1477 = Array{Taylor1{_S}}(undef, size(vi_dot_vj)) - tmp1477 .= Taylor1(zero(constant_term(q[1])), order) - tmp1478 = Array{Taylor1{_S}}(undef, size(tmp1475)) - tmp1478 .= Taylor1(zero(constant_term(q[1])), order) - Xij_t_Ui = Array{Taylor1{_S}}(undef, size(X)) - Xij_t_Ui .= Taylor1(zero(constant_term(q[1])), order) - Yij_t_Vi = Array{Taylor1{_S}}(undef, size(Y)) - Yij_t_Vi .= Taylor1(zero(constant_term(q[1])), order) - Zij_t_Wi = Array{Taylor1{_S}}(undef, size(Z)) - Zij_t_Wi .= Taylor1(zero(constant_term(q[1])), order) - tmp1484 = Array{Taylor1{_S}}(undef, size(Xij_t_Ui)) - tmp1484 .= Taylor1(zero(constant_term(q[1])), order) - Rij_dot_Vi = Array{Taylor1{_S}}(undef, size(tmp1484)) - Rij_dot_Vi .= Taylor1(zero(constant_term(q[1])), order) - tmp1487 = Array{Taylor1{_S}}(undef, size(Rij_dot_Vi)) - tmp1487 .= Taylor1(zero(constant_term(q[1])), order) - pn1t7 = Array{Taylor1{_S}}(undef, size(tmp1487)) - pn1t7 .= Taylor1(zero(constant_term(q[1])), order) - tmp1490 = Array{Taylor1{_S}}(undef, size(pn1t7)) - tmp1490 .= Taylor1(zero(constant_term(q[1])), order) - pn1t2_7 = Array{Taylor1{_S}}(undef, size(ϕs_and_vs)) - pn1t2_7 .= Taylor1(zero(constant_term(q[1])), order) - tmp1497 = Array{Taylor1{_S}}(undef, size(pNX_t_X)) - tmp1497 .= Taylor1(zero(constant_term(q[1])), order) - tmp1498 = Array{Taylor1{_S}}(undef, size(tmp1497)) - tmp1498 .= Taylor1(zero(constant_term(q[1])), order) - tmp1499 = Array{Taylor1{_S}}(undef, size(tmp1498)) - tmp1499 .= Taylor1(zero(constant_term(q[1])), order) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 - ϕi_plus_4ϕj[i] = Taylor1(constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]), order) - tmp1475[i] = Taylor1(constant_term(2) * constant_term(v2[i]), order) - tmp1477[i] = Taylor1(constant_term(4) * constant_term(vi_dot_vj[i]), order) - tmp1478[i] = Taylor1(constant_term(tmp1475[i]) - constant_term(tmp1477[i]), order) - sj2_plus_2si2_minus_4vivj[i] = Taylor1(constant_term(tmp1478[i]) + constant_term(v2[N]), order) - ϕs_and_vs[i] = Taylor1(constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]), order) - Xij_t_Ui[i] = Taylor1(constant_term(X[i]) * constant_term(ui[i]), order) - Yij_t_Vi[i] = Taylor1(constant_term(Y[i]) * constant_term(vi[i]), order) - Zij_t_Wi[i] = Taylor1(constant_term(Z[i]) * constant_term(wi[i]), order) - tmp1484[i] = Taylor1(constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]), order) - Rij_dot_Vi[i] = Taylor1(constant_term(tmp1484[i]) + constant_term(Zij_t_Wi[i]), order) - tmp1487[i] = Taylor1(constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)), order) - pn1t7[i] = Taylor1(constant_term(tmp1487[i]) / constant_term(r_p2[i]), order) - tmp1490[i] = Taylor1(constant_term(1.5) * constant_term(pn1t7[i]), order) - pn1t2_7[i] = Taylor1(constant_term(ϕs_and_vs[i]) - constant_term(tmp1490[i]), order) - pn1t1_7[i] = Taylor1(constant_term(c_p2) + constant_term(pn1t2_7[i]), order) - pNX_t_X[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(X[i]), order) - pNY_t_Y[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(Y[i]), order) - pNZ_t_Z[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(Z[i]), order) - tmp1497[i] = Taylor1(constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]), order) - tmp1498[i] = Taylor1(constant_term(tmp1497[i]) + constant_term(pNZ_t_Z[i]), order) - tmp1499[i] = Taylor1(constant_term(0.5) * constant_term(tmp1498[i]), order) - pn1[i] = Taylor1(constant_term(pn1t1_7[i]) + constant_term(tmp1499[i]), order) - X_t_pn1[i] = Taylor1(constant_term(newton_acc_X[i]) * constant_term(pn1[i]), order) - Y_t_pn1[i] = Taylor1(constant_term(newton_acc_Y[i]) * constant_term(pn1[i]), order) - Z_t_pn1[i] = Taylor1(constant_term(newton_acc_Z[i]) * constant_term(pn1[i]), order) - pNX_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(pn3[i]), order) - pNY_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]), order) - pNZ_t_pn3[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(pn3[i]), order) - end - tmp1507 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) - tmp1507 .= Taylor1(zero(constant_term(q[1])), order) - termpnx = Array{Taylor1{_S}}(undef, size(X_t_pn1)) - termpnx .= Taylor1(zero(constant_term(q[1])), order) - sumpnx = Array{Taylor1{_S}}(undef, size(termpnx)) - sumpnx .= Taylor1(zero(constant_term(q[1])), order) - tmp1510 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) - tmp1510 .= Taylor1(zero(constant_term(q[1])), order) - termpny = Array{Taylor1{_S}}(undef, size(Y_t_pn1)) - termpny .= Taylor1(zero(constant_term(q[1])), order) - sumpny = Array{Taylor1{_S}}(undef, size(termpny)) - sumpny .= Taylor1(zero(constant_term(q[1])), order) - tmp1513 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) - tmp1513 .= Taylor1(zero(constant_term(q[1])), order) - termpnz = Array{Taylor1{_S}}(undef, size(Z_t_pn1)) - termpnz .= Taylor1(zero(constant_term(q[1])), order) - sumpnz = Array{Taylor1{_S}}(undef, size(termpnz)) - sumpnz .= Taylor1(zero(constant_term(q[1])), order) - for i = 1:10 - tmp1507[i] = Taylor1(constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]), order) - termpnx[i] = Taylor1(constant_term(X_t_pn1[i]) + constant_term(tmp1507[i]), order) - sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) - pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) - tmp1510[i] = Taylor1(constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]), order) - termpny[i] = Taylor1(constant_term(Y_t_pn1[i]) + constant_term(tmp1510[i]), order) - sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) - pntempY = Taylor1(identity(constant_term(sumpny[i])), order) - tmp1513[i] = Taylor1(constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]), order) - termpnz[i] = Taylor1(constant_term(Z_t_pn1[i]) + constant_term(tmp1513[i]), order) - sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) - pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) - end - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 - X_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_X[i]), order) - Y_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Y[i]), order) - Z_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Z[i]), order) - end - for i = 11:Nm1 - termpnx[i] = Taylor1(identity(constant_term(X_t_pn1[i])), order) - sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) - pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) - termpny[i] = Taylor1(identity(constant_term(Y_t_pn1[i])), order) - sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) - pntempY = Taylor1(identity(constant_term(sumpny[i])), order) - termpnz[i] = Taylor1(identity(constant_term(Z_t_pn1[i])), order) - sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) - pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) - end - postNewtonX = Taylor1(constant_term(pntempX) * constant_term(c_m2), order) - postNewtonY = Taylor1(constant_term(pntempY) * constant_term(c_m2), order) - postNewtonZ = Taylor1(constant_term(pntempZ) * constant_term(c_m2), order) - dq[4] = Taylor1(constant_term(postNewtonX) + constant_term(accX), order) - dq[5] = Taylor1(constant_term(postNewtonY) + constant_term(accY), order) - dq[6] = Taylor1(constant_term(postNewtonZ) + constant_term(accZ), order) - return TaylorIntegration.RetAlloc{Taylor1{_S}}([tmp1457, tmp1459, tmp1460, tmp1462, pntempX, pntempY, pntempZ, accX, accY, accZ, postNewtonX, postNewtonY, postNewtonZ], [X, Y, Z, r_p2, r_p1d2, r_p3d2, r_p7d2, newtonianCoeff, ui, vi, wi, U, V, W, _4U_m_3X, _4V_m_3Y, _4W_m_3Z, UU, VV, WW, newtonian1b_Potential, newtonianNb_Potential, newton_acc_X, newton_acc_Y, newton_acc_Z, v2, vi_dot_vj, pn2, U_t_pn2, V_t_pn2, W_t_pn2, pn3, pNX_t_pn3, pNY_t_pn3, pNZ_t_pn3, _4ϕj, ϕi_plus_4ϕj, sj2_plus_2si2_minus_4vivj, ϕs_and_vs, pn1t1_7, pNX_t_X, pNY_t_Y, pNZ_t_Z, pn1, X_t_pn1, Y_t_pn1, Z_t_pn1, t31, t32, t33, r_sin_ϕ, sin_ϕ, ϕ, cos_ϕ, sin2_ϕ, sin3_ϕ, F_J2_x, F_J2_y, F_J2_z, F_J2_x1, F_J2_y1, F_J2_z1, F_J2_x2, F_J2_y2, F_J2_z2, temp_accX_i, temp_accY_i, temp_accZ_i, P_2_sin_ϕ, ∂P_2_sin_ϕ, P_3_sin_ϕ, ∂P_3_sin_ϕ, m_c_ϕ_∂P_2, m_c_ϕ_∂P_3, Λ2j_div_r4, Λ3j_div_r5, F_J_ξ, F_J_ζ, F_J2_ξ, F_J2_ζ, F_J3_ξ, F_J3_ζ, ξx, ξy, ξz, ηx, ηy, ηz, ηx1, ηy1, ηz1, ηx2, ηy2, ηz2, ζx, ζy, ζz, ζx1, ζy1, ζz1, ζx2, ζy2, ζz2, tmp1317, tmp1319, tmp1322, tmp1324, tmp1327, tmp1329, pn2x, pn2y, pn2z, tmp1337, tmp1340, tmp1342, tmp1343, tmp1345, tmp1353, tmp1354, tmp1365, tmp1367, tmp1369, tmp1371, tmp1528, tmp1529, tmp1381, tmp1387, tmp1389, tmp1393, tmp1396, tmp1397, tmp1400, tmp1401, tmp1403, tmp1405, tmp1408, tmp1412, tmp1415, tmp1417, tmp1419, tmp1449, tmp1451, tmp1452, tmp1454, temp_004, tmp1465, tmp1467, tmp1469, tmp1475, tmp1477, tmp1478, Xij_t_Ui, Yij_t_Vi, Zij_t_Wi, tmp1484, Rij_dot_Vi, tmp1487, pn1t7, tmp1490, pn1t2_7, tmp1497, tmp1498, tmp1499, tmp1507, termpnx, sumpnx, tmp1510, termpny, sumpny, tmp1513, termpnz, sumpnz], [Array{Taylor1{_S}, 2}(undef, 0, 0)], [Array{Taylor1{_S}, 3}(undef, 0, 0, 0)], [Array{Taylor1{_S}, 4}(undef, 0, 0, 0, 0)]) -end - -# TaylorIntegration.jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_eph_threads! -function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params, __ralloc::TaylorIntegration.RetAlloc{Taylor1{_S}}) where {_T <: Real, _S <: Number, _N} - order = t.order - tmp1457 = __ralloc.v0[1] - tmp1459 = __ralloc.v0[2] - tmp1460 = __ralloc.v0[3] - tmp1462 = __ralloc.v0[4] - pntempX = __ralloc.v0[5] - pntempY = __ralloc.v0[6] - pntempZ = __ralloc.v0[7] - accX = __ralloc.v0[8] - accY = __ralloc.v0[9] - accZ = __ralloc.v0[10] - postNewtonX = __ralloc.v0[11] - postNewtonY = __ralloc.v0[12] - postNewtonZ = __ralloc.v0[13] - X = __ralloc.v1[1] - Y = __ralloc.v1[2] - Z = __ralloc.v1[3] - r_p2 = __ralloc.v1[4] - r_p1d2 = __ralloc.v1[5] - r_p3d2 = __ralloc.v1[6] - r_p7d2 = __ralloc.v1[7] - newtonianCoeff = __ralloc.v1[8] - ui = __ralloc.v1[9] - vi = __ralloc.v1[10] - wi = __ralloc.v1[11] - U = __ralloc.v1[12] - V = __ralloc.v1[13] - W = __ralloc.v1[14] - _4U_m_3X = __ralloc.v1[15] - _4V_m_3Y = __ralloc.v1[16] - _4W_m_3Z = __ralloc.v1[17] - UU = __ralloc.v1[18] - VV = __ralloc.v1[19] - WW = __ralloc.v1[20] - newtonian1b_Potential = __ralloc.v1[21] - newtonianNb_Potential = __ralloc.v1[22] - newton_acc_X = __ralloc.v1[23] - newton_acc_Y = __ralloc.v1[24] - newton_acc_Z = __ralloc.v1[25] - v2 = __ralloc.v1[26] - vi_dot_vj = __ralloc.v1[27] - pn2 = __ralloc.v1[28] - U_t_pn2 = __ralloc.v1[29] - V_t_pn2 = __ralloc.v1[30] - W_t_pn2 = __ralloc.v1[31] - pn3 = __ralloc.v1[32] - pNX_t_pn3 = __ralloc.v1[33] - pNY_t_pn3 = __ralloc.v1[34] - pNZ_t_pn3 = __ralloc.v1[35] - _4ϕj = __ralloc.v1[36] - ϕi_plus_4ϕj = __ralloc.v1[37] - sj2_plus_2si2_minus_4vivj = __ralloc.v1[38] - ϕs_and_vs = __ralloc.v1[39] - pn1t1_7 = __ralloc.v1[40] - pNX_t_X = __ralloc.v1[41] - pNY_t_Y = __ralloc.v1[42] - pNZ_t_Z = __ralloc.v1[43] - pn1 = __ralloc.v1[44] - X_t_pn1 = __ralloc.v1[45] - Y_t_pn1 = __ralloc.v1[46] - Z_t_pn1 = __ralloc.v1[47] - t31 = __ralloc.v1[48] - t32 = __ralloc.v1[49] - t33 = __ralloc.v1[50] - r_sin_ϕ = __ralloc.v1[51] - sin_ϕ = __ralloc.v1[52] - ϕ = __ralloc.v1[53] - cos_ϕ = __ralloc.v1[54] - sin2_ϕ = __ralloc.v1[55] - sin3_ϕ = __ralloc.v1[56] - F_J2_x = __ralloc.v1[57] - F_J2_y = __ralloc.v1[58] - F_J2_z = __ralloc.v1[59] - F_J2_x1 = __ralloc.v1[60] - F_J2_y1 = __ralloc.v1[61] - F_J2_z1 = __ralloc.v1[62] - F_J2_x2 = __ralloc.v1[63] - F_J2_y2 = __ralloc.v1[64] - F_J2_z2 = __ralloc.v1[65] - temp_accX_i = __ralloc.v1[66] - temp_accY_i = __ralloc.v1[67] - temp_accZ_i = __ralloc.v1[68] - P_2_sin_ϕ = __ralloc.v1[69] - ∂P_2_sin_ϕ = __ralloc.v1[70] - P_3_sin_ϕ = __ralloc.v1[71] - ∂P_3_sin_ϕ = __ralloc.v1[72] - m_c_ϕ_∂P_2 = __ralloc.v1[73] - m_c_ϕ_∂P_3 = __ralloc.v1[74] - Λ2j_div_r4 = __ralloc.v1[75] - Λ3j_div_r5 = __ralloc.v1[76] - F_J_ξ = __ralloc.v1[77] - F_J_ζ = __ralloc.v1[78] - F_J2_ξ = __ralloc.v1[79] - F_J2_ζ = __ralloc.v1[80] - F_J3_ξ = __ralloc.v1[81] - F_J3_ζ = __ralloc.v1[82] - ξx = __ralloc.v1[83] - ξy = __ralloc.v1[84] - ξz = __ralloc.v1[85] - ηx = __ralloc.v1[86] - ηy = __ralloc.v1[87] - ηz = __ralloc.v1[88] - ηx1 = __ralloc.v1[89] - ηy1 = __ralloc.v1[90] - ηz1 = __ralloc.v1[91] - ηx2 = __ralloc.v1[92] - ηy2 = __ralloc.v1[93] - ηz2 = __ralloc.v1[94] - ζx = __ralloc.v1[95] - ζy = __ralloc.v1[96] - ζz = __ralloc.v1[97] - ζx1 = __ralloc.v1[98] - ζy1 = __ralloc.v1[99] - ζz1 = __ralloc.v1[100] - ζx2 = __ralloc.v1[101] - ζy2 = __ralloc.v1[102] - ζz2 = __ralloc.v1[103] - tmp1317 = __ralloc.v1[104] - tmp1319 = __ralloc.v1[105] - tmp1322 = __ralloc.v1[106] - tmp1324 = __ralloc.v1[107] - tmp1327 = __ralloc.v1[108] - tmp1329 = __ralloc.v1[109] - pn2x = __ralloc.v1[110] - pn2y = __ralloc.v1[111] - pn2z = __ralloc.v1[112] - tmp1337 = __ralloc.v1[113] - tmp1340 = __ralloc.v1[114] - tmp1342 = __ralloc.v1[115] - tmp1343 = __ralloc.v1[116] - tmp1345 = __ralloc.v1[117] - tmp1353 = __ralloc.v1[118] - tmp1354 = __ralloc.v1[119] - tmp1365 = __ralloc.v1[120] - tmp1367 = __ralloc.v1[121] - tmp1369 = __ralloc.v1[122] - tmp1371 = __ralloc.v1[123] - tmp1528 = __ralloc.v1[124] - tmp1529 = __ralloc.v1[125] - tmp1381 = __ralloc.v1[126] - tmp1387 = __ralloc.v1[127] - tmp1389 = __ralloc.v1[128] - tmp1393 = __ralloc.v1[129] - tmp1396 = __ralloc.v1[130] - tmp1397 = __ralloc.v1[131] - tmp1400 = __ralloc.v1[132] - tmp1401 = __ralloc.v1[133] - tmp1403 = __ralloc.v1[134] - tmp1405 = __ralloc.v1[135] - tmp1408 = __ralloc.v1[136] - tmp1412 = __ralloc.v1[137] - tmp1415 = __ralloc.v1[138] - tmp1417 = __ralloc.v1[139] - tmp1419 = __ralloc.v1[140] - tmp1449 = __ralloc.v1[141] - tmp1451 = __ralloc.v1[142] - tmp1452 = __ralloc.v1[143] - tmp1454 = __ralloc.v1[144] - temp_004 = __ralloc.v1[145] - tmp1465 = __ralloc.v1[146] - tmp1467 = __ralloc.v1[147] - tmp1469 = __ralloc.v1[148] - tmp1475 = __ralloc.v1[149] - tmp1477 = __ralloc.v1[150] - tmp1478 = __ralloc.v1[151] - Xij_t_Ui = __ralloc.v1[152] - Yij_t_Vi = __ralloc.v1[153] - Zij_t_Wi = __ralloc.v1[154] - tmp1484 = __ralloc.v1[155] - Rij_dot_Vi = __ralloc.v1[156] - tmp1487 = __ralloc.v1[157] - pn1t7 = __ralloc.v1[158] - tmp1490 = __ralloc.v1[159] - pn1t2_7 = __ralloc.v1[160] - tmp1497 = __ralloc.v1[161] - tmp1498 = __ralloc.v1[162] - tmp1499 = __ralloc.v1[163] - tmp1507 = __ralloc.v1[164] - termpnx = __ralloc.v1[165] - sumpnx = __ralloc.v1[166] - tmp1510 = __ralloc.v1[167] - termpny = __ralloc.v1[168] - sumpny = __ralloc.v1[169] - tmp1513 = __ralloc.v1[170] - termpnz = __ralloc.v1[171] - sumpnz = __ralloc.v1[172] - local jd0 = params[4] - local dsj2k = t + (jd0 - JD_J2000) - local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) - local acceph_t = evaleph(params[2], dsj2k, q[1]) - local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) - local S = eltype(q) - local UJ_interaction = params[5] - local N = params[6] - local Nm1 = N - 1 - local μ = params[7] - local zero_q_1 = auxzero(q[1]) - pntempX.coeffs[1] = identity(constant_term(zero_q_1)) - pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) - pntempY.coeffs[1] = identity(constant_term(zero_q_1)) - pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) - pntempZ.coeffs[1] = identity(constant_term(zero_q_1)) - pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) - accX.coeffs[1] = identity(constant_term(zero_q_1)) - accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) - accY.coeffs[1] = identity(constant_term(zero_q_1)) - accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) - accZ.coeffs[1] = identity(constant_term(zero_q_1)) - accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) - local M_ = Array{S}(undef, 3, 3, N) - local M_ .= zero_q_1 - local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 - (dq[1]).coeffs[1] = identity(constant_term(q[4])) - (dq[1]).coeffs[2:order + 1] .= zero((dq[1]).coeffs[1]) - (dq[2]).coeffs[1] = identity(constant_term(q[5])) - (dq[2]).coeffs[2:order + 1] .= zero((dq[2]).coeffs[1]) - (dq[3]).coeffs[1] = identity(constant_term(q[6])) - (dq[3]).coeffs[2:order + 1] .= zero((dq[3]).coeffs[1]) - (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(zero_q_1)) - (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 - (ui[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])) - (ui[i]).coeffs[2:order + 1] .= zero((ui[i]).coeffs[1]) - (vi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])) - (vi[i]).coeffs[2:order + 1] .= zero((vi[i]).coeffs[1]) - (wi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])) - (wi[i]).coeffs[2:order + 1] .= zero((wi[i]).coeffs[1]) - (X[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 2]) - constant_term(q[1]) - (X[i]).coeffs[2:order + 1] .= zero((X[i]).coeffs[1]) - (Y[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 1]) - constant_term(q[2]) - (Y[i]).coeffs[2:order + 1] .= zero((Y[i]).coeffs[1]) - (Z[i]).coeffs[1] = constant_term(ss16asteph_t[3i]) - constant_term(q[3]) - (Z[i]).coeffs[2:order + 1] .= zero((Z[i]).coeffs[1]) - (U[i]).coeffs[1] = constant_term(ui[i]) - constant_term(dq[1]) - (U[i]).coeffs[2:order + 1] .= zero((U[i]).coeffs[1]) - (V[i]).coeffs[1] = constant_term(vi[i]) - constant_term(dq[2]) - (V[i]).coeffs[2:order + 1] .= zero((V[i]).coeffs[1]) - (W[i]).coeffs[1] = constant_term(wi[i]) - constant_term(dq[3]) - (W[i]).coeffs[2:order + 1] .= zero((W[i]).coeffs[1]) - (tmp1317[1]).coeffs[1] = constant_term(4) * constant_term(dq[1]) - (tmp1317[1]).coeffs[2:order + 1] .= zero((tmp1317[1]).coeffs[1]) - (tmp1319[i]).coeffs[1] = constant_term(3) * constant_term(ui[i]) - (tmp1319[i]).coeffs[2:order + 1] .= zero((tmp1319[i]).coeffs[1]) - (_4U_m_3X[i]).coeffs[1] = constant_term(tmp1317[1]) - constant_term(tmp1319[i]) - (_4U_m_3X[i]).coeffs[2:order + 1] .= zero((_4U_m_3X[i]).coeffs[1]) - (tmp1322[2]).coeffs[1] = constant_term(4) * constant_term(dq[2]) - (tmp1322[2]).coeffs[2:order + 1] .= zero((tmp1322[2]).coeffs[1]) - (tmp1324[i]).coeffs[1] = constant_term(3) * constant_term(vi[i]) - (tmp1324[i]).coeffs[2:order + 1] .= zero((tmp1324[i]).coeffs[1]) - (_4V_m_3Y[i]).coeffs[1] = constant_term(tmp1322[2]) - constant_term(tmp1324[i]) - (_4V_m_3Y[i]).coeffs[2:order + 1] .= zero((_4V_m_3Y[i]).coeffs[1]) - (tmp1327[3]).coeffs[1] = constant_term(4) * constant_term(dq[3]) - (tmp1327[3]).coeffs[2:order + 1] .= zero((tmp1327[3]).coeffs[1]) - (tmp1329[i]).coeffs[1] = constant_term(3) * constant_term(wi[i]) - (tmp1329[i]).coeffs[2:order + 1] .= zero((tmp1329[i]).coeffs[1]) - (_4W_m_3Z[i]).coeffs[1] = constant_term(tmp1327[3]) - constant_term(tmp1329[i]) - (_4W_m_3Z[i]).coeffs[2:order + 1] .= zero((_4W_m_3Z[i]).coeffs[1]) - (pn2x[i]).coeffs[1] = constant_term(X[i]) * constant_term(_4U_m_3X[i]) - (pn2x[i]).coeffs[2:order + 1] .= zero((pn2x[i]).coeffs[1]) - (pn2y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(_4V_m_3Y[i]) - (pn2y[i]).coeffs[2:order + 1] .= zero((pn2y[i]).coeffs[1]) - (pn2z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(_4W_m_3Z[i]) - (pn2z[i]).coeffs[2:order + 1] .= zero((pn2z[i]).coeffs[1]) - (UU[i]).coeffs[1] = constant_term(ui[i]) * constant_term(dq[1]) - (UU[i]).coeffs[2:order + 1] .= zero((UU[i]).coeffs[1]) - (VV[i]).coeffs[1] = constant_term(vi[i]) * constant_term(dq[2]) - (VV[i]).coeffs[2:order + 1] .= zero((VV[i]).coeffs[1]) - (WW[i]).coeffs[1] = constant_term(wi[i]) * constant_term(dq[3]) - (WW[i]).coeffs[2:order + 1] .= zero((WW[i]).coeffs[1]) - (tmp1337[i]).coeffs[1] = constant_term(UU[i]) + constant_term(VV[i]) - (tmp1337[i]).coeffs[2:order + 1] .= zero((tmp1337[i]).coeffs[1]) - (vi_dot_vj[i]).coeffs[1] = constant_term(tmp1337[i]) + constant_term(WW[i]) - (vi_dot_vj[i]).coeffs[2:order + 1] .= zero((vi_dot_vj[i]).coeffs[1]) - (tmp1340[i]).coeffs[1] = constant_term(X[i]) ^ float(constant_term(2)) - (tmp1340[i]).coeffs[2:order + 1] .= zero((tmp1340[i]).coeffs[1]) - (tmp1342[i]).coeffs[1] = constant_term(Y[i]) ^ float(constant_term(2)) - (tmp1342[i]).coeffs[2:order + 1] .= zero((tmp1342[i]).coeffs[1]) - (tmp1343[i]).coeffs[1] = constant_term(tmp1340[i]) + constant_term(tmp1342[i]) - (tmp1343[i]).coeffs[2:order + 1] .= zero((tmp1343[i]).coeffs[1]) - (tmp1345[i]).coeffs[1] = constant_term(Z[i]) ^ float(constant_term(2)) - (tmp1345[i]).coeffs[2:order + 1] .= zero((tmp1345[i]).coeffs[1]) - (r_p2[i]).coeffs[1] = constant_term(tmp1343[i]) + constant_term(tmp1345[i]) - (r_p2[i]).coeffs[2:order + 1] .= zero((r_p2[i]).coeffs[1]) - (r_p1d2[i]).coeffs[1] = sqrt(constant_term(r_p2[i])) - (r_p1d2[i]).coeffs[2:order + 1] .= zero((r_p1d2[i]).coeffs[1]) - (r_p3d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(1.5)) - (r_p3d2[i]).coeffs[2:order + 1] .= zero((r_p3d2[i]).coeffs[1]) - (r_p7d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(3.5)) - (r_p7d2[i]).coeffs[2:order + 1] .= zero((r_p7d2[i]).coeffs[1]) - (newtonianCoeff[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p3d2[i]) - (newtonianCoeff[i]).coeffs[2:order + 1] .= zero((newtonianCoeff[i]).coeffs[1]) - (tmp1353[i]).coeffs[1] = constant_term(pn2x[i]) + constant_term(pn2y[i]) - (tmp1353[i]).coeffs[2:order + 1] .= zero((tmp1353[i]).coeffs[1]) - (tmp1354[i]).coeffs[1] = constant_term(tmp1353[i]) + constant_term(pn2z[i]) - (tmp1354[i]).coeffs[2:order + 1] .= zero((tmp1354[i]).coeffs[1]) - (pn2[i]).coeffs[1] = constant_term(newtonianCoeff[i]) * constant_term(tmp1354[i]) - (pn2[i]).coeffs[2:order + 1] .= zero((pn2[i]).coeffs[1]) - (newton_acc_X[i]).coeffs[1] = constant_term(X[i]) * constant_term(newtonianCoeff[i]) - (newton_acc_X[i]).coeffs[2:order + 1] .= zero((newton_acc_X[i]).coeffs[1]) - (newton_acc_Y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(newtonianCoeff[i]) - (newton_acc_Y[i]).coeffs[2:order + 1] .= zero((newton_acc_Y[i]).coeffs[1]) - (newton_acc_Z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(newtonianCoeff[i]) - (newton_acc_Z[i]).coeffs[2:order + 1] .= zero((newton_acc_Z[i]).coeffs[1]) - (newtonian1b_Potential[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p1d2[i]) - (newtonian1b_Potential[i]).coeffs[2:order + 1] .= zero((newtonian1b_Potential[i]).coeffs[1]) - (pn3[i]).coeffs[1] = constant_term(3.5) * constant_term(newtonian1b_Potential[i]) - (pn3[i]).coeffs[2:order + 1] .= zero((pn3[i]).coeffs[1]) - (U_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(U[i]) - (U_t_pn2[i]).coeffs[2:order + 1] .= zero((U_t_pn2[i]).coeffs[1]) - (V_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(V[i]) - (V_t_pn2[i]).coeffs[2:order + 1] .= zero((V_t_pn2[i]).coeffs[1]) - (W_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(W[i]) - (W_t_pn2[i]).coeffs[2:order + 1] .= zero((W_t_pn2[i]).coeffs[1]) - if UJ_interaction[i] - (tmp1365[i]).coeffs[1] = -(constant_term(X[i])) - (tmp1365[i]).coeffs[2:order + 1] .= zero((tmp1365[i]).coeffs[1]) - (t31[i]).coeffs[1] = constant_term(tmp1365[i]) * constant_term(M_[1, 3, i]) - (t31[i]).coeffs[2:order + 1] .= zero((t31[i]).coeffs[1]) - (tmp1367[i]).coeffs[1] = -(constant_term(Y[i])) - (tmp1367[i]).coeffs[2:order + 1] .= zero((tmp1367[i]).coeffs[1]) - (t32[i]).coeffs[1] = constant_term(tmp1367[i]) * constant_term(M_[2, 3, i]) - (t32[i]).coeffs[2:order + 1] .= zero((t32[i]).coeffs[1]) - (tmp1369[i]).coeffs[1] = -(constant_term(Z[i])) - (tmp1369[i]).coeffs[2:order + 1] .= zero((tmp1369[i]).coeffs[1]) - (t33[i]).coeffs[1] = constant_term(tmp1369[i]) * constant_term(M_[3, 3, i]) - (t33[i]).coeffs[2:order + 1] .= zero((t33[i]).coeffs[1]) - (tmp1371[i]).coeffs[1] = constant_term(t31[i]) + constant_term(t32[i]) - (tmp1371[i]).coeffs[2:order + 1] .= zero((tmp1371[i]).coeffs[1]) - (r_sin_ϕ[i]).coeffs[1] = constant_term(tmp1371[i]) + constant_term(t33[i]) - (r_sin_ϕ[i]).coeffs[2:order + 1] .= zero((r_sin_ϕ[i]).coeffs[1]) - (sin_ϕ[i]).coeffs[1] = constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]) - (sin_ϕ[i]).coeffs[2:order + 1] .= zero((sin_ϕ[i]).coeffs[1]) - (ϕ[i]).coeffs[1] = asin(constant_term(sin_ϕ[i])) - (ϕ[i]).coeffs[2:order + 1] .= zero((ϕ[i]).coeffs[1]) - (tmp1528[i]).coeffs[1] = sqrt(1 - constant_term(sin_ϕ[i]) ^ 2) - (tmp1528[i]).coeffs[2:order + 1] .= zero((tmp1528[i]).coeffs[1]) - (cos_ϕ[i]).coeffs[1] = cos(constant_term(ϕ[i])) - (cos_ϕ[i]).coeffs[2:order + 1] .= zero((cos_ϕ[i]).coeffs[1]) - (tmp1529[i]).coeffs[1] = sin(constant_term(ϕ[i])) - (tmp1529[i]).coeffs[2:order + 1] .= zero((tmp1529[i]).coeffs[1]) - (sin2_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(2)) - (sin2_ϕ[i]).coeffs[2:order + 1] .= zero((sin2_ϕ[i]).coeffs[1]) - (sin3_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(3)) - (sin3_ϕ[i]).coeffs[2:order + 1] .= zero((sin3_ϕ[i]).coeffs[1]) - (tmp1381[i]).coeffs[1] = constant_term(1.5) * constant_term(sin2_ϕ[i]) - (tmp1381[i]).coeffs[2:order + 1] .= zero((tmp1381[i]).coeffs[1]) - (P_2_sin_ϕ[i]).coeffs[1] = constant_term(tmp1381[i]) - constant_term(0.5) - (P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_2_sin_ϕ[i]).coeffs[1]) - (∂P_2_sin_ϕ[i]).coeffs[1] = constant_term(3) * constant_term(sin_ϕ[i]) - (∂P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_2_sin_ϕ[i]).coeffs[1]) - (tmp1387[i]).coeffs[1] = constant_term(-1.5) * constant_term(sin_ϕ[i]) - (tmp1387[i]).coeffs[2:order + 1] .= zero((tmp1387[i]).coeffs[1]) - (tmp1389[i]).coeffs[1] = constant_term(2.5) * constant_term(sin3_ϕ[i]) - (tmp1389[i]).coeffs[2:order + 1] .= zero((tmp1389[i]).coeffs[1]) - (P_3_sin_ϕ[i]).coeffs[1] = constant_term(tmp1387[i]) + constant_term(tmp1389[i]) - (P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_3_sin_ϕ[i]).coeffs[1]) - (tmp1393[i]).coeffs[1] = constant_term(7.5) * constant_term(sin2_ϕ[i]) - (tmp1393[i]).coeffs[2:order + 1] .= zero((tmp1393[i]).coeffs[1]) - (∂P_3_sin_ϕ[i]).coeffs[1] = constant_term(-1.5) + constant_term(tmp1393[i]) - (∂P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_3_sin_ϕ[i]).coeffs[1]) - (tmp1396[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(2)) - (tmp1396[i]).coeffs[2:order + 1] .= zero((tmp1396[i]).coeffs[1]) - (tmp1397[i]).coeffs[1] = constant_term(Λ2[i]) / constant_term(tmp1396[i]) - (tmp1397[i]).coeffs[2:order + 1] .= zero((tmp1397[i]).coeffs[1]) - (Λ2j_div_r4[i]).coeffs[1] = -(constant_term(tmp1397[i])) - (Λ2j_div_r4[i]).coeffs[2:order + 1] .= zero((Λ2j_div_r4[i]).coeffs[1]) - (tmp1400[i]).coeffs[1] = constant_term(r_p1d2[i]) ^ float(constant_term(5)) - (tmp1400[i]).coeffs[2:order + 1] .= zero((tmp1400[i]).coeffs[1]) - (tmp1401[i]).coeffs[1] = constant_term(Λ3[i]) / constant_term(tmp1400[i]) - (tmp1401[i]).coeffs[2:order + 1] .= zero((tmp1401[i]).coeffs[1]) - (Λ3j_div_r5[i]).coeffs[1] = -(constant_term(tmp1401[i])) - (Λ3j_div_r5[i]).coeffs[2:order + 1] .= zero((Λ3j_div_r5[i]).coeffs[1]) - (tmp1403[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) - (tmp1403[i]).coeffs[2:order + 1] .= zero((tmp1403[i]).coeffs[1]) - (m_c_ϕ_∂P_2[i]).coeffs[1] = constant_term(tmp1403[i]) * constant_term(∂P_2_sin_ϕ[i]) - (m_c_ϕ_∂P_2[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_2[i]).coeffs[1]) - (tmp1405[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) - (tmp1405[i]).coeffs[2:order + 1] .= zero((tmp1405[i]).coeffs[1]) - (m_c_ϕ_∂P_3[i]).coeffs[1] = constant_term(tmp1405[i]) * constant_term(∂P_3_sin_ϕ[i]) - (m_c_ϕ_∂P_3[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_3[i]).coeffs[1]) - (tmp1408[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(3) - (tmp1408[i]).coeffs[2:order + 1] .= zero((tmp1408[i]).coeffs[1]) - (F_J2_ξ[i]).coeffs[1] = constant_term(tmp1408[i]) * constant_term(P_2_sin_ϕ[i]) - (F_J2_ξ[i]).coeffs[2:order + 1] .= zero((F_J2_ξ[i]).coeffs[1]) - (F_J2_ζ[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]) - (F_J2_ζ[i]).coeffs[2:order + 1] .= zero((F_J2_ζ[i]).coeffs[1]) - (tmp1412[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(4) - (tmp1412[i]).coeffs[2:order + 1] .= zero((tmp1412[i]).coeffs[1]) - (F_J3_ξ[i]).coeffs[1] = constant_term(tmp1412[i]) * constant_term(P_3_sin_ϕ[i]) - (F_J3_ξ[i]).coeffs[2:order + 1] .= zero((F_J3_ξ[i]).coeffs[1]) - (F_J3_ζ[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]) - (F_J3_ζ[i]).coeffs[2:order + 1] .= zero((F_J3_ζ[i]).coeffs[1]) - (F_J_ξ[i]).coeffs[1] = identity(constant_term(F_J2_ξ[i])) - (F_J_ξ[i]).coeffs[2:order + 1] .= zero((F_J_ξ[i]).coeffs[1]) - (F_J_ζ[i]).coeffs[1] = identity(constant_term(F_J2_ζ[i])) - (F_J_ζ[i]).coeffs[2:order + 1] .= zero((F_J_ζ[i]).coeffs[1]) - (tmp1415[i]).coeffs[1] = -(constant_term(X[i])) - (tmp1415[i]).coeffs[2:order + 1] .= zero((tmp1415[i]).coeffs[1]) - (ξx[i]).coeffs[1] = constant_term(tmp1415[i]) / constant_term(r_p1d2[i]) - (ξx[i]).coeffs[2:order + 1] .= zero((ξx[i]).coeffs[1]) - (tmp1417[i]).coeffs[1] = -(constant_term(Y[i])) - (tmp1417[i]).coeffs[2:order + 1] .= zero((tmp1417[i]).coeffs[1]) - (ξy[i]).coeffs[1] = constant_term(tmp1417[i]) / constant_term(r_p1d2[i]) - (ξy[i]).coeffs[2:order + 1] .= zero((ξy[i]).coeffs[1]) - (tmp1419[i]).coeffs[1] = -(constant_term(Z[i])) - (tmp1419[i]).coeffs[2:order + 1] .= zero((tmp1419[i]).coeffs[1]) - (ξz[i]).coeffs[1] = constant_term(tmp1419[i]) / constant_term(r_p1d2[i]) - (ξz[i]).coeffs[2:order + 1] .= zero((ξz[i]).coeffs[1]) - (ηx1[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξz[i]) - (ηx1[i]).coeffs[2:order + 1] .= zero((ηx1[i]).coeffs[1]) - (ηy1[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξx[i]) - (ηy1[i]).coeffs[2:order + 1] .= zero((ηy1[i]).coeffs[1]) - (ηz1[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξy[i]) - (ηz1[i]).coeffs[2:order + 1] .= zero((ηz1[i]).coeffs[1]) - (ηx2[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξy[i]) - (ηx2[i]).coeffs[2:order + 1] .= zero((ηx2[i]).coeffs[1]) - (ηy2[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξz[i]) - (ηy2[i]).coeffs[2:order + 1] .= zero((ηy2[i]).coeffs[1]) - (ηz2[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξx[i]) - (ηz2[i]).coeffs[2:order + 1] .= zero((ηz2[i]).coeffs[1]) - (ηx[i]).coeffs[1] = constant_term(ηx1[i]) - constant_term(ηx2[i]) - (ηx[i]).coeffs[2:order + 1] .= zero((ηx[i]).coeffs[1]) - (ηy[i]).coeffs[1] = constant_term(ηy1[i]) - constant_term(ηy2[i]) - (ηy[i]).coeffs[2:order + 1] .= zero((ηy[i]).coeffs[1]) - (ηz[i]).coeffs[1] = constant_term(ηz1[i]) - constant_term(ηz2[i]) - (ηz[i]).coeffs[2:order + 1] .= zero((ηz[i]).coeffs[1]) - (ζx1[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηz[i]) - (ζx1[i]).coeffs[2:order + 1] .= zero((ζx1[i]).coeffs[1]) - (ζy1[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηx[i]) - (ζy1[i]).coeffs[2:order + 1] .= zero((ζy1[i]).coeffs[1]) - (ζz1[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηy[i]) - (ζz1[i]).coeffs[2:order + 1] .= zero((ζz1[i]).coeffs[1]) - (ζx2[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηy[i]) - (ζx2[i]).coeffs[2:order + 1] .= zero((ζx2[i]).coeffs[1]) - (ζy2[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηz[i]) - (ζy2[i]).coeffs[2:order + 1] .= zero((ζy2[i]).coeffs[1]) - (ζz2[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηx[i]) - (ζz2[i]).coeffs[2:order + 1] .= zero((ζz2[i]).coeffs[1]) - (ζx[i]).coeffs[1] = constant_term(ζx1[i]) - constant_term(ζx2[i]) - (ζx[i]).coeffs[2:order + 1] .= zero((ζx[i]).coeffs[1]) - (ζy[i]).coeffs[1] = constant_term(ζy1[i]) - constant_term(ζy2[i]) - (ζy[i]).coeffs[2:order + 1] .= zero((ζy[i]).coeffs[1]) - (ζz[i]).coeffs[1] = constant_term(ζz1[i]) - constant_term(ζz2[i]) - (ζz[i]).coeffs[2:order + 1] .= zero((ζz[i]).coeffs[1]) - (F_J2_x1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξx[i]) - (F_J2_x1[i]).coeffs[2:order + 1] .= zero((F_J2_x1[i]).coeffs[1]) - (F_J2_y1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξy[i]) - (F_J2_y1[i]).coeffs[2:order + 1] .= zero((F_J2_y1[i]).coeffs[1]) - (F_J2_z1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξz[i]) - (F_J2_z1[i]).coeffs[2:order + 1] .= zero((F_J2_z1[i]).coeffs[1]) - (F_J2_x2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζx[i]) - (F_J2_x2[i]).coeffs[2:order + 1] .= zero((F_J2_x2[i]).coeffs[1]) - (F_J2_y2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζy[i]) - (F_J2_y2[i]).coeffs[2:order + 1] .= zero((F_J2_y2[i]).coeffs[1]) - (F_J2_z2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζz[i]) - (F_J2_z2[i]).coeffs[2:order + 1] .= zero((F_J2_z2[i]).coeffs[1]) - (F_J2_x[i]).coeffs[1] = constant_term(F_J2_x1[i]) + constant_term(F_J2_x2[i]) - (F_J2_x[i]).coeffs[2:order + 1] .= zero((F_J2_x[i]).coeffs[1]) - (F_J2_y[i]).coeffs[1] = constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]) - (F_J2_y[i]).coeffs[2:order + 1] .= zero((F_J2_y[i]).coeffs[1]) - (F_J2_z[i]).coeffs[1] = constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]) - (F_J2_z[i]).coeffs[2:order + 1] .= zero((F_J2_z[i]).coeffs[1]) - end - (tmp1449[i]).coeffs[1] = constant_term(ui[i]) ^ float(constant_term(2)) - (tmp1449[i]).coeffs[2:order + 1] .= zero((tmp1449[i]).coeffs[1]) - (tmp1451[i]).coeffs[1] = constant_term(vi[i]) ^ float(constant_term(2)) - (tmp1451[i]).coeffs[2:order + 1] .= zero((tmp1451[i]).coeffs[1]) - (tmp1452[i]).coeffs[1] = constant_term(tmp1449[i]) + constant_term(tmp1451[i]) - (tmp1452[i]).coeffs[2:order + 1] .= zero((tmp1452[i]).coeffs[1]) - (tmp1454[i]).coeffs[1] = constant_term(wi[i]) ^ float(constant_term(2)) - (tmp1454[i]).coeffs[2:order + 1] .= zero((tmp1454[i]).coeffs[1]) - (v2[i]).coeffs[1] = constant_term(tmp1452[i]) + constant_term(tmp1454[i]) - (v2[i]).coeffs[2:order + 1] .= zero((v2[i]).coeffs[1]) - end - tmp1457.coeffs[1] = constant_term(q[4]) ^ float(constant_term(2)) - tmp1457.coeffs[2:order + 1] .= zero(tmp1457.coeffs[1]) - tmp1459.coeffs[1] = constant_term(q[5]) ^ float(constant_term(2)) - tmp1459.coeffs[2:order + 1] .= zero(tmp1459.coeffs[1]) - tmp1460.coeffs[1] = constant_term(tmp1457) + constant_term(tmp1459) - tmp1460.coeffs[2:order + 1] .= zero(tmp1460.coeffs[1]) - tmp1462.coeffs[1] = constant_term(q[6]) ^ float(constant_term(2)) - tmp1462.coeffs[2:order + 1] .= zero(tmp1462.coeffs[1]) - (v2[N]).coeffs[1] = constant_term(tmp1460) + constant_term(tmp1462) - (v2[N]).coeffs[2:order + 1] .= zero((v2[N]).coeffs[1]) - for i = 1:Nm1 - (temp_004[i]).coeffs[1] = constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]) - (temp_004[i]).coeffs[2:order + 1] .= zero((temp_004[i]).coeffs[1]) - (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(temp_004[i])) - (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) - if UJ_interaction[i] - (tmp1465[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_x[i]) - (tmp1465[i]).coeffs[2:order + 1] .= zero((tmp1465[i]).coeffs[1]) - (temp_accX_i[i]).coeffs[1] = constant_term(accX) - constant_term(tmp1465[i]) - (temp_accX_i[i]).coeffs[2:order + 1] .= zero((temp_accX_i[i]).coeffs[1]) - accX.coeffs[1] = identity(constant_term(temp_accX_i[i])) - accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) - (tmp1467[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_y[i]) - (tmp1467[i]).coeffs[2:order + 1] .= zero((tmp1467[i]).coeffs[1]) - (temp_accY_i[i]).coeffs[1] = constant_term(accY) - constant_term(tmp1467[i]) - (temp_accY_i[i]).coeffs[2:order + 1] .= zero((temp_accY_i[i]).coeffs[1]) - accY.coeffs[1] = identity(constant_term(temp_accY_i[i])) - accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) - (tmp1469[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_z[i]) - (tmp1469[i]).coeffs[2:order + 1] .= zero((tmp1469[i]).coeffs[1]) - (temp_accZ_i[i]).coeffs[1] = constant_term(accZ) - constant_term(tmp1469[i]) - (temp_accZ_i[i]).coeffs[2:order + 1] .= zero((temp_accZ_i[i]).coeffs[1]) - accZ.coeffs[1] = identity(constant_term(temp_accZ_i[i])) - accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) - end - end - (_4ϕj[N]).coeffs[1] = constant_term(4) * constant_term(newtonianNb_Potential[N]) - (_4ϕj[N]).coeffs[2:order + 1] .= zero((_4ϕj[N]).coeffs[1]) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 - (ϕi_plus_4ϕj[i]).coeffs[1] = constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]) - (ϕi_plus_4ϕj[i]).coeffs[2:order + 1] .= zero((ϕi_plus_4ϕj[i]).coeffs[1]) - (tmp1475[i]).coeffs[1] = constant_term(2) * constant_term(v2[i]) - (tmp1475[i]).coeffs[2:order + 1] .= zero((tmp1475[i]).coeffs[1]) - (tmp1477[i]).coeffs[1] = constant_term(4) * constant_term(vi_dot_vj[i]) - (tmp1477[i]).coeffs[2:order + 1] .= zero((tmp1477[i]).coeffs[1]) - (tmp1478[i]).coeffs[1] = constant_term(tmp1475[i]) - constant_term(tmp1477[i]) - (tmp1478[i]).coeffs[2:order + 1] .= zero((tmp1478[i]).coeffs[1]) - (sj2_plus_2si2_minus_4vivj[i]).coeffs[1] = constant_term(tmp1478[i]) + constant_term(v2[N]) - (sj2_plus_2si2_minus_4vivj[i]).coeffs[2:order + 1] .= zero((sj2_plus_2si2_minus_4vivj[i]).coeffs[1]) - (ϕs_and_vs[i]).coeffs[1] = constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]) - (ϕs_and_vs[i]).coeffs[2:order + 1] .= zero((ϕs_and_vs[i]).coeffs[1]) - (Xij_t_Ui[i]).coeffs[1] = constant_term(X[i]) * constant_term(ui[i]) - (Xij_t_Ui[i]).coeffs[2:order + 1] .= zero((Xij_t_Ui[i]).coeffs[1]) - (Yij_t_Vi[i]).coeffs[1] = constant_term(Y[i]) * constant_term(vi[i]) - (Yij_t_Vi[i]).coeffs[2:order + 1] .= zero((Yij_t_Vi[i]).coeffs[1]) - (Zij_t_Wi[i]).coeffs[1] = constant_term(Z[i]) * constant_term(wi[i]) - (Zij_t_Wi[i]).coeffs[2:order + 1] .= zero((Zij_t_Wi[i]).coeffs[1]) - (tmp1484[i]).coeffs[1] = constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]) - (tmp1484[i]).coeffs[2:order + 1] .= zero((tmp1484[i]).coeffs[1]) - (Rij_dot_Vi[i]).coeffs[1] = constant_term(tmp1484[i]) + constant_term(Zij_t_Wi[i]) - (Rij_dot_Vi[i]).coeffs[2:order + 1] .= zero((Rij_dot_Vi[i]).coeffs[1]) - (tmp1487[i]).coeffs[1] = constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)) - (tmp1487[i]).coeffs[2:order + 1] .= zero((tmp1487[i]).coeffs[1]) - (pn1t7[i]).coeffs[1] = constant_term(tmp1487[i]) / constant_term(r_p2[i]) - (pn1t7[i]).coeffs[2:order + 1] .= zero((pn1t7[i]).coeffs[1]) - (tmp1490[i]).coeffs[1] = constant_term(1.5) * constant_term(pn1t7[i]) - (tmp1490[i]).coeffs[2:order + 1] .= zero((tmp1490[i]).coeffs[1]) - (pn1t2_7[i]).coeffs[1] = constant_term(ϕs_and_vs[i]) - constant_term(tmp1490[i]) - (pn1t2_7[i]).coeffs[2:order + 1] .= zero((pn1t2_7[i]).coeffs[1]) - (pn1t1_7[i]).coeffs[1] = constant_term(c_p2) + constant_term(pn1t2_7[i]) - (pn1t1_7[i]).coeffs[2:order + 1] .= zero((pn1t1_7[i]).coeffs[1]) - (pNX_t_X[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(X[i]) - (pNX_t_X[i]).coeffs[2:order + 1] .= zero((pNX_t_X[i]).coeffs[1]) - (pNY_t_Y[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(Y[i]) - (pNY_t_Y[i]).coeffs[2:order + 1] .= zero((pNY_t_Y[i]).coeffs[1]) - (pNZ_t_Z[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(Z[i]) - (pNZ_t_Z[i]).coeffs[2:order + 1] .= zero((pNZ_t_Z[i]).coeffs[1]) - (tmp1497[i]).coeffs[1] = constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]) - (tmp1497[i]).coeffs[2:order + 1] .= zero((tmp1497[i]).coeffs[1]) - (tmp1498[i]).coeffs[1] = constant_term(tmp1497[i]) + constant_term(pNZ_t_Z[i]) - (tmp1498[i]).coeffs[2:order + 1] .= zero((tmp1498[i]).coeffs[1]) - (tmp1499[i]).coeffs[1] = constant_term(0.5) * constant_term(tmp1498[i]) - (tmp1499[i]).coeffs[2:order + 1] .= zero((tmp1499[i]).coeffs[1]) - (pn1[i]).coeffs[1] = constant_term(pn1t1_7[i]) + constant_term(tmp1499[i]) - (pn1[i]).coeffs[2:order + 1] .= zero((pn1[i]).coeffs[1]) - (X_t_pn1[i]).coeffs[1] = constant_term(newton_acc_X[i]) * constant_term(pn1[i]) - (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) - (Y_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Y[i]) * constant_term(pn1[i]) - (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) - (Z_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Z[i]) * constant_term(pn1[i]) - (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) - (pNX_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(pn3[i]) - (pNX_t_pn3[i]).coeffs[2:order + 1] .= zero((pNX_t_pn3[i]).coeffs[1]) - (pNY_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]) - (pNY_t_pn3[i]).coeffs[2:order + 1] .= zero((pNY_t_pn3[i]).coeffs[1]) - (pNZ_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(pn3[i]) - (pNZ_t_pn3[i]).coeffs[2:order + 1] .= zero((pNZ_t_pn3[i]).coeffs[1]) - end - for i = 1:10 - (tmp1507[i]).coeffs[1] = constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]) - (tmp1507[i]).coeffs[2:order + 1] .= zero((tmp1507[i]).coeffs[1]) - (termpnx[i]).coeffs[1] = constant_term(X_t_pn1[i]) + constant_term(tmp1507[i]) - (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) - (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) - (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) - pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) - pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) - (tmp1510[i]).coeffs[1] = constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]) - (tmp1510[i]).coeffs[2:order + 1] .= zero((tmp1510[i]).coeffs[1]) - (termpny[i]).coeffs[1] = constant_term(Y_t_pn1[i]) + constant_term(tmp1510[i]) - (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) - (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) - (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) - pntempY.coeffs[1] = identity(constant_term(sumpny[i])) - pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) - (tmp1513[i]).coeffs[1] = constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]) - (tmp1513[i]).coeffs[2:order + 1] .= zero((tmp1513[i]).coeffs[1]) - (termpnz[i]).coeffs[1] = constant_term(Z_t_pn1[i]) + constant_term(tmp1513[i]) - (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) - (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) - (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) - pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) - pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) - end - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 - (X_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_X[i]) - (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) - (Y_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Y[i]) - (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) - (Z_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Z[i]) - (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) - end - for i = 11:Nm1 - (termpnx[i]).coeffs[1] = identity(constant_term(X_t_pn1[i])) - (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) - (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) - (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) - pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) - pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) - (termpny[i]).coeffs[1] = identity(constant_term(Y_t_pn1[i])) - (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) - (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) - (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) - pntempY.coeffs[1] = identity(constant_term(sumpny[i])) - pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) - (termpnz[i]).coeffs[1] = identity(constant_term(Z_t_pn1[i])) - (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) - (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) - (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) - pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) - pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) - end - postNewtonX.coeffs[1] = constant_term(pntempX) * constant_term(c_m2) - postNewtonX.coeffs[2:order + 1] .= zero(postNewtonX.coeffs[1]) - postNewtonY.coeffs[1] = constant_term(pntempY) * constant_term(c_m2) - postNewtonY.coeffs[2:order + 1] .= zero(postNewtonY.coeffs[1]) - postNewtonZ.coeffs[1] = constant_term(pntempZ) * constant_term(c_m2) - postNewtonZ.coeffs[2:order + 1] .= zero(postNewtonZ.coeffs[1]) - (dq[4]).coeffs[1] = constant_term(postNewtonX) + constant_term(accX) - (dq[4]).coeffs[2:order + 1] .= zero((dq[4]).coeffs[1]) - (dq[5]).coeffs[1] = constant_term(postNewtonY) + constant_term(accY) - (dq[5]).coeffs[2:order + 1] .= zero((dq[5]).coeffs[1]) - (dq[6]).coeffs[1] = constant_term(postNewtonZ) + constant_term(accZ) - (dq[6]).coeffs[2:order + 1] .= zero((dq[6]).coeffs[1]) - for __idx = eachindex(q) - (q[__idx]).coeffs[2] = (dq[__idx]).coeffs[1] - end - for ord = 1:order - 1 - ordnext = ord + 1 - TaylorSeries.identity!(pntempX, zero_q_1, ord) - TaylorSeries.identity!(pntempY, zero_q_1, ord) - TaylorSeries.identity!(pntempZ, zero_q_1, ord) - TaylorSeries.identity!(accX, zero_q_1, ord) - TaylorSeries.identity!(accY, zero_q_1, ord) - TaylorSeries.identity!(accZ, zero_q_1, ord) - TaylorSeries.identity!(dq[1], q[4], ord) - TaylorSeries.identity!(dq[2], q[5], ord) - TaylorSeries.identity!(dq[3], q[6], ord) - TaylorSeries.identity!(newtonianNb_Potential[N], zero_q_1, ord) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 - TaylorSeries.identity!(ui[i], ss16asteph_t[3 * ((N - 1) + i) - 2], ord) - TaylorSeries.identity!(vi[i], ss16asteph_t[3 * ((N - 1) + i) - 1], ord) - TaylorSeries.identity!(wi[i], ss16asteph_t[3 * ((N - 1) + i)], ord) - TaylorSeries.subst!(X[i], ss16asteph_t[3i - 2], q[1], ord) - TaylorSeries.subst!(Y[i], ss16asteph_t[3i - 1], q[2], ord) - TaylorSeries.subst!(Z[i], ss16asteph_t[3i], q[3], ord) - TaylorSeries.subst!(U[i], ui[i], dq[1], ord) - TaylorSeries.subst!(V[i], vi[i], dq[2], ord) - TaylorSeries.subst!(W[i], wi[i], dq[3], ord) - TaylorSeries.mul!(tmp1317[1], 4, dq[1], ord) - TaylorSeries.mul!(tmp1319[i], 3, ui[i], ord) - TaylorSeries.subst!(_4U_m_3X[i], tmp1317[1], tmp1319[i], ord) - TaylorSeries.mul!(tmp1322[2], 4, dq[2], ord) - TaylorSeries.mul!(tmp1324[i], 3, vi[i], ord) - TaylorSeries.subst!(_4V_m_3Y[i], tmp1322[2], tmp1324[i], ord) - TaylorSeries.mul!(tmp1327[3], 4, dq[3], ord) - TaylorSeries.mul!(tmp1329[i], 3, wi[i], ord) - TaylorSeries.subst!(_4W_m_3Z[i], tmp1327[3], tmp1329[i], ord) - TaylorSeries.mul!(pn2x[i], X[i], _4U_m_3X[i], ord) - TaylorSeries.mul!(pn2y[i], Y[i], _4V_m_3Y[i], ord) - TaylorSeries.mul!(pn2z[i], Z[i], _4W_m_3Z[i], ord) - TaylorSeries.mul!(UU[i], ui[i], dq[1], ord) - TaylorSeries.mul!(VV[i], vi[i], dq[2], ord) - TaylorSeries.mul!(WW[i], wi[i], dq[3], ord) - TaylorSeries.add!(tmp1337[i], UU[i], VV[i], ord) - TaylorSeries.add!(vi_dot_vj[i], tmp1337[i], WW[i], ord) - TaylorSeries.pow!(tmp1340[i], X[i], 2, ord) - TaylorSeries.pow!(tmp1342[i], Y[i], 2, ord) - TaylorSeries.add!(tmp1343[i], tmp1340[i], tmp1342[i], ord) - TaylorSeries.pow!(tmp1345[i], Z[i], 2, ord) - TaylorSeries.add!(r_p2[i], tmp1343[i], tmp1345[i], ord) - TaylorSeries.sqrt!(r_p1d2[i], r_p2[i], ord) - TaylorSeries.pow!(r_p3d2[i], r_p2[i], 1.5, ord) - TaylorSeries.pow!(r_p7d2[i], r_p2[i], 3.5, ord) - TaylorSeries.div!(newtonianCoeff[i], μ[i], r_p3d2[i], ord) - TaylorSeries.add!(tmp1353[i], pn2x[i], pn2y[i], ord) - TaylorSeries.add!(tmp1354[i], tmp1353[i], pn2z[i], ord) - TaylorSeries.mul!(pn2[i], newtonianCoeff[i], tmp1354[i], ord) - TaylorSeries.mul!(newton_acc_X[i], X[i], newtonianCoeff[i], ord) - TaylorSeries.mul!(newton_acc_Y[i], Y[i], newtonianCoeff[i], ord) - TaylorSeries.mul!(newton_acc_Z[i], Z[i], newtonianCoeff[i], ord) - TaylorSeries.div!(newtonian1b_Potential[i], μ[i], r_p1d2[i], ord) - TaylorSeries.mul!(pn3[i], 3.5, newtonian1b_Potential[i], ord) - TaylorSeries.mul!(U_t_pn2[i], pn2[i], U[i], ord) - TaylorSeries.mul!(V_t_pn2[i], pn2[i], V[i], ord) - TaylorSeries.mul!(W_t_pn2[i], pn2[i], W[i], ord) - if UJ_interaction[i] - TaylorSeries.subst!(tmp1365[i], X[i], ord) - TaylorSeries.mul!(t31[i], tmp1365[i], M_[1, 3, i], ord) - TaylorSeries.subst!(tmp1367[i], Y[i], ord) - TaylorSeries.mul!(t32[i], tmp1367[i], M_[2, 3, i], ord) - TaylorSeries.subst!(tmp1369[i], Z[i], ord) - TaylorSeries.mul!(t33[i], tmp1369[i], M_[3, 3, i], ord) - TaylorSeries.add!(tmp1371[i], t31[i], t32[i], ord) - TaylorSeries.add!(r_sin_ϕ[i], tmp1371[i], t33[i], ord) - TaylorSeries.div!(sin_ϕ[i], r_sin_ϕ[i], r_p1d2[i], ord) - TaylorSeries.asin!(ϕ[i], sin_ϕ[i], tmp1528[i], ord) - TaylorSeries.sincos!(tmp1529[i], cos_ϕ[i], ϕ[i], ord) - TaylorSeries.pow!(sin2_ϕ[i], sin_ϕ[i], 2, ord) - TaylorSeries.pow!(sin3_ϕ[i], sin_ϕ[i], 3, ord) - TaylorSeries.mul!(tmp1381[i], 1.5, sin2_ϕ[i], ord) - TaylorSeries.subst!(P_2_sin_ϕ[i], tmp1381[i], 0.5, ord) - TaylorSeries.mul!(∂P_2_sin_ϕ[i], 3, sin_ϕ[i], ord) - TaylorSeries.mul!(tmp1387[i], -1.5, sin_ϕ[i], ord) - TaylorSeries.mul!(tmp1389[i], 2.5, sin3_ϕ[i], ord) - TaylorSeries.add!(P_3_sin_ϕ[i], tmp1387[i], tmp1389[i], ord) - TaylorSeries.mul!(tmp1393[i], 7.5, sin2_ϕ[i], ord) - TaylorSeries.add!(∂P_3_sin_ϕ[i], -1.5, tmp1393[i], ord) - TaylorSeries.pow!(tmp1396[i], r_p2[i], 2, ord) - TaylorSeries.div!(tmp1397[i], Λ2[i], tmp1396[i], ord) - TaylorSeries.subst!(Λ2j_div_r4[i], tmp1397[i], ord) - TaylorSeries.pow!(tmp1400[i], r_p1d2[i], 5, ord) - TaylorSeries.div!(tmp1401[i], Λ3[i], tmp1400[i], ord) - TaylorSeries.subst!(Λ3j_div_r5[i], tmp1401[i], ord) - TaylorSeries.subst!(tmp1403[i], cos_ϕ[i], ord) - TaylorSeries.mul!(m_c_ϕ_∂P_2[i], tmp1403[i], ∂P_2_sin_ϕ[i], ord) - TaylorSeries.subst!(tmp1405[i], cos_ϕ[i], ord) - TaylorSeries.mul!(m_c_ϕ_∂P_3[i], tmp1405[i], ∂P_3_sin_ϕ[i], ord) - TaylorSeries.mul!(tmp1408[i], Λ2j_div_r4[i], 3, ord) - TaylorSeries.mul!(F_J2_ξ[i], tmp1408[i], P_2_sin_ϕ[i], ord) - TaylorSeries.mul!(F_J2_ζ[i], Λ2j_div_r4[i], m_c_ϕ_∂P_2[i], ord) - TaylorSeries.mul!(tmp1412[i], Λ3j_div_r5[i], 4, ord) - TaylorSeries.mul!(F_J3_ξ[i], tmp1412[i], P_3_sin_ϕ[i], ord) - TaylorSeries.mul!(F_J3_ζ[i], Λ3j_div_r5[i], m_c_ϕ_∂P_3[i], ord) - TaylorSeries.identity!(F_J_ξ[i], F_J2_ξ[i], ord) - TaylorSeries.identity!(F_J_ζ[i], F_J2_ζ[i], ord) - TaylorSeries.subst!(tmp1415[i], X[i], ord) - TaylorSeries.div!(ξx[i], tmp1415[i], r_p1d2[i], ord) - TaylorSeries.subst!(tmp1417[i], Y[i], ord) - TaylorSeries.div!(ξy[i], tmp1417[i], r_p1d2[i], ord) - TaylorSeries.subst!(tmp1419[i], Z[i], ord) - TaylorSeries.div!(ξz[i], tmp1419[i], r_p1d2[i], ord) - TaylorSeries.mul!(ηx1[i], M_[2, 3, i], ξz[i], ord) - TaylorSeries.mul!(ηy1[i], M_[3, 3, i], ξx[i], ord) - TaylorSeries.mul!(ηz1[i], M_[1, 3, i], ξy[i], ord) - TaylorSeries.mul!(ηx2[i], M_[3, 3, i], ξy[i], ord) - TaylorSeries.mul!(ηy2[i], M_[1, 3, i], ξz[i], ord) - TaylorSeries.mul!(ηz2[i], M_[2, 3, i], ξx[i], ord) - TaylorSeries.subst!(ηx[i], ηx1[i], ηx2[i], ord) - TaylorSeries.subst!(ηy[i], ηy1[i], ηy2[i], ord) - TaylorSeries.subst!(ηz[i], ηz1[i], ηz2[i], ord) - TaylorSeries.mul!(ζx1[i], ξy[i], ηz[i], ord) - TaylorSeries.mul!(ζy1[i], ξz[i], ηx[i], ord) - TaylorSeries.mul!(ζz1[i], ξx[i], ηy[i], ord) - TaylorSeries.mul!(ζx2[i], ξz[i], ηy[i], ord) - TaylorSeries.mul!(ζy2[i], ξx[i], ηz[i], ord) - TaylorSeries.mul!(ζz2[i], ξy[i], ηx[i], ord) - TaylorSeries.subst!(ζx[i], ζx1[i], ζx2[i], ord) - TaylorSeries.subst!(ζy[i], ζy1[i], ζy2[i], ord) - TaylorSeries.subst!(ζz[i], ζz1[i], ζz2[i], ord) - TaylorSeries.mul!(F_J2_x1[i], F_J_ξ[i], ξx[i], ord) - TaylorSeries.mul!(F_J2_y1[i], F_J_ξ[i], ξy[i], ord) - TaylorSeries.mul!(F_J2_z1[i], F_J_ξ[i], ξz[i], ord) - TaylorSeries.mul!(F_J2_x2[i], F_J_ζ[i], ζx[i], ord) - TaylorSeries.mul!(F_J2_y2[i], F_J_ζ[i], ζy[i], ord) - TaylorSeries.mul!(F_J2_z2[i], F_J_ζ[i], ζz[i], ord) - TaylorSeries.add!(F_J2_x[i], F_J2_x1[i], F_J2_x2[i], ord) - TaylorSeries.add!(F_J2_y[i], F_J2_y1[i], F_J2_y2[i], ord) - TaylorSeries.add!(F_J2_z[i], F_J2_z1[i], F_J2_z2[i], ord) - end - TaylorSeries.pow!(tmp1449[i], ui[i], 2, ord) - TaylorSeries.pow!(tmp1451[i], vi[i], 2, ord) - TaylorSeries.add!(tmp1452[i], tmp1449[i], tmp1451[i], ord) - TaylorSeries.pow!(tmp1454[i], wi[i], 2, ord) - TaylorSeries.add!(v2[i], tmp1452[i], tmp1454[i], ord) - end - TaylorSeries.pow!(tmp1457, q[4], 2, ord) - TaylorSeries.pow!(tmp1459, q[5], 2, ord) - TaylorSeries.add!(tmp1460, tmp1457, tmp1459, ord) - TaylorSeries.pow!(tmp1462, q[6], 2, ord) - TaylorSeries.add!(v2[N], tmp1460, tmp1462, ord) - for i = 1:Nm1 - TaylorSeries.add!(temp_004[i], newtonian1b_Potential[i], newtonianNb_Potential[N], ord) - TaylorSeries.identity!(newtonianNb_Potential[N], temp_004[i], ord) - if UJ_interaction[i] - TaylorSeries.mul!(tmp1465[i], μ[i], F_J2_x[i], ord) - TaylorSeries.subst!(temp_accX_i[i], accX, tmp1465[i], ord) - TaylorSeries.identity!(accX, temp_accX_i[i], ord) - TaylorSeries.mul!(tmp1467[i], μ[i], F_J2_y[i], ord) - TaylorSeries.subst!(temp_accY_i[i], accY, tmp1467[i], ord) - TaylorSeries.identity!(accY, temp_accY_i[i], ord) - TaylorSeries.mul!(tmp1469[i], μ[i], F_J2_z[i], ord) - TaylorSeries.subst!(temp_accZ_i[i], accZ, tmp1469[i], ord) - TaylorSeries.identity!(accZ, temp_accZ_i[i], ord) - end - end - TaylorSeries.mul!(_4ϕj[N], 4, newtonianNb_Potential[N], ord) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 - TaylorSeries.add!(ϕi_plus_4ϕj[i], newtonianNb_Potential_t[i], _4ϕj[N], ord) - TaylorSeries.mul!(tmp1475[i], 2, v2[i], ord) - TaylorSeries.mul!(tmp1477[i], 4, vi_dot_vj[i], ord) - TaylorSeries.subst!(tmp1478[i], tmp1475[i], tmp1477[i], ord) - TaylorSeries.add!(sj2_plus_2si2_minus_4vivj[i], tmp1478[i], v2[N], ord) - TaylorSeries.subst!(ϕs_and_vs[i], sj2_plus_2si2_minus_4vivj[i], ϕi_plus_4ϕj[i], ord) - TaylorSeries.mul!(Xij_t_Ui[i], X[i], ui[i], ord) - TaylorSeries.mul!(Yij_t_Vi[i], Y[i], vi[i], ord) - TaylorSeries.mul!(Zij_t_Wi[i], Z[i], wi[i], ord) - TaylorSeries.add!(tmp1484[i], Xij_t_Ui[i], Yij_t_Vi[i], ord) - TaylorSeries.add!(Rij_dot_Vi[i], tmp1484[i], Zij_t_Wi[i], ord) - TaylorSeries.pow!(tmp1487[i], Rij_dot_Vi[i], 2, ord) - TaylorSeries.div!(pn1t7[i], tmp1487[i], r_p2[i], ord) - TaylorSeries.mul!(tmp1490[i], 1.5, pn1t7[i], ord) - TaylorSeries.subst!(pn1t2_7[i], ϕs_and_vs[i], tmp1490[i], ord) - TaylorSeries.add!(pn1t1_7[i], c_p2, pn1t2_7[i], ord) - TaylorSeries.mul!(pNX_t_X[i], acceph_t[3i - 2], X[i], ord) - TaylorSeries.mul!(pNY_t_Y[i], acceph_t[3i - 1], Y[i], ord) - TaylorSeries.mul!(pNZ_t_Z[i], acceph_t[3i], Z[i], ord) - TaylorSeries.add!(tmp1497[i], pNX_t_X[i], pNY_t_Y[i], ord) - TaylorSeries.add!(tmp1498[i], tmp1497[i], pNZ_t_Z[i], ord) - TaylorSeries.mul!(tmp1499[i], 0.5, tmp1498[i], ord) - TaylorSeries.add!(pn1[i], pn1t1_7[i], tmp1499[i], ord) - TaylorSeries.mul!(X_t_pn1[i], newton_acc_X[i], pn1[i], ord) - TaylorSeries.mul!(Y_t_pn1[i], newton_acc_Y[i], pn1[i], ord) - TaylorSeries.mul!(Z_t_pn1[i], newton_acc_Z[i], pn1[i], ord) - TaylorSeries.mul!(pNX_t_pn3[i], acceph_t[3i - 2], pn3[i], ord) - TaylorSeries.mul!(pNY_t_pn3[i], acceph_t[3i - 1], pn3[i], ord) - TaylorSeries.mul!(pNZ_t_pn3[i], acceph_t[3i], pn3[i], ord) - end - for i = 1:10 - TaylorSeries.add!(tmp1507[i], U_t_pn2[i], pNX_t_pn3[i], ord) - TaylorSeries.add!(termpnx[i], X_t_pn1[i], tmp1507[i], ord) - TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) - TaylorSeries.identity!(pntempX, sumpnx[i], ord) - TaylorSeries.add!(tmp1510[i], V_t_pn2[i], pNY_t_pn3[i], ord) - TaylorSeries.add!(termpny[i], Y_t_pn1[i], tmp1510[i], ord) - TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) - TaylorSeries.identity!(pntempY, sumpny[i], ord) - TaylorSeries.add!(tmp1513[i], W_t_pn2[i], pNZ_t_pn3[i], ord) - TaylorSeries.add!(termpnz[i], Z_t_pn1[i], tmp1513[i], ord) - TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) - TaylorSeries.identity!(pntempZ, sumpnz[i], ord) - end - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 - TaylorSeries.mul!(X_t_pn1[i], c_p2, newton_acc_X[i], ord) - TaylorSeries.mul!(Y_t_pn1[i], c_p2, newton_acc_Y[i], ord) - TaylorSeries.mul!(Z_t_pn1[i], c_p2, newton_acc_Z[i], ord) - end - for i = 11:Nm1 - TaylorSeries.identity!(termpnx[i], X_t_pn1[i], ord) - TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) - TaylorSeries.identity!(pntempX, sumpnx[i], ord) - TaylorSeries.identity!(termpny[i], Y_t_pn1[i], ord) - TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) - TaylorSeries.identity!(pntempY, sumpny[i], ord) - TaylorSeries.identity!(termpnz[i], Z_t_pn1[i], ord) - TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) - TaylorSeries.identity!(pntempZ, sumpnz[i], ord) - end - TaylorSeries.mul!(postNewtonX, pntempX, c_m2, ord) - TaylorSeries.mul!(postNewtonY, pntempY, c_m2, ord) - TaylorSeries.mul!(postNewtonZ, pntempZ, c_m2, ord) - TaylorSeries.add!(dq[4], postNewtonX, accX, ord) - TaylorSeries.add!(dq[5], postNewtonY, accY, ord) - TaylorSeries.add!(dq[6], postNewtonZ, accZ, ord) - for __idx = eachindex(q) - (q[__idx]).coeffs[ordnext + 1] = (dq[__idx]).coeffs[ordnext] / ordnext - end - end - return nothing +# DO NOT MODIFY THIS FILE BY HAND + +# Methods of `TaylorIntegration._allocate_jetcoeffs!` and `TaylorIntegration.jetcoeffs!` generated by @taylorize for the functions +# in src/propagation/asteroid_dynamical_models.jl + +# To update the functions do the following: +# 1.- Update the corresponding function in src/propagation/asteroid_dynamical_models.jl +# 2.- using TaylorIntegration +# 2.- ex = :(paste here the modified function) +# 3.- x, y = TaylorIntegration._make_parsed_coeffs(ex) +# 4.- Paste x and y in this file + +# TaylorIntegration._allocate_jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_ng_eph_threads! +function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params) where {_T <: Real, _S <: Number, _N} + order = t.order + local jd0 = params[4] + local dsj2k = t + (jd0 - JD_J2000) + local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) + local acceph_t = evaleph(params[2], dsj2k, q[1]) + local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) + local S = eltype(q) + local UJ_interaction = params[5] + local N = params[6] + local Nm1 = N - 1 + local μ = params[7] + local zero_q_1 = auxzero(q[1]) + X = Array{S}(undef, N) + Y = Array{S}(undef, N) + Z = Array{S}(undef, N) + r_p2 = Array{S}(undef, N) + r_p1d2 = Array{S}(undef, N) + r_p3d2 = Array{S}(undef, N) + r_p7d2 = Array{S}(undef, N) + newtonianCoeff = Array{S}(undef, N) + ui = Array{S}(undef, N - 1) + vi = Array{S}(undef, N - 1) + wi = Array{S}(undef, N - 1) + U = Array{S}(undef, N) + V = Array{S}(undef, N) + W = Array{S}(undef, N) + _4U_m_3X = Array{S}(undef, N) + _4V_m_3Y = Array{S}(undef, N) + _4W_m_3Z = Array{S}(undef, N) + UU = Array{S}(undef, N) + VV = Array{S}(undef, N) + WW = Array{S}(undef, N) + newtonian1b_Potential = Array{S}(undef, N) + newtonianNb_Potential = Array{S}(undef, N) + newton_acc_X = Array{S}(undef, N) + newton_acc_Y = Array{S}(undef, N) + newton_acc_Z = Array{S}(undef, N) + v2 = Array{S}(undef, N) + vi_dot_vj = Array{S}(undef, N) + pn2 = Array{S}(undef, N) + U_t_pn2 = Array{S}(undef, N) + V_t_pn2 = Array{S}(undef, N) + W_t_pn2 = Array{S}(undef, N) + pn3 = Array{S}(undef, N) + pNX_t_pn3 = Array{S}(undef, N) + pNY_t_pn3 = Array{S}(undef, N) + pNZ_t_pn3 = Array{S}(undef, N) + _4ϕj = Array{S}(undef, N) + ϕi_plus_4ϕj = Array{S}(undef, N) + sj2_plus_2si2_minus_4vivj = Array{S}(undef, N) + ϕs_and_vs = Array{S}(undef, N) + pn1t1_7 = Array{S}(undef, N) + pNX_t_X = Array{S}(undef, N) + pNY_t_Y = Array{S}(undef, N) + pNZ_t_Z = Array{S}(undef, N) + pn1 = Array{S}(undef, N) + X_t_pn1 = Array{S}(undef, N) + Y_t_pn1 = Array{S}(undef, N) + Z_t_pn1 = Array{S}(undef, N) + pntempX = Taylor1(identity(constant_term(zero_q_1)), order) + pntempY = Taylor1(identity(constant_term(zero_q_1)), order) + pntempZ = Taylor1(identity(constant_term(zero_q_1)), order) + t31 = Array{S}(undef, N) + t32 = Array{S}(undef, N) + t33 = Array{S}(undef, N) + r_sin_ϕ = Array{S}(undef, N) + sin_ϕ = Array{S}(undef, N) + ϕ = Array{S}(undef, N) + cos_ϕ = Array{S}(undef, N) + sin2_ϕ = Array{S}(undef, N) + sin3_ϕ = Array{S}(undef, N) + sin4_ϕ = Array{S}(undef, N) + F_J2_x = Array{S}(undef, N) + F_J2_y = Array{S}(undef, N) + F_J2_z = Array{S}(undef, N) + F_J2_x1 = Array{S}(undef, N) + F_J2_y1 = Array{S}(undef, N) + F_J2_z1 = Array{S}(undef, N) + F_J2_x2 = Array{S}(undef, N) + F_J2_y2 = Array{S}(undef, N) + F_J2_z2 = Array{S}(undef, N) + temp_accX_i = Array{S}(undef, N) + temp_accY_i = Array{S}(undef, N) + temp_accZ_i = Array{S}(undef, N) + P_2_sin_ϕ = Array{S}(undef, N) + ∂P_2_sin_ϕ = Array{S}(undef, N) + P_3_sin_ϕ = Array{S}(undef, N) + ∂P_3_sin_ϕ = Array{S}(undef, N) + m_c_ϕ_∂P_2 = Array{S}(undef, N) + m_c_ϕ_∂P_3 = Array{S}(undef, N) + Λ2j_div_r4 = Array{S}(undef, N) + Λ3j_div_r5 = Array{S}(undef, N) + F_J_ξ = Array{S}(undef, N) + F_J_η = Array{S}(undef, N) + F_J_ζ = Array{S}(undef, N) + F_J2_ξ = Array{S}(undef, N) + F_J2_η = Array{S}(undef, N) + F_J2_ζ = Array{S}(undef, N) + F_J3_ξ = Array{S}(undef, N) + F_J3_η = Array{S}(undef, N) + F_J3_ζ = Array{S}(undef, N) + ξx = Array{S}(undef, N) + ξy = Array{S}(undef, N) + ξz = Array{S}(undef, N) + ηx = Array{S}(undef, N) + ηy = Array{S}(undef, N) + ηz = Array{S}(undef, N) + ηx1 = Array{S}(undef, N) + ηy1 = Array{S}(undef, N) + ηz1 = Array{S}(undef, N) + ηx2 = Array{S}(undef, N) + ηy2 = Array{S}(undef, N) + ηz2 = Array{S}(undef, N) + ζx = Array{S}(undef, N) + ζy = Array{S}(undef, N) + ζz = Array{S}(undef, N) + ζx1 = Array{S}(undef, N) + ζy1 = Array{S}(undef, N) + ζz1 = Array{S}(undef, N) + ζx2 = Array{S}(undef, N) + ζy2 = Array{S}(undef, N) + ζz2 = Array{S}(undef, N) + accX = Taylor1(identity(constant_term(zero_q_1)), order) + accY = Taylor1(identity(constant_term(zero_q_1)), order) + accZ = Taylor1(identity(constant_term(zero_q_1)), order) + local M_ = Array{S}(undef, 3, 3, N) + local M_ .= zero_q_1 + local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 + dq[1] = Taylor1(identity(constant_term(q[4])), order) + dq[2] = Taylor1(identity(constant_term(q[5])), order) + dq[3] = Taylor1(identity(constant_term(q[6])), order) + newtonianNb_Potential[N] = Taylor1(identity(constant_term(zero_q_1)), order) + tmp687 = Array{Taylor1{_S}}(undef, size(dq)) + tmp687 .= Taylor1(zero(constant_term(q[1])), order) + tmp689 = Array{Taylor1{_S}}(undef, size(ui)) + tmp689 .= Taylor1(zero(constant_term(q[1])), order) + tmp692 = Array{Taylor1{_S}}(undef, size(dq)) + tmp692 .= Taylor1(zero(constant_term(q[1])), order) + tmp694 = Array{Taylor1{_S}}(undef, size(vi)) + tmp694 .= Taylor1(zero(constant_term(q[1])), order) + tmp697 = Array{Taylor1{_S}}(undef, size(dq)) + tmp697 .= Taylor1(zero(constant_term(q[1])), order) + tmp699 = Array{Taylor1{_S}}(undef, size(wi)) + tmp699 .= Taylor1(zero(constant_term(q[1])), order) + pn2x = Array{Taylor1{_S}}(undef, size(X)) + pn2x .= Taylor1(zero(constant_term(q[1])), order) + pn2y = Array{Taylor1{_S}}(undef, size(Y)) + pn2y .= Taylor1(zero(constant_term(q[1])), order) + pn2z = Array{Taylor1{_S}}(undef, size(Z)) + pn2z .= Taylor1(zero(constant_term(q[1])), order) + tmp707 = Array{Taylor1{_S}}(undef, size(UU)) + tmp707 .= Taylor1(zero(constant_term(q[1])), order) + tmp710 = Array{Taylor1{_S}}(undef, size(X)) + tmp710 .= Taylor1(zero(constant_term(q[1])), order) + tmp712 = Array{Taylor1{_S}}(undef, size(Y)) + tmp712 .= Taylor1(zero(constant_term(q[1])), order) + tmp713 = Array{Taylor1{_S}}(undef, size(tmp710)) + tmp713 .= Taylor1(zero(constant_term(q[1])), order) + tmp715 = Array{Taylor1{_S}}(undef, size(Z)) + tmp715 .= Taylor1(zero(constant_term(q[1])), order) + tmp723 = Array{Taylor1{_S}}(undef, size(pn2x)) + tmp723 .= Taylor1(zero(constant_term(q[1])), order) + tmp724 = Array{Taylor1{_S}}(undef, size(tmp723)) + tmp724 .= Taylor1(zero(constant_term(q[1])), order) + tmp819 = Array{Taylor1{_S}}(undef, size(ui)) + tmp819 .= Taylor1(zero(constant_term(q[1])), order) + tmp821 = Array{Taylor1{_S}}(undef, size(vi)) + tmp821 .= Taylor1(zero(constant_term(q[1])), order) + tmp822 = Array{Taylor1{_S}}(undef, size(tmp819)) + tmp822 .= Taylor1(zero(constant_term(q[1])), order) + tmp824 = Array{Taylor1{_S}}(undef, size(wi)) + tmp824 .= Taylor1(zero(constant_term(q[1])), order) + tmp735 = Array{Taylor1{_S}}(undef, size(X)) + tmp735 .= Taylor1(zero(constant_term(q[1])), order) + tmp737 = Array{Taylor1{_S}}(undef, size(Y)) + tmp737 .= Taylor1(zero(constant_term(q[1])), order) + tmp739 = Array{Taylor1{_S}}(undef, size(Z)) + tmp739 .= Taylor1(zero(constant_term(q[1])), order) + tmp741 = Array{Taylor1{_S}}(undef, size(t31)) + tmp741 .= Taylor1(zero(constant_term(q[1])), order) + tmp948 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) + tmp948 .= Taylor1(zero(constant_term(q[1])), order) + tmp949 = Array{Taylor1{_S}}(undef, size(ϕ)) + tmp949 .= Taylor1(zero(constant_term(q[1])), order) + tmp751 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) + tmp751 .= Taylor1(zero(constant_term(q[1])), order) + tmp757 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) + tmp757 .= Taylor1(zero(constant_term(q[1])), order) + tmp759 = Array{Taylor1{_S}}(undef, size(sin3_ϕ)) + tmp759 .= Taylor1(zero(constant_term(q[1])), order) + tmp763 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) + tmp763 .= Taylor1(zero(constant_term(q[1])), order) + tmp766 = Array{Taylor1{_S}}(undef, size(r_p2)) + tmp766 .= Taylor1(zero(constant_term(q[1])), order) + tmp767 = Array{Taylor1{_S}}(undef, size(Λ2)) + tmp767 .= Taylor1(zero(constant_term(q[1])), order) + tmp770 = Array{Taylor1{_S}}(undef, size(r_p1d2)) + tmp770 .= Taylor1(zero(constant_term(q[1])), order) + tmp771 = Array{Taylor1{_S}}(undef, size(Λ3)) + tmp771 .= Taylor1(zero(constant_term(q[1])), order) + tmp773 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) + tmp773 .= Taylor1(zero(constant_term(q[1])), order) + tmp775 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) + tmp775 .= Taylor1(zero(constant_term(q[1])), order) + tmp778 = Array{Taylor1{_S}}(undef, size(Λ2j_div_r4)) + tmp778 .= Taylor1(zero(constant_term(q[1])), order) + tmp782 = Array{Taylor1{_S}}(undef, size(Λ3j_div_r5)) + tmp782 .= Taylor1(zero(constant_term(q[1])), order) + tmp785 = Array{Taylor1{_S}}(undef, size(X)) + tmp785 .= Taylor1(zero(constant_term(q[1])), order) + tmp787 = Array{Taylor1{_S}}(undef, size(Y)) + tmp787 .= Taylor1(zero(constant_term(q[1])), order) + tmp789 = Array{Taylor1{_S}}(undef, size(Z)) + tmp789 .= Taylor1(zero(constant_term(q[1])), order) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 + ui[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])), order) + vi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])), order) + wi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])), order) + X[i] = Taylor1(constant_term(ss16asteph_t[3i - 2]) - constant_term(q[1]), order) + Y[i] = Taylor1(constant_term(ss16asteph_t[3i - 1]) - constant_term(q[2]), order) + Z[i] = Taylor1(constant_term(ss16asteph_t[3i]) - constant_term(q[3]), order) + U[i] = Taylor1(constant_term(ui[i]) - constant_term(dq[1]), order) + V[i] = Taylor1(constant_term(vi[i]) - constant_term(dq[2]), order) + W[i] = Taylor1(constant_term(wi[i]) - constant_term(dq[3]), order) + tmp687[1] = Taylor1(constant_term(4) * constant_term(dq[1]), order) + tmp689[i] = Taylor1(constant_term(3) * constant_term(ui[i]), order) + _4U_m_3X[i] = Taylor1(constant_term(tmp687[1]) - constant_term(tmp689[i]), order) + tmp692[2] = Taylor1(constant_term(4) * constant_term(dq[2]), order) + tmp694[i] = Taylor1(constant_term(3) * constant_term(vi[i]), order) + _4V_m_3Y[i] = Taylor1(constant_term(tmp692[2]) - constant_term(tmp694[i]), order) + tmp697[3] = Taylor1(constant_term(4) * constant_term(dq[3]), order) + tmp699[i] = Taylor1(constant_term(3) * constant_term(wi[i]), order) + _4W_m_3Z[i] = Taylor1(constant_term(tmp697[3]) - constant_term(tmp699[i]), order) + pn2x[i] = Taylor1(constant_term(X[i]) * constant_term(_4U_m_3X[i]), order) + pn2y[i] = Taylor1(constant_term(Y[i]) * constant_term(_4V_m_3Y[i]), order) + pn2z[i] = Taylor1(constant_term(Z[i]) * constant_term(_4W_m_3Z[i]), order) + UU[i] = Taylor1(constant_term(ui[i]) * constant_term(dq[1]), order) + VV[i] = Taylor1(constant_term(vi[i]) * constant_term(dq[2]), order) + WW[i] = Taylor1(constant_term(wi[i]) * constant_term(dq[3]), order) + tmp707[i] = Taylor1(constant_term(UU[i]) + constant_term(VV[i]), order) + vi_dot_vj[i] = Taylor1(constant_term(tmp707[i]) + constant_term(WW[i]), order) + tmp710[i] = Taylor1(constant_term(X[i]) ^ float(constant_term(2)), order) + tmp712[i] = Taylor1(constant_term(Y[i]) ^ float(constant_term(2)), order) + tmp713[i] = Taylor1(constant_term(tmp710[i]) + constant_term(tmp712[i]), order) + tmp715[i] = Taylor1(constant_term(Z[i]) ^ float(constant_term(2)), order) + r_p2[i] = Taylor1(constant_term(tmp713[i]) + constant_term(tmp715[i]), order) + r_p1d2[i] = Taylor1(sqrt(constant_term(r_p2[i])), order) + r_p3d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(1.5)), order) + r_p7d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(3.5)), order) + newtonianCoeff[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p3d2[i]), order) + tmp723[i] = Taylor1(constant_term(pn2x[i]) + constant_term(pn2y[i]), order) + tmp724[i] = Taylor1(constant_term(tmp723[i]) + constant_term(pn2z[i]), order) + pn2[i] = Taylor1(constant_term(newtonianCoeff[i]) * constant_term(tmp724[i]), order) + newton_acc_X[i] = Taylor1(constant_term(X[i]) * constant_term(newtonianCoeff[i]), order) + newton_acc_Y[i] = Taylor1(constant_term(Y[i]) * constant_term(newtonianCoeff[i]), order) + newton_acc_Z[i] = Taylor1(constant_term(Z[i]) * constant_term(newtonianCoeff[i]), order) + newtonian1b_Potential[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p1d2[i]), order) + pn3[i] = Taylor1(constant_term(3.5) * constant_term(newtonian1b_Potential[i]), order) + U_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(U[i]), order) + V_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(V[i]), order) + W_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(W[i]), order) + if UJ_interaction[i] + tmp735[i] = Taylor1(-(constant_term(X[i])), order) + t31[i] = Taylor1(constant_term(tmp735[i]) * constant_term(M_[1, 3, i]), order) + tmp737[i] = Taylor1(-(constant_term(Y[i])), order) + t32[i] = Taylor1(constant_term(tmp737[i]) * constant_term(M_[2, 3, i]), order) + tmp739[i] = Taylor1(-(constant_term(Z[i])), order) + t33[i] = Taylor1(constant_term(tmp739[i]) * constant_term(M_[3, 3, i]), order) + tmp741[i] = Taylor1(constant_term(t31[i]) + constant_term(t32[i]), order) + r_sin_ϕ[i] = Taylor1(constant_term(tmp741[i]) + constant_term(t33[i]), order) + sin_ϕ[i] = Taylor1(constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]), order) + ϕ[i] = Taylor1(asin(constant_term(sin_ϕ[i])), order) + tmp948[i] = Taylor1(sqrt(1 - constant_term(sin_ϕ[i]) ^ 2), order) + cos_ϕ[i] = Taylor1(cos(constant_term(ϕ[i])), order) + tmp949[i] = Taylor1(sin(constant_term(ϕ[i])), order) + sin2_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(2)), order) + sin3_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(3)), order) + tmp751[i] = Taylor1(constant_term(1.5) * constant_term(sin2_ϕ[i]), order) + P_2_sin_ϕ[i] = Taylor1(constant_term(tmp751[i]) - constant_term(0.5), order) + ∂P_2_sin_ϕ[i] = Taylor1(constant_term(3) * constant_term(sin_ϕ[i]), order) + tmp757[i] = Taylor1(constant_term(-1.5) * constant_term(sin_ϕ[i]), order) + tmp759[i] = Taylor1(constant_term(2.5) * constant_term(sin3_ϕ[i]), order) + P_3_sin_ϕ[i] = Taylor1(constant_term(tmp757[i]) + constant_term(tmp759[i]), order) + tmp763[i] = Taylor1(constant_term(7.5) * constant_term(sin2_ϕ[i]), order) + ∂P_3_sin_ϕ[i] = Taylor1(constant_term(-1.5) + constant_term(tmp763[i]), order) + tmp766[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(2)), order) + tmp767[i] = Taylor1(constant_term(Λ2[i]) / constant_term(tmp766[i]), order) + Λ2j_div_r4[i] = Taylor1(-(constant_term(tmp767[i])), order) + tmp770[i] = Taylor1(constant_term(r_p1d2[i]) ^ float(constant_term(5)), order) + tmp771[i] = Taylor1(constant_term(Λ3[i]) / constant_term(tmp770[i]), order) + Λ3j_div_r5[i] = Taylor1(-(constant_term(tmp771[i])), order) + tmp773[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) + m_c_ϕ_∂P_2[i] = Taylor1(constant_term(tmp773[i]) * constant_term(∂P_2_sin_ϕ[i]), order) + tmp775[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) + m_c_ϕ_∂P_3[i] = Taylor1(constant_term(tmp775[i]) * constant_term(∂P_3_sin_ϕ[i]), order) + tmp778[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(3), order) + F_J2_ξ[i] = Taylor1(constant_term(tmp778[i]) * constant_term(P_2_sin_ϕ[i]), order) + F_J2_ζ[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]), order) + tmp782[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(4), order) + F_J3_ξ[i] = Taylor1(constant_term(tmp782[i]) * constant_term(P_3_sin_ϕ[i]), order) + F_J3_ζ[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]), order) + F_J_ξ[i] = Taylor1(identity(constant_term(F_J2_ξ[i])), order) + F_J_ζ[i] = Taylor1(identity(constant_term(F_J2_ζ[i])), order) + tmp785[i] = Taylor1(-(constant_term(X[i])), order) + ξx[i] = Taylor1(constant_term(tmp785[i]) / constant_term(r_p1d2[i]), order) + tmp787[i] = Taylor1(-(constant_term(Y[i])), order) + ξy[i] = Taylor1(constant_term(tmp787[i]) / constant_term(r_p1d2[i]), order) + tmp789[i] = Taylor1(-(constant_term(Z[i])), order) + ξz[i] = Taylor1(constant_term(tmp789[i]) / constant_term(r_p1d2[i]), order) + ηx1[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξz[i]), order) + ηy1[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξx[i]), order) + ηz1[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξy[i]), order) + ηx2[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξy[i]), order) + ηy2[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξz[i]), order) + ηz2[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξx[i]), order) + ηx[i] = Taylor1(constant_term(ηx1[i]) - constant_term(ηx2[i]), order) + ηy[i] = Taylor1(constant_term(ηy1[i]) - constant_term(ηy2[i]), order) + ηz[i] = Taylor1(constant_term(ηz1[i]) - constant_term(ηz2[i]), order) + ζx1[i] = Taylor1(constant_term(ξy[i]) * constant_term(ηz[i]), order) + ζy1[i] = Taylor1(constant_term(ξz[i]) * constant_term(ηx[i]), order) + ζz1[i] = Taylor1(constant_term(ξx[i]) * constant_term(ηy[i]), order) + ζx2[i] = Taylor1(constant_term(ξz[i]) * constant_term(ηy[i]), order) + ζy2[i] = Taylor1(constant_term(ξx[i]) * constant_term(ηz[i]), order) + ζz2[i] = Taylor1(constant_term(ξy[i]) * constant_term(ηx[i]), order) + ζx[i] = Taylor1(constant_term(ζx1[i]) - constant_term(ζx2[i]), order) + ζy[i] = Taylor1(constant_term(ζy1[i]) - constant_term(ζy2[i]), order) + ζz[i] = Taylor1(constant_term(ζz1[i]) - constant_term(ζz2[i]), order) + F_J2_x1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξx[i]), order) + F_J2_y1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξy[i]), order) + F_J2_z1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξz[i]), order) + F_J2_x2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζx[i]), order) + F_J2_y2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζy[i]), order) + F_J2_z2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζz[i]), order) + F_J2_x[i] = Taylor1(constant_term(F_J2_x1[i]) + constant_term(F_J2_x2[i]), order) + F_J2_y[i] = Taylor1(constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]), order) + F_J2_z[i] = Taylor1(constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]), order) + end + tmp819[i] = Taylor1(constant_term(ui[i]) ^ float(constant_term(2)), order) + tmp821[i] = Taylor1(constant_term(vi[i]) ^ float(constant_term(2)), order) + tmp822[i] = Taylor1(constant_term(tmp819[i]) + constant_term(tmp821[i]), order) + tmp824[i] = Taylor1(constant_term(wi[i]) ^ float(constant_term(2)), order) + v2[i] = Taylor1(constant_term(tmp822[i]) + constant_term(tmp824[i]), order) + end + tmp827 = Taylor1(constant_term(q[4]) ^ float(constant_term(2)), order) + tmp829 = Taylor1(constant_term(q[5]) ^ float(constant_term(2)), order) + tmp830 = Taylor1(constant_term(tmp827) + constant_term(tmp829), order) + tmp832 = Taylor1(constant_term(q[6]) ^ float(constant_term(2)), order) + v2[N] = Taylor1(constant_term(tmp830) + constant_term(tmp832), order) + temp_004 = Array{Taylor1{_S}}(undef, size(newtonian1b_Potential)) + temp_004 .= Taylor1(zero(constant_term(q[1])), order) + tmp835 = Array{Taylor1{_S}}(undef, size(μ)) + tmp835 .= Taylor1(zero(constant_term(q[1])), order) + tmp837 = Array{Taylor1{_S}}(undef, size(μ)) + tmp837 .= Taylor1(zero(constant_term(q[1])), order) + tmp839 = Array{Taylor1{_S}}(undef, size(μ)) + tmp839 .= Taylor1(zero(constant_term(q[1])), order) + for i = 1:Nm1 + temp_004[i] = Taylor1(constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]), order) + newtonianNb_Potential[N] = Taylor1(identity(constant_term(temp_004[i])), order) + if UJ_interaction[i] + tmp835[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_x[i]), order) + temp_accX_i[i] = Taylor1(constant_term(accX) - constant_term(tmp835[i]), order) + accX = Taylor1(identity(constant_term(temp_accX_i[i])), order) + tmp837[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_y[i]), order) + temp_accY_i[i] = Taylor1(constant_term(accY) - constant_term(tmp837[i]), order) + accY = Taylor1(identity(constant_term(temp_accY_i[i])), order) + tmp839[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_z[i]), order) + temp_accZ_i[i] = Taylor1(constant_term(accZ) - constant_term(tmp839[i]), order) + accZ = Taylor1(identity(constant_term(temp_accZ_i[i])), order) + end + end + _4ϕj[N] = Taylor1(constant_term(4) * constant_term(newtonianNb_Potential[N]), order) + tmp845 = Array{Taylor1{_S}}(undef, size(v2)) + tmp845 .= Taylor1(zero(constant_term(q[1])), order) + tmp847 = Array{Taylor1{_S}}(undef, size(vi_dot_vj)) + tmp847 .= Taylor1(zero(constant_term(q[1])), order) + tmp848 = Array{Taylor1{_S}}(undef, size(tmp845)) + tmp848 .= Taylor1(zero(constant_term(q[1])), order) + Xij_t_Ui = Array{Taylor1{_S}}(undef, size(X)) + Xij_t_Ui .= Taylor1(zero(constant_term(q[1])), order) + Yij_t_Vi = Array{Taylor1{_S}}(undef, size(Y)) + Yij_t_Vi .= Taylor1(zero(constant_term(q[1])), order) + Zij_t_Wi = Array{Taylor1{_S}}(undef, size(Z)) + Zij_t_Wi .= Taylor1(zero(constant_term(q[1])), order) + tmp854 = Array{Taylor1{_S}}(undef, size(Xij_t_Ui)) + tmp854 .= Taylor1(zero(constant_term(q[1])), order) + Rij_dot_Vi = Array{Taylor1{_S}}(undef, size(tmp854)) + Rij_dot_Vi .= Taylor1(zero(constant_term(q[1])), order) + tmp857 = Array{Taylor1{_S}}(undef, size(Rij_dot_Vi)) + tmp857 .= Taylor1(zero(constant_term(q[1])), order) + pn1t7 = Array{Taylor1{_S}}(undef, size(tmp857)) + pn1t7 .= Taylor1(zero(constant_term(q[1])), order) + tmp860 = Array{Taylor1{_S}}(undef, size(pn1t7)) + tmp860 .= Taylor1(zero(constant_term(q[1])), order) + pn1t2_7 = Array{Taylor1{_S}}(undef, size(ϕs_and_vs)) + pn1t2_7 .= Taylor1(zero(constant_term(q[1])), order) + tmp867 = Array{Taylor1{_S}}(undef, size(pNX_t_X)) + tmp867 .= Taylor1(zero(constant_term(q[1])), order) + tmp868 = Array{Taylor1{_S}}(undef, size(tmp867)) + tmp868 .= Taylor1(zero(constant_term(q[1])), order) + tmp869 = Array{Taylor1{_S}}(undef, size(tmp868)) + tmp869 .= Taylor1(zero(constant_term(q[1])), order) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 + ϕi_plus_4ϕj[i] = Taylor1(constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]), order) + tmp845[i] = Taylor1(constant_term(2) * constant_term(v2[i]), order) + tmp847[i] = Taylor1(constant_term(4) * constant_term(vi_dot_vj[i]), order) + tmp848[i] = Taylor1(constant_term(tmp845[i]) - constant_term(tmp847[i]), order) + sj2_plus_2si2_minus_4vivj[i] = Taylor1(constant_term(tmp848[i]) + constant_term(v2[N]), order) + ϕs_and_vs[i] = Taylor1(constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]), order) + Xij_t_Ui[i] = Taylor1(constant_term(X[i]) * constant_term(ui[i]), order) + Yij_t_Vi[i] = Taylor1(constant_term(Y[i]) * constant_term(vi[i]), order) + Zij_t_Wi[i] = Taylor1(constant_term(Z[i]) * constant_term(wi[i]), order) + tmp854[i] = Taylor1(constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]), order) + Rij_dot_Vi[i] = Taylor1(constant_term(tmp854[i]) + constant_term(Zij_t_Wi[i]), order) + tmp857[i] = Taylor1(constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)), order) + pn1t7[i] = Taylor1(constant_term(tmp857[i]) / constant_term(r_p2[i]), order) + tmp860[i] = Taylor1(constant_term(1.5) * constant_term(pn1t7[i]), order) + pn1t2_7[i] = Taylor1(constant_term(ϕs_and_vs[i]) - constant_term(tmp860[i]), order) + pn1t1_7[i] = Taylor1(constant_term(c_p2) + constant_term(pn1t2_7[i]), order) + pNX_t_X[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(X[i]), order) + pNY_t_Y[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(Y[i]), order) + pNZ_t_Z[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(Z[i]), order) + tmp867[i] = Taylor1(constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]), order) + tmp868[i] = Taylor1(constant_term(tmp867[i]) + constant_term(pNZ_t_Z[i]), order) + tmp869[i] = Taylor1(constant_term(0.5) * constant_term(tmp868[i]), order) + pn1[i] = Taylor1(constant_term(pn1t1_7[i]) + constant_term(tmp869[i]), order) + X_t_pn1[i] = Taylor1(constant_term(newton_acc_X[i]) * constant_term(pn1[i]), order) + Y_t_pn1[i] = Taylor1(constant_term(newton_acc_Y[i]) * constant_term(pn1[i]), order) + Z_t_pn1[i] = Taylor1(constant_term(newton_acc_Z[i]) * constant_term(pn1[i]), order) + pNX_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(pn3[i]), order) + pNY_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]), order) + pNZ_t_pn3[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(pn3[i]), order) + end + tmp877 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) + tmp877 .= Taylor1(zero(constant_term(q[1])), order) + termpnx = Array{Taylor1{_S}}(undef, size(X_t_pn1)) + termpnx .= Taylor1(zero(constant_term(q[1])), order) + sumpnx = Array{Taylor1{_S}}(undef, size(termpnx)) + sumpnx .= Taylor1(zero(constant_term(q[1])), order) + tmp880 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) + tmp880 .= Taylor1(zero(constant_term(q[1])), order) + termpny = Array{Taylor1{_S}}(undef, size(Y_t_pn1)) + termpny .= Taylor1(zero(constant_term(q[1])), order) + sumpny = Array{Taylor1{_S}}(undef, size(termpny)) + sumpny .= Taylor1(zero(constant_term(q[1])), order) + tmp883 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) + tmp883 .= Taylor1(zero(constant_term(q[1])), order) + termpnz = Array{Taylor1{_S}}(undef, size(Z_t_pn1)) + termpnz .= Taylor1(zero(constant_term(q[1])), order) + sumpnz = Array{Taylor1{_S}}(undef, size(termpnz)) + sumpnz .= Taylor1(zero(constant_term(q[1])), order) + for i = 1:10 + tmp877[i] = Taylor1(constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]), order) + termpnx[i] = Taylor1(constant_term(X_t_pn1[i]) + constant_term(tmp877[i]), order) + sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) + pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) + tmp880[i] = Taylor1(constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]), order) + termpny[i] = Taylor1(constant_term(Y_t_pn1[i]) + constant_term(tmp880[i]), order) + sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) + pntempY = Taylor1(identity(constant_term(sumpny[i])), order) + tmp883[i] = Taylor1(constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]), order) + termpnz[i] = Taylor1(constant_term(Z_t_pn1[i]) + constant_term(tmp883[i]), order) + sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) + pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) + end + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 + X_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_X[i]), order) + Y_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Y[i]), order) + Z_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Z[i]), order) + end + for i = 11:Nm1 + termpnx[i] = Taylor1(identity(constant_term(X_t_pn1[i])), order) + sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) + pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) + termpny[i] = Taylor1(identity(constant_term(Y_t_pn1[i])), order) + sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) + pntempY = Taylor1(identity(constant_term(sumpny[i])), order) + termpnz[i] = Taylor1(identity(constant_term(Z_t_pn1[i])), order) + sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) + pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) + end + postNewtonX = Taylor1(constant_term(pntempX) * constant_term(c_m2), order) + postNewtonY = Taylor1(constant_term(pntempY) * constant_term(c_m2), order) + postNewtonZ = Taylor1(constant_term(pntempZ) * constant_term(c_m2), order) + tmp895 = Taylor1(constant_term(Y[1]) * constant_term(W[1]), order) + tmp896 = Taylor1(constant_term(Z[1]) * constant_term(V[1]), order) + hx = Taylor1(constant_term(tmp895) - constant_term(tmp896), order) + tmp898 = Taylor1(constant_term(Z[1]) * constant_term(U[1]), order) + tmp899 = Taylor1(constant_term(X[1]) * constant_term(W[1]), order) + hy = Taylor1(constant_term(tmp898) - constant_term(tmp899), order) + tmp901 = Taylor1(constant_term(X[1]) * constant_term(V[1]), order) + tmp902 = Taylor1(constant_term(Y[1]) * constant_term(U[1]), order) + hz = Taylor1(constant_term(tmp901) - constant_term(tmp902), order) + tmp904 = Taylor1(constant_term(hz) * constant_term(Y[1]), order) + tmp905 = Taylor1(constant_term(hy) * constant_term(Z[1]), order) + t_x = Taylor1(constant_term(tmp904) - constant_term(tmp905), order) + tmp907 = Taylor1(constant_term(hx) * constant_term(Z[1]), order) + tmp908 = Taylor1(constant_term(hz) * constant_term(X[1]), order) + t_y = Taylor1(constant_term(tmp907) - constant_term(tmp908), order) + tmp910 = Taylor1(constant_term(hy) * constant_term(X[1]), order) + tmp911 = Taylor1(constant_term(hx) * constant_term(Y[1]), order) + t_z = Taylor1(constant_term(tmp910) - constant_term(tmp911), order) + tmp914 = Taylor1(constant_term(t_x) ^ float(constant_term(2)), order) + tmp916 = Taylor1(constant_term(t_y) ^ float(constant_term(2)), order) + tmp917 = Taylor1(constant_term(tmp914) + constant_term(tmp916), order) + tmp919 = Taylor1(constant_term(t_z) ^ float(constant_term(2)), order) + tmp920 = Taylor1(constant_term(tmp917) + constant_term(tmp919), order) + t_norm = Taylor1(sqrt(constant_term(tmp920)), order) + t_x_unit = Taylor1(constant_term(t_x) / constant_term(t_norm), order) + t_y_unit = Taylor1(constant_term(t_y) / constant_term(t_norm), order) + t_z_unit = Taylor1(constant_term(t_z) / constant_term(t_norm), order) + tmp925 = Taylor1(constant_term(X[1]) / constant_term(r_p1d2[1]), order) + r_x_unit = Taylor1(-(constant_term(tmp925)), order) + tmp927 = Taylor1(constant_term(Y[1]) / constant_term(r_p1d2[1]), order) + r_y_unit = Taylor1(-(constant_term(tmp927)), order) + tmp929 = Taylor1(constant_term(Z[1]) / constant_term(r_p1d2[1]), order) + r_z_unit = Taylor1(-(constant_term(tmp929)), order) + g_r = Taylor1(identity(constant_term(r_p2[1])), order) + A2_t_g_r = Taylor1(constant_term(q[7]) / constant_term(g_r), order) + A1_t_g_r = Taylor1(constant_term(q[8]) / constant_term(g_r), order) + tmp933 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_x_unit), order) + tmp934 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_x_unit), order) + NGAx = Taylor1(constant_term(tmp933) + constant_term(tmp934), order) + tmp936 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_y_unit), order) + tmp937 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_y_unit), order) + NGAy = Taylor1(constant_term(tmp936) + constant_term(tmp937), order) + tmp939 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_z_unit), order) + tmp940 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_z_unit), order) + NGAz = Taylor1(constant_term(tmp939) + constant_term(tmp940), order) + tmp942 = Taylor1(constant_term(postNewtonX) + constant_term(accX), order) + dq[4] = Taylor1(constant_term(tmp942) + constant_term(NGAx), order) + tmp944 = Taylor1(constant_term(postNewtonY) + constant_term(accY), order) + dq[5] = Taylor1(constant_term(tmp944) + constant_term(NGAy), order) + tmp946 = Taylor1(constant_term(postNewtonZ) + constant_term(accZ), order) + dq[6] = Taylor1(constant_term(tmp946) + constant_term(NGAz), order) + dq[7] = Taylor1(identity(constant_term(zero_q_1)), order) + return TaylorIntegration.RetAlloc{Taylor1{_S}}([tmp827, tmp829, tmp830, tmp832, tmp895, tmp896, tmp898, tmp899, tmp901, tmp902, tmp904, tmp905, tmp907, tmp908, tmp910, tmp911, tmp914, tmp916, tmp917, tmp919, tmp920, tmp925, tmp927, tmp929, tmp933, tmp934, tmp936, tmp937, tmp939, tmp940, tmp942, tmp944, tmp946, pntempX, pntempY, pntempZ, accX, accY, accZ, postNewtonX, postNewtonY, postNewtonZ, hx, hy, hz, t_x, t_y, t_z, t_norm, t_x_unit, t_y_unit, t_z_unit, r_x_unit, r_y_unit, r_z_unit, g_r, A2_t_g_r, A1_t_g_r, NGAx, NGAy, NGAz], [X, Y, Z, r_p2, r_p1d2, r_p3d2, r_p7d2, newtonianCoeff, ui, vi, wi, U, V, W, _4U_m_3X, _4V_m_3Y, _4W_m_3Z, UU, VV, WW, newtonian1b_Potential, newtonianNb_Potential, newton_acc_X, newton_acc_Y, newton_acc_Z, v2, vi_dot_vj, pn2, U_t_pn2, V_t_pn2, W_t_pn2, pn3, pNX_t_pn3, pNY_t_pn3, pNZ_t_pn3, _4ϕj, ϕi_plus_4ϕj, sj2_plus_2si2_minus_4vivj, ϕs_and_vs, pn1t1_7, pNX_t_X, pNY_t_Y, pNZ_t_Z, pn1, X_t_pn1, Y_t_pn1, Z_t_pn1, t31, t32, t33, r_sin_ϕ, sin_ϕ, ϕ, cos_ϕ, sin2_ϕ, sin3_ϕ, F_J2_x, F_J2_y, F_J2_z, F_J2_x1, F_J2_y1, F_J2_z1, F_J2_x2, F_J2_y2, F_J2_z2, temp_accX_i, temp_accY_i, temp_accZ_i, P_2_sin_ϕ, ∂P_2_sin_ϕ, P_3_sin_ϕ, ∂P_3_sin_ϕ, m_c_ϕ_∂P_2, m_c_ϕ_∂P_3, Λ2j_div_r4, Λ3j_div_r5, F_J_ξ, F_J_ζ, F_J2_ξ, F_J2_ζ, F_J3_ξ, F_J3_ζ, ξx, ξy, ξz, ηx, ηy, ηz, ηx1, ηy1, ηz1, ηx2, ηy2, ηz2, ζx, ζy, ζz, ζx1, ζy1, ζz1, ζx2, ζy2, ζz2, tmp687, tmp689, tmp692, tmp694, tmp697, tmp699, pn2x, pn2y, pn2z, tmp707, tmp710, tmp712, tmp713, tmp715, tmp723, tmp724, tmp735, tmp737, tmp739, tmp741, tmp948, tmp949, tmp751, tmp757, tmp759, tmp763, tmp766, tmp767, tmp770, tmp771, tmp773, tmp775, tmp778, tmp782, tmp785, tmp787, tmp789, tmp819, tmp821, tmp822, tmp824, temp_004, tmp835, tmp837, tmp839, tmp845, tmp847, tmp848, Xij_t_Ui, Yij_t_Vi, Zij_t_Wi, tmp854, Rij_dot_Vi, tmp857, pn1t7, tmp860, pn1t2_7, tmp867, tmp868, tmp869, tmp877, termpnx, sumpnx, tmp880, termpny, sumpny, tmp883, termpnz, sumpnz], [Array{Taylor1{_S}, 2}(undef, 0, 0)], [Array{Taylor1{_S}, 3}(undef, 0, 0, 0)], [Array{Taylor1{_S}, 4}(undef, 0, 0, 0, 0)]) +end + +# TaylorIntegration.jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_ng_eph_threads! +function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params, __ralloc::TaylorIntegration.RetAlloc{Taylor1{_S}}) where {_T <: Real, _S <: Number, _N} + order = t.order + tmp827 = __ralloc.v0[1] + tmp829 = __ralloc.v0[2] + tmp830 = __ralloc.v0[3] + tmp832 = __ralloc.v0[4] + tmp895 = __ralloc.v0[5] + tmp896 = __ralloc.v0[6] + tmp898 = __ralloc.v0[7] + tmp899 = __ralloc.v0[8] + tmp901 = __ralloc.v0[9] + tmp902 = __ralloc.v0[10] + tmp904 = __ralloc.v0[11] + tmp905 = __ralloc.v0[12] + tmp907 = __ralloc.v0[13] + tmp908 = __ralloc.v0[14] + tmp910 = __ralloc.v0[15] + tmp911 = __ralloc.v0[16] + tmp914 = __ralloc.v0[17] + tmp916 = __ralloc.v0[18] + tmp917 = __ralloc.v0[19] + tmp919 = __ralloc.v0[20] + tmp920 = __ralloc.v0[21] + tmp925 = __ralloc.v0[22] + tmp927 = __ralloc.v0[23] + tmp929 = __ralloc.v0[24] + tmp933 = __ralloc.v0[25] + tmp934 = __ralloc.v0[26] + tmp936 = __ralloc.v0[27] + tmp937 = __ralloc.v0[28] + tmp939 = __ralloc.v0[29] + tmp940 = __ralloc.v0[30] + tmp942 = __ralloc.v0[31] + tmp944 = __ralloc.v0[32] + tmp946 = __ralloc.v0[33] + pntempX = __ralloc.v0[34] + pntempY = __ralloc.v0[35] + pntempZ = __ralloc.v0[36] + accX = __ralloc.v0[37] + accY = __ralloc.v0[38] + accZ = __ralloc.v0[39] + postNewtonX = __ralloc.v0[40] + postNewtonY = __ralloc.v0[41] + postNewtonZ = __ralloc.v0[42] + hx = __ralloc.v0[43] + hy = __ralloc.v0[44] + hz = __ralloc.v0[45] + t_x = __ralloc.v0[46] + t_y = __ralloc.v0[47] + t_z = __ralloc.v0[48] + t_norm = __ralloc.v0[49] + t_x_unit = __ralloc.v0[50] + t_y_unit = __ralloc.v0[51] + t_z_unit = __ralloc.v0[52] + r_x_unit = __ralloc.v0[53] + r_y_unit = __ralloc.v0[54] + r_z_unit = __ralloc.v0[55] + g_r = __ralloc.v0[56] + A2_t_g_r = __ralloc.v0[57] + A1_t_g_r = __ralloc.v0[58] + NGAx = __ralloc.v0[59] + NGAy = __ralloc.v0[60] + NGAz = __ralloc.v0[61] + X = __ralloc.v1[1] + Y = __ralloc.v1[2] + Z = __ralloc.v1[3] + r_p2 = __ralloc.v1[4] + r_p1d2 = __ralloc.v1[5] + r_p3d2 = __ralloc.v1[6] + r_p7d2 = __ralloc.v1[7] + newtonianCoeff = __ralloc.v1[8] + ui = __ralloc.v1[9] + vi = __ralloc.v1[10] + wi = __ralloc.v1[11] + U = __ralloc.v1[12] + V = __ralloc.v1[13] + W = __ralloc.v1[14] + _4U_m_3X = __ralloc.v1[15] + _4V_m_3Y = __ralloc.v1[16] + _4W_m_3Z = __ralloc.v1[17] + UU = __ralloc.v1[18] + VV = __ralloc.v1[19] + WW = __ralloc.v1[20] + newtonian1b_Potential = __ralloc.v1[21] + newtonianNb_Potential = __ralloc.v1[22] + newton_acc_X = __ralloc.v1[23] + newton_acc_Y = __ralloc.v1[24] + newton_acc_Z = __ralloc.v1[25] + v2 = __ralloc.v1[26] + vi_dot_vj = __ralloc.v1[27] + pn2 = __ralloc.v1[28] + U_t_pn2 = __ralloc.v1[29] + V_t_pn2 = __ralloc.v1[30] + W_t_pn2 = __ralloc.v1[31] + pn3 = __ralloc.v1[32] + pNX_t_pn3 = __ralloc.v1[33] + pNY_t_pn3 = __ralloc.v1[34] + pNZ_t_pn3 = __ralloc.v1[35] + _4ϕj = __ralloc.v1[36] + ϕi_plus_4ϕj = __ralloc.v1[37] + sj2_plus_2si2_minus_4vivj = __ralloc.v1[38] + ϕs_and_vs = __ralloc.v1[39] + pn1t1_7 = __ralloc.v1[40] + pNX_t_X = __ralloc.v1[41] + pNY_t_Y = __ralloc.v1[42] + pNZ_t_Z = __ralloc.v1[43] + pn1 = __ralloc.v1[44] + X_t_pn1 = __ralloc.v1[45] + Y_t_pn1 = __ralloc.v1[46] + Z_t_pn1 = __ralloc.v1[47] + t31 = __ralloc.v1[48] + t32 = __ralloc.v1[49] + t33 = __ralloc.v1[50] + r_sin_ϕ = __ralloc.v1[51] + sin_ϕ = __ralloc.v1[52] + ϕ = __ralloc.v1[53] + cos_ϕ = __ralloc.v1[54] + sin2_ϕ = __ralloc.v1[55] + sin3_ϕ = __ralloc.v1[56] + F_J2_x = __ralloc.v1[57] + F_J2_y = __ralloc.v1[58] + F_J2_z = __ralloc.v1[59] + F_J2_x1 = __ralloc.v1[60] + F_J2_y1 = __ralloc.v1[61] + F_J2_z1 = __ralloc.v1[62] + F_J2_x2 = __ralloc.v1[63] + F_J2_y2 = __ralloc.v1[64] + F_J2_z2 = __ralloc.v1[65] + temp_accX_i = __ralloc.v1[66] + temp_accY_i = __ralloc.v1[67] + temp_accZ_i = __ralloc.v1[68] + P_2_sin_ϕ = __ralloc.v1[69] + ∂P_2_sin_ϕ = __ralloc.v1[70] + P_3_sin_ϕ = __ralloc.v1[71] + ∂P_3_sin_ϕ = __ralloc.v1[72] + m_c_ϕ_∂P_2 = __ralloc.v1[73] + m_c_ϕ_∂P_3 = __ralloc.v1[74] + Λ2j_div_r4 = __ralloc.v1[75] + Λ3j_div_r5 = __ralloc.v1[76] + F_J_ξ = __ralloc.v1[77] + F_J_ζ = __ralloc.v1[78] + F_J2_ξ = __ralloc.v1[79] + F_J2_ζ = __ralloc.v1[80] + F_J3_ξ = __ralloc.v1[81] + F_J3_ζ = __ralloc.v1[82] + ξx = __ralloc.v1[83] + ξy = __ralloc.v1[84] + ξz = __ralloc.v1[85] + ηx = __ralloc.v1[86] + ηy = __ralloc.v1[87] + ηz = __ralloc.v1[88] + ηx1 = __ralloc.v1[89] + ηy1 = __ralloc.v1[90] + ηz1 = __ralloc.v1[91] + ηx2 = __ralloc.v1[92] + ηy2 = __ralloc.v1[93] + ηz2 = __ralloc.v1[94] + ζx = __ralloc.v1[95] + ζy = __ralloc.v1[96] + ζz = __ralloc.v1[97] + ζx1 = __ralloc.v1[98] + ζy1 = __ralloc.v1[99] + ζz1 = __ralloc.v1[100] + ζx2 = __ralloc.v1[101] + ζy2 = __ralloc.v1[102] + ζz2 = __ralloc.v1[103] + tmp687 = __ralloc.v1[104] + tmp689 = __ralloc.v1[105] + tmp692 = __ralloc.v1[106] + tmp694 = __ralloc.v1[107] + tmp697 = __ralloc.v1[108] + tmp699 = __ralloc.v1[109] + pn2x = __ralloc.v1[110] + pn2y = __ralloc.v1[111] + pn2z = __ralloc.v1[112] + tmp707 = __ralloc.v1[113] + tmp710 = __ralloc.v1[114] + tmp712 = __ralloc.v1[115] + tmp713 = __ralloc.v1[116] + tmp715 = __ralloc.v1[117] + tmp723 = __ralloc.v1[118] + tmp724 = __ralloc.v1[119] + tmp735 = __ralloc.v1[120] + tmp737 = __ralloc.v1[121] + tmp739 = __ralloc.v1[122] + tmp741 = __ralloc.v1[123] + tmp948 = __ralloc.v1[124] + tmp949 = __ralloc.v1[125] + tmp751 = __ralloc.v1[126] + tmp757 = __ralloc.v1[127] + tmp759 = __ralloc.v1[128] + tmp763 = __ralloc.v1[129] + tmp766 = __ralloc.v1[130] + tmp767 = __ralloc.v1[131] + tmp770 = __ralloc.v1[132] + tmp771 = __ralloc.v1[133] + tmp773 = __ralloc.v1[134] + tmp775 = __ralloc.v1[135] + tmp778 = __ralloc.v1[136] + tmp782 = __ralloc.v1[137] + tmp785 = __ralloc.v1[138] + tmp787 = __ralloc.v1[139] + tmp789 = __ralloc.v1[140] + tmp819 = __ralloc.v1[141] + tmp821 = __ralloc.v1[142] + tmp822 = __ralloc.v1[143] + tmp824 = __ralloc.v1[144] + temp_004 = __ralloc.v1[145] + tmp835 = __ralloc.v1[146] + tmp837 = __ralloc.v1[147] + tmp839 = __ralloc.v1[148] + tmp845 = __ralloc.v1[149] + tmp847 = __ralloc.v1[150] + tmp848 = __ralloc.v1[151] + Xij_t_Ui = __ralloc.v1[152] + Yij_t_Vi = __ralloc.v1[153] + Zij_t_Wi = __ralloc.v1[154] + tmp854 = __ralloc.v1[155] + Rij_dot_Vi = __ralloc.v1[156] + tmp857 = __ralloc.v1[157] + pn1t7 = __ralloc.v1[158] + tmp860 = __ralloc.v1[159] + pn1t2_7 = __ralloc.v1[160] + tmp867 = __ralloc.v1[161] + tmp868 = __ralloc.v1[162] + tmp869 = __ralloc.v1[163] + tmp877 = __ralloc.v1[164] + termpnx = __ralloc.v1[165] + sumpnx = __ralloc.v1[166] + tmp880 = __ralloc.v1[167] + termpny = __ralloc.v1[168] + sumpny = __ralloc.v1[169] + tmp883 = __ralloc.v1[170] + termpnz = __ralloc.v1[171] + sumpnz = __ralloc.v1[172] + local jd0 = params[4] + local dsj2k = t + (jd0 - JD_J2000) + local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) + local acceph_t = evaleph(params[2], dsj2k, q[1]) + local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) + local S = eltype(q) + local UJ_interaction = params[5] + local N = params[6] + local Nm1 = N - 1 + local μ = params[7] + local zero_q_1 = auxzero(q[1]) + pntempX.coeffs[1] = identity(constant_term(zero_q_1)) + pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) + pntempY.coeffs[1] = identity(constant_term(zero_q_1)) + pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) + pntempZ.coeffs[1] = identity(constant_term(zero_q_1)) + pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) + accX.coeffs[1] = identity(constant_term(zero_q_1)) + accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) + accY.coeffs[1] = identity(constant_term(zero_q_1)) + accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) + accZ.coeffs[1] = identity(constant_term(zero_q_1)) + accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) + local M_ = Array{S}(undef, 3, 3, N) + local M_ .= zero_q_1 + local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 + (dq[1]).coeffs[1] = identity(constant_term(q[4])) + (dq[1]).coeffs[2:order + 1] .= zero((dq[1]).coeffs[1]) + (dq[2]).coeffs[1] = identity(constant_term(q[5])) + (dq[2]).coeffs[2:order + 1] .= zero((dq[2]).coeffs[1]) + (dq[3]).coeffs[1] = identity(constant_term(q[6])) + (dq[3]).coeffs[2:order + 1] .= zero((dq[3]).coeffs[1]) + (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(zero_q_1)) + (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 + (ui[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])) + (ui[i]).coeffs[2:order + 1] .= zero((ui[i]).coeffs[1]) + (vi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])) + (vi[i]).coeffs[2:order + 1] .= zero((vi[i]).coeffs[1]) + (wi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])) + (wi[i]).coeffs[2:order + 1] .= zero((wi[i]).coeffs[1]) + (X[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 2]) - constant_term(q[1]) + (X[i]).coeffs[2:order + 1] .= zero((X[i]).coeffs[1]) + (Y[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 1]) - constant_term(q[2]) + (Y[i]).coeffs[2:order + 1] .= zero((Y[i]).coeffs[1]) + (Z[i]).coeffs[1] = constant_term(ss16asteph_t[3i]) - constant_term(q[3]) + (Z[i]).coeffs[2:order + 1] .= zero((Z[i]).coeffs[1]) + (U[i]).coeffs[1] = constant_term(ui[i]) - constant_term(dq[1]) + (U[i]).coeffs[2:order + 1] .= zero((U[i]).coeffs[1]) + (V[i]).coeffs[1] = constant_term(vi[i]) - constant_term(dq[2]) + (V[i]).coeffs[2:order + 1] .= zero((V[i]).coeffs[1]) + (W[i]).coeffs[1] = constant_term(wi[i]) - constant_term(dq[3]) + (W[i]).coeffs[2:order + 1] .= zero((W[i]).coeffs[1]) + (tmp687[1]).coeffs[1] = constant_term(4) * constant_term(dq[1]) + (tmp687[1]).coeffs[2:order + 1] .= zero((tmp687[1]).coeffs[1]) + (tmp689[i]).coeffs[1] = constant_term(3) * constant_term(ui[i]) + (tmp689[i]).coeffs[2:order + 1] .= zero((tmp689[i]).coeffs[1]) + (_4U_m_3X[i]).coeffs[1] = constant_term(tmp687[1]) - constant_term(tmp689[i]) + (_4U_m_3X[i]).coeffs[2:order + 1] .= zero((_4U_m_3X[i]).coeffs[1]) + (tmp692[2]).coeffs[1] = constant_term(4) * constant_term(dq[2]) + (tmp692[2]).coeffs[2:order + 1] .= zero((tmp692[2]).coeffs[1]) + (tmp694[i]).coeffs[1] = constant_term(3) * constant_term(vi[i]) + (tmp694[i]).coeffs[2:order + 1] .= zero((tmp694[i]).coeffs[1]) + (_4V_m_3Y[i]).coeffs[1] = constant_term(tmp692[2]) - constant_term(tmp694[i]) + (_4V_m_3Y[i]).coeffs[2:order + 1] .= zero((_4V_m_3Y[i]).coeffs[1]) + (tmp697[3]).coeffs[1] = constant_term(4) * constant_term(dq[3]) + (tmp697[3]).coeffs[2:order + 1] .= zero((tmp697[3]).coeffs[1]) + (tmp699[i]).coeffs[1] = constant_term(3) * constant_term(wi[i]) + (tmp699[i]).coeffs[2:order + 1] .= zero((tmp699[i]).coeffs[1]) + (_4W_m_3Z[i]).coeffs[1] = constant_term(tmp697[3]) - constant_term(tmp699[i]) + (_4W_m_3Z[i]).coeffs[2:order + 1] .= zero((_4W_m_3Z[i]).coeffs[1]) + (pn2x[i]).coeffs[1] = constant_term(X[i]) * constant_term(_4U_m_3X[i]) + (pn2x[i]).coeffs[2:order + 1] .= zero((pn2x[i]).coeffs[1]) + (pn2y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(_4V_m_3Y[i]) + (pn2y[i]).coeffs[2:order + 1] .= zero((pn2y[i]).coeffs[1]) + (pn2z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(_4W_m_3Z[i]) + (pn2z[i]).coeffs[2:order + 1] .= zero((pn2z[i]).coeffs[1]) + (UU[i]).coeffs[1] = constant_term(ui[i]) * constant_term(dq[1]) + (UU[i]).coeffs[2:order + 1] .= zero((UU[i]).coeffs[1]) + (VV[i]).coeffs[1] = constant_term(vi[i]) * constant_term(dq[2]) + (VV[i]).coeffs[2:order + 1] .= zero((VV[i]).coeffs[1]) + (WW[i]).coeffs[1] = constant_term(wi[i]) * constant_term(dq[3]) + (WW[i]).coeffs[2:order + 1] .= zero((WW[i]).coeffs[1]) + (tmp707[i]).coeffs[1] = constant_term(UU[i]) + constant_term(VV[i]) + (tmp707[i]).coeffs[2:order + 1] .= zero((tmp707[i]).coeffs[1]) + (vi_dot_vj[i]).coeffs[1] = constant_term(tmp707[i]) + constant_term(WW[i]) + (vi_dot_vj[i]).coeffs[2:order + 1] .= zero((vi_dot_vj[i]).coeffs[1]) + (tmp710[i]).coeffs[1] = constant_term(X[i]) ^ float(constant_term(2)) + (tmp710[i]).coeffs[2:order + 1] .= zero((tmp710[i]).coeffs[1]) + (tmp712[i]).coeffs[1] = constant_term(Y[i]) ^ float(constant_term(2)) + (tmp712[i]).coeffs[2:order + 1] .= zero((tmp712[i]).coeffs[1]) + (tmp713[i]).coeffs[1] = constant_term(tmp710[i]) + constant_term(tmp712[i]) + (tmp713[i]).coeffs[2:order + 1] .= zero((tmp713[i]).coeffs[1]) + (tmp715[i]).coeffs[1] = constant_term(Z[i]) ^ float(constant_term(2)) + (tmp715[i]).coeffs[2:order + 1] .= zero((tmp715[i]).coeffs[1]) + (r_p2[i]).coeffs[1] = constant_term(tmp713[i]) + constant_term(tmp715[i]) + (r_p2[i]).coeffs[2:order + 1] .= zero((r_p2[i]).coeffs[1]) + (r_p1d2[i]).coeffs[1] = sqrt(constant_term(r_p2[i])) + (r_p1d2[i]).coeffs[2:order + 1] .= zero((r_p1d2[i]).coeffs[1]) + (r_p3d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(1.5)) + (r_p3d2[i]).coeffs[2:order + 1] .= zero((r_p3d2[i]).coeffs[1]) + (r_p7d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(3.5)) + (r_p7d2[i]).coeffs[2:order + 1] .= zero((r_p7d2[i]).coeffs[1]) + (newtonianCoeff[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p3d2[i]) + (newtonianCoeff[i]).coeffs[2:order + 1] .= zero((newtonianCoeff[i]).coeffs[1]) + (tmp723[i]).coeffs[1] = constant_term(pn2x[i]) + constant_term(pn2y[i]) + (tmp723[i]).coeffs[2:order + 1] .= zero((tmp723[i]).coeffs[1]) + (tmp724[i]).coeffs[1] = constant_term(tmp723[i]) + constant_term(pn2z[i]) + (tmp724[i]).coeffs[2:order + 1] .= zero((tmp724[i]).coeffs[1]) + (pn2[i]).coeffs[1] = constant_term(newtonianCoeff[i]) * constant_term(tmp724[i]) + (pn2[i]).coeffs[2:order + 1] .= zero((pn2[i]).coeffs[1]) + (newton_acc_X[i]).coeffs[1] = constant_term(X[i]) * constant_term(newtonianCoeff[i]) + (newton_acc_X[i]).coeffs[2:order + 1] .= zero((newton_acc_X[i]).coeffs[1]) + (newton_acc_Y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(newtonianCoeff[i]) + (newton_acc_Y[i]).coeffs[2:order + 1] .= zero((newton_acc_Y[i]).coeffs[1]) + (newton_acc_Z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(newtonianCoeff[i]) + (newton_acc_Z[i]).coeffs[2:order + 1] .= zero((newton_acc_Z[i]).coeffs[1]) + (newtonian1b_Potential[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p1d2[i]) + (newtonian1b_Potential[i]).coeffs[2:order + 1] .= zero((newtonian1b_Potential[i]).coeffs[1]) + (pn3[i]).coeffs[1] = constant_term(3.5) * constant_term(newtonian1b_Potential[i]) + (pn3[i]).coeffs[2:order + 1] .= zero((pn3[i]).coeffs[1]) + (U_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(U[i]) + (U_t_pn2[i]).coeffs[2:order + 1] .= zero((U_t_pn2[i]).coeffs[1]) + (V_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(V[i]) + (V_t_pn2[i]).coeffs[2:order + 1] .= zero((V_t_pn2[i]).coeffs[1]) + (W_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(W[i]) + (W_t_pn2[i]).coeffs[2:order + 1] .= zero((W_t_pn2[i]).coeffs[1]) + if UJ_interaction[i] + (tmp735[i]).coeffs[1] = -(constant_term(X[i])) + (tmp735[i]).coeffs[2:order + 1] .= zero((tmp735[i]).coeffs[1]) + (t31[i]).coeffs[1] = constant_term(tmp735[i]) * constant_term(M_[1, 3, i]) + (t31[i]).coeffs[2:order + 1] .= zero((t31[i]).coeffs[1]) + (tmp737[i]).coeffs[1] = -(constant_term(Y[i])) + (tmp737[i]).coeffs[2:order + 1] .= zero((tmp737[i]).coeffs[1]) + (t32[i]).coeffs[1] = constant_term(tmp737[i]) * constant_term(M_[2, 3, i]) + (t32[i]).coeffs[2:order + 1] .= zero((t32[i]).coeffs[1]) + (tmp739[i]).coeffs[1] = -(constant_term(Z[i])) + (tmp739[i]).coeffs[2:order + 1] .= zero((tmp739[i]).coeffs[1]) + (t33[i]).coeffs[1] = constant_term(tmp739[i]) * constant_term(M_[3, 3, i]) + (t33[i]).coeffs[2:order + 1] .= zero((t33[i]).coeffs[1]) + (tmp741[i]).coeffs[1] = constant_term(t31[i]) + constant_term(t32[i]) + (tmp741[i]).coeffs[2:order + 1] .= zero((tmp741[i]).coeffs[1]) + (r_sin_ϕ[i]).coeffs[1] = constant_term(tmp741[i]) + constant_term(t33[i]) + (r_sin_ϕ[i]).coeffs[2:order + 1] .= zero((r_sin_ϕ[i]).coeffs[1]) + (sin_ϕ[i]).coeffs[1] = constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]) + (sin_ϕ[i]).coeffs[2:order + 1] .= zero((sin_ϕ[i]).coeffs[1]) + (ϕ[i]).coeffs[1] = asin(constant_term(sin_ϕ[i])) + (ϕ[i]).coeffs[2:order + 1] .= zero((ϕ[i]).coeffs[1]) + (tmp948[i]).coeffs[1] = sqrt(1 - constant_term(sin_ϕ[i]) ^ 2) + (tmp948[i]).coeffs[2:order + 1] .= zero((tmp948[i]).coeffs[1]) + (cos_ϕ[i]).coeffs[1] = cos(constant_term(ϕ[i])) + (cos_ϕ[i]).coeffs[2:order + 1] .= zero((cos_ϕ[i]).coeffs[1]) + (tmp949[i]).coeffs[1] = sin(constant_term(ϕ[i])) + (tmp949[i]).coeffs[2:order + 1] .= zero((tmp949[i]).coeffs[1]) + (sin2_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(2)) + (sin2_ϕ[i]).coeffs[2:order + 1] .= zero((sin2_ϕ[i]).coeffs[1]) + (sin3_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(3)) + (sin3_ϕ[i]).coeffs[2:order + 1] .= zero((sin3_ϕ[i]).coeffs[1]) + (tmp751[i]).coeffs[1] = constant_term(1.5) * constant_term(sin2_ϕ[i]) + (tmp751[i]).coeffs[2:order + 1] .= zero((tmp751[i]).coeffs[1]) + (P_2_sin_ϕ[i]).coeffs[1] = constant_term(tmp751[i]) - constant_term(0.5) + (P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_2_sin_ϕ[i]).coeffs[1]) + (∂P_2_sin_ϕ[i]).coeffs[1] = constant_term(3) * constant_term(sin_ϕ[i]) + (∂P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_2_sin_ϕ[i]).coeffs[1]) + (tmp757[i]).coeffs[1] = constant_term(-1.5) * constant_term(sin_ϕ[i]) + (tmp757[i]).coeffs[2:order + 1] .= zero((tmp757[i]).coeffs[1]) + (tmp759[i]).coeffs[1] = constant_term(2.5) * constant_term(sin3_ϕ[i]) + (tmp759[i]).coeffs[2:order + 1] .= zero((tmp759[i]).coeffs[1]) + (P_3_sin_ϕ[i]).coeffs[1] = constant_term(tmp757[i]) + constant_term(tmp759[i]) + (P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_3_sin_ϕ[i]).coeffs[1]) + (tmp763[i]).coeffs[1] = constant_term(7.5) * constant_term(sin2_ϕ[i]) + (tmp763[i]).coeffs[2:order + 1] .= zero((tmp763[i]).coeffs[1]) + (∂P_3_sin_ϕ[i]).coeffs[1] = constant_term(-1.5) + constant_term(tmp763[i]) + (∂P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_3_sin_ϕ[i]).coeffs[1]) + (tmp766[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(2)) + (tmp766[i]).coeffs[2:order + 1] .= zero((tmp766[i]).coeffs[1]) + (tmp767[i]).coeffs[1] = constant_term(Λ2[i]) / constant_term(tmp766[i]) + (tmp767[i]).coeffs[2:order + 1] .= zero((tmp767[i]).coeffs[1]) + (Λ2j_div_r4[i]).coeffs[1] = -(constant_term(tmp767[i])) + (Λ2j_div_r4[i]).coeffs[2:order + 1] .= zero((Λ2j_div_r4[i]).coeffs[1]) + (tmp770[i]).coeffs[1] = constant_term(r_p1d2[i]) ^ float(constant_term(5)) + (tmp770[i]).coeffs[2:order + 1] .= zero((tmp770[i]).coeffs[1]) + (tmp771[i]).coeffs[1] = constant_term(Λ3[i]) / constant_term(tmp770[i]) + (tmp771[i]).coeffs[2:order + 1] .= zero((tmp771[i]).coeffs[1]) + (Λ3j_div_r5[i]).coeffs[1] = -(constant_term(tmp771[i])) + (Λ3j_div_r5[i]).coeffs[2:order + 1] .= zero((Λ3j_div_r5[i]).coeffs[1]) + (tmp773[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) + (tmp773[i]).coeffs[2:order + 1] .= zero((tmp773[i]).coeffs[1]) + (m_c_ϕ_∂P_2[i]).coeffs[1] = constant_term(tmp773[i]) * constant_term(∂P_2_sin_ϕ[i]) + (m_c_ϕ_∂P_2[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_2[i]).coeffs[1]) + (tmp775[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) + (tmp775[i]).coeffs[2:order + 1] .= zero((tmp775[i]).coeffs[1]) + (m_c_ϕ_∂P_3[i]).coeffs[1] = constant_term(tmp775[i]) * constant_term(∂P_3_sin_ϕ[i]) + (m_c_ϕ_∂P_3[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_3[i]).coeffs[1]) + (tmp778[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(3) + (tmp778[i]).coeffs[2:order + 1] .= zero((tmp778[i]).coeffs[1]) + (F_J2_ξ[i]).coeffs[1] = constant_term(tmp778[i]) * constant_term(P_2_sin_ϕ[i]) + (F_J2_ξ[i]).coeffs[2:order + 1] .= zero((F_J2_ξ[i]).coeffs[1]) + (F_J2_ζ[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]) + (F_J2_ζ[i]).coeffs[2:order + 1] .= zero((F_J2_ζ[i]).coeffs[1]) + (tmp782[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(4) + (tmp782[i]).coeffs[2:order + 1] .= zero((tmp782[i]).coeffs[1]) + (F_J3_ξ[i]).coeffs[1] = constant_term(tmp782[i]) * constant_term(P_3_sin_ϕ[i]) + (F_J3_ξ[i]).coeffs[2:order + 1] .= zero((F_J3_ξ[i]).coeffs[1]) + (F_J3_ζ[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]) + (F_J3_ζ[i]).coeffs[2:order + 1] .= zero((F_J3_ζ[i]).coeffs[1]) + (F_J_ξ[i]).coeffs[1] = identity(constant_term(F_J2_ξ[i])) + (F_J_ξ[i]).coeffs[2:order + 1] .= zero((F_J_ξ[i]).coeffs[1]) + (F_J_ζ[i]).coeffs[1] = identity(constant_term(F_J2_ζ[i])) + (F_J_ζ[i]).coeffs[2:order + 1] .= zero((F_J_ζ[i]).coeffs[1]) + (tmp785[i]).coeffs[1] = -(constant_term(X[i])) + (tmp785[i]).coeffs[2:order + 1] .= zero((tmp785[i]).coeffs[1]) + (ξx[i]).coeffs[1] = constant_term(tmp785[i]) / constant_term(r_p1d2[i]) + (ξx[i]).coeffs[2:order + 1] .= zero((ξx[i]).coeffs[1]) + (tmp787[i]).coeffs[1] = -(constant_term(Y[i])) + (tmp787[i]).coeffs[2:order + 1] .= zero((tmp787[i]).coeffs[1]) + (ξy[i]).coeffs[1] = constant_term(tmp787[i]) / constant_term(r_p1d2[i]) + (ξy[i]).coeffs[2:order + 1] .= zero((ξy[i]).coeffs[1]) + (tmp789[i]).coeffs[1] = -(constant_term(Z[i])) + (tmp789[i]).coeffs[2:order + 1] .= zero((tmp789[i]).coeffs[1]) + (ξz[i]).coeffs[1] = constant_term(tmp789[i]) / constant_term(r_p1d2[i]) + (ξz[i]).coeffs[2:order + 1] .= zero((ξz[i]).coeffs[1]) + (ηx1[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξz[i]) + (ηx1[i]).coeffs[2:order + 1] .= zero((ηx1[i]).coeffs[1]) + (ηy1[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξx[i]) + (ηy1[i]).coeffs[2:order + 1] .= zero((ηy1[i]).coeffs[1]) + (ηz1[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξy[i]) + (ηz1[i]).coeffs[2:order + 1] .= zero((ηz1[i]).coeffs[1]) + (ηx2[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξy[i]) + (ηx2[i]).coeffs[2:order + 1] .= zero((ηx2[i]).coeffs[1]) + (ηy2[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξz[i]) + (ηy2[i]).coeffs[2:order + 1] .= zero((ηy2[i]).coeffs[1]) + (ηz2[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξx[i]) + (ηz2[i]).coeffs[2:order + 1] .= zero((ηz2[i]).coeffs[1]) + (ηx[i]).coeffs[1] = constant_term(ηx1[i]) - constant_term(ηx2[i]) + (ηx[i]).coeffs[2:order + 1] .= zero((ηx[i]).coeffs[1]) + (ηy[i]).coeffs[1] = constant_term(ηy1[i]) - constant_term(ηy2[i]) + (ηy[i]).coeffs[2:order + 1] .= zero((ηy[i]).coeffs[1]) + (ηz[i]).coeffs[1] = constant_term(ηz1[i]) - constant_term(ηz2[i]) + (ηz[i]).coeffs[2:order + 1] .= zero((ηz[i]).coeffs[1]) + (ζx1[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηz[i]) + (ζx1[i]).coeffs[2:order + 1] .= zero((ζx1[i]).coeffs[1]) + (ζy1[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηx[i]) + (ζy1[i]).coeffs[2:order + 1] .= zero((ζy1[i]).coeffs[1]) + (ζz1[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηy[i]) + (ζz1[i]).coeffs[2:order + 1] .= zero((ζz1[i]).coeffs[1]) + (ζx2[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηy[i]) + (ζx2[i]).coeffs[2:order + 1] .= zero((ζx2[i]).coeffs[1]) + (ζy2[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηz[i]) + (ζy2[i]).coeffs[2:order + 1] .= zero((ζy2[i]).coeffs[1]) + (ζz2[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηx[i]) + (ζz2[i]).coeffs[2:order + 1] .= zero((ζz2[i]).coeffs[1]) + (ζx[i]).coeffs[1] = constant_term(ζx1[i]) - constant_term(ζx2[i]) + (ζx[i]).coeffs[2:order + 1] .= zero((ζx[i]).coeffs[1]) + (ζy[i]).coeffs[1] = constant_term(ζy1[i]) - constant_term(ζy2[i]) + (ζy[i]).coeffs[2:order + 1] .= zero((ζy[i]).coeffs[1]) + (ζz[i]).coeffs[1] = constant_term(ζz1[i]) - constant_term(ζz2[i]) + (ζz[i]).coeffs[2:order + 1] .= zero((ζz[i]).coeffs[1]) + (F_J2_x1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξx[i]) + (F_J2_x1[i]).coeffs[2:order + 1] .= zero((F_J2_x1[i]).coeffs[1]) + (F_J2_y1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξy[i]) + (F_J2_y1[i]).coeffs[2:order + 1] .= zero((F_J2_y1[i]).coeffs[1]) + (F_J2_z1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξz[i]) + (F_J2_z1[i]).coeffs[2:order + 1] .= zero((F_J2_z1[i]).coeffs[1]) + (F_J2_x2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζx[i]) + (F_J2_x2[i]).coeffs[2:order + 1] .= zero((F_J2_x2[i]).coeffs[1]) + (F_J2_y2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζy[i]) + (F_J2_y2[i]).coeffs[2:order + 1] .= zero((F_J2_y2[i]).coeffs[1]) + (F_J2_z2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζz[i]) + (F_J2_z2[i]).coeffs[2:order + 1] .= zero((F_J2_z2[i]).coeffs[1]) + (F_J2_x[i]).coeffs[1] = constant_term(F_J2_x1[i]) + constant_term(F_J2_x2[i]) + (F_J2_x[i]).coeffs[2:order + 1] .= zero((F_J2_x[i]).coeffs[1]) + (F_J2_y[i]).coeffs[1] = constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]) + (F_J2_y[i]).coeffs[2:order + 1] .= zero((F_J2_y[i]).coeffs[1]) + (F_J2_z[i]).coeffs[1] = constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]) + (F_J2_z[i]).coeffs[2:order + 1] .= zero((F_J2_z[i]).coeffs[1]) + end + (tmp819[i]).coeffs[1] = constant_term(ui[i]) ^ float(constant_term(2)) + (tmp819[i]).coeffs[2:order + 1] .= zero((tmp819[i]).coeffs[1]) + (tmp821[i]).coeffs[1] = constant_term(vi[i]) ^ float(constant_term(2)) + (tmp821[i]).coeffs[2:order + 1] .= zero((tmp821[i]).coeffs[1]) + (tmp822[i]).coeffs[1] = constant_term(tmp819[i]) + constant_term(tmp821[i]) + (tmp822[i]).coeffs[2:order + 1] .= zero((tmp822[i]).coeffs[1]) + (tmp824[i]).coeffs[1] = constant_term(wi[i]) ^ float(constant_term(2)) + (tmp824[i]).coeffs[2:order + 1] .= zero((tmp824[i]).coeffs[1]) + (v2[i]).coeffs[1] = constant_term(tmp822[i]) + constant_term(tmp824[i]) + (v2[i]).coeffs[2:order + 1] .= zero((v2[i]).coeffs[1]) + end + tmp827.coeffs[1] = constant_term(q[4]) ^ float(constant_term(2)) + tmp827.coeffs[2:order + 1] .= zero(tmp827.coeffs[1]) + tmp829.coeffs[1] = constant_term(q[5]) ^ float(constant_term(2)) + tmp829.coeffs[2:order + 1] .= zero(tmp829.coeffs[1]) + tmp830.coeffs[1] = constant_term(tmp827) + constant_term(tmp829) + tmp830.coeffs[2:order + 1] .= zero(tmp830.coeffs[1]) + tmp832.coeffs[1] = constant_term(q[6]) ^ float(constant_term(2)) + tmp832.coeffs[2:order + 1] .= zero(tmp832.coeffs[1]) + (v2[N]).coeffs[1] = constant_term(tmp830) + constant_term(tmp832) + (v2[N]).coeffs[2:order + 1] .= zero((v2[N]).coeffs[1]) + for i = 1:Nm1 + (temp_004[i]).coeffs[1] = constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]) + (temp_004[i]).coeffs[2:order + 1] .= zero((temp_004[i]).coeffs[1]) + (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(temp_004[i])) + (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) + if UJ_interaction[i] + (tmp835[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_x[i]) + (tmp835[i]).coeffs[2:order + 1] .= zero((tmp835[i]).coeffs[1]) + (temp_accX_i[i]).coeffs[1] = constant_term(accX) - constant_term(tmp835[i]) + (temp_accX_i[i]).coeffs[2:order + 1] .= zero((temp_accX_i[i]).coeffs[1]) + accX.coeffs[1] = identity(constant_term(temp_accX_i[i])) + accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) + (tmp837[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_y[i]) + (tmp837[i]).coeffs[2:order + 1] .= zero((tmp837[i]).coeffs[1]) + (temp_accY_i[i]).coeffs[1] = constant_term(accY) - constant_term(tmp837[i]) + (temp_accY_i[i]).coeffs[2:order + 1] .= zero((temp_accY_i[i]).coeffs[1]) + accY.coeffs[1] = identity(constant_term(temp_accY_i[i])) + accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) + (tmp839[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_z[i]) + (tmp839[i]).coeffs[2:order + 1] .= zero((tmp839[i]).coeffs[1]) + (temp_accZ_i[i]).coeffs[1] = constant_term(accZ) - constant_term(tmp839[i]) + (temp_accZ_i[i]).coeffs[2:order + 1] .= zero((temp_accZ_i[i]).coeffs[1]) + accZ.coeffs[1] = identity(constant_term(temp_accZ_i[i])) + accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) + end + end + (_4ϕj[N]).coeffs[1] = constant_term(4) * constant_term(newtonianNb_Potential[N]) + (_4ϕj[N]).coeffs[2:order + 1] .= zero((_4ϕj[N]).coeffs[1]) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 + (ϕi_plus_4ϕj[i]).coeffs[1] = constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]) + (ϕi_plus_4ϕj[i]).coeffs[2:order + 1] .= zero((ϕi_plus_4ϕj[i]).coeffs[1]) + (tmp845[i]).coeffs[1] = constant_term(2) * constant_term(v2[i]) + (tmp845[i]).coeffs[2:order + 1] .= zero((tmp845[i]).coeffs[1]) + (tmp847[i]).coeffs[1] = constant_term(4) * constant_term(vi_dot_vj[i]) + (tmp847[i]).coeffs[2:order + 1] .= zero((tmp847[i]).coeffs[1]) + (tmp848[i]).coeffs[1] = constant_term(tmp845[i]) - constant_term(tmp847[i]) + (tmp848[i]).coeffs[2:order + 1] .= zero((tmp848[i]).coeffs[1]) + (sj2_plus_2si2_minus_4vivj[i]).coeffs[1] = constant_term(tmp848[i]) + constant_term(v2[N]) + (sj2_plus_2si2_minus_4vivj[i]).coeffs[2:order + 1] .= zero((sj2_plus_2si2_minus_4vivj[i]).coeffs[1]) + (ϕs_and_vs[i]).coeffs[1] = constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]) + (ϕs_and_vs[i]).coeffs[2:order + 1] .= zero((ϕs_and_vs[i]).coeffs[1]) + (Xij_t_Ui[i]).coeffs[1] = constant_term(X[i]) * constant_term(ui[i]) + (Xij_t_Ui[i]).coeffs[2:order + 1] .= zero((Xij_t_Ui[i]).coeffs[1]) + (Yij_t_Vi[i]).coeffs[1] = constant_term(Y[i]) * constant_term(vi[i]) + (Yij_t_Vi[i]).coeffs[2:order + 1] .= zero((Yij_t_Vi[i]).coeffs[1]) + (Zij_t_Wi[i]).coeffs[1] = constant_term(Z[i]) * constant_term(wi[i]) + (Zij_t_Wi[i]).coeffs[2:order + 1] .= zero((Zij_t_Wi[i]).coeffs[1]) + (tmp854[i]).coeffs[1] = constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]) + (tmp854[i]).coeffs[2:order + 1] .= zero((tmp854[i]).coeffs[1]) + (Rij_dot_Vi[i]).coeffs[1] = constant_term(tmp854[i]) + constant_term(Zij_t_Wi[i]) + (Rij_dot_Vi[i]).coeffs[2:order + 1] .= zero((Rij_dot_Vi[i]).coeffs[1]) + (tmp857[i]).coeffs[1] = constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)) + (tmp857[i]).coeffs[2:order + 1] .= zero((tmp857[i]).coeffs[1]) + (pn1t7[i]).coeffs[1] = constant_term(tmp857[i]) / constant_term(r_p2[i]) + (pn1t7[i]).coeffs[2:order + 1] .= zero((pn1t7[i]).coeffs[1]) + (tmp860[i]).coeffs[1] = constant_term(1.5) * constant_term(pn1t7[i]) + (tmp860[i]).coeffs[2:order + 1] .= zero((tmp860[i]).coeffs[1]) + (pn1t2_7[i]).coeffs[1] = constant_term(ϕs_and_vs[i]) - constant_term(tmp860[i]) + (pn1t2_7[i]).coeffs[2:order + 1] .= zero((pn1t2_7[i]).coeffs[1]) + (pn1t1_7[i]).coeffs[1] = constant_term(c_p2) + constant_term(pn1t2_7[i]) + (pn1t1_7[i]).coeffs[2:order + 1] .= zero((pn1t1_7[i]).coeffs[1]) + (pNX_t_X[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(X[i]) + (pNX_t_X[i]).coeffs[2:order + 1] .= zero((pNX_t_X[i]).coeffs[1]) + (pNY_t_Y[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(Y[i]) + (pNY_t_Y[i]).coeffs[2:order + 1] .= zero((pNY_t_Y[i]).coeffs[1]) + (pNZ_t_Z[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(Z[i]) + (pNZ_t_Z[i]).coeffs[2:order + 1] .= zero((pNZ_t_Z[i]).coeffs[1]) + (tmp867[i]).coeffs[1] = constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]) + (tmp867[i]).coeffs[2:order + 1] .= zero((tmp867[i]).coeffs[1]) + (tmp868[i]).coeffs[1] = constant_term(tmp867[i]) + constant_term(pNZ_t_Z[i]) + (tmp868[i]).coeffs[2:order + 1] .= zero((tmp868[i]).coeffs[1]) + (tmp869[i]).coeffs[1] = constant_term(0.5) * constant_term(tmp868[i]) + (tmp869[i]).coeffs[2:order + 1] .= zero((tmp869[i]).coeffs[1]) + (pn1[i]).coeffs[1] = constant_term(pn1t1_7[i]) + constant_term(tmp869[i]) + (pn1[i]).coeffs[2:order + 1] .= zero((pn1[i]).coeffs[1]) + (X_t_pn1[i]).coeffs[1] = constant_term(newton_acc_X[i]) * constant_term(pn1[i]) + (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) + (Y_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Y[i]) * constant_term(pn1[i]) + (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) + (Z_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Z[i]) * constant_term(pn1[i]) + (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) + (pNX_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(pn3[i]) + (pNX_t_pn3[i]).coeffs[2:order + 1] .= zero((pNX_t_pn3[i]).coeffs[1]) + (pNY_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]) + (pNY_t_pn3[i]).coeffs[2:order + 1] .= zero((pNY_t_pn3[i]).coeffs[1]) + (pNZ_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(pn3[i]) + (pNZ_t_pn3[i]).coeffs[2:order + 1] .= zero((pNZ_t_pn3[i]).coeffs[1]) + end + for i = 1:10 + (tmp877[i]).coeffs[1] = constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]) + (tmp877[i]).coeffs[2:order + 1] .= zero((tmp877[i]).coeffs[1]) + (termpnx[i]).coeffs[1] = constant_term(X_t_pn1[i]) + constant_term(tmp877[i]) + (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) + (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) + (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) + pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) + pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) + (tmp880[i]).coeffs[1] = constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]) + (tmp880[i]).coeffs[2:order + 1] .= zero((tmp880[i]).coeffs[1]) + (termpny[i]).coeffs[1] = constant_term(Y_t_pn1[i]) + constant_term(tmp880[i]) + (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) + (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) + (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) + pntempY.coeffs[1] = identity(constant_term(sumpny[i])) + pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) + (tmp883[i]).coeffs[1] = constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]) + (tmp883[i]).coeffs[2:order + 1] .= zero((tmp883[i]).coeffs[1]) + (termpnz[i]).coeffs[1] = constant_term(Z_t_pn1[i]) + constant_term(tmp883[i]) + (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) + (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) + (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) + pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) + pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) + end + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 + (X_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_X[i]) + (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) + (Y_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Y[i]) + (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) + (Z_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Z[i]) + (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) + end + for i = 11:Nm1 + (termpnx[i]).coeffs[1] = identity(constant_term(X_t_pn1[i])) + (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) + (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) + (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) + pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) + pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) + (termpny[i]).coeffs[1] = identity(constant_term(Y_t_pn1[i])) + (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) + (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) + (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) + pntempY.coeffs[1] = identity(constant_term(sumpny[i])) + pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) + (termpnz[i]).coeffs[1] = identity(constant_term(Z_t_pn1[i])) + (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) + (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) + (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) + pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) + pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) + end + postNewtonX.coeffs[1] = constant_term(pntempX) * constant_term(c_m2) + postNewtonX.coeffs[2:order + 1] .= zero(postNewtonX.coeffs[1]) + postNewtonY.coeffs[1] = constant_term(pntempY) * constant_term(c_m2) + postNewtonY.coeffs[2:order + 1] .= zero(postNewtonY.coeffs[1]) + postNewtonZ.coeffs[1] = constant_term(pntempZ) * constant_term(c_m2) + postNewtonZ.coeffs[2:order + 1] .= zero(postNewtonZ.coeffs[1]) + tmp895.coeffs[1] = constant_term(Y[1]) * constant_term(W[1]) + tmp895.coeffs[2:order + 1] .= zero(tmp895.coeffs[1]) + tmp896.coeffs[1] = constant_term(Z[1]) * constant_term(V[1]) + tmp896.coeffs[2:order + 1] .= zero(tmp896.coeffs[1]) + hx.coeffs[1] = constant_term(tmp895) - constant_term(tmp896) + hx.coeffs[2:order + 1] .= zero(hx.coeffs[1]) + tmp898.coeffs[1] = constant_term(Z[1]) * constant_term(U[1]) + tmp898.coeffs[2:order + 1] .= zero(tmp898.coeffs[1]) + tmp899.coeffs[1] = constant_term(X[1]) * constant_term(W[1]) + tmp899.coeffs[2:order + 1] .= zero(tmp899.coeffs[1]) + hy.coeffs[1] = constant_term(tmp898) - constant_term(tmp899) + hy.coeffs[2:order + 1] .= zero(hy.coeffs[1]) + tmp901.coeffs[1] = constant_term(X[1]) * constant_term(V[1]) + tmp901.coeffs[2:order + 1] .= zero(tmp901.coeffs[1]) + tmp902.coeffs[1] = constant_term(Y[1]) * constant_term(U[1]) + tmp902.coeffs[2:order + 1] .= zero(tmp902.coeffs[1]) + hz.coeffs[1] = constant_term(tmp901) - constant_term(tmp902) + hz.coeffs[2:order + 1] .= zero(hz.coeffs[1]) + tmp904.coeffs[1] = constant_term(hz) * constant_term(Y[1]) + tmp904.coeffs[2:order + 1] .= zero(tmp904.coeffs[1]) + tmp905.coeffs[1] = constant_term(hy) * constant_term(Z[1]) + tmp905.coeffs[2:order + 1] .= zero(tmp905.coeffs[1]) + t_x.coeffs[1] = constant_term(tmp904) - constant_term(tmp905) + t_x.coeffs[2:order + 1] .= zero(t_x.coeffs[1]) + tmp907.coeffs[1] = constant_term(hx) * constant_term(Z[1]) + tmp907.coeffs[2:order + 1] .= zero(tmp907.coeffs[1]) + tmp908.coeffs[1] = constant_term(hz) * constant_term(X[1]) + tmp908.coeffs[2:order + 1] .= zero(tmp908.coeffs[1]) + t_y.coeffs[1] = constant_term(tmp907) - constant_term(tmp908) + t_y.coeffs[2:order + 1] .= zero(t_y.coeffs[1]) + tmp910.coeffs[1] = constant_term(hy) * constant_term(X[1]) + tmp910.coeffs[2:order + 1] .= zero(tmp910.coeffs[1]) + tmp911.coeffs[1] = constant_term(hx) * constant_term(Y[1]) + tmp911.coeffs[2:order + 1] .= zero(tmp911.coeffs[1]) + t_z.coeffs[1] = constant_term(tmp910) - constant_term(tmp911) + t_z.coeffs[2:order + 1] .= zero(t_z.coeffs[1]) + tmp914.coeffs[1] = constant_term(t_x) ^ float(constant_term(2)) + tmp914.coeffs[2:order + 1] .= zero(tmp914.coeffs[1]) + tmp916.coeffs[1] = constant_term(t_y) ^ float(constant_term(2)) + tmp916.coeffs[2:order + 1] .= zero(tmp916.coeffs[1]) + tmp917.coeffs[1] = constant_term(tmp914) + constant_term(tmp916) + tmp917.coeffs[2:order + 1] .= zero(tmp917.coeffs[1]) + tmp919.coeffs[1] = constant_term(t_z) ^ float(constant_term(2)) + tmp919.coeffs[2:order + 1] .= zero(tmp919.coeffs[1]) + tmp920.coeffs[1] = constant_term(tmp917) + constant_term(tmp919) + tmp920.coeffs[2:order + 1] .= zero(tmp920.coeffs[1]) + t_norm.coeffs[1] = sqrt(constant_term(tmp920)) + t_norm.coeffs[2:order + 1] .= zero(t_norm.coeffs[1]) + t_x_unit.coeffs[1] = constant_term(t_x) / constant_term(t_norm) + t_x_unit.coeffs[2:order + 1] .= zero(t_x_unit.coeffs[1]) + t_y_unit.coeffs[1] = constant_term(t_y) / constant_term(t_norm) + t_y_unit.coeffs[2:order + 1] .= zero(t_y_unit.coeffs[1]) + t_z_unit.coeffs[1] = constant_term(t_z) / constant_term(t_norm) + t_z_unit.coeffs[2:order + 1] .= zero(t_z_unit.coeffs[1]) + tmp925.coeffs[1] = constant_term(X[1]) / constant_term(r_p1d2[1]) + tmp925.coeffs[2:order + 1] .= zero(tmp925.coeffs[1]) + r_x_unit.coeffs[1] = -(constant_term(tmp925)) + r_x_unit.coeffs[2:order + 1] .= zero(r_x_unit.coeffs[1]) + tmp927.coeffs[1] = constant_term(Y[1]) / constant_term(r_p1d2[1]) + tmp927.coeffs[2:order + 1] .= zero(tmp927.coeffs[1]) + r_y_unit.coeffs[1] = -(constant_term(tmp927)) + r_y_unit.coeffs[2:order + 1] .= zero(r_y_unit.coeffs[1]) + tmp929.coeffs[1] = constant_term(Z[1]) / constant_term(r_p1d2[1]) + tmp929.coeffs[2:order + 1] .= zero(tmp929.coeffs[1]) + r_z_unit.coeffs[1] = -(constant_term(tmp929)) + r_z_unit.coeffs[2:order + 1] .= zero(r_z_unit.coeffs[1]) + g_r.coeffs[1] = identity(constant_term(r_p2[1])) + g_r.coeffs[2:order + 1] .= zero(g_r.coeffs[1]) + A2_t_g_r.coeffs[1] = constant_term(q[7]) / constant_term(g_r) + A2_t_g_r.coeffs[2:order + 1] .= zero(A2_t_g_r.coeffs[1]) + A1_t_g_r.coeffs[1] = constant_term(q[8]) / constant_term(g_r) + A1_t_g_r.coeffs[2:order + 1] .= zero(A1_t_g_r.coeffs[1]) + tmp933.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_x_unit) + tmp933.coeffs[2:order + 1] .= zero(tmp933.coeffs[1]) + tmp934.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_x_unit) + tmp934.coeffs[2:order + 1] .= zero(tmp934.coeffs[1]) + NGAx.coeffs[1] = constant_term(tmp933) + constant_term(tmp934) + NGAx.coeffs[2:order + 1] .= zero(NGAx.coeffs[1]) + tmp936.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_y_unit) + tmp936.coeffs[2:order + 1] .= zero(tmp936.coeffs[1]) + tmp937.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_y_unit) + tmp937.coeffs[2:order + 1] .= zero(tmp937.coeffs[1]) + NGAy.coeffs[1] = constant_term(tmp936) + constant_term(tmp937) + NGAy.coeffs[2:order + 1] .= zero(NGAy.coeffs[1]) + tmp939.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_z_unit) + tmp939.coeffs[2:order + 1] .= zero(tmp939.coeffs[1]) + tmp940.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_z_unit) + tmp940.coeffs[2:order + 1] .= zero(tmp940.coeffs[1]) + NGAz.coeffs[1] = constant_term(tmp939) + constant_term(tmp940) + NGAz.coeffs[2:order + 1] .= zero(NGAz.coeffs[1]) + tmp942.coeffs[1] = constant_term(postNewtonX) + constant_term(accX) + tmp942.coeffs[2:order + 1] .= zero(tmp942.coeffs[1]) + (dq[4]).coeffs[1] = constant_term(tmp942) + constant_term(NGAx) + (dq[4]).coeffs[2:order + 1] .= zero((dq[4]).coeffs[1]) + tmp944.coeffs[1] = constant_term(postNewtonY) + constant_term(accY) + tmp944.coeffs[2:order + 1] .= zero(tmp944.coeffs[1]) + (dq[5]).coeffs[1] = constant_term(tmp944) + constant_term(NGAy) + (dq[5]).coeffs[2:order + 1] .= zero((dq[5]).coeffs[1]) + tmp946.coeffs[1] = constant_term(postNewtonZ) + constant_term(accZ) + tmp946.coeffs[2:order + 1] .= zero(tmp946.coeffs[1]) + (dq[6]).coeffs[1] = constant_term(tmp946) + constant_term(NGAz) + (dq[6]).coeffs[2:order + 1] .= zero((dq[6]).coeffs[1]) + (dq[7]).coeffs[1] = identity(constant_term(zero_q_1)) + (dq[7]).coeffs[2:order + 1] .= zero((dq[7]).coeffs[1]) + for __idx = eachindex(q) + (q[__idx]).coeffs[2] = (dq[__idx]).coeffs[1] + end + for ord = 1:order - 1 + ordnext = ord + 1 + TaylorSeries.identity!(pntempX, zero_q_1, ord) + TaylorSeries.identity!(pntempY, zero_q_1, ord) + TaylorSeries.identity!(pntempZ, zero_q_1, ord) + TaylorSeries.identity!(accX, zero_q_1, ord) + TaylorSeries.identity!(accY, zero_q_1, ord) + TaylorSeries.identity!(accZ, zero_q_1, ord) + TaylorSeries.identity!(dq[1], q[4], ord) + TaylorSeries.identity!(dq[2], q[5], ord) + TaylorSeries.identity!(dq[3], q[6], ord) + TaylorSeries.identity!(newtonianNb_Potential[N], zero_q_1, ord) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 + TaylorSeries.identity!(ui[i], ss16asteph_t[3 * ((N - 1) + i) - 2], ord) + TaylorSeries.identity!(vi[i], ss16asteph_t[3 * ((N - 1) + i) - 1], ord) + TaylorSeries.identity!(wi[i], ss16asteph_t[3 * ((N - 1) + i)], ord) + TaylorSeries.subst!(X[i], ss16asteph_t[3i - 2], q[1], ord) + TaylorSeries.subst!(Y[i], ss16asteph_t[3i - 1], q[2], ord) + TaylorSeries.subst!(Z[i], ss16asteph_t[3i], q[3], ord) + TaylorSeries.subst!(U[i], ui[i], dq[1], ord) + TaylorSeries.subst!(V[i], vi[i], dq[2], ord) + TaylorSeries.subst!(W[i], wi[i], dq[3], ord) + TaylorSeries.mul!(tmp687[1], 4, dq[1], ord) + TaylorSeries.mul!(tmp689[i], 3, ui[i], ord) + TaylorSeries.subst!(_4U_m_3X[i], tmp687[1], tmp689[i], ord) + TaylorSeries.mul!(tmp692[2], 4, dq[2], ord) + TaylorSeries.mul!(tmp694[i], 3, vi[i], ord) + TaylorSeries.subst!(_4V_m_3Y[i], tmp692[2], tmp694[i], ord) + TaylorSeries.mul!(tmp697[3], 4, dq[3], ord) + TaylorSeries.mul!(tmp699[i], 3, wi[i], ord) + TaylorSeries.subst!(_4W_m_3Z[i], tmp697[3], tmp699[i], ord) + TaylorSeries.mul!(pn2x[i], X[i], _4U_m_3X[i], ord) + TaylorSeries.mul!(pn2y[i], Y[i], _4V_m_3Y[i], ord) + TaylorSeries.mul!(pn2z[i], Z[i], _4W_m_3Z[i], ord) + TaylorSeries.mul!(UU[i], ui[i], dq[1], ord) + TaylorSeries.mul!(VV[i], vi[i], dq[2], ord) + TaylorSeries.mul!(WW[i], wi[i], dq[3], ord) + TaylorSeries.add!(tmp707[i], UU[i], VV[i], ord) + TaylorSeries.add!(vi_dot_vj[i], tmp707[i], WW[i], ord) + TaylorSeries.pow!(tmp710[i], X[i], 2, ord) + TaylorSeries.pow!(tmp712[i], Y[i], 2, ord) + TaylorSeries.add!(tmp713[i], tmp710[i], tmp712[i], ord) + TaylorSeries.pow!(tmp715[i], Z[i], 2, ord) + TaylorSeries.add!(r_p2[i], tmp713[i], tmp715[i], ord) + TaylorSeries.sqrt!(r_p1d2[i], r_p2[i], ord) + TaylorSeries.pow!(r_p3d2[i], r_p2[i], 1.5, ord) + TaylorSeries.pow!(r_p7d2[i], r_p2[i], 3.5, ord) + TaylorSeries.div!(newtonianCoeff[i], μ[i], r_p3d2[i], ord) + TaylorSeries.add!(tmp723[i], pn2x[i], pn2y[i], ord) + TaylorSeries.add!(tmp724[i], tmp723[i], pn2z[i], ord) + TaylorSeries.mul!(pn2[i], newtonianCoeff[i], tmp724[i], ord) + TaylorSeries.mul!(newton_acc_X[i], X[i], newtonianCoeff[i], ord) + TaylorSeries.mul!(newton_acc_Y[i], Y[i], newtonianCoeff[i], ord) + TaylorSeries.mul!(newton_acc_Z[i], Z[i], newtonianCoeff[i], ord) + TaylorSeries.div!(newtonian1b_Potential[i], μ[i], r_p1d2[i], ord) + TaylorSeries.mul!(pn3[i], 3.5, newtonian1b_Potential[i], ord) + TaylorSeries.mul!(U_t_pn2[i], pn2[i], U[i], ord) + TaylorSeries.mul!(V_t_pn2[i], pn2[i], V[i], ord) + TaylorSeries.mul!(W_t_pn2[i], pn2[i], W[i], ord) + if UJ_interaction[i] + TaylorSeries.subst!(tmp735[i], X[i], ord) + TaylorSeries.mul!(t31[i], tmp735[i], M_[1, 3, i], ord) + TaylorSeries.subst!(tmp737[i], Y[i], ord) + TaylorSeries.mul!(t32[i], tmp737[i], M_[2, 3, i], ord) + TaylorSeries.subst!(tmp739[i], Z[i], ord) + TaylorSeries.mul!(t33[i], tmp739[i], M_[3, 3, i], ord) + TaylorSeries.add!(tmp741[i], t31[i], t32[i], ord) + TaylorSeries.add!(r_sin_ϕ[i], tmp741[i], t33[i], ord) + TaylorSeries.div!(sin_ϕ[i], r_sin_ϕ[i], r_p1d2[i], ord) + TaylorSeries.asin!(ϕ[i], sin_ϕ[i], tmp948[i], ord) + TaylorSeries.sincos!(tmp949[i], cos_ϕ[i], ϕ[i], ord) + TaylorSeries.pow!(sin2_ϕ[i], sin_ϕ[i], 2, ord) + TaylorSeries.pow!(sin3_ϕ[i], sin_ϕ[i], 3, ord) + TaylorSeries.mul!(tmp751[i], 1.5, sin2_ϕ[i], ord) + TaylorSeries.subst!(P_2_sin_ϕ[i], tmp751[i], 0.5, ord) + TaylorSeries.mul!(∂P_2_sin_ϕ[i], 3, sin_ϕ[i], ord) + TaylorSeries.mul!(tmp757[i], -1.5, sin_ϕ[i], ord) + TaylorSeries.mul!(tmp759[i], 2.5, sin3_ϕ[i], ord) + TaylorSeries.add!(P_3_sin_ϕ[i], tmp757[i], tmp759[i], ord) + TaylorSeries.mul!(tmp763[i], 7.5, sin2_ϕ[i], ord) + TaylorSeries.add!(∂P_3_sin_ϕ[i], -1.5, tmp763[i], ord) + TaylorSeries.pow!(tmp766[i], r_p2[i], 2, ord) + TaylorSeries.div!(tmp767[i], Λ2[i], tmp766[i], ord) + TaylorSeries.subst!(Λ2j_div_r4[i], tmp767[i], ord) + TaylorSeries.pow!(tmp770[i], r_p1d2[i], 5, ord) + TaylorSeries.div!(tmp771[i], Λ3[i], tmp770[i], ord) + TaylorSeries.subst!(Λ3j_div_r5[i], tmp771[i], ord) + TaylorSeries.subst!(tmp773[i], cos_ϕ[i], ord) + TaylorSeries.mul!(m_c_ϕ_∂P_2[i], tmp773[i], ∂P_2_sin_ϕ[i], ord) + TaylorSeries.subst!(tmp775[i], cos_ϕ[i], ord) + TaylorSeries.mul!(m_c_ϕ_∂P_3[i], tmp775[i], ∂P_3_sin_ϕ[i], ord) + TaylorSeries.mul!(tmp778[i], Λ2j_div_r4[i], 3, ord) + TaylorSeries.mul!(F_J2_ξ[i], tmp778[i], P_2_sin_ϕ[i], ord) + TaylorSeries.mul!(F_J2_ζ[i], Λ2j_div_r4[i], m_c_ϕ_∂P_2[i], ord) + TaylorSeries.mul!(tmp782[i], Λ3j_div_r5[i], 4, ord) + TaylorSeries.mul!(F_J3_ξ[i], tmp782[i], P_3_sin_ϕ[i], ord) + TaylorSeries.mul!(F_J3_ζ[i], Λ3j_div_r5[i], m_c_ϕ_∂P_3[i], ord) + TaylorSeries.identity!(F_J_ξ[i], F_J2_ξ[i], ord) + TaylorSeries.identity!(F_J_ζ[i], F_J2_ζ[i], ord) + TaylorSeries.subst!(tmp785[i], X[i], ord) + TaylorSeries.div!(ξx[i], tmp785[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp787[i], Y[i], ord) + TaylorSeries.div!(ξy[i], tmp787[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp789[i], Z[i], ord) + TaylorSeries.div!(ξz[i], tmp789[i], r_p1d2[i], ord) + TaylorSeries.mul!(ηx1[i], M_[2, 3, i], ξz[i], ord) + TaylorSeries.mul!(ηy1[i], M_[3, 3, i], ξx[i], ord) + TaylorSeries.mul!(ηz1[i], M_[1, 3, i], ξy[i], ord) + TaylorSeries.mul!(ηx2[i], M_[3, 3, i], ξy[i], ord) + TaylorSeries.mul!(ηy2[i], M_[1, 3, i], ξz[i], ord) + TaylorSeries.mul!(ηz2[i], M_[2, 3, i], ξx[i], ord) + TaylorSeries.subst!(ηx[i], ηx1[i], ηx2[i], ord) + TaylorSeries.subst!(ηy[i], ηy1[i], ηy2[i], ord) + TaylorSeries.subst!(ηz[i], ηz1[i], ηz2[i], ord) + TaylorSeries.mul!(ζx1[i], ξy[i], ηz[i], ord) + TaylorSeries.mul!(ζy1[i], ξz[i], ηx[i], ord) + TaylorSeries.mul!(ζz1[i], ξx[i], ηy[i], ord) + TaylorSeries.mul!(ζx2[i], ξz[i], ηy[i], ord) + TaylorSeries.mul!(ζy2[i], ξx[i], ηz[i], ord) + TaylorSeries.mul!(ζz2[i], ξy[i], ηx[i], ord) + TaylorSeries.subst!(ζx[i], ζx1[i], ζx2[i], ord) + TaylorSeries.subst!(ζy[i], ζy1[i], ζy2[i], ord) + TaylorSeries.subst!(ζz[i], ζz1[i], ζz2[i], ord) + TaylorSeries.mul!(F_J2_x1[i], F_J_ξ[i], ξx[i], ord) + TaylorSeries.mul!(F_J2_y1[i], F_J_ξ[i], ξy[i], ord) + TaylorSeries.mul!(F_J2_z1[i], F_J_ξ[i], ξz[i], ord) + TaylorSeries.mul!(F_J2_x2[i], F_J_ζ[i], ζx[i], ord) + TaylorSeries.mul!(F_J2_y2[i], F_J_ζ[i], ζy[i], ord) + TaylorSeries.mul!(F_J2_z2[i], F_J_ζ[i], ζz[i], ord) + TaylorSeries.add!(F_J2_x[i], F_J2_x1[i], F_J2_x2[i], ord) + TaylorSeries.add!(F_J2_y[i], F_J2_y1[i], F_J2_y2[i], ord) + TaylorSeries.add!(F_J2_z[i], F_J2_z1[i], F_J2_z2[i], ord) + end + TaylorSeries.pow!(tmp819[i], ui[i], 2, ord) + TaylorSeries.pow!(tmp821[i], vi[i], 2, ord) + TaylorSeries.add!(tmp822[i], tmp819[i], tmp821[i], ord) + TaylorSeries.pow!(tmp824[i], wi[i], 2, ord) + TaylorSeries.add!(v2[i], tmp822[i], tmp824[i], ord) + end + TaylorSeries.pow!(tmp827, q[4], 2, ord) + TaylorSeries.pow!(tmp829, q[5], 2, ord) + TaylorSeries.add!(tmp830, tmp827, tmp829, ord) + TaylorSeries.pow!(tmp832, q[6], 2, ord) + TaylorSeries.add!(v2[N], tmp830, tmp832, ord) + for i = 1:Nm1 + TaylorSeries.add!(temp_004[i], newtonian1b_Potential[i], newtonianNb_Potential[N], ord) + TaylorSeries.identity!(newtonianNb_Potential[N], temp_004[i], ord) + if UJ_interaction[i] + TaylorSeries.mul!(tmp835[i], μ[i], F_J2_x[i], ord) + TaylorSeries.subst!(temp_accX_i[i], accX, tmp835[i], ord) + TaylorSeries.identity!(accX, temp_accX_i[i], ord) + TaylorSeries.mul!(tmp837[i], μ[i], F_J2_y[i], ord) + TaylorSeries.subst!(temp_accY_i[i], accY, tmp837[i], ord) + TaylorSeries.identity!(accY, temp_accY_i[i], ord) + TaylorSeries.mul!(tmp839[i], μ[i], F_J2_z[i], ord) + TaylorSeries.subst!(temp_accZ_i[i], accZ, tmp839[i], ord) + TaylorSeries.identity!(accZ, temp_accZ_i[i], ord) + end + end + TaylorSeries.mul!(_4ϕj[N], 4, newtonianNb_Potential[N], ord) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 + TaylorSeries.add!(ϕi_plus_4ϕj[i], newtonianNb_Potential_t[i], _4ϕj[N], ord) + TaylorSeries.mul!(tmp845[i], 2, v2[i], ord) + TaylorSeries.mul!(tmp847[i], 4, vi_dot_vj[i], ord) + TaylorSeries.subst!(tmp848[i], tmp845[i], tmp847[i], ord) + TaylorSeries.add!(sj2_plus_2si2_minus_4vivj[i], tmp848[i], v2[N], ord) + TaylorSeries.subst!(ϕs_and_vs[i], sj2_plus_2si2_minus_4vivj[i], ϕi_plus_4ϕj[i], ord) + TaylorSeries.mul!(Xij_t_Ui[i], X[i], ui[i], ord) + TaylorSeries.mul!(Yij_t_Vi[i], Y[i], vi[i], ord) + TaylorSeries.mul!(Zij_t_Wi[i], Z[i], wi[i], ord) + TaylorSeries.add!(tmp854[i], Xij_t_Ui[i], Yij_t_Vi[i], ord) + TaylorSeries.add!(Rij_dot_Vi[i], tmp854[i], Zij_t_Wi[i], ord) + TaylorSeries.pow!(tmp857[i], Rij_dot_Vi[i], 2, ord) + TaylorSeries.div!(pn1t7[i], tmp857[i], r_p2[i], ord) + TaylorSeries.mul!(tmp860[i], 1.5, pn1t7[i], ord) + TaylorSeries.subst!(pn1t2_7[i], ϕs_and_vs[i], tmp860[i], ord) + TaylorSeries.add!(pn1t1_7[i], c_p2, pn1t2_7[i], ord) + TaylorSeries.mul!(pNX_t_X[i], acceph_t[3i - 2], X[i], ord) + TaylorSeries.mul!(pNY_t_Y[i], acceph_t[3i - 1], Y[i], ord) + TaylorSeries.mul!(pNZ_t_Z[i], acceph_t[3i], Z[i], ord) + TaylorSeries.add!(tmp867[i], pNX_t_X[i], pNY_t_Y[i], ord) + TaylorSeries.add!(tmp868[i], tmp867[i], pNZ_t_Z[i], ord) + TaylorSeries.mul!(tmp869[i], 0.5, tmp868[i], ord) + TaylorSeries.add!(pn1[i], pn1t1_7[i], tmp869[i], ord) + TaylorSeries.mul!(X_t_pn1[i], newton_acc_X[i], pn1[i], ord) + TaylorSeries.mul!(Y_t_pn1[i], newton_acc_Y[i], pn1[i], ord) + TaylorSeries.mul!(Z_t_pn1[i], newton_acc_Z[i], pn1[i], ord) + TaylorSeries.mul!(pNX_t_pn3[i], acceph_t[3i - 2], pn3[i], ord) + TaylorSeries.mul!(pNY_t_pn3[i], acceph_t[3i - 1], pn3[i], ord) + TaylorSeries.mul!(pNZ_t_pn3[i], acceph_t[3i], pn3[i], ord) + end + for i = 1:10 + TaylorSeries.add!(tmp877[i], U_t_pn2[i], pNX_t_pn3[i], ord) + TaylorSeries.add!(termpnx[i], X_t_pn1[i], tmp877[i], ord) + TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) + TaylorSeries.identity!(pntempX, sumpnx[i], ord) + TaylorSeries.add!(tmp880[i], V_t_pn2[i], pNY_t_pn3[i], ord) + TaylorSeries.add!(termpny[i], Y_t_pn1[i], tmp880[i], ord) + TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) + TaylorSeries.identity!(pntempY, sumpny[i], ord) + TaylorSeries.add!(tmp883[i], W_t_pn2[i], pNZ_t_pn3[i], ord) + TaylorSeries.add!(termpnz[i], Z_t_pn1[i], tmp883[i], ord) + TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) + TaylorSeries.identity!(pntempZ, sumpnz[i], ord) + end + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 + TaylorSeries.mul!(X_t_pn1[i], c_p2, newton_acc_X[i], ord) + TaylorSeries.mul!(Y_t_pn1[i], c_p2, newton_acc_Y[i], ord) + TaylorSeries.mul!(Z_t_pn1[i], c_p2, newton_acc_Z[i], ord) + end + for i = 11:Nm1 + TaylorSeries.identity!(termpnx[i], X_t_pn1[i], ord) + TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) + TaylorSeries.identity!(pntempX, sumpnx[i], ord) + TaylorSeries.identity!(termpny[i], Y_t_pn1[i], ord) + TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) + TaylorSeries.identity!(pntempY, sumpny[i], ord) + TaylorSeries.identity!(termpnz[i], Z_t_pn1[i], ord) + TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) + TaylorSeries.identity!(pntempZ, sumpnz[i], ord) + end + TaylorSeries.mul!(postNewtonX, pntempX, c_m2, ord) + TaylorSeries.mul!(postNewtonY, pntempY, c_m2, ord) + TaylorSeries.mul!(postNewtonZ, pntempZ, c_m2, ord) + TaylorSeries.mul!(tmp895, Y[1], W[1], ord) + TaylorSeries.mul!(tmp896, Z[1], V[1], ord) + TaylorSeries.subst!(hx, tmp895, tmp896, ord) + TaylorSeries.mul!(tmp898, Z[1], U[1], ord) + TaylorSeries.mul!(tmp899, X[1], W[1], ord) + TaylorSeries.subst!(hy, tmp898, tmp899, ord) + TaylorSeries.mul!(tmp901, X[1], V[1], ord) + TaylorSeries.mul!(tmp902, Y[1], U[1], ord) + TaylorSeries.subst!(hz, tmp901, tmp902, ord) + TaylorSeries.mul!(tmp904, hz, Y[1], ord) + TaylorSeries.mul!(tmp905, hy, Z[1], ord) + TaylorSeries.subst!(t_x, tmp904, tmp905, ord) + TaylorSeries.mul!(tmp907, hx, Z[1], ord) + TaylorSeries.mul!(tmp908, hz, X[1], ord) + TaylorSeries.subst!(t_y, tmp907, tmp908, ord) + TaylorSeries.mul!(tmp910, hy, X[1], ord) + TaylorSeries.mul!(tmp911, hx, Y[1], ord) + TaylorSeries.subst!(t_z, tmp910, tmp911, ord) + TaylorSeries.pow!(tmp914, t_x, 2, ord) + TaylorSeries.pow!(tmp916, t_y, 2, ord) + TaylorSeries.add!(tmp917, tmp914, tmp916, ord) + TaylorSeries.pow!(tmp919, t_z, 2, ord) + TaylorSeries.add!(tmp920, tmp917, tmp919, ord) + TaylorSeries.sqrt!(t_norm, tmp920, ord) + TaylorSeries.div!(t_x_unit, t_x, t_norm, ord) + TaylorSeries.div!(t_y_unit, t_y, t_norm, ord) + TaylorSeries.div!(t_z_unit, t_z, t_norm, ord) + TaylorSeries.div!(tmp925, X[1], r_p1d2[1], ord) + TaylorSeries.subst!(r_x_unit, tmp925, ord) + TaylorSeries.div!(tmp927, Y[1], r_p1d2[1], ord) + TaylorSeries.subst!(r_y_unit, tmp927, ord) + TaylorSeries.div!(tmp929, Z[1], r_p1d2[1], ord) + TaylorSeries.subst!(r_z_unit, tmp929, ord) + TaylorSeries.identity!(g_r, r_p2[1], ord) + TaylorSeries.div!(A2_t_g_r, q[7], g_r, ord) + TaylorSeries.div!(A1_t_g_r, q[8], g_r, ord) + TaylorSeries.mul!(tmp933, A2_t_g_r, t_x_unit, ord) + TaylorSeries.mul!(tmp934, A1_t_g_r, r_x_unit, ord) + TaylorSeries.add!(NGAx, tmp933, tmp934, ord) + TaylorSeries.mul!(tmp936, A2_t_g_r, t_y_unit, ord) + TaylorSeries.mul!(tmp937, A1_t_g_r, r_y_unit, ord) + TaylorSeries.add!(NGAy, tmp936, tmp937, ord) + TaylorSeries.mul!(tmp939, A2_t_g_r, t_z_unit, ord) + TaylorSeries.mul!(tmp940, A1_t_g_r, r_z_unit, ord) + TaylorSeries.add!(NGAz, tmp939, tmp940, ord) + TaylorSeries.add!(tmp942, postNewtonX, accX, ord) + TaylorSeries.add!(dq[4], tmp942, NGAx, ord) + TaylorSeries.add!(tmp944, postNewtonY, accY, ord) + TaylorSeries.add!(dq[5], tmp944, NGAy, ord) + TaylorSeries.add!(tmp946, postNewtonZ, accZ, ord) + TaylorSeries.add!(dq[6], tmp946, NGAz, ord) + TaylorSeries.identity!(dq[7], zero_q_1, ord) + for __idx = eachindex(q) + (q[__idx]).coeffs[ordnext + 1] = (dq[__idx]).coeffs[ordnext] / ordnext + end + end + return nothing +end + +# TaylorIntegration._allocate_jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_eph_threads! +function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params) where {_T <: Real, _S <: Number, _N} + order = t.order + local jd0 = params[4] + local dsj2k = t + (jd0 - JD_J2000) + local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) + local acceph_t = evaleph(params[2], dsj2k, q[1]) + local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) + local S = eltype(q) + local UJ_interaction = params[5] + local N = params[6] + local Nm1 = N - 1 + local μ = params[7] + local zero_q_1 = auxzero(q[1]) + X = Array{S}(undef, N) + Y = Array{S}(undef, N) + Z = Array{S}(undef, N) + r_p2 = Array{S}(undef, N) + r_p1d2 = Array{S}(undef, N) + r_p3d2 = Array{S}(undef, N) + r_p7d2 = Array{S}(undef, N) + newtonianCoeff = Array{S}(undef, N) + ui = Array{S}(undef, N - 1) + vi = Array{S}(undef, N - 1) + wi = Array{S}(undef, N - 1) + U = Array{S}(undef, N) + V = Array{S}(undef, N) + W = Array{S}(undef, N) + _4U_m_3X = Array{S}(undef, N) + _4V_m_3Y = Array{S}(undef, N) + _4W_m_3Z = Array{S}(undef, N) + UU = Array{S}(undef, N) + VV = Array{S}(undef, N) + WW = Array{S}(undef, N) + newtonian1b_Potential = Array{S}(undef, N) + newtonianNb_Potential = Array{S}(undef, N) + newton_acc_X = Array{S}(undef, N) + newton_acc_Y = Array{S}(undef, N) + newton_acc_Z = Array{S}(undef, N) + v2 = Array{S}(undef, N) + vi_dot_vj = Array{S}(undef, N) + pn2 = Array{S}(undef, N) + U_t_pn2 = Array{S}(undef, N) + V_t_pn2 = Array{S}(undef, N) + W_t_pn2 = Array{S}(undef, N) + pn3 = Array{S}(undef, N) + pNX_t_pn3 = Array{S}(undef, N) + pNY_t_pn3 = Array{S}(undef, N) + pNZ_t_pn3 = Array{S}(undef, N) + _4ϕj = Array{S}(undef, N) + ϕi_plus_4ϕj = Array{S}(undef, N) + sj2_plus_2si2_minus_4vivj = Array{S}(undef, N) + ϕs_and_vs = Array{S}(undef, N) + pn1t1_7 = Array{S}(undef, N) + pNX_t_X = Array{S}(undef, N) + pNY_t_Y = Array{S}(undef, N) + pNZ_t_Z = Array{S}(undef, N) + pn1 = Array{S}(undef, N) + X_t_pn1 = Array{S}(undef, N) + Y_t_pn1 = Array{S}(undef, N) + Z_t_pn1 = Array{S}(undef, N) + pntempX = Taylor1(identity(constant_term(zero_q_1)), order) + pntempY = Taylor1(identity(constant_term(zero_q_1)), order) + pntempZ = Taylor1(identity(constant_term(zero_q_1)), order) + t31 = Array{S}(undef, N) + t32 = Array{S}(undef, N) + t33 = Array{S}(undef, N) + r_sin_ϕ = Array{S}(undef, N) + sin_ϕ = Array{S}(undef, N) + ϕ = Array{S}(undef, N) + cos_ϕ = Array{S}(undef, N) + sin2_ϕ = Array{S}(undef, N) + sin3_ϕ = Array{S}(undef, N) + sin4_ϕ = Array{S}(undef, N) + F_J2_x = Array{S}(undef, N) + F_J2_y = Array{S}(undef, N) + F_J2_z = Array{S}(undef, N) + F_J2_x1 = Array{S}(undef, N) + F_J2_y1 = Array{S}(undef, N) + F_J2_z1 = Array{S}(undef, N) + F_J2_x2 = Array{S}(undef, N) + F_J2_y2 = Array{S}(undef, N) + F_J2_z2 = Array{S}(undef, N) + temp_accX_i = Array{S}(undef, N) + temp_accY_i = Array{S}(undef, N) + temp_accZ_i = Array{S}(undef, N) + P_2_sin_ϕ = Array{S}(undef, N) + ∂P_2_sin_ϕ = Array{S}(undef, N) + P_3_sin_ϕ = Array{S}(undef, N) + ∂P_3_sin_ϕ = Array{S}(undef, N) + m_c_ϕ_∂P_2 = Array{S}(undef, N) + m_c_ϕ_∂P_3 = Array{S}(undef, N) + Λ2j_div_r4 = Array{S}(undef, N) + Λ3j_div_r5 = Array{S}(undef, N) + F_J_ξ = Array{S}(undef, N) + F_J_η = Array{S}(undef, N) + F_J_ζ = Array{S}(undef, N) + F_J2_ξ = Array{S}(undef, N) + F_J2_η = Array{S}(undef, N) + F_J2_ζ = Array{S}(undef, N) + F_J3_ξ = Array{S}(undef, N) + F_J3_η = Array{S}(undef, N) + F_J3_ζ = Array{S}(undef, N) + ξx = Array{S}(undef, N) + ξy = Array{S}(undef, N) + ξz = Array{S}(undef, N) + ηx = Array{S}(undef, N) + ηy = Array{S}(undef, N) + ηz = Array{S}(undef, N) + ηx1 = Array{S}(undef, N) + ηy1 = Array{S}(undef, N) + ηz1 = Array{S}(undef, N) + ηx2 = Array{S}(undef, N) + ηy2 = Array{S}(undef, N) + ηz2 = Array{S}(undef, N) + ζx = Array{S}(undef, N) + ζy = Array{S}(undef, N) + ζz = Array{S}(undef, N) + ζx1 = Array{S}(undef, N) + ζy1 = Array{S}(undef, N) + ζz1 = Array{S}(undef, N) + ζx2 = Array{S}(undef, N) + ζy2 = Array{S}(undef, N) + ζz2 = Array{S}(undef, N) + accX = Taylor1(identity(constant_term(zero_q_1)), order) + accY = Taylor1(identity(constant_term(zero_q_1)), order) + accZ = Taylor1(identity(constant_term(zero_q_1)), order) + local M_ = Array{S}(undef, 3, 3, N) + local M_ .= zero_q_1 + local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 + dq[1] = Taylor1(identity(constant_term(q[4])), order) + dq[2] = Taylor1(identity(constant_term(q[5])), order) + dq[3] = Taylor1(identity(constant_term(q[6])), order) + newtonianNb_Potential[N] = Taylor1(identity(constant_term(zero_q_1)), order) + tmp1317 = Array{Taylor1{_S}}(undef, size(dq)) + tmp1317 .= Taylor1(zero(constant_term(q[1])), order) + tmp1319 = Array{Taylor1{_S}}(undef, size(ui)) + tmp1319 .= Taylor1(zero(constant_term(q[1])), order) + tmp1322 = Array{Taylor1{_S}}(undef, size(dq)) + tmp1322 .= Taylor1(zero(constant_term(q[1])), order) + tmp1324 = Array{Taylor1{_S}}(undef, size(vi)) + tmp1324 .= Taylor1(zero(constant_term(q[1])), order) + tmp1327 = Array{Taylor1{_S}}(undef, size(dq)) + tmp1327 .= Taylor1(zero(constant_term(q[1])), order) + tmp1329 = Array{Taylor1{_S}}(undef, size(wi)) + tmp1329 .= Taylor1(zero(constant_term(q[1])), order) + pn2x = Array{Taylor1{_S}}(undef, size(X)) + pn2x .= Taylor1(zero(constant_term(q[1])), order) + pn2y = Array{Taylor1{_S}}(undef, size(Y)) + pn2y .= Taylor1(zero(constant_term(q[1])), order) + pn2z = Array{Taylor1{_S}}(undef, size(Z)) + pn2z .= Taylor1(zero(constant_term(q[1])), order) + tmp1337 = Array{Taylor1{_S}}(undef, size(UU)) + tmp1337 .= Taylor1(zero(constant_term(q[1])), order) + tmp1340 = Array{Taylor1{_S}}(undef, size(X)) + tmp1340 .= Taylor1(zero(constant_term(q[1])), order) + tmp1342 = Array{Taylor1{_S}}(undef, size(Y)) + tmp1342 .= Taylor1(zero(constant_term(q[1])), order) + tmp1343 = Array{Taylor1{_S}}(undef, size(tmp1340)) + tmp1343 .= Taylor1(zero(constant_term(q[1])), order) + tmp1345 = Array{Taylor1{_S}}(undef, size(Z)) + tmp1345 .= Taylor1(zero(constant_term(q[1])), order) + tmp1353 = Array{Taylor1{_S}}(undef, size(pn2x)) + tmp1353 .= Taylor1(zero(constant_term(q[1])), order) + tmp1354 = Array{Taylor1{_S}}(undef, size(tmp1353)) + tmp1354 .= Taylor1(zero(constant_term(q[1])), order) + tmp1449 = Array{Taylor1{_S}}(undef, size(ui)) + tmp1449 .= Taylor1(zero(constant_term(q[1])), order) + tmp1451 = Array{Taylor1{_S}}(undef, size(vi)) + tmp1451 .= Taylor1(zero(constant_term(q[1])), order) + tmp1452 = Array{Taylor1{_S}}(undef, size(tmp1449)) + tmp1452 .= Taylor1(zero(constant_term(q[1])), order) + tmp1454 = Array{Taylor1{_S}}(undef, size(wi)) + tmp1454 .= Taylor1(zero(constant_term(q[1])), order) + tmp1365 = Array{Taylor1{_S}}(undef, size(X)) + tmp1365 .= Taylor1(zero(constant_term(q[1])), order) + tmp1367 = Array{Taylor1{_S}}(undef, size(Y)) + tmp1367 .= Taylor1(zero(constant_term(q[1])), order) + tmp1369 = Array{Taylor1{_S}}(undef, size(Z)) + tmp1369 .= Taylor1(zero(constant_term(q[1])), order) + tmp1371 = Array{Taylor1{_S}}(undef, size(t31)) + tmp1371 .= Taylor1(zero(constant_term(q[1])), order) + tmp1528 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) + tmp1528 .= Taylor1(zero(constant_term(q[1])), order) + tmp1529 = Array{Taylor1{_S}}(undef, size(ϕ)) + tmp1529 .= Taylor1(zero(constant_term(q[1])), order) + tmp1381 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) + tmp1381 .= Taylor1(zero(constant_term(q[1])), order) + tmp1387 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) + tmp1387 .= Taylor1(zero(constant_term(q[1])), order) + tmp1389 = Array{Taylor1{_S}}(undef, size(sin3_ϕ)) + tmp1389 .= Taylor1(zero(constant_term(q[1])), order) + tmp1393 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) + tmp1393 .= Taylor1(zero(constant_term(q[1])), order) + tmp1396 = Array{Taylor1{_S}}(undef, size(r_p2)) + tmp1396 .= Taylor1(zero(constant_term(q[1])), order) + tmp1397 = Array{Taylor1{_S}}(undef, size(Λ2)) + tmp1397 .= Taylor1(zero(constant_term(q[1])), order) + tmp1400 = Array{Taylor1{_S}}(undef, size(r_p1d2)) + tmp1400 .= Taylor1(zero(constant_term(q[1])), order) + tmp1401 = Array{Taylor1{_S}}(undef, size(Λ3)) + tmp1401 .= Taylor1(zero(constant_term(q[1])), order) + tmp1403 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) + tmp1403 .= Taylor1(zero(constant_term(q[1])), order) + tmp1405 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) + tmp1405 .= Taylor1(zero(constant_term(q[1])), order) + tmp1408 = Array{Taylor1{_S}}(undef, size(Λ2j_div_r4)) + tmp1408 .= Taylor1(zero(constant_term(q[1])), order) + tmp1412 = Array{Taylor1{_S}}(undef, size(Λ3j_div_r5)) + tmp1412 .= Taylor1(zero(constant_term(q[1])), order) + tmp1415 = Array{Taylor1{_S}}(undef, size(X)) + tmp1415 .= Taylor1(zero(constant_term(q[1])), order) + tmp1417 = Array{Taylor1{_S}}(undef, size(Y)) + tmp1417 .= Taylor1(zero(constant_term(q[1])), order) + tmp1419 = Array{Taylor1{_S}}(undef, size(Z)) + tmp1419 .= Taylor1(zero(constant_term(q[1])), order) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 + ui[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])), order) + vi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])), order) + wi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])), order) + X[i] = Taylor1(constant_term(ss16asteph_t[3i - 2]) - constant_term(q[1]), order) + Y[i] = Taylor1(constant_term(ss16asteph_t[3i - 1]) - constant_term(q[2]), order) + Z[i] = Taylor1(constant_term(ss16asteph_t[3i]) - constant_term(q[3]), order) + U[i] = Taylor1(constant_term(ui[i]) - constant_term(dq[1]), order) + V[i] = Taylor1(constant_term(vi[i]) - constant_term(dq[2]), order) + W[i] = Taylor1(constant_term(wi[i]) - constant_term(dq[3]), order) + tmp1317[1] = Taylor1(constant_term(4) * constant_term(dq[1]), order) + tmp1319[i] = Taylor1(constant_term(3) * constant_term(ui[i]), order) + _4U_m_3X[i] = Taylor1(constant_term(tmp1317[1]) - constant_term(tmp1319[i]), order) + tmp1322[2] = Taylor1(constant_term(4) * constant_term(dq[2]), order) + tmp1324[i] = Taylor1(constant_term(3) * constant_term(vi[i]), order) + _4V_m_3Y[i] = Taylor1(constant_term(tmp1322[2]) - constant_term(tmp1324[i]), order) + tmp1327[3] = Taylor1(constant_term(4) * constant_term(dq[3]), order) + tmp1329[i] = Taylor1(constant_term(3) * constant_term(wi[i]), order) + _4W_m_3Z[i] = Taylor1(constant_term(tmp1327[3]) - constant_term(tmp1329[i]), order) + pn2x[i] = Taylor1(constant_term(X[i]) * constant_term(_4U_m_3X[i]), order) + pn2y[i] = Taylor1(constant_term(Y[i]) * constant_term(_4V_m_3Y[i]), order) + pn2z[i] = Taylor1(constant_term(Z[i]) * constant_term(_4W_m_3Z[i]), order) + UU[i] = Taylor1(constant_term(ui[i]) * constant_term(dq[1]), order) + VV[i] = Taylor1(constant_term(vi[i]) * constant_term(dq[2]), order) + WW[i] = Taylor1(constant_term(wi[i]) * constant_term(dq[3]), order) + tmp1337[i] = Taylor1(constant_term(UU[i]) + constant_term(VV[i]), order) + vi_dot_vj[i] = Taylor1(constant_term(tmp1337[i]) + constant_term(WW[i]), order) + tmp1340[i] = Taylor1(constant_term(X[i]) ^ float(constant_term(2)), order) + tmp1342[i] = Taylor1(constant_term(Y[i]) ^ float(constant_term(2)), order) + tmp1343[i] = Taylor1(constant_term(tmp1340[i]) + constant_term(tmp1342[i]), order) + tmp1345[i] = Taylor1(constant_term(Z[i]) ^ float(constant_term(2)), order) + r_p2[i] = Taylor1(constant_term(tmp1343[i]) + constant_term(tmp1345[i]), order) + r_p1d2[i] = Taylor1(sqrt(constant_term(r_p2[i])), order) + r_p3d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(1.5)), order) + r_p7d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(3.5)), order) + newtonianCoeff[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p3d2[i]), order) + tmp1353[i] = Taylor1(constant_term(pn2x[i]) + constant_term(pn2y[i]), order) + tmp1354[i] = Taylor1(constant_term(tmp1353[i]) + constant_term(pn2z[i]), order) + pn2[i] = Taylor1(constant_term(newtonianCoeff[i]) * constant_term(tmp1354[i]), order) + newton_acc_X[i] = Taylor1(constant_term(X[i]) * constant_term(newtonianCoeff[i]), order) + newton_acc_Y[i] = Taylor1(constant_term(Y[i]) * constant_term(newtonianCoeff[i]), order) + newton_acc_Z[i] = Taylor1(constant_term(Z[i]) * constant_term(newtonianCoeff[i]), order) + newtonian1b_Potential[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p1d2[i]), order) + pn3[i] = Taylor1(constant_term(3.5) * constant_term(newtonian1b_Potential[i]), order) + U_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(U[i]), order) + V_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(V[i]), order) + W_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(W[i]), order) + if UJ_interaction[i] + tmp1365[i] = Taylor1(-(constant_term(X[i])), order) + t31[i] = Taylor1(constant_term(tmp1365[i]) * constant_term(M_[1, 3, i]), order) + tmp1367[i] = Taylor1(-(constant_term(Y[i])), order) + t32[i] = Taylor1(constant_term(tmp1367[i]) * constant_term(M_[2, 3, i]), order) + tmp1369[i] = Taylor1(-(constant_term(Z[i])), order) + t33[i] = Taylor1(constant_term(tmp1369[i]) * constant_term(M_[3, 3, i]), order) + tmp1371[i] = Taylor1(constant_term(t31[i]) + constant_term(t32[i]), order) + r_sin_ϕ[i] = Taylor1(constant_term(tmp1371[i]) + constant_term(t33[i]), order) + sin_ϕ[i] = Taylor1(constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]), order) + ϕ[i] = Taylor1(asin(constant_term(sin_ϕ[i])), order) + tmp1528[i] = Taylor1(sqrt(1 - constant_term(sin_ϕ[i]) ^ 2), order) + cos_ϕ[i] = Taylor1(cos(constant_term(ϕ[i])), order) + tmp1529[i] = Taylor1(sin(constant_term(ϕ[i])), order) + sin2_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(2)), order) + sin3_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(3)), order) + tmp1381[i] = Taylor1(constant_term(1.5) * constant_term(sin2_ϕ[i]), order) + P_2_sin_ϕ[i] = Taylor1(constant_term(tmp1381[i]) - constant_term(0.5), order) + ∂P_2_sin_ϕ[i] = Taylor1(constant_term(3) * constant_term(sin_ϕ[i]), order) + tmp1387[i] = Taylor1(constant_term(-1.5) * constant_term(sin_ϕ[i]), order) + tmp1389[i] = Taylor1(constant_term(2.5) * constant_term(sin3_ϕ[i]), order) + P_3_sin_ϕ[i] = Taylor1(constant_term(tmp1387[i]) + constant_term(tmp1389[i]), order) + tmp1393[i] = Taylor1(constant_term(7.5) * constant_term(sin2_ϕ[i]), order) + ∂P_3_sin_ϕ[i] = Taylor1(constant_term(-1.5) + constant_term(tmp1393[i]), order) + tmp1396[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(2)), order) + tmp1397[i] = Taylor1(constant_term(Λ2[i]) / constant_term(tmp1396[i]), order) + Λ2j_div_r4[i] = Taylor1(-(constant_term(tmp1397[i])), order) + tmp1400[i] = Taylor1(constant_term(r_p1d2[i]) ^ float(constant_term(5)), order) + tmp1401[i] = Taylor1(constant_term(Λ3[i]) / constant_term(tmp1400[i]), order) + Λ3j_div_r5[i] = Taylor1(-(constant_term(tmp1401[i])), order) + tmp1403[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) + m_c_ϕ_∂P_2[i] = Taylor1(constant_term(tmp1403[i]) * constant_term(∂P_2_sin_ϕ[i]), order) + tmp1405[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) + m_c_ϕ_∂P_3[i] = Taylor1(constant_term(tmp1405[i]) * constant_term(∂P_3_sin_ϕ[i]), order) + tmp1408[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(3), order) + F_J2_ξ[i] = Taylor1(constant_term(tmp1408[i]) * constant_term(P_2_sin_ϕ[i]), order) + F_J2_ζ[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]), order) + tmp1412[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(4), order) + F_J3_ξ[i] = Taylor1(constant_term(tmp1412[i]) * constant_term(P_3_sin_ϕ[i]), order) + F_J3_ζ[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]), order) + F_J_ξ[i] = Taylor1(identity(constant_term(F_J2_ξ[i])), order) + F_J_ζ[i] = Taylor1(identity(constant_term(F_J2_ζ[i])), order) + tmp1415[i] = Taylor1(-(constant_term(X[i])), order) + ξx[i] = Taylor1(constant_term(tmp1415[i]) / constant_term(r_p1d2[i]), order) + tmp1417[i] = Taylor1(-(constant_term(Y[i])), order) + ξy[i] = Taylor1(constant_term(tmp1417[i]) / constant_term(r_p1d2[i]), order) + tmp1419[i] = Taylor1(-(constant_term(Z[i])), order) + ξz[i] = Taylor1(constant_term(tmp1419[i]) / constant_term(r_p1d2[i]), order) + ηx1[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξz[i]), order) + ηy1[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξx[i]), order) + ηz1[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξy[i]), order) + ηx2[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξy[i]), order) + ηy2[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξz[i]), order) + ηz2[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξx[i]), order) + ηx[i] = Taylor1(constant_term(ηx1[i]) - constant_term(ηx2[i]), order) + ηy[i] = Taylor1(constant_term(ηy1[i]) - constant_term(ηy2[i]), order) + ηz[i] = Taylor1(constant_term(ηz1[i]) - constant_term(ηz2[i]), order) + ζx1[i] = Taylor1(constant_term(ξy[i]) * constant_term(ηz[i]), order) + ζy1[i] = Taylor1(constant_term(ξz[i]) * constant_term(ηx[i]), order) + ζz1[i] = Taylor1(constant_term(ξx[i]) * constant_term(ηy[i]), order) + ζx2[i] = Taylor1(constant_term(ξz[i]) * constant_term(ηy[i]), order) + ζy2[i] = Taylor1(constant_term(ξx[i]) * constant_term(ηz[i]), order) + ζz2[i] = Taylor1(constant_term(ξy[i]) * constant_term(ηx[i]), order) + ζx[i] = Taylor1(constant_term(ζx1[i]) - constant_term(ζx2[i]), order) + ζy[i] = Taylor1(constant_term(ζy1[i]) - constant_term(ζy2[i]), order) + ζz[i] = Taylor1(constant_term(ζz1[i]) - constant_term(ζz2[i]), order) + F_J2_x1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξx[i]), order) + F_J2_y1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξy[i]), order) + F_J2_z1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξz[i]), order) + F_J2_x2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζx[i]), order) + F_J2_y2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζy[i]), order) + F_J2_z2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζz[i]), order) + F_J2_x[i] = Taylor1(constant_term(F_J2_x1[i]) + constant_term(F_J2_x2[i]), order) + F_J2_y[i] = Taylor1(constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]), order) + F_J2_z[i] = Taylor1(constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]), order) + end + tmp1449[i] = Taylor1(constant_term(ui[i]) ^ float(constant_term(2)), order) + tmp1451[i] = Taylor1(constant_term(vi[i]) ^ float(constant_term(2)), order) + tmp1452[i] = Taylor1(constant_term(tmp1449[i]) + constant_term(tmp1451[i]), order) + tmp1454[i] = Taylor1(constant_term(wi[i]) ^ float(constant_term(2)), order) + v2[i] = Taylor1(constant_term(tmp1452[i]) + constant_term(tmp1454[i]), order) + end + tmp1457 = Taylor1(constant_term(q[4]) ^ float(constant_term(2)), order) + tmp1459 = Taylor1(constant_term(q[5]) ^ float(constant_term(2)), order) + tmp1460 = Taylor1(constant_term(tmp1457) + constant_term(tmp1459), order) + tmp1462 = Taylor1(constant_term(q[6]) ^ float(constant_term(2)), order) + v2[N] = Taylor1(constant_term(tmp1460) + constant_term(tmp1462), order) + temp_004 = Array{Taylor1{_S}}(undef, size(newtonian1b_Potential)) + temp_004 .= Taylor1(zero(constant_term(q[1])), order) + tmp1465 = Array{Taylor1{_S}}(undef, size(μ)) + tmp1465 .= Taylor1(zero(constant_term(q[1])), order) + tmp1467 = Array{Taylor1{_S}}(undef, size(μ)) + tmp1467 .= Taylor1(zero(constant_term(q[1])), order) + tmp1469 = Array{Taylor1{_S}}(undef, size(μ)) + tmp1469 .= Taylor1(zero(constant_term(q[1])), order) + for i = 1:Nm1 + temp_004[i] = Taylor1(constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]), order) + newtonianNb_Potential[N] = Taylor1(identity(constant_term(temp_004[i])), order) + if UJ_interaction[i] + tmp1465[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_x[i]), order) + temp_accX_i[i] = Taylor1(constant_term(accX) - constant_term(tmp1465[i]), order) + accX = Taylor1(identity(constant_term(temp_accX_i[i])), order) + tmp1467[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_y[i]), order) + temp_accY_i[i] = Taylor1(constant_term(accY) - constant_term(tmp1467[i]), order) + accY = Taylor1(identity(constant_term(temp_accY_i[i])), order) + tmp1469[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_z[i]), order) + temp_accZ_i[i] = Taylor1(constant_term(accZ) - constant_term(tmp1469[i]), order) + accZ = Taylor1(identity(constant_term(temp_accZ_i[i])), order) + end + end + _4ϕj[N] = Taylor1(constant_term(4) * constant_term(newtonianNb_Potential[N]), order) + tmp1475 = Array{Taylor1{_S}}(undef, size(v2)) + tmp1475 .= Taylor1(zero(constant_term(q[1])), order) + tmp1477 = Array{Taylor1{_S}}(undef, size(vi_dot_vj)) + tmp1477 .= Taylor1(zero(constant_term(q[1])), order) + tmp1478 = Array{Taylor1{_S}}(undef, size(tmp1475)) + tmp1478 .= Taylor1(zero(constant_term(q[1])), order) + Xij_t_Ui = Array{Taylor1{_S}}(undef, size(X)) + Xij_t_Ui .= Taylor1(zero(constant_term(q[1])), order) + Yij_t_Vi = Array{Taylor1{_S}}(undef, size(Y)) + Yij_t_Vi .= Taylor1(zero(constant_term(q[1])), order) + Zij_t_Wi = Array{Taylor1{_S}}(undef, size(Z)) + Zij_t_Wi .= Taylor1(zero(constant_term(q[1])), order) + tmp1484 = Array{Taylor1{_S}}(undef, size(Xij_t_Ui)) + tmp1484 .= Taylor1(zero(constant_term(q[1])), order) + Rij_dot_Vi = Array{Taylor1{_S}}(undef, size(tmp1484)) + Rij_dot_Vi .= Taylor1(zero(constant_term(q[1])), order) + tmp1487 = Array{Taylor1{_S}}(undef, size(Rij_dot_Vi)) + tmp1487 .= Taylor1(zero(constant_term(q[1])), order) + pn1t7 = Array{Taylor1{_S}}(undef, size(tmp1487)) + pn1t7 .= Taylor1(zero(constant_term(q[1])), order) + tmp1490 = Array{Taylor1{_S}}(undef, size(pn1t7)) + tmp1490 .= Taylor1(zero(constant_term(q[1])), order) + pn1t2_7 = Array{Taylor1{_S}}(undef, size(ϕs_and_vs)) + pn1t2_7 .= Taylor1(zero(constant_term(q[1])), order) + tmp1497 = Array{Taylor1{_S}}(undef, size(pNX_t_X)) + tmp1497 .= Taylor1(zero(constant_term(q[1])), order) + tmp1498 = Array{Taylor1{_S}}(undef, size(tmp1497)) + tmp1498 .= Taylor1(zero(constant_term(q[1])), order) + tmp1499 = Array{Taylor1{_S}}(undef, size(tmp1498)) + tmp1499 .= Taylor1(zero(constant_term(q[1])), order) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 + ϕi_plus_4ϕj[i] = Taylor1(constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]), order) + tmp1475[i] = Taylor1(constant_term(2) * constant_term(v2[i]), order) + tmp1477[i] = Taylor1(constant_term(4) * constant_term(vi_dot_vj[i]), order) + tmp1478[i] = Taylor1(constant_term(tmp1475[i]) - constant_term(tmp1477[i]), order) + sj2_plus_2si2_minus_4vivj[i] = Taylor1(constant_term(tmp1478[i]) + constant_term(v2[N]), order) + ϕs_and_vs[i] = Taylor1(constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]), order) + Xij_t_Ui[i] = Taylor1(constant_term(X[i]) * constant_term(ui[i]), order) + Yij_t_Vi[i] = Taylor1(constant_term(Y[i]) * constant_term(vi[i]), order) + Zij_t_Wi[i] = Taylor1(constant_term(Z[i]) * constant_term(wi[i]), order) + tmp1484[i] = Taylor1(constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]), order) + Rij_dot_Vi[i] = Taylor1(constant_term(tmp1484[i]) + constant_term(Zij_t_Wi[i]), order) + tmp1487[i] = Taylor1(constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)), order) + pn1t7[i] = Taylor1(constant_term(tmp1487[i]) / constant_term(r_p2[i]), order) + tmp1490[i] = Taylor1(constant_term(1.5) * constant_term(pn1t7[i]), order) + pn1t2_7[i] = Taylor1(constant_term(ϕs_and_vs[i]) - constant_term(tmp1490[i]), order) + pn1t1_7[i] = Taylor1(constant_term(c_p2) + constant_term(pn1t2_7[i]), order) + pNX_t_X[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(X[i]), order) + pNY_t_Y[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(Y[i]), order) + pNZ_t_Z[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(Z[i]), order) + tmp1497[i] = Taylor1(constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]), order) + tmp1498[i] = Taylor1(constant_term(tmp1497[i]) + constant_term(pNZ_t_Z[i]), order) + tmp1499[i] = Taylor1(constant_term(0.5) * constant_term(tmp1498[i]), order) + pn1[i] = Taylor1(constant_term(pn1t1_7[i]) + constant_term(tmp1499[i]), order) + X_t_pn1[i] = Taylor1(constant_term(newton_acc_X[i]) * constant_term(pn1[i]), order) + Y_t_pn1[i] = Taylor1(constant_term(newton_acc_Y[i]) * constant_term(pn1[i]), order) + Z_t_pn1[i] = Taylor1(constant_term(newton_acc_Z[i]) * constant_term(pn1[i]), order) + pNX_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(pn3[i]), order) + pNY_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]), order) + pNZ_t_pn3[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(pn3[i]), order) + end + tmp1507 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) + tmp1507 .= Taylor1(zero(constant_term(q[1])), order) + termpnx = Array{Taylor1{_S}}(undef, size(X_t_pn1)) + termpnx .= Taylor1(zero(constant_term(q[1])), order) + sumpnx = Array{Taylor1{_S}}(undef, size(termpnx)) + sumpnx .= Taylor1(zero(constant_term(q[1])), order) + tmp1510 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) + tmp1510 .= Taylor1(zero(constant_term(q[1])), order) + termpny = Array{Taylor1{_S}}(undef, size(Y_t_pn1)) + termpny .= Taylor1(zero(constant_term(q[1])), order) + sumpny = Array{Taylor1{_S}}(undef, size(termpny)) + sumpny .= Taylor1(zero(constant_term(q[1])), order) + tmp1513 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) + tmp1513 .= Taylor1(zero(constant_term(q[1])), order) + termpnz = Array{Taylor1{_S}}(undef, size(Z_t_pn1)) + termpnz .= Taylor1(zero(constant_term(q[1])), order) + sumpnz = Array{Taylor1{_S}}(undef, size(termpnz)) + sumpnz .= Taylor1(zero(constant_term(q[1])), order) + for i = 1:10 + tmp1507[i] = Taylor1(constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]), order) + termpnx[i] = Taylor1(constant_term(X_t_pn1[i]) + constant_term(tmp1507[i]), order) + sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) + pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) + tmp1510[i] = Taylor1(constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]), order) + termpny[i] = Taylor1(constant_term(Y_t_pn1[i]) + constant_term(tmp1510[i]), order) + sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) + pntempY = Taylor1(identity(constant_term(sumpny[i])), order) + tmp1513[i] = Taylor1(constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]), order) + termpnz[i] = Taylor1(constant_term(Z_t_pn1[i]) + constant_term(tmp1513[i]), order) + sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) + pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) + end + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 + X_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_X[i]), order) + Y_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Y[i]), order) + Z_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Z[i]), order) + end + for i = 11:Nm1 + termpnx[i] = Taylor1(identity(constant_term(X_t_pn1[i])), order) + sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) + pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) + termpny[i] = Taylor1(identity(constant_term(Y_t_pn1[i])), order) + sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) + pntempY = Taylor1(identity(constant_term(sumpny[i])), order) + termpnz[i] = Taylor1(identity(constant_term(Z_t_pn1[i])), order) + sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) + pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) + end + postNewtonX = Taylor1(constant_term(pntempX) * constant_term(c_m2), order) + postNewtonY = Taylor1(constant_term(pntempY) * constant_term(c_m2), order) + postNewtonZ = Taylor1(constant_term(pntempZ) * constant_term(c_m2), order) + dq[4] = Taylor1(constant_term(postNewtonX) + constant_term(accX), order) + dq[5] = Taylor1(constant_term(postNewtonY) + constant_term(accY), order) + dq[6] = Taylor1(constant_term(postNewtonZ) + constant_term(accZ), order) + return TaylorIntegration.RetAlloc{Taylor1{_S}}([tmp1457, tmp1459, tmp1460, tmp1462, pntempX, pntempY, pntempZ, accX, accY, accZ, postNewtonX, postNewtonY, postNewtonZ], [X, Y, Z, r_p2, r_p1d2, r_p3d2, r_p7d2, newtonianCoeff, ui, vi, wi, U, V, W, _4U_m_3X, _4V_m_3Y, _4W_m_3Z, UU, VV, WW, newtonian1b_Potential, newtonianNb_Potential, newton_acc_X, newton_acc_Y, newton_acc_Z, v2, vi_dot_vj, pn2, U_t_pn2, V_t_pn2, W_t_pn2, pn3, pNX_t_pn3, pNY_t_pn3, pNZ_t_pn3, _4ϕj, ϕi_plus_4ϕj, sj2_plus_2si2_minus_4vivj, ϕs_and_vs, pn1t1_7, pNX_t_X, pNY_t_Y, pNZ_t_Z, pn1, X_t_pn1, Y_t_pn1, Z_t_pn1, t31, t32, t33, r_sin_ϕ, sin_ϕ, ϕ, cos_ϕ, sin2_ϕ, sin3_ϕ, F_J2_x, F_J2_y, F_J2_z, F_J2_x1, F_J2_y1, F_J2_z1, F_J2_x2, F_J2_y2, F_J2_z2, temp_accX_i, temp_accY_i, temp_accZ_i, P_2_sin_ϕ, ∂P_2_sin_ϕ, P_3_sin_ϕ, ∂P_3_sin_ϕ, m_c_ϕ_∂P_2, m_c_ϕ_∂P_3, Λ2j_div_r4, Λ3j_div_r5, F_J_ξ, F_J_ζ, F_J2_ξ, F_J2_ζ, F_J3_ξ, F_J3_ζ, ξx, ξy, ξz, ηx, ηy, ηz, ηx1, ηy1, ηz1, ηx2, ηy2, ηz2, ζx, ζy, ζz, ζx1, ζy1, ζz1, ζx2, ζy2, ζz2, tmp1317, tmp1319, tmp1322, tmp1324, tmp1327, tmp1329, pn2x, pn2y, pn2z, tmp1337, tmp1340, tmp1342, tmp1343, tmp1345, tmp1353, tmp1354, tmp1365, tmp1367, tmp1369, tmp1371, tmp1528, tmp1529, tmp1381, tmp1387, tmp1389, tmp1393, tmp1396, tmp1397, tmp1400, tmp1401, tmp1403, tmp1405, tmp1408, tmp1412, tmp1415, tmp1417, tmp1419, tmp1449, tmp1451, tmp1452, tmp1454, temp_004, tmp1465, tmp1467, tmp1469, tmp1475, tmp1477, tmp1478, Xij_t_Ui, Yij_t_Vi, Zij_t_Wi, tmp1484, Rij_dot_Vi, tmp1487, pn1t7, tmp1490, pn1t2_7, tmp1497, tmp1498, tmp1499, tmp1507, termpnx, sumpnx, tmp1510, termpny, sumpny, tmp1513, termpnz, sumpnz], [Array{Taylor1{_S}, 2}(undef, 0, 0)], [Array{Taylor1{_S}, 3}(undef, 0, 0, 0)], [Array{Taylor1{_S}, 4}(undef, 0, 0, 0, 0)]) +end + +# TaylorIntegration.jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_eph_threads! +function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params, __ralloc::TaylorIntegration.RetAlloc{Taylor1{_S}}) where {_T <: Real, _S <: Number, _N} + order = t.order + tmp1457 = __ralloc.v0[1] + tmp1459 = __ralloc.v0[2] + tmp1460 = __ralloc.v0[3] + tmp1462 = __ralloc.v0[4] + pntempX = __ralloc.v0[5] + pntempY = __ralloc.v0[6] + pntempZ = __ralloc.v0[7] + accX = __ralloc.v0[8] + accY = __ralloc.v0[9] + accZ = __ralloc.v0[10] + postNewtonX = __ralloc.v0[11] + postNewtonY = __ralloc.v0[12] + postNewtonZ = __ralloc.v0[13] + X = __ralloc.v1[1] + Y = __ralloc.v1[2] + Z = __ralloc.v1[3] + r_p2 = __ralloc.v1[4] + r_p1d2 = __ralloc.v1[5] + r_p3d2 = __ralloc.v1[6] + r_p7d2 = __ralloc.v1[7] + newtonianCoeff = __ralloc.v1[8] + ui = __ralloc.v1[9] + vi = __ralloc.v1[10] + wi = __ralloc.v1[11] + U = __ralloc.v1[12] + V = __ralloc.v1[13] + W = __ralloc.v1[14] + _4U_m_3X = __ralloc.v1[15] + _4V_m_3Y = __ralloc.v1[16] + _4W_m_3Z = __ralloc.v1[17] + UU = __ralloc.v1[18] + VV = __ralloc.v1[19] + WW = __ralloc.v1[20] + newtonian1b_Potential = __ralloc.v1[21] + newtonianNb_Potential = __ralloc.v1[22] + newton_acc_X = __ralloc.v1[23] + newton_acc_Y = __ralloc.v1[24] + newton_acc_Z = __ralloc.v1[25] + v2 = __ralloc.v1[26] + vi_dot_vj = __ralloc.v1[27] + pn2 = __ralloc.v1[28] + U_t_pn2 = __ralloc.v1[29] + V_t_pn2 = __ralloc.v1[30] + W_t_pn2 = __ralloc.v1[31] + pn3 = __ralloc.v1[32] + pNX_t_pn3 = __ralloc.v1[33] + pNY_t_pn3 = __ralloc.v1[34] + pNZ_t_pn3 = __ralloc.v1[35] + _4ϕj = __ralloc.v1[36] + ϕi_plus_4ϕj = __ralloc.v1[37] + sj2_plus_2si2_minus_4vivj = __ralloc.v1[38] + ϕs_and_vs = __ralloc.v1[39] + pn1t1_7 = __ralloc.v1[40] + pNX_t_X = __ralloc.v1[41] + pNY_t_Y = __ralloc.v1[42] + pNZ_t_Z = __ralloc.v1[43] + pn1 = __ralloc.v1[44] + X_t_pn1 = __ralloc.v1[45] + Y_t_pn1 = __ralloc.v1[46] + Z_t_pn1 = __ralloc.v1[47] + t31 = __ralloc.v1[48] + t32 = __ralloc.v1[49] + t33 = __ralloc.v1[50] + r_sin_ϕ = __ralloc.v1[51] + sin_ϕ = __ralloc.v1[52] + ϕ = __ralloc.v1[53] + cos_ϕ = __ralloc.v1[54] + sin2_ϕ = __ralloc.v1[55] + sin3_ϕ = __ralloc.v1[56] + F_J2_x = __ralloc.v1[57] + F_J2_y = __ralloc.v1[58] + F_J2_z = __ralloc.v1[59] + F_J2_x1 = __ralloc.v1[60] + F_J2_y1 = __ralloc.v1[61] + F_J2_z1 = __ralloc.v1[62] + F_J2_x2 = __ralloc.v1[63] + F_J2_y2 = __ralloc.v1[64] + F_J2_z2 = __ralloc.v1[65] + temp_accX_i = __ralloc.v1[66] + temp_accY_i = __ralloc.v1[67] + temp_accZ_i = __ralloc.v1[68] + P_2_sin_ϕ = __ralloc.v1[69] + ∂P_2_sin_ϕ = __ralloc.v1[70] + P_3_sin_ϕ = __ralloc.v1[71] + ∂P_3_sin_ϕ = __ralloc.v1[72] + m_c_ϕ_∂P_2 = __ralloc.v1[73] + m_c_ϕ_∂P_3 = __ralloc.v1[74] + Λ2j_div_r4 = __ralloc.v1[75] + Λ3j_div_r5 = __ralloc.v1[76] + F_J_ξ = __ralloc.v1[77] + F_J_ζ = __ralloc.v1[78] + F_J2_ξ = __ralloc.v1[79] + F_J2_ζ = __ralloc.v1[80] + F_J3_ξ = __ralloc.v1[81] + F_J3_ζ = __ralloc.v1[82] + ξx = __ralloc.v1[83] + ξy = __ralloc.v1[84] + ξz = __ralloc.v1[85] + ηx = __ralloc.v1[86] + ηy = __ralloc.v1[87] + ηz = __ralloc.v1[88] + ηx1 = __ralloc.v1[89] + ηy1 = __ralloc.v1[90] + ηz1 = __ralloc.v1[91] + ηx2 = __ralloc.v1[92] + ηy2 = __ralloc.v1[93] + ηz2 = __ralloc.v1[94] + ζx = __ralloc.v1[95] + ζy = __ralloc.v1[96] + ζz = __ralloc.v1[97] + ζx1 = __ralloc.v1[98] + ζy1 = __ralloc.v1[99] + ζz1 = __ralloc.v1[100] + ζx2 = __ralloc.v1[101] + ζy2 = __ralloc.v1[102] + ζz2 = __ralloc.v1[103] + tmp1317 = __ralloc.v1[104] + tmp1319 = __ralloc.v1[105] + tmp1322 = __ralloc.v1[106] + tmp1324 = __ralloc.v1[107] + tmp1327 = __ralloc.v1[108] + tmp1329 = __ralloc.v1[109] + pn2x = __ralloc.v1[110] + pn2y = __ralloc.v1[111] + pn2z = __ralloc.v1[112] + tmp1337 = __ralloc.v1[113] + tmp1340 = __ralloc.v1[114] + tmp1342 = __ralloc.v1[115] + tmp1343 = __ralloc.v1[116] + tmp1345 = __ralloc.v1[117] + tmp1353 = __ralloc.v1[118] + tmp1354 = __ralloc.v1[119] + tmp1365 = __ralloc.v1[120] + tmp1367 = __ralloc.v1[121] + tmp1369 = __ralloc.v1[122] + tmp1371 = __ralloc.v1[123] + tmp1528 = __ralloc.v1[124] + tmp1529 = __ralloc.v1[125] + tmp1381 = __ralloc.v1[126] + tmp1387 = __ralloc.v1[127] + tmp1389 = __ralloc.v1[128] + tmp1393 = __ralloc.v1[129] + tmp1396 = __ralloc.v1[130] + tmp1397 = __ralloc.v1[131] + tmp1400 = __ralloc.v1[132] + tmp1401 = __ralloc.v1[133] + tmp1403 = __ralloc.v1[134] + tmp1405 = __ralloc.v1[135] + tmp1408 = __ralloc.v1[136] + tmp1412 = __ralloc.v1[137] + tmp1415 = __ralloc.v1[138] + tmp1417 = __ralloc.v1[139] + tmp1419 = __ralloc.v1[140] + tmp1449 = __ralloc.v1[141] + tmp1451 = __ralloc.v1[142] + tmp1452 = __ralloc.v1[143] + tmp1454 = __ralloc.v1[144] + temp_004 = __ralloc.v1[145] + tmp1465 = __ralloc.v1[146] + tmp1467 = __ralloc.v1[147] + tmp1469 = __ralloc.v1[148] + tmp1475 = __ralloc.v1[149] + tmp1477 = __ralloc.v1[150] + tmp1478 = __ralloc.v1[151] + Xij_t_Ui = __ralloc.v1[152] + Yij_t_Vi = __ralloc.v1[153] + Zij_t_Wi = __ralloc.v1[154] + tmp1484 = __ralloc.v1[155] + Rij_dot_Vi = __ralloc.v1[156] + tmp1487 = __ralloc.v1[157] + pn1t7 = __ralloc.v1[158] + tmp1490 = __ralloc.v1[159] + pn1t2_7 = __ralloc.v1[160] + tmp1497 = __ralloc.v1[161] + tmp1498 = __ralloc.v1[162] + tmp1499 = __ralloc.v1[163] + tmp1507 = __ralloc.v1[164] + termpnx = __ralloc.v1[165] + sumpnx = __ralloc.v1[166] + tmp1510 = __ralloc.v1[167] + termpny = __ralloc.v1[168] + sumpny = __ralloc.v1[169] + tmp1513 = __ralloc.v1[170] + termpnz = __ralloc.v1[171] + sumpnz = __ralloc.v1[172] + local jd0 = params[4] + local dsj2k = t + (jd0 - JD_J2000) + local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) + local acceph_t = evaleph(params[2], dsj2k, q[1]) + local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) + local S = eltype(q) + local UJ_interaction = params[5] + local N = params[6] + local Nm1 = N - 1 + local μ = params[7] + local zero_q_1 = auxzero(q[1]) + pntempX.coeffs[1] = identity(constant_term(zero_q_1)) + pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) + pntempY.coeffs[1] = identity(constant_term(zero_q_1)) + pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) + pntempZ.coeffs[1] = identity(constant_term(zero_q_1)) + pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) + accX.coeffs[1] = identity(constant_term(zero_q_1)) + accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) + accY.coeffs[1] = identity(constant_term(zero_q_1)) + accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) + accZ.coeffs[1] = identity(constant_term(zero_q_1)) + accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) + local M_ = Array{S}(undef, 3, 3, N) + local M_ .= zero_q_1 + local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 + (dq[1]).coeffs[1] = identity(constant_term(q[4])) + (dq[1]).coeffs[2:order + 1] .= zero((dq[1]).coeffs[1]) + (dq[2]).coeffs[1] = identity(constant_term(q[5])) + (dq[2]).coeffs[2:order + 1] .= zero((dq[2]).coeffs[1]) + (dq[3]).coeffs[1] = identity(constant_term(q[6])) + (dq[3]).coeffs[2:order + 1] .= zero((dq[3]).coeffs[1]) + (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(zero_q_1)) + (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 + (ui[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])) + (ui[i]).coeffs[2:order + 1] .= zero((ui[i]).coeffs[1]) + (vi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])) + (vi[i]).coeffs[2:order + 1] .= zero((vi[i]).coeffs[1]) + (wi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])) + (wi[i]).coeffs[2:order + 1] .= zero((wi[i]).coeffs[1]) + (X[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 2]) - constant_term(q[1]) + (X[i]).coeffs[2:order + 1] .= zero((X[i]).coeffs[1]) + (Y[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 1]) - constant_term(q[2]) + (Y[i]).coeffs[2:order + 1] .= zero((Y[i]).coeffs[1]) + (Z[i]).coeffs[1] = constant_term(ss16asteph_t[3i]) - constant_term(q[3]) + (Z[i]).coeffs[2:order + 1] .= zero((Z[i]).coeffs[1]) + (U[i]).coeffs[1] = constant_term(ui[i]) - constant_term(dq[1]) + (U[i]).coeffs[2:order + 1] .= zero((U[i]).coeffs[1]) + (V[i]).coeffs[1] = constant_term(vi[i]) - constant_term(dq[2]) + (V[i]).coeffs[2:order + 1] .= zero((V[i]).coeffs[1]) + (W[i]).coeffs[1] = constant_term(wi[i]) - constant_term(dq[3]) + (W[i]).coeffs[2:order + 1] .= zero((W[i]).coeffs[1]) + (tmp1317[1]).coeffs[1] = constant_term(4) * constant_term(dq[1]) + (tmp1317[1]).coeffs[2:order + 1] .= zero((tmp1317[1]).coeffs[1]) + (tmp1319[i]).coeffs[1] = constant_term(3) * constant_term(ui[i]) + (tmp1319[i]).coeffs[2:order + 1] .= zero((tmp1319[i]).coeffs[1]) + (_4U_m_3X[i]).coeffs[1] = constant_term(tmp1317[1]) - constant_term(tmp1319[i]) + (_4U_m_3X[i]).coeffs[2:order + 1] .= zero((_4U_m_3X[i]).coeffs[1]) + (tmp1322[2]).coeffs[1] = constant_term(4) * constant_term(dq[2]) + (tmp1322[2]).coeffs[2:order + 1] .= zero((tmp1322[2]).coeffs[1]) + (tmp1324[i]).coeffs[1] = constant_term(3) * constant_term(vi[i]) + (tmp1324[i]).coeffs[2:order + 1] .= zero((tmp1324[i]).coeffs[1]) + (_4V_m_3Y[i]).coeffs[1] = constant_term(tmp1322[2]) - constant_term(tmp1324[i]) + (_4V_m_3Y[i]).coeffs[2:order + 1] .= zero((_4V_m_3Y[i]).coeffs[1]) + (tmp1327[3]).coeffs[1] = constant_term(4) * constant_term(dq[3]) + (tmp1327[3]).coeffs[2:order + 1] .= zero((tmp1327[3]).coeffs[1]) + (tmp1329[i]).coeffs[1] = constant_term(3) * constant_term(wi[i]) + (tmp1329[i]).coeffs[2:order + 1] .= zero((tmp1329[i]).coeffs[1]) + (_4W_m_3Z[i]).coeffs[1] = constant_term(tmp1327[3]) - constant_term(tmp1329[i]) + (_4W_m_3Z[i]).coeffs[2:order + 1] .= zero((_4W_m_3Z[i]).coeffs[1]) + (pn2x[i]).coeffs[1] = constant_term(X[i]) * constant_term(_4U_m_3X[i]) + (pn2x[i]).coeffs[2:order + 1] .= zero((pn2x[i]).coeffs[1]) + (pn2y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(_4V_m_3Y[i]) + (pn2y[i]).coeffs[2:order + 1] .= zero((pn2y[i]).coeffs[1]) + (pn2z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(_4W_m_3Z[i]) + (pn2z[i]).coeffs[2:order + 1] .= zero((pn2z[i]).coeffs[1]) + (UU[i]).coeffs[1] = constant_term(ui[i]) * constant_term(dq[1]) + (UU[i]).coeffs[2:order + 1] .= zero((UU[i]).coeffs[1]) + (VV[i]).coeffs[1] = constant_term(vi[i]) * constant_term(dq[2]) + (VV[i]).coeffs[2:order + 1] .= zero((VV[i]).coeffs[1]) + (WW[i]).coeffs[1] = constant_term(wi[i]) * constant_term(dq[3]) + (WW[i]).coeffs[2:order + 1] .= zero((WW[i]).coeffs[1]) + (tmp1337[i]).coeffs[1] = constant_term(UU[i]) + constant_term(VV[i]) + (tmp1337[i]).coeffs[2:order + 1] .= zero((tmp1337[i]).coeffs[1]) + (vi_dot_vj[i]).coeffs[1] = constant_term(tmp1337[i]) + constant_term(WW[i]) + (vi_dot_vj[i]).coeffs[2:order + 1] .= zero((vi_dot_vj[i]).coeffs[1]) + (tmp1340[i]).coeffs[1] = constant_term(X[i]) ^ float(constant_term(2)) + (tmp1340[i]).coeffs[2:order + 1] .= zero((tmp1340[i]).coeffs[1]) + (tmp1342[i]).coeffs[1] = constant_term(Y[i]) ^ float(constant_term(2)) + (tmp1342[i]).coeffs[2:order + 1] .= zero((tmp1342[i]).coeffs[1]) + (tmp1343[i]).coeffs[1] = constant_term(tmp1340[i]) + constant_term(tmp1342[i]) + (tmp1343[i]).coeffs[2:order + 1] .= zero((tmp1343[i]).coeffs[1]) + (tmp1345[i]).coeffs[1] = constant_term(Z[i]) ^ float(constant_term(2)) + (tmp1345[i]).coeffs[2:order + 1] .= zero((tmp1345[i]).coeffs[1]) + (r_p2[i]).coeffs[1] = constant_term(tmp1343[i]) + constant_term(tmp1345[i]) + (r_p2[i]).coeffs[2:order + 1] .= zero((r_p2[i]).coeffs[1]) + (r_p1d2[i]).coeffs[1] = sqrt(constant_term(r_p2[i])) + (r_p1d2[i]).coeffs[2:order + 1] .= zero((r_p1d2[i]).coeffs[1]) + (r_p3d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(1.5)) + (r_p3d2[i]).coeffs[2:order + 1] .= zero((r_p3d2[i]).coeffs[1]) + (r_p7d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(3.5)) + (r_p7d2[i]).coeffs[2:order + 1] .= zero((r_p7d2[i]).coeffs[1]) + (newtonianCoeff[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p3d2[i]) + (newtonianCoeff[i]).coeffs[2:order + 1] .= zero((newtonianCoeff[i]).coeffs[1]) + (tmp1353[i]).coeffs[1] = constant_term(pn2x[i]) + constant_term(pn2y[i]) + (tmp1353[i]).coeffs[2:order + 1] .= zero((tmp1353[i]).coeffs[1]) + (tmp1354[i]).coeffs[1] = constant_term(tmp1353[i]) + constant_term(pn2z[i]) + (tmp1354[i]).coeffs[2:order + 1] .= zero((tmp1354[i]).coeffs[1]) + (pn2[i]).coeffs[1] = constant_term(newtonianCoeff[i]) * constant_term(tmp1354[i]) + (pn2[i]).coeffs[2:order + 1] .= zero((pn2[i]).coeffs[1]) + (newton_acc_X[i]).coeffs[1] = constant_term(X[i]) * constant_term(newtonianCoeff[i]) + (newton_acc_X[i]).coeffs[2:order + 1] .= zero((newton_acc_X[i]).coeffs[1]) + (newton_acc_Y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(newtonianCoeff[i]) + (newton_acc_Y[i]).coeffs[2:order + 1] .= zero((newton_acc_Y[i]).coeffs[1]) + (newton_acc_Z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(newtonianCoeff[i]) + (newton_acc_Z[i]).coeffs[2:order + 1] .= zero((newton_acc_Z[i]).coeffs[1]) + (newtonian1b_Potential[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p1d2[i]) + (newtonian1b_Potential[i]).coeffs[2:order + 1] .= zero((newtonian1b_Potential[i]).coeffs[1]) + (pn3[i]).coeffs[1] = constant_term(3.5) * constant_term(newtonian1b_Potential[i]) + (pn3[i]).coeffs[2:order + 1] .= zero((pn3[i]).coeffs[1]) + (U_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(U[i]) + (U_t_pn2[i]).coeffs[2:order + 1] .= zero((U_t_pn2[i]).coeffs[1]) + (V_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(V[i]) + (V_t_pn2[i]).coeffs[2:order + 1] .= zero((V_t_pn2[i]).coeffs[1]) + (W_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(W[i]) + (W_t_pn2[i]).coeffs[2:order + 1] .= zero((W_t_pn2[i]).coeffs[1]) + if UJ_interaction[i] + (tmp1365[i]).coeffs[1] = -(constant_term(X[i])) + (tmp1365[i]).coeffs[2:order + 1] .= zero((tmp1365[i]).coeffs[1]) + (t31[i]).coeffs[1] = constant_term(tmp1365[i]) * constant_term(M_[1, 3, i]) + (t31[i]).coeffs[2:order + 1] .= zero((t31[i]).coeffs[1]) + (tmp1367[i]).coeffs[1] = -(constant_term(Y[i])) + (tmp1367[i]).coeffs[2:order + 1] .= zero((tmp1367[i]).coeffs[1]) + (t32[i]).coeffs[1] = constant_term(tmp1367[i]) * constant_term(M_[2, 3, i]) + (t32[i]).coeffs[2:order + 1] .= zero((t32[i]).coeffs[1]) + (tmp1369[i]).coeffs[1] = -(constant_term(Z[i])) + (tmp1369[i]).coeffs[2:order + 1] .= zero((tmp1369[i]).coeffs[1]) + (t33[i]).coeffs[1] = constant_term(tmp1369[i]) * constant_term(M_[3, 3, i]) + (t33[i]).coeffs[2:order + 1] .= zero((t33[i]).coeffs[1]) + (tmp1371[i]).coeffs[1] = constant_term(t31[i]) + constant_term(t32[i]) + (tmp1371[i]).coeffs[2:order + 1] .= zero((tmp1371[i]).coeffs[1]) + (r_sin_ϕ[i]).coeffs[1] = constant_term(tmp1371[i]) + constant_term(t33[i]) + (r_sin_ϕ[i]).coeffs[2:order + 1] .= zero((r_sin_ϕ[i]).coeffs[1]) + (sin_ϕ[i]).coeffs[1] = constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]) + (sin_ϕ[i]).coeffs[2:order + 1] .= zero((sin_ϕ[i]).coeffs[1]) + (ϕ[i]).coeffs[1] = asin(constant_term(sin_ϕ[i])) + (ϕ[i]).coeffs[2:order + 1] .= zero((ϕ[i]).coeffs[1]) + (tmp1528[i]).coeffs[1] = sqrt(1 - constant_term(sin_ϕ[i]) ^ 2) + (tmp1528[i]).coeffs[2:order + 1] .= zero((tmp1528[i]).coeffs[1]) + (cos_ϕ[i]).coeffs[1] = cos(constant_term(ϕ[i])) + (cos_ϕ[i]).coeffs[2:order + 1] .= zero((cos_ϕ[i]).coeffs[1]) + (tmp1529[i]).coeffs[1] = sin(constant_term(ϕ[i])) + (tmp1529[i]).coeffs[2:order + 1] .= zero((tmp1529[i]).coeffs[1]) + (sin2_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(2)) + (sin2_ϕ[i]).coeffs[2:order + 1] .= zero((sin2_ϕ[i]).coeffs[1]) + (sin3_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(3)) + (sin3_ϕ[i]).coeffs[2:order + 1] .= zero((sin3_ϕ[i]).coeffs[1]) + (tmp1381[i]).coeffs[1] = constant_term(1.5) * constant_term(sin2_ϕ[i]) + (tmp1381[i]).coeffs[2:order + 1] .= zero((tmp1381[i]).coeffs[1]) + (P_2_sin_ϕ[i]).coeffs[1] = constant_term(tmp1381[i]) - constant_term(0.5) + (P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_2_sin_ϕ[i]).coeffs[1]) + (∂P_2_sin_ϕ[i]).coeffs[1] = constant_term(3) * constant_term(sin_ϕ[i]) + (∂P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_2_sin_ϕ[i]).coeffs[1]) + (tmp1387[i]).coeffs[1] = constant_term(-1.5) * constant_term(sin_ϕ[i]) + (tmp1387[i]).coeffs[2:order + 1] .= zero((tmp1387[i]).coeffs[1]) + (tmp1389[i]).coeffs[1] = constant_term(2.5) * constant_term(sin3_ϕ[i]) + (tmp1389[i]).coeffs[2:order + 1] .= zero((tmp1389[i]).coeffs[1]) + (P_3_sin_ϕ[i]).coeffs[1] = constant_term(tmp1387[i]) + constant_term(tmp1389[i]) + (P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_3_sin_ϕ[i]).coeffs[1]) + (tmp1393[i]).coeffs[1] = constant_term(7.5) * constant_term(sin2_ϕ[i]) + (tmp1393[i]).coeffs[2:order + 1] .= zero((tmp1393[i]).coeffs[1]) + (∂P_3_sin_ϕ[i]).coeffs[1] = constant_term(-1.5) + constant_term(tmp1393[i]) + (∂P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_3_sin_ϕ[i]).coeffs[1]) + (tmp1396[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(2)) + (tmp1396[i]).coeffs[2:order + 1] .= zero((tmp1396[i]).coeffs[1]) + (tmp1397[i]).coeffs[1] = constant_term(Λ2[i]) / constant_term(tmp1396[i]) + (tmp1397[i]).coeffs[2:order + 1] .= zero((tmp1397[i]).coeffs[1]) + (Λ2j_div_r4[i]).coeffs[1] = -(constant_term(tmp1397[i])) + (Λ2j_div_r4[i]).coeffs[2:order + 1] .= zero((Λ2j_div_r4[i]).coeffs[1]) + (tmp1400[i]).coeffs[1] = constant_term(r_p1d2[i]) ^ float(constant_term(5)) + (tmp1400[i]).coeffs[2:order + 1] .= zero((tmp1400[i]).coeffs[1]) + (tmp1401[i]).coeffs[1] = constant_term(Λ3[i]) / constant_term(tmp1400[i]) + (tmp1401[i]).coeffs[2:order + 1] .= zero((tmp1401[i]).coeffs[1]) + (Λ3j_div_r5[i]).coeffs[1] = -(constant_term(tmp1401[i])) + (Λ3j_div_r5[i]).coeffs[2:order + 1] .= zero((Λ3j_div_r5[i]).coeffs[1]) + (tmp1403[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) + (tmp1403[i]).coeffs[2:order + 1] .= zero((tmp1403[i]).coeffs[1]) + (m_c_ϕ_∂P_2[i]).coeffs[1] = constant_term(tmp1403[i]) * constant_term(∂P_2_sin_ϕ[i]) + (m_c_ϕ_∂P_2[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_2[i]).coeffs[1]) + (tmp1405[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) + (tmp1405[i]).coeffs[2:order + 1] .= zero((tmp1405[i]).coeffs[1]) + (m_c_ϕ_∂P_3[i]).coeffs[1] = constant_term(tmp1405[i]) * constant_term(∂P_3_sin_ϕ[i]) + (m_c_ϕ_∂P_3[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_3[i]).coeffs[1]) + (tmp1408[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(3) + (tmp1408[i]).coeffs[2:order + 1] .= zero((tmp1408[i]).coeffs[1]) + (F_J2_ξ[i]).coeffs[1] = constant_term(tmp1408[i]) * constant_term(P_2_sin_ϕ[i]) + (F_J2_ξ[i]).coeffs[2:order + 1] .= zero((F_J2_ξ[i]).coeffs[1]) + (F_J2_ζ[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]) + (F_J2_ζ[i]).coeffs[2:order + 1] .= zero((F_J2_ζ[i]).coeffs[1]) + (tmp1412[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(4) + (tmp1412[i]).coeffs[2:order + 1] .= zero((tmp1412[i]).coeffs[1]) + (F_J3_ξ[i]).coeffs[1] = constant_term(tmp1412[i]) * constant_term(P_3_sin_ϕ[i]) + (F_J3_ξ[i]).coeffs[2:order + 1] .= zero((F_J3_ξ[i]).coeffs[1]) + (F_J3_ζ[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]) + (F_J3_ζ[i]).coeffs[2:order + 1] .= zero((F_J3_ζ[i]).coeffs[1]) + (F_J_ξ[i]).coeffs[1] = identity(constant_term(F_J2_ξ[i])) + (F_J_ξ[i]).coeffs[2:order + 1] .= zero((F_J_ξ[i]).coeffs[1]) + (F_J_ζ[i]).coeffs[1] = identity(constant_term(F_J2_ζ[i])) + (F_J_ζ[i]).coeffs[2:order + 1] .= zero((F_J_ζ[i]).coeffs[1]) + (tmp1415[i]).coeffs[1] = -(constant_term(X[i])) + (tmp1415[i]).coeffs[2:order + 1] .= zero((tmp1415[i]).coeffs[1]) + (ξx[i]).coeffs[1] = constant_term(tmp1415[i]) / constant_term(r_p1d2[i]) + (ξx[i]).coeffs[2:order + 1] .= zero((ξx[i]).coeffs[1]) + (tmp1417[i]).coeffs[1] = -(constant_term(Y[i])) + (tmp1417[i]).coeffs[2:order + 1] .= zero((tmp1417[i]).coeffs[1]) + (ξy[i]).coeffs[1] = constant_term(tmp1417[i]) / constant_term(r_p1d2[i]) + (ξy[i]).coeffs[2:order + 1] .= zero((ξy[i]).coeffs[1]) + (tmp1419[i]).coeffs[1] = -(constant_term(Z[i])) + (tmp1419[i]).coeffs[2:order + 1] .= zero((tmp1419[i]).coeffs[1]) + (ξz[i]).coeffs[1] = constant_term(tmp1419[i]) / constant_term(r_p1d2[i]) + (ξz[i]).coeffs[2:order + 1] .= zero((ξz[i]).coeffs[1]) + (ηx1[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξz[i]) + (ηx1[i]).coeffs[2:order + 1] .= zero((ηx1[i]).coeffs[1]) + (ηy1[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξx[i]) + (ηy1[i]).coeffs[2:order + 1] .= zero((ηy1[i]).coeffs[1]) + (ηz1[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξy[i]) + (ηz1[i]).coeffs[2:order + 1] .= zero((ηz1[i]).coeffs[1]) + (ηx2[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξy[i]) + (ηx2[i]).coeffs[2:order + 1] .= zero((ηx2[i]).coeffs[1]) + (ηy2[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξz[i]) + (ηy2[i]).coeffs[2:order + 1] .= zero((ηy2[i]).coeffs[1]) + (ηz2[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξx[i]) + (ηz2[i]).coeffs[2:order + 1] .= zero((ηz2[i]).coeffs[1]) + (ηx[i]).coeffs[1] = constant_term(ηx1[i]) - constant_term(ηx2[i]) + (ηx[i]).coeffs[2:order + 1] .= zero((ηx[i]).coeffs[1]) + (ηy[i]).coeffs[1] = constant_term(ηy1[i]) - constant_term(ηy2[i]) + (ηy[i]).coeffs[2:order + 1] .= zero((ηy[i]).coeffs[1]) + (ηz[i]).coeffs[1] = constant_term(ηz1[i]) - constant_term(ηz2[i]) + (ηz[i]).coeffs[2:order + 1] .= zero((ηz[i]).coeffs[1]) + (ζx1[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηz[i]) + (ζx1[i]).coeffs[2:order + 1] .= zero((ζx1[i]).coeffs[1]) + (ζy1[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηx[i]) + (ζy1[i]).coeffs[2:order + 1] .= zero((ζy1[i]).coeffs[1]) + (ζz1[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηy[i]) + (ζz1[i]).coeffs[2:order + 1] .= zero((ζz1[i]).coeffs[1]) + (ζx2[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηy[i]) + (ζx2[i]).coeffs[2:order + 1] .= zero((ζx2[i]).coeffs[1]) + (ζy2[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηz[i]) + (ζy2[i]).coeffs[2:order + 1] .= zero((ζy2[i]).coeffs[1]) + (ζz2[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηx[i]) + (ζz2[i]).coeffs[2:order + 1] .= zero((ζz2[i]).coeffs[1]) + (ζx[i]).coeffs[1] = constant_term(ζx1[i]) - constant_term(ζx2[i]) + (ζx[i]).coeffs[2:order + 1] .= zero((ζx[i]).coeffs[1]) + (ζy[i]).coeffs[1] = constant_term(ζy1[i]) - constant_term(ζy2[i]) + (ζy[i]).coeffs[2:order + 1] .= zero((ζy[i]).coeffs[1]) + (ζz[i]).coeffs[1] = constant_term(ζz1[i]) - constant_term(ζz2[i]) + (ζz[i]).coeffs[2:order + 1] .= zero((ζz[i]).coeffs[1]) + (F_J2_x1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξx[i]) + (F_J2_x1[i]).coeffs[2:order + 1] .= zero((F_J2_x1[i]).coeffs[1]) + (F_J2_y1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξy[i]) + (F_J2_y1[i]).coeffs[2:order + 1] .= zero((F_J2_y1[i]).coeffs[1]) + (F_J2_z1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξz[i]) + (F_J2_z1[i]).coeffs[2:order + 1] .= zero((F_J2_z1[i]).coeffs[1]) + (F_J2_x2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζx[i]) + (F_J2_x2[i]).coeffs[2:order + 1] .= zero((F_J2_x2[i]).coeffs[1]) + (F_J2_y2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζy[i]) + (F_J2_y2[i]).coeffs[2:order + 1] .= zero((F_J2_y2[i]).coeffs[1]) + (F_J2_z2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζz[i]) + (F_J2_z2[i]).coeffs[2:order + 1] .= zero((F_J2_z2[i]).coeffs[1]) + (F_J2_x[i]).coeffs[1] = constant_term(F_J2_x1[i]) + constant_term(F_J2_x2[i]) + (F_J2_x[i]).coeffs[2:order + 1] .= zero((F_J2_x[i]).coeffs[1]) + (F_J2_y[i]).coeffs[1] = constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]) + (F_J2_y[i]).coeffs[2:order + 1] .= zero((F_J2_y[i]).coeffs[1]) + (F_J2_z[i]).coeffs[1] = constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]) + (F_J2_z[i]).coeffs[2:order + 1] .= zero((F_J2_z[i]).coeffs[1]) + end + (tmp1449[i]).coeffs[1] = constant_term(ui[i]) ^ float(constant_term(2)) + (tmp1449[i]).coeffs[2:order + 1] .= zero((tmp1449[i]).coeffs[1]) + (tmp1451[i]).coeffs[1] = constant_term(vi[i]) ^ float(constant_term(2)) + (tmp1451[i]).coeffs[2:order + 1] .= zero((tmp1451[i]).coeffs[1]) + (tmp1452[i]).coeffs[1] = constant_term(tmp1449[i]) + constant_term(tmp1451[i]) + (tmp1452[i]).coeffs[2:order + 1] .= zero((tmp1452[i]).coeffs[1]) + (tmp1454[i]).coeffs[1] = constant_term(wi[i]) ^ float(constant_term(2)) + (tmp1454[i]).coeffs[2:order + 1] .= zero((tmp1454[i]).coeffs[1]) + (v2[i]).coeffs[1] = constant_term(tmp1452[i]) + constant_term(tmp1454[i]) + (v2[i]).coeffs[2:order + 1] .= zero((v2[i]).coeffs[1]) + end + tmp1457.coeffs[1] = constant_term(q[4]) ^ float(constant_term(2)) + tmp1457.coeffs[2:order + 1] .= zero(tmp1457.coeffs[1]) + tmp1459.coeffs[1] = constant_term(q[5]) ^ float(constant_term(2)) + tmp1459.coeffs[2:order + 1] .= zero(tmp1459.coeffs[1]) + tmp1460.coeffs[1] = constant_term(tmp1457) + constant_term(tmp1459) + tmp1460.coeffs[2:order + 1] .= zero(tmp1460.coeffs[1]) + tmp1462.coeffs[1] = constant_term(q[6]) ^ float(constant_term(2)) + tmp1462.coeffs[2:order + 1] .= zero(tmp1462.coeffs[1]) + (v2[N]).coeffs[1] = constant_term(tmp1460) + constant_term(tmp1462) + (v2[N]).coeffs[2:order + 1] .= zero((v2[N]).coeffs[1]) + for i = 1:Nm1 + (temp_004[i]).coeffs[1] = constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]) + (temp_004[i]).coeffs[2:order + 1] .= zero((temp_004[i]).coeffs[1]) + (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(temp_004[i])) + (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) + if UJ_interaction[i] + (tmp1465[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_x[i]) + (tmp1465[i]).coeffs[2:order + 1] .= zero((tmp1465[i]).coeffs[1]) + (temp_accX_i[i]).coeffs[1] = constant_term(accX) - constant_term(tmp1465[i]) + (temp_accX_i[i]).coeffs[2:order + 1] .= zero((temp_accX_i[i]).coeffs[1]) + accX.coeffs[1] = identity(constant_term(temp_accX_i[i])) + accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) + (tmp1467[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_y[i]) + (tmp1467[i]).coeffs[2:order + 1] .= zero((tmp1467[i]).coeffs[1]) + (temp_accY_i[i]).coeffs[1] = constant_term(accY) - constant_term(tmp1467[i]) + (temp_accY_i[i]).coeffs[2:order + 1] .= zero((temp_accY_i[i]).coeffs[1]) + accY.coeffs[1] = identity(constant_term(temp_accY_i[i])) + accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) + (tmp1469[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_z[i]) + (tmp1469[i]).coeffs[2:order + 1] .= zero((tmp1469[i]).coeffs[1]) + (temp_accZ_i[i]).coeffs[1] = constant_term(accZ) - constant_term(tmp1469[i]) + (temp_accZ_i[i]).coeffs[2:order + 1] .= zero((temp_accZ_i[i]).coeffs[1]) + accZ.coeffs[1] = identity(constant_term(temp_accZ_i[i])) + accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) + end + end + (_4ϕj[N]).coeffs[1] = constant_term(4) * constant_term(newtonianNb_Potential[N]) + (_4ϕj[N]).coeffs[2:order + 1] .= zero((_4ϕj[N]).coeffs[1]) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 + (ϕi_plus_4ϕj[i]).coeffs[1] = constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]) + (ϕi_plus_4ϕj[i]).coeffs[2:order + 1] .= zero((ϕi_plus_4ϕj[i]).coeffs[1]) + (tmp1475[i]).coeffs[1] = constant_term(2) * constant_term(v2[i]) + (tmp1475[i]).coeffs[2:order + 1] .= zero((tmp1475[i]).coeffs[1]) + (tmp1477[i]).coeffs[1] = constant_term(4) * constant_term(vi_dot_vj[i]) + (tmp1477[i]).coeffs[2:order + 1] .= zero((tmp1477[i]).coeffs[1]) + (tmp1478[i]).coeffs[1] = constant_term(tmp1475[i]) - constant_term(tmp1477[i]) + (tmp1478[i]).coeffs[2:order + 1] .= zero((tmp1478[i]).coeffs[1]) + (sj2_plus_2si2_minus_4vivj[i]).coeffs[1] = constant_term(tmp1478[i]) + constant_term(v2[N]) + (sj2_plus_2si2_minus_4vivj[i]).coeffs[2:order + 1] .= zero((sj2_plus_2si2_minus_4vivj[i]).coeffs[1]) + (ϕs_and_vs[i]).coeffs[1] = constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]) + (ϕs_and_vs[i]).coeffs[2:order + 1] .= zero((ϕs_and_vs[i]).coeffs[1]) + (Xij_t_Ui[i]).coeffs[1] = constant_term(X[i]) * constant_term(ui[i]) + (Xij_t_Ui[i]).coeffs[2:order + 1] .= zero((Xij_t_Ui[i]).coeffs[1]) + (Yij_t_Vi[i]).coeffs[1] = constant_term(Y[i]) * constant_term(vi[i]) + (Yij_t_Vi[i]).coeffs[2:order + 1] .= zero((Yij_t_Vi[i]).coeffs[1]) + (Zij_t_Wi[i]).coeffs[1] = constant_term(Z[i]) * constant_term(wi[i]) + (Zij_t_Wi[i]).coeffs[2:order + 1] .= zero((Zij_t_Wi[i]).coeffs[1]) + (tmp1484[i]).coeffs[1] = constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]) + (tmp1484[i]).coeffs[2:order + 1] .= zero((tmp1484[i]).coeffs[1]) + (Rij_dot_Vi[i]).coeffs[1] = constant_term(tmp1484[i]) + constant_term(Zij_t_Wi[i]) + (Rij_dot_Vi[i]).coeffs[2:order + 1] .= zero((Rij_dot_Vi[i]).coeffs[1]) + (tmp1487[i]).coeffs[1] = constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)) + (tmp1487[i]).coeffs[2:order + 1] .= zero((tmp1487[i]).coeffs[1]) + (pn1t7[i]).coeffs[1] = constant_term(tmp1487[i]) / constant_term(r_p2[i]) + (pn1t7[i]).coeffs[2:order + 1] .= zero((pn1t7[i]).coeffs[1]) + (tmp1490[i]).coeffs[1] = constant_term(1.5) * constant_term(pn1t7[i]) + (tmp1490[i]).coeffs[2:order + 1] .= zero((tmp1490[i]).coeffs[1]) + (pn1t2_7[i]).coeffs[1] = constant_term(ϕs_and_vs[i]) - constant_term(tmp1490[i]) + (pn1t2_7[i]).coeffs[2:order + 1] .= zero((pn1t2_7[i]).coeffs[1]) + (pn1t1_7[i]).coeffs[1] = constant_term(c_p2) + constant_term(pn1t2_7[i]) + (pn1t1_7[i]).coeffs[2:order + 1] .= zero((pn1t1_7[i]).coeffs[1]) + (pNX_t_X[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(X[i]) + (pNX_t_X[i]).coeffs[2:order + 1] .= zero((pNX_t_X[i]).coeffs[1]) + (pNY_t_Y[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(Y[i]) + (pNY_t_Y[i]).coeffs[2:order + 1] .= zero((pNY_t_Y[i]).coeffs[1]) + (pNZ_t_Z[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(Z[i]) + (pNZ_t_Z[i]).coeffs[2:order + 1] .= zero((pNZ_t_Z[i]).coeffs[1]) + (tmp1497[i]).coeffs[1] = constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]) + (tmp1497[i]).coeffs[2:order + 1] .= zero((tmp1497[i]).coeffs[1]) + (tmp1498[i]).coeffs[1] = constant_term(tmp1497[i]) + constant_term(pNZ_t_Z[i]) + (tmp1498[i]).coeffs[2:order + 1] .= zero((tmp1498[i]).coeffs[1]) + (tmp1499[i]).coeffs[1] = constant_term(0.5) * constant_term(tmp1498[i]) + (tmp1499[i]).coeffs[2:order + 1] .= zero((tmp1499[i]).coeffs[1]) + (pn1[i]).coeffs[1] = constant_term(pn1t1_7[i]) + constant_term(tmp1499[i]) + (pn1[i]).coeffs[2:order + 1] .= zero((pn1[i]).coeffs[1]) + (X_t_pn1[i]).coeffs[1] = constant_term(newton_acc_X[i]) * constant_term(pn1[i]) + (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) + (Y_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Y[i]) * constant_term(pn1[i]) + (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) + (Z_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Z[i]) * constant_term(pn1[i]) + (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) + (pNX_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(pn3[i]) + (pNX_t_pn3[i]).coeffs[2:order + 1] .= zero((pNX_t_pn3[i]).coeffs[1]) + (pNY_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]) + (pNY_t_pn3[i]).coeffs[2:order + 1] .= zero((pNY_t_pn3[i]).coeffs[1]) + (pNZ_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(pn3[i]) + (pNZ_t_pn3[i]).coeffs[2:order + 1] .= zero((pNZ_t_pn3[i]).coeffs[1]) + end + for i = 1:10 + (tmp1507[i]).coeffs[1] = constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]) + (tmp1507[i]).coeffs[2:order + 1] .= zero((tmp1507[i]).coeffs[1]) + (termpnx[i]).coeffs[1] = constant_term(X_t_pn1[i]) + constant_term(tmp1507[i]) + (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) + (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) + (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) + pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) + pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) + (tmp1510[i]).coeffs[1] = constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]) + (tmp1510[i]).coeffs[2:order + 1] .= zero((tmp1510[i]).coeffs[1]) + (termpny[i]).coeffs[1] = constant_term(Y_t_pn1[i]) + constant_term(tmp1510[i]) + (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) + (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) + (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) + pntempY.coeffs[1] = identity(constant_term(sumpny[i])) + pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) + (tmp1513[i]).coeffs[1] = constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]) + (tmp1513[i]).coeffs[2:order + 1] .= zero((tmp1513[i]).coeffs[1]) + (termpnz[i]).coeffs[1] = constant_term(Z_t_pn1[i]) + constant_term(tmp1513[i]) + (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) + (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) + (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) + pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) + pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) + end + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 + (X_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_X[i]) + (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) + (Y_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Y[i]) + (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) + (Z_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Z[i]) + (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) + end + for i = 11:Nm1 + (termpnx[i]).coeffs[1] = identity(constant_term(X_t_pn1[i])) + (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) + (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) + (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) + pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) + pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) + (termpny[i]).coeffs[1] = identity(constant_term(Y_t_pn1[i])) + (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) + (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) + (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) + pntempY.coeffs[1] = identity(constant_term(sumpny[i])) + pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) + (termpnz[i]).coeffs[1] = identity(constant_term(Z_t_pn1[i])) + (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) + (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) + (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) + pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) + pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) + end + postNewtonX.coeffs[1] = constant_term(pntempX) * constant_term(c_m2) + postNewtonX.coeffs[2:order + 1] .= zero(postNewtonX.coeffs[1]) + postNewtonY.coeffs[1] = constant_term(pntempY) * constant_term(c_m2) + postNewtonY.coeffs[2:order + 1] .= zero(postNewtonY.coeffs[1]) + postNewtonZ.coeffs[1] = constant_term(pntempZ) * constant_term(c_m2) + postNewtonZ.coeffs[2:order + 1] .= zero(postNewtonZ.coeffs[1]) + (dq[4]).coeffs[1] = constant_term(postNewtonX) + constant_term(accX) + (dq[4]).coeffs[2:order + 1] .= zero((dq[4]).coeffs[1]) + (dq[5]).coeffs[1] = constant_term(postNewtonY) + constant_term(accY) + (dq[5]).coeffs[2:order + 1] .= zero((dq[5]).coeffs[1]) + (dq[6]).coeffs[1] = constant_term(postNewtonZ) + constant_term(accZ) + (dq[6]).coeffs[2:order + 1] .= zero((dq[6]).coeffs[1]) + for __idx = eachindex(q) + (q[__idx]).coeffs[2] = (dq[__idx]).coeffs[1] + end + for ord = 1:order - 1 + ordnext = ord + 1 + TaylorSeries.identity!(pntempX, zero_q_1, ord) + TaylorSeries.identity!(pntempY, zero_q_1, ord) + TaylorSeries.identity!(pntempZ, zero_q_1, ord) + TaylorSeries.identity!(accX, zero_q_1, ord) + TaylorSeries.identity!(accY, zero_q_1, ord) + TaylorSeries.identity!(accZ, zero_q_1, ord) + TaylorSeries.identity!(dq[1], q[4], ord) + TaylorSeries.identity!(dq[2], q[5], ord) + TaylorSeries.identity!(dq[3], q[6], ord) + TaylorSeries.identity!(newtonianNb_Potential[N], zero_q_1, ord) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 + TaylorSeries.identity!(ui[i], ss16asteph_t[3 * ((N - 1) + i) - 2], ord) + TaylorSeries.identity!(vi[i], ss16asteph_t[3 * ((N - 1) + i) - 1], ord) + TaylorSeries.identity!(wi[i], ss16asteph_t[3 * ((N - 1) + i)], ord) + TaylorSeries.subst!(X[i], ss16asteph_t[3i - 2], q[1], ord) + TaylorSeries.subst!(Y[i], ss16asteph_t[3i - 1], q[2], ord) + TaylorSeries.subst!(Z[i], ss16asteph_t[3i], q[3], ord) + TaylorSeries.subst!(U[i], ui[i], dq[1], ord) + TaylorSeries.subst!(V[i], vi[i], dq[2], ord) + TaylorSeries.subst!(W[i], wi[i], dq[3], ord) + TaylorSeries.mul!(tmp1317[1], 4, dq[1], ord) + TaylorSeries.mul!(tmp1319[i], 3, ui[i], ord) + TaylorSeries.subst!(_4U_m_3X[i], tmp1317[1], tmp1319[i], ord) + TaylorSeries.mul!(tmp1322[2], 4, dq[2], ord) + TaylorSeries.mul!(tmp1324[i], 3, vi[i], ord) + TaylorSeries.subst!(_4V_m_3Y[i], tmp1322[2], tmp1324[i], ord) + TaylorSeries.mul!(tmp1327[3], 4, dq[3], ord) + TaylorSeries.mul!(tmp1329[i], 3, wi[i], ord) + TaylorSeries.subst!(_4W_m_3Z[i], tmp1327[3], tmp1329[i], ord) + TaylorSeries.mul!(pn2x[i], X[i], _4U_m_3X[i], ord) + TaylorSeries.mul!(pn2y[i], Y[i], _4V_m_3Y[i], ord) + TaylorSeries.mul!(pn2z[i], Z[i], _4W_m_3Z[i], ord) + TaylorSeries.mul!(UU[i], ui[i], dq[1], ord) + TaylorSeries.mul!(VV[i], vi[i], dq[2], ord) + TaylorSeries.mul!(WW[i], wi[i], dq[3], ord) + TaylorSeries.add!(tmp1337[i], UU[i], VV[i], ord) + TaylorSeries.add!(vi_dot_vj[i], tmp1337[i], WW[i], ord) + TaylorSeries.pow!(tmp1340[i], X[i], 2, ord) + TaylorSeries.pow!(tmp1342[i], Y[i], 2, ord) + TaylorSeries.add!(tmp1343[i], tmp1340[i], tmp1342[i], ord) + TaylorSeries.pow!(tmp1345[i], Z[i], 2, ord) + TaylorSeries.add!(r_p2[i], tmp1343[i], tmp1345[i], ord) + TaylorSeries.sqrt!(r_p1d2[i], r_p2[i], ord) + TaylorSeries.pow!(r_p3d2[i], r_p2[i], 1.5, ord) + TaylorSeries.pow!(r_p7d2[i], r_p2[i], 3.5, ord) + TaylorSeries.div!(newtonianCoeff[i], μ[i], r_p3d2[i], ord) + TaylorSeries.add!(tmp1353[i], pn2x[i], pn2y[i], ord) + TaylorSeries.add!(tmp1354[i], tmp1353[i], pn2z[i], ord) + TaylorSeries.mul!(pn2[i], newtonianCoeff[i], tmp1354[i], ord) + TaylorSeries.mul!(newton_acc_X[i], X[i], newtonianCoeff[i], ord) + TaylorSeries.mul!(newton_acc_Y[i], Y[i], newtonianCoeff[i], ord) + TaylorSeries.mul!(newton_acc_Z[i], Z[i], newtonianCoeff[i], ord) + TaylorSeries.div!(newtonian1b_Potential[i], μ[i], r_p1d2[i], ord) + TaylorSeries.mul!(pn3[i], 3.5, newtonian1b_Potential[i], ord) + TaylorSeries.mul!(U_t_pn2[i], pn2[i], U[i], ord) + TaylorSeries.mul!(V_t_pn2[i], pn2[i], V[i], ord) + TaylorSeries.mul!(W_t_pn2[i], pn2[i], W[i], ord) + if UJ_interaction[i] + TaylorSeries.subst!(tmp1365[i], X[i], ord) + TaylorSeries.mul!(t31[i], tmp1365[i], M_[1, 3, i], ord) + TaylorSeries.subst!(tmp1367[i], Y[i], ord) + TaylorSeries.mul!(t32[i], tmp1367[i], M_[2, 3, i], ord) + TaylorSeries.subst!(tmp1369[i], Z[i], ord) + TaylorSeries.mul!(t33[i], tmp1369[i], M_[3, 3, i], ord) + TaylorSeries.add!(tmp1371[i], t31[i], t32[i], ord) + TaylorSeries.add!(r_sin_ϕ[i], tmp1371[i], t33[i], ord) + TaylorSeries.div!(sin_ϕ[i], r_sin_ϕ[i], r_p1d2[i], ord) + TaylorSeries.asin!(ϕ[i], sin_ϕ[i], tmp1528[i], ord) + TaylorSeries.sincos!(tmp1529[i], cos_ϕ[i], ϕ[i], ord) + TaylorSeries.pow!(sin2_ϕ[i], sin_ϕ[i], 2, ord) + TaylorSeries.pow!(sin3_ϕ[i], sin_ϕ[i], 3, ord) + TaylorSeries.mul!(tmp1381[i], 1.5, sin2_ϕ[i], ord) + TaylorSeries.subst!(P_2_sin_ϕ[i], tmp1381[i], 0.5, ord) + TaylorSeries.mul!(∂P_2_sin_ϕ[i], 3, sin_ϕ[i], ord) + TaylorSeries.mul!(tmp1387[i], -1.5, sin_ϕ[i], ord) + TaylorSeries.mul!(tmp1389[i], 2.5, sin3_ϕ[i], ord) + TaylorSeries.add!(P_3_sin_ϕ[i], tmp1387[i], tmp1389[i], ord) + TaylorSeries.mul!(tmp1393[i], 7.5, sin2_ϕ[i], ord) + TaylorSeries.add!(∂P_3_sin_ϕ[i], -1.5, tmp1393[i], ord) + TaylorSeries.pow!(tmp1396[i], r_p2[i], 2, ord) + TaylorSeries.div!(tmp1397[i], Λ2[i], tmp1396[i], ord) + TaylorSeries.subst!(Λ2j_div_r4[i], tmp1397[i], ord) + TaylorSeries.pow!(tmp1400[i], r_p1d2[i], 5, ord) + TaylorSeries.div!(tmp1401[i], Λ3[i], tmp1400[i], ord) + TaylorSeries.subst!(Λ3j_div_r5[i], tmp1401[i], ord) + TaylorSeries.subst!(tmp1403[i], cos_ϕ[i], ord) + TaylorSeries.mul!(m_c_ϕ_∂P_2[i], tmp1403[i], ∂P_2_sin_ϕ[i], ord) + TaylorSeries.subst!(tmp1405[i], cos_ϕ[i], ord) + TaylorSeries.mul!(m_c_ϕ_∂P_3[i], tmp1405[i], ∂P_3_sin_ϕ[i], ord) + TaylorSeries.mul!(tmp1408[i], Λ2j_div_r4[i], 3, ord) + TaylorSeries.mul!(F_J2_ξ[i], tmp1408[i], P_2_sin_ϕ[i], ord) + TaylorSeries.mul!(F_J2_ζ[i], Λ2j_div_r4[i], m_c_ϕ_∂P_2[i], ord) + TaylorSeries.mul!(tmp1412[i], Λ3j_div_r5[i], 4, ord) + TaylorSeries.mul!(F_J3_ξ[i], tmp1412[i], P_3_sin_ϕ[i], ord) + TaylorSeries.mul!(F_J3_ζ[i], Λ3j_div_r5[i], m_c_ϕ_∂P_3[i], ord) + TaylorSeries.identity!(F_J_ξ[i], F_J2_ξ[i], ord) + TaylorSeries.identity!(F_J_ζ[i], F_J2_ζ[i], ord) + TaylorSeries.subst!(tmp1415[i], X[i], ord) + TaylorSeries.div!(ξx[i], tmp1415[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp1417[i], Y[i], ord) + TaylorSeries.div!(ξy[i], tmp1417[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp1419[i], Z[i], ord) + TaylorSeries.div!(ξz[i], tmp1419[i], r_p1d2[i], ord) + TaylorSeries.mul!(ηx1[i], M_[2, 3, i], ξz[i], ord) + TaylorSeries.mul!(ηy1[i], M_[3, 3, i], ξx[i], ord) + TaylorSeries.mul!(ηz1[i], M_[1, 3, i], ξy[i], ord) + TaylorSeries.mul!(ηx2[i], M_[3, 3, i], ξy[i], ord) + TaylorSeries.mul!(ηy2[i], M_[1, 3, i], ξz[i], ord) + TaylorSeries.mul!(ηz2[i], M_[2, 3, i], ξx[i], ord) + TaylorSeries.subst!(ηx[i], ηx1[i], ηx2[i], ord) + TaylorSeries.subst!(ηy[i], ηy1[i], ηy2[i], ord) + TaylorSeries.subst!(ηz[i], ηz1[i], ηz2[i], ord) + TaylorSeries.mul!(ζx1[i], ξy[i], ηz[i], ord) + TaylorSeries.mul!(ζy1[i], ξz[i], ηx[i], ord) + TaylorSeries.mul!(ζz1[i], ξx[i], ηy[i], ord) + TaylorSeries.mul!(ζx2[i], ξz[i], ηy[i], ord) + TaylorSeries.mul!(ζy2[i], ξx[i], ηz[i], ord) + TaylorSeries.mul!(ζz2[i], ξy[i], ηx[i], ord) + TaylorSeries.subst!(ζx[i], ζx1[i], ζx2[i], ord) + TaylorSeries.subst!(ζy[i], ζy1[i], ζy2[i], ord) + TaylorSeries.subst!(ζz[i], ζz1[i], ζz2[i], ord) + TaylorSeries.mul!(F_J2_x1[i], F_J_ξ[i], ξx[i], ord) + TaylorSeries.mul!(F_J2_y1[i], F_J_ξ[i], ξy[i], ord) + TaylorSeries.mul!(F_J2_z1[i], F_J_ξ[i], ξz[i], ord) + TaylorSeries.mul!(F_J2_x2[i], F_J_ζ[i], ζx[i], ord) + TaylorSeries.mul!(F_J2_y2[i], F_J_ζ[i], ζy[i], ord) + TaylorSeries.mul!(F_J2_z2[i], F_J_ζ[i], ζz[i], ord) + TaylorSeries.add!(F_J2_x[i], F_J2_x1[i], F_J2_x2[i], ord) + TaylorSeries.add!(F_J2_y[i], F_J2_y1[i], F_J2_y2[i], ord) + TaylorSeries.add!(F_J2_z[i], F_J2_z1[i], F_J2_z2[i], ord) + end + TaylorSeries.pow!(tmp1449[i], ui[i], 2, ord) + TaylorSeries.pow!(tmp1451[i], vi[i], 2, ord) + TaylorSeries.add!(tmp1452[i], tmp1449[i], tmp1451[i], ord) + TaylorSeries.pow!(tmp1454[i], wi[i], 2, ord) + TaylorSeries.add!(v2[i], tmp1452[i], tmp1454[i], ord) + end + TaylorSeries.pow!(tmp1457, q[4], 2, ord) + TaylorSeries.pow!(tmp1459, q[5], 2, ord) + TaylorSeries.add!(tmp1460, tmp1457, tmp1459, ord) + TaylorSeries.pow!(tmp1462, q[6], 2, ord) + TaylorSeries.add!(v2[N], tmp1460, tmp1462, ord) + for i = 1:Nm1 + TaylorSeries.add!(temp_004[i], newtonian1b_Potential[i], newtonianNb_Potential[N], ord) + TaylorSeries.identity!(newtonianNb_Potential[N], temp_004[i], ord) + if UJ_interaction[i] + TaylorSeries.mul!(tmp1465[i], μ[i], F_J2_x[i], ord) + TaylorSeries.subst!(temp_accX_i[i], accX, tmp1465[i], ord) + TaylorSeries.identity!(accX, temp_accX_i[i], ord) + TaylorSeries.mul!(tmp1467[i], μ[i], F_J2_y[i], ord) + TaylorSeries.subst!(temp_accY_i[i], accY, tmp1467[i], ord) + TaylorSeries.identity!(accY, temp_accY_i[i], ord) + TaylorSeries.mul!(tmp1469[i], μ[i], F_J2_z[i], ord) + TaylorSeries.subst!(temp_accZ_i[i], accZ, tmp1469[i], ord) + TaylorSeries.identity!(accZ, temp_accZ_i[i], ord) + end + end + TaylorSeries.mul!(_4ϕj[N], 4, newtonianNb_Potential[N], ord) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 + TaylorSeries.add!(ϕi_plus_4ϕj[i], newtonianNb_Potential_t[i], _4ϕj[N], ord) + TaylorSeries.mul!(tmp1475[i], 2, v2[i], ord) + TaylorSeries.mul!(tmp1477[i], 4, vi_dot_vj[i], ord) + TaylorSeries.subst!(tmp1478[i], tmp1475[i], tmp1477[i], ord) + TaylorSeries.add!(sj2_plus_2si2_minus_4vivj[i], tmp1478[i], v2[N], ord) + TaylorSeries.subst!(ϕs_and_vs[i], sj2_plus_2si2_minus_4vivj[i], ϕi_plus_4ϕj[i], ord) + TaylorSeries.mul!(Xij_t_Ui[i], X[i], ui[i], ord) + TaylorSeries.mul!(Yij_t_Vi[i], Y[i], vi[i], ord) + TaylorSeries.mul!(Zij_t_Wi[i], Z[i], wi[i], ord) + TaylorSeries.add!(tmp1484[i], Xij_t_Ui[i], Yij_t_Vi[i], ord) + TaylorSeries.add!(Rij_dot_Vi[i], tmp1484[i], Zij_t_Wi[i], ord) + TaylorSeries.pow!(tmp1487[i], Rij_dot_Vi[i], 2, ord) + TaylorSeries.div!(pn1t7[i], tmp1487[i], r_p2[i], ord) + TaylorSeries.mul!(tmp1490[i], 1.5, pn1t7[i], ord) + TaylorSeries.subst!(pn1t2_7[i], ϕs_and_vs[i], tmp1490[i], ord) + TaylorSeries.add!(pn1t1_7[i], c_p2, pn1t2_7[i], ord) + TaylorSeries.mul!(pNX_t_X[i], acceph_t[3i - 2], X[i], ord) + TaylorSeries.mul!(pNY_t_Y[i], acceph_t[3i - 1], Y[i], ord) + TaylorSeries.mul!(pNZ_t_Z[i], acceph_t[3i], Z[i], ord) + TaylorSeries.add!(tmp1497[i], pNX_t_X[i], pNY_t_Y[i], ord) + TaylorSeries.add!(tmp1498[i], tmp1497[i], pNZ_t_Z[i], ord) + TaylorSeries.mul!(tmp1499[i], 0.5, tmp1498[i], ord) + TaylorSeries.add!(pn1[i], pn1t1_7[i], tmp1499[i], ord) + TaylorSeries.mul!(X_t_pn1[i], newton_acc_X[i], pn1[i], ord) + TaylorSeries.mul!(Y_t_pn1[i], newton_acc_Y[i], pn1[i], ord) + TaylorSeries.mul!(Z_t_pn1[i], newton_acc_Z[i], pn1[i], ord) + TaylorSeries.mul!(pNX_t_pn3[i], acceph_t[3i - 2], pn3[i], ord) + TaylorSeries.mul!(pNY_t_pn3[i], acceph_t[3i - 1], pn3[i], ord) + TaylorSeries.mul!(pNZ_t_pn3[i], acceph_t[3i], pn3[i], ord) + end + for i = 1:10 + TaylorSeries.add!(tmp1507[i], U_t_pn2[i], pNX_t_pn3[i], ord) + TaylorSeries.add!(termpnx[i], X_t_pn1[i], tmp1507[i], ord) + TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) + TaylorSeries.identity!(pntempX, sumpnx[i], ord) + TaylorSeries.add!(tmp1510[i], V_t_pn2[i], pNY_t_pn3[i], ord) + TaylorSeries.add!(termpny[i], Y_t_pn1[i], tmp1510[i], ord) + TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) + TaylorSeries.identity!(pntempY, sumpny[i], ord) + TaylorSeries.add!(tmp1513[i], W_t_pn2[i], pNZ_t_pn3[i], ord) + TaylorSeries.add!(termpnz[i], Z_t_pn1[i], tmp1513[i], ord) + TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) + TaylorSeries.identity!(pntempZ, sumpnz[i], ord) + end + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 + TaylorSeries.mul!(X_t_pn1[i], c_p2, newton_acc_X[i], ord) + TaylorSeries.mul!(Y_t_pn1[i], c_p2, newton_acc_Y[i], ord) + TaylorSeries.mul!(Z_t_pn1[i], c_p2, newton_acc_Z[i], ord) + end + for i = 11:Nm1 + TaylorSeries.identity!(termpnx[i], X_t_pn1[i], ord) + TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) + TaylorSeries.identity!(pntempX, sumpnx[i], ord) + TaylorSeries.identity!(termpny[i], Y_t_pn1[i], ord) + TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) + TaylorSeries.identity!(pntempY, sumpny[i], ord) + TaylorSeries.identity!(termpnz[i], Z_t_pn1[i], ord) + TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) + TaylorSeries.identity!(pntempZ, sumpnz[i], ord) + end + TaylorSeries.mul!(postNewtonX, pntempX, c_m2, ord) + TaylorSeries.mul!(postNewtonY, pntempY, c_m2, ord) + TaylorSeries.mul!(postNewtonZ, pntempZ, c_m2, ord) + TaylorSeries.add!(dq[4], postNewtonX, accX, ord) + TaylorSeries.add!(dq[5], postNewtonY, accY, ord) + TaylorSeries.add!(dq[6], postNewtonZ, accZ, ord) + for __idx = eachindex(q) + (q[__idx]).coeffs[ordnext + 1] = (dq[__idx]).coeffs[ordnext] / ordnext + end + end + return nothing end \ No newline at end of file diff --git a/src/propagation/propagation.jl b/src/propagation/propagation.jl old mode 100644 new mode 100755 index c5a4e7f4..f9dc6a64 --- a/src/propagation/propagation.jl +++ b/src/propagation/propagation.jl @@ -1,221 +1,285 @@ -include("asteroid_dynamical_models.jl") -include("jetcoeffs.jl") -include("serialization.jl") - -@doc raw""" - rvelea(dx, x, params, t) - -Return `true` and the asteroid's radial velocity with respect to the Earth. - -# Arguments - -- `dx`: asteroid's velocities. -- `x`: asteroid's degrees of freedom. -- `params`: parameters (ephemeris + accelerations + newtonian N body potential + julian date of start time + matrix of extended body interactions + number of bodies + mass parameters). -- `t`: time. -""" -function rvelea(dx, x, params, t) - - jd0 = params[4] # Julian date of start time - dsj2k = t + (jd0 - JD_J2000) # Days since J2000 - ss16asteph_t = evaleph(params[1], dsj2k, x[1]) # Evaluate ephemeris at dsj2k - N = params[6] # Total number of bodies - xe = ss16asteph_t[nbodyind(N-1,ea)] # Earth's ephemeris - - return true, (x[1]-xe[1])*(x[4]-xe[4]) + (x[2]-xe[2])*(x[5]-xe[5]) + (x[3]-xe[3])*(x[6]-xe[6]) -end - -@doc raw""" - scaled_variables(c::Vector{T} = fill(1e-6, 6), names::String = "δx"; order::Int = 5) where {T <: Real} - -Equivalent to `TaylorSeries.set_variables` times a scaling given by `c`. -""" -function scaled_variables(names::String = "δx", c::Vector{T} = fill(1e-6, 6); order::Int = 5) where {T <: Real} - # Set TaylorN variables - dq = set_variables(T, names, order = order, numvars = length(c)) - # Scale jet transport perturbation - for i in eachindex(dq) - dq[i][1][i] = c[i] - end - return dq -end - -@doc raw""" - propagate_params(jd0::T, tspan::T, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, - abstol::T = abstol) where {T <: Real, U <: Number} - -Return the parameters needed for `propagate`, `propagate_root` and `propagate_lyap`. - -# Arguments - -- `jd0::T`: initial Julian date. -- `tspan::T`: time span of the integration [in years]. -- `q0::Vector{U}`: vector of initial conditions. -- `μ_ast::Vector`: vector of gravitational parameters. -- `order::Int`: order of the Taylor expansions to be used in the integration. -- `abstol::T`: absolute tolerance. -""" -function propagate_params(jd0::T, tspan::T, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, - abstol::T = abstol) where {T <: Real, U <: Number} - - # Time limits [days since J2000] - days_0, days_f = minmax(jd0, jd0 + tspan*yr) .- JD_J2000 - - # Load Solar System ephemeris [au, au/day] - _sseph = convert(T, loadpeeph(sseph, days_0, days_f)) - - # Load accelerations - _acceph = convert(T, loadpeeph(acceph, days_0, days_f)) - - # Load Newtonian potentials - _poteph = convert(T, loadpeeph(poteph, days_0, days_f)) - - # Number of massive bodies - Nm1 = numberofbodies(_sseph) - - # Number of bodies, including NEA - N = Nm1 + 1 - - # Vector of G*m values - μ = convert(Vector{T}, vcat( μ_DE430[1:11], μ_ast[1:Nm1-11], zero(T) ) ) - - # Check: number of SS bodies (N) in ephemeris must be equal to length of GM vector (μ) - @assert N == length(μ) "Total number of bodies in ephemeris must be equal to length of GM vector μ" - - # Interaction matrix with flattened bodies - UJ_interaction = fill(false, N) - - # Turn on Earth interaction - UJ_interaction[ea] = true - - # Initial time - _t0 = zero(T) - - # Final time - _tmax = _t0 + tspan*yr - - # Initial conditions - _q0 = one(T) * q0 - - # Vector of parameters for neosinteg - _params = (_sseph, _acceph, _poteph, jd0, UJ_interaction, N, μ) - - return _q0, _t0, _tmax, _params - -end - -@doc raw""" - propagate(dynamics::D, maxsteps::Int, jd0::T, tspan::T, q0::Vector{U}; - μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, - abstol::T = abstol, parse_eqs::Bool = true) where {T <: Real, U <: Number, D} - -Integrate the orbit of a NEO via the Taylor method. - -# Arguments - -- `dynamics::D`: dynamical model function. -- `maxsteps::Int`: maximum number of steps for the integration. -- `jd0::T`: initial Julian date. -- `tspan::T`: time span of the integration [in years]. -- `q0::Vector{U}`: vector of initial conditions. -- `μ_ast::Vector`: vector of gravitational parameters. -- `order::Int=order`: order of the Taylor expansions to be used in the integration. -- `abstol::T`: absolute tolerance. -- `parse_eqs::Bool`: whether to use the specialized method of `jetcoeffs` (`true`) or not. -""" -function propagate(dynamics::D, maxsteps::Int, jd0::T, tspan::T, q0::Vector{U}; - μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, - abstol::T = abstol, parse_eqs::Bool = true) where {T <: Real, U <: Number, D} - - # Check order - @assert order <= get_order(sseph.x[1]) "order ($(order)) must be less or equal than SS ephemeris order ($(get_order(sseph.x[1])))" - - # Parameters for taylorinteg - _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast = μ_ast, order = order, abstol = abstol) - - # Propagate orbit - - @time tv, xv, psol = taylorinteg(dynamics, _q0, _t0, _tmax, order, abstol, Val(true), _params; - maxsteps = maxsteps, parse_eqs = parse_eqs) - - return TaylorInterpolant(jd0 - JD_J2000, tv .- tv[1], psol) - -end - - -@doc raw""" - propagate_root(dynamics::D, maxsteps::Int, jd0::T, tspan::T, q0::Vector{U}; - parse_eqs::Bool = true, eventorder::Int = 0, newtoniter::Int = 10, - nrabstol::T = eps(T), μ_ast::Vector = μ_ast343_DE430[1:end], - order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number, D} - -Integrate the orbit of a NEO via the Taylor method while finding the zeros of `rvelea`. - -# Arguments - -- `dynamics::D`: dynamical model function. -- `maxsteps::Int`: maximum number of steps for the integration. -- `jd0::T`: initial Julian date. -- `tspan::T`: time span of the integration [in years]. -- `q0::Vector{U}`: vector of initial conditions. -- `parse_eqs::Bool`: whether to use the specialized method of `jetcoeffs` (`true`) or not. -- `eventorder::Int`: order of the derivative of `rvelea` whose roots are computed. -- `newtoniter::Int`: maximum Newton-Raphson iterations per detected root. -- `nrabstol::T`: allowed tolerance for the Newton-Raphson process. -- `μ_ast::Vector`: vector of gravitational parameters. -- `order::Int`: order of the Taylor expansions to be used in the integration. -- `abstol::T`: absolute tolerance. -""" -function propagate_root(dynamics::D, maxsteps::Int, jd0::T, tspan::T, q0::Vector{U}; - parse_eqs::Bool = true, eventorder::Int = 0, newtoniter::Int = 10, - nrabstol::T = eps(T), μ_ast::Vector = μ_ast343_DE430[1:end], - order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number, D} - - # Check order - @assert order <= get_order(sseph.x[1]) "order ($(order)) must be less or equal than SS ephemeris order ($(get_order(sseph.x[1])))" - - # Parameters for neosinteg - _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast = μ_ast, order = order, abstol = abstol) - - # Propagate orbit - @time tv, xv, psol, tvS, xvS, gvS = taylorinteg(dynamics, rvelea, _q0, _t0, _tmax, order, abstol, Val(true), _params; - maxsteps, parse_eqs, eventorder, newtoniter, nrabstol) - - return TaylorInterpolant(jd0 - JD_J2000, tv .- tv[1], psol), tvS, xvS, gvS - -end - -@doc raw""" - propagate_lyap(dynamics::D, maxsteps::Int, jd0::T, tspan::T, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], - order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: Real, U <: Number} - -Compute the Lyapunov spectrum of a NEO. - -# Arguments - -- `dynamics::D`: dynamical model function. -- `maxsteps::Int`: maximum number of steps for the integration. -- `jd0::T`: initial Julian date. -- `tspan::T`: time span of the integration [in Julian days]. -- `q0::Vector{U}`: vector of initial conditions. -- `μ_ast::Vector`: vector of gravitational parameters. -- `order::Int=order`: order of the Taylor expansions to be used in the integration. -- `abstol::T`: absolute tolerance. -- `parse_eqs::Bool`: whether to use the specialized method of `jetcoeffs` (`true`) or not. -""" -function propagate_lyap(dynamics::D, maxsteps::Int, jd0::T, tspan::T, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], - order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: Real, U <: Number, D} - - # Check order - @assert order <= get_order(sseph.x[1]) "order ($(order)) must be less or equal than SS ephemeris order ($(get_order(sseph.x[1])))" - - # Parameters for taylorinteg - _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast = μ_ast, order = order, abstol = abstol) - - # Propagate orbit - @time sol = lyap_taylorinteg(dynamics, _q0, _t0, _tmax, order, abstol, _params; - maxsteps = maxsteps, parse_eqs = parse_eqs) - - return sol - +include("asteroid_dynamical_models.jl") +include("jetcoeffs.jl") +include("serialization.jl") + +struct Parameters{T <: AbstractFloat} + maxsteps::Int + mpc_catalogue_codes_201X::Vector{String} + truth::String + resol::Resolution + bias_matrix::Matrix{T} + μ_ast::Vector{T} + order::Int + abstol::T + parse_eqs::Bool + function Parameters{T}(maxsteps::Int, mpc_catalogue_codes_201X::Vector{String}, + truth::String, resol::Resolution, bias_matrix::Matrix{T}, + μ_ast::Vector{T}, order::Int, abstol::T, parse_eqs::Bool) where {T <: AbstractFloat} + + return new{T}(maxsteps, mpc_catalogue_codes_201X, truth, resol, bias_matrix, μ_ast, + order, abstol, parse_eqs) + end +end + +@doc raw""" + Parameters(params::Parameters{T}; kwargs...) where {T <: AbstractFloat} + +Parameters for `propagate` and related functions. + +# Keyword arguments + +- `maxsteps::Int = 100`: maximum number of steps for the integration. +- `debias_table::String = "2018"`: possible values are: + - `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, + - `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, + - `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. +- `μ_ast::Vector`: vector of gravitational parameters. +- `order::Int = 25`: order of Taylor expansions wrt time. +- `abstol::T = 1e-20`: absolute tolerance (used to compute propagation timestep). +- `parse_eqs::Bool = true`: whether to use the specialized method of `jetcoeffs` (`true`) or not. +""" +function Parameters(; maxsteps::Int = 100, debias_table::String = "2018", + μ_ast::Vector{T} = μ_ast343_DE430[1:end], order::Int = 25, + abstol::T = 1e-20, parse_eqs::Bool = true) where {T <: AbstractFloat} + + mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) + return Parameters{T}(maxsteps, mpc_catalogue_codes_201X, truth, resol, bias_matrix, + μ_ast, order, abstol, parse_eqs) +end + +function Parameters(params::Parameters{T}; kwargs...) where {T <: AbstractFloat} + fields = fieldnames(Parameters{T}) + vals = Vector{Any}(undef, length(fields)) + for i in eachindex(vals) + if fields[i] in keys(kwargs) + vals[i] = kwargs[i] + else + vals[i] = getfield(params, i) + end + end + + return Parameters{T}(vals...) +end + +function residuals(obs::Vector{RadecMPC{T}}, params::Parameters{T}; kwargs...) where {T <: AbstractFloat} + return residuals(obs, params.mpc_catalogue_codes_201X, params.truth, params.resol, + params.bias_matrix; kwargs...) +end + +@doc raw""" + rvelea(dx, x, params, t) + +Return `true` and the asteroid's radial velocity with respect to the Earth. + +# Arguments + +- `dx`: asteroid's velocities. +- `x`: asteroid's degrees of freedom. +- `params`: parameters (ephemeris + accelerations + newtonian N body potential + julian date of start time + matrix of extended body interactions + number of bodies + mass parameters). +- `t`: time. +""" +function rvelea(dx, x, params, t) + + jd0 = params[4] # Julian date of start time + dsj2k = t + (jd0 - JD_J2000) # Days since J2000 + ss16asteph_t = evaleph(params[1], dsj2k, x[1]) # Evaluate ephemeris at dsj2k + N = params[6] # Total number of bodies + xe = ss16asteph_t[nbodyind(N-1,ea)] # Earth's ephemeris + + return true, (x[1]-xe[1])*(x[4]-xe[4]) + (x[2]-xe[2])*(x[5]-xe[5]) + (x[3]-xe[3])*(x[6]-xe[6]) +end + +@doc raw""" + scaled_variables(names::String = "δx", c::Vector{T} = fill(1e-6, 6); + order::Int = 5) where {T <: Real} + +Equivalent to `TaylorSeries.set_variables` times a scaling given by `c`. +""" +function scaled_variables(names::String = "δx", c::Vector{T} = fill(1e-6, 6); order::Int = 5) where {T <: Real} + # Set TaylorN variables + dq = set_variables(T, names, order = order, numvars = length(c)) + # Scale jet transport perturbation + for i in eachindex(dq) + dq[i][1][i] = c[i] + end + return dq +end + +@doc raw""" + propagate_params(jd0::T, tspan::T, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, + abstol::T = abstol) where {T <: Real, U <: Number} + +Return the parameters needed for `propagate`, `propagate_root` and `propagate_lyap`. + +# Arguments + +- `jd0::T`: initial Julian date. +- `tspan::T`: time span of the integration [in years]. +- `q0::Vector{U}`: vector of initial conditions. +- `μ_ast::Vector`: vector of gravitational parameters. +- `order::Int`: order of the Taylor expansions to be used in the integration. +- `abstol::T`: absolute tolerance. +""" +function propagate_params(jd0::T, tspan::T, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, + abstol::T = abstol) where {T <: Real, U <: Number} + + # Time limits [days since J2000] + days_0, days_f = minmax(jd0, jd0 + tspan*yr) .- JD_J2000 + + # Load Solar System ephemeris [au, au/day] + _sseph = convert(T, loadpeeph(sseph, days_0, days_f)) + + # Load accelerations + _acceph = convert(T, loadpeeph(acceph, days_0, days_f)) + + # Load Newtonian potentials + _poteph = convert(T, loadpeeph(poteph, days_0, days_f)) + + # Number of massive bodies + Nm1 = numberofbodies(_sseph) + + # Number of bodies, including NEA + N = Nm1 + 1 + + # Vector of G*m values + μ = convert(Vector{T}, vcat( μ_DE430[1:11], μ_ast[1:Nm1-11], zero(T) ) ) + + # Check: number of SS bodies (N) in ephemeris must be equal to length of GM vector (μ) + @assert N == length(μ) "Total number of bodies in ephemeris must be equal to length of GM vector μ" + + # Interaction matrix with flattened bodies + UJ_interaction = fill(false, N) + + # Turn on Earth interaction + UJ_interaction[ea] = true + + # Initial time + _t0 = zero(T) + + # Final time + _tmax = _t0 + tspan*yr + + # Initial conditions + _q0 = one(T) * q0 + + # Vector of parameters for neosinteg + _params = (_sseph, _acceph, _poteph, jd0, UJ_interaction, N, μ) + + return _q0, _t0, _tmax, _params + +end + +@doc raw""" + propagate(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, + params::Parameters{T}) where {T <: Real, U <: Number, D} + +Integrate the orbit of a NEO via the Taylor method. + +# Arguments + +- `dynamics::D`: dynamical model function. +- `jd0::T`: initial Julian date. +- `tspan::T`: time span of the integration [in years]. +- `q0::Vector{U}`: vector of initial conditions. +- `params::Parameters{T}`: see [`Parameters`](@ref). +""" +function propagate(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, + params::Parameters{T}) where {T <: Real, U <: Number, D} + + # Unfold + maxsteps, μ_ast, order, abstol, parse_eqs = params.maxsteps, params.μ_ast, params.order, + params.abstol, params.parse_eqs + + # Check order + @assert order <= get_order(sseph.x[1]) "order ($(order)) must be less or equal than SS ephemeris order ($(get_order(sseph.x[1])))" + + # Parameters for taylorinteg + _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast = μ_ast, order = order, abstol = abstol) + + # Propagate orbit + + @time tv, xv, psol = taylorinteg(dynamics, _q0, _t0, _tmax, order, abstol, Val(true), _params; + maxsteps = maxsteps, parse_eqs = parse_eqs) + + return TaylorInterpolant(jd0 - JD_J2000, tv .- tv[1], psol) + +end + +@doc raw""" + propagate_root(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, + params::Parameters{T}; eventorder::Int = 0, newtoniter::Int = 10, + nrabstol::T = eps(T)) where {T <: Real, U <: Number, D} + +Integrate the orbit of a NEO via the Taylor method while finding the zeros of +`NEOs.rvelea`. + +# Arguments + +- `dynamics::D`: dynamical model function. +- `jd0::T`: initial Julian date. +- `tspan::T`: time span of the integration [in years]. +- `q0::Vector{U}`: vector of initial conditions. +- `params::Parameters{T}`: see [`Parameters`](@ref). + +# Keyword arguments + +- `eventorder::Int`: order of the derivative of `rvelea` whose roots are computed. +- `newtoniter::Int`: maximum Newton-Raphson iterations per detected root. +- `nrabstol::T`: allowed tolerance for the Newton-Raphson process. +""" +function propagate_root(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, + params::Parameters{T}; eventorder::Int = 0, newtoniter::Int = 10, + nrabstol::T = eps(T)) where {T <: Real, U <: Number, D} + + # Unfold + maxsteps, μ_ast, order, abstol, parse_eqs = params.maxsteps, params.μ_ast, params.order, + params.abstol, params.parse_eqs + + # Check order + @assert order <= get_order(sseph.x[1]) "order ($(order)) must be less or equal than SS ephemeris order ($(get_order(sseph.x[1])))" + + # Parameters for neosinteg + _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast = μ_ast, order = order, abstol = abstol) + + # Propagate orbit + @time tv, xv, psol, tvS, xvS, gvS = taylorinteg(dynamics, rvelea, _q0, _t0, _tmax, order, abstol, Val(true), _params; + maxsteps, parse_eqs, eventorder, newtoniter, nrabstol) + + return TaylorInterpolant(jd0 - JD_J2000, tv .- tv[1], psol), tvS, xvS, gvS + +end + +@doc raw""" + propagate_lyap(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, + params::Parameters{T}) where {T <: Real, U <: Number} + +Compute the Lyapunov spectrum of a NEO. + +# Arguments + +- `dynamics::D`: dynamical model function. +- `jd0::T`: initial Julian date. +- `tspan::T`: time span of the integration [in Julian days]. +- `q0::Vector{U}`: vector of initial conditions. +- `params::Parameters{T}`: see [`Parameters`](@ref). +""" +function propagate_lyap(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, + params::Parameters{T}) where {T <: Real, U <: Number, D} + + # Unfold + maxsteps, μ_ast, order, abstol, parse_eqs = params.maxsteps, params.μ_ast, params.order, + params.abstol, params.parse_eqs + + # Check order + @assert order <= get_order(sseph.x[1]) "order ($(order)) must be less or equal than SS ephemeris order ($(get_order(sseph.x[1])))" + + # Parameters for taylorinteg + _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast = μ_ast, order = order, abstol = abstol) + + # Propagate orbit + @time sol = lyap_taylorinteg(dynamics, _q0, _t0, _tmax, order, abstol, _params; + maxsteps = maxsteps, parse_eqs = parse_eqs) + + return sol + end \ No newline at end of file diff --git a/src/propagation/serialization.jl b/src/propagation/serialization.jl old mode 100644 new mode 100755 index 8be73c35..78c33eee --- a/src/propagation/serialization.jl +++ b/src/propagation/serialization.jl @@ -1,204 +1,204 @@ -@doc raw""" - TaylorInterpolantNSerialization{T} - -Custom serialization struct to save a `TaylorInterpolant{T, TaylorN{T}, 2}` to a `.jld2` file. - -# Fields -- `vars::Vector{String}`: jet transport variables. -- `order::Int`: order of Taylor polynomials w.r.t time. -- `varorder::Int`: order of jet transport perturbations. -- `dims::Tuple{Int, Int}`: matrix dimensions. -- `t0::T`: initial time. -- `t::Vector{T}`: vector of times. -- `x::Vector{T}`: vector of coefficients. -""" -struct TaylorInterpolantNSerialization{T} - vars::Vector{String} - order::Int - varorder::Int - dims::Tuple{Int, Int} - t0::T - t::Vector{T} - x::Vector{T} -end - -# Tell JLD2 to save TaylorInterpolant{T, TaylorN{T}, 2} as TaylorInterpolantNSerialization{T} -writeas(::Type{TaylorInterpolant{T, TaylorN{T}, 2}}) where {T} = TaylorInterpolantNSerialization{T} - -# Convert method to write .jld2 files -function convert(::Type{TaylorInterpolantNSerialization{T}}, eph::TaylorInterpolant{T, TaylorN{T}, 2}) where {T} - # Variables - vars = TS.get_variable_names() - # Number of variables - n = length(vars) - # Matrix dimensions - dims = size(eph.x) - # Number of elements in matrix - N = length(eph.x) - # Taylor1 order - order = eph.x[1, 1].order - # Number of coefficients in each Taylor1 - k = order + 1 - # TaylorN order - varorder = eph.x[1, 1].coeffs[1].order - # Number of coefficients in each TaylorN - L = varorder + 1 - # Number of coefficients in each HomogeneousPolynomial - M = binomial(n + varorder, varorder) - # M = sum(binomial(n + i_3 - 1, i_3) for i_3 in 0:varorder) - - # Vector of coefficients - x = Vector{T}(undef, N * k * M) - - # Save coefficients - i = 1 - # Iterate over matrix elements - for i_1 in 1:N - # Iterate over Taylor1 coefficients - for i_2 in 1:k - # Iterate over TaylorN coefficients - for i_3 in 0:varorder - # Iterate over i_3 order HomogeneousPolynomial - for i_4 in 1:binomial(n + i_3 - 1, i_3) - x[i] = eph.x[i_1].coeffs[i_2].coeffs[i_3+1].coeffs[i_4] - i += 1 - end - end - end - end - - return TaylorInterpolantNSerialization{T}(vars, order, varorder, dims, eph.t0, eph.t, x) -end - -# Convert method to read .jld2 files -function convert(::Type{TaylorInterpolant{T, TaylorN{T}, 2}}, eph::TaylorInterpolantNSerialization{T}) where {T} - # Variables - vars = eph.vars - # Number of variables - n = length(vars) - # Matrix dimensions - dims = eph.dims - # Number of elements in matrix - N = dims[1] * dims[2] - # Taylor1 order - order = eph.order - # Number of coefficients in each Taylor1 - k = order + 1 - # TaylorN order - varorder = eph.varorder - # Number of coefficients in each TaylorN - L = varorder + 1 - # Number of coefficients in each HomogeneousPolynomial - M = binomial(n + varorder, varorder) - # M = sum(binomial(n + i_3 - 1, i_3) for i_3 in 0:varorder) - - # Set variables - if TS.get_variable_names() != vars - TS.set_variables(T, vars, order = varorder) - end - - # Matrix of Taylor polynomials - x = Matrix{Taylor1{TaylorN{T}}}(undef, dims[1], dims[2]) - - # Reconstruct Taylor polynomials - i = 1 - # Iterate over matrix elements - for i_1 in 1:N - # Reconstruct Taylor1s - Taylor1_coeffs = Vector{TaylorN{T}}(undef, k) - for i_2 in 1:k - # Reconstruct TaylorNs - TaylorN_coeffs = Vector{HomogeneousPolynomial{T}}(undef, L) - # Reconstruct HomogeneousPolynomials - for i_3 in 0:varorder - TaylorN_coeffs[i_3 + 1] = HomogeneousPolynomial(eph.x[i : i + binomial(n + i_3 - 1, i_3)-1], i_3) - i += binomial(n + i_3 - 1, i_3) - end - Taylor1_coeffs[i_2] = TaylorN(TaylorN_coeffs, varorder) - end - x[i_1] = Taylor1{TaylorN{T}}(Taylor1_coeffs, order) - end - - return TaylorInterpolant{T, TaylorN{T}, 2}(eph.t0, eph.t, x) -end - -@doc raw""" - TaylorNSerialization{T} - -Custom serialization struct to save a `TaylorN{T}` to a `.jld2` file. - -# Fields -- `vars::Vector{String}`: jet transport variables. -- `varorder::Int`: order of jet transport perturbations. -- `x::Vector{T}`: vector of coefficients. -""" -struct TaylorNSerialization{T} - vars::Vector{String} - varorder::Int - x::Vector{T} -end - -# Tell JLD2 to save TaylorN{T} as TaylorNSerialization{T} -writeas(::Type{TaylorN{T}}) where {T} = TaylorNSerialization{T} - -# Convert method to write .jld2 files -function convert(::Type{TaylorNSerialization{T}}, eph::TaylorN{T}) where {T} - # Variables - vars = TS.get_variable_names() - # Number of variables - n = length(vars) - # TaylorN order - varorder = eph.order - # Number of coefficients in each TaylorN - L = varorder + 1 - # Number of coefficients in each HomogeneousPolynomial - M = binomial(n + varorder, varorder) - # M = sum(binomial(n + i_3 - 1, i_3) for i_3 in 0:varorder) - - # Vector of coefficients - x = Vector{T}(undef, M) - - # Save coefficients - i = 1 - for i_1 in 0:varorder - # Iterate over i_1 order HomogeneousPolynomial - for i_2 in 1:binomial(n + i_1 - 1, i_1) - x[i] = eph.coeffs[i_1+1].coeffs[i_2] - i += 1 - end - end - - return TaylorNSerialization{T}(vars, varorder, x) -end - -# Convert method to read .jld2 files -function convert(::Type{TaylorN{T}}, eph::TaylorNSerialization{T}) where {T} - # Variables - vars = eph.vars - # Number of variables - n = length(vars) - # TaylorN order - varorder = eph.varorder - # Number of coefficients in each TaylorN - L = varorder + 1 - # Number of coefficients in each HomogeneousPolynomial - M = binomial(n + varorder, varorder) - # M = sum(binomial(n + i_1 - 1, i_1) for i_1 in 0:varorder) - - # Set variables - if TS.get_variable_names() != vars - TS.set_variables(T, vars, order = varorder) - end - - # Reconstruct TaylorN - i = 1 - TaylorN_coeffs = Vector{HomogeneousPolynomial{T}}(undef, L) - for i_1 in 0:varorder - # Reconstruct HomogeneousPolynomials - TaylorN_coeffs[i_1 + 1] = HomogeneousPolynomial(eph.x[i : i + binomial(n + i_1 - 1, i_1)-1], i_1) - i += binomial(n + i_1 - 1, i_1) - end - x = TaylorN{T}(TaylorN_coeffs, varorder) - - return x +@doc raw""" + TaylorInterpolantNSerialization{T} + +Custom serialization struct to save a `TaylorInterpolant{T, TaylorN{T}, 2}` to a `.jld2` file. + +# Fields +- `vars::Vector{String}`: jet transport variables. +- `order::Int`: order of Taylor polynomials w.r.t time. +- `varorder::Int`: order of jet transport perturbations. +- `dims::Tuple{Int, Int}`: matrix dimensions. +- `t0::T`: initial time. +- `t::Vector{T}`: vector of times. +- `x::Vector{T}`: vector of coefficients. +""" +struct TaylorInterpolantNSerialization{T} + vars::Vector{String} + order::Int + varorder::Int + dims::Tuple{Int, Int} + t0::T + t::Vector{T} + x::Vector{T} +end + +# Tell JLD2 to save TaylorInterpolant{T, TaylorN{T}, 2} as TaylorInterpolantNSerialization{T} +writeas(::Type{TaylorInterpolant{T, TaylorN{T}, 2}}) where {T} = TaylorInterpolantNSerialization{T} + +# Convert method to write .jld2 files +function convert(::Type{TaylorInterpolantNSerialization{T}}, eph::TaylorInterpolant{T, TaylorN{T}, 2}) where {T} + # Variables + vars = TS.get_variable_names() + # Number of variables + n = length(vars) + # Matrix dimensions + dims = size(eph.x) + # Number of elements in matrix + N = length(eph.x) + # Taylor1 order + order = eph.x[1, 1].order + # Number of coefficients in each Taylor1 + k = order + 1 + # TaylorN order + varorder = eph.x[1, 1].coeffs[1].order + # Number of coefficients in each TaylorN + L = varorder + 1 + # Number of coefficients in each HomogeneousPolynomial + M = binomial(n + varorder, varorder) + # M = sum(binomial(n + i_3 - 1, i_3) for i_3 in 0:varorder) + + # Vector of coefficients + x = Vector{T}(undef, N * k * M) + + # Save coefficients + i = 1 + # Iterate over matrix elements + for i_1 in 1:N + # Iterate over Taylor1 coefficients + for i_2 in 1:k + # Iterate over TaylorN coefficients + for i_3 in 0:varorder + # Iterate over i_3 order HomogeneousPolynomial + for i_4 in 1:binomial(n + i_3 - 1, i_3) + x[i] = eph.x[i_1].coeffs[i_2].coeffs[i_3+1].coeffs[i_4] + i += 1 + end + end + end + end + + return TaylorInterpolantNSerialization{T}(vars, order, varorder, dims, eph.t0, eph.t, x) +end + +# Convert method to read .jld2 files +function convert(::Type{TaylorInterpolant{T, TaylorN{T}, 2}}, eph::TaylorInterpolantNSerialization{T}) where {T} + # Variables + vars = eph.vars + # Number of variables + n = length(vars) + # Matrix dimensions + dims = eph.dims + # Number of elements in matrix + N = dims[1] * dims[2] + # Taylor1 order + order = eph.order + # Number of coefficients in each Taylor1 + k = order + 1 + # TaylorN order + varorder = eph.varorder + # Number of coefficients in each TaylorN + L = varorder + 1 + # Number of coefficients in each HomogeneousPolynomial + M = binomial(n + varorder, varorder) + # M = sum(binomial(n + i_3 - 1, i_3) for i_3 in 0:varorder) + + # Set variables + if TS.get_variable_names() != vars + TS.set_variables(T, vars, order = varorder) + end + + # Matrix of Taylor polynomials + x = Matrix{Taylor1{TaylorN{T}}}(undef, dims[1], dims[2]) + + # Reconstruct Taylor polynomials + i = 1 + # Iterate over matrix elements + for i_1 in 1:N + # Reconstruct Taylor1s + Taylor1_coeffs = Vector{TaylorN{T}}(undef, k) + for i_2 in 1:k + # Reconstruct TaylorNs + TaylorN_coeffs = Vector{HomogeneousPolynomial{T}}(undef, L) + # Reconstruct HomogeneousPolynomials + for i_3 in 0:varorder + TaylorN_coeffs[i_3 + 1] = HomogeneousPolynomial(eph.x[i : i + binomial(n + i_3 - 1, i_3)-1], i_3) + i += binomial(n + i_3 - 1, i_3) + end + Taylor1_coeffs[i_2] = TaylorN(TaylorN_coeffs, varorder) + end + x[i_1] = Taylor1{TaylorN{T}}(Taylor1_coeffs, order) + end + + return TaylorInterpolant{T, TaylorN{T}, 2}(eph.t0, eph.t, x) +end + +@doc raw""" + TaylorNSerialization{T} + +Custom serialization struct to save a `TaylorN{T}` to a `.jld2` file. + +# Fields +- `vars::Vector{String}`: jet transport variables. +- `varorder::Int`: order of jet transport perturbations. +- `x::Vector{T}`: vector of coefficients. +""" +struct TaylorNSerialization{T} + vars::Vector{String} + varorder::Int + x::Vector{T} +end + +# Tell JLD2 to save TaylorN{T} as TaylorNSerialization{T} +writeas(::Type{TaylorN{T}}) where {T} = TaylorNSerialization{T} + +# Convert method to write .jld2 files +function convert(::Type{TaylorNSerialization{T}}, eph::TaylorN{T}) where {T} + # Variables + vars = TS.get_variable_names() + # Number of variables + n = length(vars) + # TaylorN order + varorder = eph.order + # Number of coefficients in each TaylorN + L = varorder + 1 + # Number of coefficients in each HomogeneousPolynomial + M = binomial(n + varorder, varorder) + # M = sum(binomial(n + i_3 - 1, i_3) for i_3 in 0:varorder) + + # Vector of coefficients + x = Vector{T}(undef, M) + + # Save coefficients + i = 1 + for i_1 in 0:varorder + # Iterate over i_1 order HomogeneousPolynomial + for i_2 in 1:binomial(n + i_1 - 1, i_1) + x[i] = eph.coeffs[i_1+1].coeffs[i_2] + i += 1 + end + end + + return TaylorNSerialization{T}(vars, varorder, x) +end + +# Convert method to read .jld2 files +function convert(::Type{TaylorN{T}}, eph::TaylorNSerialization{T}) where {T} + # Variables + vars = eph.vars + # Number of variables + n = length(vars) + # TaylorN order + varorder = eph.varorder + # Number of coefficients in each TaylorN + L = varorder + 1 + # Number of coefficients in each HomogeneousPolynomial + M = binomial(n + varorder, varorder) + # M = sum(binomial(n + i_1 - 1, i_1) for i_1 in 0:varorder) + + # Set variables + if TS.get_variable_names() != vars + TS.set_variables(T, vars, order = varorder) + end + + # Reconstruct TaylorN + i = 1 + TaylorN_coeffs = Vector{HomogeneousPolynomial{T}}(undef, L) + for i_1 in 0:varorder + # Reconstruct HomogeneousPolynomials + TaylorN_coeffs[i_1 + 1] = HomogeneousPolynomial(eph.x[i : i + binomial(n + i_1 - 1, i_1)-1], i_1) + i += binomial(n + i_1 - 1, i_1) + end + x = TaylorN{T}(TaylorN_coeffs, varorder) + + return x end \ No newline at end of file diff --git a/test/Project.toml b/test/Project.toml old mode 100644 new mode 100755 index 11d054fc..1ef28247 --- a/test/Project.toml +++ b/test/Project.toml @@ -1,16 +1,16 @@ -[deps] -DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" -Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" -DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" -Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" -InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" -JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" -LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" -Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" -PlanetaryEphemeris = "d83715d0-7e5f-11e9-1a59-4137b20d8363" -Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" -Query = "1a8c2f83-1ff3-5112-b086-8aa67b057ba1" -Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" -Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" -TaylorIntegration = "92b13dbe-c966-51a2-8445-caca9f8a7d42" -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +[deps] +DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" +Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" +InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" +JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +PlanetaryEphemeris = "d83715d0-7e5f-11e9-1a59-4137b20d8363" +Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" +Query = "1a8c2f83-1ff3-5112-b086-8aa67b057ba1" +Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" +TaylorIntegration = "92b13dbe-c966-51a2-8445-caca9f8a7d42" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/data/99942_RADAR_2005_2013.dat b/test/data/99942_RADAR_2005_2013.dat old mode 100644 new mode 100755 index 864aa630..a4e41449 --- a/test/data/99942_RADAR_2005_2013.dat +++ b/test/data/99942_RADAR_2005_2013.dat @@ -1,46 +1,46 @@ -99942 Apophis (2004 MN4) 2005-01-27 23:31:00 -100849.1434 0.250 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2005-01-29 00:00:00 192028507.13 4.000 us 2380 251 251 C -99942 Apophis (2004 MN4) 2005-01-29 00:00:00 -102512.9059 0.250 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2005-01-30 00:18:00 195808170.79 4.500 us 2380 251 251 C -99942 Apophis (2004 MN4) 2005-01-30 00:18:00 -103799.8178 0.150 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2005-08-07 17:07:00 8186.8 0.200 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2006-05-06 12:49:00 -118256.8 0.100 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2012-12-21 11:10:00 57992.443 0.250 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2012-12-22 11:00:00 57880.250 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2012-12-22 11:00:00 102682986.05 0.25 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-03 09:20:00 97449107.61 0.25 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-03 09:20:00 36629.285 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-03 10:00:00 97439308.71 3.000 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-03 10:50:00 97428425.46 0.25 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-05 08:40:00 30404.009 0.2 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-05 10:40:00 96911591.52 0.25 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-05 10:40:00 20031.160 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-05 10:50:00 96910218.03 3.000 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-06 08:20:00 26660.815 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-06 09:30:00 20775.144 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-08 08:10:00 15496.441 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-09 08:00:00 9670.119 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-09 08:00:00 96451449.73 0.2 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-09 09:20:00 2690.401 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-10 08:00:00 2590.857 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-10 08:00:00 96472652.72 0.20 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-10 09:40:00 96473924.8 0.20 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-11 07:20:00 -1589.599 0.2 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-14 08:10:00 97258343.56 0.20 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-14 08:10:00 -30561.776 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-14 09:50:00 97283037.17 0.20 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-15 06:30:00 -30666.291 0.10 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-16 06:30:00 -39582.277 0.20 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-16 06:30:00 98086754. 1.000 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-16 07:50:00 -46641.384 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-17 06:20:00 -47875.142 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-02-18 00:56:00 -76760.475 0.2 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2013-02-18 01:37:00 157906444.15 0.25 us 2380 251 251 C -99942 Apophis (2004 MN4) 2013-02-18 01:37:00 -78041.365 0.2 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2013-02-19 01:08:00 -78105.657 0.2 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2013-02-20 00:38:00 -78070.341 0.2 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2013-02-20 01:26:00 163578875.87 0.25 us 2380 251 251 C -99942 Apophis (2004 MN4) 2013-02-20 01:26:00 -79560.965 0.2 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2013-02-21 01:04:00 -79697.130 0.2 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2013-03-15 23:59:00 235220855.07 2.000 us 2380 251 251 C -99942 Apophis (2004 MN4) 2013-03-15 23:59:00 -80977.5254 0.238 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2005-01-27 23:31:00 -100849.1434 0.250 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2005-01-29 00:00:00 192028507.13 4.000 us 2380 251 251 C +99942 Apophis (2004 MN4) 2005-01-29 00:00:00 -102512.9059 0.250 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2005-01-30 00:18:00 195808170.79 4.500 us 2380 251 251 C +99942 Apophis (2004 MN4) 2005-01-30 00:18:00 -103799.8178 0.150 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2005-08-07 17:07:00 8186.8 0.200 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2006-05-06 12:49:00 -118256.8 0.100 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2012-12-21 11:10:00 57992.443 0.250 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2012-12-22 11:00:00 57880.250 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2012-12-22 11:00:00 102682986.05 0.25 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-03 09:20:00 97449107.61 0.25 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-03 09:20:00 36629.285 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-03 10:00:00 97439308.71 3.000 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-03 10:50:00 97428425.46 0.25 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-05 08:40:00 30404.009 0.2 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-05 10:40:00 96911591.52 0.25 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-05 10:40:00 20031.160 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-05 10:50:00 96910218.03 3.000 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-06 08:20:00 26660.815 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-06 09:30:00 20775.144 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-08 08:10:00 15496.441 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-09 08:00:00 9670.119 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-09 08:00:00 96451449.73 0.2 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-09 09:20:00 2690.401 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-10 08:00:00 2590.857 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-10 08:00:00 96472652.72 0.20 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-10 09:40:00 96473924.8 0.20 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-11 07:20:00 -1589.599 0.2 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-14 08:10:00 97258343.56 0.20 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-14 08:10:00 -30561.776 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-14 09:50:00 97283037.17 0.20 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-15 06:30:00 -30666.291 0.10 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-16 06:30:00 -39582.277 0.20 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-16 06:30:00 98086754. 1.000 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-16 07:50:00 -46641.384 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-17 06:20:00 -47875.142 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-02-18 00:56:00 -76760.475 0.2 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-18 01:37:00 157906444.15 0.25 us 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-18 01:37:00 -78041.365 0.2 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-19 01:08:00 -78105.657 0.2 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-20 00:38:00 -78070.341 0.2 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-20 01:26:00 163578875.87 0.25 us 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-20 01:26:00 -79560.965 0.2 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-21 01:04:00 -79697.130 0.2 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2013-03-15 23:59:00 235220855.07 2.000 us 2380 251 251 C +99942 Apophis (2004 MN4) 2013-03-15 23:59:00 -80977.5254 0.238 Hz 2380 251 251 C diff --git a/test/data/99942_Tholen_etal_2013.dat b/test/data/99942_Tholen_etal_2013.dat old mode 100644 new mode 100755 index 36b71a75..00a39394 --- a/test/data/99942_Tholen_etal_2013.dat +++ b/test/data/99942_Tholen_etal_2013.dat @@ -1,432 +1,432 @@ -99942 'C2004 06 19.17015009 44 29.677+13 18 50.67 L~09vB695 -99942 'C2004 06 19.17486109 44 30.604+13 18 46.81 L~09vB695 -99942 'C2004 06 19.17967609 44 31.507+13 18 42.91 L~09vB695 -99942 'C2004 06 20.15951409 47 41.116+13 05 24.49 L~09vB695 -99942 'C2004 06 20.16431709 47 42.006+13 05 20.50 L~09vB695 -99942 'C2004 06 20.16906309 47 42.926+13 05 16.74 L~09vB695 -99942 'C2005 07 09.17600210 34 38.149+16 12 41.50 L~09vB695 -99942 'C2005 07 09.18080710 34 38.288+16 12 42.68 L~09vB695 -99942 'C2005 07 10.17554310 35 10.909+16 18 25.82 L~09vB695 -99942 'C2005 07 10.17819210 35 10.983+16 18 26.48 L~09vB695 -99942 'C2005 07 11.16972710 35 36.698+16 24 46.68 L~09vB695 -99942 2C2005 09 04.63519408 25 00.085+22 18 13.02 L~09vB568 -99942 2C2005 09 04.63627008 25 00.075+22 18 12.36 L~09vB568 -99942 2C2005 12 31.64597612 46 28.407-11 49 33.02 L~09vB568 -99942 2C2005 12 31.64713112 46 28.583-11 49 34.23 L~09vB568 -99942 2C2005 12 31.64800212 46 28.708-11 49 35.16 L~09vB568 -99942 2C2006 03 05.54636616 20 49.786-26 34 29.32 L~09vB568 -99942 2C2006 03 05.61052316 21 07.957-26 34 51.45 L~09vB568 -99942 2C2006 03 05.65266816 21 19.828-26 35 04.75 L~09vB568 -99942 2C2006 03 06.51985316 25 39.350-26 39 07.23 L~09vB568 -99942 2C2006 03 06.52154416 25 39.838-26 39 07.85 L~09vB568 -99942 2C2006 03 06.52319016 25 40.319-26 39 08.38 L~09vB568 -99942 2C2006 03 06.52483716 25 40.802-26 39 08.75 L~09vB568 -99942 2C2006 03 06.52649816 25 41.288-26 39 09.42 L~09vB568 -99942 2C2006 03 06.53152916 25 42.744-26 39 11.09 L~09vB568 -99942 2C2006 03 06.53317516 25 43.230-26 39 11.64 L~09vB568 -99942 2C2006 03 06.53785116 25 44.576-26 39 13.17 L~09vB568 -99942 2C2006 03 06.53950516 25 45.058-26 39 13.71 L~09vB568 -99942 2C2006 03 06.54114016 25 45.528-26 39 14.25 L~09vB568 -99942 2C2006 03 06.54279516 25 46.018-26 39 14.75 L~09vB568 -99942 2C2006 03 06.54460416 25 46.542-26 39 15.35 L~09vB568 -99942 2C2006 03 06.54622816 25 47.020-26 39 15.82 L~09vB568 -99942 2C2006 03 06.54788716 25 47.487-26 39 16.37 L~09vB568 -99942 2C2006 03 06.54963916 25 48.001-26 39 16.97 L~09vB568 -99942 2C2006 03 06.55128516 25 48.473-26 39 17.49 L~09vB568 -99942 2C2006 03 06.55294416 25 48.954-26 39 18.02 L~09vB568 -99942 2C2006 03 06.58062516 25 56.956-26 39 26.69 L~09vB568 -99942 2C2006 03 06.58226716 25 57.429-26 39 27.19 L~09vB568 -99942 2C2006 03 06.58390316 25 57.889-26 39 27.56 L~09vB568 -99942 2C2006 03 06.58565516 25 58.403-26 39 28.25 L~09vB568 -99942 2C2006 03 06.58729516 25 58.884-26 39 28.74 L~09vB568 -99942 2C2006 03 06.58894616 25 59.356-26 39 29.24 L~09vB568 -99942 2C2006 03 06.59071316 25 59.860-26 39 29.79 L~09vB568 -99942 2C2006 03 06.59240616 26 00.342-26 39 30.29 L~09vB568 -99942 2C2006 03 06.59416916 26 00.854-26 39 30.79 L~09vB568 -99942 2C2006 03 06.59581316 26 01.332-26 39 31.30 L~09vB568 -99942 2C2006 03 06.59986316 26 02.494-26 39 32.45 L~09vB568 -99942 2C2006 03 06.60160616 26 02.993-26 39 33.01 L~09vB568 -99942 2C2006 03 06.60323516 26 03.457-26 39 33.48 L~09vB568 -99942 2C2006 03 06.60488216 26 03.930-26 39 34.00 L~09vB568 -99942 2C2006 03 06.60655416 26 04.414-26 39 34.45 L~09vB568 -99942 2C2006 03 06.60819916 26 04.891-26 39 34.94 L~09vB568 -99942 2C2006 03 06.60994916 26 05.388-26 39 35.44 L~09vB568 -99942 2C2006 03 06.61161916 26 05.870-26 39 35.93 L~09vB568 -99942 2C2006 03 06.61340316 26 06.381-26 39 36.46 L~09vB568 -99942 2C2006 03 06.61522116 26 06.900-26 39 36.96 L~09vB568 -99942 2C2006 03 06.61779416 26 07.648-26 39 37.74 L~09vB568 -99942 2C2006 03 06.61944816 26 08.129-26 39 38.22 L~09vB568 -99942 2C2006 03 06.62108316 26 08.593-26 39 38.68 L~09vB568 -99942 2C2006 03 06.62287816 26 09.105-26 39 39.17 L~09vB568 -99942 2C2006 03 06.62453816 26 09.584-26 39 39.65 L~09vB568 -99942 2C2006 03 06.62634316 26 10.112-26 39 40.15 L~09vB568 -99942 2C2006 03 06.62962316 26 11.039-26 39 41.09 L~09vB568 -99942 2C2006 03 06.63137516 26 11.530-26 39 41.57 L~09vB568 -99942 2C2006 03 06.63303116 26 12.016-26 39 42.05 L~09vB568 -99942 2C2006 03 06.63501716 26 12.589-26 39 42.58 L~09vB568 -99942 2C2006 03 06.63831016 26 13.532-26 39 43.51 L~09vB568 -99942 2C2006 03 06.63998416 26 14.033-26 39 43.93 L~09vB568 -99942 2C2006 03 06.64177816 26 14.532-26 39 44.44 L~09vB568 -99942 2C2006 03 06.64342816 26 15.007-26 39 44.91 L~09vB568 -99942 2C2006 03 06.64522616 26 15.513-26 39 45.40 L~09vB568 -99942 2C2006 03 06.64689116 26 16.000-26 39 45.85 L~09vB568 -99942 2C2006 03 06.64869616 26 16.534-26 39 46.31 L~09vB568 -99942 2C2006 03 06.65033416 26 16.985-26 39 46.76 L~09vB568 -99942 2C2006 03 08.52450916 35 51.633-26 46 44.58 L~09vB568 -99942 2C2006 03 08.52614416 35 52.139-26 46 45.02 L~09vB568 -99942 2C2006 03 08.52778416 35 52.632-26 46 45.44 L~09vB568 -99942 2C2006 03 08.52940616 35 53.122-26 46 45.81 L~09vB568 -99942 2C2006 03 08.53118916 35 53.668-26 46 46.23 L~09vB568 -99942 2C2006 03 08.53282516 35 54.145-26 46 46.74 L~09vB568 -99942 2C2006 03 08.53446116 35 54.645-26 46 47.05 L~09vB568 -99942 2C2006 03 08.53622516 35 55.161-26 46 47.51 L~09vB568 -99942 2C2006 03 08.53952316 35 56.166-26 46 48.34 L~09vB568 -99942 2C2006 03 08.54821816 35 58.785-26 46 50.43 L~09vB568 -99942 2C2006 03 08.54987016 35 59.291-26 46 50.85 L~09vB568 -99942 2C2006 03 08.55150916 35 59.779-26 46 51.19 L~09vB568 -99942 2C2006 03 08.55327516 36 00.314-26 46 51.64 L~09vB568 -99942 2C2006 03 08.55494116 36 00.797-26 46 52.06 L~09vB568 -99942 2C2006 03 08.55657116 36 01.305-26 46 52.45 L~09vB568 -99942 2C2006 03 08.55820316 36 01.809-26 46 52.76 L~09vB568 -99942 2C2006 03 08.55999116 36 02.337-26 46 53.31 L~09vB568 -99942 2C2006 03 08.56165316 36 02.824-26 46 53.65 L~09vB568 -99942 2C2006 03 08.56331116 36 03.321-26 46 54.00 L~09vB568 -99942 2C2006 03 08.56529216 36 03.925-26 46 54.53 L~09vB568 -99942 2C2006 03 08.56705816 36 04.447-26 46 54.94 L~09vB568 -99942 2C2006 03 08.56870116 36 04.934-26 46 55.29 L~09vB568 -99942 2C2006 03 08.57034116 36 05.423-26 46 55.67 L~09vB568 -99942 2C2006 03 08.57210416 36 05.964-26 46 56.10 L~09vB568 -99942 2C2006 03 08.57374816 36 06.447-26 46 56.43 L~09vB568 -99942 2C2006 03 08.57878216 36 07.950-26 46 57.62 L~09vB568 -99942 2C2006 03 08.58043616 36 08.453-26 46 57.97 L~09vB568 -99942 2C2006 03 08.59506416 36 12.824-26 47 01.24 L~09vB568 -99942 2C2006 03 08.59679916 36 13.342-26 47 01.59 L~09vB568 -99942 2C2006 03 08.59842816 36 13.834-26 47 01.97 L~09vB568 -99942 2C2006 03 08.60007616 36 14.327-26 47 02.20 L~09vB568 -99942 2C2006 03 08.60176516 36 14.819-26 47 02.62 L~09vB568 -99942 2C2006 03 08.60342016 36 15.335-26 47 03.00 L~09vB568 -99942 2C2006 03 08.60506016 36 15.804-26 47 03.30 L~09vB568 -99942 2C2006 03 08.60672516 36 16.308-26 47 03.66 L~09vB568 -99942 2C2006 03 08.60840016 36 16.812-26 47 04.07 L~09vB568 -99942 2C2006 03 08.61019116 36 17.347-26 47 04.43 L~09vB568 -99942 2C2006 03 08.61180216 36 17.821-26 47 04.73 L~09vB568 -99942 2C2006 03 08.61356016 36 18.338-26 47 05.15 L~09vB568 -99942 2C2006 03 08.61522616 36 18.848-26 47 05.46 L~09vB568 -99942 2C2006 03 08.61702416 36 19.384-26 47 05.80 L~09vB568 -99942 2C2006 03 08.61880916 36 19.911-26 47 06.18 L~09vB568 -99942 2C2006 03 08.62044116 36 20.397-26 47 06.50 L~09vB568 -99942 2C2006 03 08.62209616 36 20.893-26 47 06.83 L~09vB568 -99942 2C2006 03 08.62373616 36 21.391-26 47 07.18 L~09vB568 -99942 2C2006 03 08.62551916 36 21.915-26 47 07.56 L~09vB568 -99942 2C2006 03 08.62716816 36 22.403-26 47 07.90 L~09vB568 -99942 2C2006 03 08.62914916 36 23.003-26 47 08.29 L~09vB568 -99942 2C2006 03 08.63083816 36 23.503-26 47 08.58 L~09vB568 -99942 2C2006 03 08.63248116 36 23.992-26 47 08.94 L~09vB568 -99942 2C2006 03 08.63410316 36 24.477-26 47 09.24 L~09vB568 -99942 2C2006 03 08.63588516 36 24.997-26 47 09.59 L~09vB568 -99942 2C2006 03 08.63752916 36 25.500-26 47 09.91 L~09vB568 -99942 2C2006 03 08.63917116 36 25.991-26 47 10.23 L~09vB568 -99942 2C2006 03 08.64083116 36 26.480-26 47 10.54 L~09vB568 -99942 2C2006 03 08.64263816 36 27.008-26 47 10.89 L~09vB568 -99942 2C2006 03 08.64430016 36 27.506-26 47 11.22 L~09vB568 -99942 2C2006 03 08.64589016 36 27.988-26 47 11.49 L~09vB568 -99942 2C2006 03 08.64751516 36 28.476-26 47 11.82 L~09vB568 -99942 2C2006 03 08.64930316 36 29.008-26 47 12.13 L~09vB568 -99942 2C2006 03 08.65095316 36 29.492-26 47 12.45 L~09vB568 -99942 2C2006 03 08.66103116 36 32.496-26 47 14.31 L~09vB568 -99942 2C2006 05 01.62736922 43 36.580-01 20 46.01 L~09vB568 -99942 2C2006 05 01.62821822 43 36.869-01 20 44.02 L~09vB568 -99942 2C2006 06 01.60681201 12 41.522+14 14 31.91 L~09vB568 -99942 2C2006 06 01.60868801 12 41.959+14 14 34.24 L~09vB568 -99942 2C2006 06 02.59935901 16 48.755+14 34 20.07 L~09vB568 -99942 2C2006 06 02.60078001 16 49.108+14 34 21.72 L~09vB568 -99942 2C2006 06 02.60224201 16 49.478+14 34 23.59 L~09vB568 -99942 2C2006 07 27.61254105 06 37.958+23 53 27.72 L~09vB568 -99942 2C2006 07 27.61447305 06 38.465+23 53 27.83 L~09vB568 -99942 2C2006 08 15.61852106 26 52.404+22 57 47.52 L~09vB568 -99942 2C2006 08 15.62233206 26 53.348+22 57 46.02 L~09vB568 -99942 2C2006 08 16.62183606 31 00.059+22 51 14.54 L~09vB568 -99942 2C2006 08 16.62441906 31 00.629+22 51 13.69 L~09vB568 -99942 2C2006 08 16.62695406 31 01.254+22 51 12.76 L~09vB568 -99942 2C2006 09 04.59915907 45 57.632+19 48 13.43 L~09vB568 -99942 2C2006 09 04.60174207 45 58.282+19 48 11.30 L~09vB568 -99942 2C2006 09 04.60702707 45 59.441+19 48 07.57 L~09vB568 -99942 2C2006 09 04.60960407 46 00.032+19 48 05.65 L~09vB568 -99942 2C2006 09 04.61217807 46 00.596+19 48 03.81 L~09vC568 -99942 2C2006 09 04.61475007 46 01.189+19 48 01.98 L~09vC568 -99942 2C2006 09 04.61733207 46 01.771+19 48 00.12 L~09vC568 -99942 2C2006 09 04.61991607 46 02.330+19 47 58.33 L~09vC568 -99942 2C2006 09 04.62259307 46 02.963+19 47 56.27 L~09vC568 -99942 2C2006 09 04.62517107 46 03.533+19 47 54.35 L~09vC568 -99942 2C2006 09 04.62774407 46 04.120+19 47 52.46 L~09vC568 -99942 2C2006 10 25.59993210 38 53.805+05 37 27.51 L~09vC568 -99942 2C2006 10 25.60369210 38 54.499+05 37 23.28 L~09vC568 -99942 2C2006 10 25.60744010 38 55.203+05 37 18.89 L~09vC568 -99942 2C2006 10 25.61132210 38 55.912+05 37 14.36 L~09vC568 -99942 2C2006 10 25.61506310 38 56.601+05 37 10.09 L~09vC568 -99942 2C2006 10 25.61879910 38 57.275+05 37 05.78 L~09vC568 -99942 2C2006 10 25.62267810 38 58.014+05 37 01.23 L~09vC568 -99942 2C2006 10 25.62640510 38 58.696+05 36 56.87 L~09vC568 -99942 2C2006 10 25.63014810 38 59.377+05 36 52.66 L~09vC568 -99942 2C2006 10 25.63403010 39 00.098+05 36 48.23 L~09vC568 -99942 2C2006 10 25.63779510 39 00.816+05 36 43.85 L~09vC568 -99942 2C2006 11 28.59593412 23 24.533-05 33 25.55 L~09vC568 -99942 2C2006 11 28.59911212 23 25.116-05 33 29.23 L~09vC568 -99942 2C2006 11 28.60196112 23 25.630-05 33 32.60 L~09vC568 -99942 2C2006 11 28.60444112 23 26.110-05 33 35.60 L~09vC568 -99942 2C2006 11 28.60694712 23 26.572-05 33 38.57 L~09vC568 -99942 2C2006 11 28.60930612 23 27.008-05 33 41.28 L~09vC568 -99942 2C2006 11 28.61175812 23 27.455-05 33 44.13 L~09vC568 -99942 2C2006 11 28.61410412 23 27.900-05 33 47.02 L~09vC568 -99942 2C2006 11 28.61644012 23 28.333-05 33 49.76 L~09vC568 -99942 2C2006 11 28.61881912 23 28.750-05 33 52.52 L~09vC568 -99942 2C2006 11 28.62122512 23 29.200-05 33 55.26 L~09vC568 -99942 2C2006 11 28.62509412 23 29.918-05 33 59.86 L~09vC568 -99942 2C2006 11 28.62744612 23 30.356-05 34 02.67 L~09vC568 -99942 2C2006 11 28.62980412 23 30.783-05 34 05.39 L~09vC568 -99942 2C2006 11 28.63229412 23 31.243-05 34 08.35 L~09vC568 -99942 2C2006 11 28.63463812 23 31.694-05 34 11.18 L~09vC568 -99942 2C2006 11 28.63699212 23 32.122-05 34 13.96 L~09vC568 -99942 2C2006 11 28.63939612 23 32.559-05 34 16.72 L~09vC568 -99942 2C2006 11 28.64191212 23 33.023-05 34 19.79 L~09vC568 -99942 2C2006 11 28.64780312 23 34.102-05 34 26.64 L~09vC568 -99942 2C2006 12 25.61583813 51 22.763-13 59 56.70 L~09vC568 -99942 2C2006 12 25.61784113 51 23.174-13 59 58.77 L~09vC568 -99942 2C2006 12 25.61998413 51 23.614-14 00 01.00 L~09vC568 -99942 2C2006 12 25.62212713 51 24.048-14 00 03.19 L~09vC568 -99942 2C2006 12 25.62426613 51 24.483-14 00 05.46 L~09vC568 -99942 2C2006 12 25.62626013 51 24.897-14 00 07.57 L~09vC568 -99942 2C2006 12 25.62826013 51 25.303-14 00 09.63 L~09vC568 -99942 2C2006 12 25.63026913 51 25.727-14 00 11.91 L~09vC568 -99942 2C2006 12 25.63226613 51 26.111-14 00 13.98 L~09vC568 -99942 2C2006 12 25.63432513 51 26.550-14 00 16.10 L~09vC568 -99942 2C2006 12 25.63633713 51 26.944-14 00 18.32 L~09vC568 -99942 2C2006 12 25.63845413 51 27.397-14 00 20.54 L~09vC568 -99942 2C2006 12 25.64046913 51 27.795-14 00 22.50 L~09vC568 -99942 2C2006 12 25.64260413 51 28.243-14 00 24.79 L~09vC568 -99942 2C2006 12 25.64459413 51 28.632-14 00 26.91 L~09vC568 -99942 2C2006 12 25.64658913 51 29.049-14 00 28.99 L~09vC568 -99942 2C2006 12 25.64859613 51 29.453-14 00 31.11 L~09vC568 -99942 2C2006 12 25.65072813 51 29.887-14 00 33.30 L~09vC568 -99942 2C2006 12 25.65277913 51 30.308-14 00 35.48 L~09vC568 -99942 2C2006 12 25.65477513 51 30.727-14 00 37.66 L~09vC568 -99942 2C2006 12 26.61927413 54 51.077-14 17 22.37 L~09vC568 -99942 2C2006 12 26.62186713 54 51.617-14 17 25.10 L~09vC568 -99942 2C2006 12 26.62443413 54 52.140-14 17 27.76 L~09vC568 -99942 2C2006 12 26.62701613 54 52.676-14 17 30.47 L~09vC568 -99942 2C2006 12 26.62959313 54 53.203-14 17 33.18 L~09vC568 -99942 2C2006 12 26.63231513 54 53.784-14 17 36.02 L~09vC568 -99942 2C2006 12 26.63489013 54 54.277-14 17 38.64 L~09vC568 -99942 2C2006 12 26.63746513 54 54.814-14 17 41.38 L~09vC568 -99942 2C2006 12 26.64003713 54 55.344-14 17 44.03 L~09vC568 -99942 2C2006 12 26.64443813 54 56.257-14 17 48.70 L~09vC568 -99942 2C2006 12 26.64702413 54 56.800-14 17 51.38 L~09vC568 -99942 2C2006 12 26.64960613 54 57.317-14 17 54.00 L~09vC568 -99942 2C2006 12 26.65233913 54 57.885-14 17 56.94 L~09vC568 -99942 2C2006 12 26.65491313 54 58.410-14 17 59.59 L~09vC568 -99942 2C2006 12 26.65764213 54 58.975-14 18 02.42 L~09vC568 -99942 2C2006 12 26.66021313 54 59.492-14 18 05.09 L~09vC568 -99942 2C2006 12 26.66295113 55 00.066-14 18 08.04 L~09vC568 -99942 2C2006 12 27.61377913 58 18.687-14 34 30.21 L~09vC568 -99942 2C2006 12 27.61612413 58 19.180-14 34 32.59 L~09vC568 -99942 2C2006 12 27.61846613 58 19.669-14 34 35.08 L~09vC568 -99942 2C2006 12 27.62092113 58 20.171-14 34 37.59 L~09vC568 -99942 2C2006 12 27.62343213 58 20.692-14 34 40.16 L~09vC568 -99942 2C2006 12 27.62813013 58 21.676-14 34 45.11 L~09vC568 -99942 2C2006 12 27.63047513 58 22.157-14 34 47.55 L~09vC568 -99942 2C2006 12 27.63283013 58 22.638-14 34 49.94 L~09vC568 -99942 2C2006 12 27.63536613 58 23.164-14 34 52.56 L~09vC568 -99942 2C2006 12 27.63772213 58 23.654-14 34 55.02 L~09vC568 -99942 2C2006 12 27.64018213 58 24.160-14 34 57.58 L~09vC568 -99942 2C2006 12 27.64251713 58 24.633-14 34 59.93 L~09vC568 -99942 2C2006 12 27.64486213 58 25.128-14 35 02.41 L~09vC568 -99942 2C2006 12 27.64733813 58 25.643-14 35 05.02 L~09vC568 -99942 2C2006 12 27.64968213 58 26.118-14 35 07.34 L~09vC568 -99942 2C2006 12 27.65219913 58 26.645-14 35 10.02 L~09vC568 -99942 2C2006 12 27.65454513 58 27.136-14 35 12.46 L~09vC568 -99942 2C2006 12 27.65693913 58 27.617-14 35 14.94 L~09vC568 -99942 2C2006 12 27.65923513 58 28.080-14 35 17.27 L~09vC568 -99942 2C2006 12 27.66161613 58 28.593-14 35 19.73 L~09vC568 -99942 2C2006 12 28.59892614 01 45.532-14 51 20.18 L~09vC568 -99942 2C2006 12 28.60127214 01 45.990-14 51 22.22 L~09vC568 -99942 2C2006 12 28.60361214 01 46.474-14 51 24.86 L~09vC568 -99942 2C2006 12 28.60595614 01 46.965-14 51 27.09 L~09vC568 -99942 2C2006 12 28.60834814 01 47.466-14 51 29.59 L~09vC568 -99942 2C2006 12 28.61068214 01 47.954-14 51 31.93 L~09vC568 -99942 2C2006 12 28.61313714 01 48.465-14 51 34.53 L~09vC568 -99942 2C2006 12 28.61548314 01 48.954-14 51 36.90 L~09vC568 -99942 2C2006 12 28.61782414 01 49.441-14 51 39.29 L~09vC568 -99942 2C2006 12 28.62048314 01 49.989-14 51 42.06 L~09vC568 -99942 2C2006 12 28.62284414 01 50.480-14 51 44.43 L~09vC568 -99942 2C2006 12 28.62521914 01 50.990-14 51 46.97 L~09vC568 -99942 2C2006 12 28.62755814 01 51.480-14 51 49.37 L~09vC568 -99942 2C2006 12 28.62989814 01 51.941-14 51 51.72 L~09vC568 -99942 2C2006 12 28.63223614 01 52.447-14 51 54.12 L~09vC568 -99942 2C2006 12 28.63472114 01 52.958-14 51 56.69 L~09vC568 -99942 2C2006 12 28.63709614 01 53.453-14 51 59.27 L~09vC568 -99942 2C2006 12 28.63958114 01 53.965-14 52 01.62 L~09vC568 -99942 2C2006 12 28.64222114 01 54.514-14 52 04.38 L~09vC568 -99942 2C2006 12 28.64470914 01 55.039-14 52 06.96 L~09vC568 -99942 2C2006 12 28.64705014 01 55.531-14 52 09.35 L~09vC568 -99942 2C2006 12 28.64938714 01 55.996-14 52 11.67 L~09vC568 -99942 2C2006 12 28.65175514 01 56.494-14 52 14.11 L~09vC568 -99942 2C2006 12 28.65410114 01 57.003-14 52 16.60 L~09vC568 -99942 2C2006 12 28.65644714 01 57.472-14 52 18.98 L~09vC568 -99942 2C2006 12 28.65879714 01 57.960-14 52 21.42 L~09vC568 -99942 2C2007 01 21.58245615 32 42.616-20 42 32.51 L~09vC568 -99942 2C2007 01 21.58477315 32 43.182-20 42 34.17 L~09vC568 -99942 2C2007 01 21.58711715 32 43.754-20 42 35.81 L~09vC568 -99942 2C2007 01 21.58959315 32 44.371-20 42 37.63 L~09vC568 -99942 2C2007 01 21.59195815 32 44.938-20 42 39.26 L~09vC568 -99942 2C2007 01 21.59430315 32 45.499-20 42 40.83 L~09vC568 -99942 2C2007 01 21.59664515 32 46.078-20 42 42.56 L~09vC568 -99942 2C2007 01 21.59911315 32 46.703-20 42 44.34 L~09vC568 -99942 2C2007 01 21.60382415 32 47.848-20 42 47.67 L~09vC568 -99942 2C2007 01 21.60630415 32 48.443-20 42 49.39 L~09vC568 -99942 2C2007 01 21.60865515 32 49.033-20 42 51.06 L~09vC568 -99942 2C2007 01 21.61111115 32 49.620-20 42 52.79 L~09vC568 -99942 2C2007 01 21.61348815 32 50.198-20 42 54.45 L~09vC568 -99942 2C2007 01 21.61596315 32 50.816-20 42 56.26 L~09vC568 -99942 2C2007 01 21.61830115 32 51.395-20 42 57.88 L~09vC568 -99942 2C2007 01 21.62065315 32 51.961-20 42 59.57 L~09vC568 -99942 2C2007 01 21.62537515 32 53.108-20 43 02.86 L~09vC568 -99942 2C2007 01 21.63384715 32 55.168-20 43 08.85 L~09vC568 -99942 2C2007 01 21.63855815 32 56.312-20 43 12.14 L~09vC568 -99942 2C2007 01 21.64091415 32 56.911-20 43 13.89 L~09vC568 -99942 2C2007 01 21.64325715 32 57.478-20 43 15.48 L~09vC568 -99942 2C2007 01 21.65294215 32 59.821-20 43 22.32 L~09vC568 -99942 2C2007 01 21.65549215 33 00.470-20 43 24.16 L~09vC568 -99942 2C2007 01 21.65785015 33 01.030-20 43 25.75 L~09vC568 -99942 2C2007 01 21.66020015 33 01.605-20 43 27.43 L~09vC568 -99942 2C2007 01 21.66256215 33 02.171-20 43 29.04 L~09vC568 -99942 2C2007 01 21.66506015 33 02.793-20 43 30.82 L~09vC568 -99942 2C2007 01 21.66740615 33 03.361-20 43 32.52 L~09vC568 -99942 2C2007 01 21.66975715 33 03.947-20 43 34.16 L~09vC568 -99942 2C2007 01 22.57214015 36 47.728-20 53 51.02 L~09vC568 -99942 2C2007 01 22.57654615 36 48.815-20 53 53.82 L~09vC568 -99942 2C2007 01 22.58476015 36 50.845-20 53 59.54 L~09vC568 -99942 2C2007 01 22.58756915 36 51.544-20 54 01.48 L~09vC568 -99942 2C2007 01 22.59237415 36 52.723-20 54 04.90 L~09vC568 -99942 2C2007 01 22.59473715 36 53.296-20 54 06.42 L~09vC568 -99942 2C2007 01 22.59708115 36 53.865-20 54 07.99 L~09vC568 -99942 2C2007 01 22.59954915 36 54.479-20 54 09.82 L~09vC568 -99942 2C2007 01 22.60189015 36 55.064-20 54 11.36 L~09vC568 -99942 2C2007 01 22.60423615 36 55.637-20 54 12.96 L~09vC568 -99942 2C2007 01 22.60669315 36 56.236-20 54 14.69 L~09vC568 -99942 2C2007 01 22.60915215 36 56.845-20 54 16.36 L~09vC568 -99942 2C2007 01 22.61163715 36 57.473-20 54 18.12 L~09vC568 -99942 2C2007 01 22.61397715 36 58.034-20 54 19.83 L~09vC568 -99942 2C2007 01 22.61632415 36 58.619-20 54 21.25 L~09vC568 -99942 2C2007 01 22.61878615 36 59.210-20 54 22.97 L~09vC568 -99942 2C2007 01 22.62113415 36 59.808-20 54 24.59 L~09vC568 -99942 2C2007 01 22.62347015 37 00.364-20 54 26.20 L~09vC568 -99942 2C2007 01 22.62593415 37 00.969-20 54 27.89 L~09vC568 -99942 2C2007 01 22.62827215 37 01.551-20 54 29.50 L~09vC568 -99942 2C2007 01 22.63124215 37 02.296-20 54 31.56 L~09vC568 -99942 2C2007 01 22.63360515 37 02.858-20 54 33.24 L~09vC568 -99942 2C2007 01 22.63609015 37 03.468-20 54 34.88 L~09vC568 -99942 2C2007 01 22.63845815 37 04.044-20 54 36.49 L~09vC568 -99942 2C2007 01 22.64095315 37 04.663-20 54 38.24 L~09vC568 -99942 2C2007 01 22.64329615 37 05.241-20 54 39.79 L~09vC568 -99942 2C2007 01 22.64563215 37 05.805-20 54 41.42 L~09vC568 -99942 2C2007 01 22.64797215 37 06.399-20 54 43.05 L~09vC568 -99942 2C2007 01 22.65031215 37 06.975-20 54 44.58 L~09vC568 -99942 2C2007 01 22.65520515 37 08.177-20 54 48.01 L~09vC568 -99942 2C2007 01 22.65766615 37 08.765-20 54 49.68 L~09vC568 -99942 2C2007 01 22.66000615 37 09.346-20 54 51.23 L~09vC568 -99942 2C2007 01 22.66233915 37 09.914-20 54 52.83 L~09vC568 -99942 2C2007 01 24.57992215 45 10.267-21 15 47.20 L~09vC568 -99942 2C2007 01 24.58237315 45 10.845-21 15 48.76 L~09vC568 -99942 2C2007 01 24.58473515 45 11.459-21 15 50.79 L~09vC568 -99942 2C2007 01 24.58708115 45 12.051-21 15 52.00 L~09vC568 -99942 2C2007 01 24.58943115 45 12.639-21 15 53.62 L~09vC568 -99942 2C2007 01 24.59180315 45 13.201-21 15 55.01 L~09vC568 -99942 2C2007 01 24.59415315 45 13.810-21 15 56.62 L~09vC568 -99942 2C2007 01 24.59649815 45 14.398-21 15 58.15 L~09vC568 -99942 2C2007 01 24.59884615 45 14.981-21 15 59.67 L~09vC568 -99942 2C2007 01 24.60130815 45 15.601-21 16 01.20 L~09vC568 -99942 2C2007 01 24.60397015 45 16.258-21 16 02.96 L~09vC568 -99942 2C2007 01 24.60631615 45 16.864-21 16 04.53 L~09vC568 -99942 2C2007 01 24.60865915 45 17.437-21 16 06.03 L~09vC568 -99942 2C2007 01 24.61100715 45 18.015-21 16 07.64 L~09vC568 -99942 2C2007 01 24.61337815 45 18.617-21 16 09.04 L~09vC568 -99942 2C2007 01 24.61572015 45 19.205-21 16 10.60 L~09vC568 -99942 2C2007 01 24.61806315 45 19.787-21 16 12.11 L~09vC568 -99942 2C2007 01 24.62052215 45 20.394-21 16 13.80 L~09vC568 -99942 2C2007 01 24.62288015 45 20.996-21 16 15.28 L~09vC568 -99942 2C2007 01 24.62536915 45 21.610-21 16 16.86 L~09vC568 -99942 2C2007 01 24.62770915 45 22.184-21 16 18.37 L~09vC568 -99942 2C2007 01 24.63004715 45 22.784-21 16 19.89 L~09vC568 -99942 2C2007 01 24.63253115 45 23.400-21 16 21.47 L~09vC568 -99942 2C2007 01 24.63488415 45 23.956-21 16 22.98 L~09vC568 -99942 2C2007 01 24.63722615 45 24.576-21 16 24.46 L~09vC568 -99942 2C2007 01 24.63968615 45 25.180-21 16 26.08 L~09vC568 -99942 2C2007 01 24.64206015 45 25.765-21 16 27.61 L~09vC568 -99942 2C2007 01 24.64453715 45 26.385-21 16 29.24 L~09vC568 -99942 2C2007 01 24.64749315 45 27.120-21 16 31.13 L~09vC568 -99942 2C2007 01 24.64984515 45 27.716-21 16 32.67 L~09vD568 -99942 2C2007 01 24.65218915 45 28.295-21 16 34.14 L~09vD568 -99942 2C2007 01 24.65453715 45 28.875-21 16 35.68 L~09vD568 -99942 2C2007 01 24.65700115 45 29.476-21 16 37.24 L~09vD568 -99942 2C2007 01 24.65933815 45 30.069-21 16 38.76 L~09vD568 -99942 2C2007 01 24.66186915 45 30.702-21 16 40.35 L~09vD568 -99942 2C2007 01 24.66421415 45 31.282-21 16 41.89 L~09vD568 -99942 2C2007 01 24.66673715 45 31.913-21 16 43.52 L~09vD568 -99942 2C2007 01 24.66915915 45 32.521-21 16 45.04 L~09vD568 -99942 2C2007 01 25.57819315 49 22.787-21 26 10.76 L~09vD568 -99942 2C2007 01 25.58054715 49 23.382-21 26 12.24 L~09vD568 -99942 2C2007 01 25.58288715 49 24.005-21 26 13.93 L~09vD568 -99942 2C2007 01 25.58538115 49 24.619-21 26 15.27 L~09vD568 -99942 2C2007 01 25.58871815 49 25.448-21 26 17.35 L~09vD568 -99942 2C2007 01 25.59107515 49 26.056-21 26 18.94 L~09vD568 -99942 2C2007 01 25.59341915 49 26.638-21 26 20.34 L~09vD568 -99942 2C2007 01 25.59578215 49 27.232-21 26 21.81 L~09vD568 -99942 2C2007 01 25.59814815 49 27.836-21 26 23.28 L~09vD568 -99942 2C2007 01 25.60048815 49 28.426-21 26 24.78 L~09vD568 -99942 2C2007 01 25.60298015 49 29.040-21 26 26.32 L~09vD568 -99942 2C2007 01 25.60533815 49 29.635-21 26 27.79 L~09vD568 -99942 2C2007 01 25.60768815 49 30.217-21 26 29.23 L~09vD568 -99942 2C2007 01 25.61044415 49 30.921-21 26 30.98 L~09vD568 -99942 2C2007 01 25.61280315 49 31.515-21 26 32.50 L~09vD568 -99942 2C2007 01 25.61514615 49 32.099-21 26 33.92 L~09vD568 -99942 2C2007 01 25.61763015 49 32.743-21 26 35.57 L~09vD568 -99942 2C2007 01 25.62004115 49 33.333-21 26 37.04 L~09vD568 -99942 2C2007 01 25.62238915 49 33.920-21 26 38.54 L~09vD568 -99942 2C2007 01 25.62486615 49 34.551-21 26 40.09 L~09vD568 -99942 2C2007 01 25.62721115 49 35.141-21 26 41.54 L~09vD568 -99942 2C2007 01 25.62955615 49 35.721-21 26 42.96 L~09vD568 -99942 2C2007 01 25.63218615 49 36.378-21 26 44.65 L~09vD568 -99942 2C2007 01 25.63452915 49 36.980-21 26 46.10 L~09vD568 -99942 2C2007 01 25.63686715 49 37.574-21 26 47.55 L~09vD568 -99942 2C2007 01 25.63935415 49 38.186-21 26 49.11 L~09vD568 -99942 2C2007 01 25.64171915 49 38.758-21 26 50.54 L~09vD568 -99942 2C2007 01 25.64421215 49 39.407-21 26 52.14 L~09vD568 -99942 2C2007 01 25.64655615 49 39.998-21 26 53.60 L~09vD568 -99942 2C2007 01 25.64907615 49 40.623-21 26 54.91 L~09vD568 -99942 2C2007 03 09.65417619 16 36.695-21 11 06.90 L~09vD568 -99942 2C2007 03 09.65641119 16 37.371-21 11 04.96 L~09vD568 -99942 2C2007 12 13.66071314 26 35.206-15 26 51.52 L~09vD568 -99942 2C2008 01 06.63895716 03 51.245-20 51 51.34 L~09vD568 -99942 2C2008 01 06.64603616 03 53.080-20 51 55.60 L~09vD568 -99942 2C2008 01 06.64949016 03 53.986-20 51 57.69 L~09vD568 -99942 2C2008 01 06.65292016 03 54.887-20 51 59.83 L~09vD568 -99942 2C2008 01 06.65654416 03 55.801-20 52 01.94 L~09vD568 -99942 2C2008 01 06.66000516 03 56.765-20 52 04.16 L~09vD568 -99942 2C2008 01 06.66349216 03 57.618-20 52 06.04 L~09vD568 -99942 2C2008 01 07.64179316 08 14.721-21 01 32.09 L~09vD568 -99942 2C2008 01 07.64518616 08 15.608-21 01 33.99 L~09vD568 -99942 2C2008 01 07.65285816 08 17.617-21 01 38.46 L~09vD568 -99942 2C2008 01 07.65670716 08 18.608-21 01 40.57 L~09vD568 -99942 2C2008 01 08.65407416 12 42.234-21 10 54.03 L~09vD568 -99942 2C2008 01 08.65691716 12 42.968-21 10 55.80 L~09vD568 -99942 2C2008 01 08.65923516 12 43.584-21 10 56.95 L~09vD568 -99942 2C2008 01 08.66382416 12 44.803-21 10 59.64 L~09vD568 -99942 2C2008 01 08.66575916 12 45.323-21 11 00.64 L~09vD568 -99942 2C2008 01 09.64923016 17 06.855-21 19 43.21 L~09vD568 -99942 2C2008 01 09.65116616 17 07.315-21 19 44.16 L~09vD568 -99942 2C2008 01 09.65314116 17 07.868-21 19 45.05 L~09vD568 -99942 2C2008 01 09.65508216 17 08.370-21 19 46.22 L~09vD568 -99942 2C2008 01 09.65908916 17 09.415-21 19 48.28 L~09vD568 -99942 2C2008 01 09.66102716 17 09.953-21 19 49.41 L~09vD568 -99942 2C2008 01 09.66312516 17 10.506-21 19 50.39 L~09vD568 -99942 2C2008 01 09.66508816 17 11.010-21 19 51.46 L~09vD568 +99942 'C2004 06 19.17015009 44 29.677+13 18 50.67 L~09vB695 +99942 'C2004 06 19.17486109 44 30.604+13 18 46.81 L~09vB695 +99942 'C2004 06 19.17967609 44 31.507+13 18 42.91 L~09vB695 +99942 'C2004 06 20.15951409 47 41.116+13 05 24.49 L~09vB695 +99942 'C2004 06 20.16431709 47 42.006+13 05 20.50 L~09vB695 +99942 'C2004 06 20.16906309 47 42.926+13 05 16.74 L~09vB695 +99942 'C2005 07 09.17600210 34 38.149+16 12 41.50 L~09vB695 +99942 'C2005 07 09.18080710 34 38.288+16 12 42.68 L~09vB695 +99942 'C2005 07 10.17554310 35 10.909+16 18 25.82 L~09vB695 +99942 'C2005 07 10.17819210 35 10.983+16 18 26.48 L~09vB695 +99942 'C2005 07 11.16972710 35 36.698+16 24 46.68 L~09vB695 +99942 2C2005 09 04.63519408 25 00.085+22 18 13.02 L~09vB568 +99942 2C2005 09 04.63627008 25 00.075+22 18 12.36 L~09vB568 +99942 2C2005 12 31.64597612 46 28.407-11 49 33.02 L~09vB568 +99942 2C2005 12 31.64713112 46 28.583-11 49 34.23 L~09vB568 +99942 2C2005 12 31.64800212 46 28.708-11 49 35.16 L~09vB568 +99942 2C2006 03 05.54636616 20 49.786-26 34 29.32 L~09vB568 +99942 2C2006 03 05.61052316 21 07.957-26 34 51.45 L~09vB568 +99942 2C2006 03 05.65266816 21 19.828-26 35 04.75 L~09vB568 +99942 2C2006 03 06.51985316 25 39.350-26 39 07.23 L~09vB568 +99942 2C2006 03 06.52154416 25 39.838-26 39 07.85 L~09vB568 +99942 2C2006 03 06.52319016 25 40.319-26 39 08.38 L~09vB568 +99942 2C2006 03 06.52483716 25 40.802-26 39 08.75 L~09vB568 +99942 2C2006 03 06.52649816 25 41.288-26 39 09.42 L~09vB568 +99942 2C2006 03 06.53152916 25 42.744-26 39 11.09 L~09vB568 +99942 2C2006 03 06.53317516 25 43.230-26 39 11.64 L~09vB568 +99942 2C2006 03 06.53785116 25 44.576-26 39 13.17 L~09vB568 +99942 2C2006 03 06.53950516 25 45.058-26 39 13.71 L~09vB568 +99942 2C2006 03 06.54114016 25 45.528-26 39 14.25 L~09vB568 +99942 2C2006 03 06.54279516 25 46.018-26 39 14.75 L~09vB568 +99942 2C2006 03 06.54460416 25 46.542-26 39 15.35 L~09vB568 +99942 2C2006 03 06.54622816 25 47.020-26 39 15.82 L~09vB568 +99942 2C2006 03 06.54788716 25 47.487-26 39 16.37 L~09vB568 +99942 2C2006 03 06.54963916 25 48.001-26 39 16.97 L~09vB568 +99942 2C2006 03 06.55128516 25 48.473-26 39 17.49 L~09vB568 +99942 2C2006 03 06.55294416 25 48.954-26 39 18.02 L~09vB568 +99942 2C2006 03 06.58062516 25 56.956-26 39 26.69 L~09vB568 +99942 2C2006 03 06.58226716 25 57.429-26 39 27.19 L~09vB568 +99942 2C2006 03 06.58390316 25 57.889-26 39 27.56 L~09vB568 +99942 2C2006 03 06.58565516 25 58.403-26 39 28.25 L~09vB568 +99942 2C2006 03 06.58729516 25 58.884-26 39 28.74 L~09vB568 +99942 2C2006 03 06.58894616 25 59.356-26 39 29.24 L~09vB568 +99942 2C2006 03 06.59071316 25 59.860-26 39 29.79 L~09vB568 +99942 2C2006 03 06.59240616 26 00.342-26 39 30.29 L~09vB568 +99942 2C2006 03 06.59416916 26 00.854-26 39 30.79 L~09vB568 +99942 2C2006 03 06.59581316 26 01.332-26 39 31.30 L~09vB568 +99942 2C2006 03 06.59986316 26 02.494-26 39 32.45 L~09vB568 +99942 2C2006 03 06.60160616 26 02.993-26 39 33.01 L~09vB568 +99942 2C2006 03 06.60323516 26 03.457-26 39 33.48 L~09vB568 +99942 2C2006 03 06.60488216 26 03.930-26 39 34.00 L~09vB568 +99942 2C2006 03 06.60655416 26 04.414-26 39 34.45 L~09vB568 +99942 2C2006 03 06.60819916 26 04.891-26 39 34.94 L~09vB568 +99942 2C2006 03 06.60994916 26 05.388-26 39 35.44 L~09vB568 +99942 2C2006 03 06.61161916 26 05.870-26 39 35.93 L~09vB568 +99942 2C2006 03 06.61340316 26 06.381-26 39 36.46 L~09vB568 +99942 2C2006 03 06.61522116 26 06.900-26 39 36.96 L~09vB568 +99942 2C2006 03 06.61779416 26 07.648-26 39 37.74 L~09vB568 +99942 2C2006 03 06.61944816 26 08.129-26 39 38.22 L~09vB568 +99942 2C2006 03 06.62108316 26 08.593-26 39 38.68 L~09vB568 +99942 2C2006 03 06.62287816 26 09.105-26 39 39.17 L~09vB568 +99942 2C2006 03 06.62453816 26 09.584-26 39 39.65 L~09vB568 +99942 2C2006 03 06.62634316 26 10.112-26 39 40.15 L~09vB568 +99942 2C2006 03 06.62962316 26 11.039-26 39 41.09 L~09vB568 +99942 2C2006 03 06.63137516 26 11.530-26 39 41.57 L~09vB568 +99942 2C2006 03 06.63303116 26 12.016-26 39 42.05 L~09vB568 +99942 2C2006 03 06.63501716 26 12.589-26 39 42.58 L~09vB568 +99942 2C2006 03 06.63831016 26 13.532-26 39 43.51 L~09vB568 +99942 2C2006 03 06.63998416 26 14.033-26 39 43.93 L~09vB568 +99942 2C2006 03 06.64177816 26 14.532-26 39 44.44 L~09vB568 +99942 2C2006 03 06.64342816 26 15.007-26 39 44.91 L~09vB568 +99942 2C2006 03 06.64522616 26 15.513-26 39 45.40 L~09vB568 +99942 2C2006 03 06.64689116 26 16.000-26 39 45.85 L~09vB568 +99942 2C2006 03 06.64869616 26 16.534-26 39 46.31 L~09vB568 +99942 2C2006 03 06.65033416 26 16.985-26 39 46.76 L~09vB568 +99942 2C2006 03 08.52450916 35 51.633-26 46 44.58 L~09vB568 +99942 2C2006 03 08.52614416 35 52.139-26 46 45.02 L~09vB568 +99942 2C2006 03 08.52778416 35 52.632-26 46 45.44 L~09vB568 +99942 2C2006 03 08.52940616 35 53.122-26 46 45.81 L~09vB568 +99942 2C2006 03 08.53118916 35 53.668-26 46 46.23 L~09vB568 +99942 2C2006 03 08.53282516 35 54.145-26 46 46.74 L~09vB568 +99942 2C2006 03 08.53446116 35 54.645-26 46 47.05 L~09vB568 +99942 2C2006 03 08.53622516 35 55.161-26 46 47.51 L~09vB568 +99942 2C2006 03 08.53952316 35 56.166-26 46 48.34 L~09vB568 +99942 2C2006 03 08.54821816 35 58.785-26 46 50.43 L~09vB568 +99942 2C2006 03 08.54987016 35 59.291-26 46 50.85 L~09vB568 +99942 2C2006 03 08.55150916 35 59.779-26 46 51.19 L~09vB568 +99942 2C2006 03 08.55327516 36 00.314-26 46 51.64 L~09vB568 +99942 2C2006 03 08.55494116 36 00.797-26 46 52.06 L~09vB568 +99942 2C2006 03 08.55657116 36 01.305-26 46 52.45 L~09vB568 +99942 2C2006 03 08.55820316 36 01.809-26 46 52.76 L~09vB568 +99942 2C2006 03 08.55999116 36 02.337-26 46 53.31 L~09vB568 +99942 2C2006 03 08.56165316 36 02.824-26 46 53.65 L~09vB568 +99942 2C2006 03 08.56331116 36 03.321-26 46 54.00 L~09vB568 +99942 2C2006 03 08.56529216 36 03.925-26 46 54.53 L~09vB568 +99942 2C2006 03 08.56705816 36 04.447-26 46 54.94 L~09vB568 +99942 2C2006 03 08.56870116 36 04.934-26 46 55.29 L~09vB568 +99942 2C2006 03 08.57034116 36 05.423-26 46 55.67 L~09vB568 +99942 2C2006 03 08.57210416 36 05.964-26 46 56.10 L~09vB568 +99942 2C2006 03 08.57374816 36 06.447-26 46 56.43 L~09vB568 +99942 2C2006 03 08.57878216 36 07.950-26 46 57.62 L~09vB568 +99942 2C2006 03 08.58043616 36 08.453-26 46 57.97 L~09vB568 +99942 2C2006 03 08.59506416 36 12.824-26 47 01.24 L~09vB568 +99942 2C2006 03 08.59679916 36 13.342-26 47 01.59 L~09vB568 +99942 2C2006 03 08.59842816 36 13.834-26 47 01.97 L~09vB568 +99942 2C2006 03 08.60007616 36 14.327-26 47 02.20 L~09vB568 +99942 2C2006 03 08.60176516 36 14.819-26 47 02.62 L~09vB568 +99942 2C2006 03 08.60342016 36 15.335-26 47 03.00 L~09vB568 +99942 2C2006 03 08.60506016 36 15.804-26 47 03.30 L~09vB568 +99942 2C2006 03 08.60672516 36 16.308-26 47 03.66 L~09vB568 +99942 2C2006 03 08.60840016 36 16.812-26 47 04.07 L~09vB568 +99942 2C2006 03 08.61019116 36 17.347-26 47 04.43 L~09vB568 +99942 2C2006 03 08.61180216 36 17.821-26 47 04.73 L~09vB568 +99942 2C2006 03 08.61356016 36 18.338-26 47 05.15 L~09vB568 +99942 2C2006 03 08.61522616 36 18.848-26 47 05.46 L~09vB568 +99942 2C2006 03 08.61702416 36 19.384-26 47 05.80 L~09vB568 +99942 2C2006 03 08.61880916 36 19.911-26 47 06.18 L~09vB568 +99942 2C2006 03 08.62044116 36 20.397-26 47 06.50 L~09vB568 +99942 2C2006 03 08.62209616 36 20.893-26 47 06.83 L~09vB568 +99942 2C2006 03 08.62373616 36 21.391-26 47 07.18 L~09vB568 +99942 2C2006 03 08.62551916 36 21.915-26 47 07.56 L~09vB568 +99942 2C2006 03 08.62716816 36 22.403-26 47 07.90 L~09vB568 +99942 2C2006 03 08.62914916 36 23.003-26 47 08.29 L~09vB568 +99942 2C2006 03 08.63083816 36 23.503-26 47 08.58 L~09vB568 +99942 2C2006 03 08.63248116 36 23.992-26 47 08.94 L~09vB568 +99942 2C2006 03 08.63410316 36 24.477-26 47 09.24 L~09vB568 +99942 2C2006 03 08.63588516 36 24.997-26 47 09.59 L~09vB568 +99942 2C2006 03 08.63752916 36 25.500-26 47 09.91 L~09vB568 +99942 2C2006 03 08.63917116 36 25.991-26 47 10.23 L~09vB568 +99942 2C2006 03 08.64083116 36 26.480-26 47 10.54 L~09vB568 +99942 2C2006 03 08.64263816 36 27.008-26 47 10.89 L~09vB568 +99942 2C2006 03 08.64430016 36 27.506-26 47 11.22 L~09vB568 +99942 2C2006 03 08.64589016 36 27.988-26 47 11.49 L~09vB568 +99942 2C2006 03 08.64751516 36 28.476-26 47 11.82 L~09vB568 +99942 2C2006 03 08.64930316 36 29.008-26 47 12.13 L~09vB568 +99942 2C2006 03 08.65095316 36 29.492-26 47 12.45 L~09vB568 +99942 2C2006 03 08.66103116 36 32.496-26 47 14.31 L~09vB568 +99942 2C2006 05 01.62736922 43 36.580-01 20 46.01 L~09vB568 +99942 2C2006 05 01.62821822 43 36.869-01 20 44.02 L~09vB568 +99942 2C2006 06 01.60681201 12 41.522+14 14 31.91 L~09vB568 +99942 2C2006 06 01.60868801 12 41.959+14 14 34.24 L~09vB568 +99942 2C2006 06 02.59935901 16 48.755+14 34 20.07 L~09vB568 +99942 2C2006 06 02.60078001 16 49.108+14 34 21.72 L~09vB568 +99942 2C2006 06 02.60224201 16 49.478+14 34 23.59 L~09vB568 +99942 2C2006 07 27.61254105 06 37.958+23 53 27.72 L~09vB568 +99942 2C2006 07 27.61447305 06 38.465+23 53 27.83 L~09vB568 +99942 2C2006 08 15.61852106 26 52.404+22 57 47.52 L~09vB568 +99942 2C2006 08 15.62233206 26 53.348+22 57 46.02 L~09vB568 +99942 2C2006 08 16.62183606 31 00.059+22 51 14.54 L~09vB568 +99942 2C2006 08 16.62441906 31 00.629+22 51 13.69 L~09vB568 +99942 2C2006 08 16.62695406 31 01.254+22 51 12.76 L~09vB568 +99942 2C2006 09 04.59915907 45 57.632+19 48 13.43 L~09vB568 +99942 2C2006 09 04.60174207 45 58.282+19 48 11.30 L~09vB568 +99942 2C2006 09 04.60702707 45 59.441+19 48 07.57 L~09vB568 +99942 2C2006 09 04.60960407 46 00.032+19 48 05.65 L~09vB568 +99942 2C2006 09 04.61217807 46 00.596+19 48 03.81 L~09vC568 +99942 2C2006 09 04.61475007 46 01.189+19 48 01.98 L~09vC568 +99942 2C2006 09 04.61733207 46 01.771+19 48 00.12 L~09vC568 +99942 2C2006 09 04.61991607 46 02.330+19 47 58.33 L~09vC568 +99942 2C2006 09 04.62259307 46 02.963+19 47 56.27 L~09vC568 +99942 2C2006 09 04.62517107 46 03.533+19 47 54.35 L~09vC568 +99942 2C2006 09 04.62774407 46 04.120+19 47 52.46 L~09vC568 +99942 2C2006 10 25.59993210 38 53.805+05 37 27.51 L~09vC568 +99942 2C2006 10 25.60369210 38 54.499+05 37 23.28 L~09vC568 +99942 2C2006 10 25.60744010 38 55.203+05 37 18.89 L~09vC568 +99942 2C2006 10 25.61132210 38 55.912+05 37 14.36 L~09vC568 +99942 2C2006 10 25.61506310 38 56.601+05 37 10.09 L~09vC568 +99942 2C2006 10 25.61879910 38 57.275+05 37 05.78 L~09vC568 +99942 2C2006 10 25.62267810 38 58.014+05 37 01.23 L~09vC568 +99942 2C2006 10 25.62640510 38 58.696+05 36 56.87 L~09vC568 +99942 2C2006 10 25.63014810 38 59.377+05 36 52.66 L~09vC568 +99942 2C2006 10 25.63403010 39 00.098+05 36 48.23 L~09vC568 +99942 2C2006 10 25.63779510 39 00.816+05 36 43.85 L~09vC568 +99942 2C2006 11 28.59593412 23 24.533-05 33 25.55 L~09vC568 +99942 2C2006 11 28.59911212 23 25.116-05 33 29.23 L~09vC568 +99942 2C2006 11 28.60196112 23 25.630-05 33 32.60 L~09vC568 +99942 2C2006 11 28.60444112 23 26.110-05 33 35.60 L~09vC568 +99942 2C2006 11 28.60694712 23 26.572-05 33 38.57 L~09vC568 +99942 2C2006 11 28.60930612 23 27.008-05 33 41.28 L~09vC568 +99942 2C2006 11 28.61175812 23 27.455-05 33 44.13 L~09vC568 +99942 2C2006 11 28.61410412 23 27.900-05 33 47.02 L~09vC568 +99942 2C2006 11 28.61644012 23 28.333-05 33 49.76 L~09vC568 +99942 2C2006 11 28.61881912 23 28.750-05 33 52.52 L~09vC568 +99942 2C2006 11 28.62122512 23 29.200-05 33 55.26 L~09vC568 +99942 2C2006 11 28.62509412 23 29.918-05 33 59.86 L~09vC568 +99942 2C2006 11 28.62744612 23 30.356-05 34 02.67 L~09vC568 +99942 2C2006 11 28.62980412 23 30.783-05 34 05.39 L~09vC568 +99942 2C2006 11 28.63229412 23 31.243-05 34 08.35 L~09vC568 +99942 2C2006 11 28.63463812 23 31.694-05 34 11.18 L~09vC568 +99942 2C2006 11 28.63699212 23 32.122-05 34 13.96 L~09vC568 +99942 2C2006 11 28.63939612 23 32.559-05 34 16.72 L~09vC568 +99942 2C2006 11 28.64191212 23 33.023-05 34 19.79 L~09vC568 +99942 2C2006 11 28.64780312 23 34.102-05 34 26.64 L~09vC568 +99942 2C2006 12 25.61583813 51 22.763-13 59 56.70 L~09vC568 +99942 2C2006 12 25.61784113 51 23.174-13 59 58.77 L~09vC568 +99942 2C2006 12 25.61998413 51 23.614-14 00 01.00 L~09vC568 +99942 2C2006 12 25.62212713 51 24.048-14 00 03.19 L~09vC568 +99942 2C2006 12 25.62426613 51 24.483-14 00 05.46 L~09vC568 +99942 2C2006 12 25.62626013 51 24.897-14 00 07.57 L~09vC568 +99942 2C2006 12 25.62826013 51 25.303-14 00 09.63 L~09vC568 +99942 2C2006 12 25.63026913 51 25.727-14 00 11.91 L~09vC568 +99942 2C2006 12 25.63226613 51 26.111-14 00 13.98 L~09vC568 +99942 2C2006 12 25.63432513 51 26.550-14 00 16.10 L~09vC568 +99942 2C2006 12 25.63633713 51 26.944-14 00 18.32 L~09vC568 +99942 2C2006 12 25.63845413 51 27.397-14 00 20.54 L~09vC568 +99942 2C2006 12 25.64046913 51 27.795-14 00 22.50 L~09vC568 +99942 2C2006 12 25.64260413 51 28.243-14 00 24.79 L~09vC568 +99942 2C2006 12 25.64459413 51 28.632-14 00 26.91 L~09vC568 +99942 2C2006 12 25.64658913 51 29.049-14 00 28.99 L~09vC568 +99942 2C2006 12 25.64859613 51 29.453-14 00 31.11 L~09vC568 +99942 2C2006 12 25.65072813 51 29.887-14 00 33.30 L~09vC568 +99942 2C2006 12 25.65277913 51 30.308-14 00 35.48 L~09vC568 +99942 2C2006 12 25.65477513 51 30.727-14 00 37.66 L~09vC568 +99942 2C2006 12 26.61927413 54 51.077-14 17 22.37 L~09vC568 +99942 2C2006 12 26.62186713 54 51.617-14 17 25.10 L~09vC568 +99942 2C2006 12 26.62443413 54 52.140-14 17 27.76 L~09vC568 +99942 2C2006 12 26.62701613 54 52.676-14 17 30.47 L~09vC568 +99942 2C2006 12 26.62959313 54 53.203-14 17 33.18 L~09vC568 +99942 2C2006 12 26.63231513 54 53.784-14 17 36.02 L~09vC568 +99942 2C2006 12 26.63489013 54 54.277-14 17 38.64 L~09vC568 +99942 2C2006 12 26.63746513 54 54.814-14 17 41.38 L~09vC568 +99942 2C2006 12 26.64003713 54 55.344-14 17 44.03 L~09vC568 +99942 2C2006 12 26.64443813 54 56.257-14 17 48.70 L~09vC568 +99942 2C2006 12 26.64702413 54 56.800-14 17 51.38 L~09vC568 +99942 2C2006 12 26.64960613 54 57.317-14 17 54.00 L~09vC568 +99942 2C2006 12 26.65233913 54 57.885-14 17 56.94 L~09vC568 +99942 2C2006 12 26.65491313 54 58.410-14 17 59.59 L~09vC568 +99942 2C2006 12 26.65764213 54 58.975-14 18 02.42 L~09vC568 +99942 2C2006 12 26.66021313 54 59.492-14 18 05.09 L~09vC568 +99942 2C2006 12 26.66295113 55 00.066-14 18 08.04 L~09vC568 +99942 2C2006 12 27.61377913 58 18.687-14 34 30.21 L~09vC568 +99942 2C2006 12 27.61612413 58 19.180-14 34 32.59 L~09vC568 +99942 2C2006 12 27.61846613 58 19.669-14 34 35.08 L~09vC568 +99942 2C2006 12 27.62092113 58 20.171-14 34 37.59 L~09vC568 +99942 2C2006 12 27.62343213 58 20.692-14 34 40.16 L~09vC568 +99942 2C2006 12 27.62813013 58 21.676-14 34 45.11 L~09vC568 +99942 2C2006 12 27.63047513 58 22.157-14 34 47.55 L~09vC568 +99942 2C2006 12 27.63283013 58 22.638-14 34 49.94 L~09vC568 +99942 2C2006 12 27.63536613 58 23.164-14 34 52.56 L~09vC568 +99942 2C2006 12 27.63772213 58 23.654-14 34 55.02 L~09vC568 +99942 2C2006 12 27.64018213 58 24.160-14 34 57.58 L~09vC568 +99942 2C2006 12 27.64251713 58 24.633-14 34 59.93 L~09vC568 +99942 2C2006 12 27.64486213 58 25.128-14 35 02.41 L~09vC568 +99942 2C2006 12 27.64733813 58 25.643-14 35 05.02 L~09vC568 +99942 2C2006 12 27.64968213 58 26.118-14 35 07.34 L~09vC568 +99942 2C2006 12 27.65219913 58 26.645-14 35 10.02 L~09vC568 +99942 2C2006 12 27.65454513 58 27.136-14 35 12.46 L~09vC568 +99942 2C2006 12 27.65693913 58 27.617-14 35 14.94 L~09vC568 +99942 2C2006 12 27.65923513 58 28.080-14 35 17.27 L~09vC568 +99942 2C2006 12 27.66161613 58 28.593-14 35 19.73 L~09vC568 +99942 2C2006 12 28.59892614 01 45.532-14 51 20.18 L~09vC568 +99942 2C2006 12 28.60127214 01 45.990-14 51 22.22 L~09vC568 +99942 2C2006 12 28.60361214 01 46.474-14 51 24.86 L~09vC568 +99942 2C2006 12 28.60595614 01 46.965-14 51 27.09 L~09vC568 +99942 2C2006 12 28.60834814 01 47.466-14 51 29.59 L~09vC568 +99942 2C2006 12 28.61068214 01 47.954-14 51 31.93 L~09vC568 +99942 2C2006 12 28.61313714 01 48.465-14 51 34.53 L~09vC568 +99942 2C2006 12 28.61548314 01 48.954-14 51 36.90 L~09vC568 +99942 2C2006 12 28.61782414 01 49.441-14 51 39.29 L~09vC568 +99942 2C2006 12 28.62048314 01 49.989-14 51 42.06 L~09vC568 +99942 2C2006 12 28.62284414 01 50.480-14 51 44.43 L~09vC568 +99942 2C2006 12 28.62521914 01 50.990-14 51 46.97 L~09vC568 +99942 2C2006 12 28.62755814 01 51.480-14 51 49.37 L~09vC568 +99942 2C2006 12 28.62989814 01 51.941-14 51 51.72 L~09vC568 +99942 2C2006 12 28.63223614 01 52.447-14 51 54.12 L~09vC568 +99942 2C2006 12 28.63472114 01 52.958-14 51 56.69 L~09vC568 +99942 2C2006 12 28.63709614 01 53.453-14 51 59.27 L~09vC568 +99942 2C2006 12 28.63958114 01 53.965-14 52 01.62 L~09vC568 +99942 2C2006 12 28.64222114 01 54.514-14 52 04.38 L~09vC568 +99942 2C2006 12 28.64470914 01 55.039-14 52 06.96 L~09vC568 +99942 2C2006 12 28.64705014 01 55.531-14 52 09.35 L~09vC568 +99942 2C2006 12 28.64938714 01 55.996-14 52 11.67 L~09vC568 +99942 2C2006 12 28.65175514 01 56.494-14 52 14.11 L~09vC568 +99942 2C2006 12 28.65410114 01 57.003-14 52 16.60 L~09vC568 +99942 2C2006 12 28.65644714 01 57.472-14 52 18.98 L~09vC568 +99942 2C2006 12 28.65879714 01 57.960-14 52 21.42 L~09vC568 +99942 2C2007 01 21.58245615 32 42.616-20 42 32.51 L~09vC568 +99942 2C2007 01 21.58477315 32 43.182-20 42 34.17 L~09vC568 +99942 2C2007 01 21.58711715 32 43.754-20 42 35.81 L~09vC568 +99942 2C2007 01 21.58959315 32 44.371-20 42 37.63 L~09vC568 +99942 2C2007 01 21.59195815 32 44.938-20 42 39.26 L~09vC568 +99942 2C2007 01 21.59430315 32 45.499-20 42 40.83 L~09vC568 +99942 2C2007 01 21.59664515 32 46.078-20 42 42.56 L~09vC568 +99942 2C2007 01 21.59911315 32 46.703-20 42 44.34 L~09vC568 +99942 2C2007 01 21.60382415 32 47.848-20 42 47.67 L~09vC568 +99942 2C2007 01 21.60630415 32 48.443-20 42 49.39 L~09vC568 +99942 2C2007 01 21.60865515 32 49.033-20 42 51.06 L~09vC568 +99942 2C2007 01 21.61111115 32 49.620-20 42 52.79 L~09vC568 +99942 2C2007 01 21.61348815 32 50.198-20 42 54.45 L~09vC568 +99942 2C2007 01 21.61596315 32 50.816-20 42 56.26 L~09vC568 +99942 2C2007 01 21.61830115 32 51.395-20 42 57.88 L~09vC568 +99942 2C2007 01 21.62065315 32 51.961-20 42 59.57 L~09vC568 +99942 2C2007 01 21.62537515 32 53.108-20 43 02.86 L~09vC568 +99942 2C2007 01 21.63384715 32 55.168-20 43 08.85 L~09vC568 +99942 2C2007 01 21.63855815 32 56.312-20 43 12.14 L~09vC568 +99942 2C2007 01 21.64091415 32 56.911-20 43 13.89 L~09vC568 +99942 2C2007 01 21.64325715 32 57.478-20 43 15.48 L~09vC568 +99942 2C2007 01 21.65294215 32 59.821-20 43 22.32 L~09vC568 +99942 2C2007 01 21.65549215 33 00.470-20 43 24.16 L~09vC568 +99942 2C2007 01 21.65785015 33 01.030-20 43 25.75 L~09vC568 +99942 2C2007 01 21.66020015 33 01.605-20 43 27.43 L~09vC568 +99942 2C2007 01 21.66256215 33 02.171-20 43 29.04 L~09vC568 +99942 2C2007 01 21.66506015 33 02.793-20 43 30.82 L~09vC568 +99942 2C2007 01 21.66740615 33 03.361-20 43 32.52 L~09vC568 +99942 2C2007 01 21.66975715 33 03.947-20 43 34.16 L~09vC568 +99942 2C2007 01 22.57214015 36 47.728-20 53 51.02 L~09vC568 +99942 2C2007 01 22.57654615 36 48.815-20 53 53.82 L~09vC568 +99942 2C2007 01 22.58476015 36 50.845-20 53 59.54 L~09vC568 +99942 2C2007 01 22.58756915 36 51.544-20 54 01.48 L~09vC568 +99942 2C2007 01 22.59237415 36 52.723-20 54 04.90 L~09vC568 +99942 2C2007 01 22.59473715 36 53.296-20 54 06.42 L~09vC568 +99942 2C2007 01 22.59708115 36 53.865-20 54 07.99 L~09vC568 +99942 2C2007 01 22.59954915 36 54.479-20 54 09.82 L~09vC568 +99942 2C2007 01 22.60189015 36 55.064-20 54 11.36 L~09vC568 +99942 2C2007 01 22.60423615 36 55.637-20 54 12.96 L~09vC568 +99942 2C2007 01 22.60669315 36 56.236-20 54 14.69 L~09vC568 +99942 2C2007 01 22.60915215 36 56.845-20 54 16.36 L~09vC568 +99942 2C2007 01 22.61163715 36 57.473-20 54 18.12 L~09vC568 +99942 2C2007 01 22.61397715 36 58.034-20 54 19.83 L~09vC568 +99942 2C2007 01 22.61632415 36 58.619-20 54 21.25 L~09vC568 +99942 2C2007 01 22.61878615 36 59.210-20 54 22.97 L~09vC568 +99942 2C2007 01 22.62113415 36 59.808-20 54 24.59 L~09vC568 +99942 2C2007 01 22.62347015 37 00.364-20 54 26.20 L~09vC568 +99942 2C2007 01 22.62593415 37 00.969-20 54 27.89 L~09vC568 +99942 2C2007 01 22.62827215 37 01.551-20 54 29.50 L~09vC568 +99942 2C2007 01 22.63124215 37 02.296-20 54 31.56 L~09vC568 +99942 2C2007 01 22.63360515 37 02.858-20 54 33.24 L~09vC568 +99942 2C2007 01 22.63609015 37 03.468-20 54 34.88 L~09vC568 +99942 2C2007 01 22.63845815 37 04.044-20 54 36.49 L~09vC568 +99942 2C2007 01 22.64095315 37 04.663-20 54 38.24 L~09vC568 +99942 2C2007 01 22.64329615 37 05.241-20 54 39.79 L~09vC568 +99942 2C2007 01 22.64563215 37 05.805-20 54 41.42 L~09vC568 +99942 2C2007 01 22.64797215 37 06.399-20 54 43.05 L~09vC568 +99942 2C2007 01 22.65031215 37 06.975-20 54 44.58 L~09vC568 +99942 2C2007 01 22.65520515 37 08.177-20 54 48.01 L~09vC568 +99942 2C2007 01 22.65766615 37 08.765-20 54 49.68 L~09vC568 +99942 2C2007 01 22.66000615 37 09.346-20 54 51.23 L~09vC568 +99942 2C2007 01 22.66233915 37 09.914-20 54 52.83 L~09vC568 +99942 2C2007 01 24.57992215 45 10.267-21 15 47.20 L~09vC568 +99942 2C2007 01 24.58237315 45 10.845-21 15 48.76 L~09vC568 +99942 2C2007 01 24.58473515 45 11.459-21 15 50.79 L~09vC568 +99942 2C2007 01 24.58708115 45 12.051-21 15 52.00 L~09vC568 +99942 2C2007 01 24.58943115 45 12.639-21 15 53.62 L~09vC568 +99942 2C2007 01 24.59180315 45 13.201-21 15 55.01 L~09vC568 +99942 2C2007 01 24.59415315 45 13.810-21 15 56.62 L~09vC568 +99942 2C2007 01 24.59649815 45 14.398-21 15 58.15 L~09vC568 +99942 2C2007 01 24.59884615 45 14.981-21 15 59.67 L~09vC568 +99942 2C2007 01 24.60130815 45 15.601-21 16 01.20 L~09vC568 +99942 2C2007 01 24.60397015 45 16.258-21 16 02.96 L~09vC568 +99942 2C2007 01 24.60631615 45 16.864-21 16 04.53 L~09vC568 +99942 2C2007 01 24.60865915 45 17.437-21 16 06.03 L~09vC568 +99942 2C2007 01 24.61100715 45 18.015-21 16 07.64 L~09vC568 +99942 2C2007 01 24.61337815 45 18.617-21 16 09.04 L~09vC568 +99942 2C2007 01 24.61572015 45 19.205-21 16 10.60 L~09vC568 +99942 2C2007 01 24.61806315 45 19.787-21 16 12.11 L~09vC568 +99942 2C2007 01 24.62052215 45 20.394-21 16 13.80 L~09vC568 +99942 2C2007 01 24.62288015 45 20.996-21 16 15.28 L~09vC568 +99942 2C2007 01 24.62536915 45 21.610-21 16 16.86 L~09vC568 +99942 2C2007 01 24.62770915 45 22.184-21 16 18.37 L~09vC568 +99942 2C2007 01 24.63004715 45 22.784-21 16 19.89 L~09vC568 +99942 2C2007 01 24.63253115 45 23.400-21 16 21.47 L~09vC568 +99942 2C2007 01 24.63488415 45 23.956-21 16 22.98 L~09vC568 +99942 2C2007 01 24.63722615 45 24.576-21 16 24.46 L~09vC568 +99942 2C2007 01 24.63968615 45 25.180-21 16 26.08 L~09vC568 +99942 2C2007 01 24.64206015 45 25.765-21 16 27.61 L~09vC568 +99942 2C2007 01 24.64453715 45 26.385-21 16 29.24 L~09vC568 +99942 2C2007 01 24.64749315 45 27.120-21 16 31.13 L~09vC568 +99942 2C2007 01 24.64984515 45 27.716-21 16 32.67 L~09vD568 +99942 2C2007 01 24.65218915 45 28.295-21 16 34.14 L~09vD568 +99942 2C2007 01 24.65453715 45 28.875-21 16 35.68 L~09vD568 +99942 2C2007 01 24.65700115 45 29.476-21 16 37.24 L~09vD568 +99942 2C2007 01 24.65933815 45 30.069-21 16 38.76 L~09vD568 +99942 2C2007 01 24.66186915 45 30.702-21 16 40.35 L~09vD568 +99942 2C2007 01 24.66421415 45 31.282-21 16 41.89 L~09vD568 +99942 2C2007 01 24.66673715 45 31.913-21 16 43.52 L~09vD568 +99942 2C2007 01 24.66915915 45 32.521-21 16 45.04 L~09vD568 +99942 2C2007 01 25.57819315 49 22.787-21 26 10.76 L~09vD568 +99942 2C2007 01 25.58054715 49 23.382-21 26 12.24 L~09vD568 +99942 2C2007 01 25.58288715 49 24.005-21 26 13.93 L~09vD568 +99942 2C2007 01 25.58538115 49 24.619-21 26 15.27 L~09vD568 +99942 2C2007 01 25.58871815 49 25.448-21 26 17.35 L~09vD568 +99942 2C2007 01 25.59107515 49 26.056-21 26 18.94 L~09vD568 +99942 2C2007 01 25.59341915 49 26.638-21 26 20.34 L~09vD568 +99942 2C2007 01 25.59578215 49 27.232-21 26 21.81 L~09vD568 +99942 2C2007 01 25.59814815 49 27.836-21 26 23.28 L~09vD568 +99942 2C2007 01 25.60048815 49 28.426-21 26 24.78 L~09vD568 +99942 2C2007 01 25.60298015 49 29.040-21 26 26.32 L~09vD568 +99942 2C2007 01 25.60533815 49 29.635-21 26 27.79 L~09vD568 +99942 2C2007 01 25.60768815 49 30.217-21 26 29.23 L~09vD568 +99942 2C2007 01 25.61044415 49 30.921-21 26 30.98 L~09vD568 +99942 2C2007 01 25.61280315 49 31.515-21 26 32.50 L~09vD568 +99942 2C2007 01 25.61514615 49 32.099-21 26 33.92 L~09vD568 +99942 2C2007 01 25.61763015 49 32.743-21 26 35.57 L~09vD568 +99942 2C2007 01 25.62004115 49 33.333-21 26 37.04 L~09vD568 +99942 2C2007 01 25.62238915 49 33.920-21 26 38.54 L~09vD568 +99942 2C2007 01 25.62486615 49 34.551-21 26 40.09 L~09vD568 +99942 2C2007 01 25.62721115 49 35.141-21 26 41.54 L~09vD568 +99942 2C2007 01 25.62955615 49 35.721-21 26 42.96 L~09vD568 +99942 2C2007 01 25.63218615 49 36.378-21 26 44.65 L~09vD568 +99942 2C2007 01 25.63452915 49 36.980-21 26 46.10 L~09vD568 +99942 2C2007 01 25.63686715 49 37.574-21 26 47.55 L~09vD568 +99942 2C2007 01 25.63935415 49 38.186-21 26 49.11 L~09vD568 +99942 2C2007 01 25.64171915 49 38.758-21 26 50.54 L~09vD568 +99942 2C2007 01 25.64421215 49 39.407-21 26 52.14 L~09vD568 +99942 2C2007 01 25.64655615 49 39.998-21 26 53.60 L~09vD568 +99942 2C2007 01 25.64907615 49 40.623-21 26 54.91 L~09vD568 +99942 2C2007 03 09.65417619 16 36.695-21 11 06.90 L~09vD568 +99942 2C2007 03 09.65641119 16 37.371-21 11 04.96 L~09vD568 +99942 2C2007 12 13.66071314 26 35.206-15 26 51.52 L~09vD568 +99942 2C2008 01 06.63895716 03 51.245-20 51 51.34 L~09vD568 +99942 2C2008 01 06.64603616 03 53.080-20 51 55.60 L~09vD568 +99942 2C2008 01 06.64949016 03 53.986-20 51 57.69 L~09vD568 +99942 2C2008 01 06.65292016 03 54.887-20 51 59.83 L~09vD568 +99942 2C2008 01 06.65654416 03 55.801-20 52 01.94 L~09vD568 +99942 2C2008 01 06.66000516 03 56.765-20 52 04.16 L~09vD568 +99942 2C2008 01 06.66349216 03 57.618-20 52 06.04 L~09vD568 +99942 2C2008 01 07.64179316 08 14.721-21 01 32.09 L~09vD568 +99942 2C2008 01 07.64518616 08 15.608-21 01 33.99 L~09vD568 +99942 2C2008 01 07.65285816 08 17.617-21 01 38.46 L~09vD568 +99942 2C2008 01 07.65670716 08 18.608-21 01 40.57 L~09vD568 +99942 2C2008 01 08.65407416 12 42.234-21 10 54.03 L~09vD568 +99942 2C2008 01 08.65691716 12 42.968-21 10 55.80 L~09vD568 +99942 2C2008 01 08.65923516 12 43.584-21 10 56.95 L~09vD568 +99942 2C2008 01 08.66382416 12 44.803-21 10 59.64 L~09vD568 +99942 2C2008 01 08.66575916 12 45.323-21 11 00.64 L~09vD568 +99942 2C2008 01 09.64923016 17 06.855-21 19 43.21 L~09vD568 +99942 2C2008 01 09.65116616 17 07.315-21 19 44.16 L~09vD568 +99942 2C2008 01 09.65314116 17 07.868-21 19 45.05 L~09vD568 +99942 2C2008 01 09.65508216 17 08.370-21 19 46.22 L~09vD568 +99942 2C2008 01 09.65908916 17 09.415-21 19 48.28 L~09vD568 +99942 2C2008 01 09.66102716 17 09.953-21 19 49.41 L~09vD568 +99942 2C2008 01 09.66312516 17 10.506-21 19 50.39 L~09vD568 +99942 2C2008 01 09.66508816 17 11.010-21 19 51.46 L~09vD568 diff --git a/test/data/RADEC_2023_DW.dat b/test/data/RADEC_2023_DW.dat old mode 100644 new mode 100755 index 78794849..5dad9242 --- a/test/data/RADEC_2023_DW.dat +++ b/test/data/RADEC_2023_DW.dat @@ -1,123 +1,123 @@ - K23D00W*KC2023 02 26.12762 10 41 50.04 -10 23 20.0 18.2 GV~6ErWW94 - K23D00W KC2023 02 26.13393 10 41 44.54 -10 22 57.3 19.2 GV~6ErWW94 - K23D00W KC2023 02 26.14029 10 41 38.99 -10 22 33.9 19.5 GV~6ErWW94 - K23D00W KC2023 02 26.21229 10 40 36.05 -10 18 10.5 20.0 GV~6ErWW95 - K23D00W KC2023 02 26.21785 10 40 31.20 -10 17 50.3 20.0 GV~6ErWW95 - K23D00W KC2023 02 26.22336 10 40 26.36 -10 17 29.8 20.2 GV~6ErWW95 - K23D00W KC2023 02 26.29905010 39 23.74 -10 14 50.8 19.6 GV~6ErWH21 - K23D00W KC2023 02 26.30072610 39 22.31 -10 14 44.6 19.5 GV~6ErWH21 - K23D00W KC2023 02 26.30268310 39 20.64 -10 14 37.5 19.4 GV~6ErWH21 - K23D00W KC2023 02 26.51483810 36 31.98 -09 59 04.9 19.8 GV~6ErW474 - K23D00W KC2023 02 26.51607410 36 30.95 -09 59 00.8 19.4 GV~6ErW474 - K23D00W KC2023 02 26.51669210 36 30.39 -09 58 58.4 19.3 GV~6ErW474 - K23D00W KC2023 02 26.51792810 36 29.37 -09 58 53.8 19.4 GV~6ErW474 - K23D00W KC2023 02 26.99237710 30 19.04 -09 33 13.0 17.8 GX~6ErW958 - K23D00W KC2023 02 26.99624310 30 15.97 -09 33 00.0 18.3 GX~6ErW958 - K23D00W KC2023 02 27.00003610 30 12.92 -09 32 47.1 18.3 GX~6ErW958 - K23D00W KC2023 02 27.01955810 29 57.533-09 31 45.01 19.1 GV~6ErWJ95 - K23D00W KC2023 02 27.02274710 29 54.974-09 31 34.21 19.5 GV~6ErWJ95 - K23D00W KC2023 02 27.02670610 29 51.854-09 31 19.81 19.2 GV~6ErWJ95 - K23D00W |C2023 02 27.09047 10 29 08.49 -09 25 07.5 19.8 Vu~6ErW807 - K23D00W |C2023 02 27.09529 10 29 04.64 -09 24 50.4 19.8 Vu~6ErW807 - K23D00W |C2023 02 27.10011 10 29 00.88 -09 24 33.8 19.8 Vu~6ErW807 - K23D00W KC2023 02 27.37331910 25 38.34 -09 08 10.1 19.9 GV~6ErW474 - K23D00W KC2023 02 27.37513610 25 36.96 -09 08 04.3 19.8 GV~6ErW474 - K23D00W KC2023 02 27.37604510 25 36.31 -09 08 01.0 19.6 GV~6ErW474 - K23D00W KC2023 02 27.37786310 25 34.92 -09 07 54.8 20.1 GV~6ErW474 - K23D00W KC2023 02 27.84406510 20 00.514-08 43 47.28 19.8 rZ~6IqML34 - K23D00W KC2023 02 28.08327810 17 08.954-08 30 39.56 19.8 GV~6ErWJ95 - K23D00W KC2023 02 28.09127410 17 03.338-08 30 12.56 19.7 GV~6ErWJ95 - K23D00W KC2023 02 28.09176410 17 02.46 -08 30 03.4 20.0 GX~6ErWI93 - K23D00W KC2023 02 28.09557210 16 59.74 -08 29 50.8 19.3 GX~6ErWI93 - K23D00W KC2023 02 28.09926010 16 57.11 -08 29 38.3 20.0 GX~6ErWI93 - K23D00W KC2023 02 28.10219610 16 55.567-08 29 36.02 19.7 GV~6ErWJ95 - K23D00W KC2023 02 28.15117 10 16 28.89 -08 26 37.5 19.6 Vq~6ErWH36 - K23D00W KC2023 02 28.15916 10 16 23.19 -08 26 10.6 19.6 Vq~6ErWH36 - K23D00W mC2023 02 28.16844010 16 18.232-08 25 29.46 19.78GV~6ErWI52 - K23D00W mC2023 02 28.17101110 16 16.399-08 25 21.61 19.99GV~6ErWI52 - K23D00W mC2023 02 28.17381110 16 14.419-08 25 11.57 19.53GV~6ErWI52 - K23D00W mC2023 02 28.17638210 16 12.673-08 25 03.54 19.74GV~6ErWI52 - K23D00W KC2023 02 28.30056 10 14 44.76 -08 18 16.0 19.1 RV~6ErW691 - K23D00W KC2023 02 28.31214 10 14 36.61 -08 17 37.9 19.2 RV~6ErW691 - K23D00W KC2023 02 28.88605510 08 28.10 -07 46 58.9 19.5 GU~6IqML06 - K23D00W KC2023 02 28.88633110 08 27.87 -07 46 58.4 19.6 GU~6IqML06 - K23D00W KC2023 03 01.09750210 06 14.926-07 34 04.87 19.7 GX~6ErWY00 - K23D00W KC2023 03 01.11043910 06 06.437-07 33 23.88 20.0 GX~6ErWY00 - K23D00W KC2023 03 01.12317910 05 58.113-07 32 44.46 20.4 GX~6ErWY00 - K23D00W |C2023 03 01.21364 10 05 02.22 -07 27 46.4 19.8 Vu~6IqM807 - K23D00W |C2023 03 01.21720 10 04 59.98 -07 27 34.9 20.1 Vu~6IqM807 - K23D00W |C2023 03 01.22452 10 04 55.23 -07 27 12.2 19.8 Vu~6IqM807 - K23D00W KC2023 03 01.29513 10 04 14.27 -07 25 22.0 19.9 RV~6ErW691 - K23D00W KC2023 03 01.30289 10 04 09.32 -07 24 57.7 19.2 RV~6ErW691 - K23D00W KC2023 03 01.31066 10 04 04.34 -07 24 34.5 19.6 RV~6ErW691 - K23D00W .C2023 03 02.03196 09 57 07.53 -06 48 20.8 19.1 RV~6IqM950 - K23D00W .C2023 03 02.04667 09 56 58.80 -06 47 37.6 19.1 RV~6IqM950 - K23D00W .C2023 03 02.06140 09 56 50.06 -06 46 54.4 19.1 RV~6IqM950 - K23D00W 1C2023 03 02.85549909 49 52.127-06 09 26.45 20.2 GV~6IqMZ84 - K23D00W 1C2023 03 02.85820109 49 50.695-06 09 19.44 20.3 GV~6IqMZ84 - K23D00W 1C2023 03 02.86090109 49 49.235-06 09 11.73 19.9 GV~6IqMZ84 - K23D00W KC2023 03 04.24171 09 38 50.70 -05 08 48.6 20.3 RV~6IqM291 - K23D00W KC2023 03 04.26765 09 38 38.43 -05 07 44.0 V~6IqM291 - K23D00W KC2023 03 04.97492809 33 37.19 -04 39 30.8 20.2 GU~6IqML06 - K23D00W KC2023 03 04.97633409 33 36.56 -04 39 27.6 19.9 GU~6IqML06 - K23D00W 4C2023 03 09.05679509 11 01.665-02 20 50.12 20.9 GV~6VNlW85 - K23D00W 4C2023 03 09.06694609 10 58.684-02 20 32.84 20.8 GV~6VNlW85 - K23D00W 4C2023 03 09.07580009 10 56.116-02 20 17.70 21.2 GV~6VNlW85 - K23D00W KC2023 03 10.07650409 06 42.51 -01 54 07.0 X~6VNlW62 - K23D00W KC2023 03 10.09679709 06 37.17 -01 53 34.7 20.5 GX~6VNlW62 - K23D00W KC2023 03 10.11709909 06 31.85 -01 53 02.4 20.6 GX~6VNlW62 - K23D00W KC2023 03 10.87422 09 03 36.955-01 32 20.90 21.2 GX~6VNlL87 - K23D00W KC2023 03 10.88471 09 03 34.411-01 32 06.36 20.4 GX~6VNlL87 - K23D00W KC2023 03 11.21539 09 02 23.09 -01 24 58.1 21.5 Ro~6VNl291 - K23D00W KC2023 03 11.23274 09 02 18.97 -01 24 33.0 o~6VNl291 - K23D00W 2C2023 03 11.88641909 00 03.510-01 07 48.54 21.7 GV~6VNlK92 - K23D00W 2C2023 03 11.89503709 00 01.624-01 07 37.03 21.4 GV~6VNlK92 - K23D00W 2C2023 03 11.90366008 59 59.712-01 07 24.83 21.6 GV~6VNlK92 - K23D00W KC2023 03 11.93841 08 59 52.205-01 06 45.32 20.3 GX~6VNlL87 - K23D00W KC2023 03 11.93961 08 59 51.926-01 06 44.03 20.2 GX~6VNlL87 - K23D00W KC2023 03 12.81534 08 57 08.904-00 47 05.10 X~6VNlL87 - K23D00W KC2023 03 12.82659 08 57 06.610-00 46 49.94 20.4 GX~6VNlL87 - K23D00W KC2023 03 12.83793 08 57 04.255-00 46 35.08 20.0 GX~6VNlL87 - K23D00W 2C2023 03 13.05856408 56 25.317-00 41 43.43 21.8 GV~6VNlW86 - K23D00W 2C2023 03 13.07094308 56 22.864-00 41 27.63 21.8 GV~6VNlW86 - K23D00W 2C2023 03 13.08487308 56 20.082-00 41 09.71 21.6 GV~6VNlW86 - K23D00W KC2023 03 13.11090 08 56 16.38 -00 41 45.8 21.8 Vq~6VNlH36 - K23D00W KC2023 03 13.12641 08 56 13.38 -00 41 26.3 22.0 Vq~6VNl734 - K23D00W C2023 03 13.13945608 56 11.493-00 41 05.78 21.4 GV~6VNlH01 - K23D00W KC2023 03 13.14195 08 56 10.32 -00 41 06.7 q~6VNlH36 - K23D00W C2023 03 13.14286308 56 10.830-00 41 01.42 21.6 GV~6VNlH01 - K23D00W KC2023 03 13.14821 08 56 09.06 -00 40 58.7 21.8 Vq~6VNl734 - K23D00W C2023 03 13.15637208 56 08.190-00 40 44.18 21.4 GV~6VNlH01 - K23D00W KC2023 03 13.16090 08 56 07.59 -00 40 36.8 o~6VNl291 - K23D00W C2023 03 13.16255608 56 06.979-00 40 36.27 21.3 GV~6VNlH01 - K23D00W KC2023 03 13.17151 08 56 05.48 -00 40 22.8 21.4 Ro~6VNl291 - K23D00W KC2023 03 13.18212 08 56 03.40 -00 40 09.8 21.4 Ro~6VNl291 - K23D00W KC2023 03 13.89706 08 54 01.882-00 24 25.13 20.4 GX~6VNlL87 - K23D00W KC2023 03 13.90587 08 54 00.266-00 24 14.65 21.0 GX~6VNlL87 - K23D00W KC2023 03 13.91447 08 53 58.646-00 24 04.61 20.3 GX~6VNlL87 - K23D00W LC2023 03 14.04842008 53 39.687-00 21 17.57 21.3 GX~6VNl807 - K23D00W LC2023 03 14.05993108 53 37.550-00 21 02.85 21.6 GX~6VNl807 - K23D00W KC2023 03 14.17439 08 53 19.48 -00 19 48.1 21.8 Ro~6VNl291 - K23D00W KC2023 03 14.21103 08 53 13.00 -00 19 04.8 o~6VNl291 - K23D00W 2C2023 03 15.04936308 51 08.796-00 01 58.62 21.9 GV~6VNlW86 - K23D00W 2C2023 03 15.05826008 51 07.335-00 01 48.69 22.0 GV~6VNlW86 - K23D00W KC2023 03 15.06387908 51 07.24 -00 02 48.0 21.9 GV~6VNlH21 - K23D00W 2C2023 03 15.06716808 51 05.881-00 01 38.66 21.7 GV~6VNlW86 - K23D00W KC2023 03 15.06822008 51 06.55 -00 02 43.0 22.0 GV~6VNlH21 - K23D00W (C2023 03 15.55940908 49 55.602+00 07 22.75 22.4 GV~6VNlE10 - K23D00W (C2023 03 15.56530608 49 54.700+00 07 29.00 21.9 GV~6VNlE10 - K23D00W (C2023 03 15.57051908 49 53.913+00 07 34.74 22.1 GV~6VNlE10 - K23D00W 1C2023 03 15.89724 08 49 11.91 +00 12 11.0 22.1 VX~6VNl033 - K23D00W 1C2023 03 15.90083 08 49 11.41 +00 12 15.2 22.2 VX~6VNl033 - K23D00W 1C2023 03 15.90441 08 49 10.88 +00 12 18.9 22.0 VX~6VNl033 - K23D00W KC2023 03 16.06829508 48 51.01 +00 15 17.4 21.2 GX~6VNlW62 - K23D00W KC2023 03 16.07698908 48 49.78 +00 15 26.7 21.3 GX~6VNlW62 - K23D00W KC2023 03 16.08568908 48 48.49 +00 15 35.8 X~6VNlW62 - K23D00W 0C2023 03 18.45831608 44 21.170+00 54 05.97 22.54GV~6VNlT12 - K23D00W 0C2023 03 18.46207108 44 20.761+00 54 09.28 22.60GV~6VNlT12 - K23D00W 0C2023 03 18.46589808 44 20.354+00 54 12.69 22.53GV~6VNlT12 - K23D00W &C2023 03 19.00066008 43 34.315+01 02 40.16 22.8 GV~6VNl309 - K23D00W &C2023 03 19.00265708 43 34.098+01 02 41.96 22.5 GV~6VNl309 - K23D00W &C2023 03 19.00472108 43 33.876+01 02 43.68 22.7 GV~6VNl309 - K23D00W &C2023 03 19.00688808 43 33.639+01 02 45.50 22.6 GV~6VNl309 - K23D00W &C2023 03 19.00888608 43 33.425+01 02 47.29 22.7 GV~6VNl309 + K23D00W*KC2023 02 26.12762 10 41 50.04 -10 23 20.0 18.2 GV~6ErWW94 + K23D00W KC2023 02 26.13393 10 41 44.54 -10 22 57.3 19.2 GV~6ErWW94 + K23D00W KC2023 02 26.14029 10 41 38.99 -10 22 33.9 19.5 GV~6ErWW94 + K23D00W KC2023 02 26.21229 10 40 36.05 -10 18 10.5 20.0 GV~6ErWW95 + K23D00W KC2023 02 26.21785 10 40 31.20 -10 17 50.3 20.0 GV~6ErWW95 + K23D00W KC2023 02 26.22336 10 40 26.36 -10 17 29.8 20.2 GV~6ErWW95 + K23D00W KC2023 02 26.29905010 39 23.74 -10 14 50.8 19.6 GV~6ErWH21 + K23D00W KC2023 02 26.30072610 39 22.31 -10 14 44.6 19.5 GV~6ErWH21 + K23D00W KC2023 02 26.30268310 39 20.64 -10 14 37.5 19.4 GV~6ErWH21 + K23D00W KC2023 02 26.51483810 36 31.98 -09 59 04.9 19.8 GV~6ErW474 + K23D00W KC2023 02 26.51607410 36 30.95 -09 59 00.8 19.4 GV~6ErW474 + K23D00W KC2023 02 26.51669210 36 30.39 -09 58 58.4 19.3 GV~6ErW474 + K23D00W KC2023 02 26.51792810 36 29.37 -09 58 53.8 19.4 GV~6ErW474 + K23D00W KC2023 02 26.99237710 30 19.04 -09 33 13.0 17.8 GX~6ErW958 + K23D00W KC2023 02 26.99624310 30 15.97 -09 33 00.0 18.3 GX~6ErW958 + K23D00W KC2023 02 27.00003610 30 12.92 -09 32 47.1 18.3 GX~6ErW958 + K23D00W KC2023 02 27.01955810 29 57.533-09 31 45.01 19.1 GV~6ErWJ95 + K23D00W KC2023 02 27.02274710 29 54.974-09 31 34.21 19.5 GV~6ErWJ95 + K23D00W KC2023 02 27.02670610 29 51.854-09 31 19.81 19.2 GV~6ErWJ95 + K23D00W |C2023 02 27.09047 10 29 08.49 -09 25 07.5 19.8 Vu~6ErW807 + K23D00W |C2023 02 27.09529 10 29 04.64 -09 24 50.4 19.8 Vu~6ErW807 + K23D00W |C2023 02 27.10011 10 29 00.88 -09 24 33.8 19.8 Vu~6ErW807 + K23D00W KC2023 02 27.37331910 25 38.34 -09 08 10.1 19.9 GV~6ErW474 + K23D00W KC2023 02 27.37513610 25 36.96 -09 08 04.3 19.8 GV~6ErW474 + K23D00W KC2023 02 27.37604510 25 36.31 -09 08 01.0 19.6 GV~6ErW474 + K23D00W KC2023 02 27.37786310 25 34.92 -09 07 54.8 20.1 GV~6ErW474 + K23D00W KC2023 02 27.84406510 20 00.514-08 43 47.28 19.8 rZ~6IqML34 + K23D00W KC2023 02 28.08327810 17 08.954-08 30 39.56 19.8 GV~6ErWJ95 + K23D00W KC2023 02 28.09127410 17 03.338-08 30 12.56 19.7 GV~6ErWJ95 + K23D00W KC2023 02 28.09176410 17 02.46 -08 30 03.4 20.0 GX~6ErWI93 + K23D00W KC2023 02 28.09557210 16 59.74 -08 29 50.8 19.3 GX~6ErWI93 + K23D00W KC2023 02 28.09926010 16 57.11 -08 29 38.3 20.0 GX~6ErWI93 + K23D00W KC2023 02 28.10219610 16 55.567-08 29 36.02 19.7 GV~6ErWJ95 + K23D00W KC2023 02 28.15117 10 16 28.89 -08 26 37.5 19.6 Vq~6ErWH36 + K23D00W KC2023 02 28.15916 10 16 23.19 -08 26 10.6 19.6 Vq~6ErWH36 + K23D00W mC2023 02 28.16844010 16 18.232-08 25 29.46 19.78GV~6ErWI52 + K23D00W mC2023 02 28.17101110 16 16.399-08 25 21.61 19.99GV~6ErWI52 + K23D00W mC2023 02 28.17381110 16 14.419-08 25 11.57 19.53GV~6ErWI52 + K23D00W mC2023 02 28.17638210 16 12.673-08 25 03.54 19.74GV~6ErWI52 + K23D00W KC2023 02 28.30056 10 14 44.76 -08 18 16.0 19.1 RV~6ErW691 + K23D00W KC2023 02 28.31214 10 14 36.61 -08 17 37.9 19.2 RV~6ErW691 + K23D00W KC2023 02 28.88605510 08 28.10 -07 46 58.9 19.5 GU~6IqML06 + K23D00W KC2023 02 28.88633110 08 27.87 -07 46 58.4 19.6 GU~6IqML06 + K23D00W KC2023 03 01.09750210 06 14.926-07 34 04.87 19.7 GX~6ErWY00 + K23D00W KC2023 03 01.11043910 06 06.437-07 33 23.88 20.0 GX~6ErWY00 + K23D00W KC2023 03 01.12317910 05 58.113-07 32 44.46 20.4 GX~6ErWY00 + K23D00W |C2023 03 01.21364 10 05 02.22 -07 27 46.4 19.8 Vu~6IqM807 + K23D00W |C2023 03 01.21720 10 04 59.98 -07 27 34.9 20.1 Vu~6IqM807 + K23D00W |C2023 03 01.22452 10 04 55.23 -07 27 12.2 19.8 Vu~6IqM807 + K23D00W KC2023 03 01.29513 10 04 14.27 -07 25 22.0 19.9 RV~6ErW691 + K23D00W KC2023 03 01.30289 10 04 09.32 -07 24 57.7 19.2 RV~6ErW691 + K23D00W KC2023 03 01.31066 10 04 04.34 -07 24 34.5 19.6 RV~6ErW691 + K23D00W .C2023 03 02.03196 09 57 07.53 -06 48 20.8 19.1 RV~6IqM950 + K23D00W .C2023 03 02.04667 09 56 58.80 -06 47 37.6 19.1 RV~6IqM950 + K23D00W .C2023 03 02.06140 09 56 50.06 -06 46 54.4 19.1 RV~6IqM950 + K23D00W 1C2023 03 02.85549909 49 52.127-06 09 26.45 20.2 GV~6IqMZ84 + K23D00W 1C2023 03 02.85820109 49 50.695-06 09 19.44 20.3 GV~6IqMZ84 + K23D00W 1C2023 03 02.86090109 49 49.235-06 09 11.73 19.9 GV~6IqMZ84 + K23D00W KC2023 03 04.24171 09 38 50.70 -05 08 48.6 20.3 RV~6IqM291 + K23D00W KC2023 03 04.26765 09 38 38.43 -05 07 44.0 V~6IqM291 + K23D00W KC2023 03 04.97492809 33 37.19 -04 39 30.8 20.2 GU~6IqML06 + K23D00W KC2023 03 04.97633409 33 36.56 -04 39 27.6 19.9 GU~6IqML06 + K23D00W 4C2023 03 09.05679509 11 01.665-02 20 50.12 20.9 GV~6VNlW85 + K23D00W 4C2023 03 09.06694609 10 58.684-02 20 32.84 20.8 GV~6VNlW85 + K23D00W 4C2023 03 09.07580009 10 56.116-02 20 17.70 21.2 GV~6VNlW85 + K23D00W KC2023 03 10.07650409 06 42.51 -01 54 07.0 X~6VNlW62 + K23D00W KC2023 03 10.09679709 06 37.17 -01 53 34.7 20.5 GX~6VNlW62 + K23D00W KC2023 03 10.11709909 06 31.85 -01 53 02.4 20.6 GX~6VNlW62 + K23D00W KC2023 03 10.87422 09 03 36.955-01 32 20.90 21.2 GX~6VNlL87 + K23D00W KC2023 03 10.88471 09 03 34.411-01 32 06.36 20.4 GX~6VNlL87 + K23D00W KC2023 03 11.21539 09 02 23.09 -01 24 58.1 21.5 Ro~6VNl291 + K23D00W KC2023 03 11.23274 09 02 18.97 -01 24 33.0 o~6VNl291 + K23D00W 2C2023 03 11.88641909 00 03.510-01 07 48.54 21.7 GV~6VNlK92 + K23D00W 2C2023 03 11.89503709 00 01.624-01 07 37.03 21.4 GV~6VNlK92 + K23D00W 2C2023 03 11.90366008 59 59.712-01 07 24.83 21.6 GV~6VNlK92 + K23D00W KC2023 03 11.93841 08 59 52.205-01 06 45.32 20.3 GX~6VNlL87 + K23D00W KC2023 03 11.93961 08 59 51.926-01 06 44.03 20.2 GX~6VNlL87 + K23D00W KC2023 03 12.81534 08 57 08.904-00 47 05.10 X~6VNlL87 + K23D00W KC2023 03 12.82659 08 57 06.610-00 46 49.94 20.4 GX~6VNlL87 + K23D00W KC2023 03 12.83793 08 57 04.255-00 46 35.08 20.0 GX~6VNlL87 + K23D00W 2C2023 03 13.05856408 56 25.317-00 41 43.43 21.8 GV~6VNlW86 + K23D00W 2C2023 03 13.07094308 56 22.864-00 41 27.63 21.8 GV~6VNlW86 + K23D00W 2C2023 03 13.08487308 56 20.082-00 41 09.71 21.6 GV~6VNlW86 + K23D00W KC2023 03 13.11090 08 56 16.38 -00 41 45.8 21.8 Vq~6VNlH36 + K23D00W KC2023 03 13.12641 08 56 13.38 -00 41 26.3 22.0 Vq~6VNl734 + K23D00W C2023 03 13.13945608 56 11.493-00 41 05.78 21.4 GV~6VNlH01 + K23D00W KC2023 03 13.14195 08 56 10.32 -00 41 06.7 q~6VNlH36 + K23D00W C2023 03 13.14286308 56 10.830-00 41 01.42 21.6 GV~6VNlH01 + K23D00W KC2023 03 13.14821 08 56 09.06 -00 40 58.7 21.8 Vq~6VNl734 + K23D00W C2023 03 13.15637208 56 08.190-00 40 44.18 21.4 GV~6VNlH01 + K23D00W KC2023 03 13.16090 08 56 07.59 -00 40 36.8 o~6VNl291 + K23D00W C2023 03 13.16255608 56 06.979-00 40 36.27 21.3 GV~6VNlH01 + K23D00W KC2023 03 13.17151 08 56 05.48 -00 40 22.8 21.4 Ro~6VNl291 + K23D00W KC2023 03 13.18212 08 56 03.40 -00 40 09.8 21.4 Ro~6VNl291 + K23D00W KC2023 03 13.89706 08 54 01.882-00 24 25.13 20.4 GX~6VNlL87 + K23D00W KC2023 03 13.90587 08 54 00.266-00 24 14.65 21.0 GX~6VNlL87 + K23D00W KC2023 03 13.91447 08 53 58.646-00 24 04.61 20.3 GX~6VNlL87 + K23D00W LC2023 03 14.04842008 53 39.687-00 21 17.57 21.3 GX~6VNl807 + K23D00W LC2023 03 14.05993108 53 37.550-00 21 02.85 21.6 GX~6VNl807 + K23D00W KC2023 03 14.17439 08 53 19.48 -00 19 48.1 21.8 Ro~6VNl291 + K23D00W KC2023 03 14.21103 08 53 13.00 -00 19 04.8 o~6VNl291 + K23D00W 2C2023 03 15.04936308 51 08.796-00 01 58.62 21.9 GV~6VNlW86 + K23D00W 2C2023 03 15.05826008 51 07.335-00 01 48.69 22.0 GV~6VNlW86 + K23D00W KC2023 03 15.06387908 51 07.24 -00 02 48.0 21.9 GV~6VNlH21 + K23D00W 2C2023 03 15.06716808 51 05.881-00 01 38.66 21.7 GV~6VNlW86 + K23D00W KC2023 03 15.06822008 51 06.55 -00 02 43.0 22.0 GV~6VNlH21 + K23D00W (C2023 03 15.55940908 49 55.602+00 07 22.75 22.4 GV~6VNlE10 + K23D00W (C2023 03 15.56530608 49 54.700+00 07 29.00 21.9 GV~6VNlE10 + K23D00W (C2023 03 15.57051908 49 53.913+00 07 34.74 22.1 GV~6VNlE10 + K23D00W 1C2023 03 15.89724 08 49 11.91 +00 12 11.0 22.1 VX~6VNl033 + K23D00W 1C2023 03 15.90083 08 49 11.41 +00 12 15.2 22.2 VX~6VNl033 + K23D00W 1C2023 03 15.90441 08 49 10.88 +00 12 18.9 22.0 VX~6VNl033 + K23D00W KC2023 03 16.06829508 48 51.01 +00 15 17.4 21.2 GX~6VNlW62 + K23D00W KC2023 03 16.07698908 48 49.78 +00 15 26.7 21.3 GX~6VNlW62 + K23D00W KC2023 03 16.08568908 48 48.49 +00 15 35.8 X~6VNlW62 + K23D00W 0C2023 03 18.45831608 44 21.170+00 54 05.97 22.54GV~6VNlT12 + K23D00W 0C2023 03 18.46207108 44 20.761+00 54 09.28 22.60GV~6VNlT12 + K23D00W 0C2023 03 18.46589808 44 20.354+00 54 12.69 22.53GV~6VNlT12 + K23D00W &C2023 03 19.00066008 43 34.315+01 02 40.16 22.8 GV~6VNl309 + K23D00W &C2023 03 19.00265708 43 34.098+01 02 41.96 22.5 GV~6VNl309 + K23D00W &C2023 03 19.00472108 43 33.876+01 02 43.68 22.7 GV~6VNl309 + K23D00W &C2023 03 19.00688808 43 33.639+01 02 45.50 22.6 GV~6VNl309 + K23D00W &C2023 03 19.00888608 43 33.425+01 02 47.29 22.7 GV~6VNl309 diff --git a/test/extensions.jl b/test/extensions.jl old mode 100644 new mode 100755 index c0512ff4..f5d5a527 --- a/test/extensions.jl +++ b/test/extensions.jl @@ -1,52 +1,52 @@ -using NEOs -using Dates -using Tables -using DataFrames -using Query -using Test - -using NEOs: read_radec_mpc, RadecMPC, read_radar_jpl, RadarJPL - -@testset "DataFramesExt" begin - - # RadecMPC - radec_2023DW = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) - - df_2023DW = DataFrame(radec_2023DW) - - @test nrow(df_2023DW) == length(radec_2023DW) - @test all(names(df_2023DW) .== String.(fieldnames(RadecMPC{Float64}))) - @test all(eltype.(eachcol(df_2023DW)) .== fieldtypes(RadecMPC{Float64})) - - recovered_2023DW = Vector{RadecMPC{Float64}}(df_2023DW) - - @test recovered_2023DW == radec_2023DW - - # Query RadecMPC - I52_2023_02_28 = radec_2023DW |> @filter(Date(date(_)) == Date(2023, 2, 28) && observatory(_) == search_obs_code("I52")) |> DataFrame - - @test nrow(I52_2023_02_28) == 4 - @test all(Date.(I52_2023_02_28.date) .== Date(2023, 2, 28)) - @test allequal(I52_2023_02_28.observatory) && I52_2023_02_28.observatory[1] == search_obs_code("I52") - - # RadarJPL - radar_Apophis = read_radar_jpl(joinpath("data", "99942_RADAR_2005_2013.dat")) - - df_Apophis = DataFrame(radar_Apophis) - - @test nrow(df_Apophis) == length(radar_Apophis) - @test all(names(df_Apophis) .== String.(fieldnames(RadarJPL{Float64}))) - @test all(eltype.(eachcol(df_Apophis)) .== fieldtypes(RadarJPL{Float64})) - - recovered_Apophis = Vector{RadarJPL{Float64}}(df_Apophis) - - @test recovered_Apophis == radar_Apophis - - # Query RadarJPL - _251_before_2013 = radar_Apophis |> @filter(date(_) < Date(2013) && rcvr(_) == search_obs_code("251")) |> DataFrame - - @test nrow(_251_before_2013) == 5 - @test all(_251_before_2013.date .< Date(2013)) - @test allequal(_251_before_2013.rcvr) && _251_before_2013.rcvr[1] == search_obs_code("251") - +using NEOs +using Dates +using Tables +using DataFrames +using Query +using Test + +using NEOs: read_radec_mpc, RadecMPC, read_radar_jpl, RadarJPL + +@testset "DataFramesExt" begin + + # RadecMPC + radec_2023DW = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) + + df_2023DW = DataFrame(radec_2023DW) + + @test nrow(df_2023DW) == length(radec_2023DW) + @test all(names(df_2023DW) .== String.(fieldnames(RadecMPC{Float64}))) + @test all(eltype.(eachcol(df_2023DW)) .== fieldtypes(RadecMPC{Float64})) + + recovered_2023DW = Vector{RadecMPC{Float64}}(df_2023DW) + + @test recovered_2023DW == radec_2023DW + + # Query RadecMPC + I52_2023_02_28 = radec_2023DW |> @filter(Date(date(_)) == Date(2023, 2, 28) && observatory(_) == search_obs_code("I52")) |> DataFrame + + @test nrow(I52_2023_02_28) == 4 + @test all(Date.(I52_2023_02_28.date) .== Date(2023, 2, 28)) + @test allequal(I52_2023_02_28.observatory) && I52_2023_02_28.observatory[1] == search_obs_code("I52") + + # RadarJPL + radar_Apophis = read_radar_jpl(joinpath("data", "99942_RADAR_2005_2013.dat")) + + df_Apophis = DataFrame(radar_Apophis) + + @test nrow(df_Apophis) == length(radar_Apophis) + @test all(names(df_Apophis) .== String.(fieldnames(RadarJPL{Float64}))) + @test all(eltype.(eachcol(df_Apophis)) .== fieldtypes(RadarJPL{Float64})) + + recovered_Apophis = Vector{RadarJPL{Float64}}(df_Apophis) + + @test recovered_Apophis == radar_Apophis + + # Query RadarJPL + _251_before_2013 = radar_Apophis |> @filter(date(_) < Date(2013) && rcvr(_) == search_obs_code("251")) |> DataFrame + + @test nrow(_251_before_2013) == 5 + @test all(_251_before_2013.date .< Date(2013)) + @test allequal(_251_before_2013.rcvr) && _251_before_2013.rcvr[1] == search_obs_code("251") + end \ No newline at end of file diff --git a/test/gauss.jl b/test/gauss.jl old mode 100644 new mode 100755 index e0fac79c..2e802790 --- a/test/gauss.jl +++ b/test/gauss.jl @@ -1,49 +1,47 @@ -# This file is part of the NEOs.jl package; MIT licensed - -using NEOs -using PlanetaryEphemeris -using LinearAlgebra -using Test - -using NEOs: NEOSolution, adaptative_maxsteps, scaled_variables -@testset "Gauss initial conditions" begin - # Load observations - radec = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) - # Abstolute tolerance - abstol = 1e-20 - # Order (wrt time) - order = 25 - # Use @taylorize - parse_eqs = true - - # Gauss initial conditions - sol = gaussinitcond(radec; order = order, abstol = abstol) - - @test isa(sol, NEOSolution{Float64, Float64}) - @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] - @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] - @test all( norm.(sol.bwd.x, Inf) .< 2 ) - @test all( norm.(sol.fwd.x, Inf) .< 2 ) - @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) - @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) - @test length(sol.res) == 123 - @test sol.fit.success - @test all( sqrt.(diag(sol.fit.Γ)) .< 10 ) - @test nrms(sol) < 0.4 - - # Orbit determination (with outlier rejection) - sol = orbitdetermination(radec, sol; order = order, abstol = abstol, parse_eqs = parse_eqs) - - @test isa(sol, NEOSolution{Float64, Float64}) - @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] - @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] - @test all( norm.(sol.bwd.x, Inf) .< 2 ) - @test all( norm.(sol.fwd.x, Inf) .< 2 ) - @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) - @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) - @test length(sol.res) == 123 - @test sol.fit.success - @test all( sqrt.(diag(sol.fit.Γ)) .< 100 ) - @test nrms(sol) < 0.4 - @test count(outlier.(sol.res)) == 0 +# This file is part of the NEOs.jl package; MIT licensed + +using NEOs +using PlanetaryEphemeris +using LinearAlgebra +using Test + +using NEOs: NEOSolution, reduce_nights, adaptative_maxsteps, scaled_variables +@testset "Gauss initial conditions" begin + # Load observations + radec = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) + # Reduce nights by linear regression + gdf, cdf = reduce_nights(radec) + # Parameters + params = Parameters(abstol = 1e-20, order = 25, parse_eqs = true) + + # Gauss initial conditions + sol = gaussinitcond(radec, gdf, cdf, params) + + @test isa(sol, NEOSolution{Float64, Float64}) + @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] + @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] + @test all( norm.(sol.bwd.x, Inf) .< 2 ) + @test all( norm.(sol.fwd.x, Inf) .< 2 ) + @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) + @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) + @test length(sol.res) == 123 + @test sol.fit.success + @test all( sqrt.(diag(sol.fit.Γ)) .< 10 ) + @test nrms(sol) < 0.4 + + # Gauss refinement (with outlier rejection) + sol = gauss_refinement(radec, sol, params) + + @test isa(sol, NEOSolution{Float64, Float64}) + @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] + @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] + @test all( norm.(sol.bwd.x, Inf) .< 2 ) + @test all( norm.(sol.fwd.x, Inf) .< 2 ) + @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) + @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) + @test length(sol.res) == 123 + @test sol.fit.success + @test all( sqrt.(diag(sol.fit.Γ)) .< 100 ) + @test nrms(sol) < 0.4 + @test count(outlier.(sol.res)) == 0 end \ No newline at end of file diff --git a/test/observations.jl b/test/observations.jl old mode 100644 new mode 100755 index f66c2f06..21866593 --- a/test/observations.jl +++ b/test/observations.jl @@ -1,286 +1,286 @@ -# This file is part of the NEOs.jl package; MIT licensed - -using NEOs -using Dates -using Test - -using NEOs: src_path - -@testset "Observations" begin - - @testset "CatalogueMPC" begin - - using NEOs: CATALOGUE_MPC_REGEX, CatalogueMPC - - # Check global variable NEOs.CATALOGUES_MPC[] - @test allunique(NEOs.CATALOGUES_MPC[]) - @test isa(NEOs.CATALOGUES_MPC[], Vector{CatalogueMPC}) - - # Parse CatalogueMPC - gaia_s = " 6 Gaia2016" - gaia_m = match(CATALOGUE_MPC_REGEX, gaia_s) - gaia = CatalogueMPC(gaia_m) - @test gaia.code == "6" - @test gaia.name == "Gaia2016" - - # Unknown catalogue - unkcat = unknowncat() - @test isunknown(unkcat) - @test !isunknown(gaia) - - # Catalogue equality - @test unkcat == unkcat - @test gaia == gaia - @test gaia != unkcat - - # Read/write catalogues file - check_file = joinpath(dirname(src_path), "test", "data", "CatalogueCodes.txt") - write_catalogues_mpc(NEOs.CATALOGUES_MPC[], check_file) - check_cat = read_catalogues_mpc(check_file) - rm(check_file) - @test NEOs.CATALOGUES_MPC[] == check_cat - - # Update catalogues file - update_catalogues_mpc() - @test allunique(NEOs.CATALOGUES_MPC[]) - @test isa(NEOs.CATALOGUES_MPC[], Vector{CatalogueMPC}) - - # Search catalogue code - cat = search_cat_code("6") - @test cat == gaia - end - - @testset "ObservatoryMPC" begin - - using NEOs: OBSERVATORY_MPC_REGEX, ObservatoryMPC - - # Check global variable NEOs.OBSERVATORIES_MPC[] - @test allunique(NEOs.OBSERVATORIES_MPC[]) - @test isa(NEOs.OBSERVATORIES_MPC[], Vector{ObservatoryMPC{Float64}}) - - # Parse ObservatoryMPC - arecibo_s = "251 293.246920.949577+0.312734Arecibo" - arecibo_m = match(OBSERVATORY_MPC_REGEX, arecibo_s) - arecibo = ObservatoryMPC(arecibo_m) - @test arecibo.code == "251" - @test arecibo.long == 293.24692 - @test arecibo.cos == 0.949577 - @test arecibo.sin == +0.312734 - @test arecibo.name == "Arecibo" - - hubble_s = "250 Hubble Space Telescope" - hubble_m = match(OBSERVATORY_MPC_REGEX, hubble_s) - hubble = ObservatoryMPC(hubble_m) - @test hubble.code == "250" - @test isnan(hubble.long) - @test isnan(hubble.cos) - @test isnan(hubble.sin) - @test hubble.name == "Hubble Space Telescope" - - # Unknown observatory - unkobs = unknownobs() - @test isunknown(unkobs) - @test !isunknown(arecibo) - @test !isunknown(hubble) - - # hascoord - @test hascoord(arecibo) - @test !hascoord(hubble) - @test !hascoord(unkobs) - - # Catalogue equality - @test unkobs == unkobs - @test arecibo == arecibo - @test hubble == hubble - @test arecibo != unkobs - @test hubble != unkobs - @test arecibo != hubble - - # Read/write observatories file - check_file = joinpath(dirname(src_path), "test", "data", "ObsCodes.txt") - write_observatories_mpc(NEOs.OBSERVATORIES_MPC[], check_file) - check_obs = read_observatories_mpc(check_file) - rm(check_file) - @test NEOs.OBSERVATORIES_MPC[] == check_obs - - # Update observatories file - update_observatories_mpc() - @test allunique(NEOs.OBSERVATORIES_MPC[]) - @test isa(NEOs.OBSERVATORIES_MPC[], Vector{ObservatoryMPC{Float64}}) - - # Search observatory code - obs = search_obs_code("250") - @test obs == hubble - obs = search_obs_code("251") - @test obs == arecibo - end - - @testset "RadecMPC" begin - - using NEOs: RADEC_MPC_REGEX, RadecMPC - using Dates - - # Parse RadecMPC - apophis_s = "99942K04M04N C2004 03 15.10789 04 06 08.08 +16 55 04.6 om6394691" - apophis_m = match(RADEC_MPC_REGEX, apophis_s) - apophis = RadecMPC(apophis_m) - @test apophis.num == "99942" - @test apophis.tmpdesig == "K04M04N" - @test apophis.discovery == "" - @test apophis.publishnote == "" - @test apophis.obstech == "C" - @test apophis.date == DateTime("2004-03-15T02:35:21.696") - @test apophis.α == 1.0739650841580173 - @test apophis.δ == 0.2952738332250385 - @test apophis.info1 == "" - @test isnan(apophis.mag) - @test apophis.band == "" - @test apophis.catalogue == search_cat_code("o") - @test apophis.info2 == "m6394" - @test apophis.observatory == search_obs_code("691") - - # RadecMPC equality - @test apophis == apophis - - # Read/write radec file - source_file = joinpath("data", "RADEC_2023_DW.dat") - source_radec = read_radec_mpc(source_file) - - @test isa(source_radec, Vector{RadecMPC{Float64}}) - @test issorted(source_radec) - @test allunique(source_radec) - @test all( length.(string.(source_radec)) .== 80) - - check_file = joinpath("data", "RADEC_2023_DW_.dat") - write_radec_mpc(source_radec, check_file) - check_radec = read_radec_mpc(check_file) - rm(check_file) - - @test source_radec == check_radec - - # Get RadecMPC - source_file = joinpath("data", "99942.txt") - get_radec_mpc("number" => "99942", source_file) - - @test isfile(source_file) - - source_radec = read_radec_mpc(source_file) - rm(source_file) - - @test isa(source_radec, Vector{RadecMPC{Float64}}) - @test issorted(source_radec) - @test allunique(source_radec) - @test all( map(x -> length(string(x)) ∈ [80, 161], source_radec)) - - check_file = joinpath("data", "99942_.txt") - write_radec_mpc(source_radec, check_file) - check_radec = read_radec_mpc(check_file) - rm(check_file) - - @test source_radec == check_radec - end - - @testset "RadarJPL" begin - - using NEOs: jpl_radar_regex, RadarJPL, jpl_radar_dateformat - - # Parse RadarJPL - apophis_s = "99942 Apophis (2004 MN4) 2005-01-27 23:31:00 -100849.1434 0.250 Hz 2380 251 251 C" - apophis_m = match(jpl_radar_regex, apophis_s) - apophis = RadarJPL(Val(false), apophis_m) - @test apophis.id == "99942 Apophis (2004 MN4)" - @test apophis.date == DateTime("2005-01-27 23:31:00", jpl_radar_dateformat) - @test isnan(apophis.Δτ) - @test isnan(apophis.Δτ_σ) - @test apophis.Δτ_units == "" - @test apophis.Δν == -100849.1434 - @test apophis.Δν_σ == 0.250 - @test apophis.Δν_units == "Hz" - @test apophis.freq == 2380.0 - @test apophis.rcvr == search_obs_code("251") - @test apophis.xmit == search_obs_code("251") - @test apophis.bouncepoint == "C" - @test ismonostatic(apophis) - @test !hasdelay(apophis) - @test hasdoppler(apophis) - - # RadarJPL equality - @test apophis == apophis - - # Read/write radar file - source_file = joinpath(dirname(src_path), "data/99942_RADAR_2005_2013.dat") - source_radar = read_radar_jpl(source_file) - check_file = joinpath(dirname(src_path), "data/99942_RADAR_2005_2013_.dat") - write_radar_jpl(source_radar, check_file) - check_radar = read_radar_jpl(check_file) - rm(check_file) - - @test source_radar == check_radar - end - - @testset "Topocentric" begin - using NEOs: TimeOfDay, sunriseset, obsposECEF, obsposvelECI - - # Ground observation - radec_1 = read_radec_mpc(""" - 99942 |C2012 12 12.33230011 28 40.300-26 29 32.10 17.70Vu~0mfl807 - 99942 |C2012 12 12.33730011 28 38.970-26 29 34.80 17.60Vu~0mfl807 - 99942 |C2012 12 12.34221011 28 37.640-26 29 37.50 17.50Vu~0mfl807 - 99942 |C2012 12 12.34712011 28 36.330-26 29 40.00 17.50Vu~0mfl807 - 99942 |C2012 12 12.35054011 28 35.400-26 29 41.80 17.50Vu~0mfl807 - """) - # Sattellite observation - radec_2 = read_radec_mpc(""" - 99942 S2020 12 18.97667011 30 15.530-10 46 20.20 19.00RL~4ROFC51 - 99942 s2020 12 18.9766701 - 5634.1734 - 2466.2657 - 3038.3924 ~4ROFC51 - 99942 S2020 12 19.10732011 30 22.510-10 48 20.00 L~4ROFC51 - 99942 s2020 12 19.1073201 - 5654.1816 - 2501.9465 - 2971.1902 ~4ROFC51 - 99942 S2020 12 19.23810011 30 29.500-10 50 19.60 L~4ROFC51 - 99942 s2020 12 19.2381001 - 5645.7831 - 2512.1036 - 2978.6411 ~4ROFC51 - 99942 S2020 12 19.23822011 30 29.570-10 50 19.20 L~4ROFC51 - 99942 s2020 12 19.2382201 - 5617.3465 - 2486.4031 - 3053.2209 ~4ROFC51 - """) - - # Check parsing - @test length(radec_1) == 5 - @test all( map(x -> x.observatory.code, radec_1) .== "807") - @test length(radec_2) == 4 - @test all( map(x -> x.observatory.code, radec_2) .== "C51") - - # TimeOfDay - tod_1 = TimeOfDay.(radec_1) - tod_2 = TimeOfDay.(radec_2) - # Check - @test allequal(tod_1) - @test tod_1[1].light == :night - @test tod_1[1].start == Date(2012, 12, 11) - @test tod_1[1].stop == Date(2012, 12, 12) - @test tod_1[1].utc == -5 - @test allunique(tod_2) - @test all( getfield.(tod_2, :light) .== :space ) - @test all( date.(radec_2) .== getfield.(tod_2, :start) .== getfield.(tod_2, :start) ) - @test all( getfield.(tod_2, :utc) .== 0 ) - - # Sunrise and sunset - radec = read_radec_mpc("99942 8C2020 12 08.15001011 20 07.510-08 02 54.20 18.50GV~4ROF094") - sun = sunriseset(radec[1]) - @test datetime2julian(sun[1]) ≈ datetime2julian(DateTime("2020-12-08T05:05:59.384")) - @test datetime2julian(sun[2]) ≈ datetime2julian(DateTime("2020-12-08T14:05:49.386")) - - # obsposECEF - ecef_2 = obsposECEF.(radec_2) - @test ecef_2[1] ≈ [-3462.643557087632, 5076.197661798687, -3049.6756672719907] - @test ecef_2[2] ≈ [1351.315736765706, 6027.937408384214, -2982.5146167937583] - @test ecef_2[3] ≈ [5332.067839021762, 3112.403799578623, -2989.9547254809945] - @test ecef_2[4] ≈ [5308.786202404402, 3079.725220466387, -3064.4773721684687] - - # obsposvelECI - eci_2 = obsposvelECI.(radec_2) - @test eci_2[1] == [-5634.1734, -2466.2657, -3038.3924, 0.0, 0.0, 0.0] - @test eci_2[2] == [-5654.1816, -2501.9465, -2971.1902, 0.0, 0.0, 0.0] - @test eci_2[3] == [-5645.7831, -2512.1036, -2978.6411, 0.0, 0.0, 0.0] - @test eci_2[4] == [-5617.3465, -2486.4031, -3053.2209, 0.0, 0.0, 0.0] - - end - -end +# This file is part of the NEOs.jl package; MIT licensed + +using NEOs +using Dates +using Test + +using NEOs: src_path + +@testset "Observations" begin + + @testset "CatalogueMPC" begin + + using NEOs: CATALOGUE_MPC_REGEX, CatalogueMPC, isunknown + + # Check global variable NEOs.CATALOGUES_MPC[] + @test allunique(NEOs.CATALOGUES_MPC[]) + @test isa(NEOs.CATALOGUES_MPC[], Vector{CatalogueMPC}) + + # Parse CatalogueMPC + gaia_s = " 6 Gaia2016" + gaia_m = match(CATALOGUE_MPC_REGEX, gaia_s) + gaia = CatalogueMPC(gaia_m) + @test gaia.code == "6" + @test gaia.name == "Gaia2016" + + # Unknown catalogue + unkcat = unknowncat() + @test isunknown(unkcat) + @test !isunknown(gaia) + + # Catalogue equality + @test unkcat == unkcat + @test gaia == gaia + @test gaia != unkcat + + # Read/write catalogues file + check_file = joinpath(dirname(src_path), "test", "data", "CatalogueCodes.txt") + write_catalogues_mpc(NEOs.CATALOGUES_MPC[], check_file) + check_cat = read_catalogues_mpc(check_file) + rm(check_file) + @test NEOs.CATALOGUES_MPC[] == check_cat + + # Update catalogues file + update_catalogues_mpc() + @test allunique(NEOs.CATALOGUES_MPC[]) + @test isa(NEOs.CATALOGUES_MPC[], Vector{CatalogueMPC}) + + # Search catalogue code + cat = search_cat_code("6") + @test cat == gaia + end + + @testset "ObservatoryMPC" begin + + using NEOs: OBSERVATORY_MPC_REGEX, ObservatoryMPC, isunknown + + # Check global variable NEOs.OBSERVATORIES_MPC[] + @test allunique(NEOs.OBSERVATORIES_MPC[]) + @test isa(NEOs.OBSERVATORIES_MPC[], Vector{ObservatoryMPC{Float64}}) + + # Parse ObservatoryMPC + arecibo_s = "251 293.246920.949577+0.312734Arecibo" + arecibo_m = match(OBSERVATORY_MPC_REGEX, arecibo_s) + arecibo = ObservatoryMPC(arecibo_m) + @test arecibo.code == "251" + @test arecibo.long == 293.24692 + @test arecibo.cos == 0.949577 + @test arecibo.sin == +0.312734 + @test arecibo.name == "Arecibo" + + hubble_s = "250 Hubble Space Telescope" + hubble_m = match(OBSERVATORY_MPC_REGEX, hubble_s) + hubble = ObservatoryMPC(hubble_m) + @test hubble.code == "250" + @test isnan(hubble.long) + @test isnan(hubble.cos) + @test isnan(hubble.sin) + @test hubble.name == "Hubble Space Telescope" + + # Unknown observatory + unkobs = unknownobs() + @test isunknown(unkobs) + @test !isunknown(arecibo) + @test !isunknown(hubble) + + # hascoord + @test hascoord(arecibo) + @test !hascoord(hubble) + @test !hascoord(unkobs) + + # Catalogue equality + @test unkobs == unkobs + @test arecibo == arecibo + @test hubble == hubble + @test arecibo != unkobs + @test hubble != unkobs + @test arecibo != hubble + + # Read/write observatories file + check_file = joinpath(dirname(src_path), "test", "data", "ObsCodes.txt") + write_observatories_mpc(NEOs.OBSERVATORIES_MPC[], check_file) + check_obs = read_observatories_mpc(check_file) + rm(check_file) + @test NEOs.OBSERVATORIES_MPC[] == check_obs + + # Update observatories file + update_observatories_mpc() + @test allunique(NEOs.OBSERVATORIES_MPC[]) + @test isa(NEOs.OBSERVATORIES_MPC[], Vector{ObservatoryMPC{Float64}}) + + # Search observatory code + obs = search_obs_code("250") + @test obs == hubble + obs = search_obs_code("251") + @test obs == arecibo + end + + @testset "RadecMPC" begin + + using NEOs: RADEC_MPC_REGEX, RadecMPC + using Dates + + # Parse RadecMPC + apophis_s = "99942K04M04N C2004 03 15.10789 04 06 08.08 +16 55 04.6 om6394691" + apophis_m = match(RADEC_MPC_REGEX, apophis_s) + apophis = RadecMPC(apophis_m) + @test apophis.num == "99942" + @test apophis.tmpdesig == "K04M04N" + @test apophis.discovery == "" + @test apophis.publishnote == "" + @test apophis.obstech == "C" + @test apophis.date == DateTime("2004-03-15T02:35:21.696") + @test apophis.α == 1.0739650841580173 + @test apophis.δ == 0.2952738332250385 + @test apophis.info1 == "" + @test isnan(apophis.mag) + @test apophis.band == "" + @test apophis.catalogue == search_cat_code("o") + @test apophis.info2 == "m6394" + @test apophis.observatory == search_obs_code("691") + + # RadecMPC equality + @test apophis == apophis + + # Read/write radec file + source_file = joinpath("data", "RADEC_2023_DW.dat") + source_radec = read_radec_mpc(source_file) + + @test isa(source_radec, Vector{RadecMPC{Float64}}) + @test issorted(source_radec) + @test allunique(source_radec) + @test all( length.(string.(source_radec)) .== 80) + + check_file = joinpath("data", "RADEC_2023_DW_.dat") + write_radec_mpc(source_radec, check_file) + check_radec = read_radec_mpc(check_file) + rm(check_file) + + @test source_radec == check_radec + + # Get RadecMPC + source_file = joinpath("data", "99942.txt") + get_radec_mpc("number" => "99942", source_file) + + @test isfile(source_file) + + source_radec = read_radec_mpc(source_file) + rm(source_file) + + @test isa(source_radec, Vector{RadecMPC{Float64}}) + @test issorted(source_radec) + @test allunique(source_radec) + @test all( map(x -> length(string(x)) ∈ [80, 161], source_radec)) + + check_file = joinpath("data", "99942_.txt") + write_radec_mpc(source_radec, check_file) + check_radec = read_radec_mpc(check_file) + rm(check_file) + + @test source_radec == check_radec + end + + @testset "RadarJPL" begin + + using NEOs: RADAR_JPL_REGEX, RadarJPL, RADAR_JPL_DATEFORMAT, ismonostatic + + # Parse RadarJPL + apophis_s = "99942 Apophis (2004 MN4) 2005-01-27 23:31:00 -100849.1434 0.250 Hz 2380 251 251 C" + apophis_m = match(RADAR_JPL_REGEX, apophis_s) + apophis = RadarJPL(Val(false), apophis_m) + @test apophis.id == "99942 Apophis (2004 MN4)" + @test apophis.date == DateTime("2005-01-27 23:31:00", RADAR_JPL_DATEFORMAT) + @test isnan(apophis.Δτ) + @test isnan(apophis.Δτ_σ) + @test apophis.Δτ_units == "" + @test apophis.Δν == -100849.1434 + @test apophis.Δν_σ == 0.250 + @test apophis.Δν_units == "Hz" + @test apophis.freq == 2380.0 + @test apophis.rcvr == search_obs_code("251") + @test apophis.xmit == search_obs_code("251") + @test apophis.bouncepoint == "C" + @test ismonostatic(apophis) + @test !hasdelay(apophis) + @test hasdoppler(apophis) + + # RadarJPL equality + @test apophis == apophis + + # Read/write radar file + source_file = joinpath(dirname(src_path), "data/99942_RADAR_2005_2013.dat") + source_radar = read_radar_jpl(source_file) + check_file = joinpath(dirname(src_path), "data/99942_RADAR_2005_2013_.dat") + write_radar_jpl(source_radar, check_file) + check_radar = read_radar_jpl(check_file) + rm(check_file) + + @test source_radar == check_radar + end + + @testset "Topocentric" begin + using NEOs: TimeOfDay, sunriseset, obsposECEF, obsposvelECI + + # Ground observation + radec_1 = read_radec_mpc(""" + 99942 |C2012 12 12.33230011 28 40.300-26 29 32.10 17.70Vu~0mfl807 + 99942 |C2012 12 12.33730011 28 38.970-26 29 34.80 17.60Vu~0mfl807 + 99942 |C2012 12 12.34221011 28 37.640-26 29 37.50 17.50Vu~0mfl807 + 99942 |C2012 12 12.34712011 28 36.330-26 29 40.00 17.50Vu~0mfl807 + 99942 |C2012 12 12.35054011 28 35.400-26 29 41.80 17.50Vu~0mfl807 + """) + # Sattellite observation + radec_2 = read_radec_mpc(""" + 99942 S2020 12 18.97667011 30 15.530-10 46 20.20 19.00RL~4ROFC51 + 99942 s2020 12 18.9766701 - 5634.1734 - 2466.2657 - 3038.3924 ~4ROFC51 + 99942 S2020 12 19.10732011 30 22.510-10 48 20.00 L~4ROFC51 + 99942 s2020 12 19.1073201 - 5654.1816 - 2501.9465 - 2971.1902 ~4ROFC51 + 99942 S2020 12 19.23810011 30 29.500-10 50 19.60 L~4ROFC51 + 99942 s2020 12 19.2381001 - 5645.7831 - 2512.1036 - 2978.6411 ~4ROFC51 + 99942 S2020 12 19.23822011 30 29.570-10 50 19.20 L~4ROFC51 + 99942 s2020 12 19.2382201 - 5617.3465 - 2486.4031 - 3053.2209 ~4ROFC51 + """) + + # Check parsing + @test length(radec_1) == 5 + @test all( map(x -> x.observatory.code, radec_1) .== "807") + @test length(radec_2) == 4 + @test all( map(x -> x.observatory.code, radec_2) .== "C51") + + # TimeOfDay + tod_1 = TimeOfDay.(radec_1) + tod_2 = TimeOfDay.(radec_2) + # Check + @test allequal(tod_1) + @test tod_1[1].light == :night + @test tod_1[1].start == Date(2012, 12, 11) + @test tod_1[1].stop == Date(2012, 12, 12) + @test tod_1[1].utc == -5 + @test allunique(tod_2) + @test all( getfield.(tod_2, :light) .== :space ) + @test all( date.(radec_2) .== getfield.(tod_2, :start) .== getfield.(tod_2, :start) ) + @test all( getfield.(tod_2, :utc) .== 0 ) + + # Sunrise and sunset + radec = read_radec_mpc("99942 8C2020 12 08.15001011 20 07.510-08 02 54.20 18.50GV~4ROF094") + sun = sunriseset(radec[1]) + @test datetime2julian(sun[1]) ≈ datetime2julian(DateTime("2020-12-08T05:05:59.384")) + @test datetime2julian(sun[2]) ≈ datetime2julian(DateTime("2020-12-08T14:05:49.386")) + + # obsposECEF + ecef_2 = obsposECEF.(radec_2) + @test ecef_2[1] ≈ [-3462.643557087632, 5076.197661798687, -3049.6756672719907] + @test ecef_2[2] ≈ [1351.315736765706, 6027.937408384214, -2982.5146167937583] + @test ecef_2[3] ≈ [5332.067839021762, 3112.403799578623, -2989.9547254809945] + @test ecef_2[4] ≈ [5308.786202404402, 3079.725220466387, -3064.4773721684687] + + # obsposvelECI + eci_2 = obsposvelECI.(radec_2) + @test eci_2[1] == [-5634.1734, -2466.2657, -3038.3924, 0.0, 0.0, 0.0] + @test eci_2[2] == [-5654.1816, -2501.9465, -2971.1902, 0.0, 0.0, 0.0] + @test eci_2[3] == [-5645.7831, -2512.1036, -2978.6411, 0.0, 0.0, 0.0] + @test eci_2[4] == [-5617.3465, -2486.4031, -3053.2209, 0.0, 0.0, 0.0] + + end + +end diff --git a/test/osculating.jl b/test/osculating.jl old mode 100644 new mode 100755 index 6cf5e078..68c4c928 --- a/test/osculating.jl +++ b/test/osculating.jl @@ -1,16 +1,16 @@ -using NEOs -using Dates -using Test -using LinearAlgebra: norm - -@testset "Keplerian osculating elements" begin - q = [-9.759018085743707E-01, 3.896554445697074E-01, 1.478066121706831E-01, -9.071450085084557E-03, -9.353197026254517E-03, -5.610023032269034E-03] - kep = pv2kep(q) - jd2000 = datetime2julian(DateTime(2000,1,1,12)) - @test norm(kep(jd2000) - q, Inf) < 1e-10 - - qa = [-1.0506628055913627, -0.06064314196134998, -0.04997102228887035, 0.0029591421121582077, -0.01423233538611057, -0.005218412537773594] - jda = datetime2julian(DateTime(2004,6,1)) - kepa = pv2kep(qa) - @test norm(kepa(jd2000) - qa, Inf) < 1e-10 +using NEOs +using Dates +using Test +using LinearAlgebra: norm + +@testset "Keplerian osculating elements" begin + q = [-9.759018085743707E-01, 3.896554445697074E-01, 1.478066121706831E-01, -9.071450085084557E-03, -9.353197026254517E-03, -5.610023032269034E-03] + kep = pv2kep(q) + jd2000 = datetime2julian(DateTime(2000,1,1,12)) + @test norm(kep(jd2000) - q, Inf) < 1e-10 + + qa = [-1.0506628055913627, -0.06064314196134998, -0.04997102228887035, 0.0029591421121582077, -0.01423233538611057, -0.005218412537773594] + jda = datetime2julian(DateTime(2004,6,1)) + kepa = pv2kep(qa) + @test norm(kepa(jd2000) - qa, Inf) < 1e-10 end \ No newline at end of file diff --git a/test/propagation.jl b/test/propagation.jl old mode 100644 new mode 100755 index fee3d4d7..5761a59f --- a/test/propagation.jl +++ b/test/propagation.jl @@ -1,402 +1,404 @@ -# This file is part of the NEOs.jl package; MIT licensed - -using NEOs -using PlanetaryEphemeris -using Dates -using TaylorIntegration -using JLD2 -using Test - -using InteractiveUtils: methodswith - -@testset "Orbit propagation" begin - - @testset "Integration methods" begin - - @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, TaylorIntegration.jetcoeffs!)) - @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, TaylorIntegration._allocate_jetcoeffs!)) - - @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorIntegration.jetcoeffs!)) - @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorIntegration._allocate_jetcoeffs!)) - - end - - using PlanetaryEphemeris: selecteph, ea, su, daysec, auday2kmsec - using Statistics - - @testset "Orbit propagation without nongravs: 2023 DW" begin - - objname = "2023DW" - maxsteps = 1000 - nyears = 0.2 - dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! - # Initial time [Julian date] - jd0 = datetime2julian(DateTime(2023,2,25,0,0,0)) - # Initial time [days since J2000] - t0 = jd0 - PE.J2000 - # unperturbed initial condition - q0 = [-9.759018085743707E-01, 3.896554445697074E-01, 1.478066121706831E-01, -9.071450085084557E-03, -9.353197026254517E-03, -5.610023032269034E-03] - # Solar System ephemeris - sseph = loadpeeph(NEOs.sseph, t0 - nyears*yr, t0 + nyears*yr) - # Sun's ephemeris - eph_su = selecteph(sseph, su) - # Earth's ephemeris - eph_ea = selecteph(sseph, ea) - - # warmup propagation (forward) - NEOs.propagate( - dynamics, - 1, - jd0, - nyears, - q0, - order = 25, - abstol = 1e-20, - parse_eqs = true - ) - - # propagate orbit - sol_bwd = NEOs.propagate( - dynamics, - maxsteps, - jd0, - -nyears, - q0, - order = 25, - abstol = 1e-20, - parse_eqs = true - ) - sol = NEOs.propagate( - dynamics, - maxsteps, - jd0, - nyears, - q0, - order = 25, - abstol = 1e-20, - parse_eqs = true - ) - - # check that solution saves correctly - jldsave("test.jld2"; sol_bwd, sol) - recovered_sol = JLD2.load("test.jld2", "sol") - recovered_sol_bwd = JLD2.load("test.jld2", "sol_bwd") - @test sol == recovered_sol - @test sol_bwd == recovered_sol_bwd - rm("test.jld2") - - @test sol_bwd.t0 == sol.t0 - @test (sol_bwd.t[end]-sol_bwd.t[1])/yr ≈ -nyears - @test (sol.t[end]-sol.t[1])/yr ≈ nyears - @test sol(sol.t0) == q0 - q_fwd_end = [-1.0168239304400228, -0.3800432452351079, -0.2685901784950398, 0.007623614213394988, -0.00961901551025335, -0.004682171726467166] - @test norm(sol(sol.t0 + sol.t[end])-q_fwd_end, Inf) < 1e-12 - @test sol_bwd(sol_bwd.t0) == q0 - q_bwd_end = [0.2689956497466164, 0.4198851302334139, 0.2438053951982368, -0.018875911266050937, 0.0167349306087375, 0.007789382070881366] - @test norm(sol_bwd(sol_bwd.t0 + sol_bwd.t[end])-q_bwd_end, Inf) < 1e-12 - - # Read optical astrometry file - - obs_radec_mpc_2023DW = NEOs.read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) - - # Compute residuals - _res_ = NEOs.residuals( - obs_radec_mpc_2023DW, - xve=t->auday2kmsec(eph_ea(t/daysec)), - xvs=t->auday2kmsec(eph_su(t/daysec)), - xva=t->auday2kmsec(sol(t/daysec)) - ) - res, w = NEOs.unfold(_res_) - - mean_radec0 = mean(res) - std_radec0 = std(res) - rms_radec0 = nrms(res,ones(length(res))) # un-normalized RMS - @test mean_radec0 ≈ -0.667 atol=1e-3 - @test std_radec0 ≈ 0.736 atol=1e-3 - @test rms_radec0 ≈ 0.992 atol=1e-3 - - # propagate orbit with perturbed initial conditions - q1 = q0 + vcat(1e-3randn(3), 1e-5randn(3)) - sol1 = NEOs.propagate( - dynamics, - maxsteps, - jd0, - nyears, - q1, - order = 25, - abstol = 1e-20, - parse_eqs = true - ) - - # check that solution saves correctly - jldsave("test.jld2"; sol1 = sol1) - recovered_sol1 = JLD2.load("test.jld2", "sol1") - @test sol1 == recovered_sol1 - rm("test.jld2") - - # compute residuals for orbit with perturbed initial conditions - _res1_ = NEOs.residuals( - obs_radec_mpc_2023DW, - xve=t->auday2kmsec(eph_ea(t/daysec)), - xvs=t->auday2kmsec(eph_su(t/daysec)), - xva=t->auday2kmsec(sol1(t/daysec)) - ) - res1, _ = NEOs.unfold(_res1_) - mean_radec1 = mean(res1) - std_radec1 = std(res1) - rms_radec1 = nrms(res1,ones(length(res1))) - - @test abs(mean_radec1) ≥ abs(mean_radec0) - @test std_radec1 ≥ std_radec0 - @test rms_radec1 ≥ rms_radec0 - end - - @testset "Orbit propagation with nongravs: (99942) Apophis" begin - - # integration parameters - objname = "Apophis" - maxsteps = 5000 - nyears = 9.0 - dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! - # Initial time [Julian date] - jd0 = datetime2julian(DateTime(2004,6,1)) - # Initial time [days since J2000] - t0 = jd0 - PE.J2000 - # JPL #199 solution for Apophis at June 1st, 2004 - q0 = [-1.0506628055913627, -0.06064314196134998, -0.04997102228887035, 0.0029591421121582077, -0.01423233538611057, -0.005218412537773594, -5.592839897872e-14, 0.0] - # Solar System ephemeris - sseph = loadpeeph(NEOs.sseph, t0, t0 + nyears*yr) - # Sun's ephemeris - eph_su = selecteph(sseph, su) - # Earth's ephemeris - eph_ea = selecteph(sseph, ea) - - # warmup propagation - sol = NEOs.propagate( - dynamics, - 1, - jd0, - nyears, - q0, - order = 25, - abstol = 1e-20, - parse_eqs = true - ) - - # propagate orbit - sol = NEOs.propagate( - dynamics, - maxsteps, - jd0, - nyears, - q0, - order = 25, - abstol = 1e-20, - parse_eqs = true - ) - - # check that solution saves correctly - jldsave("test.jld2"; sol = sol) - recovered_sol = JLD2.load("test.jld2", "sol") - @test sol == recovered_sol - rm("test.jld2") - - # Read optical astrometry file - obs_radec_mpc_apophis = NEOs.read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) - - # Compute optical astrometry residuals - _res_radec_ = NEOs.residuals( - obs_radec_mpc_apophis, - xve=t->auday2kmsec(eph_ea(t/daysec)), - xvs=t->auday2kmsec(eph_su(t/daysec)), - xva=t->auday2kmsec(sol(t/daysec)) - ) - res_radec, w_radec = NEOs.unfold(_res_radec_) - nobsopt = round(Int, length(res_radec)) - - # Compute mean optical astrometric residual (right ascension and declination) - res_ra = res_radec[1:round(Int,nobsopt/2)] - res_dec = res_radec[round(Int,nobsopt/2)+1:end] - mean_ra = mean(res_ra) - mean_dec = mean(res_dec) - std_ra = std(res_ra) - std_dec = std(res_dec) - rms_ra = nrms(res_ra,ones(length(res_ra))) - rms_dec = nrms(res_dec,ones(length(res_dec))) - @test mean_ra ≈ 0.0224 atol=1e-4 - @test std_ra ≈ 0.136 atol=1e-3 - @test rms_ra ≈ std_ra atol=1e-2 - @test mean_dec ≈ -0.0124 atol=1e-2 - @test std_dec ≈ 0.0714 atol=1e-2 - @test rms_dec ≈ std_dec atol=1e-2 - - # Read radar astrometry file - deldop_2005_2013 = NEOs.read_radar_jpl(joinpath("data", "99942_RADAR_2005_2013.dat")) - - # Compute mean radar (time-delay and Doppler-shift) residuals - @time res_del, w_del, res_dop, w_dop = residuals( - deldop_2005_2013, - xve=t->auday2kmsec(eph_ea(t/daysec)), - xvs=t->auday2kmsec(eph_su(t/daysec)), - xva=t->auday2kmsec(sol(t/daysec)), - niter=4, - tord=5 - ) - - mean_del = mean(res_del) - mean_dop = mean(res_dop) - std_del = std(res_del) - std_dop = std(res_dop) - - @test mean_del ≈ 0.281 atol=1e-2 - @test mean_dop ≈ -0.084 atol=1e-2 - @test std_del ≈ 1.246 atol=1e-2 - @test std_dop ≈ 0.286 atol=1e-2 - - res = vcat(res_radec, res_del, res_dop) - w = vcat(w_radec, w_del, w_dop) - - # Total normalized RMS - @test nrms(res, w) ≈ 0.366 atol=1e-3 - end - - @testset "Jet transport propagation and TaylorN serialization" begin - - # Test integration (Apophis) - - # Dynamical function - local dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! - # Order of Taylor polynomials - local order = 25 - # Absolute tolerance - local abstol = 1e-20 - # Whether to use @taylorize - local parse_eqs = true - # Perturbation to nominal initial condition (Taylor1 jet transport) - local dq = NEOs.scaled_variables() - # Initial date of integration (julian days) - local jd0 = datetime2julian(DateTime(2029, 4, 13, 20)) - # Initial conditions - local q0 = [-0.9170913888342959, -0.37154308794738056, -0.1610606989484252, - 0.009701519087787077, -0.012766026792868212, -0.0043488589639194275] .+ dq - - sol = NEOs.propagate(dynamics, 10, jd0, 0.02, q0; order, abstol, parse_eqs) - jldsave("test.jld2"; sol) - recovered_sol = JLD2.load("test.jld2", "sol") - @test sol == recovered_sol - rm("test.jld2") - - sol, tvS, xvS, gvS = NEOs.propagate_root(dynamics, 1, jd0, 0.02, q0; order, abstol, parse_eqs) - - jldsave("test.jld2"; sol, tvS, xvS, gvS) - recovered_sol = JLD2.load("test.jld2", "sol") - recovered_tvS = JLD2.load("test.jld2", "tvS") - recovered_xvS = JLD2.load("test.jld2", "xvS") - recovered_gvS = JLD2.load("test.jld2", "gvS") - @test sol == recovered_sol - @test tvS == recovered_tvS - @test xvS == recovered_xvS - @test gvS == recovered_gvS - rm("test.jld2") - - # It is unlikely that such a short integration generates a non-trivial tvS, xvS and gvS. Therefore, to test - # VectorTaylorNSerialization I suggest to generate random TaylorN and check it saves correctly... - local random_TaylorN = [cos(sum(dq .* rand(6))), sin(sum(dq .* rand(6))), tan(sum(dq .* rand(6)))] - jldsave("test.jld2"; random_TaylorN = random_TaylorN) - recovered_taylorN = JLD2.load("test.jld2", "random_TaylorN") - @test recovered_taylorN == random_TaylorN - rm("test.jld2") - - end - - @testset "Jet transport orbit propagation and astrometric observables: (99942) Apophis" begin - - # integration parameters - objname::String = "Apophis" - maxsteps::Int = 2000 - nyears::Float64 = 10.0 - varorder::Int = 1 - dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! - jd0::Float64 = datetime2julian(DateTime(2004,6,1)) #Julian date of integration initial time - # JPL #199 solution for Apophis at June 1st, 2004 - q00::Vector{Float64} = [-1.0506627988664696, -0.060643124245514164, -0.0499709975200415, 0.0029591416313078838, -0.014232335581939919, -0.0052184125285361415, -2.898870403031058e-14, -0.0] - dq::Vector{TaylorN{Float64}} = NEOs.scaled_variables("δx", vcat(fill(1e-8, 6), 1e-14), order = varorder) - q0::Vector{TaylorN{Float64}} = q00 .+ vcat(dq, 0dq[1]) - - # propagate orbit - sol = NEOs.propagate( - dynamics, - maxsteps, - jd0, - nyears, - q0, - order = 25, - abstol = 1e-20, - parse_eqs = true - ) - - sseph_obs::TaylorInterpolant{Float64,Float64,2} = loadpeeph(NEOs.sseph, sol.t0, sol.t0 + sol.t[end]) - # Sun's ephemeris - eph_su::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph_obs, su) - # Earth's ephemeris - eph_ea::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph_obs, ea) - - # Read optical astrometry file - obs_radec_mpc_apophis = NEOs.read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) - - # Compute optical astrometry residuals - _res_radec_ = NEOs.residuals( - obs_radec_mpc_apophis, - xve=t->auday2kmsec(eph_ea(t/daysec)), - xvs=t->auday2kmsec(eph_su(t/daysec)), - xva=t->auday2kmsec(sol(t/daysec)) - ) - res_radec, w_radec = NEOs.unfold(_res_radec_) - nobsopt = round(Int, length(res_radec)) - - # Compute mean optical astrometric residual (right ascension and declination) - res_ra = res_radec[1:round(Int,nobsopt/2)]() - res_dec = res_radec[round(Int,nobsopt/2)+1:end]() - mean_ra = mean(res_ra) - mean_dec = mean(res_dec) - std_ra = std(res_ra) - std_dec = std(res_dec) - rms_ra = nrms(res_ra,ones(length(res_ra))) - rms_dec = nrms(res_dec,ones(length(res_dec))) - @test mean_ra ≈ 0.0083 atol=1e-4 - @test std_ra ≈ 0.136 atol=1e-3 - @test rms_ra ≈ std_ra atol=1e-2 - @test mean_dec ≈ -0.0124 atol=1e-2 - @test std_dec ≈ 0.0714 atol=1e-2 - @test rms_dec ≈ std_dec atol=1e-2 - - # Read radar astrometry file - deldop_2005_2013 = NEOs.read_radar_jpl(joinpath("data", "99942_RADAR_2005_2013.dat")) - - # Compute mean radar (time-delay and Doppler-shift) residuals - @time res_del, w_del, res_dop, w_dop = residuals( - deldop_2005_2013[1:4], - xve=t->auday2kmsec(eph_ea(t/daysec)), - xvs=t->auday2kmsec(eph_su(t/daysec)), - xva=t->auday2kmsec(sol(t/daysec)), - niter=10, - tord=10 - ) - - @test abs(res_dop[1]()) ≤ deldop_2005_2013[1].Δν_σ - @test abs(res_del[1]()) ≤ deldop_2005_2013[2].Δτ_σ - @test abs(res_dop[2]()) ≤ deldop_2005_2013[2].Δν_σ - @test abs(res_del[2]()) ≤ deldop_2005_2013[2].Δτ_σ - @test abs(res_dop[3]()) ≤ deldop_2005_2013[3].Δν_σ - @test abs(res_dop[4]()) ≤ deldop_2005_2013[4].Δν_σ - - dq_sample = 2ones(7) - @test abs(res_dop[1](dq_sample)) ≥ deldop_2005_2013[1].Δν_σ - @test abs(res_del[1](dq_sample)) ≥ deldop_2005_2013[2].Δτ_σ - @test abs(res_dop[2](dq_sample)) ≥ deldop_2005_2013[2].Δν_σ - @test abs(res_del[2](dq_sample)) ≥ deldop_2005_2013[2].Δτ_σ - @test abs(res_dop[3](dq_sample)) ≥ deldop_2005_2013[3].Δν_σ - @test abs(res_dop[4](dq_sample)) ≥ deldop_2005_2013[4].Δν_σ - end - -end +# This file is part of the NEOs.jl package; MIT licensed + +using NEOs +using PlanetaryEphemeris +using Dates +using TaylorIntegration +using JLD2 +using Test + +using InteractiveUtils: methodswith + +@testset "Orbit propagation" begin + + @testset "Integration methods" begin + + @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, TaylorIntegration.jetcoeffs!)) + @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, TaylorIntegration._allocate_jetcoeffs!)) + + @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorIntegration.jetcoeffs!)) + @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorIntegration._allocate_jetcoeffs!)) + + end + + using PlanetaryEphemeris: selecteph, ea, su, daysec, auday2kmsec + using Statistics + + @testset "Orbit propagation without nongravs: 2023 DW" begin + + objname = "2023DW" + # Dynamical function + dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! + # Initial time [Julian date] + jd0 = datetime2julian(DateTime(2023, 2, 25, 0, 0, 0)) + # Time of integration [years] + nyears = 0.2 + # Unperturbed initial condition + q0 = [-9.759018085743707E-01, 3.896554445697074E-01, 1.478066121706831E-01, + -9.071450085084557E-03, -9.353197026254517E-03, -5.610023032269034E-03] + # Propagation parameters + params = Parameters(maxsteps = 1, order = 25, abstol = 1e-20, + parse_eqs = true) + + # Initial time [days since J2000] + t0 = jd0 - PE.J2000 + # Solar System ephemeris + sseph = loadpeeph(NEOs.sseph, t0 - nyears*yr, t0 + nyears*yr) + # Sun's ephemeris + eph_su = selecteph(sseph, su) + # Earth's ephemeris + eph_ea = selecteph(sseph, ea) + + # Warmup propagation (forward) + NEOs.propagate( + dynamics, + jd0, + nyears, + q0, + params + ) + # Propagate orbit + params = Parameters(params; maxsteps = 1_000) + sol_bwd = NEOs.propagate( + dynamics, + jd0, + -nyears, + q0, + params + ) + sol = NEOs.propagate( + dynamics, + jd0, + nyears, + q0, + params + ) + + # Check that solution saves correctly + jldsave("test.jld2"; sol_bwd, sol) + recovered_sol = JLD2.load("test.jld2", "sol") + recovered_sol_bwd = JLD2.load("test.jld2", "sol_bwd") + @test sol == recovered_sol + @test sol_bwd == recovered_sol_bwd + rm("test.jld2") + + @test sol_bwd.t0 == sol.t0 + @test (sol_bwd.t[end]-sol_bwd.t[1])/yr ≈ -nyears + @test (sol.t[end]-sol.t[1])/yr ≈ nyears + @test sol(sol.t0) == q0 + q_fwd_end = [-1.0168239304400228, -0.3800432452351079, -0.2685901784950398, + 0.007623614213394988, -0.00961901551025335, -0.004682171726467166] + @test norm(sol(sol.t0 + sol.t[end])-q_fwd_end, Inf) < 1e-12 + @test sol_bwd(sol_bwd.t0) == q0 + q_bwd_end = [0.2689956497466164, 0.4198851302334139, 0.2438053951982368, + -0.018875911266050937, 0.0167349306087375, 0.007789382070881366] + @test norm(sol_bwd(sol_bwd.t0 + sol_bwd.t[end])-q_bwd_end, Inf) < 1e-12 + + # Read optical astrometry file + + obs_radec_mpc_2023DW = NEOs.read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) + + # Compute residuals + _res_ = NEOs.residuals( + obs_radec_mpc_2023DW, + params, + xve = t -> auday2kmsec(eph_ea(t/daysec)), + xvs = t -> auday2kmsec(eph_su(t/daysec)), + xva = t -> auday2kmsec(sol(t/daysec)) + ) + res, w = NEOs.unfold(_res_) + + mean_radec0 = mean(res) + std_radec0 = std(res) + rms_radec0 = nrms(res, ones(length(res))) # un-normalized RMS + @test mean_radec0 ≈ -0.667 atol=1e-3 + @test std_radec0 ≈ 0.736 atol=1e-3 + @test rms_radec0 ≈ 0.992 atol=1e-3 + + # Propagate orbit with perturbed initial conditions + q1 = q0 + vcat(1e-3randn(3), 1e-5randn(3)) + sol1 = NEOs.propagate( + dynamics, + jd0, + nyears, + q1, + params + ) + + # Check that solution saves correctly + jldsave("test.jld2"; sol1 = sol1) + recovered_sol1 = JLD2.load("test.jld2", "sol1") + @test sol1 == recovered_sol1 + rm("test.jld2") + + # Compute residuals for orbit with perturbed initial conditions + _res1_ = NEOs.residuals( + obs_radec_mpc_2023DW, + params, + xve = t -> auday2kmsec(eph_ea(t/daysec)), + xvs = t -> auday2kmsec(eph_su(t/daysec)), + xva = t -> auday2kmsec(sol1(t/daysec)) + ) + res1, _ = NEOs.unfold(_res1_) + mean_radec1 = mean(res1) + std_radec1 = std(res1) + rms_radec1 = nrms(res1, ones(length(res1))) + + @test abs(mean_radec1) ≥ abs(mean_radec0) + @test std_radec1 ≥ std_radec0 + @test rms_radec1 ≥ rms_radec0 + end + + @testset "Orbit propagation with nongravs: (99942) Apophis" begin + + objname = "Apophis" + # Dynamical function + dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! + # Initial time [Julian date] + jd0 = datetime2julian(DateTime(2004, 6, 1)) + # Time of integration [years] + nyears = 9.0 + # JPL #199 solution for Apophis at June 1st, 2004 + q0 = [-1.0506628055913627, -0.06064314196134998, -0.04997102228887035, + 0.0029591421121582077, -0.01423233538611057, -0.005218412537773594, + -5.592839897872e-14, 0.0] + # Propagation parameters + params = Parameters(maxsteps = 1, order = 25, abstol = 1e-20, + parse_eqs = true) + + # Initial time [days since J2000] + t0 = jd0 - PE.J2000 + # Solar System ephemeris + sseph = loadpeeph(NEOs.sseph, t0, t0 + nyears*yr) + # Sun's ephemeris + eph_su = selecteph(sseph, su) + # Earth's ephemeris + eph_ea = selecteph(sseph, ea) + + # Warmup propagation + sol = NEOs.propagate( + dynamics, + jd0, + nyears, + q0, + params + ) + # Propagate orbit + params = Parameters(params, maxsteps = 5_000) + sol = NEOs.propagate( + dynamics, + jd0, + nyears, + q0, + params + ) + + # Check that solution saves correctly + jldsave("test.jld2"; sol = sol) + recovered_sol = JLD2.load("test.jld2", "sol") + @test sol == recovered_sol + rm("test.jld2") + + # Read optical astrometry file + obs_radec_mpc_apophis = NEOs.read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) + + # Compute optical astrometry residuals + _res_radec_ = NEOs.residuals( + obs_radec_mpc_apophis, + params, + xve = t -> auday2kmsec(eph_ea(t/daysec)), + xvs = t -> auday2kmsec(eph_su(t/daysec)), + xva = t -> auday2kmsec(sol(t/daysec)) + ) + res_radec, w_radec = NEOs.unfold(_res_radec_) + nobsopt = round(Int, length(res_radec)) + + # Compute mean optical astrometric residual (right ascension and declination) + res_ra = res_radec[1:round(Int,nobsopt/2)] + res_dec = res_radec[round(Int,nobsopt/2)+1:end] + mean_ra = mean(res_ra) + mean_dec = mean(res_dec) + std_ra = std(res_ra) + std_dec = std(res_dec) + rms_ra = nrms(res_ra,ones(length(res_ra))) + rms_dec = nrms(res_dec,ones(length(res_dec))) + @test mean_ra ≈ 0.0224 atol=1e-4 + @test std_ra ≈ 0.136 atol=1e-3 + @test rms_ra ≈ std_ra atol=1e-2 + @test mean_dec ≈ -0.0124 atol=1e-2 + @test std_dec ≈ 0.0714 atol=1e-2 + @test rms_dec ≈ std_dec atol=1e-2 + + # Read radar astrometry file + deldop_2005_2013 = NEOs.read_radar_jpl(joinpath("data", "99942_RADAR_2005_2013.dat")) + + # Compute mean radar (time-delay and Doppler-shift) residuals + @time res_del, w_del, res_dop, w_dop = residuals( + deldop_2005_2013, + xve = t -> auday2kmsec(eph_ea(t/daysec)), + xvs = t -> auday2kmsec(eph_su(t/daysec)), + xva = t -> auday2kmsec(sol(t/daysec)), + niter = 4, + tord = 5 + ) + + mean_del = mean(res_del) + mean_dop = mean(res_dop) + std_del = std(res_del) + std_dop = std(res_dop) + + @test mean_del ≈ 0.281 atol=1e-2 + @test mean_dop ≈ -0.084 atol=1e-2 + @test std_del ≈ 1.246 atol=1e-2 + @test std_dop ≈ 0.286 atol=1e-2 + + res = vcat(res_radec, res_del, res_dop) + w = vcat(w_radec, w_del, w_dop) + + # Total normalized RMS + @test nrms(res, w) ≈ 0.366 atol=1e-3 + end + + @testset "Jet transport propagation and TaylorN serialization" begin + + # Test integration (Apophis) + + # Dynamical function + dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! + # Initial date of integration [julian days] + jd0 = datetime2julian(DateTime(2029, 4, 13, 20)) + # Time of integration [years] + nyears = 0.02 + # Perturbation to nominal initial condition (Taylor1 jet transport) + dq = NEOs.scaled_variables() + # Initial conditions + q0 = [-0.9170913888342959, -0.37154308794738056, -0.1610606989484252, + 0.009701519087787077, -0.012766026792868212, -0.0043488589639194275] .+ dq + # Propagation parameters + params = Parameters(maxsteps = 10, order = 25, abstol = 1e-20, parse_eqs = true) + + # Propagate orbit + sol = NEOs.propagate(dynamics, jd0, nyears, q0, params) + jldsave("test.jld2"; sol) + recovered_sol = JLD2.load("test.jld2", "sol") + @test sol == recovered_sol + rm("test.jld2") + + params = Parameters(params; maxsteps = 1) + sol, tvS, xvS, gvS = NEOs.propagate_root(dynamics, jd0, nyears, q0, params) + + jldsave("test.jld2"; sol, tvS, xvS, gvS) + recovered_sol = JLD2.load("test.jld2", "sol") + recovered_tvS = JLD2.load("test.jld2", "tvS") + recovered_xvS = JLD2.load("test.jld2", "xvS") + recovered_gvS = JLD2.load("test.jld2", "gvS") + @test sol == recovered_sol + @test tvS == recovered_tvS + @test xvS == recovered_xvS + @test gvS == recovered_gvS + rm("test.jld2") + + # It is unlikely that such a short integration generates a non-trivial tvS, xvS and gvS. + # Therefore, to test TaylorNSerialization I suggest to generate random TaylorN and check + # it saves correctly... + random_TaylorN = [cos(sum(dq .* rand(6))), sin(sum(dq .* rand(6))), tan(sum(dq .* rand(6)))] + jldsave("test.jld2"; random_TaylorN = random_TaylorN) + recovered_taylorN = JLD2.load("test.jld2", "random_TaylorN") + @test recovered_taylorN == random_TaylorN + rm("test.jld2") + + end + + @testset "Jet transport orbit propagation and astrometric observables: (99942) Apophis" begin + + objname::String = "Apophis" + # Dynamical function + dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! + # Initial date of integration [julian days] + jd0::Float64 = datetime2julian(DateTime(2004, 6, 1)) + # Time of integration [years] + nyears::Float64 = 10.0 + # JPL #199 solution for Apophis at June 1st, 2004 + q00::Vector{Float64} = [-1.0506627988664696, -0.060643124245514164, -0.0499709975200415, 0.0029591416313078838, -0.014232335581939919, -0.0052184125285361415, -2.898870403031058e-14, -0.0] + varorder::Int = 1 + dq::Vector{TaylorN{Float64}} = NEOs.scaled_variables("δx", vcat(fill(1e-8, 6), 1e-14), order = varorder) + q0::Vector{TaylorN{Float64}} = q00 .+ vcat(dq, 0dq[1]) + # Propagation parameters + params = Parameters(maxsteps = 2_000, order = 25, abstol = 1e-20, parse_eqs = true) + + # Propagate orbit + sol = NEOs.propagate( + dynamics, + jd0, + nyears, + q0, + params + ) + + # Solar System ephemeris + sseph_obs::TaylorInterpolant{Float64,Float64,2} = loadpeeph(NEOs.sseph, sol.t0, sol.t0 + sol.t[end]) + # Sun's ephemeris + eph_su::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph_obs, su) + # Earth's ephemeris + eph_ea::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph_obs, ea) + + # Read optical astrometry file + obs_radec_mpc_apophis = NEOs.read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) + + # Compute optical astrometry residuals + _res_radec_ = NEOs.residuals( + obs_radec_mpc_apophis, + params, + xve = t -> auday2kmsec(eph_ea(t/daysec)), + xvs = t -> auday2kmsec(eph_su(t/daysec)), + xva = t -> auday2kmsec(sol(t/daysec)) + ) + res_radec, w_radec = NEOs.unfold(_res_radec_) + nobsopt = round(Int, length(res_radec)) + + # Compute mean optical astrometric residual (right ascension and declination) + res_ra = res_radec[1:round(Int,nobsopt/2)]() + res_dec = res_radec[round(Int,nobsopt/2)+1:end]() + mean_ra = mean(res_ra) + mean_dec = mean(res_dec) + std_ra = std(res_ra) + std_dec = std(res_dec) + rms_ra = nrms(res_ra,ones(length(res_ra))) + rms_dec = nrms(res_dec,ones(length(res_dec))) + @test mean_ra ≈ 0.0083 atol=1e-4 + @test std_ra ≈ 0.136 atol=1e-3 + @test rms_ra ≈ std_ra atol=1e-2 + @test mean_dec ≈ -0.0124 atol=1e-2 + @test std_dec ≈ 0.0714 atol=1e-2 + @test rms_dec ≈ std_dec atol=1e-2 + + # Read radar astrometry file + deldop_2005_2013 = NEOs.read_radar_jpl(joinpath("data", "99942_RADAR_2005_2013.dat")) + + # Compute mean radar (time-delay and Doppler-shift) residuals + @time res_del, w_del, res_dop, w_dop = residuals( + deldop_2005_2013[1:4], + xve = t -> auday2kmsec(eph_ea(t/daysec)), + xvs = t -> auday2kmsec(eph_su(t/daysec)), + xva = t -> auday2kmsec(sol(t/daysec)), + niter=10, + tord=10 + ) + + @test abs(res_dop[1]()) ≤ deldop_2005_2013[1].Δν_σ + @test abs(res_del[1]()) ≤ deldop_2005_2013[2].Δτ_σ + @test abs(res_dop[2]()) ≤ deldop_2005_2013[2].Δν_σ + @test abs(res_del[2]()) ≤ deldop_2005_2013[2].Δτ_σ + @test abs(res_dop[3]()) ≤ deldop_2005_2013[3].Δν_σ + @test abs(res_dop[4]()) ≤ deldop_2005_2013[4].Δν_σ + + dq_sample = 2ones(7) + @test abs(res_dop[1](dq_sample)) ≥ deldop_2005_2013[1].Δν_σ + @test abs(res_del[1](dq_sample)) ≥ deldop_2005_2013[2].Δτ_σ + @test abs(res_dop[2](dq_sample)) ≥ deldop_2005_2013[2].Δν_σ + @test abs(res_del[2](dq_sample)) ≥ deldop_2005_2013[2].Δτ_σ + @test abs(res_dop[3](dq_sample)) ≥ deldop_2005_2013[3].Δν_σ + @test abs(res_dop[4](dq_sample)) ≥ deldop_2005_2013[4].Δν_σ + end + +end diff --git a/test/runtests.jl b/test/runtests.jl old mode 100644 new mode 100755 index 97c6dc72..a6801a9b --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,13 +1,13 @@ -# This file is part of the NEOs.jl package; MIT licensed - -testfiles = ( - "osculating.jl", - "observations.jl", - "propagation.jl", - "gauss.jl", - "extensions.jl" - ) - -for file in testfiles - include(file) +# This file is part of the NEOs.jl package; MIT licensed + +testfiles = ( + "osculating.jl", + "observations.jl", + "propagation.jl", + "gauss.jl", + "extensions.jl" + ) + +for file in testfiles + include(file) end \ No newline at end of file From ca76e8a5cb1fbbe66bb779e81823d31f1bc0333a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 26 Nov 2023 12:04:01 -0600 Subject: [PATCH 076/173] issinglearc --- src/NEOs.jl | 2 +- src/orbit_determination/orbit_determination.jl | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index 083265a7..c3b1075f 100755 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -69,7 +69,7 @@ export tooshortarc # Gauss method export gauss_method, gaussinitcond, gauss_refinement # Orbit determination -export orbitdetermination +export issinglearc, orbitdetermination include("constants.jl") include("observations/process_radar.jl") diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index 9f620d4e..9d35bb4b 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -2,6 +2,15 @@ include("osculating.jl") include("tooshortarc.jl") include("gauss_method.jl") +function issinglearc(radec::Vector{RadecMPC{T}}, arc::Day = Day(30)) where {T <: AbstractFloat} + for i in 2:length(radec) + if date(radec[i]) - date(radec[i-1]) > arc + return false + end + end + return true +end + @doc raw""" orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}; kwargs...) where {T <: AbstractFloat} From 162d8ef72ac4a9d6a7eff6b573690928d68e3676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 1 Dec 2023 11:26:17 -0600 Subject: [PATCH 077/173] Fixes to tooshortarc --- src/orbit_determination/gauss_method.jl | 2 - .../orbit_determination.jl | 2 + src/orbit_determination/tooshortarc.jl | 82 +++++++++++-------- 3 files changed, 50 insertions(+), 36 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index fb40056f..037d1084 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -448,8 +448,6 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::D t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) # Julian day when to start propagation jd0 = zero(T) - # Maximum number of steps - params = Parameters(params; maxsteps = adaptative_maxsteps(radec)) # Jet transport perturbation (ra/dec) dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃"; order = varorder) # Sun's ephemeris diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index 9d35bb4b..b1ff77c7 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -33,6 +33,8 @@ Initial Orbit Determination (IOD) routine. function orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}; maxiter::Int = 50, max_triplets::Int = 10, Q_max::T = 10., niter::Int = 5, varorder::Int = 5, max_per::T = 18.0) where {T <: AbstractFloat} + # Maximum number of steps + params = Parameters(params; maxsteps = adaptative_maxsteps(radec)) # Eliminate observatories without coordinates filter!(x -> hascoord(observatory(x)), radec) # Reduce observation nights by linear regression diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index a0917dd6..c53f3740 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -159,7 +159,7 @@ Return the maximum range for the left connected component of `A`. function max_range(A::AdmissibleRegion{T}) where {T <: AbstractFloat} # Find max_range ρ = find_zeros(s -> A.coeffs[2]^2/4 - admsreg_W(A, s) + 2*k_gauss^2/sqrt(admsreg_S(A, s)), - R_SI, 1.0)[1] + R_SI, 2.0)[1] # Make sure there is no sqrt(negative) niter = 0 while admsreg_S(A, ρ) < 0 && niter < 100 @@ -283,16 +283,18 @@ end @doc raw""" gradient_descent(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; maxiter::Int = 50) where {T <: AbstractFloat} + params::Parameters{T}; maxiter::Int = 200) where {T <: AbstractFloat} Gradient descent minimizer of root mean square error over `A`. """ function gradient_descent(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; maxiter::Int = 50) where {T <: AbstractFloat} + params::Parameters{T}; maxiter::Int = 200) where {T <: AbstractFloat} # Origin x0 = zeros(T, 2) + # Scaling factors + scalings = [1e-3, 1e-5] # Jet transport variables - dq = scaled_variables("dρ dvρ", fill(1e-3, 2), order = 1) + dq = scaled_variables("dρ dvρ", scalings, order = 1) # Allocate memory ρs = Vector{T}(undef, maxiter+1) v_ρs = Vector{T}(undef, maxiter+1) @@ -342,18 +344,20 @@ end @doc raw""" momentum_descent(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; maxiter::Int = 50, α::T = 1.0, + params::Parameters{T}; maxiter::Int = 200, α::T = 10.0, β::T = 0.75, Qtol::T = 0.01) where {T <: AbstractFloat} Momentum gradient descent minimizer of root mean square error over `A`. """ function momentum_descent(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; maxiter::Int = 50, α::T = 1.0, + params::Parameters{T}; maxiter::Int = 200, α::T = 10.0, β::T = 0.75, Qtol::T = 0.01) where {T <: AbstractFloat} # Origin x0 = zeros(T, 2) + # Scaling factors + scalings = [1e-3, 1e-5] # Jet transport variables - dq = scaled_variables("dρ dvρ", fill(1e-3, 2), order = 1) + dq = scaled_variables("dρ dvρ", scalings, order = 1) # Allocate memory ρs = Vector{T}(undef, maxiter+1) v_ρs = Vector{T}(undef, maxiter+1) @@ -406,18 +410,20 @@ end @doc raw""" rmsprop(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; maxiter::Int = 50, α::T = 1.0, β::T = 0.9, + params::Parameters{T}; maxiter::Int = 200, α::T = 10.0, β::T = 0.9, ϵ::T = 1e-8, Qtol::T = 0.01) where {T <: AbstractFloat} RMSPROP minimizer of root mean square error over `A`. """ function rmsprop(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; maxiter::Int = 50, α::T = 1.0, β::T = 0.9, + params::Parameters{T}; maxiter::Int = 200, α::T = 10.0, β::T = 0.9, ϵ::T = 1e-8, Qtol::T = 0.01) where {T <: AbstractFloat} # Origin x0 = zeros(T, 2) + # Scaling factors + scalings = [1e-3, 1e-5] # Jet transport variables - dq = scaled_variables("dρ dvρ", fill(1e-3, 2), order = 1) + dq = scaled_variables("dρ dvρ", scalings, order = 1) # Allocate memory ρs = Vector{T}(undef, maxiter+1) v_ρs = Vector{T}(undef, maxiter+1) @@ -469,18 +475,20 @@ end @doc raw""" adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; maxiter::Int = 50, α::T = 1.0, β_1::T = 0.75, + params::Parameters{T}; maxiter::Int = 200, α::T = 10.0, β_1::T = 0.75, β_2::T = 0.85, ϵ::T = 1e-8, Qtol::T = 0.01) where {T <: AbstractFloat} ADAM minimizer of root mean square error over `A`. """ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; maxiter::Int = 50, α::T = 1.0, β_1::T = 0.75, + params::Parameters{T}; maxiter::Int = 200, α::T = 10.0, β_1::T = 0.75, β_2::T = 0.85, ϵ::T = 1e-8, Qtol::T = 0.01) where {T <: AbstractFloat} # Origin x0 = zeros(T, 2) + # Scaling factors + scalings = [1e-3, 1e-5] # Jet transport variables - dq = scaled_variables("dρ dvρ", fill(1e-3, 2), order = 1) + dq = scaled_variables("dρ dvρ", scalings, order = 1) # Allocate memory ρs = Vector{T}(undef, maxiter+1) v_ρs = Vector{T}(undef, maxiter+1) @@ -540,8 +548,10 @@ function tryls(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{T}, params::Parame maxiter::Int = 5) where {T <: AbstractFloat} # Origin x0 = zeros(T, 6) + # Scaling factors + scalings = [1e-5, 1e-5, 1e-5, 1e-7, 1e-7, 1e-7] # Jet transport variables - dq = scaled_variables("dx", fill(1e-6, 6), order = 6) + dq = scaled_variables("dx", scalings, order = 6) # Allocate memory qs = Matrix{T}(undef, 6, maxiter+1) Qs = Vector{T}(undef, maxiter+1) @@ -600,29 +610,33 @@ the admissible region. # Keyword arguments -- `maxiter::Int = 50`: maximum number of iterations. +- `maxiter::Int = 200`: maximum number of iterations. """ function tooshortarc(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::DataFrame, - params::Parameters{T}; maxiter::Int = 50) where {T <: AbstractFloat} - # Find indexes corresponding to observatory with the most number of - # observations - frecs = map(i -> nrow(gdf[i]), 1:nrow(cdf)) - obs_max = argmax(frecs) - idxs = getfield(gdf[obs_max], :rows) - # Admissible region - A = AdmissibleRegion(cdf[obs_max, :]) - # Center - ρ = (R_SI + max_range(A)) / 2 - v_ρ = sum(range_rate(A, R_SI)) / 2 - # Minimization over admissible region - ρs, v_ρs, Qs = adam(radec[idxs], A, ρ, v_ρ, params; maxiter = maxiter) - # 6 variables least squares - q0 = topo2bary(A, ρs[end], v_ρs[end]) - sol = tryls(radec[idxs], datetime2julian(A.date), q0, params; maxiter = 5) - if length(idxs) < length(radec) + params::Parameters{T}; maxiter::Int = 200) where {T <: AbstractFloat} + + # Number of observations per night + nobs = map(i -> nrow(gdf[i]), 1:nrow(cdf)) + # Sort nights by number of observations + idxs = sortperm(nobs, rev = true) + # Allocate memory for output + sol = zero(NEOSolution{T, T}) + + for i in idxs + # Admissible region + A = AdmissibleRegion(cdf[i, :]) + # Center + ρ = (R_SI + max_range(A)) / 2 + v_ρ = sum(range_rate(A, R_SI)) / 2 + # Minimization over admissible region + ρs, v_ρs, Qs = adam(radec, A, ρ, v_ρ, params; maxiter = maxiter) # 6 variables least squares - sol = tryls(radec, datetime2julian(A.date), sol(), params; maxiter = 5) + q0 = topo2bary(A, ρs[end], v_ρs[end]) + sol = tryls(radec, datetime2julian(A.date), q0, params; maxiter = 5) + if nrms(sol) < 1 + return sol + end end - + return sol end \ No newline at end of file From d670d64a99568108deeacbc198fbbc8bdeb28578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Mon, 4 Dec 2023 15:16:38 -0600 Subject: [PATCH 078/173] Automatic scaling --- src/observations/process_radec.jl | 4 +- .../orbit_determination.jl | 16 +++- src/orbit_determination/tooshortarc.jl | 78 +++++++++---------- 3 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index b46c537c..2db57e3e 100755 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -603,7 +603,7 @@ function extrapolation(df::AbstractDataFrame) # Only one observation if isone(nrow(df)) return (observatory = df.observatory[1], date = df.date[1], α = df.α[1], - δ = df.δ[1], v_α = 0.0, v_δ = 0.0) + δ = df.δ[1], v_α = 0.0, v_δ = 0.0, nobs = 1) end # Make sure there are no repeated dates @@ -636,7 +636,7 @@ function extrapolation(df::AbstractDataFrame) δ_mean = δ_coef[1] + δ_coef[2] * t_mean return (observatory = df.observatory[1], date = julian2datetime(df.t_julian[1] + t_mean), - α = α_mean, δ = δ_mean, v_α = α_coef[2], v_δ = δ_coef[2]) + α = α_mean, δ = δ_mean, v_α = α_coef[2], v_δ = δ_coef[2], nobs = nrow(df)) end @doc raw""" diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index b1ff77c7..247a5a1e 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -23,29 +23,37 @@ Initial Orbit Determination (IOD) routine. # Keyword arguments -- `maxiter::Int = 50`: maximum number of iterations. +- `maxiter::Int = 200`: maximum number of iterations. - `varorder::Int`: order of jet transport perturbation. - `max_triplets::Int`: maximum number of triplets. - `Q_max::T`: the maximum nrms that is considered a good enough orbit. - `niter::Int`: number of iterations for Newton's method. - `max_per::T = 18.0`: maximum allowed rejection percentage. """ -function orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}; maxiter::Int = 50, +function orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}; maxiter::Int = 200, max_triplets::Int = 10, Q_max::T = 10., niter::Int = 5, varorder::Int = 5, max_per::T = 18.0) where {T <: AbstractFloat} + + # Allocate memory for output + sol = zero(NEOSolution{T, T}) # Maximum number of steps params = Parameters(params; maxsteps = adaptative_maxsteps(radec)) # Eliminate observatories without coordinates filter!(x -> hascoord(observatory(x)), radec) + # Cannot handle zero observations or multiple arcs + if iszero(length(radec)) || !issinglearc(radec) + return sol + end # Reduce observation nights by linear regression gdf, cdf = reduce_nights(radec) - + # Case 1: Too Short Arc (TSA) if length(gdf) < 3 || numberofdays(radec) < 1 sol = tooshortarc(radec, gdf, cdf, params; maxiter) + # Case 2: Gauss Method else sol = gaussinitcond(radec, gdf, cdf, params; max_triplets, Q_max, niter, varorder) - if nrms(sol) > 1.0 + if nrms(sol) > 1.0 && !iszero(sol) sol = gauss_refinement(radec, sol, params; max_per, niter, varorder) end end diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index c53f3740..42deacf1 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -159,7 +159,7 @@ Return the maximum range for the left connected component of `A`. function max_range(A::AdmissibleRegion{T}) where {T <: AbstractFloat} # Find max_range ρ = find_zeros(s -> A.coeffs[2]^2/4 - admsreg_W(A, s) + 2*k_gauss^2/sqrt(admsreg_S(A, s)), - R_SI, 2.0)[1] + R_SI, 10.0)[1] # Make sure there is no sqrt(negative) niter = 0 while admsreg_S(A, ρ) < 0 && niter < 100 @@ -481,12 +481,12 @@ end ADAM minimizer of root mean square error over `A`. """ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; maxiter::Int = 200, α::T = 10.0, β_1::T = 0.75, + params::Parameters{T}; maxiter::Int = 200, α::T = 25.0, β_1::T = 0.5, β_2::T = 0.85, ϵ::T = 1e-8, Qtol::T = 0.01) where {T <: AbstractFloat} # Origin x0 = zeros(T, 2) # Scaling factors - scalings = [1e-3, 1e-5] + scalings = [max_range(A) - R_SI, boundary(A, 1)[2]- boundary(A, 0)[2]] / 1_000 # Jet transport variables dq = scaled_variables("dρ dvρ", scalings, order = 1) # Allocate memory @@ -544,55 +544,45 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T return ρs[1:niter], v_ρs[1:niter], Qs[1:niter] end +# Special method of tryls for tooshortarc function tryls(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{T}, params::Parameters{T}; maxiter::Int = 5) where {T <: AbstractFloat} + # Allocate memory + sols = zeros(NEOSolution{T, T}, maxiter) # Origin x0 = zeros(T, 6) # Scaling factors - scalings = [1e-5, 1e-5, 1e-5, 1e-7, 1e-7, 1e-7] + scalings = abs.(q0) ./ 10^5 # Jet transport variables dq = scaled_variables("dx", scalings, order = 6) - # Allocate memory - qs = Matrix{T}(undef, 6, maxiter+1) - Qs = Vector{T}(undef, maxiter+1) - # Initial conditions - qs[:, 1] = q0 - q = q0 + dq - bwd, fwd, res = propres(radec, jd0, q, params) - Qs[1] = nms(res(x0)) # Number of iterations niter = 1 # Minimization loop while niter <= maxiter - # Try fit + # Initial conditions + q = q0 + dq + # Propagation & residuals + bwd, fwd, res = propres(radec, jd0, q, params) + # Least squares fit fit = tryls(res, x0, 5) - # Temporary Q - _Q_ = nms(res(fit.x)) - if _Q_ < Qs[niter] - # Update values - q0 = q(fit.x) - # Save current variables - qs[:, niter+1] = q0 - Qs[niter+1] = _Q_ - - # Convergence condition - if Qs[niter+1] < 1 - return evalfit(NEOSolution(bwd, fwd, res, fit)) - end - - # New initial conditions - q = q0 + dq - # Update obbjective function - bwd, fwd, res = propres(radec, jd0, q, params) - - niter += 1 - - else + # Case: unsuccessful fit + if !fit.success || any(diag(fit.Γ) .< 0) break - end + end + # Current solution + sols[niter] = evalfit(NEOSolution(bwd, fwd, res, fit)) + # Convergence condition + if niter > 1 && nrms(sols[niter-1]) - nrms(sols[niter]) < 0.1 + break + end + # Update values + q0 = q(fit.x) + # Update number of iterations + niter += 1 end - return zero(NEOSolution{T, T}) + return sols[niter] + end @doc raw""" @@ -615,10 +605,10 @@ the admissible region. function tooshortarc(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::DataFrame, params::Parameters{T}; maxiter::Int = 200) where {T <: AbstractFloat} - # Number of observations per night - nobs = map(i -> nrow(gdf[i]), 1:nrow(cdf)) + # Reverse temporal order + reverse!(cdf) # Sort nights by number of observations - idxs = sortperm(nobs, rev = true) + idxs = sortperm(cdf.nobs, rev = true) # Allocate memory for output sol = zero(NEOSolution{T, T}) @@ -629,11 +619,13 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::Dat ρ = (R_SI + max_range(A)) / 2 v_ρ = sum(range_rate(A, R_SI)) / 2 # Minimization over admissible region - ρs, v_ρs, Qs = adam(radec, A, ρ, v_ρ, params; maxiter = maxiter) - # 6 variables least squares + ρs, v_ρs, Qs = adam(radec, A, ρ, v_ρ, params; maxiter) + # Barycentric initial conditions q0 = topo2bary(A, ρs[end], v_ρs[end]) + # 6 variables least squares sol = tryls(radec, datetime2julian(A.date), q0, params; maxiter = 5) - if nrms(sol) < 1 + + if nrms(sol) < 1.5 return sol end end From b479dfa3f054bd82c13e694bc099e457cb0fbf07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 6 Dec 2023 17:37:40 -0600 Subject: [PATCH 079/173] Tiny object boundary --- src/observations/process_radec.jl | 9 +- src/orbit_determination/tooshortarc.jl | 368 +++++++------------------ 2 files changed, 103 insertions(+), 274 deletions(-) diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index 2db57e3e..f812c7a3 100755 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -603,12 +603,12 @@ function extrapolation(df::AbstractDataFrame) # Only one observation if isone(nrow(df)) return (observatory = df.observatory[1], date = df.date[1], α = df.α[1], - δ = df.δ[1], v_α = 0.0, v_δ = 0.0, nobs = 1) + δ = df.δ[1], v_α = 0.0, v_δ = 0.0, mag = df.mag[1], nobs = 1) end # Make sure there are no repeated dates gdf = groupby(df, :date) - df = combine(gdf, [:α, :δ] .=> mean, :observatory => identity, renamecols = false) + df = combine(gdf, [:α, :δ, :mag] .=> mean, :observatory => identity, renamecols = false) # Julian days of observation df.t_julian = datetime2julian.(df.date) @@ -635,8 +635,11 @@ function extrapolation(df::AbstractDataFrame) α_mean = mod2pi(α_coef[1] + α_coef[2] * t_mean) δ_mean = δ_coef[1] + δ_coef[2] * t_mean + # Mean apparent magnitude + mag = mean(filter(!isnan, df.mag)) + return (observatory = df.observatory[1], date = julian2datetime(df.t_julian[1] + t_mean), - α = α_mean, δ = δ_mean, v_α = α_coef[2], v_δ = δ_coef[2], nobs = nrow(df)) + α = α_mean, δ = δ_mean, v_α = α_coef[2], v_δ = δ_coef[2], mag = mag, nobs = nrow(df)) end @doc raw""" diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 42deacf1..0b6895bf 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -11,9 +11,12 @@ some dynamical constrainits on a too short arc. - `δ::T`: declination. - `v_α::T`: right ascension velocity. - `v_δ::T`: declination velocity. -- `ρ_unit, ρ_α, _δ::Vector{T}`: topocentric unit vector and its partials. +- `ρ_unit, ρ_α, ρ_δ::Vector{T}`: topocentric unit vector and its partials. - `q::Vector{T}`: heliocentric position of observer. - `coeffs::Vector{T}`: polynomial coefficients. +- `ρ_domain::Vector{T}`: range domain. +- `v_ρ_domain::Vector{T}`: range-rate domain. +- `Fs::Matrix{T}`: boundary points. - `observatory::ObservatoryMPC{T}`: observing station. !!! reference @@ -30,13 +33,16 @@ some dynamical constrainits on a too short arc. ρ_δ::Vector{T} q::Vector{T} coeffs::Vector{T} + ρ_domain::Vector{T} + v_ρ_domain::Vector{T} + Fs::Matrix{T} observatory::ObservatoryMPC{T} end # Outer constructor function AdmissibleRegion(cdf::DataFrameRow) # Unfold - obs, t_datetime, α, δ, v_α, v_δ = cdf + obs, t_datetime, α, δ, v_α, v_δ, mag, _ = cdf # Topocentric unit vector and partials ρ, ρ_α, ρ_δ = topounitpdv(α, δ) # Time of observation [days since J2000] @@ -50,26 +56,36 @@ function AdmissibleRegion(cdf::DataFrameRow) q = eph_ea(t_days) + kmsec2auday(obsposvelECI(obs, t_et)) - eph_su(t_days) # Admissible region coefficients coeffs = admsreg_coeffs(α, δ, v_α, v_δ, ρ, ρ_α, ρ_δ, q) - + # Tiny object boundary + H_max = 32.0 # Maximum allowed absolute magnitude + if isnan(mag) + ρ_min = R_SI + else + ρ_min = 10^((mag - H_max)/5) + end + # Maximum range (heliocentric constraint) + ρ_max = find_zeros(s -> admsreg_U(coeffs, s), ρ_min, 10.0)[1] + # Make sure U(ρ) ≥ 0 + niter = 0 + while admsreg_U(coeffs, ρ_max) < 0 && niter < 1_000 + niter += 1 + ρ_max = prevfloat(ρ_max) + end + # Range domain + ρ_domain = [ρ_min, ρ_max] + # Range rate domain + v_ρ_min, v_ρ_max = range_rate(coeffs, ρ_min)[1:2] + v_ρ_domain = [v_ρ_min, v_ρ_max] + # Range rate symmetry level + v_ρ_mid = range_rate(coeffs, ρ_max)[1] + # Boundary points + Fs = Matrix{Float64}(undef, 3, 2) + Fs[1, :] .= [ρ_min, v_ρ_min] + Fs[2, :] .= [ρ_min, v_ρ_max] + Fs[3, :] .= [ρ_max, v_ρ_mid] + return AdmissibleRegion{Float64}(t_datetime, α, δ, v_α, v_δ, ρ, ρ_α, ρ_δ, q, - coeffs, obs) -end - -@doc raw""" - topounitpdv(α::T, δ::T) where {T <: Number} - -Return the topocentric unit vector and its partial derivatives with -respect to `α` and `δ`. -""" -function topounitpdv(α::T, δ::T) where {T <: Number} - sin_α, cos_α = sincos(α) - sin_δ, cos_δ = sincos(δ) - - ρ = [cos_δ * cos_α, cos_δ * sin_α, sin_δ] - ρ_α = [-sin_α * cos_δ, cos_α * cos_δ, zero(T)] - ρ_δ = [-cos_α * sin_δ, -sin_α * sin_δ, cos_δ] - - return ρ, ρ_α, ρ_δ + coeffs, ρ_domain, v_ρ_domain, Fs, obs) end @doc raw""" @@ -86,7 +102,7 @@ function admsreg_coeffs(α::T, δ::T, v_α::T, v_δ::T, ρ::Vector{T}, coeffs = Vector{T}(undef, 6) coeffs[1] = dot(q[1:3], q[1:3]) coeffs[2] = 2 * dot(q[4:6], ρ) - coeffs[3] = v_α^2 * cos(δ)^2 + v_δ^2 + coeffs[3] = v_α^2 * cos(δ)^2 + v_δ^2 coeffs[4] = 2 * v_α * dot(q[4:6], ρ_α) + 2 * v_δ * dot(q[4:6], ρ_δ) coeffs[5] = dot(q[4:6], q[4:6]) coeffs[6] = 2*dot(q[1:3], ρ) @@ -94,81 +110,83 @@ function admsreg_coeffs(α::T, δ::T, v_α::T, v_δ::T, ρ::Vector{T}, end @doc raw""" - solve_quadratic(a::T, b::T, c::T) where {T <: AbstractFloat} + topounitpdv(α::T, δ::T) where {T <: Number} -Return real solutions of cuadratic equation `ax² + bx + c = 0`. +Return the topocentric unit vector and its partial derivatives with +respect to `α` and `δ`. """ -function solve_quadratic(a::T, b::T, c::T) where {T <: AbstractFloat} - # Discriminant - Δ = b^2 - 4*a*c - # Cases - if Δ > 0 - x_1 = (-b + sqrt(Δ))/(2*a) - x_2 = (-b - sqrt(Δ))/(2*a) - elseif iszero(Δ) - x_1 = -b / (2*a) - x_2 = T(NaN) - else - x_1 = T(NaN) - x_2 = T(NaN) - end - - return x_1, x_2 +function topounitpdv(α::T, δ::T) where {T <: Number} + sin_α, cos_α = sincos(α) + sin_δ, cos_δ = sincos(δ) + + ρ = [cos_δ * cos_α, cos_δ * sin_α, sin_δ] + ρ_α = [-sin_α * cos_δ, cos_α * cos_δ, zero(T)] + ρ_δ = [-cos_α * sin_δ, -sin_α * sin_δ, cos_δ] + + return ρ, ρ_α, ρ_δ end @doc raw""" admsreg_W(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} -W function of an [`AdmissibleRegioin`](@ref). +W function of an [`AdmissibleRegion`](@ref). !!! reference See equation (8.9) of https://doi.org/10.1017/CBO9781139175371. """ -function admsreg_W(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} - return A.coeffs[3] * ρ^2 + A.coeffs[4] * ρ + A.coeffs[5] +function admsreg_W(coeffs::Vector{T}, ρ::S) where {T <: AbstractFloat, S <: Number} + return coeffs[3] * ρ^2 + coeffs[4] * ρ + coeffs[5] end +admsreg_W(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} = admsreg_W(A.coeffs, ρ) @doc raw""" admsreg_S(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} -S function of an [`AdmissibleRegioin`](@ref). +S function of an [`AdmissibleRegion`](@ref). !!! reference See equation (8.9) of https://doi.org/10.1017/CBO9781139175371. """ -function admsreg_S(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} - return ρ^2 + A.coeffs[6] * ρ + A.coeffs[1] +function admsreg_S(coeffs::Vector{T}, ρ::S) where {T <: AbstractFloat, S <: Number} + return ρ^2 + coeffs[6] * ρ + coeffs[1] end +admsreg_S(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} = admsreg_S(A.coeffs, ρ) @doc raw""" - range_rate(A::AdmissibleRegion{T}, ρ::S) where {T, S <: AbstractFloat} + admsreg_U(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} -Return the two possible range rates in the boundary of `A` for a given range `ρ`. +U function of an [`AdmissibleRegion`](@ref). + +!!! reference + See second equation after (8.9) of https://doi.org/10.1017/CBO9781139175371. """ -function range_rate(A::AdmissibleRegion{T}, ρ::S) where {T, S <: AbstractFloat} - c = admsreg_W(A, ρ) - 2*k_gauss^2/sqrt(admsreg_S(A, ρ)) - sol = solve_quadratic(one(T), A.coeffs[2], c) - return minmax(sol[1], sol[2]) +function admsreg_U(coeffs::Vector{T}, ρ::S) where {T <: AbstractFloat, S <: Number} + return coeffs[2]^2/4 - admsreg_W(coeffs, ρ) + 2*k_gauss^2/sqrt(admsreg_S(coeffs, ρ)) end +admsreg_U(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} = admsreg_U(A.coeffs, ρ) @doc raw""" - max_range(A::AdmissibleRegion{T}) where {T <: AbstractFloat} + admsreg_V(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} + +V function of an [`AdmissibleRegion`](@ref). -Return the maximum range for the left connected component of `A`. +!!! reference + See first equation after (8.9) of https://doi.org/10.1017/CBO9781139175371. """ -function max_range(A::AdmissibleRegion{T}) where {T <: AbstractFloat} - # Find max_range - ρ = find_zeros(s -> A.coeffs[2]^2/4 - admsreg_W(A, s) + 2*k_gauss^2/sqrt(admsreg_S(A, s)), - R_SI, 10.0)[1] - # Make sure there is no sqrt(negative) - niter = 0 - while admsreg_S(A, ρ) < 0 && niter < 100 - niter += 1 - ρ -= eps() - end - - return ρ +function admsreg_V(coeffs::Vector{T}, ρ::S, v_ρ::S) where {T <: AbstractFloat, S <: Number} + return v_ρ^2 + coeffs[2] * v_ρ + admsreg_W(coeffs, ρ) - 2*k_gauss^2/sqrt(admsreg_S(coeffs, ρ)) +end +admsreg_V(A::AdmissibleRegion{T}, ρ::S, v_ρ::S) where {T <: AbstractFloat, S <: Number} = admsreg_V(A.coeffs, ρ, v_ρ) + +@doc raw""" + range_rate(A::AdmissibleRegion{T}, ρ::S) where {T, S <: AbstractFloat} + +Return the two possible range rates in the boundary of `A` for a given range `ρ`. +""" +function range_rate(coeffs::Vector{T}, ρ::S) where {T, S <: AbstractFloat} + return find_zeros(s -> admsreg_V(coeffs, ρ, s), -10.0, 10.0) end +range_rate(A::AdmissibleRegion{T}, ρ::S) where {T, S <: AbstractFloat} = range_rate(A.coeffs, ρ) @doc raw""" boundary(A::AdmissibleRegion{T}, t::S) where {T <: AbstractFloat, S <: Number} @@ -179,20 +197,20 @@ function boundary(A::AdmissibleRegion{T}, t::S) where {T <: AbstractFloat, S <: # Parametrization domain @assert 0.0 <= t <= 3.0 # Lower (upper) bounds - y_min, y_max = range_rate(A, R_SI) - # ρ = R_SI + x_min, x_max = A.ρ_domain + y_min, y_max = A.v_ρ_domain + # ρ = x_min if 0.0 <= t <= 1.0 - return [R_SI, y_min + t * (y_max - y_min)] + return [x_min, y_min + t * (y_max - y_min)] else - x_max = max_range(A) # Upper curve if 1.0 <= t <= 2.0 - ρ = R_SI + (t-1)*(x_max - R_SI) - _, v_ρ = range_rate(A, ρ) + ρ = x_min + (t-1)*(x_max - x_min) + v_ρ = range_rate(A, ρ)[end] # Lower curve elseif 2.0 <= t <= 3.0 - ρ = x_max - (t-2)*(x_max - R_SI) - v_ρ, _ = range_rate(A, ρ) + ρ = x_max - (t-2)*(x_max - x_min) + v_ρ = range_rate(A, ρ)[1] end return [ρ, v_ρ] end @@ -205,7 +223,7 @@ Project `[ρ, v_ρ]` into `A`'s boundary. """ function boundary_projection(A::AdmissibleRegion{T}, ρ::T, v_ρ::T) where {T <: AbstractFloat} # Project range - ρ = clamp(ρ, R_SI, max_range(A)) + ρ = clamp(ρ, A.ρ_domain[1], A.ρ_domain[2]) # Project range-rate y_min, y_max = range_rate(A, ρ) v_ρ = clamp(v_ρ, y_min, y_max) @@ -216,7 +234,7 @@ end # Check whether P is inside A's boundary function in(P::Vector{T}, A::AdmissibleRegion{T}) where {T <: AbstractFloat} @assert length(P) == 2 "Points in admissible region are of dimension 2" - if R_SI <= P[1] <= max_range(A) && boundary(A, 0.0)[2] <= P[2] <= boundary(A, 1.0)[2] + if A.ρ_domain[1] <= P[1] <= A.ρ_domain[2] && A.v_ρ_domain[1] <= P[2] <= A.v_ρ_domain[2] y_min, y_max = range_rate(A, P[1]) return y_min <= P[2] <= y_max else @@ -281,198 +299,6 @@ function propres(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{U}, return bwd, fwd, res end -@doc raw""" - gradient_descent(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; maxiter::Int = 200) where {T <: AbstractFloat} - -Gradient descent minimizer of root mean square error over `A`. -""" -function gradient_descent(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; maxiter::Int = 200) where {T <: AbstractFloat} - # Origin - x0 = zeros(T, 2) - # Scaling factors - scalings = [1e-3, 1e-5] - # Jet transport variables - dq = scaled_variables("dρ dvρ", scalings, order = 1) - # Allocate memory - ρs = Vector{T}(undef, maxiter+1) - v_ρs = Vector{T}(undef, maxiter+1) - Qs = fill(T(Inf), maxiter+1) - # Initial time of integration [julian days] - jd0 = datetime2julian(A.date) - # Initial conditions - ρs[1] = ρ - v_ρs[1] = v_ρ - q0 = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) - _, _, res = propres(radec, jd0, q0, params) - Q = nms(res) - Qs[1] = Q(x0) - # Number of iterations - niter = 0 - # Gradient descent - while niter < maxiter - # Update number of iterations - niter += 1 - # Gradient of objective function - dQ = TaylorSeries.gradient(Q)(x0) - # Step - x1 = x0 - normalize(dQ) - # Update values - ρ, v_ρ = bary2topo(A, q0(x1)) - # Projection - ρ, v_ρ = boundary_projection(A, ρ, v_ρ) - # New initial conditions - q0 = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) - # Update objective function - _, _, res = propres(radec, jd0, q0, params) - Q = nms(res) - # Convergence condition - if Q(x0) > Qs[niter] - break - end - # Save current variables - ρs[niter+1] = ρ - v_ρs[niter+1] = v_ρ - Qs[niter+1] = Q(x0) - end - - niter = argmin(Qs) - - return ρs[1:niter], v_ρs[1:niter], Qs[1:niter] -end - -@doc raw""" - momentum_descent(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; maxiter::Int = 200, α::T = 10.0, - β::T = 0.75, Qtol::T = 0.01) where {T <: AbstractFloat} - -Momentum gradient descent minimizer of root mean square error over `A`. -""" -function momentum_descent(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; maxiter::Int = 200, α::T = 10.0, - β::T = 0.75, Qtol::T = 0.01) where {T <: AbstractFloat} - # Origin - x0 = zeros(T, 2) - # Scaling factors - scalings = [1e-3, 1e-5] - # Jet transport variables - dq = scaled_variables("dρ dvρ", scalings, order = 1) - # Allocate memory - ρs = Vector{T}(undef, maxiter+1) - v_ρs = Vector{T}(undef, maxiter+1) - Qs = fill(T(Inf), maxiter+1) - # Initial time of integration [julian days] - jd0 = datetime2julian(A.date) - # Initial conditions - ρs[1] = ρ - v_ρs[1] = v_ρ - q0 = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) - _, _, res = propres(radec, jd0, q0, params) - Q = nms(res) - Qs[1] = Q(x0) - m = zeros(T, 2) - # Number of iterations - niter = 0 - # Gradient descent - while niter < maxiter - # Update number of iterations - niter += 1 - # Gradient of objective function - dQ = TaylorSeries.gradient(Q)(x0) - # Momentum - m = β * m + (1 - β) * dQ - # Step - x1 = x0 - α * m - # Update values - ρ, v_ρ = bary2topo(A, q0(x1)) - # Projection - ρ, v_ρ = boundary_projection(A, ρ, v_ρ) - # New initial conditions - q0 = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) - # Update obbjective function - _, _, res = propres(radec, jd0, q0, params) - Q = nms(res) - # Convergence condition - if abs(Q(x0) - Qs[niter]) < Qtol - break - end - # Save current variables - ρs[niter+1] = ρ - v_ρs[niter+1] = v_ρ - Qs[niter+1] = Q(x0) - end - - niter = argmin(Qs) - - return ρs[1:niter], v_ρs[1:niter], Qs[1:niter] -end - -@doc raw""" - rmsprop(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; maxiter::Int = 200, α::T = 10.0, β::T = 0.9, - ϵ::T = 1e-8, Qtol::T = 0.01) where {T <: AbstractFloat} - -RMSPROP minimizer of root mean square error over `A`. -""" -function rmsprop(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; maxiter::Int = 200, α::T = 10.0, β::T = 0.9, - ϵ::T = 1e-8, Qtol::T = 0.01) where {T <: AbstractFloat} - # Origin - x0 = zeros(T, 2) - # Scaling factors - scalings = [1e-3, 1e-5] - # Jet transport variables - dq = scaled_variables("dρ dvρ", scalings, order = 1) - # Allocate memory - ρs = Vector{T}(undef, maxiter+1) - v_ρs = Vector{T}(undef, maxiter+1) - Qs = fill(T(Inf), maxiter+1) - # Initial time of integration [julian days] - jd0 = datetime2julian(A.date) - # Initial conditions - ρs[1] = ρ - v_ρs[1] = v_ρ - q0 = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) - Q, _ = nms6v(radec, q0, jd0, params) - Qs[1] = Q(x0) - v = zeros(T, 2) - # Number of iterations - niter = 0 - # Gradient descent - while niter < maxiter - # Update number of iterations - niter += 1 - # Gradient of objective function - dQ = TaylorSeries.gradient(Q)(x0) - # Sum of square of past gradients - v = β * v + (1 - β) * dQ .^ 2 - # Step - x1 = x0 - α * dQ ./ sqrt.(v .+ ϵ) - # Update values - ρ, v_ρ = bary2topo(A, q0(x1)) - # Projection - ρ, v_ρ = boundary_projection(A, ρ, v_ρ) - # New initial conditions - q0 = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) - # Update obbjective function - _, _, res = propres(radec, jd0, q0, params) - Q = nms(res) - # Convergence condition - if abs(Q(x0) - Qs[niter]) < Qtol - break - end - # Save current variables - ρs[niter+1] = ρ - v_ρs[niter+1] = v_ρ - Qs[niter+1] = Q(x0) - end - - niter = argmin(Qs) - - return ρs[1:niter], v_ρs[1:niter], Qs[1:niter] -end - @doc raw""" adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, params::Parameters{T}; maxiter::Int = 200, α::T = 10.0, β_1::T = 0.75, @@ -486,7 +312,7 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T # Origin x0 = zeros(T, 2) # Scaling factors - scalings = [max_range(A) - R_SI, boundary(A, 1)[2]- boundary(A, 0)[2]] / 1_000 + scalings = [A.ρ_domain[2] - A.ρ_domain[1], A.v_ρ_domain[2] - A.v_ρ_domain[1]] / 1_000 # Jet transport variables dq = scaled_variables("dρ dvρ", scalings, order = 1) # Allocate memory @@ -616,8 +442,8 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::Dat # Admissible region A = AdmissibleRegion(cdf[i, :]) # Center - ρ = (R_SI + max_range(A)) / 2 - v_ρ = sum(range_rate(A, R_SI)) / 2 + ρ = sum(A.ρ_domain) / 2 + v_ρ = sum(A.v_ρ_domain) / 2 # Minimization over admissible region ρs, v_ρs, Qs = adam(radec, A, ρ, v_ρ, params; maxiter) # Barycentric initial conditions From 12e36e92acc1fc5e1003258e75a5d11eb49468fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 9 Dec 2023 17:41:36 -0600 Subject: [PATCH 080/173] Minor fixes --- src/orbit_determination/gauss_method.jl | 2 +- src/orbit_determination/orbit_determination.jl | 16 +++++++++++----- src/orbit_determination/tooshortarc.jl | 8 ++++++-- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 037d1084..452ee8a1 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -435,7 +435,7 @@ See also [`gauss_method`](@ref). This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. """ function gaussinitcond(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::DataFrame, - params::Parameters{T}; max_triplets::Int = 10, Q_max::T = 10., + params::Parameters{T}; max_triplets::Int = 10, Q_max::T = 5.0, niter::Int = 5, varorder::Int = 5) where {T <: AbstractFloat} # Allocate memory for initial conditions diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index 247a5a1e..600ba292 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -2,6 +2,12 @@ include("osculating.jl") include("tooshortarc.jl") include("gauss_method.jl") +@doc raw""" + issinglearc(radec::Vector{RadecMPC{T}}, arc::Day = Day(30)) where {T <: AbstractFloat} + +Check whether `radec` is a single observational arc, i.e. no two consecutive observations +are more than `arc` days appart. +""" function issinglearc(radec::Vector{RadecMPC{T}}, arc::Day = Day(30)) where {T <: AbstractFloat} for i in 2:length(radec) if date(radec[i]) - date(radec[i-1]) > arc @@ -24,14 +30,14 @@ Initial Orbit Determination (IOD) routine. # Keyword arguments - `maxiter::Int = 200`: maximum number of iterations. -- `varorder::Int`: order of jet transport perturbation. -- `max_triplets::Int`: maximum number of triplets. -- `Q_max::T`: the maximum nrms that is considered a good enough orbit. -- `niter::Int`: number of iterations for Newton's method. +- `max_triplets::Int = 10`: maximum number of triplets. +- `Q_max::T = 5.0`: the maximum nrms that is considered a good enough orbit. +- `niter::Int = 5`: number of iterations for Newton's method. +- `varorder::Int = 5`: order of jet transport perturbation. - `max_per::T = 18.0`: maximum allowed rejection percentage. """ function orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}; maxiter::Int = 200, - max_triplets::Int = 10, Q_max::T = 10., niter::Int = 5, + max_triplets::Int = 10, Q_max::T = 5.0, niter::Int = 5, varorder::Int = 5, max_per::T = 18.0) where {T <: AbstractFloat} # Allocate memory for output diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 0b6895bf..33ab0fcb 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -235,8 +235,12 @@ end function in(P::Vector{T}, A::AdmissibleRegion{T}) where {T <: AbstractFloat} @assert length(P) == 2 "Points in admissible region are of dimension 2" if A.ρ_domain[1] <= P[1] <= A.ρ_domain[2] && A.v_ρ_domain[1] <= P[2] <= A.v_ρ_domain[2] - y_min, y_max = range_rate(A, P[1]) - return y_min <= P[2] <= y_max + y_range = range_rate(A, P[1]) + if length(y_range) == 1 + return P[2] == y_range + else + return y_range[1] <= P[2] <= y_range[2] + end else return false end From c360026ad29646e4870754d6af041c08ae9ea35c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 19 Dec 2023 17:00:15 -0600 Subject: [PATCH 081/173] ObservationNight --- .gitignore | 1 + src/observations/observation_night.jl | 133 ++++++++++++++++++++++++++ src/observations/process_radar.jl | 1 + src/observations/process_radec.jl | 74 +------------- src/observations/radec_mpc.jl | 2 +- src/observations/topocentric.jl | 2 +- test/observations.jl | 24 +++++ 7 files changed, 162 insertions(+), 75 deletions(-) create mode 100644 src/observations/observation_night.jl diff --git a/.gitignore b/.gitignore index adaa2e71..1a18b9f6 100755 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ jldeph/ notebooks/figs EOP_IAU*.TXT Manifest.toml +*.DS_Store diff --git a/src/observations/observation_night.jl b/src/observations/observation_night.jl new file mode 100644 index 00000000..9a103bc5 --- /dev/null +++ b/src/observations/observation_night.jl @@ -0,0 +1,133 @@ +@doc raw""" + ObservationNight{T <: AbstractFloat} + +A set of optical observations taken by the same observatory on the same night. + +# Fields + +- `radec::Vector{RadecMPC{T}}`: vector of observations. +- `observatory::ObservatoryMPC{T}`: observing station. +- `night::TimeOfDay`: night of observation. +- `date::DateTime`: mean date of observation. +- `α::T`: mean right ascension. +- `δ::T`: mean declination. +- `v_α::T`: mean right ascension velocity. +- `v_δ::T`: mean declination velocity. +- `mag::T`: mean apparent magnitude. +- `nobs::Int`: number of observations. +""" +@auto_hash_equals struct ObservationNight{T <: AbstractFloat} + radec::Vector{RadecMPC{T}} + observatory::ObservatoryMPC{T} + night::TimeOfDay + date::DateTime + α::T + δ::T + v_α::T + v_δ::T + mag::T + nobs::Int + # Inner constructor + function ObservationNight{T}(radec::Vector{RadecMPC{T}}, observatory::ObservatoryMPC{T}, + night::TimeOfDay, date::DateTime, α::T, δ::T, v_α::T, + v_δ::T, mag::T, nobs::Int) where {T <: AbstractFloat} + + return new{T}(radec, observatory, night, date, α, δ, v_α, v_δ, mag, nobs) + end +end + +# Print method for ObservationNight{T} +# Examples: +# 3 observation night around 2023-11-18T19:59:55.392 at WFST, Lenghu +# 4 observation night around 2023-11-22T08:07:46.336 at Mt. Lemmon Survey +function show(io::IO, x::ObservationNight{T}) where {T <: AbstractFloat} + print(io, x.nobs, " observation night around ", x.date, " at ", x.observatory.name) +end + +# Order in ObservationNight is given by date +isless(a::ObservationNight{T}, b::ObservationNight{T}) where {T <: AbstractFloat} = a.date < b.date + +# Outer constructor +function ObservationNight(radec::Vector{RadecMPC{T}}, df::AbstractDataFrame) where {T <: AbstractFloat} + # Defining quantities of an ObservationNight + observatory = df.observatory[1] + night = df.TimeOfDay[1] + nobs = nrow(df) + + # Only one observation + if isone(nobs) + date = df.date[1] + α, δ = df.α[1], df.δ[1] + v_α, v_δ = zero(T), zero(T) + mag = df.mag[1] + return ObservationNight{T}(radec, observatory, night, date, α, + δ, v_α, v_δ, mag, nobs) + end + + # Make sure there are no repeated dates + gdf = groupby(df, :date) + df = combine(gdf, [:α, :δ, :mag] .=> mean, renamecols = false) + + # Julian days of observation + df.t_julian = datetime2julian.(df.date) + # Days of observation [relative to first observation] + df.t_rel = df.t_julian .- df.t_julian[1] + # Mean date [relative to first observation] + t_mean = mean(df.t_rel) + # Mean date [DateTime] + date = julian2datetime(df.t_julian[1] + t_mean) + + # Points in top quarter + N_top = count(x -> x > 3π/2, df.α) + # Points in bottom quarter + N_bottom = count(x -> x < π/2, df.α) + # Discontinuity + if !iszero(N_top) && !iszero(N_bottom) + df.α = map(x -> x < π ? x + 2π : x, df.α) + end + + # Linear regression + α_p = lm(@formula(α ~ t_rel), df) + α_coef = coef(α_p) + δ_p = lm(@formula(δ ~ t_rel), df) + δ_coef = coef(δ_p) + + # Evaluate polynomials at mean date + α = mod2pi(α_coef[1] + α_coef[2] * t_mean) + δ = δ_coef[1] + δ_coef[2] * t_mean + v_α = α_coef[2] + v_δ = δ_coef[2] + + # Mean apparent magnitude + mag = mean(filter(!isnan, df.mag)) + + return ObservationNight{T}(radec, observatory, night, date, α, δ, v_α, + v_δ, mag, nobs) +end + +@doc raw""" + reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + +Return a `Vector{ObservationNight{T}}` where each eleement corresponds to a batch of +observations taken by the same observatory on the same night. +The reduction is performed via linear regression. +""" +function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + # Convert to DataFrame + df = DataFrame(radec) + # Compute TimeOfDay + df.TimeOfDay = TimeOfDay.(radec) + # Group by observatory and TimeOfDay + gdf = groupby(df, [:observatory, :TimeOfDay]) + # Allocate memmory for nights vector + nights = Vector{ObservationNight{T}}(undef, gdf.ngroups) + # Reduce nights + Threads.@threads for i in 1:gdf.ngroups + rows = getfield(gdf[i], :rows) + nights[i] = ObservationNight(radec[rows], gdf[i]) + end + # Sort by date + sort!(nights) + + return nights +end \ No newline at end of file diff --git a/src/observations/process_radar.jl b/src/observations/process_radar.jl index 7cd4eb0d..24de6d13 100755 --- a/src/observations/process_radar.jl +++ b/src/observations/process_radar.jl @@ -5,6 +5,7 @@ include("radar_jpl.jl") include("units.jl") include("jpl_eph.jl") include("topocentric.jl") +include("observation_night.jl") include("process_radec.jl") @doc raw""" diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index f812c7a3..6595087b 100755 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -592,76 +592,4 @@ function residuals(obs::Vector{RadecMPC{T}}, mpc_catalogue_codes_201X::Vector{St end return res -end - -@doc raw""" - extrapolation(df::AbstractDataFrame) - -Special method of [`extrapolation`](@ref) to be used by [`gaussinitcond`](@ref). -""" -function extrapolation(df::AbstractDataFrame) - # Only one observation - if isone(nrow(df)) - return (observatory = df.observatory[1], date = df.date[1], α = df.α[1], - δ = df.δ[1], v_α = 0.0, v_δ = 0.0, mag = df.mag[1], nobs = 1) - end - - # Make sure there are no repeated dates - gdf = groupby(df, :date) - df = combine(gdf, [:α, :δ, :mag] .=> mean, :observatory => identity, renamecols = false) - - # Julian days of observation - df.t_julian = datetime2julian.(df.date) - # Days of observation [relative to first observation] - df.t_rel = df.t_julian .- df.t_julian[1] - # Mean date - t_mean = mean(df.t_rel) - - # Points in top quarter - N_top = count(x -> x > 3π/2, df.α) - # Points in bottom quarter - N_bottom = count(x -> x < π/2, df.α) - # Discontinuity - if !iszero(N_top) && !iszero(N_bottom) - df.α = map(x -> x < π ? x + 2π : x, df.α) - end - # Linear regression - α_p = lm(@formula(α ~ t_rel), df) - α_coef = coef(α_p) - δ_p = lm(@formula(δ ~ t_rel), df) - δ_coef = coef(δ_p) - - # Evaluate polynomials at mean date - α_mean = mod2pi(α_coef[1] + α_coef[2] * t_mean) - δ_mean = δ_coef[1] + δ_coef[2] * t_mean - - # Mean apparent magnitude - mag = mean(filter(!isnan, df.mag)) - - return (observatory = df.observatory[1], date = julian2datetime(df.t_julian[1] + t_mean), - α = α_mean, δ = δ_mean, v_α = α_coef[2], v_δ = δ_coef[2], mag = mag, nobs = nrow(df)) -end - -@doc raw""" - reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - -Return one observatory, date, right ascension and declination per observation night in `radec`. The reduction is performed -via polynomial interpolation. -""" -function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - # Convert to DataFrame - df = DataFrame(radec) - # Compute TimeOfDay - df.TimeOfDay = TimeOfDay.(df.date, df.observatory) - # Group by observatory and TimeOfDay - gdf = groupby(df, [:observatory, :TimeOfDay]) - # Interpolate observation nights - cdf = combine(gdf, extrapolation, keepkeys = false) - # Eliminate unsuccesful interpolations - filter!(:α => !isnan, cdf) - filter!(:δ => !isnan, cdf) - # Sort by date - idxs = sortperm(cdf, :date) - - return gdf[idxs], cdf[idxs, :] -end \ No newline at end of file +end \ No newline at end of file diff --git a/src/observations/radec_mpc.jl b/src/observations/radec_mpc.jl index 809e3009..be682448 100755 --- a/src/observations/radec_mpc.jl +++ b/src/observations/radec_mpc.jl @@ -418,7 +418,7 @@ rows(x::Vector{<:AbstractAstrometry}) = x schema(::Vector{T}) where {T <: AbstractAstrometry} = Schema(fieldnames(T), Tuple{fieldtypes(T)...}) # Methods to convert a DataFrame to a Vector{<:AbstractAstrometry} -function Vector{T}(df::DataFrame) where {T <: AbstractAstrometry} +function Vector{T}(df::AbstractDataFrame) where {T <: AbstractAstrometry} @assert all(String.(fieldnames(T)) .== names(df)) "`DataFrame` column names don't match `$T` fieldnames" @assert all(fieldtypes(T) .== eltype.(eachcol(df))) "`DataFrame` column types don't match `$T` fieldtypes" obs = Vector{T}(undef, nrow(df)) diff --git a/src/observations/topocentric.jl b/src/observations/topocentric.jl index a251e583..8a4ea583 100755 --- a/src/observations/topocentric.jl +++ b/src/observations/topocentric.jl @@ -50,7 +50,7 @@ isnight(x::TimeOfDay) = x.light == :night # Night from 2023-06-29 to 2023-06-29 at UTC-7 # Night from 2023-06-29 to 2023-06-30 at UTC+3 function show(io::IO, m::TimeOfDay) - print(io, uppercasefirst(string(m.light)), " from ", m.start, " to ", m.stop, + print(io, uppercasefirst(string(m.light)), " from ", Date(m.start), " to ", Date(m.stop), " at UTC", @sprintf("%+d", m.utc)) end diff --git a/test/observations.jl b/test/observations.jl index 21866593..3734e15f 100755 --- a/test/observations.jl +++ b/test/observations.jl @@ -283,4 +283,28 @@ using NEOs: src_path end + @testset "ObservationNight" begin + using NEOs: reduce_nights + + # Choose this example because of the discontinuity in α + + # Optical astrometry file + filename = joinpath("data", "2020_TJ6.txt") + # Download optical astrometry + get_radec_mpc("designation" => "2020 TJ6", filename) + # Parse observations + radec = read_radec_mpc(filename) + # Reduce observation nights + nights = reduce_nights(radec) + # Remove downloaded file + rm(filename) + + # Values by December 19, 2023 + @test length(nights) == 5 + @test getfield.(nights, :nobs) == [4, 4, 3, 4, 3] + @test nights[3].α ≈ 6.2831 atol = 1e-4 + @test nights[3].observatory == search_obs_code("J04") + @test nights[3].night.utc == -1 + end + end From 7f37ac9e53446810248b8b562a5441548d989f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 21 Dec 2023 07:38:14 -0600 Subject: [PATCH 082/173] Fixes to Gauss Method --- src/NEOs.jl | 2 +- src/observations/observation_night.jl | 21 +- src/observations/process_radec.jl | 49 +-- src/observations/topocentric.jl | 31 +- src/orbit_determination/gauss_method.jl | 325 +++++------------- .../orbit_determination.jl | 32 +- src/orbit_determination/outlier_rejection.jl | 183 ++++++++++ src/postprocessing/neosolution.jl | 86 +++-- src/propagation/parameters.jl | 82 +++++ src/propagation/propagation.jl | 65 +--- 10 files changed, 487 insertions(+), 389 deletions(-) create mode 100644 src/orbit_determination/outlier_rejection.jl create mode 100644 src/propagation/parameters.jl diff --git a/src/NEOs.jl b/src/NEOs.jl index c3b1075f..fe05b6fd 100755 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -69,7 +69,7 @@ export tooshortarc # Gauss method export gauss_method, gaussinitcond, gauss_refinement # Orbit determination -export issinglearc, orbitdetermination +export issinglearc, orbitdetermination, sigmas include("constants.jl") include("observations/process_radar.jl") diff --git a/src/observations/observation_night.jl b/src/observations/observation_night.jl index 9a103bc5..60cc7a54 100644 --- a/src/observations/observation_night.jl +++ b/src/observations/observation_night.jl @@ -15,6 +15,7 @@ A set of optical observations taken by the same observatory on the same night. - `v_δ::T`: mean declination velocity. - `mag::T`: mean apparent magnitude. - `nobs::Int`: number of observations. +- `idxs::Vector{Int}`: indices of original `radec` that entered the night. """ @auto_hash_equals struct ObservationNight{T <: AbstractFloat} radec::Vector{RadecMPC{T}} @@ -27,15 +28,23 @@ A set of optical observations taken by the same observatory on the same night. v_δ::T mag::T nobs::Int + indices::Vector{Int} # Inner constructor function ObservationNight{T}(radec::Vector{RadecMPC{T}}, observatory::ObservatoryMPC{T}, - night::TimeOfDay, date::DateTime, α::T, δ::T, v_α::T, - v_δ::T, mag::T, nobs::Int) where {T <: AbstractFloat} + night::TimeOfDay, date::DateTime, α::T, δ::T, v_α::T, v_δ::T, + mag::T, nobs::Int, indices::Vector{Int}) where {T <: AbstractFloat} - return new{T}(radec, observatory, night, date, α, δ, v_α, v_δ, mag, nobs) + return new{T}(radec, observatory, night, date, α, δ, v_α, v_δ, mag, nobs, indices) end end +# Functions to get specific fields of a ObservationNight object +date(x::ObservationNight{T}) where {T <: AbstractFloat} = x.date +ra(x::ObservationNight{T}) where {T <: AbstractFloat} = x.α +dec(x::ObservationNight{T}) where {T <: AbstractFloat} = x.δ +observatory(x::ObservationNight{T}) where {T <: AbstractFloat} = x.observatory +indices(x::ObservationNight{T}) where {T <: AbstractFloat} = x.indices + # Print method for ObservationNight{T} # Examples: # 3 observation night around 2023-11-18T19:59:55.392 at WFST, Lenghu @@ -53,7 +62,7 @@ function ObservationNight(radec::Vector{RadecMPC{T}}, df::AbstractDataFrame) whe observatory = df.observatory[1] night = df.TimeOfDay[1] nobs = nrow(df) - + indices = getfield(df, :rows) # Only one observation if isone(nobs) date = df.date[1] @@ -61,7 +70,7 @@ function ObservationNight(radec::Vector{RadecMPC{T}}, df::AbstractDataFrame) whe v_α, v_δ = zero(T), zero(T) mag = df.mag[1] return ObservationNight{T}(radec, observatory, night, date, α, - δ, v_α, v_δ, mag, nobs) + δ, v_α, v_δ, mag, nobs, indices) end # Make sure there are no repeated dates @@ -102,7 +111,7 @@ function ObservationNight(radec::Vector{RadecMPC{T}}, df::AbstractDataFrame) whe mag = mean(filter(!isnan, df.mag)) return ObservationNight{T}(radec, observatory, night, date, α, δ, v_α, - v_δ, mag, nobs) + v_δ, mag, nobs, indices) end @doc raw""" diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index 6595087b..c00f0984 100755 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -93,6 +93,9 @@ weight_dec(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.w_δ relax_factor(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.relax_factor outlier(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.outlier +euclid3D(x::Vector{U}) where {U <: Number} = sqrt(x[1]*x[1] + x[2]*x[2] + x[3]*x[3]) +dot3D(x::Vector{U}, y::Vector{V}) where {U, V <: Number} = x[1]*y[1] + x[2]*y[2] + x[3]*y[3] + @doc raw""" compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; kwargs...) where {T <: AbstractFloat} compute_radec(obs::RadecMPC{T}; kwargs...) where {T <: AbstractFloat} @@ -119,29 +122,30 @@ All ephemeris must take [et seconds since J2000] and return [barycentric positio and velocity in km/sec]. """ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter::Int = 5, - xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} + xvs::SunEph = sunposvel, xve::EarthEph = earthposvel, + xva::AstEph) where {T <: AbstractFloat, SunEph, EarthEph, AstEph} # Transform receiving time from UTC to TDB seconds since J2000 et_r_secs = datetime2et(t_r_utc) - # Compute geocentric position/velocity of receiving antenna in inertial frame [km, km/s] - RV_r = obsposvelECI(observatory, et_r_secs) - R_r = RV_r[1:3] + # Sun barycentric position and velocity at receive time + rv_s_t_r = xvs(et_r_secs) + r_s_t_r = rv_s_t_r[1:3] # Earth's barycentric position and velocity at receive time rv_e_t_r = xve(et_r_secs) r_e_t_r = rv_e_t_r[1:3] - # Receiver barycentric position and velocity at receive time - r_r_t_r = r_e_t_r + R_r # Asteroid barycentric position and velocity at receive time rv_a_t_r = xva(et_r_secs) r_a_t_r = rv_a_t_r[1:3] - # Sun barycentric position and velocity at receive time - rv_s_t_r = xvs(et_r_secs) - r_s_t_r = rv_s_t_r[1:3] - + # Compute geocentric position/velocity of receiving antenna in inertial frame [km, km/s] + RV_r = obsposvelECI(observatory, et_r_secs) + R_r = RV_r[1:3] + # Receiver barycentric position and velocity at receive time + r_r_t_r = r_e_t_r + R_r + # Down-leg iteration # τ_D first approximation # See equation (1) of https://doi.org/10.1086/116062 ρ_vec_r = r_a_t_r - r_r_t_r - ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) + ρ_r = euclid3D(ρ_vec_r) # -R_b/c, but delay is wrt asteroid Center (Brozovic et al., 2018) τ_D = ρ_r/clightkms # (seconds) # Bounce time, new estimate @@ -164,7 +168,7 @@ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter: ρ_vec_r = r_a_t_b - r_r_t_r # Magnitude of ρ_vec_r # See equation (4) of https://doi.org/10.1086/116062 - ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) + ρ_r = euclid3D(ρ_vec_r) # Compute down-leg Shapiro delay # NOTE: when using PPN, substitute 2 -> 1+γ in expressions for Shapiro delay, @@ -173,14 +177,14 @@ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter: # Earth's position at t_r e_D_vec = r_r_t_r - r_s_t_r # Heliocentric distance of Earth at t_r - e_D = sqrt(e_D_vec[1]^2 + e_D_vec[2]^2 + e_D_vec[3]^2) + e_D = euclid3D(e_D_vec) # Barycentric position of Sun at estimated bounce time rv_s_t_b = xvs(et_b_secs) r_s_t_b = rv_s_t_b[1:3] # Heliocentric position of asteroid at t_b p_D_vec = r_a_t_b - r_s_t_b # Heliocentric distance of asteroid at t_b - p_D = sqrt(p_D_vec[1]^2 + p_D_vec[2]^2 + p_D_vec[3]^2) + p_D = euclid3D(p_D_vec) # Signal path distance (down-leg) q_D = ρ_r @@ -194,7 +198,7 @@ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter: Δτ_D = Δτ_rel_D # + Δτ_tropo_D #+ Δτ_corona_D # seconds # New estimate - p_dot_23 = dot(ρ_vec_r, v_a_t_b)/ρ_r + p_dot_23 = dot3D(ρ_vec_r, v_a_t_b)/ρ_r # Time delay correction Δt_2 = (τ_D - ρ_r/clightkms - Δτ_rel_D)/(1.0-p_dot_23/clightkms) # Time delay new estimate @@ -203,6 +207,7 @@ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter: # See equation (2) of https://doi.org/10.1086/116062 et_b_secs = et_r_secs - τ_D end + # Asteroid barycentric position (in km) and velocity (in km/s) at bounce time (TDB) rv_a_t_b = xva(et_b_secs) r_a_t_b = rv_a_t_b[1:3] @@ -212,7 +217,7 @@ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter: ρ_vec_r = r_a_t_b - r_r_t_r # Magnitude of ρ_vec_r # See equation (4) of https://doi.org/10.1086/116062 - ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) + ρ_r = euclid3D(ρ_vec_r) # TODO: add aberration and atmospheric refraction corrections @@ -226,15 +231,15 @@ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter: rv_s_t_b = xvs(et_b_secs) r_s_t_b = rv_s_t_b[1:3] Q_vec = r_a_t_b - r_s_t_b # ESAA 2014, equation (7.113) - q_vec = Q_vec/sqrt(Q_vec[1]^2 + Q_vec[2]^2 + Q_vec[3]^2) - E_H = sqrt(E_H_vec[1]^2 + E_H_vec[2]^2 + E_H_vec[3]^2) + q_vec = Q_vec/ euclid3D(Q_vec) + E_H = euclid3D(E_H_vec) e_vec = E_H_vec/E_H # See ESAA 2014, equation (7.115) g1 = (2μ_DE430[su]/(c_au_per_day^2))/(E_H/au) - g2 = 1 + dot(q_vec, e_vec) + g2 = 1 + dot3D(q_vec, e_vec) # See ESAA 2014, equation (7.116) - u1_vec = U_norm*( u_vec + (g1/g2)*( dot(u_vec,q_vec)*e_vec - dot(e_vec,u_vec)*q_vec ) ) - u1_norm = sqrt(u1_vec[1]^2 + u1_vec[2]^2 + u1_vec[3]^2) + u1_vec = U_norm*( u_vec + (g1/g2)*( dot3D(u_vec,q_vec)*e_vec - dot3D(e_vec,u_vec)*q_vec ) ) + u1_norm = euclid3D(u1_vec) # Compute right ascension, declination angles α_rad_ = mod2pi(atan(u1_vec[2], u1_vec[1])) @@ -570,7 +575,7 @@ function residuals(obs::Vector{RadecMPC{T}}, mpc_catalogue_codes_201X::Vector{St δ_obs = rad2arcsec(dec(obs[i])) # arcsec # Computed ra/dec - α_comp, δ_comp = compute_radec(obs[i]; xva, kwargs...) # arcsec + α_comp, δ_comp = compute_radec(obs[i]; xva = xva, kwargs...) # arcsec # Debiasing corrections α_corr, δ_corr = debiasing(obs[i], mpc_catalogue_codes_201X, truth, resol, bias_matrix) diff --git a/src/observations/topocentric.jl b/src/observations/topocentric.jl index 8a4ea583..3e1dc3f1 100755 --- a/src/observations/topocentric.jl +++ b/src/observations/topocentric.jl @@ -243,7 +243,7 @@ function sv_ecef_to_eci( end @doc raw""" - obsposvelECI(observatory::ObservatoryMPC{T}, et::T; kwarg) where {T <: AbstractFloat} + obsposvelECI(observatory::ObservatoryMPC{T}, et::U; kwarg) where {T <: AbstractFloat, U <: Number} obsposvelECI(x::RadecMPC{T}; kwarg) where {T <: AbstractFloat} obsposvelECI(x::RadarJPL{T}; kwarg) where {T <: AbstractFloat} @@ -260,21 +260,25 @@ See also [`SatelliteToolboxBase.OrbitStateVector`](@ref) and # Arguments - `observatory::ObservatoryMPC{T}`: observation site. -- `et::T`: ephemeris time (TDB seconds since J2000.0 epoch). +- `et::U`: ephemeris time (TDB seconds since J2000.0 epoch). +- `x::RadecMPC{T}/RadarJPL{T}`: astrometric observation. # Keyword argument - `eop::Union{EopIau1980, EopIau2000A}`: Earth Orientation Parameters (eop). """ -function obsposvelECI(observatory::ObservatoryMPC{T}, et::ET; - eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat, ET<:Union{T,Taylor1{T},Taylor1{TaylorN{T}}}} +function obsposvelECI(observatory::ObservatoryMPC{T}, et::U; + eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat, U <: Number} # Make sure observatory has coordinates @assert hascoord(observatory) "Cannot compute position for observatory [$(observatory.code)] without coordinates" + # One with correct type + oneU = one(et) if issatellite(observatory) || isoccultation(observatory) - #@assert datetime2et(observatory.date) == cte(et) - return [observatory.long, observatory.cos, observatory.sin, zero(T), zero(T), zero(T)] + # @assert datetime2et(observatory.date) == cte(et) + return [observatory.long * oneU, observatory.cos * oneU, observatory.sin * oneU, + zero(et), zero(et), zero(et)] else # Earth-Centered Earth-Fixed position position of observer pos_ECEF = obsposECEF(observatory) @@ -291,13 +295,18 @@ function obsposvelECI(observatory::ObservatoryMPC{T}, et::ET; # GCRF: Geocentric Celestial Reference Frame pv_ECI = sv_ecef_to_eci(pv_ECEF, Val(:ITRF), Val(:GCRF), jd_utc, eop) + # ECI state vector (of correct type) + r_ECI = Vector{U}(undef, 6) # Inertial position - p_ECI = convert(Vector{eltype(pv_ECI.r)}, pv_ECI.r) + for i in eachindex(pv_ECI.r) + r_ECI[i] = pv_ECI.r[i] * oneU + end # Inertial velocity - v_ECI = convert(Vector{eltype(pv_ECI.v)}, pv_ECI.v) - - # Concat position and velocity - return vcat(p_ECI, v_ECI) + for i in eachindex(pv_ECI.v) + r_ECI[i+3] = pv_ECI.v[i] * oneU + end + + return r_ECI end end diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 452ee8a1..bbe35802 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -75,7 +75,8 @@ topounit(obs::RadecMPC{T}) where {T <: AbstractFloat} = topounit(obs.α, obs.δ) Return the 1st order approximation to Lagrange's f function. """ function f_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} - return 1 - μ_S * (τ^2) / 2 / (r^3) + r3 = r * r * r + return 1 - μ_S * (τ^2) / 2 / r3 end @doc raw""" @@ -84,7 +85,8 @@ end Return the 1st order approximation to Lagrange's g function. """ function g_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} - return τ - μ_S * (τ^3) / 6 / (r^3) + r3 = r * r * r + return τ - μ_S * (τ^3) / 6 / r3 end @doc raw""" @@ -112,14 +114,24 @@ end Lagrange polynomial to be solved during Gauss method. """ -lagrange(x::T, a::U, b::U, c::U) where {T, U <: Number} = x^8 + a*x^6 + b*x^3 + c +function lagrange(x::T, a::U, b::U, c::U) where {T, U <: Number} + # Evaluate via Horner's method + x2 = x * x + x3 = x2 * x + return c + x3 * (b + x3 * (a + x2)) +end @doc raw""" lagrange_derivative(x::T, a::T, b::T) where {T <: Number} Derivative of Lagrange polynomial to be solved during Gauss method. """ -lagrange_derivative(x::T, a::U, b::U) where {T, U <: Number} = 8*x^7 + 6*a*x^5 + 3*b*x^2 +function lagrange_derivative(x::T, a::U, b::U) where {T, U <: Number} + # Evaluate via Horner's method + x2 = x * x + x3 = x2 * x + return x2 * (3*b + x3 * (6*a + 8*x2)) +end # TO DO: Allow to control interval over which to look for solutions # Currently we look between the radius of the Sun (∼0.00465047 AU) and @@ -142,11 +154,13 @@ function solve_lagrange(a::TaylorN{T}, b::TaylorN{T}, c::TaylorN{T}; niter::Int sol_0 = solve_lagrange(cte(a), cte(b), cte(c)) # Vector of solutions sol = Vector{TaylorN{T}}(undef, length(sol_0)) + # Conversion factor to TaylorN + oneN = one(a) # Iterate solutions for i in eachindex(sol) # Newton's method - r_0 = sol_0[i] - r_2 = sol_0[i] + r_0::TaylorN{T} = sol_0[i] * oneN + r_2::TaylorN{T} = sol_0[i] * oneN for j in 1:niter r_2 = r_0 - lagrange(r_0, a, b, c) / lagrange_derivative(r_0, a, b) r_0 = r_2 @@ -237,9 +251,9 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da # Cross products p_vec = zeros(U, 3, 3) - p_vec[1, :] = cross(ρ_vec[2, :], ρ_vec[3, :]) - p_vec[2, :] = cross(ρ_vec[1, :], ρ_vec[3, :]) - p_vec[3, :] = cross(ρ_vec[1, :], ρ_vec[2, :]) + p_vec[1, :] = @views cross(ρ_vec[2, :], ρ_vec[3, :]) + p_vec[2, :] = @views cross(ρ_vec[1, :], ρ_vec[3, :]) + p_vec[3, :] = @views cross(ρ_vec[1, :], ρ_vec[2, :]) # Gauss scalar D_0 = dot(ρ_vec[1, :], p_vec[1, :]) @@ -248,7 +262,7 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da D = zeros(U, 3, 3) for i in 1:3 for j in 1:3 - D[i, j] = dot(R_vec[i, :], p_vec[j, :]) + D[i, j] = @views dot(R_vec[i, :], p_vec[j, :]) end end @@ -257,13 +271,13 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da B = (D[1, 2]*(τ_3^2 - τ^2)*τ_3/τ + D[3, 2]*(τ^2 - τ_1^2)*τ_1/τ) / 6 / D_0 # E and F scalars - E = dot(R_vec[2, :], ρ_vec[2, :]) - F = dot(R_vec[2, :], R_vec[2, :]) + E = @views dot(R_vec[2, :], ρ_vec[2, :]) + F = @views dot(R_vec[2, :], R_vec[2, :]) # Lagrange equation coefficients - a = -(A^2 + 2*A*E + F) + a = -(A*A + 2*A*E + F) b = -2*μ_S*B*(A + E) - c = -(μ_S^2)*(B^2) + c = -(μ_S^2)*(B*B) # Solve Lagrange equation sol = solve_lagrange(a, b, c; niter = niter) @@ -284,21 +298,23 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da for i in eachindex(sol_gauss) # Heliocentric range r_2 = sol[i] + # Range cubed + r_23 = r_2 * r_2 * r_2 # Slant ranges ρ = zeros(U, 3) - num_1 = 6*(D[3, 1]*τ_1/τ_3 + D[2, 1]*τ/τ_3)*(r_2^3) + μ_S*D[3, 1]*(τ^2 - τ_1^2)*τ_1/τ_3 - den_1 = 6*(r_2^3) + μ_S*(τ^2 - τ_3^2) + num_1 = 6*(D[3, 1]*τ_1/τ_3 + D[2, 1]*τ/τ_3)*r_23 + μ_S*D[3, 1]*(τ^2 - τ_1^2)*τ_1/τ_3 + den_1 = 6*r_23 + μ_S*(τ^2 - τ_3^2) ρ[1] = (num_1 / den_1 - D[1, 1]) / D_0 - ρ[2] = A + μ_S*B/(r_2^3) + ρ[2] = A + μ_S*B/r_23 - num_3 = 6*(D[1, 3]*τ_3/τ_1 - D[2, 3]*τ/τ_1)*(r_2^3) + μ_S*D[1, 3]*(τ^2 - τ_3^2)*τ_3/τ_1 - den_3 = 6*(r_2^3) + μ_S*(τ^2 - τ_1^2) + num_3 = 6*(D[1, 3]*τ_3/τ_1 - D[2, 3]*τ/τ_1)*r_23 + μ_S*D[1, 3]*(τ^2 - τ_3^2)*τ_3/τ_1 + den_3 = 6*r_23 + μ_S*(τ^2 - τ_1^2) ρ[3] = (num_3 / den_3 - D[3, 3]) / D_0 # Heliocentric position of the NEO - r_vec = R_vec .+ ρ.*ρ_vec + r_vec = R_vec .+ ρ .* ρ_vec # f, g Lagrange coefficients f_1 = f_Lagrange(τ_1, r_2) @@ -308,9 +324,10 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da g_3 = g_Lagrange(τ_3, r_2) # Heliocentric velocity of the NEO - v_2_vec = (- f_3 * r_vec[1, :] + f_1 * r_vec[3, :]) / (f_1*g_3 - f_3*g_1) + v_2_vec = @views (- f_3 * r_vec[1, :] + f_1 * r_vec[3, :]) / (f_1*g_3 - f_3*g_1) - sol_gauss[i] = GaussSolution{T, U}(vcat(r_vec[2, :], v_2_vec), D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3) + sol_gauss[i] = GaussSolution{T, U}(vcat(r_vec[2, :], v_2_vec), D, R_vec, ρ_vec, + τ_1, τ_3, f_1, g_1, f_3, g_3) end # Sort solutions by heliocentric range return sort!(sol_gauss, by = x -> norm(cte.(x.statevect[1:3]))) @@ -411,45 +428,42 @@ end @doc raw""" - gaussinitcond(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::DataFrame, - params::Parameters{T}; kwargs...) where {T <: AbstractFloat} + gaussinitcond(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, + params::Parameters{T}) where {T <: AbstractFloat} -Return initial conditions via Gauss method. +Return initial conditions via Gauss Method. See also [`gauss_method`](@ref). # Arguments - `radec::Vector{RadecMPC{T}}`: vector of observations. -- `gdf::GroupedDataFrame`, `cdf::DataFrame`: output of [`reduce_nights`](@ref). -- `params::Parameters{T}`: see [`Parameters`](@ref). - -# Keyword arguments - -- `varorder::Int`: order of jet transport perturbation. -- `max_triplets::Int`: maximum number of triplets. -- `Q_max::T`: the maximum nrms that is considered a good enough orbit. -- `niter::Int`: number of iterations for Newton's method. +- `nights::Vector{ObservationNight{T}},`: vector of observation nights. +- `params::Parameters{T}`: see `Gauss Method Parameters` of [`Parameters`](@ref). !!! warning This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. """ -function gaussinitcond(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::DataFrame, - params::Parameters{T}; max_triplets::Int = 10, Q_max::T = 5.0, - niter::Int = 5, varorder::Int = 5) where {T <: AbstractFloat} +function gaussinitcond(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, + params::Parameters{T}) where {T <: AbstractFloat} # Allocate memory for initial conditions best_sol = zero(NEOSolution{T, T}) # Unfold - observatories, dates, α, δ = cdf.observatory, cdf.date, cdf.α, cdf.δ + observatories, dates, α, δ = observatory.(nights), date.(nights), ra.(nights), dec.(nights) # Observations triplets - triplets = gauss_triplets(dates, max_triplets) + triplets = gauss_triplets(dates, params.max_triplets) # Julian day of first (last) observation t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) # Julian day when to start propagation jd0 = zero(T) + # Start point of LS fits + x0 = zeros(T, 6) + # Jet transport scaling factors + scalings = fill(1e-6, 6) # Jet transport perturbation (ra/dec) - dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃"; order = varorder) + dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃", scalings, + order = params.varorder) # Sun's ephemeris eph_su = selecteph(sseph, su) # Earth's ephemeris @@ -466,13 +480,13 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::D triplet = triplets[j] # Julian day when to start propagation jd0 = datetime2julian(dates[triplet[2]]) - # Number of years in forward integration + # Number of years in forward integration nyears_fwd = (tf - jd0 + 2) / yr # Number of years in backward integration nyears_bwd = -(jd0 - t0 + 2) / yr # Gauss method solution sol = gauss_method(observatories[triplet], dates[triplet], α[triplet] .+ dq[1:3], - δ[triplet] .+ dq[4:6]; niter = niter) + δ[triplet] .+ dq[4:6]; niter = params.niter) # Filter Gauss solutions by heliocentric energy filter!(x -> heliocentric_energy(x.statevect) <= 0, sol) @@ -480,38 +494,44 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::D for i in eachindex(sol) # Initial conditions (jet transport) - q0 = sol[i].statevect .+ eph_su(jd0 - PE.J2000) + q0::Vector{TaylorN{T}} = sol[i].statevect .+ eph_su(jd0 - PE.J2000) # Backward propagation - bwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q0, params) + bwd::TaylorInterpolant{T, TaylorN{T}, 2} = propagate( + RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q0, params + ) - if bwd.t[end] > t0 - jd0 + if bwd.t[end]::T > t0 - jd0 continue end # Forward propagation - fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q0, params) + fwd::TaylorInterpolant{T, TaylorN{T}, 2} = propagate( + RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q0, params + ) - if fwd.t[end] < tf - jd0 + if fwd.t[end]::T < tf - jd0 continue end # O-C residuals - res = residuals(radec, params; - xvs = et -> auday2kmsec(eph_su(et/daysec)), - xve = et -> auday2kmsec(eph_ea(et/daysec)), - xva = et -> bwdfwdeph(et, bwd, fwd)) + res::Vector{OpticalResidual{T, TaylorN{T}}} = residuals( + radec, params; + xvs = et -> auday2kmsec(eph_su(et/daysec)), + xve = et -> auday2kmsec(eph_ea(et/daysec)), + xva = et -> bwdfwdeph(et, bwd, fwd) + ) # Subset of radec for orbit fit g_0 = triplet[1] g_f = triplet[3] - idxs = findall(x -> g_0 <= x <= g_f, gdf.groups) + idxs = reduce(vcat, indices.(nights[g_0:g_f])) sort!(idxs) # Orbit fit - fit = tryls(res[idxs], zeros(get_numvars()), niter) + fit = tryls(res[idxs], x0, params.niter) !fit.success && continue # Right iteration - for k in g_f+1:length(gdf) - extra = findall(x -> x == k, gdf.groups) - fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) + for k in g_f+1:length(nights) + extra = indices(nights[k]) + fit_new = tryls(res[idxs ∪ extra], x0, params.niter) if fit_new.success fit = fit_new idxs = vcat(idxs, extra) @@ -523,8 +543,8 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::D # Left iteration for k in g_0-1:-1:1 - extra = findall(x -> x == k, gdf.groups) - fit_new = tryls(res[idxs ∪ extra], zeros(get_numvars()), niter) + extra = indices(nights[k]) + fit_new = tryls(res[idxs ∪ extra], x0, params.niter) if fit_new.success fit = fit_new idxs = vcat(idxs, extra) @@ -541,10 +561,11 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::D # Update NRMS and initial conditions if Q < best_Q best_Q = Q - best_sol = evalfit(NEOSolution(bwd, fwd, res[idxs], fit)) + best_sol = evalfit(NEOSolution(nights, bwd, fwd, res[idxs], + fit, scalings)) end # Break condition - if Q <= Q_max + if Q <= params.Q_max flag = true break end @@ -562,188 +583,4 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::D return best_sol end -end - -@doc raw""" - residual_norm(x::OpticalResidual{T, T}) where {T <: Real} - -Return the contribution of `x` to the nrms. -""" -residual_norm(x::OpticalResidual{T, T}) where {T <: Real} = x.w_α * x.ξ_α^2 / x.relax_factor + x.w_δ * x.ξ_δ^2 / x.relax_factor - -@doc raw""" - gauss_refinement(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, params::Parameters{T}; - kwargs...) where {T <: AbstractFloat} - -Refine an orbit computed by [`gaussinitcond`](@ref) via propagation and/or outlier rejection. - -# Arguments - -- `radec::Vector{RadecMPC{T}}`: vector of observations. -- `sol::NEOSolution{T, T}`: orbit to be refined. -- `params::Parameters{T}`: see [`Parameters`](@ref). - -# Keyword arguments - -- `max_per::T = 18.0`: maximum allowed rejection percentage. -- `niter::Int = 5`: number of iterations. -- `varorder::Int`: order of jet transport perturbation. -""" -function gauss_refinement(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, params::Parameters{T}; - max_per::T = 18.0, niter::Int = 5, varorder::Int = 5) where {T <: AbstractFloat} - - # Sun's ephemeris - eph_su = selecteph(sseph, su) - # Earth's ephemeris - eph_ea = selecteph(sseph, ea) - # Julian day to start propagation - jd0 = sol.bwd.t0 + PE.J2000 - # Julian day of first (last) observation - t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) - # Number of years in forward integration - nyears_fwd = (tf - jd0 + 2) / yr - # Number of years in backward integration - nyears_bwd = -(jd0 - t0 + 2) / yr - # Dynamical function - dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! - # Maximum number of steps - params = Parameters(params; maxsteps = adaptative_maxsteps(radec)) - # Initial conditions (T) - q00 = sol(sol.bwd.t0) - # Jet transport perturbation - dq = scaled_variables("δx", fill(1e-6, 6); order = varorder) - # Initial conditions (jet transport) - q0 = q00 .+ dq - - # Backward integration - bwd = propagate(dynamics, jd0, nyears_bwd, q0, params) - - if bwd.t[end] > t0 - jd0 - return zero(NEOSolution{T, T}) - end - - # Forward integration - fwd = propagate(dynamics, jd0, nyears_fwd, q0, params) - - if fwd.t[end] < tf - jd0 - return zero(NEOSolution{T, T}) - end - - # Residuals - res = residuals(radec, params; - xvs = et -> auday2kmsec(eph_su(et/daysec)), - xve = et -> auday2kmsec(eph_ea(et/daysec)), - xva = et -> bwdfwdeph(et, bwd, fwd)) - # Orbit fit - fit = tryls(res, zeros(get_numvars()), niter) - - # NRMS (with 0 outliers) - Q_0 = nrms(res, fit) - - if Q_0 < 1 - return evalfit(NEOSolution(bwd, fwd, res, fit)) - end - - # Number of observations - N_radec = length(radec) - # Maximum allowed outliers - max_drop = ceil(Int, N_radec * max_per / 100) - # Boolean mask (0: included in fit, 1: outlier) - new_outliers = BitVector(zeros(N_radec)) - - # Drop loop - for i in 1:max_drop - # Contribution of each residual to nrms - norms = residual_norm.(res(fit.x)) - # Iterate norms from largest to smallest - idxs = sortperm(norms, rev = true) - - for j in idxs - if !new_outliers[j] - # Drop residual - new_outliers[j] = true - # Update residuals - res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), - relax_factor.(res), new_outliers) - # Update fit - fit = tryls(res, zeros(get_numvars()), niter) - break - end - end - end - - # Outliers - idxs = Vector{Int}(undef, max_drop) - # NRMS - Qs = Vector{T}(undef, max_drop + 1) - # Number of outliers - N_outliers = Vector{T}(undef, max_drop + 1) - - # Recovery loop - for i in 1:max_drop - # NRMS of current fit - Qs[i] = nrms(res, fit) - # Number of outliers in current fit - N_outliers[i] = float(max_drop - i + 1) - # Contribution of each residual to nrms - norms = residual_norm.(res(fit.x)) - # Minimum norm among outliers - j = findmin(norms[new_outliers])[2] - # Find residual with minimum norm - j = findall(new_outliers)[j] - # Add j-th residual to outliers list - idxs[i] = j - # Recover residual - new_outliers[j] = false - # Update residuals - res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), - relax_factor.(res), new_outliers) - # Update fit - fit = tryls(res, zeros(get_numvars()), niter) - end - # Add 0 outliers fit - Qs[end] = Q_0 - N_outliers[end] = zero(T) - - # Outlier rejection cannot reduce Q - if all(Qs .> 1.) - # Reset boolean mask - new_outliers[1:end] .= false - # Update residuals - res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), - relax_factor.(res), new_outliers) - # Update fit - fit = tryls(res, zeros(get_numvars()), niter) - - return evalfit(NEOSolution(bwd, fwd, res, fit)) - end - - if max_drop > 1 - # Assemble points - points = Matrix{T}(undef, 2, max_drop + 1) - for i in eachindex(Qs) - points[1, i] = Qs[i] - points[2, i] = N_outliers[i] - end - # K-means clustering - cluster = kmeans(points, 2) - # Index of smallest cluster - i_0 = cluster.assignments[1] - # Find last fit of smallest cluster - i = findfirst(x -> x != i_0, cluster.assignments) - 1 - # Update outliers indexes - idxs = idxs[i:end] - end - - # Reset boolean mask - new_outliers[1:end] .= false - # Outliers - new_outliers[idxs] .= true - # Update residuals - res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), - relax_factor.(res), new_outliers) - # Update fit - fit = tryls(res, zeros(get_numvars()), niter) - - return evalfit(NEOSolution(bwd, fwd, res, fit)) end \ No newline at end of file diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index 600ba292..71a165f6 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -6,7 +6,7 @@ include("gauss_method.jl") issinglearc(radec::Vector{RadecMPC{T}}, arc::Day = Day(30)) where {T <: AbstractFloat} Check whether `radec` is a single observational arc, i.e. no two consecutive observations -are more than `arc` days appart. +are more than `arc` days appart. The function assumes `radec` is sorted. """ function issinglearc(radec::Vector{RadecMPC{T}}, arc::Day = Day(30)) where {T <: AbstractFloat} for i in 2:length(radec) @@ -18,7 +18,8 @@ function issinglearc(radec::Vector{RadecMPC{T}}, arc::Day = Day(30)) where {T <: end @doc raw""" - orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}; kwargs...) where {T <: AbstractFloat} + orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}; + kwargs...) where {T <: AbstractFloat} Initial Orbit Determination (IOD) routine. @@ -30,15 +31,10 @@ Initial Orbit Determination (IOD) routine. # Keyword arguments - `maxiter::Int = 200`: maximum number of iterations. -- `max_triplets::Int = 10`: maximum number of triplets. -- `Q_max::T = 5.0`: the maximum nrms that is considered a good enough orbit. -- `niter::Int = 5`: number of iterations for Newton's method. -- `varorder::Int = 5`: order of jet transport perturbation. - `max_per::T = 18.0`: maximum allowed rejection percentage. """ -function orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}; maxiter::Int = 200, - max_triplets::Int = 10, Q_max::T = 5.0, niter::Int = 5, - varorder::Int = 5, max_per::T = 18.0) where {T <: AbstractFloat} +function orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}; + maxiter::Int = 200, max_per::T = 18.0) where {T <: AbstractFloat} # Allocate memory for output sol = zero(NEOSolution{T, T}) @@ -48,22 +44,22 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}; m filter!(x -> hascoord(observatory(x)), radec) # Cannot handle zero observations or multiple arcs if iszero(length(radec)) || !issinglearc(radec) - return sol + return sol::NEOSolution{T, T} end # Reduce observation nights by linear regression - gdf, cdf = reduce_nights(radec) + nights = reduce_nights(radec) # Case 1: Too Short Arc (TSA) - if length(gdf) < 3 || numberofdays(radec) < 1 + if length(nights) < 3 || numberofdays(radec) < 1 sol = tooshortarc(radec, gdf, cdf, params; maxiter) # Case 2: Gauss Method else - sol = gaussinitcond(radec, gdf, cdf, params; max_triplets, Q_max, niter, - varorder) - if nrms(sol) > 1.0 && !iszero(sol) - sol = gauss_refinement(radec, sol, params; max_per, niter, varorder) - end + sol = gaussinitcond(radec, nights, params) + end + # Outlier rejection (if needed) + if nrms(sol) > 1.0 && !iszero(sol) + sol = gauss_refinement(radec, sol, params; max_per, niter, varorder) end - return sol + return sol::NEOSolution{T, T} end \ No newline at end of file diff --git a/src/orbit_determination/outlier_rejection.jl b/src/orbit_determination/outlier_rejection.jl new file mode 100644 index 00000000..1da31530 --- /dev/null +++ b/src/orbit_determination/outlier_rejection.jl @@ -0,0 +1,183 @@ +@doc raw""" + residual_norm(x::OpticalResidual{T, T}) where {T <: Real} + +Return the contribution of `x` to the nrms. +""" +residual_norm(x::OpticalResidual{T, T}) where {T <: Real} = x.w_α * x.ξ_α^2 / x.relax_factor + x.w_δ * x.ξ_δ^2 / x.relax_factor + +@doc raw""" + gauss_refinement(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, params::Parameters{T}; + kwargs...) where {T <: AbstractFloat} + +Refine an orbit computed by [`gaussinitcond`](@ref) via propagation and/or outlier rejection. + +# Arguments + +- `radec::Vector{RadecMPC{T}}`: vector of observations. +- `sol::NEOSolution{T, T}`: orbit to be refined. +- `params::Parameters{T}`: see [`Parameters`](@ref). + +# Keyword arguments + +- `max_per::T = 18.0`: maximum allowed rejection percentage. +- `niter::Int = 5`: number of iterations. +- `varorder::Int`: order of jet transport perturbation. +""" +function gauss_refinement(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, params::Parameters{T}; + max_per::T = 18.0, niter::Int = 5, varorder::Int = 5) where {T <: AbstractFloat} + + # Sun's ephemeris + eph_su = selecteph(sseph, su) + # Earth's ephemeris + eph_ea = selecteph(sseph, ea) + # Julian day to start propagation + jd0 = sol.bwd.t0 + PE.J2000 + # Julian day of first (last) observation + t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) + # Number of years in forward integration + nyears_fwd = (tf - jd0 + 2) / yr + # Number of years in backward integration + nyears_bwd = -(jd0 - t0 + 2) / yr + # Dynamical function + dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! + # Maximum number of steps + params = Parameters(params; maxsteps = adaptative_maxsteps(radec)) + # Initial conditions (T) + q00 = sol(sol.bwd.t0) + # Jet transport perturbation + dq = scaled_variables("δx", fill(1e-6, 6); order = varorder) + # Initial conditions (jet transport) + q0 = q00 .+ dq + + # Backward integration + bwd = propagate(dynamics, jd0, nyears_bwd, q0, params) + + if bwd.t[end] > t0 - jd0 + return zero(NEOSolution{T, T}) + end + + # Forward integration + fwd = propagate(dynamics, jd0, nyears_fwd, q0, params) + + if fwd.t[end] < tf - jd0 + return zero(NEOSolution{T, T}) + end + + # Residuals + res = residuals(radec, params; + xvs = et -> auday2kmsec(eph_su(et/daysec)), + xve = et -> auday2kmsec(eph_ea(et/daysec)), + xva = et -> bwdfwdeph(et, bwd, fwd)) + # Orbit fit + fit = tryls(res, zeros(get_numvars()), niter) + + # NRMS (with 0 outliers) + Q_0 = nrms(res, fit) + + if Q_0 < 1 + return evalfit(NEOSolution(bwd, fwd, res, fit)) + end + + # Number of observations + N_radec = length(radec) + # Maximum allowed outliers + max_drop = ceil(Int, N_radec * max_per / 100) + # Boolean mask (0: included in fit, 1: outlier) + new_outliers = BitVector(zeros(N_radec)) + + # Drop loop + for i in 1:max_drop + # Contribution of each residual to nrms + norms = residual_norm.(res(fit.x)) + # Iterate norms from largest to smallest + idxs = sortperm(norms, rev = true) + + for j in idxs + if !new_outliers[j] + # Drop residual + new_outliers[j] = true + # Update residuals + res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), + relax_factor.(res), new_outliers) + # Update fit + fit = tryls(res, zeros(get_numvars()), niter) + break + end + end + end + + # Outliers + idxs = Vector{Int}(undef, max_drop) + # NRMS + Qs = Vector{T}(undef, max_drop + 1) + # Number of outliers + N_outliers = Vector{T}(undef, max_drop + 1) + + # Recovery loop + for i in 1:max_drop + # NRMS of current fit + Qs[i] = nrms(res, fit) + # Number of outliers in current fit + N_outliers[i] = float(max_drop - i + 1) + # Contribution of each residual to nrms + norms = residual_norm.(res(fit.x)) + # Minimum norm among outliers + j = findmin(norms[new_outliers])[2] + # Find residual with minimum norm + j = findall(new_outliers)[j] + # Add j-th residual to outliers list + idxs[i] = j + # Recover residual + new_outliers[j] = false + # Update residuals + res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), + relax_factor.(res), new_outliers) + # Update fit + fit = tryls(res, zeros(get_numvars()), niter) + end + # Add 0 outliers fit + Qs[end] = Q_0 + N_outliers[end] = zero(T) + + # Outlier rejection cannot reduce Q + if all(Qs .> 1.) + # Reset boolean mask + new_outliers[1:end] .= false + # Update residuals + res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), + relax_factor.(res), new_outliers) + # Update fit + fit = tryls(res, zeros(get_numvars()), niter) + + return evalfit(NEOSolution(bwd, fwd, res, fit)) + end + + if max_drop > 1 + # Assemble points + points = Matrix{T}(undef, 2, max_drop + 1) + for i in eachindex(Qs) + points[1, i] = Qs[i] + points[2, i] = N_outliers[i] + end + # K-means clustering + cluster = kmeans(points, 2) + # Index of smallest cluster + i_0 = cluster.assignments[1] + # Find last fit of smallest cluster + i = findfirst(x -> x != i_0, cluster.assignments) - 1 + # Update outliers indexes + idxs = idxs[i:end] + end + + # Reset boolean mask + new_outliers[1:end] .= false + # Outliers + new_outliers[idxs] .= true + # Update residuals + res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), + relax_factor.(res), new_outliers) + # Update fit + fit = tryls(res, zeros(get_numvars()), niter) + + return evalfit(NEOSolution(bwd, fwd, res, fit)) +end \ No newline at end of file diff --git a/src/postprocessing/neosolution.jl b/src/postprocessing/neosolution.jl index a085df11..be8f779a 100755 --- a/src/postprocessing/neosolution.jl +++ b/src/postprocessing/neosolution.jl @@ -8,51 +8,79 @@ The outcome of the orbit determination process for a NEO. # Fields +- `nights::Vector{ObservationNight{T}}`: vector of observation nights. - `bwd/fwd::TaylorInterpolant{T, U, 2}`: backward (forward) integration. - `t_bwd/t_fwd::Vector{U}`: time of Earth close approach. - `x_bwd/x_fwd::Vector{U}`: state vector at Earth close approach. - `g_bwd/g_fwd::Vector{U}`: geocentric distance at close approach. - `res::Vector{OpticalResidual{T, U}}`: vector of optical residuals. - `fit::OrbitFit{T}`: least squares fit. +- `scalings::Vector{T}`: jet transport scaling factors. """ @auto_hash_equals struct NEOSolution{T <: Real, U <: Number} + nights::Vector{ObservationNight{T}} bwd::TaylorInterpolant{T, U, 2} t_bwd::Vector{U} - x_bwd::Vector{U} + x_bwd::Matrix{U} g_bwd::Vector{U} fwd::TaylorInterpolant{T, U, 2} t_fwd::Vector{U} - x_fwd::Vector{U} + x_fwd::Matrix{U} g_fwd::Vector{U} res::Vector{OpticalResidual{T, U}} fit::OrbitFit{T} + scalings::Vector{T} # Inner constructor - function NEOSolution{T, U}(bwd::TaylorInterpolant{T, U, 2}, t_bwd::Vector{U}, x_bwd::Vector{U}, g_bwd::Vector{U}, - fwd::TaylorInterpolant{T, U, 2}, t_fwd::Vector{U}, x_fwd::Vector{U}, g_fwd::Vector{U}, - res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}) where {T <: Real, U <: Number} + function NEOSolution{T, U}( + nights::Vector{ObservationNight{T}}, + bwd::TaylorInterpolant{T, U, 2}, t_bwd::Vector{U}, x_bwd::Matrix{U}, g_bwd::Vector{U}, + fwd::TaylorInterpolant{T, U, 2}, t_fwd::Vector{U}, x_fwd::Matrix{U}, g_fwd::Vector{U}, + res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}, scalings::Vector{T} + ) where {T <: Real, U <: Number} @assert bwd.t0 == fwd.t0 "Backward and forward propagation initial times must match" - new{T, U}(bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, res, fit) + new{T, U}( + nights, + bwd, t_bwd, x_bwd, g_bwd, + fwd, t_fwd, x_fwd, g_fwd, + res, fit, scalings + ) end end # Outer constructors -function NEOSolution(bwd::TaylorInterpolant{T, U, 2}, t_bwd::Vector{U}, x_bwd::Vector{U}, g_bwd::Vector{U}, - fwd::TaylorInterpolant{T, U, 2}, t_fwd::Vector{U}, x_fwd::Vector{U}, g_fwd::Vector{U}, - res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}) where {T <: Real, U <: Number} - NEOSolution{T, U}(bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, res, fit) +function NEOSolution( + nights::Vector{ObservationNight{T}}, + bwd::TaylorInterpolant{T, U, 2}, t_bwd::Vector{U}, x_bwd::Matrix{U}, g_bwd::Vector{U}, + fwd::TaylorInterpolant{T, U, 2}, t_fwd::Vector{U}, x_fwd::Matrix{U}, g_fwd::Vector{U}, + res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}, scalings::Vector{T} +) where {T <: Real, U <: Number} + NEOSolution{T, U}( + nights, + bwd, t_bwd, x_bwd, g_bwd, + fwd, t_fwd, x_fwd, g_fwd, + res, fit, scalings + ) end -function NEOSolution(bwd::TaylorInterpolant{T, U, 2}, fwd::TaylorInterpolant{T, U, 2}, - res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}) where {T <: Real, U <: Number} +function NEOSolution( + nights::Vector{ObservationNight{T}}, + bwd::TaylorInterpolant{T, U, 2}, fwd::TaylorInterpolant{T, U, 2}, + res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}, scalings::Vector{T} +) where {T <: Real, U <: Number} # Backward roots t_bwd = Vector{U}(undef, 0) - x_bwd = Vector{U}(undef, 0) + x_bwd = Matrix{U}(undef, 0, 0) g_bwd = Vector{U}(undef, 0) # Forward roots t_fwd = Vector{U}(undef, 0) - x_fwd = Vector{U}(undef, 0) + x_fwd = Matrix{U}(undef, 0, 0) g_fwd = Vector{U}(undef, 0) - return NEOSolution{T, U}(bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, res, fit) + NEOSolution{T, U}( + nights, + bwd, t_bwd, x_bwd, g_bwd, + fwd, t_fwd, x_fwd, g_fwd, + res, fit, scalings + ) end # Print method for NEOSolution @@ -92,25 +120,35 @@ function evalfit(sol::NEOSolution{T, TaylorN{T}}) where {T <: Real} # Evaluate residuals new_res = sol.res(δs) - return NEOSolution{T, T}(new_bwd, new_t_bwd, new_x_bwd, new_g_bwd, - new_fwd, new_t_fwd, new_x_fwd, new_g_fwd, - new_res, sol.fit) + NEOSolution{T, T}( + sol.nights, + new_bwd, new_t_bwd, new_x_bwd, new_g_bwd, + new_fwd, new_t_fwd, new_x_fwd, new_g_fwd, + new_res, sol.fit, sol.scalings + ) end # Definition of zero NEOSolution function zero(::Type{NEOSolution{T, U}}) where {T <: Real, U <: Number} + nights = Vector{ObservationNight{T}}(undef, 0) bwd = TaylorInterpolant{T, U, 2}(zero(T), zeros(T, 1), Matrix{Taylor1{U}}(undef, 0, 0)) t_bwd = Vector{U}(undef, 0) - x_bwd = Vector{U}(undef, 0) + x_bwd = Matrix{U}(undef, 0, 0) g_bwd = Vector{U}(undef, 0) fwd = TaylorInterpolant{T, U, 2}(zero(T), zeros(T, 1), Matrix{Taylor1{U}}(undef, 0, 0)) t_fwd = Vector{U}(undef, 0) - x_fwd = Vector{U}(undef, 0) + x_fwd = Matrix{U}(undef, 0, 0) g_fwd = Vector{U}(undef, 0) res = Vector{OpticalResidual{T, U}}(undef, 0) fit = OrbitFit{T}(false, Vector{T}(undef, 0), Matrix{T}(undef, 0, 0), :newton) - return NEOSolution{T, U}(bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, - res, fit) + scalings = Vector{T}(undef, 0) + + NEOSolution{T, U}( + nights, + bwd, t_bwd, x_bwd, g_bwd, + fwd, t_fwd, x_fwd, g_fwd, + res, fit, scalings + ) end iszero(x::NEOSolution{T, U}) where {T <: Real, U <: Number} = x == zero(NEOSolution{T, U}) @@ -122,4 +160,6 @@ function nrms(sol::NEOSolution{T, T}) where {T <: Real} else return nrms(sol.res) end -end \ No newline at end of file +end + +sigmas(sol::NEOSolution{T, T}) where {T <: Real} = sqrt.(diag(sol.fit.Γ)) .* sol.scalings \ No newline at end of file diff --git a/src/propagation/parameters.jl b/src/propagation/parameters.jl new file mode 100644 index 00000000..f4dde6fd --- /dev/null +++ b/src/propagation/parameters.jl @@ -0,0 +1,82 @@ +struct Parameters{T <: AbstractFloat} + # Propagation parameters + maxsteps::Int + μ_ast::Vector{T} + order::Int + abstol::T + parse_eqs::Bool + # Residuals parameters + mpc_catalogue_codes_201X::Vector{String} + truth::String + resol::Resolution + bias_matrix::Matrix{T} + # Least squares fit parameters + niter::Int + # Gauss Method parameters + max_triplets::Int + varorder::Int + Q_max::T + # Inner constructor is generated by default +end + +# Outer constructors + +@doc raw""" + Parameters([params::Parameters{T};] kwargs...) where {T <: AbstractFloat} + +Parameters for all orbit determination functions. + +# Propagation Parameters + +- `maxsteps::Int`: maximum number of steps for the integration (default: `100`). +- `μ_ast::Vector{T}`: vector of gravitational parameters (default: `μ_ast343_DE430[1:end]`). +- `order::Int`: order of Taylor expansions wrt time (default: 25). +- `abstol::T`: absolute tolerance used to compute propagation timestep (default: `1e-20`). +- `parse_eqs::Bool`: whether to use the specialized method of `jetcoeffs` or not (default: `true`). + +# Residuals Parameters + +- `debias_table::String`: debiasing scheme (default: `"2018"`). Possible values are: + - `"2014"` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, + - `"2018"` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, + - `"hires2018"` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. + +# Least Squares Fit Parameters + +- `niter::Int`: number of iterations for differential corrections / Newton's method (default: `5`). + +# Gauss Method Parameters + +- `max_triplets::Int`: maximum number of triplets to check for a solution (default: `10`). +- `varorder::Int`: order of jet transport perturbation (default: `5`). +- `Q_max::T`: maximum nrms that is considered a good enough orbit (default: `5.0`). +""" +function Parameters(; maxsteps::Int = 100, μ_ast::Vector{T} = μ_ast343_DE430[1:end], + order::Int = 25, abstol::T = 1e-20, parse_eqs::Bool = true, + debias_table::String = "2018", niter::Int = 5, max_triplets::Int = 10, + varorder::Int = 5, Q_max::T = 5.0) where {T <: AbstractFloat} + # Unfold debiasing matrix + mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) + # Assemble Parameters + return Parameters{T}(maxsteps, μ_ast, order, abstol, parse_eqs, mpc_catalogue_codes_201X, + truth, resol, bias_matrix, niter, max_triplets, varorder, Q_max) +end + +function Parameters(params::Parameters{T}; kwargs...) where {T <: AbstractFloat} + fields = fieldnames(Parameters{T}) + vals = Vector{Any}(undef, length(fields)) + for i in eachindex(vals) + if fields[i] in keys(kwargs) + vals[i] = kwargs[i] + else + vals[i] = getfield(params, i) + end + end + + return Parameters{T}(vals...) +end + +function residuals(obs::Vector{RadecMPC{T}}, params::Parameters{T}; kwargs...) where {T <: AbstractFloat} + return residuals(obs, params.mpc_catalogue_codes_201X, params.truth, params.resol, + params.bias_matrix; kwargs...) +end \ No newline at end of file diff --git a/src/propagation/propagation.jl b/src/propagation/propagation.jl index e24341ee..8c3ec2c4 100755 --- a/src/propagation/propagation.jl +++ b/src/propagation/propagation.jl @@ -1,70 +1,7 @@ include("asteroid_dynamical_models.jl") include("jetcoeffs.jl") include("serialization.jl") - -struct Parameters{T <: AbstractFloat} - maxsteps::Int - mpc_catalogue_codes_201X::Vector{String} - truth::String - resol::Resolution - bias_matrix::Matrix{T} - μ_ast::Vector{T} - order::Int - abstol::T - parse_eqs::Bool - function Parameters{T}(maxsteps::Int, mpc_catalogue_codes_201X::Vector{String}, - truth::String, resol::Resolution, bias_matrix::Matrix{T}, - μ_ast::Vector{T}, order::Int, abstol::T, parse_eqs::Bool) where {T <: AbstractFloat} - - return new{T}(maxsteps, mpc_catalogue_codes_201X, truth, resol, bias_matrix, μ_ast, - order, abstol, parse_eqs) - end -end - -@doc raw""" - Parameters(params::Parameters{T}; kwargs...) where {T <: AbstractFloat} - -Parameters for `propagate` and related functions. - -# Keyword arguments - -- `maxsteps::Int = 100`: maximum number of steps for the integration. -- `debias_table::String = "2018"`: possible values are: - - `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, - - `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, - - `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. -- `μ_ast::Vector`: vector of gravitational parameters. -- `order::Int = 25`: order of Taylor expansions wrt time. -- `abstol::T = 1e-20`: absolute tolerance (used to compute propagation timestep). -- `parse_eqs::Bool = true`: whether to use the specialized method of `jetcoeffs` (`true`) or not. -""" -function Parameters(; maxsteps::Int = 100, debias_table::String = "2018", - μ_ast::Vector{T} = μ_ast343_DE430[1:end], order::Int = 25, - abstol::T = 1e-20, parse_eqs::Bool = true) where {T <: AbstractFloat} - - mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) - return Parameters{T}(maxsteps, mpc_catalogue_codes_201X, truth, resol, bias_matrix, - μ_ast, order, abstol, parse_eqs) -end - -function Parameters(params::Parameters{T}; kwargs...) where {T <: AbstractFloat} - fields = fieldnames(Parameters{T}) - vals = Vector{Any}(undef, length(fields)) - for i in eachindex(vals) - if fields[i] in keys(kwargs) - vals[i] = kwargs[i] - else - vals[i] = getfield(params, i) - end - end - - return Parameters{T}(vals...) -end - -function residuals(obs::Vector{RadecMPC{T}}, params::Parameters{T}; kwargs...) where {T <: AbstractFloat} - return residuals(obs, params.mpc_catalogue_codes_201X, params.truth, params.resol, - params.bias_matrix; kwargs...) -end +include("parameters.jl") @doc raw""" rvelea(dx, x, params, t) From 365b7d6c3ef4dc2c716f5a4b1d0c0c7c486b6b24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 21 Dec 2023 07:41:37 -0600 Subject: [PATCH 083/173] Minor fix --- src/observations/process_radec.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index c00f0984..7f64f5c8 100755 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -489,7 +489,7 @@ function relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} # Convert to DataFrame df = DataFrame(radec) # Group by observatory and TimeOfDay - df.TimeOfDay = TimeOfDay.(df.date, df.observatory) + df.TimeOfDay = TimeOfDay.(radec) gdf = groupby(df, [:observatory, :TimeOfDay]) # Interpolate observation nights cdf = combine(gdf, nrow) From 5ff0784373a67830ca78b8701b6ef7194d7ecb45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 21 Dec 2023 08:28:28 -0600 Subject: [PATCH 084/173] Update Gauss Method tests --- src/NEOs.jl | 4 +- src/orbit_determination/gauss_method.jl | 5 +++ .../orbit_determination.jl | 8 ++++ test/{gauss.jl => orbit_determination.jl} | 39 +++++++++++++------ test/runtests.jl | 2 +- 5 files changed, 44 insertions(+), 14 deletions(-) rename test/{gauss.jl => orbit_determination.jl} (65%) diff --git a/src/NEOs.jl b/src/NEOs.jl index fe05b6fd..8be57e6c 100755 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -61,7 +61,7 @@ export Parameters, propagate, propagate_lyap, propagate_root # B plane export valsecchi_circle, bopik # Least squares -export outlier_rejection, project, chi2, nms, nrms, diffcorr, newtonls, tryls +export outlier_rejection, project, chi2, nms, nrms, diffcorr, newtonls, tryls, sigmas # Osculating export pv2kep, yarkp2adot # Too Short Arc @@ -69,7 +69,7 @@ export tooshortarc # Gauss method export gauss_method, gaussinitcond, gauss_refinement # Orbit determination -export issinglearc, orbitdetermination, sigmas +export issinglearc, istsa, orbitdetermination include("constants.jl") include("observations/process_radar.jl") diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index bbe35802..64cbe22e 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -339,6 +339,7 @@ end @doc raw""" numberofdays(dates::Vector{DateTime}) numberofdays(dates::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + numberofdays(dates::Vector{ObservationNight{T}}) where {T <: AbstractFloat} Return the time span of `dates` in days. The function assumes `dates` is sorted. """ @@ -348,6 +349,10 @@ function numberofdays(dates::Vector{RadecMPC{T}}) where {T <: AbstractFloat} return (dates[end].date - dates[1].date).value / 86_400_000 end +function numberofdays(dates::Vector{ObservationNight{T}}) where {T <: AbstractFloat} + return (dates[end].radec[end].date - dates[1].radec[1].date).value / 86_400_000 +end + @doc raw""" gauss_norm(dates::Vector{DateTime}) diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index 71a165f6..e6f424c6 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -17,6 +17,14 @@ function issinglearc(radec::Vector{RadecMPC{T}}, arc::Day = Day(30)) where {T <: return true end +@doc raw""" + istsa(sol::NEOSolution{T, T}) where {T <: AbstractFloat} +Check whether `sol` was computed via Too Short Arc (`true`) or via Gauss Method (`false`). +""" +function istsa(sol::NEOSolution{T, T}) where {T <: AbstractFloat} + return length(sol.nights) < 3 || numberofdays(sol.nights) < 1 +end + @doc raw""" orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}; kwargs...) where {T <: AbstractFloat} diff --git a/test/gauss.jl b/test/orbit_determination.jl similarity index 65% rename from test/gauss.jl rename to test/orbit_determination.jl index 2e802790..ed6065a3 100755 --- a/test/gauss.jl +++ b/test/orbit_determination.jl @@ -5,31 +5,47 @@ using PlanetaryEphemeris using LinearAlgebra using Test -using NEOs: NEOSolution, reduce_nights, adaptative_maxsteps, scaled_variables -@testset "Gauss initial conditions" begin +using NEOs: NEOSolution, numberofdays +@testset "Gauss Method" begin # Load observations radec = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) - # Reduce nights by linear regression - gdf, cdf = reduce_nights(radec) # Parameters params = Parameters(abstol = 1e-20, order = 25, parse_eqs = true) - - # Gauss initial conditions - sol = gaussinitcond(radec, gdf, cdf, params) + # Orbit Determination + sol = orbitdetermination(radec, params) + + # Values by December 21, 2023 + + # Vector of observations + @test length(radec) == 123 + @test numberofdays(radec) < 21.0 + # Orbit solution @test isa(sol, NEOSolution{Float64, Float64}) + # Observation nights + @test length(sol.nights) == 44 + @test sol.nights[1].radec[1] == radec[1] + @test sol.nights[end].radec[end] == radec[end] + # Backward integration @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] - @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] @test all( norm.(sol.bwd.x, Inf) .< 2 ) - @test all( norm.(sol.fwd.x, Inf) .< 2 ) @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) + # Forward integration + @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] + @test all( norm.(sol.fwd.x, Inf) .< 2 ) @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) + # Vector of residuals @test length(sol.res) == 123 + @test iszero(count(outlier.(sol.res))) + # Least squares fit @test sol.fit.success - @test all( sqrt.(diag(sol.fit.Γ)) .< 10 ) - @test nrms(sol) < 0.4 + @test all( sigmas(sol) .< 1e-4 ) + @test nrms(sol) < 0.38 + # Scalig factors + @test all(sol.scalings .== 1e-6) # Gauss refinement (with outlier rejection) + #= sol = gauss_refinement(radec, sol, params) @test isa(sol, NEOSolution{Float64, Float64}) @@ -44,4 +60,5 @@ using NEOs: NEOSolution, reduce_nights, adaptative_maxsteps, scaled_variables @test all( sqrt.(diag(sol.fit.Γ)) .< 100 ) @test nrms(sol) < 0.4 @test count(outlier.(sol.res)) == 0 + =# end \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index a6801a9b..18f8f774 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,7 +4,7 @@ testfiles = ( "osculating.jl", "observations.jl", "propagation.jl", - "gauss.jl", + "orbit_determination.jl", "extensions.jl" ) From fe9d0547db1246084e8e5d16c784f783cfe88ea0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 22 Dec 2023 10:45:55 -0600 Subject: [PATCH 085/173] Update Too Short Arc --- src/observations/observation_night.jl | 3 + .../orbit_determination.jl | 5 +- src/orbit_determination/tooshortarc.jl | 70 ++++++++++--------- src/propagation/parameters.jl | 10 ++- 4 files changed, 49 insertions(+), 39 deletions(-) diff --git a/src/observations/observation_night.jl b/src/observations/observation_night.jl index 60cc7a54..c5a9569f 100644 --- a/src/observations/observation_night.jl +++ b/src/observations/observation_night.jl @@ -43,6 +43,9 @@ date(x::ObservationNight{T}) where {T <: AbstractFloat} = x.date ra(x::ObservationNight{T}) where {T <: AbstractFloat} = x.α dec(x::ObservationNight{T}) where {T <: AbstractFloat} = x.δ observatory(x::ObservationNight{T}) where {T <: AbstractFloat} = x.observatory +vra(x::ObservationNight{T}) where {T <: AbstractFloat} = x.v_α +vdec(x::ObservationNight{T}) where {T <: AbstractFloat} = x.v_δ +mag(x::ObservationNight{T}) where {T <: AbstractFloat} = x.mag indices(x::ObservationNight{T}) where {T <: AbstractFloat} = x.indices # Print method for ObservationNight{T} diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index e6f424c6..ea8d8493 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -38,11 +38,10 @@ Initial Orbit Determination (IOD) routine. # Keyword arguments -- `maxiter::Int = 200`: maximum number of iterations. - `max_per::T = 18.0`: maximum allowed rejection percentage. """ function orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}; - maxiter::Int = 200, max_per::T = 18.0) where {T <: AbstractFloat} + max_per::T = 18.0) where {T <: AbstractFloat} # Allocate memory for output sol = zero(NEOSolution{T, T}) @@ -58,7 +57,7 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}; nights = reduce_nights(radec) # Case 1: Too Short Arc (TSA) if length(nights) < 3 || numberofdays(radec) < 1 - sol = tooshortarc(radec, gdf, cdf, params; maxiter) + sol = tooshortarc(radec, nights, params) # Case 2: Gauss Method else sol = gaussinitcond(radec, nights, params) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 33ab0fcb..9b2c7f1c 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -40,9 +40,10 @@ some dynamical constrainits on a too short arc. end # Outer constructor -function AdmissibleRegion(cdf::DataFrameRow) +function AdmissibleRegion(night::ObservationNight{T}) where {T <: AbstractFloat} # Unfold - obs, t_datetime, α, δ, v_α, v_δ, mag, _ = cdf + obs, t_datetime, α, δ = observatory(night), date(night), ra(night), dec(night) + v_α, v_δ, h = vra(night), vdec(night), mag(night) # Topocentric unit vector and partials ρ, ρ_α, ρ_δ = topounitpdv(α, δ) # Time of observation [days since J2000] @@ -58,10 +59,10 @@ function AdmissibleRegion(cdf::DataFrameRow) coeffs = admsreg_coeffs(α, δ, v_α, v_δ, ρ, ρ_α, ρ_δ, q) # Tiny object boundary H_max = 32.0 # Maximum allowed absolute magnitude - if isnan(mag) + if isnan(h) ρ_min = R_SI else - ρ_min = 10^((mag - H_max)/5) + ρ_min = 10^((h - H_max)/5) end # Maximum range (heliocentric constraint) ρ_max = find_zeros(s -> admsreg_U(coeffs, s), ρ_min, 10.0)[1] @@ -305,14 +306,14 @@ end @doc raw""" adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; maxiter::Int = 200, α::T = 10.0, β_1::T = 0.75, - β_2::T = 0.85, ϵ::T = 1e-8, Qtol::T = 0.01) where {T <: AbstractFloat} + params::Parameters{T}; α::T = 25.0, β_1::T = 0.5, β_2::T = 0.85, + ϵ::T = 1e-8, Qtol::T = 0.01) where {T <: AbstractFloat} ADAM minimizer of root mean square error over `A`. """ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; maxiter::Int = 200, α::T = 25.0, β_1::T = 0.5, - β_2::T = 0.85, ϵ::T = 1e-8, Qtol::T = 0.01) where {T <: AbstractFloat} + params::Parameters{T}; α::T = 25.0, β_1::T = 0.5, β_2::T = 0.85, + ϵ::T = 1e-8, Qtol::T = 0.01) where {T <: AbstractFloat} # Origin x0 = zeros(T, 2) # Scaling factors @@ -320,9 +321,9 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T # Jet transport variables dq = scaled_variables("dρ dvρ", scalings, order = 1) # Allocate memory - ρs = Vector{T}(undef, maxiter+1) - v_ρs = Vector{T}(undef, maxiter+1) - Qs = fill(T(Inf), maxiter+1) + ρs = Vector{T}(undef, params.maxiter+1) + v_ρs = Vector{T}(undef, params.maxiter+1) + Qs = fill(T(Inf), params.maxiter+1) # Initial time of integration [julian days] jd0 = datetime2julian(A.date) # Initial conditions @@ -337,7 +338,7 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T # Number of iterations niter = 0 # Gradient descent - while niter < maxiter + while niter < params.maxiter # Update number of iterations niter += 1 # Gradient of objective function @@ -375,8 +376,8 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T end # Special method of tryls for tooshortarc -function tryls(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{T}, params::Parameters{T}; - maxiter::Int = 5) where {T <: AbstractFloat} +function tryls(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, + jd0::T, q0::Vector{T}, params::Parameters{T}; maxiter::Int = 5) where {T <: AbstractFloat} # Allocate memory sols = zeros(NEOSolution{T, T}, maxiter) # Origin @@ -400,13 +401,17 @@ function tryls(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{T}, params::Parame break end # Current solution - sols[niter] = evalfit(NEOSolution(bwd, fwd, res, fit)) + sols[niter] = evalfit(NEOSolution(nights, bwd, fwd, res, fit, scalings)) # Convergence condition if niter > 1 && nrms(sols[niter-1]) - nrms(sols[niter]) < 0.1 break end # Update values q0 = q(fit.x) + # Update scaling factors + scalings = abs.(q0) ./ 10^5 + # Update Jet transport variables + dq = scaled_variables("dx", scalings, order = 6) # Update number of iterations niter += 1 end @@ -416,44 +421,41 @@ function tryls(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{T}, params::Parame end @doc raw""" - tooshortarc(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::DataFrame, - params::Parameters{T}; kwargs...) where {T <: AbstractFloat} + tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, + params::Parameters{T}) where {T <: AbstractFloat} -Return initial conditions by minimizing the normalized root mean square error over -the admissible region. +Return initial conditions by minimizing the normalized root mean square residual +over the admissible region. # Arguments - `radec::Vector{RadecMPC{T}}`: vector of observations. -- `gdf::GroupedDataFrame`, `cdf::DataFrame`: output of [`reduce_nights`](@ref). -- `params::Parameters{T}`: see [`Parameters`](@ref). +- `nights::Vector{ObservationNight{T}},`: vector of observation nights. +- `params::Parameters{T}`: see `Admissible Region Parameters` of [`Parameters`](@ref). -# Keyword arguments - -- `maxiter::Int = 200`: maximum number of iterations. +!!! warning + This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. """ -function tooshortarc(radec::Vector{RadecMPC{T}}, gdf::GroupedDataFrame, cdf::DataFrame, - params::Parameters{T}; maxiter::Int = 200) where {T <: AbstractFloat} +function tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, + params::Parameters{T}) where {T <: AbstractFloat} + - # Reverse temporal order - reverse!(cdf) - # Sort nights by number of observations - idxs = sortperm(cdf.nobs, rev = true) # Allocate memory for output sol = zero(NEOSolution{T, T}) - for i in idxs + # Iterate observation nights (in reverse temporal order) + for i in reverse(eachindex(nights)) # Admissible region - A = AdmissibleRegion(cdf[i, :]) + A = AdmissibleRegion(nights[i]) # Center ρ = sum(A.ρ_domain) / 2 v_ρ = sum(A.v_ρ_domain) / 2 # Minimization over admissible region - ρs, v_ρs, Qs = adam(radec, A, ρ, v_ρ, params; maxiter) + ρs, v_ρs, Qs = adam(radec, A, ρ, v_ρ, params) # Barycentric initial conditions q0 = topo2bary(A, ρs[end], v_ρs[end]) # 6 variables least squares - sol = tryls(radec, datetime2julian(A.date), q0, params; maxiter = 5) + sol = tryls(radec, nights, datetime2julian(A.date), q0, params; maxiter = 5) if nrms(sol) < 1.5 return sol diff --git a/src/propagation/parameters.jl b/src/propagation/parameters.jl index f4dde6fd..95ae8545 100644 --- a/src/propagation/parameters.jl +++ b/src/propagation/parameters.jl @@ -16,6 +16,8 @@ struct Parameters{T <: AbstractFloat} max_triplets::Int varorder::Int Q_max::T + # Admissible Region parameters + maxiter::Int # Inner constructor is generated by default end @@ -50,16 +52,20 @@ Parameters for all orbit determination functions. - `max_triplets::Int`: maximum number of triplets to check for a solution (default: `10`). - `varorder::Int`: order of jet transport perturbation (default: `5`). - `Q_max::T`: maximum nrms that is considered a good enough orbit (default: `5.0`). + +# Admissible Region Parameters + +- `maxiter::Int`: maximum number of iterations for admissible region `ADAM` optimizer. """ function Parameters(; maxsteps::Int = 100, μ_ast::Vector{T} = μ_ast343_DE430[1:end], order::Int = 25, abstol::T = 1e-20, parse_eqs::Bool = true, debias_table::String = "2018", niter::Int = 5, max_triplets::Int = 10, - varorder::Int = 5, Q_max::T = 5.0) where {T <: AbstractFloat} + varorder::Int = 5, Q_max::T = 5.0, maxiter::Int = 200) where {T <: AbstractFloat} # Unfold debiasing matrix mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) # Assemble Parameters return Parameters{T}(maxsteps, μ_ast, order, abstol, parse_eqs, mpc_catalogue_codes_201X, - truth, resol, bias_matrix, niter, max_triplets, varorder, Q_max) + truth, resol, bias_matrix, niter, max_triplets, varorder, Q_max, maxiter) end function Parameters(params::Parameters{T}; kwargs...) where {T <: AbstractFloat} From 7237c66555b7882ccefeeb4ee90e1f3463cf91fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 22 Dec 2023 11:05:18 -0600 Subject: [PATCH 086/173] Update TSA tests --- test/orbit_determination.jl | 148 ++++++++++++++++++++++++------------ 1 file changed, 100 insertions(+), 48 deletions(-) diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index ed6065a3..a92f1fe4 100755 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -6,59 +6,111 @@ using LinearAlgebra using Test using NEOs: NEOSolution, numberofdays -@testset "Gauss Method" begin - # Load observations - radec = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) - # Parameters - params = Parameters(abstol = 1e-20, order = 25, parse_eqs = true) - # Orbit Determination - sol = orbitdetermination(radec, params) +@testset "Orbit Determination" begin + @testset "Gauss Method" begin + # Load observations + radec = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) + # Parameters + params = Parameters(abstol = 1e-20, order = 25, parse_eqs = true) + + # Orbit Determination + sol = orbitdetermination(radec, params) + + # Values by December 21, 2023 + + # Vector of observations + @test length(radec) == 123 + @test numberofdays(radec) < 21.0 + # Orbit solution + @test isa(sol, NEOSolution{Float64, Float64}) + # Observation nights + @test length(sol.nights) == 44 + @test sol.nights[1].radec[1] == radec[1] + @test sol.nights[end].radec[end] == radec[end] + @test issorted(sol.nights) + # Backward integration + @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] + @test all( norm.(sol.bwd.x, Inf) .< 2 ) + @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) + # Forward integration + @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] + @test all( norm.(sol.fwd.x, Inf) .< 2 ) + @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) + # Vector of residuals + @test length(sol.res) == 123 + @test iszero(count(outlier.(sol.res))) + # Least squares fit + @test sol.fit.success + @test all( sigmas(sol) .< 1e-4 ) + @test nrms(sol) < 0.38 + # Scalig factors + @test all(sol.scalings .== 1e-6) + end - # Values by December 21, 2023 + @testset "Too Short Arc" begin + # Optical astrometry file + filename = joinpath("data", "2008_EK68.txt") + # Download observations + get_radec_mpc("designation" => "2008 EK68", filename) + # Load observations + radec = read_radec_mpc(filename) + # Delete astrometry file + rm(filename) + # Parameters + params = Parameters(abstol = 1e-20, order = 25, parse_eqs = true) - # Vector of observations - @test length(radec) == 123 - @test numberofdays(radec) < 21.0 - # Orbit solution - @test isa(sol, NEOSolution{Float64, Float64}) - # Observation nights - @test length(sol.nights) == 44 - @test sol.nights[1].radec[1] == radec[1] - @test sol.nights[end].radec[end] == radec[end] - # Backward integration - @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] - @test all( norm.(sol.bwd.x, Inf) .< 2 ) - @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) - # Forward integration - @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] - @test all( norm.(sol.fwd.x, Inf) .< 2 ) - @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) - # Vector of residuals - @test length(sol.res) == 123 - @test iszero(count(outlier.(sol.res))) - # Least squares fit - @test sol.fit.success - @test all( sigmas(sol) .< 1e-4 ) - @test nrms(sol) < 0.38 - # Scalig factors - @test all(sol.scalings .== 1e-6) + # Orbit Determination + sol = orbitdetermination(radec, params) - # Gauss refinement (with outlier rejection) + # Values by December 22, 2023 + + # Vector of observations + @test length(radec) == 10 + @test numberofdays(radec) < 0.05 + # Orbit solution + @test isa(sol, NEOSolution{Float64, Float64}) + # Observation nights + @test length(sol.nights) == 1 + @test sol.nights[1].radec[1] == radec[1] + @test sol.nights[end].radec[end] == radec[end] + @test issorted(sol.nights) + # Backward integration + @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] + @test all( norm.(sol.bwd.x, Inf) .< 2 ) + @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) + # Forward integration + @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] + @test all( norm.(sol.fwd.x, Inf) .< 2 ) + @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) + # Vector of residuals + @test length(sol.res) == 10 + @test iszero(count(outlier.(sol.res))) + # Least squares fit + @test sol.fit.success + @test all( sigmas(sol) .< 6e-3 ) + @test nrms(sol) < 0.85 + # Scalig factors + @test all(sol.scalings .< 1e-5) + end #= - sol = gauss_refinement(radec, sol, params) + @test "Outlier Rejection" begin + # Gauss refinement (with outlier rejection) - @test isa(sol, NEOSolution{Float64, Float64}) - @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] - @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] - @test all( norm.(sol.bwd.x, Inf) .< 2 ) - @test all( norm.(sol.fwd.x, Inf) .< 2 ) - @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) - @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) - @test length(sol.res) == 123 - @test sol.fit.success - @test all( sqrt.(diag(sol.fit.Γ)) .< 100 ) - @test nrms(sol) < 0.4 - @test count(outlier.(sol.res)) == 0 + sol = gauss_refinement(radec, sol, params) + + @test isa(sol, NEOSolution{Float64, Float64}) + @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] + @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] + @test all( norm.(sol.bwd.x, Inf) .< 2 ) + @test all( norm.(sol.fwd.x, Inf) .< 2 ) + @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) + @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) + @test length(sol.res) == 123 + @test sol.fit.success + @test all( sqrt.(diag(sol.fit.Γ)) .< 100 ) + @test nrms(sol) < 0.4 + @test count(outlier.(sol.res)) == 0 + end =# end \ No newline at end of file From 476e1ee6c4831fb2c8ce7946f51ced67aa0625d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 23 Dec 2023 07:13:18 -0600 Subject: [PATCH 087/173] Update Outlier Rejection --- src/NEOs.jl | 4 +- src/observations/process_radec.jl | 6 +- .../orbit_determination.jl | 15 ++--- src/orbit_determination/outlier_rejection.jl | 56 +++++++++---------- src/propagation/parameters.jl | 14 ++++- 5 files changed, 51 insertions(+), 44 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index 8be57e6c..f81e23e0 100755 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -61,13 +61,15 @@ export Parameters, propagate, propagate_lyap, propagate_root # B plane export valsecchi_circle, bopik # Least squares -export outlier_rejection, project, chi2, nms, nrms, diffcorr, newtonls, tryls, sigmas +export project, chi2, nms, nrms, diffcorr, newtonls, tryls, sigmas # Osculating export pv2kep, yarkp2adot # Too Short Arc export tooshortarc # Gauss method export gauss_method, gaussinitcond, gauss_refinement +# Outlier rejection +export outlier_rejection # Orbit determination export issinglearc, istsa, orbitdetermination diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index 7f64f5c8..d59d2dda 100755 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -49,9 +49,11 @@ end # Print method for OpticalResidual # Examples: # α: -138.79801 δ: -89.80025 -# α: -134.79450 δ: -91.42509 +# α: -134.79450 δ: -91.42509 (outlier) function show(io::IO, x::OpticalResidual{T, U}) where {T <: Real, U <: Number} - print(io, "α: ", @sprintf("%+.5f", cte(x.ξ_α)), " δ: ", @sprintf("%+.5f", cte(x.ξ_δ))) + outlier_flag = outlier(x) ? " (outlier)" : "" + print(io, "α: ", @sprintf("%+.5f", cte(x.ξ_α)), " δ: ", + @sprintf("%+.5f", cte(x.ξ_δ)), outlier_flag) end @doc raw""" diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index ea8d8493..4fc424a7 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -1,6 +1,7 @@ include("osculating.jl") include("tooshortarc.jl") include("gauss_method.jl") +include("outlier_rejection.jl") @doc raw""" issinglearc(radec::Vector{RadecMPC{T}}, arc::Day = Day(30)) where {T <: AbstractFloat} @@ -26,8 +27,7 @@ function istsa(sol::NEOSolution{T, T}) where {T <: AbstractFloat} end @doc raw""" - orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}; - kwargs...) where {T <: AbstractFloat} + orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}) where {T <: AbstractFloat} Initial Orbit Determination (IOD) routine. @@ -35,13 +35,8 @@ Initial Orbit Determination (IOD) routine. - `radec::Vector{RadecMPC{T}}`: vector of observations. - `params::Parameters{T}`: see [`Parameters`](@ref). - -# Keyword arguments - -- `max_per::T = 18.0`: maximum allowed rejection percentage. """ -function orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}; - max_per::T = 18.0) where {T <: AbstractFloat} +function orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}) where {T <: AbstractFloat} # Allocate memory for output sol = zero(NEOSolution{T, T}) @@ -63,8 +58,8 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}; sol = gaussinitcond(radec, nights, params) end # Outlier rejection (if needed) - if nrms(sol) > 1.0 && !iszero(sol) - sol = gauss_refinement(radec, sol, params; max_per, niter, varorder) + if nrms(sol) > 1 && !iszero(sol) + sol = outlier_rejection(radec, sol, params) end return sol::NEOSolution{T, T} diff --git a/src/orbit_determination/outlier_rejection.jl b/src/orbit_determination/outlier_rejection.jl index 1da31530..403c46b2 100644 --- a/src/orbit_determination/outlier_rejection.jl +++ b/src/orbit_determination/outlier_rejection.jl @@ -6,30 +6,30 @@ Return the contribution of `x` to the nrms. residual_norm(x::OpticalResidual{T, T}) where {T <: Real} = x.w_α * x.ξ_α^2 / x.relax_factor + x.w_δ * x.ξ_δ^2 / x.relax_factor @doc raw""" - gauss_refinement(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, params::Parameters{T}; - kwargs...) where {T <: AbstractFloat} + outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, + params::Parameters{T}) where {T <: AbstractFloat} -Refine an orbit computed by [`gaussinitcond`](@ref) via propagation and/or outlier rejection. +Refine an orbit, computed by [`tooshortarc`](@ref) or [`gaussinitcond`](@ref), +via propagation and/or outlier rejection. # Arguments - `radec::Vector{RadecMPC{T}}`: vector of observations. - `sol::NEOSolution{T, T}`: orbit to be refined. -- `params::Parameters{T}`: see [`Parameters`](@ref). +- `params::Parameters{T}`: see `Outlier Rejection Parameters` of [`Parameters`](@ref). -# Keyword arguments - -- `max_per::T = 18.0`: maximum allowed rejection percentage. -- `niter::Int = 5`: number of iterations. -- `varorder::Int`: order of jet transport perturbation. +!!! warning + This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. """ -function gauss_refinement(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, params::Parameters{T}; - max_per::T = 18.0, niter::Int = 5, varorder::Int = 5) where {T <: AbstractFloat} +function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, + params::Parameters{T}) where {T <: AbstractFloat} # Sun's ephemeris eph_su = selecteph(sseph, su) # Earth's ephemeris eph_ea = selecteph(sseph, ea) + # Origin + x0 = zeros(T, 6) # Julian day to start propagation jd0 = sol.bwd.t0 + PE.J2000 # Julian day of first (last) observation @@ -40,24 +40,24 @@ function gauss_refinement(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, pa nyears_bwd = -(jd0 - t0 + 2) / yr # Dynamical function dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! - # Maximum number of steps - params = Parameters(params; maxsteps = adaptative_maxsteps(radec)) # Initial conditions (T) - q00 = sol(sol.bwd.t0) + q0 = sol(sol.bwd.t0) + # Scaling factors + scalings = abs.(q0) ./ 10^6 # Jet transport perturbation - dq = scaled_variables("δx", fill(1e-6, 6); order = varorder) + dq = scaled_variables("δx", scalings; order = params.varorder) # Initial conditions (jet transport) - q0 = q00 .+ dq + q = q0 .+ dq # Backward integration - bwd = propagate(dynamics, jd0, nyears_bwd, q0, params) + bwd = propagate(dynamics, jd0, nyears_bwd, q, params) if bwd.t[end] > t0 - jd0 return zero(NEOSolution{T, T}) end # Forward integration - fwd = propagate(dynamics, jd0, nyears_fwd, q0, params) + fwd = propagate(dynamics, jd0, nyears_fwd, q, params) if fwd.t[end] < tf - jd0 return zero(NEOSolution{T, T}) @@ -69,21 +69,21 @@ function gauss_refinement(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, pa xve = et -> auday2kmsec(eph_ea(et/daysec)), xva = et -> bwdfwdeph(et, bwd, fwd)) # Orbit fit - fit = tryls(res, zeros(get_numvars()), niter) + fit = tryls(res, x0, params.niter) # NRMS (with 0 outliers) Q_0 = nrms(res, fit) if Q_0 < 1 - return evalfit(NEOSolution(bwd, fwd, res, fit)) + return evalfit(NEOSolution(sol.nights, bwd, fwd, res, fit, scalings)) end # Number of observations N_radec = length(radec) # Maximum allowed outliers - max_drop = ceil(Int, N_radec * max_per / 100) + max_drop = ceil(Int, N_radec * params.max_per / 100) # Boolean mask (0: included in fit, 1: outlier) - new_outliers = BitVector(zeros(N_radec)) + new_outliers = BitVector(zeros(Int, N_radec)) # Drop loop for i in 1:max_drop @@ -100,7 +100,7 @@ function gauss_refinement(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, pa res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) # Update fit - fit = tryls(res, zeros(get_numvars()), niter) + fit = tryls(res, x0, params.niter) break end end @@ -133,7 +133,7 @@ function gauss_refinement(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, pa res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) # Update fit - fit = tryls(res, zeros(get_numvars()), niter) + fit = tryls(res, x0, params.niter) end # Add 0 outliers fit Qs[end] = Q_0 @@ -147,9 +147,9 @@ function gauss_refinement(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, pa res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) # Update fit - fit = tryls(res, zeros(get_numvars()), niter) + fit = tryls(res, x0, params.niter) - return evalfit(NEOSolution(bwd, fwd, res, fit)) + return evalfit(NEOSolution(sol.nights, bwd, fwd, res, fit, scalings)) end if max_drop > 1 @@ -177,7 +177,7 @@ function gauss_refinement(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, pa res = OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), relax_factor.(res), new_outliers) # Update fit - fit = tryls(res, zeros(get_numvars()), niter) + fit = tryls(res, x0, params.niter) - return evalfit(NEOSolution(bwd, fwd, res, fit)) + return evalfit(NEOSolution(sol.nights, bwd, fwd, res, fit, scalings)) end \ No newline at end of file diff --git a/src/propagation/parameters.jl b/src/propagation/parameters.jl index 95ae8545..3df2a9d4 100644 --- a/src/propagation/parameters.jl +++ b/src/propagation/parameters.jl @@ -18,6 +18,8 @@ struct Parameters{T <: AbstractFloat} Q_max::T # Admissible Region parameters maxiter::Int + # Outlier rejection parameters + max_per::T # Inner constructor is generated by default end @@ -55,17 +57,23 @@ Parameters for all orbit determination functions. # Admissible Region Parameters -- `maxiter::Int`: maximum number of iterations for admissible region `ADAM` optimizer. +- `maxiter::Int`: maximum number of iterations for admissible region `ADAM` optimizer (default: `200`). + +# Outlier Rejection Parameters + +- `max_per::T`: maximum allowed rejection percentage (default: `18.0`). """ function Parameters(; maxsteps::Int = 100, μ_ast::Vector{T} = μ_ast343_DE430[1:end], order::Int = 25, abstol::T = 1e-20, parse_eqs::Bool = true, debias_table::String = "2018", niter::Int = 5, max_triplets::Int = 10, - varorder::Int = 5, Q_max::T = 5.0, maxiter::Int = 200) where {T <: AbstractFloat} + varorder::Int = 5, Q_max::T = 5.0, maxiter::Int = 200, + max_per::T = 18.0) where {T <: AbstractFloat} # Unfold debiasing matrix mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) # Assemble Parameters return Parameters{T}(maxsteps, μ_ast, order, abstol, parse_eqs, mpc_catalogue_codes_201X, - truth, resol, bias_matrix, niter, max_triplets, varorder, Q_max, maxiter) + truth, resol, bias_matrix, niter, max_triplets, varorder, Q_max, + maxiter, max_per) end function Parameters(params::Parameters{T}; kwargs...) where {T <: AbstractFloat} From 924502cefb680ba72f7adb9d86f6998eb7bdfe9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 23 Dec 2023 09:16:05 -0600 Subject: [PATCH 088/173] Update Outlier Rejection tests --- test/orbit_determination.jl | 49 ++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index a92f1fe4..f69f02f0 100755 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -93,24 +93,51 @@ using NEOs: NEOSolution, numberofdays # Scalig factors @test all(sol.scalings .< 1e-5) end - #= + @test "Outlier Rejection" begin - # Gauss refinement (with outlier rejection) + # Optical astrometry file + filename = joinpath("data", "2007_VV7.txt") + # Download observations + get_radec_mpc("designation" => "2007 VV7", filename) + # Load observations + radec = read_radec_mpc(filename) + # Delete astrometry file + rm(filename) + # Parameters + params = Parameters(abstol = 1e-20, order = 25, parse_eqs = true) - sol = gauss_refinement(radec, sol, params) - + # Orbit Determination + sol = orbitdetermination(radec, params) + + # Values by December 23, 2023 + + # Vector of observations + @test length(radec) == 21 + @test numberofdays(radec) < 3.03 + # Orbit solution @test isa(sol, NEOSolution{Float64, Float64}) + # Observation nights + @test length(sol.nights) == 4 + @test sol.nights[1].radec[1] == radec[1] + @test sol.nights[end].radec[end] == radec[end] + @test issorted(sol.nights) + # Backward integration @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] - @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] @test all( norm.(sol.bwd.x, Inf) .< 2 ) - @test all( norm.(sol.fwd.x, Inf) .< 2 ) @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) + # Forward integration + @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] + @test all( norm.(sol.fwd.x, Inf) .< 2 ) @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) - @test length(sol.res) == 123 + # Vector of residuals + @test length(sol.res) == 21 + @test count(outlier.(sol.res)) == 2 + # Least squares fit @test sol.fit.success - @test all( sqrt.(diag(sol.fit.Γ)) .< 100 ) - @test nrms(sol) < 0.4 - @test count(outlier.(sol.res)) == 0 + @test all( sigmas(sol) .< 5e-4 ) + @test nrms(sol) < 0.25 + # Scalig factors + @test all(sol.scalings .< 8e-7) end - =# + end \ No newline at end of file From 820e4e32b4fc3b35eeda53bdcf90696a6e1f88fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 23 Dec 2023 09:36:00 -0600 Subject: [PATCH 089/173] Minor fix --- test/orbit_determination.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index f69f02f0..09581b60 100755 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -94,7 +94,7 @@ using NEOs: NEOSolution, numberofdays @test all(sol.scalings .< 1e-5) end - @test "Outlier Rejection" begin + @testset "Outlier Rejection" begin # Optical astrometry file filename = joinpath("data", "2007_VV7.txt") # Download observations From 5cef34b239e2f3db54d1045b05a5fd6414a5fe2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 26 Dec 2023 11:51:43 -0600 Subject: [PATCH 090/173] tsanightorder & naive maxsteps --- src/orbit_determination/gauss_method.jl | 19 ----------------- .../orbit_determination.jl | 21 +++++++++++++++++++ src/orbit_determination/tooshortarc.jl | 18 ++++++++++++---- 3 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 64cbe22e..51bb1d73 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -413,25 +413,6 @@ function gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_ite return triplets[1:n] end -@doc raw""" - adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - -Empirical upper bound for the number of steps used for propagation. -""" -function adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - # Time difference [ms] - Δ_ms = getfield(date(radec[end]) - date(radec[1]), :value) - # Time difference [days] - Δ_day = Δ_ms / 86_400_000 - # Adaptative maxsteps - if Δ_day <= 30 - return 55 - floor(Int, 5*Δ_day/6) - else - return ceil(Int, (Δ_day + 360)/13) - end -end - - @doc raw""" gaussinitcond(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, params::Parameters{T}) where {T <: AbstractFloat} diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index 4fc424a7..8665f585 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -26,6 +26,27 @@ function istsa(sol::NEOSolution{T, T}) where {T <: AbstractFloat} return length(sol.nights) < 3 || numberofdays(sol.nights) < 1 end +@doc raw""" + adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + +Empirical upper bound for the number of steps used for propagation. +""" +function adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + #= + # Time difference [ms] + Δ_ms = getfield(date(radec[end]) - date(radec[1]), :value) + # Time difference [days] + Δ_day = Δ_ms / 86_400_000 + # Adaptative maxsteps + if Δ_day <= 30 + return 55 - floor(Int, 5*Δ_day/6) + else + return ceil(Int, (Δ_day + 360)/13) + end + =# + return 100 +end + @doc raw""" orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}) where {T <: AbstractFloat} diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 9b2c7f1c..0b58c538 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -420,6 +420,15 @@ function tryls(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, end +# Order in which to check nights in tooshortarc +function tsanightorder(x::ObservationNight{T}, y::ObservationNight{T}) where {T <: AbstractFloat} + if x.nobs == y.nobs + return x.date > y.date + else + return x.nobs > y.nobs + end +end + @doc raw""" tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, params::Parameters{T}) where {T <: AbstractFloat} @@ -438,13 +447,14 @@ over the admissible region. """ function tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, params::Parameters{T}) where {T <: AbstractFloat} - - + # Allocate memory for output sol = zero(NEOSolution{T, T}) + # Sort nights by tsanightorder + idxs = sortperm(nights, lt = tsanightorder) - # Iterate observation nights (in reverse temporal order) - for i in reverse(eachindex(nights)) + # Iterate observation nights + for i in idxs # Admissible region A = AdmissibleRegion(nights[i]) # Center From 12dbf5df3eae59752591006636e267810583597b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 2 Jan 2024 07:29:37 -0600 Subject: [PATCH 091/173] Fixes to TSA --- .../orbit_determination.jl | 2 +- src/orbit_determination/tooshortarc.jl | 179 ++++++++++-------- src/propagation/parameters.jl | 8 +- 3 files changed, 102 insertions(+), 87 deletions(-) diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index 8665f585..bc2f66e9 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -44,7 +44,7 @@ function adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFlo return ceil(Int, (Δ_day + 360)/13) end =# - return 100 + return 500 end @doc raw""" diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 0b58c538..c7c238f8 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -292,6 +292,9 @@ function propres(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{U}, # Backward (forward) integration bwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q0, params) fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q0, params) + if bwd.t[end] > t0 - jd0 || fwd.t[end] < tf - jd0 + return bwd, fwd, Vector{OpticalResidual{T, U}}(undef, 0) + end # Sun (Earth) ephemeris eph_su = selecteph(sseph, su) eph_ea = selecteph(sseph, ea) @@ -306,118 +309,128 @@ end @doc raw""" adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; α::T = 25.0, β_1::T = 0.5, β_2::T = 0.85, - ϵ::T = 1e-8, Qtol::T = 0.01) where {T <: AbstractFloat} + params::Parameters{T}; η::T = 25.0, μ::T = 0.75, ν::T = 0.9, + ϵ::T = 1e-8, Qtol::T = 0.001) where {T <: AbstractFloat} + +Adaptative moment estimation (ADAM) minimizer of normalized mean square +residual over and admissible region `A`. -ADAM minimizer of root mean square error over `A`. +!!! warning + This function will set the (global) `TaylorSeries` variables to `δρ δvρ`. + +!!! reference + See Algorithm 1 of https://doi.org/10.48550/arXiv.1412.6980. """ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; α::T = 25.0, β_1::T = 0.5, β_2::T = 0.85, - ϵ::T = 1e-8, Qtol::T = 0.01) where {T <: AbstractFloat} - # Origin - x0 = zeros(T, 2) + params::Parameters{T}; η::T = 25.0, μ::T = 0.75, ν::T = 0.9, + ϵ::T = 1e-8, Qtol::T = 0.001) where {T <: AbstractFloat} + # Initial time of integration [julian days] + jd0 = datetime2julian(A.date) # Scaling factors scalings = [A.ρ_domain[2] - A.ρ_domain[1], A.v_ρ_domain[2] - A.v_ρ_domain[1]] / 1_000 # Jet transport variables dq = scaled_variables("dρ dvρ", scalings, order = 1) + # Maximum number of iterations + maxiter = params.maxiter # Allocate memory - ρs = Vector{T}(undef, params.maxiter+1) - v_ρs = Vector{T}(undef, params.maxiter+1) - Qs = fill(T(Inf), params.maxiter+1) - # Initial time of integration [julian days] - jd0 = datetime2julian(A.date) - # Initial conditions - ρs[1] = ρ - v_ρs[1] = v_ρ - q0 = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) - _, _, res = propres(radec, jd0, q0, params) - Q = nms(res) - Qs[1] = Q(x0) + ρs = Vector{T}(undef, maxiter+1) + v_ρs = Vector{T}(undef, maxiter+1) + Qs = fill(T(Inf), maxiter+1) + # Origin + x0 = zeros(T, 2) + # First momentum m = zeros(T, 2) - v = zeros(T, 2) - # Number of iterations - niter = 0 + _m_ = zeros(T, 2) + # Second momentum + n = zeros(T, 2) + _n_ = zeros(T, 2) # Gradient descent - while niter < params.maxiter - # Update number of iterations - niter += 1 + for t in 1:maxiter+1 + # Current position in admissible region + ρs[t] = ρ + v_ρs[t] = v_ρ + # Current barycentric state vector + q = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) + # Propagation and residuals + _, _, res = propres(radec, jd0, q, params) + iszero(length(res)) && break + # Current Q + Q = nms(res) + Qs[t] = Q(x0) + # Convergence condition + t > 1 && abs(Qs[t] - Qs[t-1]) / Qs[t] < Qtol && break # Gradient of objective function - dQ = TaylorSeries.gradient(Q)(x0) - # Momentum - m = β_1 * m + (1 - β_1) * dQ - _m_ = m / (1 - β_1^niter) - # Sum of square of past gradients - v = β_2 * v + (1 - β_2) * dQ .^ 2 - _v_ = v / (1 - β_2^niter) + g_t = TaylorSeries.gradient(Q)(x0) + # First momentum + m .= μ * m + (1 - μ) * g_t + _m_ .= m / (1 - μ^t) + # Second momentum + n .= ν * n + (1 - ν) * g_t .^ 2 + _n_ .= n / (1 - ν^t) # Step - x1 = x0 - α * _m_ ./ (sqrt.(_v_) .+ ϵ) + x1 = x0 - η * _m_ ./ (sqrt.(_n_) .+ ϵ) # Update values - ρ, v_ρ = bary2topo(A, q0(x1)) + ρ, v_ρ = bary2topo(A, q(x1)) # Projection ρ, v_ρ = boundary_projection(A, ρ, v_ρ) - # New initial conditions - q0 = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) - # Update obbjective function - _, _, res = propres(radec, jd0, q0, params) - Q = nms(res) - # Convergence condition - if abs(Q(x0) - Qs[niter]) < Qtol - break - end - # Save current variables - ρs[niter+1] = ρ - v_ρs[niter+1] = v_ρ - Qs[niter+1] = Q(x0) end + # Find point with smallest Q + t = argmin(Qs) + # Return path + return view(ρs, 1:t), view(v_ρs, 1:t), view(Qs, 1:t) +end - niter = argmin(Qs) +@doc raw""" + tsals(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, + jd0::T, q0::Vector{T}, params::Parameters{T}; maxiter::Int = 5, + Qtol::T = 0.1) where {T <: AbstractFloat} - return ρs[1:niter], v_ρs[1:niter], Qs[1:niter] -end +Used within [`tooshortarc`](@ref) to compute an orbit from a point in an +admissible region via least squares. -# Special method of tryls for tooshortarc -function tryls(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, - jd0::T, q0::Vector{T}, params::Parameters{T}; maxiter::Int = 5) where {T <: AbstractFloat} - # Allocate memory - sols = zeros(NEOSolution{T, T}, maxiter) - # Origin - x0 = zeros(T, 6) +!!! warning + This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. +""" +function tsals(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, + jd0::T, q0::Vector{T}, params::Parameters{T}; maxiter::Int = 5, + Qtol::T = 0.1) where {T <: AbstractFloat} # Scaling factors scalings = abs.(q0) ./ 10^5 # Jet transport variables dq = scaled_variables("dx", scalings, order = 6) - # Number of iterations - niter = 1 - # Minimization loop - while niter <= maxiter + # Allocate memory + sols = zeros(NEOSolution{T, T}, maxiter+1) + Qs = fill(T(Inf), maxiter+1) + # Origin + x0 = zeros(T, 6) + # Least squares + for t in 1:maxiter+1 # Initial conditions q = q0 + dq # Propagation & residuals bwd, fwd, res = propres(radec, jd0, q, params) + iszero(length(res)) && break # Least squares fit - fit = tryls(res, x0, 5) + fit = tryls(res, x0, params.niter) # Case: unsuccessful fit if !fit.success || any(diag(fit.Γ) .< 0) break end # Current solution - sols[niter] = evalfit(NEOSolution(nights, bwd, fwd, res, fit, scalings)) - # Convergence condition - if niter > 1 && nrms(sols[niter-1]) - nrms(sols[niter]) < 0.1 - break + sols[t] = evalfit(NEOSolution(nights, bwd, fwd, res, fit, scalings)) + Qs[t] = nrms(sols[t]) + # Convergence conditions + if t > 1 + Qs[t] > Qs[t-1] && break + abs(Qs[t] - Qs[t-1]) < Qtol && break end # Update values q0 = q(fit.x) - # Update scaling factors - scalings = abs.(q0) ./ 10^5 - # Update Jet transport variables - dq = scaled_variables("dx", scalings, order = 6) - # Update number of iterations - niter += 1 end - - return sols[niter] - + # Find solution with smallest Q + t = argmin(Qs) + # Return solution + return sols[t] end # Order in which to check nights in tooshortarc @@ -449,7 +462,7 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight params::Parameters{T}) where {T <: AbstractFloat} # Allocate memory for output - sol = zero(NEOSolution{T, T}) + best_sol = zero(NEOSolution{T, T}) # Sort nights by tsanightorder idxs = sortperm(nights, lt = tsanightorder) @@ -461,16 +474,18 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight ρ = sum(A.ρ_domain) / 2 v_ρ = sum(A.v_ρ_domain) / 2 # Minimization over admissible region - ρs, v_ρs, Qs = adam(radec, A, ρ, v_ρ, params) + ρs, v_ρs, _ = adam(radec, A, ρ, v_ρ, params) # Barycentric initial conditions q0 = topo2bary(A, ρs[end], v_ρs[end]) # 6 variables least squares - sol = tryls(radec, nights, datetime2julian(A.date), q0, params; maxiter = 5) - - if nrms(sol) < 1.5 - return sol + sol = tsals(radec, nights, datetime2julian(A.date), q0, params; maxiter = 5) + # Update best solution + if nrms(sol) < nrms(best_sol) + best_sol = sol + # Break condition + nrms(sol) < 1.5 && break end end - return sol + return best_sol end \ No newline at end of file diff --git a/src/propagation/parameters.jl b/src/propagation/parameters.jl index 3df2a9d4..72dda533 100644 --- a/src/propagation/parameters.jl +++ b/src/propagation/parameters.jl @@ -32,7 +32,7 @@ Parameters for all orbit determination functions. # Propagation Parameters -- `maxsteps::Int`: maximum number of steps for the integration (default: `100`). +- `maxsteps::Int`: maximum number of steps for the integration (default: `500`). - `μ_ast::Vector{T}`: vector of gravitational parameters (default: `μ_ast343_DE430[1:end]`). - `order::Int`: order of Taylor expansions wrt time (default: 25). - `abstol::T`: absolute tolerance used to compute propagation timestep (default: `1e-20`). @@ -57,16 +57,16 @@ Parameters for all orbit determination functions. # Admissible Region Parameters -- `maxiter::Int`: maximum number of iterations for admissible region `ADAM` optimizer (default: `200`). +- `maxiter::Int`: maximum number of iterations for admissible region `ADAM` optimizer (default: `100`). # Outlier Rejection Parameters - `max_per::T`: maximum allowed rejection percentage (default: `18.0`). """ -function Parameters(; maxsteps::Int = 100, μ_ast::Vector{T} = μ_ast343_DE430[1:end], +function Parameters(; maxsteps::Int = 500, μ_ast::Vector{T} = μ_ast343_DE430[1:end], order::Int = 25, abstol::T = 1e-20, parse_eqs::Bool = true, debias_table::String = "2018", niter::Int = 5, max_triplets::Int = 10, - varorder::Int = 5, Q_max::T = 5.0, maxiter::Int = 200, + varorder::Int = 5, Q_max::T = 5.0, maxiter::Int = 100, max_per::T = 18.0) where {T <: AbstractFloat} # Unfold debiasing matrix mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) From 086014488421d41a0434783341908f6392ec5d05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 2 Jan 2024 12:00:23 -0600 Subject: [PATCH 092/173] Fix istsa --- .../orbit_determination.jl | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index bc2f66e9..16e8290e 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -20,12 +20,27 @@ end @doc raw""" istsa(sol::NEOSolution{T, T}) where {T <: AbstractFloat} -Check whether `sol` was computed via Too Short Arc (`true`) or via Gauss Method (`false`). + +Check whether `sol` was computed via [`tooshortarc`](@ref) (`true`) or +via [`gaussinitcond`](@ref) (`false`). """ -function istsa(sol::NEOSolution{T, T}) where {T <: AbstractFloat} - return length(sol.nights) < 3 || numberofdays(sol.nights) < 1 +function istsa(nights::Vector{ObservationNight{T}}) where {T <: AbstractFloat} + # Observing stations + obs = observatory.(nights) + # Satellite observatories can only be handled by Gauss + any(issatellite.(obs)) && return false + # Gauss cannot handle less than 3 observation nights + length(nights) < 3 && return true + # Time span + Δ = numberofdays(nights) + # Gauss aproximation do not work with less than 1 day + Δ < 1 && return true + # All observations come from the same observatory + return allequal(obs) && Δ < 5 end +istsa(sol::NEOSolution{T, T}) where {T <: AbstractFloat} = istsa(sol.nights) + @doc raw""" adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} @@ -72,7 +87,7 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}) w # Reduce observation nights by linear regression nights = reduce_nights(radec) # Case 1: Too Short Arc (TSA) - if length(nights) < 3 || numberofdays(radec) < 1 + if istsa(nights) sol = tooshortarc(radec, nights, params) # Case 2: Gauss Method else From af451b6278bb67dd2cfef9279aca8df75668ca5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 2 Jan 2024 16:54:57 -0600 Subject: [PATCH 093/173] Fix boundary_projection --- src/orbit_determination/tooshortarc.jl | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index c7c238f8..03931d61 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -226,9 +226,15 @@ function boundary_projection(A::AdmissibleRegion{T}, ρ::T, v_ρ::T) where {T <: # Project range ρ = clamp(ρ, A.ρ_domain[1], A.ρ_domain[2]) # Project range-rate - y_min, y_max = range_rate(A, ρ) - v_ρ = clamp(v_ρ, y_min, y_max) - + y_domain = range_rate(A, ρ) + if iszero(length(y_domain)) + v_ρ = sum(A.v_ρ_domain) / 2 + elseif isone(length(y_domain)) + v_ρ = y_domain[1] + else + v_ρ = clamp(v_ρ, y_domain[1], y_domain[2]) + end + return ρ, v_ρ end From 0c1053045cbb24dad7b416e7eb3db4523a492c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 2 Jan 2024 18:30:35 -0600 Subject: [PATCH 094/173] Add init to kmeans --- src/orbit_determination/outlier_rejection.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/orbit_determination/outlier_rejection.jl b/src/orbit_determination/outlier_rejection.jl index 403c46b2..f81144d6 100644 --- a/src/orbit_determination/outlier_rejection.jl +++ b/src/orbit_determination/outlier_rejection.jl @@ -160,7 +160,7 @@ function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, points[2, i] = N_outliers[i] end # K-means clustering - cluster = kmeans(points, 2) + cluster = kmeans(points, 2; init = [1, max_drop + 1]) # Index of smallest cluster i_0 = cluster.assignments[1] # Find last fit of smallest cluster From 0fc33c448e11bb8f954d28768f20a867f75d4aab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 4 Jan 2024 11:09:12 -0600 Subject: [PATCH 095/173] Minor fixes --- src/orbit_determination/tooshortarc.jl | 28 +++++++++++++++++++------- src/postprocessing/least_squares.jl | 12 +++++++++-- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 03931d61..bcaf9759 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -65,13 +65,7 @@ function AdmissibleRegion(night::ObservationNight{T}) where {T <: AbstractFloat} ρ_min = 10^((h - H_max)/5) end # Maximum range (heliocentric constraint) - ρ_max = find_zeros(s -> admsreg_U(coeffs, s), ρ_min, 10.0)[1] - # Make sure U(ρ) ≥ 0 - niter = 0 - while admsreg_U(coeffs, ρ_max) < 0 && niter < 1_000 - niter += 1 - ρ_max = prevfloat(ρ_max) - end + ρ_max = max_range(coeffs, ρ_min) # Range domain ρ_domain = [ρ_min, ρ_max] # Range rate domain @@ -189,6 +183,26 @@ function range_rate(coeffs::Vector{T}, ρ::S) where {T, S <: AbstractFloat} end range_rate(A::AdmissibleRegion{T}, ρ::S) where {T, S <: AbstractFloat} = range_rate(A.coeffs, ρ) +@doc raw""" + max_range(coeffs::Vector{T}, ρ_min::T) where {T <: AbstractFloat} + +Return the maximum possible range in the boundary of an admissible region +with coefficients `coeffs` and minimum allowed range `ρ_min`. +""" +function max_range(coeffs::Vector{T}, ρ_min::T) where {T <: AbstractFloat} + # Initial guess + ρ_max = find_zeros(s -> admsreg_U(coeffs, s), ρ_min, 10.0)[1] + # Make sure U(ρ) ≥ 0 and there is at least one range_rate solution + niter = 0 + while admsreg_U(coeffs, ρ_max) < 0 || length(range_rate(coeffs, ρ_max)) == 0 + niter += 1 + ρ_max = prevfloat(ρ_max) + niter > 1_000 && break + end + + return ρ_max +end + @doc raw""" boundary(A::AdmissibleRegion{T}, t::S) where {T <: AbstractFloat, S <: Number} diff --git a/src/postprocessing/least_squares.jl b/src/postprocessing/least_squares.jl index 9a679ebe..22f07251 100755 --- a/src/postprocessing/least_squares.jl +++ b/src/postprocessing/least_squares.jl @@ -383,7 +383,11 @@ function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, # Covariance matrix Γ = inv(C) - return OrbitFit(true, x_new, Γ, :diffcorr) + if any(diag(Γ) .< 0) + return OrbitFit(false, x_new, Γ, :diffcorr) + else + return OrbitFit(true, x_new, Γ, :diffcorr) + end end function diffcorr(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, @@ -479,7 +483,11 @@ function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, # Covariance matrix Γ = inv(C) - return OrbitFit(true, x_new, Γ, :newton) + if any(diag(Γ) .< 0) + return OrbitFit(false, x_new, Γ, :newton) + else + return OrbitFit(true, x_new, Γ, :newton) + end end function newtonls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, From fe7f6da7ccf0ebef2ce6c6adc302843a01c11102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 5 Jan 2024 08:25:58 -0600 Subject: [PATCH 096/173] Polynomial fit --- Project.toml | 2 +- src/NEOs.jl | 2 +- src/observations/observation_night.jl | 55 ++++++++++++++++++++++----- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/Project.toml b/Project.toml index 5b800100..841c0c7c 100755 --- a/Project.toml +++ b/Project.toml @@ -12,7 +12,6 @@ Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" -GLM = "38e38edf-8417-5370-95a0-9cbb8c7f171a" HORIZONS = "5a3ac768-beb4-554a-9c98-3342fe3377f5" HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" Healpix = "9f4e344d-96bc-545a-84a3-ae6b9e1b672b" @@ -21,6 +20,7 @@ JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" LazyArtifacts = "4af54fe1-eca0-43a8-85a7-787d91b784e3" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +LsqFit = "2fda8390-95c7-5789-9bda-21331edee243" PlanetaryEphemeris = "d83715d0-7e5f-11e9-1a59-4137b20d8363" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Quadmath = "be4d8f0f-7fa4-5f49-b795-2f01399ab2dd" diff --git a/src/NEOs.jl b/src/NEOs.jl index f81e23e0..a48fb4ae 100755 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -23,7 +23,7 @@ using PlanetaryEphemeris: daysec, yr, TaylorInterpolant, auday2kmsec, su, ea, au meanmotion, meananomaly, selecteph using Healpix: ang2pixRing, Resolution using StatsBase: mean, std -using GLM: @formula, lm, coef +using LsqFit: curve_fit using Roots: find_zeros using Clustering: kmeans diff --git a/src/observations/observation_night.jl b/src/observations/observation_night.jl index c5a9569f..b8a2fa76 100644 --- a/src/observations/observation_night.jl +++ b/src/observations/observation_night.jl @@ -59,6 +59,45 @@ end # Order in ObservationNight is given by date isless(a::ObservationNight{T}, b::ObservationNight{T}) where {T <: AbstractFloat} = a.date < b.date +# Evaluate a polynomial with coefficients p in every element of x +polymodel(x, p) = map(y -> evalpoly(y, p), x) + +# Normalized mean square residual for polynomial fit +polyerror(x) = sum(x .^ 2) / length(x) + +@doc raw""" + polyfit(x::Vector{T}, y::Vector{T}; tol::T = 1e-4) where {T <: AbstractFloat} + +Fit a polynomial to points `(x, y)`. The order of the polynomial is increased +until `polyerror` is less than `tol`. +""" +function polyfit(x::Vector{T}, y::Vector{T}; tol::T = 1e-4) where {T <: AbstractFloat} + # Avoid odd and high orders (to have a defined concavity and avoid overfit) + for order in [1, 2, 4, 6] + # Initial guess for coefficients + coeffs = ones(T, order+1) + # Polynomial fit + fit = curve_fit(polymodel, x, y, coeffs) + # Convergence condition + if polyerror(fit.resid) < tol || order == 6 + return fit.param + end + end +end + +@doc raw""" + diffcoeffs(x::Vector{T}) where {T <: AbstractFloat} + +Return the coefficients of the derivative of a polynomial with coefficients `x`. +""" +function diffcoeffs(x::Vector{T}) where {T <: AbstractFloat} + y = Vector{T}(undef, length(x)-1) + for i in eachindex(y) + y[i] = i * x[i+1] + end + return y +end + # Outer constructor function ObservationNight(radec::Vector{RadecMPC{T}}, df::AbstractDataFrame) where {T <: AbstractFloat} # Defining quantities of an ObservationNight @@ -98,17 +137,15 @@ function ObservationNight(radec::Vector{RadecMPC{T}}, df::AbstractDataFrame) whe df.α = map(x -> x < π ? x + 2π : x, df.α) end - # Linear regression - α_p = lm(@formula(α ~ t_rel), df) - α_coef = coef(α_p) - δ_p = lm(@formula(δ ~ t_rel), df) - δ_coef = coef(δ_p) + # Polynomial regression + α_coef = polyfit(df.t_rel, df.α) + δ_coef = polyfit(df.t_rel, df.δ) # Evaluate polynomials at mean date - α = mod2pi(α_coef[1] + α_coef[2] * t_mean) - δ = δ_coef[1] + δ_coef[2] * t_mean - v_α = α_coef[2] - v_δ = δ_coef[2] + α = mod2pi(polymodel(t_mean, α_coef)) + δ = polymodel(t_mean, δ_coef) + v_α = polymodel(t_mean, diffcoeffs(α_coef)) + v_δ = polymodel(t_mean, diffcoeffs(δ_coef)) # Mean apparent magnitude mag = mean(filter(!isnan, df.mag)) From 1d36ab198bd96556d34571221f3f0df701b1be02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 6 Jan 2024 11:21:58 -0600 Subject: [PATCH 097/173] Heel anomaly in tsa --- src/orbit_determination/tooshortarc.jl | 32 ++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index bcaf9759..fc810cec 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -497,8 +497,36 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight ρs, v_ρs, _ = adam(radec, A, ρ, v_ρ, params) # Barycentric initial conditions q0 = topo2bary(A, ρs[end], v_ρs[end]) + # Initial time of integration [julian days] + jd0 = datetime2julian(A.date) # 6 variables least squares - sol = tsals(radec, nights, datetime2julian(A.date), q0, params; maxiter = 5) + sol = tsals(radec, nights, jd0, q0, params; maxiter = 5) + # Update best solution + if nrms(sol) < nrms(best_sol) + best_sol = sol + # Break condition + nrms(sol) < 1.5 && break + end + # Heel anomaly + ρ = A.ρ_domain[1] + v_ρs = LinRange(A.v_ρ_domain[1], A.v_ρ_domain[2], 25) + Qs = fill(Inf, 25) + for i in eachindex(Qs) + # Barycentric initial conditions + q = topo2bary(A, ρ, v_ρs[i]) + # Propagation & residuals + _, _, res = propres(radec, jd0, q, params) + iszero(length(res)) && continue + # NRMS + Qs[i] = nrms(res) + end + # Find solution with smallest Q + t = argmin(Qs) + isinf(Qs[t]) && continue + # Barycentric initial conditions + q0 = topo2bary(A, ρ, v_ρs[t]) + # 6 variables least squares + sol = tsals(radec, nights, jd0, q0, params; maxiter = 5) # Update best solution if nrms(sol) < nrms(best_sol) best_sol = sol @@ -506,6 +534,6 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight nrms(sol) < 1.5 && break end end - + return best_sol end \ No newline at end of file From 074372ed5096c74e84e1770cc466bee8e00f00d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 7 Jan 2024 07:36:43 -0600 Subject: [PATCH 098/173] Minor fix --- src/orbit_determination/tooshortarc.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index fc810cec..44bdaf2c 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -312,7 +312,8 @@ function propres(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{U}, # Backward (forward) integration bwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q0, params) fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q0, params) - if bwd.t[end] > t0 - jd0 || fwd.t[end] < tf - jd0 + if bwd.t[end] > t0 - jd0 || fwd.t[end] < tf - jd0 || + any(norm.(bwd.x, Inf) .> 100) || any(norm.(fwd.x, Inf) .> 100) return bwd, fwd, Vector{OpticalResidual{T, U}}(undef, 0) end # Sun (Earth) ephemeris From db73ab30a991928bc59d195c8b51e2533084ec7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Mon, 8 Jan 2024 07:11:08 -0600 Subject: [PATCH 099/173] Another minor fix --- src/orbit_determination/outlier_rejection.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/orbit_determination/outlier_rejection.jl b/src/orbit_determination/outlier_rejection.jl index f81144d6..09ffec08 100644 --- a/src/orbit_determination/outlier_rejection.jl +++ b/src/orbit_determination/outlier_rejection.jl @@ -52,14 +52,14 @@ function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, # Backward integration bwd = propagate(dynamics, jd0, nyears_bwd, q, params) - if bwd.t[end] > t0 - jd0 + if bwd.t[end] > t0 - jd0 || any(norm.(bwd.x, Inf) .> 100) return zero(NEOSolution{T, T}) end # Forward integration fwd = propagate(dynamics, jd0, nyears_fwd, q, params) - if fwd.t[end] < tf - jd0 + if fwd.t[end] < tf - jd0 || any(norm.(fwd.x, Inf) .> 100) return zero(NEOSolution{T, T}) end From bf58bac45978a8c32b8eb02d5e555d2b2dcf0980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 9 Jan 2024 20:05:06 -0600 Subject: [PATCH 100/173] unsuccessful_propagation --- src/orbit_determination/gauss_method.jl | 8 +++--- src/orbit_determination/outlier_rejection.jl | 4 +-- src/orbit_determination/tooshortarc.jl | 22 +++++++++++--- src/propagation/propagation.jl | 30 ++++++++++++++++++-- 4 files changed, 52 insertions(+), 12 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 51bb1d73..09e44c04 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -485,18 +485,18 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNig bwd::TaylorInterpolant{T, TaylorN{T}, 2} = propagate( RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q0, params ) - - if bwd.t[end]::T > t0 - jd0 + if unsuccessful_propagation(bwd, t0 - jd0) continue end + # Forward propagation fwd::TaylorInterpolant{T, TaylorN{T}, 2} = propagate( RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q0, params ) - - if fwd.t[end]::T < tf - jd0 + if unsuccessful_propagation(fwd, tf - jd0) continue end + # O-C residuals res::Vector{OpticalResidual{T, TaylorN{T}}} = residuals( radec, params; diff --git a/src/orbit_determination/outlier_rejection.jl b/src/orbit_determination/outlier_rejection.jl index 09ffec08..962db8cf 100644 --- a/src/orbit_determination/outlier_rejection.jl +++ b/src/orbit_determination/outlier_rejection.jl @@ -52,14 +52,14 @@ function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, # Backward integration bwd = propagate(dynamics, jd0, nyears_bwd, q, params) - if bwd.t[end] > t0 - jd0 || any(norm.(bwd.x, Inf) .> 100) + if unsuccessful_propagation(bwd, t0 - jd0) return zero(NEOSolution{T, T}) end # Forward integration fwd = propagate(dynamics, jd0, nyears_fwd, q, params) - if fwd.t[end] < tf - jd0 || any(norm.(fwd.x, Inf) .> 100) + if unsuccessful_propagation(fwd, tf - jd0) return zero(NEOSolution{T, T}) end diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 44bdaf2c..d862a22a 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -39,6 +39,17 @@ some dynamical constrainits on a too short arc. observatory::ObservatoryMPC{T} end +# Definition of zero AdmissibleRegion{T} +function zero(::Type{AdmissibleRegion{T}}) where {T <: AbstractFloat} + return AdmissibleRegion{T}( + DateTime(2000), zero(T), zero(T), zero(T), zero(T), Vector{T}(undef, 0), + Vector{T}(undef, 0), Vector{T}(undef, 0), Vector{T}(undef, 0), Vector{T}(undef, 0), + Vector{T}(undef, 0), Vector{T}(undef, 0), Matrix{T}(undef, 0, 0), unknownobs() + ) +end + +iszero(x::AdmissibleRegion{T}) where {T <: AbstractFloat} = x == zero(AdmissibleRegion{T}) + # Outer constructor function AdmissibleRegion(night::ObservationNight{T}) where {T <: AbstractFloat} # Unfold @@ -66,6 +77,7 @@ function AdmissibleRegion(night::ObservationNight{T}) where {T <: AbstractFloat} end # Maximum range (heliocentric constraint) ρ_max = max_range(coeffs, ρ_min) + iszero(ρ_max) && return zero(AdmissibleRegion{Float64}) # Range domain ρ_domain = [ρ_min, ρ_max] # Range rate domain @@ -87,7 +99,7 @@ end admsreg_coeffs(α::T, δ::T, v_α::T, v_δ::T, ρ::Vector{T}, ρ_α::Vector{T}, ρ_δ::Vector{T}, q::Vector{T}) where {T <: Number} -Return the polynomial coefficients for an [`AdmissibleRegioin`](@ref). +Return the polynomial coefficients for an [`AdmissibleRegion`](@ref). !!! reference See equation (8.8) of https://doi.org/10.1017/CBO9781139175371. @@ -191,7 +203,9 @@ with coefficients `coeffs` and minimum allowed range `ρ_min`. """ function max_range(coeffs::Vector{T}, ρ_min::T) where {T <: AbstractFloat} # Initial guess - ρ_max = find_zeros(s -> admsreg_U(coeffs, s), ρ_min, 10.0)[1] + sol = find_zeros(s -> admsreg_U(coeffs, s), ρ_min, 10.0) + iszero(length(sol)) && return zero(T) + ρ_max = sol[1] # Make sure U(ρ) ≥ 0 and there is at least one range_rate solution niter = 0 while admsreg_U(coeffs, ρ_max) < 0 || length(range_rate(coeffs, ρ_max)) == 0 @@ -312,8 +326,7 @@ function propres(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{U}, # Backward (forward) integration bwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q0, params) fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q0, params) - if bwd.t[end] > t0 - jd0 || fwd.t[end] < tf - jd0 || - any(norm.(bwd.x, Inf) .> 100) || any(norm.(fwd.x, Inf) .> 100) + if unsuccessful_propagation(bwd, t0 - jd0) || unsuccessful_propagation(fwd, tf - jd0) return bwd, fwd, Vector{OpticalResidual{T, U}}(undef, 0) end # Sun (Earth) ephemeris @@ -491,6 +504,7 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight for i in idxs # Admissible region A = AdmissibleRegion(nights[i]) + iszero(A) && continue # Center ρ = sum(A.ρ_domain) / 2 v_ρ = sum(A.v_ρ_domain) / 2 diff --git a/src/propagation/propagation.jl b/src/propagation/propagation.jl index 8c3ec2c4..03163959 100755 --- a/src/propagation/propagation.jl +++ b/src/propagation/propagation.jl @@ -42,6 +42,26 @@ function scaled_variables(names::String = "δx", c::Vector{T} = fill(1e-6, 6); o return dq end +# Definition of zero TaylorInterpolant{T, U, 2} +function zero(::Type{TaylorInterpolant{T, U, 2}}) where {T <: Real, U <: Number} + return TaylorInterpolant{T, U, 2}(zero(T), zeros(T, 1), Matrix{Taylor1{U}}(undef, 0, 0)) +end + +iszero(x::TaylorInterpolant{T, U, 2}) where {T <: Real, U <: Number} = x == zero(TaylorInterpolant{T, U, 2}) + +function unsuccessful_propagation(sol::TaylorInterpolant{T, U, 2}, t::T) where {T <: Real, U <: Number} + + if issorted(sol.t) + c = sol.t[end] < t + elseif issorted(sol.t, rev = true) + c = sol.t[end] > t + else + c = true + end + + return iszero(sol) || any(norm.(sol.x, Inf) .> 10) || c +end + @doc raw""" propagate_params(jd0::T, tspan::T, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number} @@ -138,8 +158,14 @@ function propagate(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, @time tv, xv, psol = taylorinteg(dynamics, _q0, _t0, _tmax, order, abstol, Val(true), _params; maxsteps = maxsteps, parse_eqs = parse_eqs) - return TaylorInterpolant(jd0 - JD_J2000, tv .- tv[1], psol) - + # Assemble TaylorInterpolant + t0 = jd0 - JD_J2000 + t = tv .- tv[1] + if issorted(t) || issorted(t, rev = true) + return TaylorInterpolant{T, U, 2}(t0, t, psol) + else + return zero(TaylorInterpolant{T, U, 2}) + end end @doc raw""" From ad9471abbfd4de2e5b853aef2b87333e1875f1cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 18 Jan 2024 12:52:12 -0600 Subject: [PATCH 101/173] Try reset CI.yml to origin/main --- .github/workflows/CI.yml | 102 +++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 51 deletions(-) mode change 100755 => 100644 .github/workflows/CI.yml diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml old mode 100755 new mode 100644 index f402e19a..ce1a4a14 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -1,51 +1,51 @@ -name: CI -on: - push: - paths-ignore: - - 'LICENSE.md' - - 'README.md' - pull_request: - branches: - - main - tags: '*' -concurrency: - # Skip intermediate builds: always. - # Cancel intermediate builds: only if it is a pull request build. - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} -jobs: - test: - name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} - runs-on: ${{ matrix.os }} - continue-on-error: ${{ matrix.version == 'nightly' }} - strategy: - fail-fast: false - matrix: - version: - - '1.9' - # - '1' - - 'nightly' - os: - - ubuntu-latest - - macos-latest - - windows-latest - arch: - - x64 - steps: - - uses: actions/checkout@v3 - - uses: julia-actions/setup-julia@v1 - with: - version: ${{ matrix.version }} - arch: ${{ matrix.arch }} - - uses: julia-actions/cache@v1 - - uses: julia-actions/julia-buildpkg@v1 - - uses: julia-actions/julia-runtest@v1 - env: - JULIA_NUM_THREADS: 2 - - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v3 - with: - files: lcov.info - - uses: julia-actions/julia-uploadcoveralls@v1 - env: - COVERALLS_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} +name: CI +on: + push: + paths-ignore: + - 'LICENSE.md' + - 'README.md' + pull_request: + branches: + - main + tags: '*' +concurrency: + # Skip intermediate builds: always. + # Cancel intermediate builds: only if it is a pull request build. + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} +jobs: + test: + name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} + runs-on: ${{ matrix.os }} + continue-on-error: ${{ matrix.version == 'nightly' }} + strategy: + fail-fast: false + matrix: + version: + - '1.9' + # - '1' + - 'nightly' + os: + - ubuntu-latest + - macos-latest + - windows-latest + arch: + - x64 + steps: + - uses: actions/checkout@v3 + - uses: julia-actions/setup-julia@v1 + with: + version: ${{ matrix.version }} + arch: ${{ matrix.arch }} + - uses: julia-actions/cache@v1 + - uses: julia-actions/julia-buildpkg@v1 + - uses: julia-actions/julia-runtest@v1 + env: + JULIA_NUM_THREADS: 2 + - uses: julia-actions/julia-processcoverage@v1 + - uses: codecov/codecov-action@v3 + with: + files: lcov.info + - uses: julia-actions/julia-uploadcoveralls@v1 + env: + COVERALLS_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} From 6b0307b798cd57ae682fd25e9245ce9b3cf4e460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 18 Jan 2024 12:57:01 -0600 Subject: [PATCH 102/173] Reset .github/ and data/ to origin/main --- .github/workflows/CompatHelper.yml | 32 +++++++++++++++--------------- .github/workflows/TagBot.yml | 30 ++++++++++++++-------------- data/101955_OPTICAL_1999_2006.dat | 0 data/101955_OPTICAL_2011_2018.dat | 0 data/101955_RADAR_1999_2005.dat | 0 data/101955_RADAR_2011.dat | 0 data/99942.dat | 0 data/99942_2004_2020.dat | 0 data/99942_2020_2021.dat | 0 data/99942_RADAR_2005_2013.dat | 0 data/99942_RADAR_2021.dat | 0 data/Apophis_JPL_data.dat | 0 data/mpec_2014-R71.dat | 0 data/mps_375184.dat | 0 data/panstarrs-1.dat | 0 data/tholenetal2013_opterror.dat | 0 data/vokr15_mpc_formatted.dat | 0 17 files changed, 31 insertions(+), 31 deletions(-) mode change 100755 => 100644 .github/workflows/CompatHelper.yml mode change 100755 => 100644 .github/workflows/TagBot.yml mode change 100755 => 100644 data/101955_OPTICAL_1999_2006.dat mode change 100755 => 100644 data/101955_OPTICAL_2011_2018.dat mode change 100755 => 100644 data/101955_RADAR_1999_2005.dat mode change 100755 => 100644 data/101955_RADAR_2011.dat mode change 100755 => 100644 data/99942.dat mode change 100755 => 100644 data/99942_2004_2020.dat mode change 100755 => 100644 data/99942_2020_2021.dat mode change 100755 => 100644 data/99942_RADAR_2005_2013.dat mode change 100755 => 100644 data/99942_RADAR_2021.dat mode change 100755 => 100644 data/Apophis_JPL_data.dat mode change 100755 => 100644 data/mpec_2014-R71.dat mode change 100755 => 100644 data/mps_375184.dat mode change 100755 => 100644 data/panstarrs-1.dat mode change 100755 => 100644 data/tholenetal2013_opterror.dat mode change 100755 => 100644 data/vokr15_mpc_formatted.dat diff --git a/.github/workflows/CompatHelper.yml b/.github/workflows/CompatHelper.yml old mode 100755 new mode 100644 index 4e822131..cba9134c --- a/.github/workflows/CompatHelper.yml +++ b/.github/workflows/CompatHelper.yml @@ -1,16 +1,16 @@ -name: CompatHelper -on: - schedule: - - cron: 0 0 * * * - workflow_dispatch: -jobs: - CompatHelper: - runs-on: ubuntu-latest - steps: - - name: Pkg.add("CompatHelper") - run: julia -e 'using Pkg; Pkg.add("CompatHelper")' - - name: CompatHelper.main() - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - COMPATHELPER_PRIV: ${{ secrets.DOCUMENTER_KEY }} - run: julia -e 'using CompatHelper; CompatHelper.main()' +name: CompatHelper +on: + schedule: + - cron: 0 0 * * * + workflow_dispatch: +jobs: + CompatHelper: + runs-on: ubuntu-latest + steps: + - name: Pkg.add("CompatHelper") + run: julia -e 'using Pkg; Pkg.add("CompatHelper")' + - name: CompatHelper.main() + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COMPATHELPER_PRIV: ${{ secrets.DOCUMENTER_KEY }} + run: julia -e 'using CompatHelper; CompatHelper.main()' diff --git a/.github/workflows/TagBot.yml b/.github/workflows/TagBot.yml old mode 100755 new mode 100644 index 083baf95..f49313b6 --- a/.github/workflows/TagBot.yml +++ b/.github/workflows/TagBot.yml @@ -1,15 +1,15 @@ -name: TagBot -on: - issue_comment: - types: - - created - workflow_dispatch: -jobs: - TagBot: - if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' - runs-on: ubuntu-latest - steps: - - uses: JuliaRegistries/TagBot@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - ssh: ${{ secrets.DOCUMENTER_KEY }} +name: TagBot +on: + issue_comment: + types: + - created + workflow_dispatch: +jobs: + TagBot: + if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' + runs-on: ubuntu-latest + steps: + - uses: JuliaRegistries/TagBot@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + ssh: ${{ secrets.DOCUMENTER_KEY }} diff --git a/data/101955_OPTICAL_1999_2006.dat b/data/101955_OPTICAL_1999_2006.dat old mode 100755 new mode 100644 diff --git a/data/101955_OPTICAL_2011_2018.dat b/data/101955_OPTICAL_2011_2018.dat old mode 100755 new mode 100644 diff --git a/data/101955_RADAR_1999_2005.dat b/data/101955_RADAR_1999_2005.dat old mode 100755 new mode 100644 diff --git a/data/101955_RADAR_2011.dat b/data/101955_RADAR_2011.dat old mode 100755 new mode 100644 diff --git a/data/99942.dat b/data/99942.dat old mode 100755 new mode 100644 diff --git a/data/99942_2004_2020.dat b/data/99942_2004_2020.dat old mode 100755 new mode 100644 diff --git a/data/99942_2020_2021.dat b/data/99942_2020_2021.dat old mode 100755 new mode 100644 diff --git a/data/99942_RADAR_2005_2013.dat b/data/99942_RADAR_2005_2013.dat old mode 100755 new mode 100644 diff --git a/data/99942_RADAR_2021.dat b/data/99942_RADAR_2021.dat old mode 100755 new mode 100644 diff --git a/data/Apophis_JPL_data.dat b/data/Apophis_JPL_data.dat old mode 100755 new mode 100644 diff --git a/data/mpec_2014-R71.dat b/data/mpec_2014-R71.dat old mode 100755 new mode 100644 diff --git a/data/mps_375184.dat b/data/mps_375184.dat old mode 100755 new mode 100644 diff --git a/data/panstarrs-1.dat b/data/panstarrs-1.dat old mode 100755 new mode 100644 diff --git a/data/tholenetal2013_opterror.dat b/data/tholenetal2013_opterror.dat old mode 100755 new mode 100644 diff --git a/data/vokr15_mpc_formatted.dat b/data/vokr15_mpc_formatted.dat old mode 100755 new mode 100644 From 9c10cee579686a648181015f7e5cb03d88a6d4f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 18 Jan 2024 13:00:35 -0600 Subject: [PATCH 103/173] Reset dev/ and notebooks/ to origin/main --- dev/generate_artifacts.jl | 200 +-- notebooks/Apophis.ipynb | 2262 +++++++++++++++---------------- notebooks/B-plane-jt-o5v7.ipynb | 0 notebooks/Plots-paper.ipynb | 0 notebooks/gnuplot.cfg | 0 5 files changed, 1231 insertions(+), 1231 deletions(-) mode change 100755 => 100644 dev/generate_artifacts.jl mode change 100755 => 100644 notebooks/Apophis.ipynb mode change 100755 => 100644 notebooks/B-plane-jt-o5v7.ipynb mode change 100755 => 100644 notebooks/Plots-paper.ipynb mode change 100755 => 100644 notebooks/gnuplot.cfg diff --git a/dev/generate_artifacts.jl b/dev/generate_artifacts.jl old mode 100755 new mode 100644 index 770bf545..f901ea8d --- a/dev/generate_artifacts.jl +++ b/dev/generate_artifacts.jl @@ -1,100 +1,100 @@ -# This script generates Julia artifacts for NEOs.jl, including -# - debiasing tables from Chesley et al. (2010), Farnocchia et al. (2015) and Eggl et al. (2020) -# - JPL lsk and spk -# - PlanetaryEphemeris.jl Solar System ephemeris -# TODO: adapt script for 2010 debiasing tables (requires extra unpacking) -# -# This script can be run from NEOs.jl root directory with: -# julia --project dev/generate_artifacts.jl - -using Pkg.Artifacts -using Pkg.PlatformEngines: sha256, unpack -using Downloads - -# This is the path to the Artifacts.toml we will manipulate -const artifact_toml = joinpath(dirname(@__DIR__), "Artifacts.toml") - -# JPL FTP URL -const ftp_jpl = "https://ssd.jpl.nasa.gov/ftp/" - -# Debiasing tables names and URLs -const names_debias = ["debias", "debias_2014", "debias_2018", "debias_hires2018"] -const urls_debias = ftp_jpl .* "ssd/debias/" .* names_debias .* ".tgz" - -# JPL lsk and spk names and URLs -const names_lsk_spk = ["naif0012", "de430", "TTmTDBde430", "a99942"] -const urls_lsk_spk = [ - "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/lsk/naif0012.tls", - ftp_jpl*"eph/planets/bsp/de430_1850-2150.bsp", - ftp_jpl*"eph/planets/bsp/TTmTDB.de430.19feb2015.bsp", - "https://raw.githubusercontent.com/PerezHz/jpleph/main/a99942.tar.gz", -] - -# PlanetaryEphemeris.jl Solar System ephemeris name and URL -const name_sseph = "sseph_p100" -const url_sseph = "https://github.com/LuEdRaMo/sseph/raw/main/sseph343ast016_p100y_et.tar.gz" - -# Collect names and URLs -const urls = vcat(urls_lsk_spk, urls_debias, url_sseph) -const names = vcat(names_lsk_spk, names_debias, name_sseph) - -for (url, name) in zip(urls, names) - # Query the `Artifacts.toml` file for the hash bound to the name - # (returns `nothing` if no such binding exists) - artfct_hash = artifact_hash(name, artifact_toml) - # If the name was not bound, or the hash it was bound to does not exist, create it! - if isnothing(artfct_hash) || !artifact_exists(artfct_hash) - tb = Tuple[] - # create_artifact() returns the content-hash of the artifact directory once we're finished creating it - artfct_hash = create_artifact() do artifact_dir - # We create the artifact by simply downloading a few files into the new artifact directory - @show url name - tmp_dir = mktempdir() - basename_url = basename(url) - @show basename_url - dot_idx = findlast(isequal('.'), basename_url) - ext = basename_url[dot_idx+1:end] - if ext in ["gz", "tgz"] # If artifact is a tarball with many files - # the following code block was adapted from PlatformEngines.jl, MIT licensed - # https://github.com/JuliaLang/Pkg.jl/blob/048b0e86deba0c5f491eb1a3af2f3c97cac675b3/src/PlatformEngines.jl#L348 - dest = joinpath(tmp_dir, basename(url)) - tarball = "" - f = retry(delays = fill(1.0, 3)) do - try - tarball = Downloads.download(url, dest) - catch err - @debug "download and verify failed" url dest err - rethrow() - end - end - f() - try - tarball_hash = open(tarball) do file - bytes2hex(sha256(file)) - end - unpack(tarball, artifact_dir) - tb = [(url, tarball_hash)] - finally - rm(tarball) - end - else # url containing a single non-tarball file - fpath = Downloads.download(url, joinpath(artifact_dir, basename(url))) - file_hash = open(fpath) do file - bytes2hex(sha256(file)) - end - tb = [(url, file_hash)] - end - end - @show artfct_hash typeof(artfct_hash) - # Now bind that hash within our `Artifacts.toml`. `force = true` means that if it already exists, - # just overwrite the corresponding entry in `Artifacts.toml` with the new content-hash. - # Unless the source files change, we do not expect the content hash to - # change, so this should not cause unnecessary version control churn. - bind_artifact!(artifact_toml, name, artfct_hash, lazy=true, force=true, download_info=tb) - end - - # Get the path of the artifact, either newly created or previously generated. - # this should be something like `~/.julia/artifacts/dbd04e28be047a54fbe9bf67e934be5b5e0d357a` - artfct_path = artifact_path(artfct_hash) - println(name, " artifact saved to ", artfct_path) -end +# This script generates Julia artifacts for NEOs.jl, including +# - debiasing tables from Chesley et al. (2010), Farnocchia et al. (2015) and Eggl et al. (2020) +# - JPL lsk and spk +# - PlanetaryEphemeris.jl Solar System ephemeris +# TODO: adapt script for 2010 debiasing tables (requires extra unpacking) +# +# This script can be run from NEOs.jl root directory with: +# julia --project dev/generate_artifacts.jl + +using Pkg.Artifacts +using Pkg.PlatformEngines: sha256, unpack +using Downloads + +# This is the path to the Artifacts.toml we will manipulate +const artifact_toml = joinpath(dirname(@__DIR__), "Artifacts.toml") + +# JPL FTP URL +const ftp_jpl = "https://ssd.jpl.nasa.gov/ftp/" + +# Debiasing tables names and URLs +const names_debias = ["debias", "debias_2014", "debias_2018", "debias_hires2018"] +const urls_debias = ftp_jpl .* "ssd/debias/" .* names_debias .* ".tgz" + +# JPL lsk and spk names and URLs +const names_lsk_spk = ["naif0012", "de430", "TTmTDBde430", "a99942"] +const urls_lsk_spk = [ + "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/lsk/naif0012.tls", + ftp_jpl*"eph/planets/bsp/de430_1850-2150.bsp", + ftp_jpl*"eph/planets/bsp/TTmTDB.de430.19feb2015.bsp", + "https://raw.githubusercontent.com/PerezHz/jpleph/main/a99942.tar.gz", +] + +# PlanetaryEphemeris.jl Solar System ephemeris name and URL +const name_sseph = "sseph_p100" +const url_sseph = "https://github.com/LuEdRaMo/sseph/raw/main/sseph343ast016_p100y_et.tar.gz" + +# Collect names and URLs +const urls = vcat(urls_lsk_spk, urls_debias, url_sseph) +const names = vcat(names_lsk_spk, names_debias, name_sseph) + +for (url, name) in zip(urls, names) + # Query the `Artifacts.toml` file for the hash bound to the name + # (returns `nothing` if no such binding exists) + artfct_hash = artifact_hash(name, artifact_toml) + # If the name was not bound, or the hash it was bound to does not exist, create it! + if isnothing(artfct_hash) || !artifact_exists(artfct_hash) + tb = Tuple[] + # create_artifact() returns the content-hash of the artifact directory once we're finished creating it + artfct_hash = create_artifact() do artifact_dir + # We create the artifact by simply downloading a few files into the new artifact directory + @show url name + tmp_dir = mktempdir() + basename_url = basename(url) + @show basename_url + dot_idx = findlast(isequal('.'), basename_url) + ext = basename_url[dot_idx+1:end] + if ext in ["gz", "tgz"] # If artifact is a tarball with many files + # the following code block was adapted from PlatformEngines.jl, MIT licensed + # https://github.com/JuliaLang/Pkg.jl/blob/048b0e86deba0c5f491eb1a3af2f3c97cac675b3/src/PlatformEngines.jl#L348 + dest = joinpath(tmp_dir, basename(url)) + tarball = "" + f = retry(delays = fill(1.0, 3)) do + try + tarball = Downloads.download(url, dest) + catch err + @debug "download and verify failed" url dest err + rethrow() + end + end + f() + try + tarball_hash = open(tarball) do file + bytes2hex(sha256(file)) + end + unpack(tarball, artifact_dir) + tb = [(url, tarball_hash)] + finally + rm(tarball) + end + else # url containing a single non-tarball file + fpath = Downloads.download(url, joinpath(artifact_dir, basename(url))) + file_hash = open(fpath) do file + bytes2hex(sha256(file)) + end + tb = [(url, file_hash)] + end + end + @show artfct_hash typeof(artfct_hash) + # Now bind that hash within our `Artifacts.toml`. `force = true` means that if it already exists, + # just overwrite the corresponding entry in `Artifacts.toml` with the new content-hash. + # Unless the source files change, we do not expect the content hash to + # change, so this should not cause unnecessary version control churn. + bind_artifact!(artifact_toml, name, artfct_hash, lazy=true, force=true, download_info=tb) + end + + # Get the path of the artifact, either newly created or previously generated. + # this should be something like `~/.julia/artifacts/dbd04e28be047a54fbe9bf67e934be5b5e0d357a` + artfct_path = artifact_path(artfct_hash) + println(name, " artifact saved to ", artfct_path) +end diff --git a/notebooks/Apophis.ipynb b/notebooks/Apophis.ipynb old mode 100755 new mode 100644 index 1249db69..59f9c9a7 --- a/notebooks/Apophis.ipynb +++ b/notebooks/Apophis.ipynb @@ -1,1131 +1,1131 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true, - "tags": [] - }, - "outputs": [], - "source": [ - "import Pkg\n", - "Pkg.activate(\"../pha\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "using Revise" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "using NEOs\n", - "using DataFrames\n", - "using TaylorIntegration\n", - "using PlanetaryEphemeris\n", - "using JLD2\n", - "using Statistics\n", - "using LinearAlgebra\n", - "using Dates\n", - "using StatsBase\n", - "using Gaston\n", - "using DelimitedFiles" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dq = set_variables(\"δx\", order=5, numvars=7)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Load Sun, Earth and Apophis ephemeris" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sol_bwd = JLD2.load(\"Apophis_bwd.jld2\", \"asteph\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sol_fwd = JLD2.load(\"Apophis_fwd.jld2\", \"asteph\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sseph::TaylorInterpolant{Float64,Float64,2} = loadpeeph(NEOs.sseph, sol_bwd.t0+sol_bwd.t[end], sol_fwd.t0+sol_fwd.t[end])\n", - "eph_su::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, su)\n", - "eph_ea::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, ea)\n", - "\n", - "# NEO\n", - "# Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec\n", - "xva_bwd(et) = auday2kmsec(sol_bwd(et/daysec)[1:6])\n", - "xva_fwd(et) = auday2kmsec(sol_fwd(et/daysec)[1:6])\n", - "xva(et) = bwdfwdeph(et, sol_bwd, sol_fwd)\n", - "# Earth\n", - "# Change x, v units, resp., from au, au/day to km, km/sec\n", - "xve(et) = auday2kmsec(eph_ea(et/daysec))\n", - "# Sun\n", - "# Change x, v units, resp., from au, au/day to km, km/sec\n", - "xvs(et) = auday2kmsec(eph_su(et/daysec))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "# get optical observations\n", - "radec_2004_2020 = read_radec_mpc(joinpath(pkgdir(NEOs), \"data\", \"99942_2004_2020.dat\"))\n", - "radec_2020_2021 = read_radec_mpc(joinpath(pkgdir(NEOs), \"data\", \"99942_2020_2021.dat\"))\n", - "radec = vcat(radec_2004_2020,radec_2020_2021)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "# get radar observations\n", - "deldop_2005_2013 = read_radar_jpl(joinpath(pkgdir(NEOs), \"data\", \"99942_RADAR_2005_2013.dat\"))\n", - "deldop_2021 = read_radar_jpl(joinpath(pkgdir(NEOs), \"data\", \"99942_RADAR_2021.dat\"))\n", - "deldop = vcat(deldop_2005_2013,deldop_2021)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "# Compute optical residuals\n", - "@time res_radec_all, w_radec_all = NEOs.residuals(radec; xvs, xve, xva);" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Compute radar residuals\n", - "@time res_del, w_del, res_dop, w_dop = NEOs.residuals(deldop; xvs, xve, xva, niter=10, tord=10);" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Process optical data (filter, weight, debias)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "# filter out biased observations from observatory 217 on 28-Jan-2021\n", - "df_radec = DataFrame(radec)\n", - "# add residuals and weights to optical astrometry DataFrame\n", - "df_radec[!, :res_α] .= res_radec_all[1:round(Int,length(res_radec_all)/2)]\n", - "df_radec[!, :res_δ] .= res_radec_all[1+round(Int,length(res_radec_all)/2):end]\n", - "df_radec[!, :w_α] .= w_radec_all[1:round(Int,length(res_radec_all)/2)]\n", - "df_radec[!, :w_δ] .= w_radec_all[1+round(Int,length(res_radec_all)/2):end]\n", - "filter!(\n", - " x->(Date(x.date) != Date(2021, 1, 28)),\n", - " df_radec\n", - ")\n", - "\n", - "# read astrometric errors from Tholen et al. (2013)\n", - "tho13_errors = readdlm(joinpath(pkgdir(NEOs), \"data\", \"tholenetal2013_opterror.dat\"), ',')\n", - "# compute weights\n", - "w_α_tho13 = 1 ./ (tho13_errors[:,1].^2 .+ tho13_errors[:,3].^2 .+ tho13_errors[:,5].^2)\n", - "w_δ_tho13 = 1 ./ (tho13_errors[:,2].^2 .+ tho13_errors[:,4].^2 .+ tho13_errors[:,6].^2)\n", - "# Tholen et al. (2013) obs table\n", - "radec_tho13 = DataFrame(read_radec_mpc(joinpath(pkgdir(NEOs), \"test\", \"data\", \"99942_Tholen_etal_2013.dat\")))\n", - "# vector of RA values from Tholen et al. (2013) observations (used for filtering)\n", - "tho13_α = radec_tho13[!,:α]\n", - "# set weights in Tholen et al. (2013) astrometry corresponding to associated uncertainties\n", - "df_radec[in.(df_radec.α, Ref(tho13_α)),:w_α] = w_α_tho13\n", - "df_radec[in.(df_radec.α, Ref(tho13_α)),:w_δ] = w_δ_tho13\n", - "\n", - "# Relaxation factor (account for correlations in optical astrometry data)\n", - "# for each observation batch, count the number of observations made in\n", - "# the same night by the same observatory\n", - "# Ref: Veres et al. (2017)\n", - "date_site_v = select(df_radec, :date => ByRow(Date), :observatory)\n", - "Nv = [count(x->x.date_Date==i.date_Date && x.observatory==i.observatory, eachrow(date_site_v)) for i in eachrow(date_site_v)]\n", - "relax_factor = map(x->x>4.0 ? x/4.0 : 1.0, Nv)\n", - "# inflate uncertainties (i.e., relax weights) by relaxation factor\n", - "df_radec[!, :w_α] .= (df_radec.w_α)./relax_factor\n", - "df_radec[!, :w_δ] .= (df_radec.w_δ)./relax_factor\n", - "\n", - "# update optical residuals and weights\n", - "res_radec = vcat(df_radec.res_α, df_radec.res_δ)\n", - "w_radec = vcat(df_radec.w_α, df_radec.w_δ)\n", - ";" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# check if all RA/Dec observations are CCD:\n", - "\n", - "all(\n", - " select(\n", - " df_radec, \n", - " :obstech => ByRow(x->x == \"C\" || x == \"X\")\n", - " )[!,1]\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# there are 512 RA/Dec obs without catalog info\n", - "\n", - "length(df_radec[isunknown.(df_radec.catalogue),:catalogue])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Construct vector of residuals and weights\n", - "\n", - "res = vcat(res_radec, res_del, res_dop)\n", - "w = vcat(w_radec, w_del, w_dop)\n", - ";" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "### Perform 7-DOF orbital fit to optical and radar astrometry data\n", - "\n", - "@show success, δx_OR7, Γ_OR7 = newtonls(res, w, zeros(get_numvars()), 10)\n", - "x_OR7 = sol_fwd(sol_fwd.t0)(δx_OR7);" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "### Perform 6-DOF orbital fit (i.e., without Yarkovsky effect) to optical and radar astrometry data\n", - "\n", - "δx_OR6, Γ_OR6 = newtonls_6v(res, w, zeros(get_numvars()), 10)\n", - "x_OR6 = sol_fwd(sol_fwd.t0)(δx_OR6);" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "### Print results\n", - "\n", - "# orbital fit\n", - "@show success\n", - "@show x_OR7 # cartesian state vector at solution reference epoch\n", - "@show sqrt.(diag(Γ_OR7)).*vcat(1e-8ones(6),1e-14) # uncertainties at solution reference epoch (1-sigma)\n", - ";" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Fit quality statistics: $\\chi^2$, normalized RMS" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The results below correspond to Table 1 of Pérez-Hernández and Benet (2022)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# post-fit statistics\n", - "\n", - "nradec = length(res_radec)\n", - "res_α = view(res_radec, 1:nradec÷2)\n", - "res_δ = view(res_radec, 1+nradec÷2:nradec)\n", - "res_τ = res_del\n", - "res_ν = res_dop\n", - "w_α = view(w_radec, 1:nradec÷2)\n", - "w_δ = view(w_radec, 1+nradec÷2:nradec)\n", - "res_α_OR6 = res_α(δx_OR6)\n", - "res_δ_OR6 = res_δ(δx_OR6)\n", - "res_α_OR7 = res_α(δx_OR7)\n", - "res_δ_OR7 = res_δ(δx_OR7)\n", - "\n", - "@show nrms_radec = nrms(res_radec(δx_OR7),w_radec)\n", - "@show nrms_radec = nrms(vcat(res_del,res_dop)(δx_OR7),vcat(w_del,w_dop))\n", - "@show nrms_optrad = nrms(res(δx_OR7),w)\n", - "@show mean_ra = mean(res_ra(δx_OR7), weights(w_ra))\n", - "@show mean_dec = mean(res_dec(δx_OR7), weights(w_dec))\n", - "@show mean_del = mean(res_del(δx_OR7), weights(w_del))\n", - "@show mean_dop = mean(res_dop(δx_OR7), weights(w_dop))\n", - "@show chi2_optrad = chi2(res(δx_OR7),w)\n", - ";" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Semimajor axis drift" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "jd0 = J2000 + sol_fwd.t0 #Julian date (TDB) of integration initial time\n", - "et0 = (jd0 - J2000)*daysec" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Apophis heliocentric position and velocity at solution reference epoch (plus autodiff perturbations)\n", - "xas = sol_fwd(sol_fwd.t0)[1:6] .- eph_su(jd0-J2000)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Orbital elements of new solution (ecliptic frame at J2000.0 epoch)\n", - "pv2kep(xas(δx_OR7), jd=jd0, frame=:ecliptic)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# JPL solution #216 for Apophis\n", - "kep_JPL216 = [\n", - " 0.1914347568286823, \n", - " 0.7460634895090179, \n", - " 2459424.558511739019, \n", - " 203.9662692226386, \n", - " 126.5900238507279, \n", - " 3.338874353538208, \n", - " -2.901085583204654E-14, \n", - " 5.E-13\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "kep_JT = pv2kep(xas, jd=jd0, frame=:ecliptic) # Orbital elements of JT solution at ref. epoch\n", - "kep_OR7 = pv2kep(xas(δx_OR7), jd=jd0, frame=:ecliptic) # Orbital elements of new solution at ref. epoch" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "# Jacobian of transformation: cartesian state -> Keplerian elements\n", - "t_car2kep(x) = hcat(\n", - " TaylorSeries.gradient(kep_JT.e), \n", - " TaylorSeries.gradient(kep_JT.q),\n", - " TaylorSeries.gradient(kep_JT.tp),\n", - " TaylorSeries.gradient(kep_JT.Ω),\n", - " TaylorSeries.gradient(kep_JT.ω),\n", - " TaylorSeries.gradient(kep_JT.i),\n", - " TaylorSeries.gradient(kep_JT.M),\n", - " TaylorSeries.gradient(kep_JT.a),\n", - " )(x)\n", - "\n", - "# semimajor axis drift \\dot{a} due to Yarkovsky effect in units of au per day, as a function of initial condition\n", - "ady_kep = yarkp2adot(sol_fwd(sol_fwd.t0)[7], kep_JT.a, kep_JT.e)\n", - "\n", - "# semimajor axis drift, au per million years\n", - "ady_kep_au_My = 1e6yr*ady_kep\n", - "\n", - "# semimajor axis drift, meters per year\n", - "ady_kep_m_y = 1e3au*yr*ady_kep\n", - "\n", - "# Jacobian of transformation: cartesian state -> semimajor axis drift in au per million years\n", - "t_kep2ady_au_My(x) = TaylorSeries.gradient(ady_kep_au_My)(x)\n", - "\n", - "# Jacobian of transformation: cartesian state -> semimajor axis drift in meters per year\n", - "t_kep2ady_m_y(x) = TaylorSeries.gradient(ady_kep_m_y)(x)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# mean semimajor axis drift, au per million years\n", - "ady_kep_au_My_OR7 = ady_kep_au_My(δx_OR7) # au/Myr" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# mean semimajor axis drift, meters per year\n", - "ady_kep_m_y_OR7 = 1e3au*yr*ady_kep(δx_OR7) # m/yr" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# uncertainty in semimajor axis drift, au per million years\n", - "sqrt( t_kep2ady_m_y(δx_OR7)'*Γ*t_kep2ady_m_y(δx_OR7) )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# uncertainty in semimajor axis drift, au per million years\n", - "sqrt( t_kep2ady_au_My(δx_OR7)'*Γ*t_kep2ady_au_My(δx_OR7) )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# covariance matrix of Keplerian elements\n", - "Γ_kep = t_car2kep(δx_OR7)'*Γ*t_car2kep(δx_OR7)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#formal uncertainties in Keplerian elements (1-sigma)\n", - "\n", - "sqrt.(diag(Γ_kep))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Plots: optical astrometry post-fit residuals" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#bins_hist = -2.0:0.1:2.0\n", - "nbins_plot = 100\n", - "\n", - "#h_a = fit(Histogram, res_α_OR6, bins_hist)\n", - "h_a = fit(Histogram, res_α_OR6, nbins=nbins_plot)\n", - "bc_a = midpoints(h_a.edges[1]) # bin centers\n", - "bs_a = fill(h_a.edges[1].step.hi, length(bc_a)) # bin sizes\n", - ";\n", - "\n", - "#h_b = fit(Histogram, res_δ_OR6, bins_hist)\n", - "h_b = fit(Histogram, res_δ_OR6, nbins=nbins_plot)\n", - "bc_b = midpoints(h_b.edges[1]) # bin centers\n", - "bs_b = fill(h_b.edges[1].step.hi, length(bc_b)) # bin sizes\n", - "\n", - "#h_c = fit(Histogram, res_α_OR7, bins_hist)\n", - "h_c = fit(Histogram, res_α_OR7, nbins=nbins_plot)\n", - "bc_c = midpoints(h_c.edges[1]) # bin centers\n", - "bs_c = fill(h_c.edges[1].step.hi, length(bc_c)) # bin sizes\n", - "\n", - "#h_d = fit(Histogram, res_δ_OR7, bins_hist)\n", - "h_d = fit(Histogram, res_δ_OR7, nbins=nbins_plot)\n", - "bc_d = midpoints(h_d.edges[1]) # bin centers\n", - "bs_d = fill(h_d.edges[1].step.hi, length(bc_d)) # bin sizes\n", - ";" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "minimum(res_α_OR6), maximum(res_α_OR6)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "minimum(res_δ_OR6), maximum(res_δ_OR6)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "minimum(res_α_OR7), maximum(res_α_OR7)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "minimum(res_δ_OR7), maximum(res_δ_OR7)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "mean(res_α_OR6), mean(res_δ_OR6)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "mean(res_α_OR7), mean(res_δ_OR7)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "angv = vcat(range(0, length=1000, stop=prevfloat(2pi)), 0)\n", - "sigma_factor = 3.0\n", - "σ_cos_ang = sigma_factor*cos.(angv)\n", - "σ_sin_ang = sigma_factor*sin.(angv)\n", - "\n", - "cov_αδ_cholf_OR6 = cholesky(cov(hcat(res_α_OR6, res_δ_OR6)))\n", - "cov_αδ_cholf_OR7 = cholesky(cov(hcat(res_α_OR7, res_δ_OR7)))\n", - "\n", - "ell_3σ_x_OR6 = mean(res_α_OR6) .+ cov_αδ_cholf_OR6.L[1,1].*σ_cos_ang .+ cov_αδ_cholf_OR6.L[1,2].*σ_sin_ang\n", - "ell_3σ_y_OR6 = mean(res_δ_OR6) .+ cov_αδ_cholf_OR6.L[2,1].*σ_cos_ang .+ cov_αδ_cholf_OR6.L[2,2].*σ_sin_ang\n", - "\n", - "ell_3σ_x_OR7 = mean(res_α_OR7) .+ cov_αδ_cholf_OR7.L[1,1].*σ_cos_ang .+ cov_αδ_cholf_OR7.L[1,2].*σ_sin_ang\n", - "ell_3σ_y_OR7 = mean(res_δ_OR7) .+ cov_αδ_cholf_OR7.L[2,1].*σ_cos_ang .+ cov_αδ_cholf_OR7.L[2,2].*σ_sin_ang\n", - ";" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "gap = 0.01\n", - "xlim_plt = 3.5\n", - "ymin_plt = -5.0\n", - "ymax_plt = 5.0\n", - "\n", - "Gaston.set(preamble=\"set grid; set style circle radius 0.02\")\n", - "\n", - "p1 = Gaston.plot(\n", - " bc_a,\n", - " h_a.weights./2, \n", - " supp=[bs_a./2 h_a.weights./2], \n", - " curveconf=\"w boxxy notit fs transparent solid 0.4\", \n", - " Axes(\n", - " #linetype = :tab10,\n", - " axesconf=\"set lmargin at screen 0.1; set rmargin at screen 0.85; set tmargin at screen 0.99; set bmargin at screen 0.8+$gap\",\n", - " xrange = (-xlim_plt, xlim_plt),\n", - " format = \"''\",\n", - " label=\"1 '(b)' at graph 0.05,0.8\"\n", - " ),\n", - " handle = 1\n", - ")\n", - "Gaston.plot!(\n", - " bc_c,\n", - " h_c.weights./2, \n", - " supp=[bs_c./2 h_c.weights./2], \n", - " curveconf=\"w boxxy notit fs transparent solid 0.4\"\n", - ")\n", - "\n", - "p2 = Gaston.plot(\n", - " res_α_OR6, \n", - " res_δ_OR6, \n", - " curveconf=\"w circles fill transparent solid 0.4 noborder tit 'gravity-only'\",\n", - " Axes(\n", - " #linetype = :tab10,\n", - " key=\"at screen 0.835, screen 0.78 box spacing 1.2 height 0.4\", #\"outside top right box spacing 1.2 height 1\",\n", - " axesconf=\"set lmargin at screen 0.1; set rmargin at screen 0.85; set tmargin at screen 0.8; set bmargin at screen 0.1\",\n", - " xrange = (-xlim_plt, xlim_plt),\n", - " yrange = (ymin_plt, ymax_plt),\n", - " format = \"\\\"%g\\\"\",\n", - " xlabel=\"'\\$\\\\alpha\\\\cos(\\\\delta)\\$ \\$[\\$arcsec\\$]\\$'\",\n", - " ylabel=\"'\\$\\\\delta\\$ \\$[\\$arcsec\\$]\\$'\",\n", - " label=\"1 '(a)' at graph 0.05,0.925\"\n", - " ), \n", - " handle = 2\n", - ")\n", - "Gaston.plot!(res_α_OR7, res_δ_OR7, \n", - " curveconf=\"w circles fill transparent solid 0.4 noborder tit 'non-grav.'\"\n", - ")\n", - "Gaston.plot!([mean(res_α_OR6)], [mean(res_δ_OR6)], curveconf=\"w p pt 4 ps 1.5 lw 8\") # tit 'mean R.A./Dec (OR6)'\n", - "Gaston.plot!([mean(res_α_OR7)], [mean(res_δ_OR7)], curveconf=\"w p pt 6 ps 1.5 lw 8\") # tit 'mean R.A./Dec (OR7)'\n", - "Gaston.plot!(ell_3σ_x_OR6, ell_3σ_y_OR6, curveconf=\"w l lw 8 lc 3\")\n", - "Gaston.plot!(ell_3σ_x_OR7, ell_3σ_y_OR7, curveconf=\"w l lw 8 lc 4\")\n", - "\n", - "p4 = Gaston.plot(\n", - " h_b.weights./2,\n", - " bc_b,\n", - " supp=[h_b.weights./2 bs_b./2],\n", - " curveconf=\"w boxxy notit fs transparent solid 0.4\",\n", - " Axes(\n", - " #linetype = :tab10,\n", - " axesconf=\"set lmargin at screen 0.85+$gap; set rmargin at screen 0.99; set tmargin at screen 0.8; set bmargin at screen 0.1\",\n", - " yrange = (ymin_plt, ymax_plt),\n", - " format = \"''\",\n", - " label=\"1 '(c)' at graph 0.15,0.925\"\n", - " ),\n", - " handle = 4\n", - ")\n", - "Gaston.plot!(\n", - " h_d.weights./2,\n", - " bc_d,\n", - " supp=[h_d.weights./2 bs_d./2],\n", - " curveconf=\"w boxxy notit fs transparent solid 0.4\"\n", - ")\n", - "\n", - "Gaston.plot([p1 nothing ; p2 p4])\n", - "\n", - "#Gaston.save(term = \"cairolatex\", output = \"radec_hist.tex\", saveopts = \"pdf standalone color dashed transparent size 7in,5in font ',12'\")\n", - "#run(`lualatex radec_hist.tex`)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Plots: radar astrometry post-fit residuals" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "del_index = findall(x->x.Δτ_units==\"us\", deldop)\n", - "dop_index = findall(x->x.Δν_units==\"Hz\", deldop)\n", - "length(del_index), length(dop_index)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "length(deldop)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "del_dates_plot_ = date.(deldop[del_index])\n", - "dop_dates_plot_ = date.(deldop[dop_index])\n", - "\n", - "del_dates_plot = Dates.format.(del_dates_plot_, \"dd/mm/yy HHMM\")\n", - "dop_dates_plot = Dates.format.(dop_dates_plot_, \"dd/mm/yy HHMM\")\n", - "\n", - "σ_del_all = delay_sigma.(deldop[del_index])\n", - "σ_dop_all = doppler_sigma.(deldop[dop_index])\n", - ";" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "p1 = Gaston.plot(\n", - " del_index,\n", - " res_τ(δx_OR6),\n", - " supp = σ_del_all,\n", - " key=\"box spacing 1.2 height 0.4\", #at screen 0.835, screen 0.78 \n", - " curveconf = \"u 1:2:3 w errorbars pt 6 lw 4 tit 'gravity-only'\",\n", - " Axes(\n", - " #axesconf=\"set lmargin at screen 0.15; set rmargin at screen 0.95; set bmargin at screen 0.5\",\n", - " axesconf=\"set lmargin at screen 0.11\",\n", - " #linetype = :tab10,\n", - " bars = 2,\n", - " ylabel = \"'Time-delay resid. \\$[\\$us\\$]\\$'\",\n", - " xrange = (0,39),\n", - " xtics = \"1,2,40\",\n", - " format = \"y '%1.1f'\",\n", - " yrange=(-7,8),\n", - " label=\"1 '(a)' at graph 0.05,0.9\"#,\n", - " #title = \"'gravity-only'\"\n", - " ),\n", - " handle = 1\n", - ")\n", - "Gaston.plot!(\n", - " del_index,\n", - " res_τ(δx_OR7),\n", - " supp = σ_del_all,\n", - " curveconf = \"u 1:2:3 w errorbars pt 4 lw 4 tit 'non-gravitational'\",\n", - " lc = 2\n", - ")\n", - "\n", - "p2 = Gaston.plot(\n", - " dop_index,\n", - " res_ν(δx_OR6),\n", - " supp = σ_dop_all,\n", - " curveconf = \"u 1:2:3 w errorbars pt 6 lw 4 tit 'gravity-only'\",\n", - " key=\"box spacing 1.2 height 0.4\",\n", - " Axes(\n", - " #axesconf=\"set lmargin at screen 0.15; set rmargin at screen 0.95; set tmargin at screen 0.5\",\n", - " axesconf=\"set lmargin at screen 0.11\",\n", - " #linetype = :tab10,\n", - " bars = 2,\n", - " ylabel = \"'Doppler shift resid. \\$[\\$Hz\\$]\\$'\",\n", - " xrange = (0,39),\n", - " xtics = \"1,2,40\",\n", - " format = \"y '%1.1f'\",\n", - " yrange=(-0.6,0.8),\n", - " label=\"1 '(b)' at graph 0.05,0.9\" #,\n", - " # title = \"'non-gravitational'\"\n", - " ),\n", - " handle = 2\n", - ")\n", - "Gaston.plot!(\n", - " dop_index,\n", - " res_ν(δx_OR7),\n", - " supp = σ_dop_all,\n", - " curveconf = \"u 1:2:3 w errorbars pt 4 lw 4 tit 'non-gravitational'\",\n", - " lc = 2\n", - ")\n", - "\n", - "\n", - "Gaston.plot([p1; p2])\n", - "\n", - "#Gaston.save(term = \"cairolatex\", output = \"deldop_residuals.tex\", saveopts = \"pdf standalone color dashed transparent size 10in,7in font ',14'\")\n", - "#run(`pdflatex deldop_residuals.tex`)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "deldop_dates_plot_xaxis = vcat(\"01/06/04 0000\", del_dates_plot, \"31/03/21 2359\");" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "tmargin_bmargin_gap = 0.03\n", - "bmargin_ths_plt = 0.5 + tmargin_bmargin_gap\n", - "tmargin_ths_plt = 0.965\n", - "axsbrk_v = 1.25*0.01\n", - "axsbrk_h = 1.25*0.005\n", - "lw_ths_plt = 3\n", - "rmargin_ths_plt = 0.3\n", - "\n", - "p1 = Gaston.plot(\n", - " del_dates_plot,\n", - " res_τ(δx_OR6),\n", - " supp = σ_del_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", - " Axes(\n", - " #linetype = :tab10,\n", - " axesconf = \"set rmargin at screen 0.3; set tmargin at screen $tmargin_ths_plt; set bmargin at screen $bmargin_ths_plt\",\n", - " xdata = \"time\",\n", - " timefmt = \"'%d/%m/%y %H%M'\",\n", - " xtics = false, #\"format '' time (\\\"01/01/05\\\",\\\"01/01/06\\\")\", # '%d/%b/%y'\n", - " xrange = \"[\\\"01/12/04\\\":\\\"30/05/06\\\"]\",\n", - " #xlabel = \"\\\"Date\\\"\",\n", - " bars = false, #2,\n", - " ylabel = \"'Time-delay resid. (O-C) [\\$\\\\mu\\$s]'\",\n", - " border = \"1+2+4\",\n", - " ytics = [\"nomirror\", \"format '%1.1f'\"],\n", - " yrange = \"[-8.0:6.0]\",\n", - " arrow = [\n", - " \"from screen 0.3-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.3+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.3-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.3+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\"\n", - " ],\n", - " label=\"1 '(a)' at graph 0.2,0.9\",\n", - " grid=false\n", - " #arrow = \"from screen 0.3-0.01,1.0-0.01 to screen 0.3+0.01,1.0+0.01 nohead\"\n", - " #format = \"x ''\"\n", - " #title = \"'Time-delay resid. (O-C)'\"\n", - " ),\n", - " handle = 1\n", - ")\n", - "Gaston.plot!(\n", - " del_dates_plot,\n", - " res_τ(δx_OR7),\n", - " supp = σ_del_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", - " lc = 2\n", - ")\n", - "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", - "\n", - "p2 = Gaston.plot(\n", - " del_dates_plot,\n", - " res_τ(δx_OR6),\n", - " supp = σ_del_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", - " Axes(\n", - " #linetype = :tab10,\n", - " xdata = \"time\",\n", - " timefmt = \"'%d/%m/%y %H%M'\",\n", - " axesconf = \"set lmargin at screen 0.35; set tmargin at screen $tmargin_ths_plt; set rmargin at screen 0.8; set bmargin at screen $bmargin_ths_plt\",\n", - " xtics = false, #\"format '' time (\\\"01/01/13\\\",\\\"01/02/13\\\",\\\"01/03/13\\\")\", # '%d/%b/%y'\n", - " xrange = \"[\\\"15/12/12\\\":\\\"20/03/13\\\"]\",\n", - " #xlabel = \"\\\"Date\\\"\",\n", - " bars = false, #2,\n", - " #tics=\"scale 0\",\n", - " ytics = false, #[false, \"(\\\"\\\" 0)\"], #\"nomirror\",\n", - " border = \"1+4\",\n", - " yrange = \"[-8.0:6.0]\",\n", - " format = [\"x ''\", \"y ''\"], #%1.1f\n", - " arrow = [\n", - " \"from screen 0.35-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.35+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.35-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.35+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.80-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.80+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.80-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.80+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\"\n", - " ],\n", - " #ylabel = \"'[us]'\"\n", - " ),\n", - " handle = 2\n", - ")\n", - "Gaston.plot!(\n", - " del_dates_plot,\n", - " res_τ(δx_OR7),\n", - " supp = σ_del_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", - " lc = 2\n", - ")\n", - "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", - "\n", - "p3 = Gaston.plot(\n", - " del_dates_plot,\n", - " res_τ(δx_OR6),\n", - " supp = σ_del_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", - " Axes(\n", - " #linetype = :tab10,\n", - " xdata = \"time\",\n", - " timefmt = \"'%d/%m/%y %H%M'\",\n", - " axesconf = \"set lmargin at screen 0.85; set tmargin at screen 0.965; set bmargin at screen $bmargin_ths_plt\",\n", - " xtics = false, #\"format '' time (\\\"03/03/21\\\",\\\"11/03/21\\\")\", #'%d/%b/%y'\n", - " xrange = \"[\\\"02/03/21\\\":\\\"15/03/21\\\"]\",\n", - " #xlabel = \"\\\"Date\\\"\",\n", - " bars = false, #2,\n", - " #tics=\"scale 0\",\n", - " ytics = false, #[false, \"(\\\"\\\" 0)\"], #\"nomirror\",\n", - " border = \"1+4+8\",\n", - " yrange = \"[-8.0:6.0]\",\n", - " format = [\"x ''\", \"y ''\"], #%1.1f\n", - " arrow = [\n", - " \"from screen 0.85-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.85+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.85-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.85+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\"\n", - " ],\n", - " #ylabel = \"'[us]'\"\n", - " ),\n", - " handle = 3\n", - ")\n", - "Gaston.plot!(\n", - " del_dates_plot,\n", - " res_τ(δx_OR7),\n", - " supp = σ_del_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", - " lc = 2\n", - ")\n", - "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", - "\n", - "Gaston.plot([p1 p2 p3])\n", - "\n", - "#Gaston.save(term = \"cairolatex\", output = \"del_resids.tex\", saveopts = \"pdf standalone color dashed transparent size 10in,7in font ',14'\")\n", - "#run(`pdflatex del_resids.tex`)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "jupyter": { - "source_hidden": true - } - }, - "outputs": [], - "source": [ - "tmargin_ths_plt = 0.5 - tmargin_bmargin_gap\n", - "bmargin_ths_plt = 0.05\n", - "\n", - "Gaston.set(preamble=\"unset grid\")\n", - "p4 = Gaston.plot(\n", - " dop_dates_plot,\n", - " res_ν(δx_OR6),\n", - " supp = σ_dop_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", - " Axes(\n", - " #linetype = :tab10,\n", - " axesconf=\"set rmargin at screen $rmargin_ths_plt; set tmargin at screen $tmargin_ths_plt; set bmargin at screen $bmargin_ths_plt\",\n", - " xdata = \"time\",\n", - " timefmt = \"'%d/%m/%y %H%M'\",\n", - " xtics = \"format '%d/%b/%y' time (\\\"01/01/05\\\",\\\"01/01/06\\\")\",\n", - " xrange = \"[\\\"01/12/04\\\":\\\"30/05/06\\\"]\",\n", - " #xlabel = \"\\\"Date\\\"\",\n", - " bars = false,#2,\n", - " ylabel = \"'Doppler shift resid. (O-C) [Hz]'\",\n", - " border=\"1+2+4\",\n", - " ytics = [\"nomirror\", \"format '%1.1f'\"],\n", - " yrange=\"[-0.5:0.5]\",\n", - " arrow = [\n", - " \"from screen 0.3-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.3+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.3-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.3+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\"\n", - " ],\n", - " label=\"1 '(b)' at graph 0.2,0.9\"\n", - " #title = \"'Doppler shift resid. (O-C)'\"\n", - " ),\n", - " handle = 4\n", - ")\n", - "Gaston.plot!(\n", - " dop_dates_plot,\n", - " res_ν(δx_OR7),\n", - " supp = σ_dop_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", - " lc = 2\n", - ")\n", - "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", - "\n", - "p5 = Gaston.plot(\n", - " dop_dates_plot,\n", - " res_ν(δx_OR6),\n", - " supp = σ_dop_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", - " Axes(\n", - " #linetype = :tab10,\n", - " xdata = \"time\",\n", - " timefmt = \"'%d/%m/%y %H%M'\",\n", - " axesconf=\"set lmargin at screen $rmargin_ths_plt+0.05; set rmargin at screen 0.8; set tmargin at screen $tmargin_ths_plt; set bmargin at screen $bmargin_ths_plt\",\n", - " xtics=\"format '%d/%b/%y' time (\\\"01/01/13\\\",\\\"01/02/13\\\",\\\"01/03/13\\\")\",\n", - " xrange=\"[\\\"15/12/12\\\":\\\"20/03/13\\\"]\",\n", - " #xlabel = \"\\\"Date\\\"\",\n", - " bars = false, #2,\n", - " ytics=false,\n", - " border=\"1+4\",\n", - " yrange=\"[-0.5:0.5]\",\n", - " arrow = [\n", - " \"from screen 0.35-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.35+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.35-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.35+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.8-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.8+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.8-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.8+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\"\n", - " ],\n", - " #ylabel = \"'[Hz]'\"\n", - " ),\n", - " handle = 5\n", - ")\n", - "Gaston.plot!(\n", - " dop_dates_plot,\n", - " res_ν(δx_OR7),\n", - " supp = σ_dop_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", - " lc = 2\n", - ")\n", - "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", - "\n", - "p6 = Gaston.plot(\n", - " dop_dates_plot,\n", - " res_ν(δx_OR6),\n", - " supp = σ_dop_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", - " Axes(\n", - " #linetype = :tab10,\n", - " xdata = \"time\",\n", - " timefmt = \"'%d/%m/%y %H%M'\",\n", - " axesconf=\"set lmargin at screen 0.85; set tmargin at screen $tmargin_ths_plt; set bmargin at screen $bmargin_ths_plt\",\n", - " xtics=\"format '%d/%b/%y' time (\\\"03/03/21\\\",\\\"13/03/21\\\")\",\n", - " xrange=\"[\\\"02/03/21\\\":\\\"15/03/21\\\"]\",\n", - " #xlabel = \"\\\"Date\\\"\",\n", - " bars = false, #2,\n", - " #format=\"y ''\",\n", - " ytics=false,\n", - " border=\"1+4+8\",\n", - " yrange=\"[-0.5:0.5]\",\n", - " arrow = [\n", - " \"from screen 0.85-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.85+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", - " \"from screen 0.85-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.85+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\"\n", - " ],\n", - " #ylabel = \"'[Hz]'\"\n", - " ),\n", - " handle = 6\n", - ")\n", - "Gaston.plot!(\n", - " dop_dates_plot,\n", - " res_ν(δx_OR7),\n", - " supp = σ_dop_all,\n", - " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", - " lc = 2\n", - ")\n", - "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", - "\n", - "Gaston.plot([p4 p5 p6])\n", - "\n", - "#Gaston.save(term = \"cairolatex\", output = \"dop_resids.tex\", saveopts = \"pdf standalone color dashed transparent size 10in,7in font ',14'\")\n", - "#run(`pdflatex dop_resids.tex`)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Gaston.plot([p1 p2 p3; p4 p5 p6])\n", - "\n", - "#Gaston.save(term = \"cairolatex\", output = \"deldop_residuals_dates.tex\", saveopts = \"pdf standalone color dashed transparent size 10in,7in font ',14'\")\n", - "#run(`lualatex deldop_residuals_dates.tex`)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Julia-4-threads 1.9.1", - "language": "julia", - "name": "julia-4-threads-1.9" - }, - "language_info": { - "file_extension": ".jl", - "mimetype": "application/julia", - "name": "julia", - "version": "1.9.2" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "import Pkg\n", + "Pkg.activate(\"../pha\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "using Revise" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "using NEOs\n", + "using DataFrames\n", + "using TaylorIntegration\n", + "using PlanetaryEphemeris\n", + "using JLD2\n", + "using Statistics\n", + "using LinearAlgebra\n", + "using Dates\n", + "using StatsBase\n", + "using Gaston\n", + "using DelimitedFiles" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dq = set_variables(\"δx\", order=5, numvars=7)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load Sun, Earth and Apophis ephemeris" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sol_bwd = JLD2.load(\"Apophis_bwd.jld2\", \"asteph\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sol_fwd = JLD2.load(\"Apophis_fwd.jld2\", \"asteph\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sseph::TaylorInterpolant{Float64,Float64,2} = loadpeeph(NEOs.sseph, sol_bwd.t0+sol_bwd.t[end], sol_fwd.t0+sol_fwd.t[end])\n", + "eph_su::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, su)\n", + "eph_ea::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, ea)\n", + "\n", + "# NEO\n", + "# Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec\n", + "xva_bwd(et) = auday2kmsec(sol_bwd(et/daysec)[1:6])\n", + "xva_fwd(et) = auday2kmsec(sol_fwd(et/daysec)[1:6])\n", + "xva(et) = bwdfwdeph(et, sol_bwd, sol_fwd)\n", + "# Earth\n", + "# Change x, v units, resp., from au, au/day to km, km/sec\n", + "xve(et) = auday2kmsec(eph_ea(et/daysec))\n", + "# Sun\n", + "# Change x, v units, resp., from au, au/day to km, km/sec\n", + "xvs(et) = auday2kmsec(eph_su(et/daysec))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# get optical observations\n", + "radec_2004_2020 = read_radec_mpc(joinpath(pkgdir(NEOs), \"data\", \"99942_2004_2020.dat\"))\n", + "radec_2020_2021 = read_radec_mpc(joinpath(pkgdir(NEOs), \"data\", \"99942_2020_2021.dat\"))\n", + "radec = vcat(radec_2004_2020,radec_2020_2021)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# get radar observations\n", + "deldop_2005_2013 = read_radar_jpl(joinpath(pkgdir(NEOs), \"data\", \"99942_RADAR_2005_2013.dat\"))\n", + "deldop_2021 = read_radar_jpl(joinpath(pkgdir(NEOs), \"data\", \"99942_RADAR_2021.dat\"))\n", + "deldop = vcat(deldop_2005_2013,deldop_2021)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# Compute optical residuals\n", + "@time res_radec_all, w_radec_all = NEOs.residuals(radec; xvs, xve, xva);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Compute radar residuals\n", + "@time res_del, w_del, res_dop, w_dop = NEOs.residuals(deldop; xvs, xve, xva, niter=10, tord=10);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Process optical data (filter, weight, debias)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# filter out biased observations from observatory 217 on 28-Jan-2021\n", + "df_radec = DataFrame(radec)\n", + "# add residuals and weights to optical astrometry DataFrame\n", + "df_radec[!, :res_α] .= res_radec_all[1:round(Int,length(res_radec_all)/2)]\n", + "df_radec[!, :res_δ] .= res_radec_all[1+round(Int,length(res_radec_all)/2):end]\n", + "df_radec[!, :w_α] .= w_radec_all[1:round(Int,length(res_radec_all)/2)]\n", + "df_radec[!, :w_δ] .= w_radec_all[1+round(Int,length(res_radec_all)/2):end]\n", + "filter!(\n", + " x->(Date(x.date) != Date(2021, 1, 28)),\n", + " df_radec\n", + ")\n", + "\n", + "# read astrometric errors from Tholen et al. (2013)\n", + "tho13_errors = readdlm(joinpath(pkgdir(NEOs), \"data\", \"tholenetal2013_opterror.dat\"), ',')\n", + "# compute weights\n", + "w_α_tho13 = 1 ./ (tho13_errors[:,1].^2 .+ tho13_errors[:,3].^2 .+ tho13_errors[:,5].^2)\n", + "w_δ_tho13 = 1 ./ (tho13_errors[:,2].^2 .+ tho13_errors[:,4].^2 .+ tho13_errors[:,6].^2)\n", + "# Tholen et al. (2013) obs table\n", + "radec_tho13 = DataFrame(read_radec_mpc(joinpath(pkgdir(NEOs), \"test\", \"data\", \"99942_Tholen_etal_2013.dat\")))\n", + "# vector of RA values from Tholen et al. (2013) observations (used for filtering)\n", + "tho13_α = radec_tho13[!,:α]\n", + "# set weights in Tholen et al. (2013) astrometry corresponding to associated uncertainties\n", + "df_radec[in.(df_radec.α, Ref(tho13_α)),:w_α] = w_α_tho13\n", + "df_radec[in.(df_radec.α, Ref(tho13_α)),:w_δ] = w_δ_tho13\n", + "\n", + "# Relaxation factor (account for correlations in optical astrometry data)\n", + "# for each observation batch, count the number of observations made in\n", + "# the same night by the same observatory\n", + "# Ref: Veres et al. (2017)\n", + "date_site_v = select(df_radec, :date => ByRow(Date), :observatory)\n", + "Nv = [count(x->x.date_Date==i.date_Date && x.observatory==i.observatory, eachrow(date_site_v)) for i in eachrow(date_site_v)]\n", + "relax_factor = map(x->x>4.0 ? x/4.0 : 1.0, Nv)\n", + "# inflate uncertainties (i.e., relax weights) by relaxation factor\n", + "df_radec[!, :w_α] .= (df_radec.w_α)./relax_factor\n", + "df_radec[!, :w_δ] .= (df_radec.w_δ)./relax_factor\n", + "\n", + "# update optical residuals and weights\n", + "res_radec = vcat(df_radec.res_α, df_radec.res_δ)\n", + "w_radec = vcat(df_radec.w_α, df_radec.w_δ)\n", + ";" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# check if all RA/Dec observations are CCD:\n", + "\n", + "all(\n", + " select(\n", + " df_radec, \n", + " :obstech => ByRow(x->x == \"C\" || x == \"X\")\n", + " )[!,1]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# there are 512 RA/Dec obs without catalog info\n", + "\n", + "length(df_radec[isunknown.(df_radec.catalogue),:catalogue])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Construct vector of residuals and weights\n", + "\n", + "res = vcat(res_radec, res_del, res_dop)\n", + "w = vcat(w_radec, w_del, w_dop)\n", + ";" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "### Perform 7-DOF orbital fit to optical and radar astrometry data\n", + "\n", + "@show success, δx_OR7, Γ_OR7 = newtonls(res, w, zeros(get_numvars()), 10)\n", + "x_OR7 = sol_fwd(sol_fwd.t0)(δx_OR7);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "### Perform 6-DOF orbital fit (i.e., without Yarkovsky effect) to optical and radar astrometry data\n", + "\n", + "δx_OR6, Γ_OR6 = newtonls_6v(res, w, zeros(get_numvars()), 10)\n", + "x_OR6 = sol_fwd(sol_fwd.t0)(δx_OR6);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "### Print results\n", + "\n", + "# orbital fit\n", + "@show success\n", + "@show x_OR7 # cartesian state vector at solution reference epoch\n", + "@show sqrt.(diag(Γ_OR7)).*vcat(1e-8ones(6),1e-14) # uncertainties at solution reference epoch (1-sigma)\n", + ";" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Fit quality statistics: $\\chi^2$, normalized RMS" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The results below correspond to Table 1 of Pérez-Hernández and Benet (2022)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# post-fit statistics\n", + "\n", + "nradec = length(res_radec)\n", + "res_α = view(res_radec, 1:nradec÷2)\n", + "res_δ = view(res_radec, 1+nradec÷2:nradec)\n", + "res_τ = res_del\n", + "res_ν = res_dop\n", + "w_α = view(w_radec, 1:nradec÷2)\n", + "w_δ = view(w_radec, 1+nradec÷2:nradec)\n", + "res_α_OR6 = res_α(δx_OR6)\n", + "res_δ_OR6 = res_δ(δx_OR6)\n", + "res_α_OR7 = res_α(δx_OR7)\n", + "res_δ_OR7 = res_δ(δx_OR7)\n", + "\n", + "@show nrms_radec = nrms(res_radec(δx_OR7),w_radec)\n", + "@show nrms_radec = nrms(vcat(res_del,res_dop)(δx_OR7),vcat(w_del,w_dop))\n", + "@show nrms_optrad = nrms(res(δx_OR7),w)\n", + "@show mean_ra = mean(res_ra(δx_OR7), weights(w_ra))\n", + "@show mean_dec = mean(res_dec(δx_OR7), weights(w_dec))\n", + "@show mean_del = mean(res_del(δx_OR7), weights(w_del))\n", + "@show mean_dop = mean(res_dop(δx_OR7), weights(w_dop))\n", + "@show chi2_optrad = chi2(res(δx_OR7),w)\n", + ";" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Semimajor axis drift" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "jd0 = J2000 + sol_fwd.t0 #Julian date (TDB) of integration initial time\n", + "et0 = (jd0 - J2000)*daysec" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Apophis heliocentric position and velocity at solution reference epoch (plus autodiff perturbations)\n", + "xas = sol_fwd(sol_fwd.t0)[1:6] .- eph_su(jd0-J2000)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Orbital elements of new solution (ecliptic frame at J2000.0 epoch)\n", + "pv2kep(xas(δx_OR7), jd=jd0, frame=:ecliptic)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# JPL solution #216 for Apophis\n", + "kep_JPL216 = [\n", + " 0.1914347568286823, \n", + " 0.7460634895090179, \n", + " 2459424.558511739019, \n", + " 203.9662692226386, \n", + " 126.5900238507279, \n", + " 3.338874353538208, \n", + " -2.901085583204654E-14, \n", + " 5.E-13\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "kep_JT = pv2kep(xas, jd=jd0, frame=:ecliptic) # Orbital elements of JT solution at ref. epoch\n", + "kep_OR7 = pv2kep(xas(δx_OR7), jd=jd0, frame=:ecliptic) # Orbital elements of new solution at ref. epoch" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# Jacobian of transformation: cartesian state -> Keplerian elements\n", + "t_car2kep(x) = hcat(\n", + " TaylorSeries.gradient(kep_JT.e), \n", + " TaylorSeries.gradient(kep_JT.q),\n", + " TaylorSeries.gradient(kep_JT.tp),\n", + " TaylorSeries.gradient(kep_JT.Ω),\n", + " TaylorSeries.gradient(kep_JT.ω),\n", + " TaylorSeries.gradient(kep_JT.i),\n", + " TaylorSeries.gradient(kep_JT.M),\n", + " TaylorSeries.gradient(kep_JT.a),\n", + " )(x)\n", + "\n", + "# semimajor axis drift \\dot{a} due to Yarkovsky effect in units of au per day, as a function of initial condition\n", + "ady_kep = yarkp2adot(sol_fwd(sol_fwd.t0)[7], kep_JT.a, kep_JT.e)\n", + "\n", + "# semimajor axis drift, au per million years\n", + "ady_kep_au_My = 1e6yr*ady_kep\n", + "\n", + "# semimajor axis drift, meters per year\n", + "ady_kep_m_y = 1e3au*yr*ady_kep\n", + "\n", + "# Jacobian of transformation: cartesian state -> semimajor axis drift in au per million years\n", + "t_kep2ady_au_My(x) = TaylorSeries.gradient(ady_kep_au_My)(x)\n", + "\n", + "# Jacobian of transformation: cartesian state -> semimajor axis drift in meters per year\n", + "t_kep2ady_m_y(x) = TaylorSeries.gradient(ady_kep_m_y)(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# mean semimajor axis drift, au per million years\n", + "ady_kep_au_My_OR7 = ady_kep_au_My(δx_OR7) # au/Myr" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# mean semimajor axis drift, meters per year\n", + "ady_kep_m_y_OR7 = 1e3au*yr*ady_kep(δx_OR7) # m/yr" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# uncertainty in semimajor axis drift, au per million years\n", + "sqrt( t_kep2ady_m_y(δx_OR7)'*Γ*t_kep2ady_m_y(δx_OR7) )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# uncertainty in semimajor axis drift, au per million years\n", + "sqrt( t_kep2ady_au_My(δx_OR7)'*Γ*t_kep2ady_au_My(δx_OR7) )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# covariance matrix of Keplerian elements\n", + "Γ_kep = t_car2kep(δx_OR7)'*Γ*t_car2kep(δx_OR7)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#formal uncertainties in Keplerian elements (1-sigma)\n", + "\n", + "sqrt.(diag(Γ_kep))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plots: optical astrometry post-fit residuals" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#bins_hist = -2.0:0.1:2.0\n", + "nbins_plot = 100\n", + "\n", + "#h_a = fit(Histogram, res_α_OR6, bins_hist)\n", + "h_a = fit(Histogram, res_α_OR6, nbins=nbins_plot)\n", + "bc_a = midpoints(h_a.edges[1]) # bin centers\n", + "bs_a = fill(h_a.edges[1].step.hi, length(bc_a)) # bin sizes\n", + ";\n", + "\n", + "#h_b = fit(Histogram, res_δ_OR6, bins_hist)\n", + "h_b = fit(Histogram, res_δ_OR6, nbins=nbins_plot)\n", + "bc_b = midpoints(h_b.edges[1]) # bin centers\n", + "bs_b = fill(h_b.edges[1].step.hi, length(bc_b)) # bin sizes\n", + "\n", + "#h_c = fit(Histogram, res_α_OR7, bins_hist)\n", + "h_c = fit(Histogram, res_α_OR7, nbins=nbins_plot)\n", + "bc_c = midpoints(h_c.edges[1]) # bin centers\n", + "bs_c = fill(h_c.edges[1].step.hi, length(bc_c)) # bin sizes\n", + "\n", + "#h_d = fit(Histogram, res_δ_OR7, bins_hist)\n", + "h_d = fit(Histogram, res_δ_OR7, nbins=nbins_plot)\n", + "bc_d = midpoints(h_d.edges[1]) # bin centers\n", + "bs_d = fill(h_d.edges[1].step.hi, length(bc_d)) # bin sizes\n", + ";" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "minimum(res_α_OR6), maximum(res_α_OR6)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "minimum(res_δ_OR6), maximum(res_δ_OR6)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "minimum(res_α_OR7), maximum(res_α_OR7)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "minimum(res_δ_OR7), maximum(res_δ_OR7)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mean(res_α_OR6), mean(res_δ_OR6)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mean(res_α_OR7), mean(res_δ_OR7)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "angv = vcat(range(0, length=1000, stop=prevfloat(2pi)), 0)\n", + "sigma_factor = 3.0\n", + "σ_cos_ang = sigma_factor*cos.(angv)\n", + "σ_sin_ang = sigma_factor*sin.(angv)\n", + "\n", + "cov_αδ_cholf_OR6 = cholesky(cov(hcat(res_α_OR6, res_δ_OR6)))\n", + "cov_αδ_cholf_OR7 = cholesky(cov(hcat(res_α_OR7, res_δ_OR7)))\n", + "\n", + "ell_3σ_x_OR6 = mean(res_α_OR6) .+ cov_αδ_cholf_OR6.L[1,1].*σ_cos_ang .+ cov_αδ_cholf_OR6.L[1,2].*σ_sin_ang\n", + "ell_3σ_y_OR6 = mean(res_δ_OR6) .+ cov_αδ_cholf_OR6.L[2,1].*σ_cos_ang .+ cov_αδ_cholf_OR6.L[2,2].*σ_sin_ang\n", + "\n", + "ell_3σ_x_OR7 = mean(res_α_OR7) .+ cov_αδ_cholf_OR7.L[1,1].*σ_cos_ang .+ cov_αδ_cholf_OR7.L[1,2].*σ_sin_ang\n", + "ell_3σ_y_OR7 = mean(res_δ_OR7) .+ cov_αδ_cholf_OR7.L[2,1].*σ_cos_ang .+ cov_αδ_cholf_OR7.L[2,2].*σ_sin_ang\n", + ";" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gap = 0.01\n", + "xlim_plt = 3.5\n", + "ymin_plt = -5.0\n", + "ymax_plt = 5.0\n", + "\n", + "Gaston.set(preamble=\"set grid; set style circle radius 0.02\")\n", + "\n", + "p1 = Gaston.plot(\n", + " bc_a,\n", + " h_a.weights./2, \n", + " supp=[bs_a./2 h_a.weights./2], \n", + " curveconf=\"w boxxy notit fs transparent solid 0.4\", \n", + " Axes(\n", + " #linetype = :tab10,\n", + " axesconf=\"set lmargin at screen 0.1; set rmargin at screen 0.85; set tmargin at screen 0.99; set bmargin at screen 0.8+$gap\",\n", + " xrange = (-xlim_plt, xlim_plt),\n", + " format = \"''\",\n", + " label=\"1 '(b)' at graph 0.05,0.8\"\n", + " ),\n", + " handle = 1\n", + ")\n", + "Gaston.plot!(\n", + " bc_c,\n", + " h_c.weights./2, \n", + " supp=[bs_c./2 h_c.weights./2], \n", + " curveconf=\"w boxxy notit fs transparent solid 0.4\"\n", + ")\n", + "\n", + "p2 = Gaston.plot(\n", + " res_α_OR6, \n", + " res_δ_OR6, \n", + " curveconf=\"w circles fill transparent solid 0.4 noborder tit 'gravity-only'\",\n", + " Axes(\n", + " #linetype = :tab10,\n", + " key=\"at screen 0.835, screen 0.78 box spacing 1.2 height 0.4\", #\"outside top right box spacing 1.2 height 1\",\n", + " axesconf=\"set lmargin at screen 0.1; set rmargin at screen 0.85; set tmargin at screen 0.8; set bmargin at screen 0.1\",\n", + " xrange = (-xlim_plt, xlim_plt),\n", + " yrange = (ymin_plt, ymax_plt),\n", + " format = \"\\\"%g\\\"\",\n", + " xlabel=\"'\\$\\\\alpha\\\\cos(\\\\delta)\\$ \\$[\\$arcsec\\$]\\$'\",\n", + " ylabel=\"'\\$\\\\delta\\$ \\$[\\$arcsec\\$]\\$'\",\n", + " label=\"1 '(a)' at graph 0.05,0.925\"\n", + " ), \n", + " handle = 2\n", + ")\n", + "Gaston.plot!(res_α_OR7, res_δ_OR7, \n", + " curveconf=\"w circles fill transparent solid 0.4 noborder tit 'non-grav.'\"\n", + ")\n", + "Gaston.plot!([mean(res_α_OR6)], [mean(res_δ_OR6)], curveconf=\"w p pt 4 ps 1.5 lw 8\") # tit 'mean R.A./Dec (OR6)'\n", + "Gaston.plot!([mean(res_α_OR7)], [mean(res_δ_OR7)], curveconf=\"w p pt 6 ps 1.5 lw 8\") # tit 'mean R.A./Dec (OR7)'\n", + "Gaston.plot!(ell_3σ_x_OR6, ell_3σ_y_OR6, curveconf=\"w l lw 8 lc 3\")\n", + "Gaston.plot!(ell_3σ_x_OR7, ell_3σ_y_OR7, curveconf=\"w l lw 8 lc 4\")\n", + "\n", + "p4 = Gaston.plot(\n", + " h_b.weights./2,\n", + " bc_b,\n", + " supp=[h_b.weights./2 bs_b./2],\n", + " curveconf=\"w boxxy notit fs transparent solid 0.4\",\n", + " Axes(\n", + " #linetype = :tab10,\n", + " axesconf=\"set lmargin at screen 0.85+$gap; set rmargin at screen 0.99; set tmargin at screen 0.8; set bmargin at screen 0.1\",\n", + " yrange = (ymin_plt, ymax_plt),\n", + " format = \"''\",\n", + " label=\"1 '(c)' at graph 0.15,0.925\"\n", + " ),\n", + " handle = 4\n", + ")\n", + "Gaston.plot!(\n", + " h_d.weights./2,\n", + " bc_d,\n", + " supp=[h_d.weights./2 bs_d./2],\n", + " curveconf=\"w boxxy notit fs transparent solid 0.4\"\n", + ")\n", + "\n", + "Gaston.plot([p1 nothing ; p2 p4])\n", + "\n", + "#Gaston.save(term = \"cairolatex\", output = \"radec_hist.tex\", saveopts = \"pdf standalone color dashed transparent size 7in,5in font ',12'\")\n", + "#run(`lualatex radec_hist.tex`)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plots: radar astrometry post-fit residuals" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "del_index = findall(x->x.Δτ_units==\"us\", deldop)\n", + "dop_index = findall(x->x.Δν_units==\"Hz\", deldop)\n", + "length(del_index), length(dop_index)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "length(deldop)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "del_dates_plot_ = date.(deldop[del_index])\n", + "dop_dates_plot_ = date.(deldop[dop_index])\n", + "\n", + "del_dates_plot = Dates.format.(del_dates_plot_, \"dd/mm/yy HHMM\")\n", + "dop_dates_plot = Dates.format.(dop_dates_plot_, \"dd/mm/yy HHMM\")\n", + "\n", + "σ_del_all = delay_sigma.(deldop[del_index])\n", + "σ_dop_all = doppler_sigma.(deldop[dop_index])\n", + ";" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "p1 = Gaston.plot(\n", + " del_index,\n", + " res_τ(δx_OR6),\n", + " supp = σ_del_all,\n", + " key=\"box spacing 1.2 height 0.4\", #at screen 0.835, screen 0.78 \n", + " curveconf = \"u 1:2:3 w errorbars pt 6 lw 4 tit 'gravity-only'\",\n", + " Axes(\n", + " #axesconf=\"set lmargin at screen 0.15; set rmargin at screen 0.95; set bmargin at screen 0.5\",\n", + " axesconf=\"set lmargin at screen 0.11\",\n", + " #linetype = :tab10,\n", + " bars = 2,\n", + " ylabel = \"'Time-delay resid. \\$[\\$us\\$]\\$'\",\n", + " xrange = (0,39),\n", + " xtics = \"1,2,40\",\n", + " format = \"y '%1.1f'\",\n", + " yrange=(-7,8),\n", + " label=\"1 '(a)' at graph 0.05,0.9\"#,\n", + " #title = \"'gravity-only'\"\n", + " ),\n", + " handle = 1\n", + ")\n", + "Gaston.plot!(\n", + " del_index,\n", + " res_τ(δx_OR7),\n", + " supp = σ_del_all,\n", + " curveconf = \"u 1:2:3 w errorbars pt 4 lw 4 tit 'non-gravitational'\",\n", + " lc = 2\n", + ")\n", + "\n", + "p2 = Gaston.plot(\n", + " dop_index,\n", + " res_ν(δx_OR6),\n", + " supp = σ_dop_all,\n", + " curveconf = \"u 1:2:3 w errorbars pt 6 lw 4 tit 'gravity-only'\",\n", + " key=\"box spacing 1.2 height 0.4\",\n", + " Axes(\n", + " #axesconf=\"set lmargin at screen 0.15; set rmargin at screen 0.95; set tmargin at screen 0.5\",\n", + " axesconf=\"set lmargin at screen 0.11\",\n", + " #linetype = :tab10,\n", + " bars = 2,\n", + " ylabel = \"'Doppler shift resid. \\$[\\$Hz\\$]\\$'\",\n", + " xrange = (0,39),\n", + " xtics = \"1,2,40\",\n", + " format = \"y '%1.1f'\",\n", + " yrange=(-0.6,0.8),\n", + " label=\"1 '(b)' at graph 0.05,0.9\" #,\n", + " # title = \"'non-gravitational'\"\n", + " ),\n", + " handle = 2\n", + ")\n", + "Gaston.plot!(\n", + " dop_index,\n", + " res_ν(δx_OR7),\n", + " supp = σ_dop_all,\n", + " curveconf = \"u 1:2:3 w errorbars pt 4 lw 4 tit 'non-gravitational'\",\n", + " lc = 2\n", + ")\n", + "\n", + "\n", + "Gaston.plot([p1; p2])\n", + "\n", + "#Gaston.save(term = \"cairolatex\", output = \"deldop_residuals.tex\", saveopts = \"pdf standalone color dashed transparent size 10in,7in font ',14'\")\n", + "#run(`pdflatex deldop_residuals.tex`)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "deldop_dates_plot_xaxis = vcat(\"01/06/04 0000\", del_dates_plot, \"31/03/21 2359\");" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "tmargin_bmargin_gap = 0.03\n", + "bmargin_ths_plt = 0.5 + tmargin_bmargin_gap\n", + "tmargin_ths_plt = 0.965\n", + "axsbrk_v = 1.25*0.01\n", + "axsbrk_h = 1.25*0.005\n", + "lw_ths_plt = 3\n", + "rmargin_ths_plt = 0.3\n", + "\n", + "p1 = Gaston.plot(\n", + " del_dates_plot,\n", + " res_τ(δx_OR6),\n", + " supp = σ_del_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", + " Axes(\n", + " #linetype = :tab10,\n", + " axesconf = \"set rmargin at screen 0.3; set tmargin at screen $tmargin_ths_plt; set bmargin at screen $bmargin_ths_plt\",\n", + " xdata = \"time\",\n", + " timefmt = \"'%d/%m/%y %H%M'\",\n", + " xtics = false, #\"format '' time (\\\"01/01/05\\\",\\\"01/01/06\\\")\", # '%d/%b/%y'\n", + " xrange = \"[\\\"01/12/04\\\":\\\"30/05/06\\\"]\",\n", + " #xlabel = \"\\\"Date\\\"\",\n", + " bars = false, #2,\n", + " ylabel = \"'Time-delay resid. (O-C) [\\$\\\\mu\\$s]'\",\n", + " border = \"1+2+4\",\n", + " ytics = [\"nomirror\", \"format '%1.1f'\"],\n", + " yrange = \"[-8.0:6.0]\",\n", + " arrow = [\n", + " \"from screen 0.3-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.3+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.3-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.3+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\"\n", + " ],\n", + " label=\"1 '(a)' at graph 0.2,0.9\",\n", + " grid=false\n", + " #arrow = \"from screen 0.3-0.01,1.0-0.01 to screen 0.3+0.01,1.0+0.01 nohead\"\n", + " #format = \"x ''\"\n", + " #title = \"'Time-delay resid. (O-C)'\"\n", + " ),\n", + " handle = 1\n", + ")\n", + "Gaston.plot!(\n", + " del_dates_plot,\n", + " res_τ(δx_OR7),\n", + " supp = σ_del_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", + " lc = 2\n", + ")\n", + "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", + "\n", + "p2 = Gaston.plot(\n", + " del_dates_plot,\n", + " res_τ(δx_OR6),\n", + " supp = σ_del_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", + " Axes(\n", + " #linetype = :tab10,\n", + " xdata = \"time\",\n", + " timefmt = \"'%d/%m/%y %H%M'\",\n", + " axesconf = \"set lmargin at screen 0.35; set tmargin at screen $tmargin_ths_plt; set rmargin at screen 0.8; set bmargin at screen $bmargin_ths_plt\",\n", + " xtics = false, #\"format '' time (\\\"01/01/13\\\",\\\"01/02/13\\\",\\\"01/03/13\\\")\", # '%d/%b/%y'\n", + " xrange = \"[\\\"15/12/12\\\":\\\"20/03/13\\\"]\",\n", + " #xlabel = \"\\\"Date\\\"\",\n", + " bars = false, #2,\n", + " #tics=\"scale 0\",\n", + " ytics = false, #[false, \"(\\\"\\\" 0)\"], #\"nomirror\",\n", + " border = \"1+4\",\n", + " yrange = \"[-8.0:6.0]\",\n", + " format = [\"x ''\", \"y ''\"], #%1.1f\n", + " arrow = [\n", + " \"from screen 0.35-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.35+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.35-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.35+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.80-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.80+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.80-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.80+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\"\n", + " ],\n", + " #ylabel = \"'[us]'\"\n", + " ),\n", + " handle = 2\n", + ")\n", + "Gaston.plot!(\n", + " del_dates_plot,\n", + " res_τ(δx_OR7),\n", + " supp = σ_del_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", + " lc = 2\n", + ")\n", + "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", + "\n", + "p3 = Gaston.plot(\n", + " del_dates_plot,\n", + " res_τ(δx_OR6),\n", + " supp = σ_del_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", + " Axes(\n", + " #linetype = :tab10,\n", + " xdata = \"time\",\n", + " timefmt = \"'%d/%m/%y %H%M'\",\n", + " axesconf = \"set lmargin at screen 0.85; set tmargin at screen 0.965; set bmargin at screen $bmargin_ths_plt\",\n", + " xtics = false, #\"format '' time (\\\"03/03/21\\\",\\\"11/03/21\\\")\", #'%d/%b/%y'\n", + " xrange = \"[\\\"02/03/21\\\":\\\"15/03/21\\\"]\",\n", + " #xlabel = \"\\\"Date\\\"\",\n", + " bars = false, #2,\n", + " #tics=\"scale 0\",\n", + " ytics = false, #[false, \"(\\\"\\\" 0)\"], #\"nomirror\",\n", + " border = \"1+4+8\",\n", + " yrange = \"[-8.0:6.0]\",\n", + " format = [\"x ''\", \"y ''\"], #%1.1f\n", + " arrow = [\n", + " \"from screen 0.85-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.85+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.85-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.85+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\"\n", + " ],\n", + " #ylabel = \"'[us]'\"\n", + " ),\n", + " handle = 3\n", + ")\n", + "Gaston.plot!(\n", + " del_dates_plot,\n", + " res_τ(δx_OR7),\n", + " supp = σ_del_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", + " lc = 2\n", + ")\n", + "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", + "\n", + "Gaston.plot([p1 p2 p3])\n", + "\n", + "#Gaston.save(term = \"cairolatex\", output = \"del_resids.tex\", saveopts = \"pdf standalone color dashed transparent size 10in,7in font ',14'\")\n", + "#run(`pdflatex del_resids.tex`)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "jupyter": { + "source_hidden": true + } + }, + "outputs": [], + "source": [ + "tmargin_ths_plt = 0.5 - tmargin_bmargin_gap\n", + "bmargin_ths_plt = 0.05\n", + "\n", + "Gaston.set(preamble=\"unset grid\")\n", + "p4 = Gaston.plot(\n", + " dop_dates_plot,\n", + " res_ν(δx_OR6),\n", + " supp = σ_dop_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", + " Axes(\n", + " #linetype = :tab10,\n", + " axesconf=\"set rmargin at screen $rmargin_ths_plt; set tmargin at screen $tmargin_ths_plt; set bmargin at screen $bmargin_ths_plt\",\n", + " xdata = \"time\",\n", + " timefmt = \"'%d/%m/%y %H%M'\",\n", + " xtics = \"format '%d/%b/%y' time (\\\"01/01/05\\\",\\\"01/01/06\\\")\",\n", + " xrange = \"[\\\"01/12/04\\\":\\\"30/05/06\\\"]\",\n", + " #xlabel = \"\\\"Date\\\"\",\n", + " bars = false,#2,\n", + " ylabel = \"'Doppler shift resid. (O-C) [Hz]'\",\n", + " border=\"1+2+4\",\n", + " ytics = [\"nomirror\", \"format '%1.1f'\"],\n", + " yrange=\"[-0.5:0.5]\",\n", + " arrow = [\n", + " \"from screen 0.3-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.3+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.3-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.3+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\"\n", + " ],\n", + " label=\"1 '(b)' at graph 0.2,0.9\"\n", + " #title = \"'Doppler shift resid. (O-C)'\"\n", + " ),\n", + " handle = 4\n", + ")\n", + "Gaston.plot!(\n", + " dop_dates_plot,\n", + " res_ν(δx_OR7),\n", + " supp = σ_dop_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", + " lc = 2\n", + ")\n", + "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", + "\n", + "p5 = Gaston.plot(\n", + " dop_dates_plot,\n", + " res_ν(δx_OR6),\n", + " supp = σ_dop_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", + " Axes(\n", + " #linetype = :tab10,\n", + " xdata = \"time\",\n", + " timefmt = \"'%d/%m/%y %H%M'\",\n", + " axesconf=\"set lmargin at screen $rmargin_ths_plt+0.05; set rmargin at screen 0.8; set tmargin at screen $tmargin_ths_plt; set bmargin at screen $bmargin_ths_plt\",\n", + " xtics=\"format '%d/%b/%y' time (\\\"01/01/13\\\",\\\"01/02/13\\\",\\\"01/03/13\\\")\",\n", + " xrange=\"[\\\"15/12/12\\\":\\\"20/03/13\\\"]\",\n", + " #xlabel = \"\\\"Date\\\"\",\n", + " bars = false, #2,\n", + " ytics=false,\n", + " border=\"1+4\",\n", + " yrange=\"[-0.5:0.5]\",\n", + " arrow = [\n", + " \"from screen 0.35-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.35+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.35-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.35+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.8-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.8+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.8-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.8+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\"\n", + " ],\n", + " #ylabel = \"'[Hz]'\"\n", + " ),\n", + " handle = 5\n", + ")\n", + "Gaston.plot!(\n", + " dop_dates_plot,\n", + " res_ν(δx_OR7),\n", + " supp = σ_dop_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", + " lc = 2\n", + ")\n", + "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", + "\n", + "p6 = Gaston.plot(\n", + " dop_dates_plot,\n", + " res_ν(δx_OR6),\n", + " supp = σ_dop_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 6 lw $lw_ths_plt\",\n", + " Axes(\n", + " #linetype = :tab10,\n", + " xdata = \"time\",\n", + " timefmt = \"'%d/%m/%y %H%M'\",\n", + " axesconf=\"set lmargin at screen 0.85; set tmargin at screen $tmargin_ths_plt; set bmargin at screen $bmargin_ths_plt\",\n", + " xtics=\"format '%d/%b/%y' time (\\\"03/03/21\\\",\\\"13/03/21\\\")\",\n", + " xrange=\"[\\\"02/03/21\\\":\\\"15/03/21\\\"]\",\n", + " #xlabel = \"\\\"Date\\\"\",\n", + " bars = false, #2,\n", + " #format=\"y ''\",\n", + " ytics=false,\n", + " border=\"1+4+8\",\n", + " yrange=\"[-0.5:0.5]\",\n", + " arrow = [\n", + " \"from screen 0.85-$axsbrk_h,$tmargin_ths_plt-$axsbrk_v to screen 0.85+$axsbrk_h,$tmargin_ths_plt+$axsbrk_v nohead\",\n", + " \"from screen 0.85-$axsbrk_h,$bmargin_ths_plt-$axsbrk_v to screen 0.85+$axsbrk_h,$bmargin_ths_plt+$axsbrk_v nohead\"\n", + " ],\n", + " #ylabel = \"'[Hz]'\"\n", + " ),\n", + " handle = 6\n", + ")\n", + "Gaston.plot!(\n", + " dop_dates_plot,\n", + " res_ν(δx_OR7),\n", + " supp = σ_dop_all,\n", + " curveconf = \"u 1:3:4 w errorbars pt 4 lw $lw_ths_plt\",\n", + " lc = 2\n", + ")\n", + "Gaston.plot!(deldop_dates_plot_xaxis, zeros(length(deldop_dates_plot_xaxis)), curveconf=\" u 1:3 w l lc rgb 'gray' lw 4 dt 2\")\n", + "\n", + "Gaston.plot([p4 p5 p6])\n", + "\n", + "#Gaston.save(term = \"cairolatex\", output = \"dop_resids.tex\", saveopts = \"pdf standalone color dashed transparent size 10in,7in font ',14'\")\n", + "#run(`pdflatex dop_resids.tex`)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Gaston.plot([p1 p2 p3; p4 p5 p6])\n", + "\n", + "#Gaston.save(term = \"cairolatex\", output = \"deldop_residuals_dates.tex\", saveopts = \"pdf standalone color dashed transparent size 10in,7in font ',14'\")\n", + "#run(`lualatex deldop_residuals_dates.tex`)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Julia-4-threads 1.9.1", + "language": "julia", + "name": "julia-4-threads-1.9" + }, + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/notebooks/B-plane-jt-o5v7.ipynb b/notebooks/B-plane-jt-o5v7.ipynb old mode 100755 new mode 100644 diff --git a/notebooks/Plots-paper.ipynb b/notebooks/Plots-paper.ipynb old mode 100755 new mode 100644 diff --git a/notebooks/gnuplot.cfg b/notebooks/gnuplot.cfg old mode 100755 new mode 100644 From d1d1829145c7886d37ced5e2f4188a17ed8e7310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 18 Jan 2024 13:02:26 -0600 Subject: [PATCH 104/173] Reset pha/ and scripts/ to origin/main --- pha/Project.toml | 0 pha/bennu.jl | 0 scripts/distributed.jl | 106 +++++++++++++++++------------------ scripts/main.jl | 124 ++++++++++++++++++++--------------------- scripts/main.lsf | 0 scripts/setup.jl | 0 scripts/setup.lsf | 0 7 files changed, 115 insertions(+), 115 deletions(-) mode change 100755 => 100644 pha/Project.toml mode change 100755 => 100644 pha/bennu.jl mode change 100755 => 100644 scripts/distributed.jl mode change 100755 => 100644 scripts/main.jl mode change 100755 => 100644 scripts/main.lsf mode change 100755 => 100644 scripts/setup.jl mode change 100755 => 100644 scripts/setup.lsf diff --git a/pha/Project.toml b/pha/Project.toml old mode 100755 new mode 100644 diff --git a/pha/bennu.jl b/pha/bennu.jl old mode 100755 new mode 100644 diff --git a/scripts/distributed.jl b/scripts/distributed.jl old mode 100755 new mode 100644 index 88cb8640..da6ac270 --- a/scripts/distributed.jl +++ b/scripts/distributed.jl @@ -1,53 +1,53 @@ -###julia --machine-file distributed.jl -###julia -p distributed.jl - -# using Distributed # not necessary when doing `julia -p ...` or `julia --machine-file...` -@everywhere begin - import Pkg - Pkg.activate("../") - # Pkg.instantiate() -end -@everywhere begin - using Apophis - using Dates - using TaylorSeries - - #script parameters (TODO: use ArgParse.jl instead) - const objname = "Apophis" - const maxsteps = 10000 - const nyears = 5.0 - const dense = true#false - const apophisjlpath = pkgdir(Apophis) - const radarobsfile = joinpath(apophisjlpath, "Apophis_JPL_data_2012_2013.dat") - const dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! - const t0 = datetime2julian(DateTime(2008,9,24,0,0,0)) #starting time of integration - const tmax = t0+365.25nyears #final time of integration - @show t0 == 2454733.5 - @show tmax - - function earth_et(et) - return ss16asteph( Apophis.etsecs2julian(et) )[union(3*4-2:3*4,3*(27+4)-2:3*(27+4))] - end - function sun_et(et) - return ss16asteph( Apophis.etsecs2julian(et) )[union(3*1-2:3*1,3*(27+1)-2:3*(27+1))] - end -end - -# path to local Solar System ephemeris file -# ss_eph_file = joinpath(pkgdir(Apophis), "jldeph", "ss16ast343_eph_24yr_tx.jld") -ss_eph_file = joinpath(pkgdir(Apophis), "jldeph", "ss16ast343_eph_5yr_tx.jld") - -ss16asteph, acc_eph, newtonianNb_Potential = Apophis.loadeph(ss_eph_file) - -aux = (ss16asteph, acc_eph, newtonianNb_Potential, earth_et, sun_et) -for i in 1:nworkers() - @spawnat i+1 aux = (ss16asteph, acc_eph, newtonianNb_Potential, earth_et, sun_et) -end - -#warmup (compilation) short run on all processes -parallel_run(objname, dynamics, 1, t0, tmax, aux, output=false) -println("*** Finished warmup") - -#Full jet transport integration until ~2038: about 8,000 steps -# parallel_run(objname, dynamics, maxsteps, t0, tmax, aux, radarobsfile=radarobsfile) -# println("*** Finished full jet transport integration") +###julia --machine-file distributed.jl +###julia -p distributed.jl + +# using Distributed # not necessary when doing `julia -p ...` or `julia --machine-file...` +@everywhere begin + import Pkg + Pkg.activate("../") + # Pkg.instantiate() +end +@everywhere begin + using Apophis + using Dates + using TaylorSeries + + #script parameters (TODO: use ArgParse.jl instead) + const objname = "Apophis" + const maxsteps = 10000 + const nyears = 5.0 + const dense = true#false + const apophisjlpath = pkgdir(Apophis) + const radarobsfile = joinpath(apophisjlpath, "Apophis_JPL_data_2012_2013.dat") + const dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! + const t0 = datetime2julian(DateTime(2008,9,24,0,0,0)) #starting time of integration + const tmax = t0+365.25nyears #final time of integration + @show t0 == 2454733.5 + @show tmax + + function earth_et(et) + return ss16asteph( Apophis.etsecs2julian(et) )[union(3*4-2:3*4,3*(27+4)-2:3*(27+4))] + end + function sun_et(et) + return ss16asteph( Apophis.etsecs2julian(et) )[union(3*1-2:3*1,3*(27+1)-2:3*(27+1))] + end +end + +# path to local Solar System ephemeris file +# ss_eph_file = joinpath(pkgdir(Apophis), "jldeph", "ss16ast343_eph_24yr_tx.jld") +ss_eph_file = joinpath(pkgdir(Apophis), "jldeph", "ss16ast343_eph_5yr_tx.jld") + +ss16asteph, acc_eph, newtonianNb_Potential = Apophis.loadeph(ss_eph_file) + +aux = (ss16asteph, acc_eph, newtonianNb_Potential, earth_et, sun_et) +for i in 1:nworkers() + @spawnat i+1 aux = (ss16asteph, acc_eph, newtonianNb_Potential, earth_et, sun_et) +end + +#warmup (compilation) short run on all processes +parallel_run(objname, dynamics, 1, t0, tmax, aux, output=false) +println("*** Finished warmup") + +#Full jet transport integration until ~2038: about 8,000 steps +# parallel_run(objname, dynamics, maxsteps, t0, tmax, aux, radarobsfile=radarobsfile) +# println("*** Finished full jet transport integration") diff --git a/scripts/main.jl b/scripts/main.jl old mode 100755 new mode 100644 index ed497d1a..8d518ca4 --- a/scripts/main.jl +++ b/scripts/main.jl @@ -1,62 +1,62 @@ -#Multi-threaded: -#julia -t --project=@. main.jl -#Single thread: -#julia --project=@. main.jl -using NEOs -using Dates -using TaylorIntegration -using JLD2 -using SPICE: furnsh -@show Threads.nthreads() - -#script parameters (TODO: use ArgParse.jl instead) -const varorder = 5 # 1 # varorder is the order corresponding to the jet transport perturbation -const nv = 7 #number of TaylorN variables -const objname = "Apophis" -const maxsteps = 10000 -const nyears = 6.0 #-5.0 #21.0 -const dense = false #true -const quadmath = false # use quadruple precision -const debias_table = "2018" # "2014", "hires2018" -const apophisjlpath = pkgdir(NEOs) -const dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! -const jd0 = datetime2julian(DateTime(2008,9,24,0,0,0)) #Julian date of integration initial time -@show jd0 == 2454733.5 -const t0 = 0.0 # integration initial time - -#### observation data files (ra/dec, del/dop) -const opticalobsfile = "" -const radarobsfile = "" -#const opticalobsfile = joinpath(apophisjlpath, "data", "tholen13_mpc_formatted.dat") -#const radarobsfile = joinpath(apophisjlpath, "data", "Apophis_JPL_data_2005_2006.dat") -#const opticalobsfile = joinpath(apophisjlpath, "data", "vokr15_mpc_formatted.dat") -#const radarobsfile = joinpath(apophisjlpath, "data", "Apophis_JPL_data_2012_2013.dat") - -# path to local Solar System ephemeris file -#ss_eph_file = joinpath(apophisjlpath, "jldeph", "ss16ast343_eph_m5y_et.jld") -ss_eph_file = joinpath(apophisjlpath, "jldeph", "ss16ast343_eph_p6y_et.jld") - -#### dq: perturbation to nominal initial condition (Taylor1 jet transport) -#dq = Taylor1.(zeros(7), varorder) -#dq[end][1] = 1e-14 - -#### dq: perturbation to nominal initial condition (TaylorN jet transport) -dq = set_variables("δx", order=varorder, numvars=nv) -for i in 1:6 - dq[i][1][i] = 1e-8 -end -if get_numvars() == 7 - dq[7][1][7] = 1e-14 -end - -####integrator warmup -propagate(objname, dynamics, 1, t0, nyears, ss_eph_file, output=false, dense=dense, dq=dq, quadmath=quadmath) -println("*** Finished warmup") - -#propagate(objname, dynamics, 300 #=5=#, t0, nyears, ss_eph_file, dense=dense, dq=dq, quadmath=quadmath) -#println("*** Finished 5 steps") - -######Full jet transport integration until ~2038: about 8,000 steps -###propagate(objname, dynamics, maxsteps, t0, nyears, ss_eph_file, dense=dense, dq=dq) # no obs ephemeris computation -propagate(objname, dynamics, maxsteps, t0, nyears, ss_eph_file, dense=dense, dq=dq, quadmath=quadmath, radarobsfile=radarobsfile, opticalobsfile=opticalobsfile, debias_table=debias_table) -println("*** Finished full jet transport integration") +#Multi-threaded: +#julia -t --project=@. main.jl +#Single thread: +#julia --project=@. main.jl +using NEOs +using Dates +using TaylorIntegration +using JLD2 +using SPICE: furnsh +@show Threads.nthreads() + +#script parameters (TODO: use ArgParse.jl instead) +const varorder = 5 # 1 # varorder is the order corresponding to the jet transport perturbation +const nv = 7 #number of TaylorN variables +const objname = "Apophis" +const maxsteps = 10000 +const nyears = 6.0 #-5.0 #21.0 +const dense = false #true +const quadmath = false # use quadruple precision +const debias_table = "2018" # "2014", "hires2018" +const apophisjlpath = pkgdir(NEOs) +const dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! +const jd0 = datetime2julian(DateTime(2008,9,24,0,0,0)) #Julian date of integration initial time +@show jd0 == 2454733.5 +const t0 = 0.0 # integration initial time + +#### observation data files (ra/dec, del/dop) +const opticalobsfile = "" +const radarobsfile = "" +#const opticalobsfile = joinpath(apophisjlpath, "data", "tholen13_mpc_formatted.dat") +#const radarobsfile = joinpath(apophisjlpath, "data", "Apophis_JPL_data_2005_2006.dat") +#const opticalobsfile = joinpath(apophisjlpath, "data", "vokr15_mpc_formatted.dat") +#const radarobsfile = joinpath(apophisjlpath, "data", "Apophis_JPL_data_2012_2013.dat") + +# path to local Solar System ephemeris file +#ss_eph_file = joinpath(apophisjlpath, "jldeph", "ss16ast343_eph_m5y_et.jld") +ss_eph_file = joinpath(apophisjlpath, "jldeph", "ss16ast343_eph_p6y_et.jld") + +#### dq: perturbation to nominal initial condition (Taylor1 jet transport) +#dq = Taylor1.(zeros(7), varorder) +#dq[end][1] = 1e-14 + +#### dq: perturbation to nominal initial condition (TaylorN jet transport) +dq = set_variables("δx", order=varorder, numvars=nv) +for i in 1:6 + dq[i][1][i] = 1e-8 +end +if get_numvars() == 7 + dq[7][1][7] = 1e-14 +end + +####integrator warmup +propagate(objname, dynamics, 1, t0, nyears, ss_eph_file, output=false, dense=dense, dq=dq, quadmath=quadmath) +println("*** Finished warmup") + +#propagate(objname, dynamics, 300 #=5=#, t0, nyears, ss_eph_file, dense=dense, dq=dq, quadmath=quadmath) +#println("*** Finished 5 steps") + +######Full jet transport integration until ~2038: about 8,000 steps +###propagate(objname, dynamics, maxsteps, t0, nyears, ss_eph_file, dense=dense, dq=dq) # no obs ephemeris computation +propagate(objname, dynamics, maxsteps, t0, nyears, ss_eph_file, dense=dense, dq=dq, quadmath=quadmath, radarobsfile=radarobsfile, opticalobsfile=opticalobsfile, debias_table=debias_table) +println("*** Finished full jet transport integration") diff --git a/scripts/main.lsf b/scripts/main.lsf old mode 100755 new mode 100644 diff --git a/scripts/setup.jl b/scripts/setup.jl old mode 100755 new mode 100644 diff --git a/scripts/setup.lsf b/scripts/setup.lsf old mode 100755 new mode 100644 From 2b6f17471809ca47c90385fac63aa3162d0415cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 18 Jan 2024 13:05:37 -0600 Subject: [PATCH 105/173] Reset NEOs.jl/ to origin/main --- .codecov.yml | 2 +- Artifacts.toml | 142 ++++++++++++++++++++++++------------------------- CITATION.cff | 0 LICENSE.md | 0 README.md | 124 +++++++++++++++++++++--------------------- 5 files changed, 134 insertions(+), 134 deletions(-) mode change 100755 => 100644 .codecov.yml mode change 100755 => 100644 Artifacts.toml mode change 100755 => 100644 CITATION.cff mode change 100755 => 100644 LICENSE.md mode change 100755 => 100644 README.md diff --git a/.codecov.yml b/.codecov.yml old mode 100755 new mode 100644 index d6c6c1ae..69cb7601 --- a/.codecov.yml +++ b/.codecov.yml @@ -1 +1 @@ -comment: false +comment: false diff --git a/Artifacts.toml b/Artifacts.toml old mode 100755 new mode 100644 index bce6b6ee..5187ed24 --- a/Artifacts.toml +++ b/Artifacts.toml @@ -1,71 +1,71 @@ -[TTmTDBde430] -git-tree-sha1 = "de3fba2237359dc941a057d492c305afeccba133" -lazy = true - - [[TTmTDBde430.download]] - sha256 = "a8e09c3d2f68f77c641eed0b41d2441b11a7b4f12daed8144638fdca02eb4d5d" - url = "https://ssd.jpl.nasa.gov/ftp/eph/planets/bsp/TTmTDB.de430.19feb2015.bsp" - -[a99942] -git-tree-sha1 = "7cdf1265a22c52329651c4a71a9835d1b90f568e" -lazy = true - - [[a99942.download]] - sha256 = "d1cdcad22c8060e98d7ca116973b64bc65cdb5e62fb045637701b57aa146a434" - url = "https://raw.githubusercontent.com/PerezHz/jpleph/main/a99942.tar.gz" - -[de430] -git-tree-sha1 = "db3e3a765712a792a7f4a73634213d53fc0561ec" -lazy = true - - [[de430.download]] - sha256 = "b70b72fde86923475fac6cec1e0887040bb80ffe159f153aab647cdfdf897351" - url = "https://ssd.jpl.nasa.gov/ftp/eph/planets/bsp/de430_1850-2150.bsp" - -[debias] -git-tree-sha1 = "cfd0d2615770087d3c564b7f6143f01930ccb45e" -lazy = true - - [[debias.download]] - sha256 = "8b107db9506ec45c8cad78d0981c48693c6e5957912df95f4a3df826c7736227" - url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias.tgz" - -[debias_2014] -git-tree-sha1 = "1b6a82575ac74386b893f8c51361d19d350bd234" -lazy = true - - [[debias_2014.download]] - sha256 = "1d44c6443d08f83c79017afd218c3b4e326c573d84842c88713e4b6c8d6d5b03" - url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias_2014.tgz" - -[debias_2018] -git-tree-sha1 = "ea7915a243ea4c8e0960817f50677598076beeaa" -lazy = true - - [[debias_2018.download]] - sha256 = "288132cefea7f1bdf0989782db1173948dd7dfef7da31910be90b16b73cfea6c" - url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias_2018.tgz" - -[debias_hires2018] -git-tree-sha1 = "cebf83360f68870a628805aea9b4261d0d6b4545" -lazy = true - - [[debias_hires2018.download]] - sha256 = "2b292fc79c202d38dfab386783fee10d422f6919afc58348c72059710dd6cd92" - url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias_hires2018.tgz" - -[naif0012] -git-tree-sha1 = "8fa307fe9da2a63ed0cf9d681540d94a619a0995" -lazy = true - - [[naif0012.download]] - sha256 = "678e32bdb5a744117a467cd9601cd6b373f0e9bc9bbde1371d5eee39600a039b" - url = "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/lsk/naif0012.tls" - -[sseph_p100] -git-tree-sha1 = "d4d91f0045063719c9bf581bf20bbc212327b2d0" -lazy = true - - [[sseph_p100.download]] - sha256 = "25b525ffef5c05cc51ee554760ae83107b9bd163577439470b60c2d4c7153a21" - url = "https://github.com/LuEdRaMo/sseph/raw/main/sseph343ast016_p100y_et.tar.gz" +[TTmTDBde430] +git-tree-sha1 = "de3fba2237359dc941a057d492c305afeccba133" +lazy = true + + [[TTmTDBde430.download]] + sha256 = "a8e09c3d2f68f77c641eed0b41d2441b11a7b4f12daed8144638fdca02eb4d5d" + url = "https://ssd.jpl.nasa.gov/ftp/eph/planets/bsp/TTmTDB.de430.19feb2015.bsp" + +[a99942] +git-tree-sha1 = "7cdf1265a22c52329651c4a71a9835d1b90f568e" +lazy = true + + [[a99942.download]] + sha256 = "d1cdcad22c8060e98d7ca116973b64bc65cdb5e62fb045637701b57aa146a434" + url = "https://raw.githubusercontent.com/PerezHz/jpleph/main/a99942.tar.gz" + +[de430] +git-tree-sha1 = "db3e3a765712a792a7f4a73634213d53fc0561ec" +lazy = true + + [[de430.download]] + sha256 = "b70b72fde86923475fac6cec1e0887040bb80ffe159f153aab647cdfdf897351" + url = "https://ssd.jpl.nasa.gov/ftp/eph/planets/bsp/de430_1850-2150.bsp" + +[debias] +git-tree-sha1 = "cfd0d2615770087d3c564b7f6143f01930ccb45e" +lazy = true + + [[debias.download]] + sha256 = "8b107db9506ec45c8cad78d0981c48693c6e5957912df95f4a3df826c7736227" + url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias.tgz" + +[debias_2014] +git-tree-sha1 = "1b6a82575ac74386b893f8c51361d19d350bd234" +lazy = true + + [[debias_2014.download]] + sha256 = "1d44c6443d08f83c79017afd218c3b4e326c573d84842c88713e4b6c8d6d5b03" + url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias_2014.tgz" + +[debias_2018] +git-tree-sha1 = "ea7915a243ea4c8e0960817f50677598076beeaa" +lazy = true + + [[debias_2018.download]] + sha256 = "288132cefea7f1bdf0989782db1173948dd7dfef7da31910be90b16b73cfea6c" + url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias_2018.tgz" + +[debias_hires2018] +git-tree-sha1 = "cebf83360f68870a628805aea9b4261d0d6b4545" +lazy = true + + [[debias_hires2018.download]] + sha256 = "2b292fc79c202d38dfab386783fee10d422f6919afc58348c72059710dd6cd92" + url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias_hires2018.tgz" + +[naif0012] +git-tree-sha1 = "8fa307fe9da2a63ed0cf9d681540d94a619a0995" +lazy = true + + [[naif0012.download]] + sha256 = "678e32bdb5a744117a467cd9601cd6b373f0e9bc9bbde1371d5eee39600a039b" + url = "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/lsk/naif0012.tls" + +[sseph_p100] +git-tree-sha1 = "d4d91f0045063719c9bf581bf20bbc212327b2d0" +lazy = true + + [[sseph_p100.download]] + sha256 = "25b525ffef5c05cc51ee554760ae83107b9bd163577439470b60c2d4c7153a21" + url = "https://github.com/LuEdRaMo/sseph/raw/main/sseph343ast016_p100y_et.tar.gz" diff --git a/CITATION.cff b/CITATION.cff old mode 100755 new mode 100644 diff --git a/LICENSE.md b/LICENSE.md old mode 100755 new mode 100644 diff --git a/README.md b/README.md old mode 100755 new mode 100644 index 0ffd83ce..7b2a8fc4 --- a/README.md +++ b/README.md @@ -1,62 +1,62 @@ -# NEOs.jl - -[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5152449.svg)](https://doi.org/10.5281/zenodo.5152449) -[![CI](https://github.com/PerezHz/NEOs.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/PerezHz/NEOs.jl/actions/workflows/CI.yml) -[![Coverage Status](https://coveralls.io/repos/github/PerezHz/NEOs.jl/badge.svg?branch=main)](https://coveralls.io/github/PerezHz/NEOs.jl?branch=main) -[![codecov](https://codecov.io/gh/PerezHz/NEOs.jl/branch/main/graph/badge.svg?token=F1IY79YP3J)](https://codecov.io/gh/PerezHz/NEOs.jl) - -`NEOs.jl` is a Julia package for high-accuracy orbit determination and propagation of -Near-Earth Objects. `NEOs.jl` exploits jet transport techniques via -[TaylorIntegration.jl](https://github.com/PerezHz/TaylorIntegration.jl). - -## Authors - -- [Jorge A. Pérez](https://github.com/PerezHz), -Instituto de Ciencias Físicas, Universidad Nacional Autónoma de México (UNAM) -- [Luis Benet](http://www.cicc.unam.mx/~benet/), -Instituto de Ciencias Físicas, Universidad Nacional Autónoma de México (UNAM) -- [Luis Eduardo Ramírez Montoya](https://github.com/LuEdRaMo), -Facultad de Ciencias, Universidad Nacional Autónoma de México (UNAM) - -## Installation - -The current version of this package may be installed in Julia pkg manager via: -``` -] add NEOs -``` - -## Usage - -The `pha` directory contains the `apophis.jl` script which performs an -orbit determination for asteroid (99942) Apophis from optical and radar astrometry. In order -to run this script, the environment corresponding to the `Project.toml` contained in the -`pha` directory has to be active and instantiated. This can be done, for example, by running -the following command from the `pha` directory: - -``julia -e `import Pkg; Pkg.activate(); Pkg.instantiate()` # run this from the `pha` directory `` - -Once the `pha` environment is active, this script may be called from the `pha` directory -with the default settings as: - -`julia --project apophis.jl` - -The `--help` option can be passed to see a list of the customizable settings - -`julia --project apophis.jl --help` - -`NEOs.propagate` also supports multi-threading: - -`julia -t --project apophis.jl --help` - -## Acknowledgments - -We acknowledge financial support from UNAM-PAPIIT grant IG100819 and computing -resources provided by LANCAD-UNAM-DGTIC-284. - -## References - -- Pérez-Hernández, J.A., Benet, L. Non-zero Yarkovsky acceleration for near-Earth asteroid - (99942) Apophis. Commun Earth Environ 3, 10 (2022). https://doi.org/10.1038/s43247-021-00337-x -- Pérez-Hernández, Jorge A., & Benet, Luis. (2023). - [PerezHz/TaylorIntegration.jl](https://github.com/PerezHzTaylorIntegration.jl): - v0.14.2 (Version v0.14.2). Zenodo. https://doi.org/10.5281/zenodo.8104080 +# NEOs.jl + +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5152449.svg)](https://doi.org/10.5281/zenodo.5152449) +[![CI](https://github.com/PerezHz/NEOs.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/PerezHz/NEOs.jl/actions/workflows/CI.yml) +[![Coverage Status](https://coveralls.io/repos/github/PerezHz/NEOs.jl/badge.svg?branch=main)](https://coveralls.io/github/PerezHz/NEOs.jl?branch=main) +[![codecov](https://codecov.io/gh/PerezHz/NEOs.jl/branch/main/graph/badge.svg?token=F1IY79YP3J)](https://codecov.io/gh/PerezHz/NEOs.jl) + +`NEOs.jl` is a Julia package for high-accuracy orbit determination and propagation of +Near-Earth Objects. `NEOs.jl` exploits jet transport techniques via +[TaylorIntegration.jl](https://github.com/PerezHz/TaylorIntegration.jl). + +## Authors + +- [Jorge A. Pérez](https://github.com/PerezHz), +Instituto de Ciencias Físicas, Universidad Nacional Autónoma de México (UNAM) +- [Luis Benet](http://www.cicc.unam.mx/~benet/), +Instituto de Ciencias Físicas, Universidad Nacional Autónoma de México (UNAM) +- [Luis Eduardo Ramírez Montoya](https://github.com/LuEdRaMo), +Facultad de Ciencias, Universidad Nacional Autónoma de México (UNAM) + +## Installation + +The current version of this package may be installed in Julia pkg manager via: +``` +] add NEOs +``` + +## Usage + +The `pha` directory contains the `apophis.jl` script which performs an +orbit determination for asteroid (99942) Apophis from optical and radar astrometry. In order +to run this script, the environment corresponding to the `Project.toml` contained in the +`pha` directory has to be active and instantiated. This can be done, for example, by running +the following command from the `pha` directory: + +``julia -e `import Pkg; Pkg.activate(); Pkg.instantiate()` # run this from the `pha` directory `` + +Once the `pha` environment is active, this script may be called from the `pha` directory +with the default settings as: + +`julia --project apophis.jl` + +The `--help` option can be passed to see a list of the customizable settings + +`julia --project apophis.jl --help` + +`NEOs.propagate` also supports multi-threading: + +`julia -t --project apophis.jl --help` + +## Acknowledgments + +We acknowledge financial support from UNAM-PAPIIT grant IG100819 and computing +resources provided by LANCAD-UNAM-DGTIC-284. + +## References + +- Pérez-Hernández, J.A., Benet, L. Non-zero Yarkovsky acceleration for near-Earth asteroid + (99942) Apophis. Commun Earth Environ 3, 10 (2022). https://doi.org/10.1038/s43247-021-00337-x +- Pérez-Hernández, Jorge A., & Benet, Luis. (2023). + [PerezHz/TaylorIntegration.jl](https://github.com/PerezHzTaylorIntegration.jl): + v0.14.2 (Version v0.14.2). Zenodo. https://doi.org/10.5281/zenodo.8104080 From 98d910e169b25a2db370dadfdf1dd971f6b400bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 18 Jan 2024 13:07:53 -0600 Subject: [PATCH 106/173] Reset test/ to origin/main --- test/Project.toml | 32 +- test/data/99942_RADAR_2005_2013.dat | 92 +-- test/data/99942_Tholen_etal_2013.dat | 864 +++++++++++++-------------- test/data/RADEC_2023_DW.dat | 246 ++++---- test/extensions.jl | 102 ++-- test/osculating.jl | 30 +- 6 files changed, 683 insertions(+), 683 deletions(-) mode change 100755 => 100644 test/Project.toml mode change 100755 => 100644 test/data/99942_RADAR_2005_2013.dat mode change 100755 => 100644 test/data/99942_Tholen_etal_2013.dat mode change 100755 => 100644 test/data/RADEC_2023_DW.dat mode change 100755 => 100644 test/extensions.jl mode change 100755 => 100644 test/osculating.jl diff --git a/test/Project.toml b/test/Project.toml old mode 100755 new mode 100644 index 1ef28247..11d054fc --- a/test/Project.toml +++ b/test/Project.toml @@ -1,16 +1,16 @@ -[deps] -DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" -Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" -DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" -Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" -InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" -JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" -LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" -Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" -PlanetaryEphemeris = "d83715d0-7e5f-11e9-1a59-4137b20d8363" -Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" -Query = "1a8c2f83-1ff3-5112-b086-8aa67b057ba1" -Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" -Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" -TaylorIntegration = "92b13dbe-c966-51a2-8445-caca9f8a7d42" -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +[deps] +DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" +Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" +InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" +JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +PlanetaryEphemeris = "d83715d0-7e5f-11e9-1a59-4137b20d8363" +Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" +Query = "1a8c2f83-1ff3-5112-b086-8aa67b057ba1" +Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" +TaylorIntegration = "92b13dbe-c966-51a2-8445-caca9f8a7d42" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/data/99942_RADAR_2005_2013.dat b/test/data/99942_RADAR_2005_2013.dat old mode 100755 new mode 100644 index a4e41449..864aa630 --- a/test/data/99942_RADAR_2005_2013.dat +++ b/test/data/99942_RADAR_2005_2013.dat @@ -1,46 +1,46 @@ -99942 Apophis (2004 MN4) 2005-01-27 23:31:00 -100849.1434 0.250 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2005-01-29 00:00:00 192028507.13 4.000 us 2380 251 251 C -99942 Apophis (2004 MN4) 2005-01-29 00:00:00 -102512.9059 0.250 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2005-01-30 00:18:00 195808170.79 4.500 us 2380 251 251 C -99942 Apophis (2004 MN4) 2005-01-30 00:18:00 -103799.8178 0.150 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2005-08-07 17:07:00 8186.8 0.200 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2006-05-06 12:49:00 -118256.8 0.100 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2012-12-21 11:10:00 57992.443 0.250 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2012-12-22 11:00:00 57880.250 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2012-12-22 11:00:00 102682986.05 0.25 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-03 09:20:00 97449107.61 0.25 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-03 09:20:00 36629.285 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-03 10:00:00 97439308.71 3.000 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-03 10:50:00 97428425.46 0.25 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-05 08:40:00 30404.009 0.2 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-05 10:40:00 96911591.52 0.25 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-05 10:40:00 20031.160 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-05 10:50:00 96910218.03 3.000 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-06 08:20:00 26660.815 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-06 09:30:00 20775.144 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-08 08:10:00 15496.441 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-09 08:00:00 9670.119 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-09 08:00:00 96451449.73 0.2 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-09 09:20:00 2690.401 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-10 08:00:00 2590.857 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-10 08:00:00 96472652.72 0.20 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-10 09:40:00 96473924.8 0.20 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-11 07:20:00 -1589.599 0.2 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-14 08:10:00 97258343.56 0.20 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-14 08:10:00 -30561.776 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-14 09:50:00 97283037.17 0.20 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-15 06:30:00 -30666.291 0.10 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-16 06:30:00 -39582.277 0.20 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-16 06:30:00 98086754. 1.000 us 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-16 07:50:00 -46641.384 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-01-17 06:20:00 -47875.142 0.1 Hz 8560 253 253 C -99942 Apophis (2004 MN4) 2013-02-18 00:56:00 -76760.475 0.2 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2013-02-18 01:37:00 157906444.15 0.25 us 2380 251 251 C -99942 Apophis (2004 MN4) 2013-02-18 01:37:00 -78041.365 0.2 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2013-02-19 01:08:00 -78105.657 0.2 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2013-02-20 00:38:00 -78070.341 0.2 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2013-02-20 01:26:00 163578875.87 0.25 us 2380 251 251 C -99942 Apophis (2004 MN4) 2013-02-20 01:26:00 -79560.965 0.2 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2013-02-21 01:04:00 -79697.130 0.2 Hz 2380 251 251 C -99942 Apophis (2004 MN4) 2013-03-15 23:59:00 235220855.07 2.000 us 2380 251 251 C -99942 Apophis (2004 MN4) 2013-03-15 23:59:00 -80977.5254 0.238 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2005-01-27 23:31:00 -100849.1434 0.250 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2005-01-29 00:00:00 192028507.13 4.000 us 2380 251 251 C +99942 Apophis (2004 MN4) 2005-01-29 00:00:00 -102512.9059 0.250 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2005-01-30 00:18:00 195808170.79 4.500 us 2380 251 251 C +99942 Apophis (2004 MN4) 2005-01-30 00:18:00 -103799.8178 0.150 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2005-08-07 17:07:00 8186.8 0.200 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2006-05-06 12:49:00 -118256.8 0.100 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2012-12-21 11:10:00 57992.443 0.250 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2012-12-22 11:00:00 57880.250 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2012-12-22 11:00:00 102682986.05 0.25 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-03 09:20:00 97449107.61 0.25 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-03 09:20:00 36629.285 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-03 10:00:00 97439308.71 3.000 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-03 10:50:00 97428425.46 0.25 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-05 08:40:00 30404.009 0.2 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-05 10:40:00 96911591.52 0.25 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-05 10:40:00 20031.160 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-05 10:50:00 96910218.03 3.000 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-06 08:20:00 26660.815 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-06 09:30:00 20775.144 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-08 08:10:00 15496.441 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-09 08:00:00 9670.119 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-09 08:00:00 96451449.73 0.2 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-09 09:20:00 2690.401 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-10 08:00:00 2590.857 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-10 08:00:00 96472652.72 0.20 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-10 09:40:00 96473924.8 0.20 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-11 07:20:00 -1589.599 0.2 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-14 08:10:00 97258343.56 0.20 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-14 08:10:00 -30561.776 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-14 09:50:00 97283037.17 0.20 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-15 06:30:00 -30666.291 0.10 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-16 06:30:00 -39582.277 0.20 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-16 06:30:00 98086754. 1.000 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-16 07:50:00 -46641.384 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-17 06:20:00 -47875.142 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-02-18 00:56:00 -76760.475 0.2 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-18 01:37:00 157906444.15 0.25 us 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-18 01:37:00 -78041.365 0.2 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-19 01:08:00 -78105.657 0.2 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-20 00:38:00 -78070.341 0.2 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-20 01:26:00 163578875.87 0.25 us 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-20 01:26:00 -79560.965 0.2 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-21 01:04:00 -79697.130 0.2 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2013-03-15 23:59:00 235220855.07 2.000 us 2380 251 251 C +99942 Apophis (2004 MN4) 2013-03-15 23:59:00 -80977.5254 0.238 Hz 2380 251 251 C diff --git a/test/data/99942_Tholen_etal_2013.dat b/test/data/99942_Tholen_etal_2013.dat old mode 100755 new mode 100644 index 00a39394..36b71a75 --- a/test/data/99942_Tholen_etal_2013.dat +++ b/test/data/99942_Tholen_etal_2013.dat @@ -1,432 +1,432 @@ -99942 'C2004 06 19.17015009 44 29.677+13 18 50.67 L~09vB695 -99942 'C2004 06 19.17486109 44 30.604+13 18 46.81 L~09vB695 -99942 'C2004 06 19.17967609 44 31.507+13 18 42.91 L~09vB695 -99942 'C2004 06 20.15951409 47 41.116+13 05 24.49 L~09vB695 -99942 'C2004 06 20.16431709 47 42.006+13 05 20.50 L~09vB695 -99942 'C2004 06 20.16906309 47 42.926+13 05 16.74 L~09vB695 -99942 'C2005 07 09.17600210 34 38.149+16 12 41.50 L~09vB695 -99942 'C2005 07 09.18080710 34 38.288+16 12 42.68 L~09vB695 -99942 'C2005 07 10.17554310 35 10.909+16 18 25.82 L~09vB695 -99942 'C2005 07 10.17819210 35 10.983+16 18 26.48 L~09vB695 -99942 'C2005 07 11.16972710 35 36.698+16 24 46.68 L~09vB695 -99942 2C2005 09 04.63519408 25 00.085+22 18 13.02 L~09vB568 -99942 2C2005 09 04.63627008 25 00.075+22 18 12.36 L~09vB568 -99942 2C2005 12 31.64597612 46 28.407-11 49 33.02 L~09vB568 -99942 2C2005 12 31.64713112 46 28.583-11 49 34.23 L~09vB568 -99942 2C2005 12 31.64800212 46 28.708-11 49 35.16 L~09vB568 -99942 2C2006 03 05.54636616 20 49.786-26 34 29.32 L~09vB568 -99942 2C2006 03 05.61052316 21 07.957-26 34 51.45 L~09vB568 -99942 2C2006 03 05.65266816 21 19.828-26 35 04.75 L~09vB568 -99942 2C2006 03 06.51985316 25 39.350-26 39 07.23 L~09vB568 -99942 2C2006 03 06.52154416 25 39.838-26 39 07.85 L~09vB568 -99942 2C2006 03 06.52319016 25 40.319-26 39 08.38 L~09vB568 -99942 2C2006 03 06.52483716 25 40.802-26 39 08.75 L~09vB568 -99942 2C2006 03 06.52649816 25 41.288-26 39 09.42 L~09vB568 -99942 2C2006 03 06.53152916 25 42.744-26 39 11.09 L~09vB568 -99942 2C2006 03 06.53317516 25 43.230-26 39 11.64 L~09vB568 -99942 2C2006 03 06.53785116 25 44.576-26 39 13.17 L~09vB568 -99942 2C2006 03 06.53950516 25 45.058-26 39 13.71 L~09vB568 -99942 2C2006 03 06.54114016 25 45.528-26 39 14.25 L~09vB568 -99942 2C2006 03 06.54279516 25 46.018-26 39 14.75 L~09vB568 -99942 2C2006 03 06.54460416 25 46.542-26 39 15.35 L~09vB568 -99942 2C2006 03 06.54622816 25 47.020-26 39 15.82 L~09vB568 -99942 2C2006 03 06.54788716 25 47.487-26 39 16.37 L~09vB568 -99942 2C2006 03 06.54963916 25 48.001-26 39 16.97 L~09vB568 -99942 2C2006 03 06.55128516 25 48.473-26 39 17.49 L~09vB568 -99942 2C2006 03 06.55294416 25 48.954-26 39 18.02 L~09vB568 -99942 2C2006 03 06.58062516 25 56.956-26 39 26.69 L~09vB568 -99942 2C2006 03 06.58226716 25 57.429-26 39 27.19 L~09vB568 -99942 2C2006 03 06.58390316 25 57.889-26 39 27.56 L~09vB568 -99942 2C2006 03 06.58565516 25 58.403-26 39 28.25 L~09vB568 -99942 2C2006 03 06.58729516 25 58.884-26 39 28.74 L~09vB568 -99942 2C2006 03 06.58894616 25 59.356-26 39 29.24 L~09vB568 -99942 2C2006 03 06.59071316 25 59.860-26 39 29.79 L~09vB568 -99942 2C2006 03 06.59240616 26 00.342-26 39 30.29 L~09vB568 -99942 2C2006 03 06.59416916 26 00.854-26 39 30.79 L~09vB568 -99942 2C2006 03 06.59581316 26 01.332-26 39 31.30 L~09vB568 -99942 2C2006 03 06.59986316 26 02.494-26 39 32.45 L~09vB568 -99942 2C2006 03 06.60160616 26 02.993-26 39 33.01 L~09vB568 -99942 2C2006 03 06.60323516 26 03.457-26 39 33.48 L~09vB568 -99942 2C2006 03 06.60488216 26 03.930-26 39 34.00 L~09vB568 -99942 2C2006 03 06.60655416 26 04.414-26 39 34.45 L~09vB568 -99942 2C2006 03 06.60819916 26 04.891-26 39 34.94 L~09vB568 -99942 2C2006 03 06.60994916 26 05.388-26 39 35.44 L~09vB568 -99942 2C2006 03 06.61161916 26 05.870-26 39 35.93 L~09vB568 -99942 2C2006 03 06.61340316 26 06.381-26 39 36.46 L~09vB568 -99942 2C2006 03 06.61522116 26 06.900-26 39 36.96 L~09vB568 -99942 2C2006 03 06.61779416 26 07.648-26 39 37.74 L~09vB568 -99942 2C2006 03 06.61944816 26 08.129-26 39 38.22 L~09vB568 -99942 2C2006 03 06.62108316 26 08.593-26 39 38.68 L~09vB568 -99942 2C2006 03 06.62287816 26 09.105-26 39 39.17 L~09vB568 -99942 2C2006 03 06.62453816 26 09.584-26 39 39.65 L~09vB568 -99942 2C2006 03 06.62634316 26 10.112-26 39 40.15 L~09vB568 -99942 2C2006 03 06.62962316 26 11.039-26 39 41.09 L~09vB568 -99942 2C2006 03 06.63137516 26 11.530-26 39 41.57 L~09vB568 -99942 2C2006 03 06.63303116 26 12.016-26 39 42.05 L~09vB568 -99942 2C2006 03 06.63501716 26 12.589-26 39 42.58 L~09vB568 -99942 2C2006 03 06.63831016 26 13.532-26 39 43.51 L~09vB568 -99942 2C2006 03 06.63998416 26 14.033-26 39 43.93 L~09vB568 -99942 2C2006 03 06.64177816 26 14.532-26 39 44.44 L~09vB568 -99942 2C2006 03 06.64342816 26 15.007-26 39 44.91 L~09vB568 -99942 2C2006 03 06.64522616 26 15.513-26 39 45.40 L~09vB568 -99942 2C2006 03 06.64689116 26 16.000-26 39 45.85 L~09vB568 -99942 2C2006 03 06.64869616 26 16.534-26 39 46.31 L~09vB568 -99942 2C2006 03 06.65033416 26 16.985-26 39 46.76 L~09vB568 -99942 2C2006 03 08.52450916 35 51.633-26 46 44.58 L~09vB568 -99942 2C2006 03 08.52614416 35 52.139-26 46 45.02 L~09vB568 -99942 2C2006 03 08.52778416 35 52.632-26 46 45.44 L~09vB568 -99942 2C2006 03 08.52940616 35 53.122-26 46 45.81 L~09vB568 -99942 2C2006 03 08.53118916 35 53.668-26 46 46.23 L~09vB568 -99942 2C2006 03 08.53282516 35 54.145-26 46 46.74 L~09vB568 -99942 2C2006 03 08.53446116 35 54.645-26 46 47.05 L~09vB568 -99942 2C2006 03 08.53622516 35 55.161-26 46 47.51 L~09vB568 -99942 2C2006 03 08.53952316 35 56.166-26 46 48.34 L~09vB568 -99942 2C2006 03 08.54821816 35 58.785-26 46 50.43 L~09vB568 -99942 2C2006 03 08.54987016 35 59.291-26 46 50.85 L~09vB568 -99942 2C2006 03 08.55150916 35 59.779-26 46 51.19 L~09vB568 -99942 2C2006 03 08.55327516 36 00.314-26 46 51.64 L~09vB568 -99942 2C2006 03 08.55494116 36 00.797-26 46 52.06 L~09vB568 -99942 2C2006 03 08.55657116 36 01.305-26 46 52.45 L~09vB568 -99942 2C2006 03 08.55820316 36 01.809-26 46 52.76 L~09vB568 -99942 2C2006 03 08.55999116 36 02.337-26 46 53.31 L~09vB568 -99942 2C2006 03 08.56165316 36 02.824-26 46 53.65 L~09vB568 -99942 2C2006 03 08.56331116 36 03.321-26 46 54.00 L~09vB568 -99942 2C2006 03 08.56529216 36 03.925-26 46 54.53 L~09vB568 -99942 2C2006 03 08.56705816 36 04.447-26 46 54.94 L~09vB568 -99942 2C2006 03 08.56870116 36 04.934-26 46 55.29 L~09vB568 -99942 2C2006 03 08.57034116 36 05.423-26 46 55.67 L~09vB568 -99942 2C2006 03 08.57210416 36 05.964-26 46 56.10 L~09vB568 -99942 2C2006 03 08.57374816 36 06.447-26 46 56.43 L~09vB568 -99942 2C2006 03 08.57878216 36 07.950-26 46 57.62 L~09vB568 -99942 2C2006 03 08.58043616 36 08.453-26 46 57.97 L~09vB568 -99942 2C2006 03 08.59506416 36 12.824-26 47 01.24 L~09vB568 -99942 2C2006 03 08.59679916 36 13.342-26 47 01.59 L~09vB568 -99942 2C2006 03 08.59842816 36 13.834-26 47 01.97 L~09vB568 -99942 2C2006 03 08.60007616 36 14.327-26 47 02.20 L~09vB568 -99942 2C2006 03 08.60176516 36 14.819-26 47 02.62 L~09vB568 -99942 2C2006 03 08.60342016 36 15.335-26 47 03.00 L~09vB568 -99942 2C2006 03 08.60506016 36 15.804-26 47 03.30 L~09vB568 -99942 2C2006 03 08.60672516 36 16.308-26 47 03.66 L~09vB568 -99942 2C2006 03 08.60840016 36 16.812-26 47 04.07 L~09vB568 -99942 2C2006 03 08.61019116 36 17.347-26 47 04.43 L~09vB568 -99942 2C2006 03 08.61180216 36 17.821-26 47 04.73 L~09vB568 -99942 2C2006 03 08.61356016 36 18.338-26 47 05.15 L~09vB568 -99942 2C2006 03 08.61522616 36 18.848-26 47 05.46 L~09vB568 -99942 2C2006 03 08.61702416 36 19.384-26 47 05.80 L~09vB568 -99942 2C2006 03 08.61880916 36 19.911-26 47 06.18 L~09vB568 -99942 2C2006 03 08.62044116 36 20.397-26 47 06.50 L~09vB568 -99942 2C2006 03 08.62209616 36 20.893-26 47 06.83 L~09vB568 -99942 2C2006 03 08.62373616 36 21.391-26 47 07.18 L~09vB568 -99942 2C2006 03 08.62551916 36 21.915-26 47 07.56 L~09vB568 -99942 2C2006 03 08.62716816 36 22.403-26 47 07.90 L~09vB568 -99942 2C2006 03 08.62914916 36 23.003-26 47 08.29 L~09vB568 -99942 2C2006 03 08.63083816 36 23.503-26 47 08.58 L~09vB568 -99942 2C2006 03 08.63248116 36 23.992-26 47 08.94 L~09vB568 -99942 2C2006 03 08.63410316 36 24.477-26 47 09.24 L~09vB568 -99942 2C2006 03 08.63588516 36 24.997-26 47 09.59 L~09vB568 -99942 2C2006 03 08.63752916 36 25.500-26 47 09.91 L~09vB568 -99942 2C2006 03 08.63917116 36 25.991-26 47 10.23 L~09vB568 -99942 2C2006 03 08.64083116 36 26.480-26 47 10.54 L~09vB568 -99942 2C2006 03 08.64263816 36 27.008-26 47 10.89 L~09vB568 -99942 2C2006 03 08.64430016 36 27.506-26 47 11.22 L~09vB568 -99942 2C2006 03 08.64589016 36 27.988-26 47 11.49 L~09vB568 -99942 2C2006 03 08.64751516 36 28.476-26 47 11.82 L~09vB568 -99942 2C2006 03 08.64930316 36 29.008-26 47 12.13 L~09vB568 -99942 2C2006 03 08.65095316 36 29.492-26 47 12.45 L~09vB568 -99942 2C2006 03 08.66103116 36 32.496-26 47 14.31 L~09vB568 -99942 2C2006 05 01.62736922 43 36.580-01 20 46.01 L~09vB568 -99942 2C2006 05 01.62821822 43 36.869-01 20 44.02 L~09vB568 -99942 2C2006 06 01.60681201 12 41.522+14 14 31.91 L~09vB568 -99942 2C2006 06 01.60868801 12 41.959+14 14 34.24 L~09vB568 -99942 2C2006 06 02.59935901 16 48.755+14 34 20.07 L~09vB568 -99942 2C2006 06 02.60078001 16 49.108+14 34 21.72 L~09vB568 -99942 2C2006 06 02.60224201 16 49.478+14 34 23.59 L~09vB568 -99942 2C2006 07 27.61254105 06 37.958+23 53 27.72 L~09vB568 -99942 2C2006 07 27.61447305 06 38.465+23 53 27.83 L~09vB568 -99942 2C2006 08 15.61852106 26 52.404+22 57 47.52 L~09vB568 -99942 2C2006 08 15.62233206 26 53.348+22 57 46.02 L~09vB568 -99942 2C2006 08 16.62183606 31 00.059+22 51 14.54 L~09vB568 -99942 2C2006 08 16.62441906 31 00.629+22 51 13.69 L~09vB568 -99942 2C2006 08 16.62695406 31 01.254+22 51 12.76 L~09vB568 -99942 2C2006 09 04.59915907 45 57.632+19 48 13.43 L~09vB568 -99942 2C2006 09 04.60174207 45 58.282+19 48 11.30 L~09vB568 -99942 2C2006 09 04.60702707 45 59.441+19 48 07.57 L~09vB568 -99942 2C2006 09 04.60960407 46 00.032+19 48 05.65 L~09vB568 -99942 2C2006 09 04.61217807 46 00.596+19 48 03.81 L~09vC568 -99942 2C2006 09 04.61475007 46 01.189+19 48 01.98 L~09vC568 -99942 2C2006 09 04.61733207 46 01.771+19 48 00.12 L~09vC568 -99942 2C2006 09 04.61991607 46 02.330+19 47 58.33 L~09vC568 -99942 2C2006 09 04.62259307 46 02.963+19 47 56.27 L~09vC568 -99942 2C2006 09 04.62517107 46 03.533+19 47 54.35 L~09vC568 -99942 2C2006 09 04.62774407 46 04.120+19 47 52.46 L~09vC568 -99942 2C2006 10 25.59993210 38 53.805+05 37 27.51 L~09vC568 -99942 2C2006 10 25.60369210 38 54.499+05 37 23.28 L~09vC568 -99942 2C2006 10 25.60744010 38 55.203+05 37 18.89 L~09vC568 -99942 2C2006 10 25.61132210 38 55.912+05 37 14.36 L~09vC568 -99942 2C2006 10 25.61506310 38 56.601+05 37 10.09 L~09vC568 -99942 2C2006 10 25.61879910 38 57.275+05 37 05.78 L~09vC568 -99942 2C2006 10 25.62267810 38 58.014+05 37 01.23 L~09vC568 -99942 2C2006 10 25.62640510 38 58.696+05 36 56.87 L~09vC568 -99942 2C2006 10 25.63014810 38 59.377+05 36 52.66 L~09vC568 -99942 2C2006 10 25.63403010 39 00.098+05 36 48.23 L~09vC568 -99942 2C2006 10 25.63779510 39 00.816+05 36 43.85 L~09vC568 -99942 2C2006 11 28.59593412 23 24.533-05 33 25.55 L~09vC568 -99942 2C2006 11 28.59911212 23 25.116-05 33 29.23 L~09vC568 -99942 2C2006 11 28.60196112 23 25.630-05 33 32.60 L~09vC568 -99942 2C2006 11 28.60444112 23 26.110-05 33 35.60 L~09vC568 -99942 2C2006 11 28.60694712 23 26.572-05 33 38.57 L~09vC568 -99942 2C2006 11 28.60930612 23 27.008-05 33 41.28 L~09vC568 -99942 2C2006 11 28.61175812 23 27.455-05 33 44.13 L~09vC568 -99942 2C2006 11 28.61410412 23 27.900-05 33 47.02 L~09vC568 -99942 2C2006 11 28.61644012 23 28.333-05 33 49.76 L~09vC568 -99942 2C2006 11 28.61881912 23 28.750-05 33 52.52 L~09vC568 -99942 2C2006 11 28.62122512 23 29.200-05 33 55.26 L~09vC568 -99942 2C2006 11 28.62509412 23 29.918-05 33 59.86 L~09vC568 -99942 2C2006 11 28.62744612 23 30.356-05 34 02.67 L~09vC568 -99942 2C2006 11 28.62980412 23 30.783-05 34 05.39 L~09vC568 -99942 2C2006 11 28.63229412 23 31.243-05 34 08.35 L~09vC568 -99942 2C2006 11 28.63463812 23 31.694-05 34 11.18 L~09vC568 -99942 2C2006 11 28.63699212 23 32.122-05 34 13.96 L~09vC568 -99942 2C2006 11 28.63939612 23 32.559-05 34 16.72 L~09vC568 -99942 2C2006 11 28.64191212 23 33.023-05 34 19.79 L~09vC568 -99942 2C2006 11 28.64780312 23 34.102-05 34 26.64 L~09vC568 -99942 2C2006 12 25.61583813 51 22.763-13 59 56.70 L~09vC568 -99942 2C2006 12 25.61784113 51 23.174-13 59 58.77 L~09vC568 -99942 2C2006 12 25.61998413 51 23.614-14 00 01.00 L~09vC568 -99942 2C2006 12 25.62212713 51 24.048-14 00 03.19 L~09vC568 -99942 2C2006 12 25.62426613 51 24.483-14 00 05.46 L~09vC568 -99942 2C2006 12 25.62626013 51 24.897-14 00 07.57 L~09vC568 -99942 2C2006 12 25.62826013 51 25.303-14 00 09.63 L~09vC568 -99942 2C2006 12 25.63026913 51 25.727-14 00 11.91 L~09vC568 -99942 2C2006 12 25.63226613 51 26.111-14 00 13.98 L~09vC568 -99942 2C2006 12 25.63432513 51 26.550-14 00 16.10 L~09vC568 -99942 2C2006 12 25.63633713 51 26.944-14 00 18.32 L~09vC568 -99942 2C2006 12 25.63845413 51 27.397-14 00 20.54 L~09vC568 -99942 2C2006 12 25.64046913 51 27.795-14 00 22.50 L~09vC568 -99942 2C2006 12 25.64260413 51 28.243-14 00 24.79 L~09vC568 -99942 2C2006 12 25.64459413 51 28.632-14 00 26.91 L~09vC568 -99942 2C2006 12 25.64658913 51 29.049-14 00 28.99 L~09vC568 -99942 2C2006 12 25.64859613 51 29.453-14 00 31.11 L~09vC568 -99942 2C2006 12 25.65072813 51 29.887-14 00 33.30 L~09vC568 -99942 2C2006 12 25.65277913 51 30.308-14 00 35.48 L~09vC568 -99942 2C2006 12 25.65477513 51 30.727-14 00 37.66 L~09vC568 -99942 2C2006 12 26.61927413 54 51.077-14 17 22.37 L~09vC568 -99942 2C2006 12 26.62186713 54 51.617-14 17 25.10 L~09vC568 -99942 2C2006 12 26.62443413 54 52.140-14 17 27.76 L~09vC568 -99942 2C2006 12 26.62701613 54 52.676-14 17 30.47 L~09vC568 -99942 2C2006 12 26.62959313 54 53.203-14 17 33.18 L~09vC568 -99942 2C2006 12 26.63231513 54 53.784-14 17 36.02 L~09vC568 -99942 2C2006 12 26.63489013 54 54.277-14 17 38.64 L~09vC568 -99942 2C2006 12 26.63746513 54 54.814-14 17 41.38 L~09vC568 -99942 2C2006 12 26.64003713 54 55.344-14 17 44.03 L~09vC568 -99942 2C2006 12 26.64443813 54 56.257-14 17 48.70 L~09vC568 -99942 2C2006 12 26.64702413 54 56.800-14 17 51.38 L~09vC568 -99942 2C2006 12 26.64960613 54 57.317-14 17 54.00 L~09vC568 -99942 2C2006 12 26.65233913 54 57.885-14 17 56.94 L~09vC568 -99942 2C2006 12 26.65491313 54 58.410-14 17 59.59 L~09vC568 -99942 2C2006 12 26.65764213 54 58.975-14 18 02.42 L~09vC568 -99942 2C2006 12 26.66021313 54 59.492-14 18 05.09 L~09vC568 -99942 2C2006 12 26.66295113 55 00.066-14 18 08.04 L~09vC568 -99942 2C2006 12 27.61377913 58 18.687-14 34 30.21 L~09vC568 -99942 2C2006 12 27.61612413 58 19.180-14 34 32.59 L~09vC568 -99942 2C2006 12 27.61846613 58 19.669-14 34 35.08 L~09vC568 -99942 2C2006 12 27.62092113 58 20.171-14 34 37.59 L~09vC568 -99942 2C2006 12 27.62343213 58 20.692-14 34 40.16 L~09vC568 -99942 2C2006 12 27.62813013 58 21.676-14 34 45.11 L~09vC568 -99942 2C2006 12 27.63047513 58 22.157-14 34 47.55 L~09vC568 -99942 2C2006 12 27.63283013 58 22.638-14 34 49.94 L~09vC568 -99942 2C2006 12 27.63536613 58 23.164-14 34 52.56 L~09vC568 -99942 2C2006 12 27.63772213 58 23.654-14 34 55.02 L~09vC568 -99942 2C2006 12 27.64018213 58 24.160-14 34 57.58 L~09vC568 -99942 2C2006 12 27.64251713 58 24.633-14 34 59.93 L~09vC568 -99942 2C2006 12 27.64486213 58 25.128-14 35 02.41 L~09vC568 -99942 2C2006 12 27.64733813 58 25.643-14 35 05.02 L~09vC568 -99942 2C2006 12 27.64968213 58 26.118-14 35 07.34 L~09vC568 -99942 2C2006 12 27.65219913 58 26.645-14 35 10.02 L~09vC568 -99942 2C2006 12 27.65454513 58 27.136-14 35 12.46 L~09vC568 -99942 2C2006 12 27.65693913 58 27.617-14 35 14.94 L~09vC568 -99942 2C2006 12 27.65923513 58 28.080-14 35 17.27 L~09vC568 -99942 2C2006 12 27.66161613 58 28.593-14 35 19.73 L~09vC568 -99942 2C2006 12 28.59892614 01 45.532-14 51 20.18 L~09vC568 -99942 2C2006 12 28.60127214 01 45.990-14 51 22.22 L~09vC568 -99942 2C2006 12 28.60361214 01 46.474-14 51 24.86 L~09vC568 -99942 2C2006 12 28.60595614 01 46.965-14 51 27.09 L~09vC568 -99942 2C2006 12 28.60834814 01 47.466-14 51 29.59 L~09vC568 -99942 2C2006 12 28.61068214 01 47.954-14 51 31.93 L~09vC568 -99942 2C2006 12 28.61313714 01 48.465-14 51 34.53 L~09vC568 -99942 2C2006 12 28.61548314 01 48.954-14 51 36.90 L~09vC568 -99942 2C2006 12 28.61782414 01 49.441-14 51 39.29 L~09vC568 -99942 2C2006 12 28.62048314 01 49.989-14 51 42.06 L~09vC568 -99942 2C2006 12 28.62284414 01 50.480-14 51 44.43 L~09vC568 -99942 2C2006 12 28.62521914 01 50.990-14 51 46.97 L~09vC568 -99942 2C2006 12 28.62755814 01 51.480-14 51 49.37 L~09vC568 -99942 2C2006 12 28.62989814 01 51.941-14 51 51.72 L~09vC568 -99942 2C2006 12 28.63223614 01 52.447-14 51 54.12 L~09vC568 -99942 2C2006 12 28.63472114 01 52.958-14 51 56.69 L~09vC568 -99942 2C2006 12 28.63709614 01 53.453-14 51 59.27 L~09vC568 -99942 2C2006 12 28.63958114 01 53.965-14 52 01.62 L~09vC568 -99942 2C2006 12 28.64222114 01 54.514-14 52 04.38 L~09vC568 -99942 2C2006 12 28.64470914 01 55.039-14 52 06.96 L~09vC568 -99942 2C2006 12 28.64705014 01 55.531-14 52 09.35 L~09vC568 -99942 2C2006 12 28.64938714 01 55.996-14 52 11.67 L~09vC568 -99942 2C2006 12 28.65175514 01 56.494-14 52 14.11 L~09vC568 -99942 2C2006 12 28.65410114 01 57.003-14 52 16.60 L~09vC568 -99942 2C2006 12 28.65644714 01 57.472-14 52 18.98 L~09vC568 -99942 2C2006 12 28.65879714 01 57.960-14 52 21.42 L~09vC568 -99942 2C2007 01 21.58245615 32 42.616-20 42 32.51 L~09vC568 -99942 2C2007 01 21.58477315 32 43.182-20 42 34.17 L~09vC568 -99942 2C2007 01 21.58711715 32 43.754-20 42 35.81 L~09vC568 -99942 2C2007 01 21.58959315 32 44.371-20 42 37.63 L~09vC568 -99942 2C2007 01 21.59195815 32 44.938-20 42 39.26 L~09vC568 -99942 2C2007 01 21.59430315 32 45.499-20 42 40.83 L~09vC568 -99942 2C2007 01 21.59664515 32 46.078-20 42 42.56 L~09vC568 -99942 2C2007 01 21.59911315 32 46.703-20 42 44.34 L~09vC568 -99942 2C2007 01 21.60382415 32 47.848-20 42 47.67 L~09vC568 -99942 2C2007 01 21.60630415 32 48.443-20 42 49.39 L~09vC568 -99942 2C2007 01 21.60865515 32 49.033-20 42 51.06 L~09vC568 -99942 2C2007 01 21.61111115 32 49.620-20 42 52.79 L~09vC568 -99942 2C2007 01 21.61348815 32 50.198-20 42 54.45 L~09vC568 -99942 2C2007 01 21.61596315 32 50.816-20 42 56.26 L~09vC568 -99942 2C2007 01 21.61830115 32 51.395-20 42 57.88 L~09vC568 -99942 2C2007 01 21.62065315 32 51.961-20 42 59.57 L~09vC568 -99942 2C2007 01 21.62537515 32 53.108-20 43 02.86 L~09vC568 -99942 2C2007 01 21.63384715 32 55.168-20 43 08.85 L~09vC568 -99942 2C2007 01 21.63855815 32 56.312-20 43 12.14 L~09vC568 -99942 2C2007 01 21.64091415 32 56.911-20 43 13.89 L~09vC568 -99942 2C2007 01 21.64325715 32 57.478-20 43 15.48 L~09vC568 -99942 2C2007 01 21.65294215 32 59.821-20 43 22.32 L~09vC568 -99942 2C2007 01 21.65549215 33 00.470-20 43 24.16 L~09vC568 -99942 2C2007 01 21.65785015 33 01.030-20 43 25.75 L~09vC568 -99942 2C2007 01 21.66020015 33 01.605-20 43 27.43 L~09vC568 -99942 2C2007 01 21.66256215 33 02.171-20 43 29.04 L~09vC568 -99942 2C2007 01 21.66506015 33 02.793-20 43 30.82 L~09vC568 -99942 2C2007 01 21.66740615 33 03.361-20 43 32.52 L~09vC568 -99942 2C2007 01 21.66975715 33 03.947-20 43 34.16 L~09vC568 -99942 2C2007 01 22.57214015 36 47.728-20 53 51.02 L~09vC568 -99942 2C2007 01 22.57654615 36 48.815-20 53 53.82 L~09vC568 -99942 2C2007 01 22.58476015 36 50.845-20 53 59.54 L~09vC568 -99942 2C2007 01 22.58756915 36 51.544-20 54 01.48 L~09vC568 -99942 2C2007 01 22.59237415 36 52.723-20 54 04.90 L~09vC568 -99942 2C2007 01 22.59473715 36 53.296-20 54 06.42 L~09vC568 -99942 2C2007 01 22.59708115 36 53.865-20 54 07.99 L~09vC568 -99942 2C2007 01 22.59954915 36 54.479-20 54 09.82 L~09vC568 -99942 2C2007 01 22.60189015 36 55.064-20 54 11.36 L~09vC568 -99942 2C2007 01 22.60423615 36 55.637-20 54 12.96 L~09vC568 -99942 2C2007 01 22.60669315 36 56.236-20 54 14.69 L~09vC568 -99942 2C2007 01 22.60915215 36 56.845-20 54 16.36 L~09vC568 -99942 2C2007 01 22.61163715 36 57.473-20 54 18.12 L~09vC568 -99942 2C2007 01 22.61397715 36 58.034-20 54 19.83 L~09vC568 -99942 2C2007 01 22.61632415 36 58.619-20 54 21.25 L~09vC568 -99942 2C2007 01 22.61878615 36 59.210-20 54 22.97 L~09vC568 -99942 2C2007 01 22.62113415 36 59.808-20 54 24.59 L~09vC568 -99942 2C2007 01 22.62347015 37 00.364-20 54 26.20 L~09vC568 -99942 2C2007 01 22.62593415 37 00.969-20 54 27.89 L~09vC568 -99942 2C2007 01 22.62827215 37 01.551-20 54 29.50 L~09vC568 -99942 2C2007 01 22.63124215 37 02.296-20 54 31.56 L~09vC568 -99942 2C2007 01 22.63360515 37 02.858-20 54 33.24 L~09vC568 -99942 2C2007 01 22.63609015 37 03.468-20 54 34.88 L~09vC568 -99942 2C2007 01 22.63845815 37 04.044-20 54 36.49 L~09vC568 -99942 2C2007 01 22.64095315 37 04.663-20 54 38.24 L~09vC568 -99942 2C2007 01 22.64329615 37 05.241-20 54 39.79 L~09vC568 -99942 2C2007 01 22.64563215 37 05.805-20 54 41.42 L~09vC568 -99942 2C2007 01 22.64797215 37 06.399-20 54 43.05 L~09vC568 -99942 2C2007 01 22.65031215 37 06.975-20 54 44.58 L~09vC568 -99942 2C2007 01 22.65520515 37 08.177-20 54 48.01 L~09vC568 -99942 2C2007 01 22.65766615 37 08.765-20 54 49.68 L~09vC568 -99942 2C2007 01 22.66000615 37 09.346-20 54 51.23 L~09vC568 -99942 2C2007 01 22.66233915 37 09.914-20 54 52.83 L~09vC568 -99942 2C2007 01 24.57992215 45 10.267-21 15 47.20 L~09vC568 -99942 2C2007 01 24.58237315 45 10.845-21 15 48.76 L~09vC568 -99942 2C2007 01 24.58473515 45 11.459-21 15 50.79 L~09vC568 -99942 2C2007 01 24.58708115 45 12.051-21 15 52.00 L~09vC568 -99942 2C2007 01 24.58943115 45 12.639-21 15 53.62 L~09vC568 -99942 2C2007 01 24.59180315 45 13.201-21 15 55.01 L~09vC568 -99942 2C2007 01 24.59415315 45 13.810-21 15 56.62 L~09vC568 -99942 2C2007 01 24.59649815 45 14.398-21 15 58.15 L~09vC568 -99942 2C2007 01 24.59884615 45 14.981-21 15 59.67 L~09vC568 -99942 2C2007 01 24.60130815 45 15.601-21 16 01.20 L~09vC568 -99942 2C2007 01 24.60397015 45 16.258-21 16 02.96 L~09vC568 -99942 2C2007 01 24.60631615 45 16.864-21 16 04.53 L~09vC568 -99942 2C2007 01 24.60865915 45 17.437-21 16 06.03 L~09vC568 -99942 2C2007 01 24.61100715 45 18.015-21 16 07.64 L~09vC568 -99942 2C2007 01 24.61337815 45 18.617-21 16 09.04 L~09vC568 -99942 2C2007 01 24.61572015 45 19.205-21 16 10.60 L~09vC568 -99942 2C2007 01 24.61806315 45 19.787-21 16 12.11 L~09vC568 -99942 2C2007 01 24.62052215 45 20.394-21 16 13.80 L~09vC568 -99942 2C2007 01 24.62288015 45 20.996-21 16 15.28 L~09vC568 -99942 2C2007 01 24.62536915 45 21.610-21 16 16.86 L~09vC568 -99942 2C2007 01 24.62770915 45 22.184-21 16 18.37 L~09vC568 -99942 2C2007 01 24.63004715 45 22.784-21 16 19.89 L~09vC568 -99942 2C2007 01 24.63253115 45 23.400-21 16 21.47 L~09vC568 -99942 2C2007 01 24.63488415 45 23.956-21 16 22.98 L~09vC568 -99942 2C2007 01 24.63722615 45 24.576-21 16 24.46 L~09vC568 -99942 2C2007 01 24.63968615 45 25.180-21 16 26.08 L~09vC568 -99942 2C2007 01 24.64206015 45 25.765-21 16 27.61 L~09vC568 -99942 2C2007 01 24.64453715 45 26.385-21 16 29.24 L~09vC568 -99942 2C2007 01 24.64749315 45 27.120-21 16 31.13 L~09vC568 -99942 2C2007 01 24.64984515 45 27.716-21 16 32.67 L~09vD568 -99942 2C2007 01 24.65218915 45 28.295-21 16 34.14 L~09vD568 -99942 2C2007 01 24.65453715 45 28.875-21 16 35.68 L~09vD568 -99942 2C2007 01 24.65700115 45 29.476-21 16 37.24 L~09vD568 -99942 2C2007 01 24.65933815 45 30.069-21 16 38.76 L~09vD568 -99942 2C2007 01 24.66186915 45 30.702-21 16 40.35 L~09vD568 -99942 2C2007 01 24.66421415 45 31.282-21 16 41.89 L~09vD568 -99942 2C2007 01 24.66673715 45 31.913-21 16 43.52 L~09vD568 -99942 2C2007 01 24.66915915 45 32.521-21 16 45.04 L~09vD568 -99942 2C2007 01 25.57819315 49 22.787-21 26 10.76 L~09vD568 -99942 2C2007 01 25.58054715 49 23.382-21 26 12.24 L~09vD568 -99942 2C2007 01 25.58288715 49 24.005-21 26 13.93 L~09vD568 -99942 2C2007 01 25.58538115 49 24.619-21 26 15.27 L~09vD568 -99942 2C2007 01 25.58871815 49 25.448-21 26 17.35 L~09vD568 -99942 2C2007 01 25.59107515 49 26.056-21 26 18.94 L~09vD568 -99942 2C2007 01 25.59341915 49 26.638-21 26 20.34 L~09vD568 -99942 2C2007 01 25.59578215 49 27.232-21 26 21.81 L~09vD568 -99942 2C2007 01 25.59814815 49 27.836-21 26 23.28 L~09vD568 -99942 2C2007 01 25.60048815 49 28.426-21 26 24.78 L~09vD568 -99942 2C2007 01 25.60298015 49 29.040-21 26 26.32 L~09vD568 -99942 2C2007 01 25.60533815 49 29.635-21 26 27.79 L~09vD568 -99942 2C2007 01 25.60768815 49 30.217-21 26 29.23 L~09vD568 -99942 2C2007 01 25.61044415 49 30.921-21 26 30.98 L~09vD568 -99942 2C2007 01 25.61280315 49 31.515-21 26 32.50 L~09vD568 -99942 2C2007 01 25.61514615 49 32.099-21 26 33.92 L~09vD568 -99942 2C2007 01 25.61763015 49 32.743-21 26 35.57 L~09vD568 -99942 2C2007 01 25.62004115 49 33.333-21 26 37.04 L~09vD568 -99942 2C2007 01 25.62238915 49 33.920-21 26 38.54 L~09vD568 -99942 2C2007 01 25.62486615 49 34.551-21 26 40.09 L~09vD568 -99942 2C2007 01 25.62721115 49 35.141-21 26 41.54 L~09vD568 -99942 2C2007 01 25.62955615 49 35.721-21 26 42.96 L~09vD568 -99942 2C2007 01 25.63218615 49 36.378-21 26 44.65 L~09vD568 -99942 2C2007 01 25.63452915 49 36.980-21 26 46.10 L~09vD568 -99942 2C2007 01 25.63686715 49 37.574-21 26 47.55 L~09vD568 -99942 2C2007 01 25.63935415 49 38.186-21 26 49.11 L~09vD568 -99942 2C2007 01 25.64171915 49 38.758-21 26 50.54 L~09vD568 -99942 2C2007 01 25.64421215 49 39.407-21 26 52.14 L~09vD568 -99942 2C2007 01 25.64655615 49 39.998-21 26 53.60 L~09vD568 -99942 2C2007 01 25.64907615 49 40.623-21 26 54.91 L~09vD568 -99942 2C2007 03 09.65417619 16 36.695-21 11 06.90 L~09vD568 -99942 2C2007 03 09.65641119 16 37.371-21 11 04.96 L~09vD568 -99942 2C2007 12 13.66071314 26 35.206-15 26 51.52 L~09vD568 -99942 2C2008 01 06.63895716 03 51.245-20 51 51.34 L~09vD568 -99942 2C2008 01 06.64603616 03 53.080-20 51 55.60 L~09vD568 -99942 2C2008 01 06.64949016 03 53.986-20 51 57.69 L~09vD568 -99942 2C2008 01 06.65292016 03 54.887-20 51 59.83 L~09vD568 -99942 2C2008 01 06.65654416 03 55.801-20 52 01.94 L~09vD568 -99942 2C2008 01 06.66000516 03 56.765-20 52 04.16 L~09vD568 -99942 2C2008 01 06.66349216 03 57.618-20 52 06.04 L~09vD568 -99942 2C2008 01 07.64179316 08 14.721-21 01 32.09 L~09vD568 -99942 2C2008 01 07.64518616 08 15.608-21 01 33.99 L~09vD568 -99942 2C2008 01 07.65285816 08 17.617-21 01 38.46 L~09vD568 -99942 2C2008 01 07.65670716 08 18.608-21 01 40.57 L~09vD568 -99942 2C2008 01 08.65407416 12 42.234-21 10 54.03 L~09vD568 -99942 2C2008 01 08.65691716 12 42.968-21 10 55.80 L~09vD568 -99942 2C2008 01 08.65923516 12 43.584-21 10 56.95 L~09vD568 -99942 2C2008 01 08.66382416 12 44.803-21 10 59.64 L~09vD568 -99942 2C2008 01 08.66575916 12 45.323-21 11 00.64 L~09vD568 -99942 2C2008 01 09.64923016 17 06.855-21 19 43.21 L~09vD568 -99942 2C2008 01 09.65116616 17 07.315-21 19 44.16 L~09vD568 -99942 2C2008 01 09.65314116 17 07.868-21 19 45.05 L~09vD568 -99942 2C2008 01 09.65508216 17 08.370-21 19 46.22 L~09vD568 -99942 2C2008 01 09.65908916 17 09.415-21 19 48.28 L~09vD568 -99942 2C2008 01 09.66102716 17 09.953-21 19 49.41 L~09vD568 -99942 2C2008 01 09.66312516 17 10.506-21 19 50.39 L~09vD568 -99942 2C2008 01 09.66508816 17 11.010-21 19 51.46 L~09vD568 +99942 'C2004 06 19.17015009 44 29.677+13 18 50.67 L~09vB695 +99942 'C2004 06 19.17486109 44 30.604+13 18 46.81 L~09vB695 +99942 'C2004 06 19.17967609 44 31.507+13 18 42.91 L~09vB695 +99942 'C2004 06 20.15951409 47 41.116+13 05 24.49 L~09vB695 +99942 'C2004 06 20.16431709 47 42.006+13 05 20.50 L~09vB695 +99942 'C2004 06 20.16906309 47 42.926+13 05 16.74 L~09vB695 +99942 'C2005 07 09.17600210 34 38.149+16 12 41.50 L~09vB695 +99942 'C2005 07 09.18080710 34 38.288+16 12 42.68 L~09vB695 +99942 'C2005 07 10.17554310 35 10.909+16 18 25.82 L~09vB695 +99942 'C2005 07 10.17819210 35 10.983+16 18 26.48 L~09vB695 +99942 'C2005 07 11.16972710 35 36.698+16 24 46.68 L~09vB695 +99942 2C2005 09 04.63519408 25 00.085+22 18 13.02 L~09vB568 +99942 2C2005 09 04.63627008 25 00.075+22 18 12.36 L~09vB568 +99942 2C2005 12 31.64597612 46 28.407-11 49 33.02 L~09vB568 +99942 2C2005 12 31.64713112 46 28.583-11 49 34.23 L~09vB568 +99942 2C2005 12 31.64800212 46 28.708-11 49 35.16 L~09vB568 +99942 2C2006 03 05.54636616 20 49.786-26 34 29.32 L~09vB568 +99942 2C2006 03 05.61052316 21 07.957-26 34 51.45 L~09vB568 +99942 2C2006 03 05.65266816 21 19.828-26 35 04.75 L~09vB568 +99942 2C2006 03 06.51985316 25 39.350-26 39 07.23 L~09vB568 +99942 2C2006 03 06.52154416 25 39.838-26 39 07.85 L~09vB568 +99942 2C2006 03 06.52319016 25 40.319-26 39 08.38 L~09vB568 +99942 2C2006 03 06.52483716 25 40.802-26 39 08.75 L~09vB568 +99942 2C2006 03 06.52649816 25 41.288-26 39 09.42 L~09vB568 +99942 2C2006 03 06.53152916 25 42.744-26 39 11.09 L~09vB568 +99942 2C2006 03 06.53317516 25 43.230-26 39 11.64 L~09vB568 +99942 2C2006 03 06.53785116 25 44.576-26 39 13.17 L~09vB568 +99942 2C2006 03 06.53950516 25 45.058-26 39 13.71 L~09vB568 +99942 2C2006 03 06.54114016 25 45.528-26 39 14.25 L~09vB568 +99942 2C2006 03 06.54279516 25 46.018-26 39 14.75 L~09vB568 +99942 2C2006 03 06.54460416 25 46.542-26 39 15.35 L~09vB568 +99942 2C2006 03 06.54622816 25 47.020-26 39 15.82 L~09vB568 +99942 2C2006 03 06.54788716 25 47.487-26 39 16.37 L~09vB568 +99942 2C2006 03 06.54963916 25 48.001-26 39 16.97 L~09vB568 +99942 2C2006 03 06.55128516 25 48.473-26 39 17.49 L~09vB568 +99942 2C2006 03 06.55294416 25 48.954-26 39 18.02 L~09vB568 +99942 2C2006 03 06.58062516 25 56.956-26 39 26.69 L~09vB568 +99942 2C2006 03 06.58226716 25 57.429-26 39 27.19 L~09vB568 +99942 2C2006 03 06.58390316 25 57.889-26 39 27.56 L~09vB568 +99942 2C2006 03 06.58565516 25 58.403-26 39 28.25 L~09vB568 +99942 2C2006 03 06.58729516 25 58.884-26 39 28.74 L~09vB568 +99942 2C2006 03 06.58894616 25 59.356-26 39 29.24 L~09vB568 +99942 2C2006 03 06.59071316 25 59.860-26 39 29.79 L~09vB568 +99942 2C2006 03 06.59240616 26 00.342-26 39 30.29 L~09vB568 +99942 2C2006 03 06.59416916 26 00.854-26 39 30.79 L~09vB568 +99942 2C2006 03 06.59581316 26 01.332-26 39 31.30 L~09vB568 +99942 2C2006 03 06.59986316 26 02.494-26 39 32.45 L~09vB568 +99942 2C2006 03 06.60160616 26 02.993-26 39 33.01 L~09vB568 +99942 2C2006 03 06.60323516 26 03.457-26 39 33.48 L~09vB568 +99942 2C2006 03 06.60488216 26 03.930-26 39 34.00 L~09vB568 +99942 2C2006 03 06.60655416 26 04.414-26 39 34.45 L~09vB568 +99942 2C2006 03 06.60819916 26 04.891-26 39 34.94 L~09vB568 +99942 2C2006 03 06.60994916 26 05.388-26 39 35.44 L~09vB568 +99942 2C2006 03 06.61161916 26 05.870-26 39 35.93 L~09vB568 +99942 2C2006 03 06.61340316 26 06.381-26 39 36.46 L~09vB568 +99942 2C2006 03 06.61522116 26 06.900-26 39 36.96 L~09vB568 +99942 2C2006 03 06.61779416 26 07.648-26 39 37.74 L~09vB568 +99942 2C2006 03 06.61944816 26 08.129-26 39 38.22 L~09vB568 +99942 2C2006 03 06.62108316 26 08.593-26 39 38.68 L~09vB568 +99942 2C2006 03 06.62287816 26 09.105-26 39 39.17 L~09vB568 +99942 2C2006 03 06.62453816 26 09.584-26 39 39.65 L~09vB568 +99942 2C2006 03 06.62634316 26 10.112-26 39 40.15 L~09vB568 +99942 2C2006 03 06.62962316 26 11.039-26 39 41.09 L~09vB568 +99942 2C2006 03 06.63137516 26 11.530-26 39 41.57 L~09vB568 +99942 2C2006 03 06.63303116 26 12.016-26 39 42.05 L~09vB568 +99942 2C2006 03 06.63501716 26 12.589-26 39 42.58 L~09vB568 +99942 2C2006 03 06.63831016 26 13.532-26 39 43.51 L~09vB568 +99942 2C2006 03 06.63998416 26 14.033-26 39 43.93 L~09vB568 +99942 2C2006 03 06.64177816 26 14.532-26 39 44.44 L~09vB568 +99942 2C2006 03 06.64342816 26 15.007-26 39 44.91 L~09vB568 +99942 2C2006 03 06.64522616 26 15.513-26 39 45.40 L~09vB568 +99942 2C2006 03 06.64689116 26 16.000-26 39 45.85 L~09vB568 +99942 2C2006 03 06.64869616 26 16.534-26 39 46.31 L~09vB568 +99942 2C2006 03 06.65033416 26 16.985-26 39 46.76 L~09vB568 +99942 2C2006 03 08.52450916 35 51.633-26 46 44.58 L~09vB568 +99942 2C2006 03 08.52614416 35 52.139-26 46 45.02 L~09vB568 +99942 2C2006 03 08.52778416 35 52.632-26 46 45.44 L~09vB568 +99942 2C2006 03 08.52940616 35 53.122-26 46 45.81 L~09vB568 +99942 2C2006 03 08.53118916 35 53.668-26 46 46.23 L~09vB568 +99942 2C2006 03 08.53282516 35 54.145-26 46 46.74 L~09vB568 +99942 2C2006 03 08.53446116 35 54.645-26 46 47.05 L~09vB568 +99942 2C2006 03 08.53622516 35 55.161-26 46 47.51 L~09vB568 +99942 2C2006 03 08.53952316 35 56.166-26 46 48.34 L~09vB568 +99942 2C2006 03 08.54821816 35 58.785-26 46 50.43 L~09vB568 +99942 2C2006 03 08.54987016 35 59.291-26 46 50.85 L~09vB568 +99942 2C2006 03 08.55150916 35 59.779-26 46 51.19 L~09vB568 +99942 2C2006 03 08.55327516 36 00.314-26 46 51.64 L~09vB568 +99942 2C2006 03 08.55494116 36 00.797-26 46 52.06 L~09vB568 +99942 2C2006 03 08.55657116 36 01.305-26 46 52.45 L~09vB568 +99942 2C2006 03 08.55820316 36 01.809-26 46 52.76 L~09vB568 +99942 2C2006 03 08.55999116 36 02.337-26 46 53.31 L~09vB568 +99942 2C2006 03 08.56165316 36 02.824-26 46 53.65 L~09vB568 +99942 2C2006 03 08.56331116 36 03.321-26 46 54.00 L~09vB568 +99942 2C2006 03 08.56529216 36 03.925-26 46 54.53 L~09vB568 +99942 2C2006 03 08.56705816 36 04.447-26 46 54.94 L~09vB568 +99942 2C2006 03 08.56870116 36 04.934-26 46 55.29 L~09vB568 +99942 2C2006 03 08.57034116 36 05.423-26 46 55.67 L~09vB568 +99942 2C2006 03 08.57210416 36 05.964-26 46 56.10 L~09vB568 +99942 2C2006 03 08.57374816 36 06.447-26 46 56.43 L~09vB568 +99942 2C2006 03 08.57878216 36 07.950-26 46 57.62 L~09vB568 +99942 2C2006 03 08.58043616 36 08.453-26 46 57.97 L~09vB568 +99942 2C2006 03 08.59506416 36 12.824-26 47 01.24 L~09vB568 +99942 2C2006 03 08.59679916 36 13.342-26 47 01.59 L~09vB568 +99942 2C2006 03 08.59842816 36 13.834-26 47 01.97 L~09vB568 +99942 2C2006 03 08.60007616 36 14.327-26 47 02.20 L~09vB568 +99942 2C2006 03 08.60176516 36 14.819-26 47 02.62 L~09vB568 +99942 2C2006 03 08.60342016 36 15.335-26 47 03.00 L~09vB568 +99942 2C2006 03 08.60506016 36 15.804-26 47 03.30 L~09vB568 +99942 2C2006 03 08.60672516 36 16.308-26 47 03.66 L~09vB568 +99942 2C2006 03 08.60840016 36 16.812-26 47 04.07 L~09vB568 +99942 2C2006 03 08.61019116 36 17.347-26 47 04.43 L~09vB568 +99942 2C2006 03 08.61180216 36 17.821-26 47 04.73 L~09vB568 +99942 2C2006 03 08.61356016 36 18.338-26 47 05.15 L~09vB568 +99942 2C2006 03 08.61522616 36 18.848-26 47 05.46 L~09vB568 +99942 2C2006 03 08.61702416 36 19.384-26 47 05.80 L~09vB568 +99942 2C2006 03 08.61880916 36 19.911-26 47 06.18 L~09vB568 +99942 2C2006 03 08.62044116 36 20.397-26 47 06.50 L~09vB568 +99942 2C2006 03 08.62209616 36 20.893-26 47 06.83 L~09vB568 +99942 2C2006 03 08.62373616 36 21.391-26 47 07.18 L~09vB568 +99942 2C2006 03 08.62551916 36 21.915-26 47 07.56 L~09vB568 +99942 2C2006 03 08.62716816 36 22.403-26 47 07.90 L~09vB568 +99942 2C2006 03 08.62914916 36 23.003-26 47 08.29 L~09vB568 +99942 2C2006 03 08.63083816 36 23.503-26 47 08.58 L~09vB568 +99942 2C2006 03 08.63248116 36 23.992-26 47 08.94 L~09vB568 +99942 2C2006 03 08.63410316 36 24.477-26 47 09.24 L~09vB568 +99942 2C2006 03 08.63588516 36 24.997-26 47 09.59 L~09vB568 +99942 2C2006 03 08.63752916 36 25.500-26 47 09.91 L~09vB568 +99942 2C2006 03 08.63917116 36 25.991-26 47 10.23 L~09vB568 +99942 2C2006 03 08.64083116 36 26.480-26 47 10.54 L~09vB568 +99942 2C2006 03 08.64263816 36 27.008-26 47 10.89 L~09vB568 +99942 2C2006 03 08.64430016 36 27.506-26 47 11.22 L~09vB568 +99942 2C2006 03 08.64589016 36 27.988-26 47 11.49 L~09vB568 +99942 2C2006 03 08.64751516 36 28.476-26 47 11.82 L~09vB568 +99942 2C2006 03 08.64930316 36 29.008-26 47 12.13 L~09vB568 +99942 2C2006 03 08.65095316 36 29.492-26 47 12.45 L~09vB568 +99942 2C2006 03 08.66103116 36 32.496-26 47 14.31 L~09vB568 +99942 2C2006 05 01.62736922 43 36.580-01 20 46.01 L~09vB568 +99942 2C2006 05 01.62821822 43 36.869-01 20 44.02 L~09vB568 +99942 2C2006 06 01.60681201 12 41.522+14 14 31.91 L~09vB568 +99942 2C2006 06 01.60868801 12 41.959+14 14 34.24 L~09vB568 +99942 2C2006 06 02.59935901 16 48.755+14 34 20.07 L~09vB568 +99942 2C2006 06 02.60078001 16 49.108+14 34 21.72 L~09vB568 +99942 2C2006 06 02.60224201 16 49.478+14 34 23.59 L~09vB568 +99942 2C2006 07 27.61254105 06 37.958+23 53 27.72 L~09vB568 +99942 2C2006 07 27.61447305 06 38.465+23 53 27.83 L~09vB568 +99942 2C2006 08 15.61852106 26 52.404+22 57 47.52 L~09vB568 +99942 2C2006 08 15.62233206 26 53.348+22 57 46.02 L~09vB568 +99942 2C2006 08 16.62183606 31 00.059+22 51 14.54 L~09vB568 +99942 2C2006 08 16.62441906 31 00.629+22 51 13.69 L~09vB568 +99942 2C2006 08 16.62695406 31 01.254+22 51 12.76 L~09vB568 +99942 2C2006 09 04.59915907 45 57.632+19 48 13.43 L~09vB568 +99942 2C2006 09 04.60174207 45 58.282+19 48 11.30 L~09vB568 +99942 2C2006 09 04.60702707 45 59.441+19 48 07.57 L~09vB568 +99942 2C2006 09 04.60960407 46 00.032+19 48 05.65 L~09vB568 +99942 2C2006 09 04.61217807 46 00.596+19 48 03.81 L~09vC568 +99942 2C2006 09 04.61475007 46 01.189+19 48 01.98 L~09vC568 +99942 2C2006 09 04.61733207 46 01.771+19 48 00.12 L~09vC568 +99942 2C2006 09 04.61991607 46 02.330+19 47 58.33 L~09vC568 +99942 2C2006 09 04.62259307 46 02.963+19 47 56.27 L~09vC568 +99942 2C2006 09 04.62517107 46 03.533+19 47 54.35 L~09vC568 +99942 2C2006 09 04.62774407 46 04.120+19 47 52.46 L~09vC568 +99942 2C2006 10 25.59993210 38 53.805+05 37 27.51 L~09vC568 +99942 2C2006 10 25.60369210 38 54.499+05 37 23.28 L~09vC568 +99942 2C2006 10 25.60744010 38 55.203+05 37 18.89 L~09vC568 +99942 2C2006 10 25.61132210 38 55.912+05 37 14.36 L~09vC568 +99942 2C2006 10 25.61506310 38 56.601+05 37 10.09 L~09vC568 +99942 2C2006 10 25.61879910 38 57.275+05 37 05.78 L~09vC568 +99942 2C2006 10 25.62267810 38 58.014+05 37 01.23 L~09vC568 +99942 2C2006 10 25.62640510 38 58.696+05 36 56.87 L~09vC568 +99942 2C2006 10 25.63014810 38 59.377+05 36 52.66 L~09vC568 +99942 2C2006 10 25.63403010 39 00.098+05 36 48.23 L~09vC568 +99942 2C2006 10 25.63779510 39 00.816+05 36 43.85 L~09vC568 +99942 2C2006 11 28.59593412 23 24.533-05 33 25.55 L~09vC568 +99942 2C2006 11 28.59911212 23 25.116-05 33 29.23 L~09vC568 +99942 2C2006 11 28.60196112 23 25.630-05 33 32.60 L~09vC568 +99942 2C2006 11 28.60444112 23 26.110-05 33 35.60 L~09vC568 +99942 2C2006 11 28.60694712 23 26.572-05 33 38.57 L~09vC568 +99942 2C2006 11 28.60930612 23 27.008-05 33 41.28 L~09vC568 +99942 2C2006 11 28.61175812 23 27.455-05 33 44.13 L~09vC568 +99942 2C2006 11 28.61410412 23 27.900-05 33 47.02 L~09vC568 +99942 2C2006 11 28.61644012 23 28.333-05 33 49.76 L~09vC568 +99942 2C2006 11 28.61881912 23 28.750-05 33 52.52 L~09vC568 +99942 2C2006 11 28.62122512 23 29.200-05 33 55.26 L~09vC568 +99942 2C2006 11 28.62509412 23 29.918-05 33 59.86 L~09vC568 +99942 2C2006 11 28.62744612 23 30.356-05 34 02.67 L~09vC568 +99942 2C2006 11 28.62980412 23 30.783-05 34 05.39 L~09vC568 +99942 2C2006 11 28.63229412 23 31.243-05 34 08.35 L~09vC568 +99942 2C2006 11 28.63463812 23 31.694-05 34 11.18 L~09vC568 +99942 2C2006 11 28.63699212 23 32.122-05 34 13.96 L~09vC568 +99942 2C2006 11 28.63939612 23 32.559-05 34 16.72 L~09vC568 +99942 2C2006 11 28.64191212 23 33.023-05 34 19.79 L~09vC568 +99942 2C2006 11 28.64780312 23 34.102-05 34 26.64 L~09vC568 +99942 2C2006 12 25.61583813 51 22.763-13 59 56.70 L~09vC568 +99942 2C2006 12 25.61784113 51 23.174-13 59 58.77 L~09vC568 +99942 2C2006 12 25.61998413 51 23.614-14 00 01.00 L~09vC568 +99942 2C2006 12 25.62212713 51 24.048-14 00 03.19 L~09vC568 +99942 2C2006 12 25.62426613 51 24.483-14 00 05.46 L~09vC568 +99942 2C2006 12 25.62626013 51 24.897-14 00 07.57 L~09vC568 +99942 2C2006 12 25.62826013 51 25.303-14 00 09.63 L~09vC568 +99942 2C2006 12 25.63026913 51 25.727-14 00 11.91 L~09vC568 +99942 2C2006 12 25.63226613 51 26.111-14 00 13.98 L~09vC568 +99942 2C2006 12 25.63432513 51 26.550-14 00 16.10 L~09vC568 +99942 2C2006 12 25.63633713 51 26.944-14 00 18.32 L~09vC568 +99942 2C2006 12 25.63845413 51 27.397-14 00 20.54 L~09vC568 +99942 2C2006 12 25.64046913 51 27.795-14 00 22.50 L~09vC568 +99942 2C2006 12 25.64260413 51 28.243-14 00 24.79 L~09vC568 +99942 2C2006 12 25.64459413 51 28.632-14 00 26.91 L~09vC568 +99942 2C2006 12 25.64658913 51 29.049-14 00 28.99 L~09vC568 +99942 2C2006 12 25.64859613 51 29.453-14 00 31.11 L~09vC568 +99942 2C2006 12 25.65072813 51 29.887-14 00 33.30 L~09vC568 +99942 2C2006 12 25.65277913 51 30.308-14 00 35.48 L~09vC568 +99942 2C2006 12 25.65477513 51 30.727-14 00 37.66 L~09vC568 +99942 2C2006 12 26.61927413 54 51.077-14 17 22.37 L~09vC568 +99942 2C2006 12 26.62186713 54 51.617-14 17 25.10 L~09vC568 +99942 2C2006 12 26.62443413 54 52.140-14 17 27.76 L~09vC568 +99942 2C2006 12 26.62701613 54 52.676-14 17 30.47 L~09vC568 +99942 2C2006 12 26.62959313 54 53.203-14 17 33.18 L~09vC568 +99942 2C2006 12 26.63231513 54 53.784-14 17 36.02 L~09vC568 +99942 2C2006 12 26.63489013 54 54.277-14 17 38.64 L~09vC568 +99942 2C2006 12 26.63746513 54 54.814-14 17 41.38 L~09vC568 +99942 2C2006 12 26.64003713 54 55.344-14 17 44.03 L~09vC568 +99942 2C2006 12 26.64443813 54 56.257-14 17 48.70 L~09vC568 +99942 2C2006 12 26.64702413 54 56.800-14 17 51.38 L~09vC568 +99942 2C2006 12 26.64960613 54 57.317-14 17 54.00 L~09vC568 +99942 2C2006 12 26.65233913 54 57.885-14 17 56.94 L~09vC568 +99942 2C2006 12 26.65491313 54 58.410-14 17 59.59 L~09vC568 +99942 2C2006 12 26.65764213 54 58.975-14 18 02.42 L~09vC568 +99942 2C2006 12 26.66021313 54 59.492-14 18 05.09 L~09vC568 +99942 2C2006 12 26.66295113 55 00.066-14 18 08.04 L~09vC568 +99942 2C2006 12 27.61377913 58 18.687-14 34 30.21 L~09vC568 +99942 2C2006 12 27.61612413 58 19.180-14 34 32.59 L~09vC568 +99942 2C2006 12 27.61846613 58 19.669-14 34 35.08 L~09vC568 +99942 2C2006 12 27.62092113 58 20.171-14 34 37.59 L~09vC568 +99942 2C2006 12 27.62343213 58 20.692-14 34 40.16 L~09vC568 +99942 2C2006 12 27.62813013 58 21.676-14 34 45.11 L~09vC568 +99942 2C2006 12 27.63047513 58 22.157-14 34 47.55 L~09vC568 +99942 2C2006 12 27.63283013 58 22.638-14 34 49.94 L~09vC568 +99942 2C2006 12 27.63536613 58 23.164-14 34 52.56 L~09vC568 +99942 2C2006 12 27.63772213 58 23.654-14 34 55.02 L~09vC568 +99942 2C2006 12 27.64018213 58 24.160-14 34 57.58 L~09vC568 +99942 2C2006 12 27.64251713 58 24.633-14 34 59.93 L~09vC568 +99942 2C2006 12 27.64486213 58 25.128-14 35 02.41 L~09vC568 +99942 2C2006 12 27.64733813 58 25.643-14 35 05.02 L~09vC568 +99942 2C2006 12 27.64968213 58 26.118-14 35 07.34 L~09vC568 +99942 2C2006 12 27.65219913 58 26.645-14 35 10.02 L~09vC568 +99942 2C2006 12 27.65454513 58 27.136-14 35 12.46 L~09vC568 +99942 2C2006 12 27.65693913 58 27.617-14 35 14.94 L~09vC568 +99942 2C2006 12 27.65923513 58 28.080-14 35 17.27 L~09vC568 +99942 2C2006 12 27.66161613 58 28.593-14 35 19.73 L~09vC568 +99942 2C2006 12 28.59892614 01 45.532-14 51 20.18 L~09vC568 +99942 2C2006 12 28.60127214 01 45.990-14 51 22.22 L~09vC568 +99942 2C2006 12 28.60361214 01 46.474-14 51 24.86 L~09vC568 +99942 2C2006 12 28.60595614 01 46.965-14 51 27.09 L~09vC568 +99942 2C2006 12 28.60834814 01 47.466-14 51 29.59 L~09vC568 +99942 2C2006 12 28.61068214 01 47.954-14 51 31.93 L~09vC568 +99942 2C2006 12 28.61313714 01 48.465-14 51 34.53 L~09vC568 +99942 2C2006 12 28.61548314 01 48.954-14 51 36.90 L~09vC568 +99942 2C2006 12 28.61782414 01 49.441-14 51 39.29 L~09vC568 +99942 2C2006 12 28.62048314 01 49.989-14 51 42.06 L~09vC568 +99942 2C2006 12 28.62284414 01 50.480-14 51 44.43 L~09vC568 +99942 2C2006 12 28.62521914 01 50.990-14 51 46.97 L~09vC568 +99942 2C2006 12 28.62755814 01 51.480-14 51 49.37 L~09vC568 +99942 2C2006 12 28.62989814 01 51.941-14 51 51.72 L~09vC568 +99942 2C2006 12 28.63223614 01 52.447-14 51 54.12 L~09vC568 +99942 2C2006 12 28.63472114 01 52.958-14 51 56.69 L~09vC568 +99942 2C2006 12 28.63709614 01 53.453-14 51 59.27 L~09vC568 +99942 2C2006 12 28.63958114 01 53.965-14 52 01.62 L~09vC568 +99942 2C2006 12 28.64222114 01 54.514-14 52 04.38 L~09vC568 +99942 2C2006 12 28.64470914 01 55.039-14 52 06.96 L~09vC568 +99942 2C2006 12 28.64705014 01 55.531-14 52 09.35 L~09vC568 +99942 2C2006 12 28.64938714 01 55.996-14 52 11.67 L~09vC568 +99942 2C2006 12 28.65175514 01 56.494-14 52 14.11 L~09vC568 +99942 2C2006 12 28.65410114 01 57.003-14 52 16.60 L~09vC568 +99942 2C2006 12 28.65644714 01 57.472-14 52 18.98 L~09vC568 +99942 2C2006 12 28.65879714 01 57.960-14 52 21.42 L~09vC568 +99942 2C2007 01 21.58245615 32 42.616-20 42 32.51 L~09vC568 +99942 2C2007 01 21.58477315 32 43.182-20 42 34.17 L~09vC568 +99942 2C2007 01 21.58711715 32 43.754-20 42 35.81 L~09vC568 +99942 2C2007 01 21.58959315 32 44.371-20 42 37.63 L~09vC568 +99942 2C2007 01 21.59195815 32 44.938-20 42 39.26 L~09vC568 +99942 2C2007 01 21.59430315 32 45.499-20 42 40.83 L~09vC568 +99942 2C2007 01 21.59664515 32 46.078-20 42 42.56 L~09vC568 +99942 2C2007 01 21.59911315 32 46.703-20 42 44.34 L~09vC568 +99942 2C2007 01 21.60382415 32 47.848-20 42 47.67 L~09vC568 +99942 2C2007 01 21.60630415 32 48.443-20 42 49.39 L~09vC568 +99942 2C2007 01 21.60865515 32 49.033-20 42 51.06 L~09vC568 +99942 2C2007 01 21.61111115 32 49.620-20 42 52.79 L~09vC568 +99942 2C2007 01 21.61348815 32 50.198-20 42 54.45 L~09vC568 +99942 2C2007 01 21.61596315 32 50.816-20 42 56.26 L~09vC568 +99942 2C2007 01 21.61830115 32 51.395-20 42 57.88 L~09vC568 +99942 2C2007 01 21.62065315 32 51.961-20 42 59.57 L~09vC568 +99942 2C2007 01 21.62537515 32 53.108-20 43 02.86 L~09vC568 +99942 2C2007 01 21.63384715 32 55.168-20 43 08.85 L~09vC568 +99942 2C2007 01 21.63855815 32 56.312-20 43 12.14 L~09vC568 +99942 2C2007 01 21.64091415 32 56.911-20 43 13.89 L~09vC568 +99942 2C2007 01 21.64325715 32 57.478-20 43 15.48 L~09vC568 +99942 2C2007 01 21.65294215 32 59.821-20 43 22.32 L~09vC568 +99942 2C2007 01 21.65549215 33 00.470-20 43 24.16 L~09vC568 +99942 2C2007 01 21.65785015 33 01.030-20 43 25.75 L~09vC568 +99942 2C2007 01 21.66020015 33 01.605-20 43 27.43 L~09vC568 +99942 2C2007 01 21.66256215 33 02.171-20 43 29.04 L~09vC568 +99942 2C2007 01 21.66506015 33 02.793-20 43 30.82 L~09vC568 +99942 2C2007 01 21.66740615 33 03.361-20 43 32.52 L~09vC568 +99942 2C2007 01 21.66975715 33 03.947-20 43 34.16 L~09vC568 +99942 2C2007 01 22.57214015 36 47.728-20 53 51.02 L~09vC568 +99942 2C2007 01 22.57654615 36 48.815-20 53 53.82 L~09vC568 +99942 2C2007 01 22.58476015 36 50.845-20 53 59.54 L~09vC568 +99942 2C2007 01 22.58756915 36 51.544-20 54 01.48 L~09vC568 +99942 2C2007 01 22.59237415 36 52.723-20 54 04.90 L~09vC568 +99942 2C2007 01 22.59473715 36 53.296-20 54 06.42 L~09vC568 +99942 2C2007 01 22.59708115 36 53.865-20 54 07.99 L~09vC568 +99942 2C2007 01 22.59954915 36 54.479-20 54 09.82 L~09vC568 +99942 2C2007 01 22.60189015 36 55.064-20 54 11.36 L~09vC568 +99942 2C2007 01 22.60423615 36 55.637-20 54 12.96 L~09vC568 +99942 2C2007 01 22.60669315 36 56.236-20 54 14.69 L~09vC568 +99942 2C2007 01 22.60915215 36 56.845-20 54 16.36 L~09vC568 +99942 2C2007 01 22.61163715 36 57.473-20 54 18.12 L~09vC568 +99942 2C2007 01 22.61397715 36 58.034-20 54 19.83 L~09vC568 +99942 2C2007 01 22.61632415 36 58.619-20 54 21.25 L~09vC568 +99942 2C2007 01 22.61878615 36 59.210-20 54 22.97 L~09vC568 +99942 2C2007 01 22.62113415 36 59.808-20 54 24.59 L~09vC568 +99942 2C2007 01 22.62347015 37 00.364-20 54 26.20 L~09vC568 +99942 2C2007 01 22.62593415 37 00.969-20 54 27.89 L~09vC568 +99942 2C2007 01 22.62827215 37 01.551-20 54 29.50 L~09vC568 +99942 2C2007 01 22.63124215 37 02.296-20 54 31.56 L~09vC568 +99942 2C2007 01 22.63360515 37 02.858-20 54 33.24 L~09vC568 +99942 2C2007 01 22.63609015 37 03.468-20 54 34.88 L~09vC568 +99942 2C2007 01 22.63845815 37 04.044-20 54 36.49 L~09vC568 +99942 2C2007 01 22.64095315 37 04.663-20 54 38.24 L~09vC568 +99942 2C2007 01 22.64329615 37 05.241-20 54 39.79 L~09vC568 +99942 2C2007 01 22.64563215 37 05.805-20 54 41.42 L~09vC568 +99942 2C2007 01 22.64797215 37 06.399-20 54 43.05 L~09vC568 +99942 2C2007 01 22.65031215 37 06.975-20 54 44.58 L~09vC568 +99942 2C2007 01 22.65520515 37 08.177-20 54 48.01 L~09vC568 +99942 2C2007 01 22.65766615 37 08.765-20 54 49.68 L~09vC568 +99942 2C2007 01 22.66000615 37 09.346-20 54 51.23 L~09vC568 +99942 2C2007 01 22.66233915 37 09.914-20 54 52.83 L~09vC568 +99942 2C2007 01 24.57992215 45 10.267-21 15 47.20 L~09vC568 +99942 2C2007 01 24.58237315 45 10.845-21 15 48.76 L~09vC568 +99942 2C2007 01 24.58473515 45 11.459-21 15 50.79 L~09vC568 +99942 2C2007 01 24.58708115 45 12.051-21 15 52.00 L~09vC568 +99942 2C2007 01 24.58943115 45 12.639-21 15 53.62 L~09vC568 +99942 2C2007 01 24.59180315 45 13.201-21 15 55.01 L~09vC568 +99942 2C2007 01 24.59415315 45 13.810-21 15 56.62 L~09vC568 +99942 2C2007 01 24.59649815 45 14.398-21 15 58.15 L~09vC568 +99942 2C2007 01 24.59884615 45 14.981-21 15 59.67 L~09vC568 +99942 2C2007 01 24.60130815 45 15.601-21 16 01.20 L~09vC568 +99942 2C2007 01 24.60397015 45 16.258-21 16 02.96 L~09vC568 +99942 2C2007 01 24.60631615 45 16.864-21 16 04.53 L~09vC568 +99942 2C2007 01 24.60865915 45 17.437-21 16 06.03 L~09vC568 +99942 2C2007 01 24.61100715 45 18.015-21 16 07.64 L~09vC568 +99942 2C2007 01 24.61337815 45 18.617-21 16 09.04 L~09vC568 +99942 2C2007 01 24.61572015 45 19.205-21 16 10.60 L~09vC568 +99942 2C2007 01 24.61806315 45 19.787-21 16 12.11 L~09vC568 +99942 2C2007 01 24.62052215 45 20.394-21 16 13.80 L~09vC568 +99942 2C2007 01 24.62288015 45 20.996-21 16 15.28 L~09vC568 +99942 2C2007 01 24.62536915 45 21.610-21 16 16.86 L~09vC568 +99942 2C2007 01 24.62770915 45 22.184-21 16 18.37 L~09vC568 +99942 2C2007 01 24.63004715 45 22.784-21 16 19.89 L~09vC568 +99942 2C2007 01 24.63253115 45 23.400-21 16 21.47 L~09vC568 +99942 2C2007 01 24.63488415 45 23.956-21 16 22.98 L~09vC568 +99942 2C2007 01 24.63722615 45 24.576-21 16 24.46 L~09vC568 +99942 2C2007 01 24.63968615 45 25.180-21 16 26.08 L~09vC568 +99942 2C2007 01 24.64206015 45 25.765-21 16 27.61 L~09vC568 +99942 2C2007 01 24.64453715 45 26.385-21 16 29.24 L~09vC568 +99942 2C2007 01 24.64749315 45 27.120-21 16 31.13 L~09vC568 +99942 2C2007 01 24.64984515 45 27.716-21 16 32.67 L~09vD568 +99942 2C2007 01 24.65218915 45 28.295-21 16 34.14 L~09vD568 +99942 2C2007 01 24.65453715 45 28.875-21 16 35.68 L~09vD568 +99942 2C2007 01 24.65700115 45 29.476-21 16 37.24 L~09vD568 +99942 2C2007 01 24.65933815 45 30.069-21 16 38.76 L~09vD568 +99942 2C2007 01 24.66186915 45 30.702-21 16 40.35 L~09vD568 +99942 2C2007 01 24.66421415 45 31.282-21 16 41.89 L~09vD568 +99942 2C2007 01 24.66673715 45 31.913-21 16 43.52 L~09vD568 +99942 2C2007 01 24.66915915 45 32.521-21 16 45.04 L~09vD568 +99942 2C2007 01 25.57819315 49 22.787-21 26 10.76 L~09vD568 +99942 2C2007 01 25.58054715 49 23.382-21 26 12.24 L~09vD568 +99942 2C2007 01 25.58288715 49 24.005-21 26 13.93 L~09vD568 +99942 2C2007 01 25.58538115 49 24.619-21 26 15.27 L~09vD568 +99942 2C2007 01 25.58871815 49 25.448-21 26 17.35 L~09vD568 +99942 2C2007 01 25.59107515 49 26.056-21 26 18.94 L~09vD568 +99942 2C2007 01 25.59341915 49 26.638-21 26 20.34 L~09vD568 +99942 2C2007 01 25.59578215 49 27.232-21 26 21.81 L~09vD568 +99942 2C2007 01 25.59814815 49 27.836-21 26 23.28 L~09vD568 +99942 2C2007 01 25.60048815 49 28.426-21 26 24.78 L~09vD568 +99942 2C2007 01 25.60298015 49 29.040-21 26 26.32 L~09vD568 +99942 2C2007 01 25.60533815 49 29.635-21 26 27.79 L~09vD568 +99942 2C2007 01 25.60768815 49 30.217-21 26 29.23 L~09vD568 +99942 2C2007 01 25.61044415 49 30.921-21 26 30.98 L~09vD568 +99942 2C2007 01 25.61280315 49 31.515-21 26 32.50 L~09vD568 +99942 2C2007 01 25.61514615 49 32.099-21 26 33.92 L~09vD568 +99942 2C2007 01 25.61763015 49 32.743-21 26 35.57 L~09vD568 +99942 2C2007 01 25.62004115 49 33.333-21 26 37.04 L~09vD568 +99942 2C2007 01 25.62238915 49 33.920-21 26 38.54 L~09vD568 +99942 2C2007 01 25.62486615 49 34.551-21 26 40.09 L~09vD568 +99942 2C2007 01 25.62721115 49 35.141-21 26 41.54 L~09vD568 +99942 2C2007 01 25.62955615 49 35.721-21 26 42.96 L~09vD568 +99942 2C2007 01 25.63218615 49 36.378-21 26 44.65 L~09vD568 +99942 2C2007 01 25.63452915 49 36.980-21 26 46.10 L~09vD568 +99942 2C2007 01 25.63686715 49 37.574-21 26 47.55 L~09vD568 +99942 2C2007 01 25.63935415 49 38.186-21 26 49.11 L~09vD568 +99942 2C2007 01 25.64171915 49 38.758-21 26 50.54 L~09vD568 +99942 2C2007 01 25.64421215 49 39.407-21 26 52.14 L~09vD568 +99942 2C2007 01 25.64655615 49 39.998-21 26 53.60 L~09vD568 +99942 2C2007 01 25.64907615 49 40.623-21 26 54.91 L~09vD568 +99942 2C2007 03 09.65417619 16 36.695-21 11 06.90 L~09vD568 +99942 2C2007 03 09.65641119 16 37.371-21 11 04.96 L~09vD568 +99942 2C2007 12 13.66071314 26 35.206-15 26 51.52 L~09vD568 +99942 2C2008 01 06.63895716 03 51.245-20 51 51.34 L~09vD568 +99942 2C2008 01 06.64603616 03 53.080-20 51 55.60 L~09vD568 +99942 2C2008 01 06.64949016 03 53.986-20 51 57.69 L~09vD568 +99942 2C2008 01 06.65292016 03 54.887-20 51 59.83 L~09vD568 +99942 2C2008 01 06.65654416 03 55.801-20 52 01.94 L~09vD568 +99942 2C2008 01 06.66000516 03 56.765-20 52 04.16 L~09vD568 +99942 2C2008 01 06.66349216 03 57.618-20 52 06.04 L~09vD568 +99942 2C2008 01 07.64179316 08 14.721-21 01 32.09 L~09vD568 +99942 2C2008 01 07.64518616 08 15.608-21 01 33.99 L~09vD568 +99942 2C2008 01 07.65285816 08 17.617-21 01 38.46 L~09vD568 +99942 2C2008 01 07.65670716 08 18.608-21 01 40.57 L~09vD568 +99942 2C2008 01 08.65407416 12 42.234-21 10 54.03 L~09vD568 +99942 2C2008 01 08.65691716 12 42.968-21 10 55.80 L~09vD568 +99942 2C2008 01 08.65923516 12 43.584-21 10 56.95 L~09vD568 +99942 2C2008 01 08.66382416 12 44.803-21 10 59.64 L~09vD568 +99942 2C2008 01 08.66575916 12 45.323-21 11 00.64 L~09vD568 +99942 2C2008 01 09.64923016 17 06.855-21 19 43.21 L~09vD568 +99942 2C2008 01 09.65116616 17 07.315-21 19 44.16 L~09vD568 +99942 2C2008 01 09.65314116 17 07.868-21 19 45.05 L~09vD568 +99942 2C2008 01 09.65508216 17 08.370-21 19 46.22 L~09vD568 +99942 2C2008 01 09.65908916 17 09.415-21 19 48.28 L~09vD568 +99942 2C2008 01 09.66102716 17 09.953-21 19 49.41 L~09vD568 +99942 2C2008 01 09.66312516 17 10.506-21 19 50.39 L~09vD568 +99942 2C2008 01 09.66508816 17 11.010-21 19 51.46 L~09vD568 diff --git a/test/data/RADEC_2023_DW.dat b/test/data/RADEC_2023_DW.dat old mode 100755 new mode 100644 index 5dad9242..78794849 --- a/test/data/RADEC_2023_DW.dat +++ b/test/data/RADEC_2023_DW.dat @@ -1,123 +1,123 @@ - K23D00W*KC2023 02 26.12762 10 41 50.04 -10 23 20.0 18.2 GV~6ErWW94 - K23D00W KC2023 02 26.13393 10 41 44.54 -10 22 57.3 19.2 GV~6ErWW94 - K23D00W KC2023 02 26.14029 10 41 38.99 -10 22 33.9 19.5 GV~6ErWW94 - K23D00W KC2023 02 26.21229 10 40 36.05 -10 18 10.5 20.0 GV~6ErWW95 - K23D00W KC2023 02 26.21785 10 40 31.20 -10 17 50.3 20.0 GV~6ErWW95 - K23D00W KC2023 02 26.22336 10 40 26.36 -10 17 29.8 20.2 GV~6ErWW95 - K23D00W KC2023 02 26.29905010 39 23.74 -10 14 50.8 19.6 GV~6ErWH21 - K23D00W KC2023 02 26.30072610 39 22.31 -10 14 44.6 19.5 GV~6ErWH21 - K23D00W KC2023 02 26.30268310 39 20.64 -10 14 37.5 19.4 GV~6ErWH21 - K23D00W KC2023 02 26.51483810 36 31.98 -09 59 04.9 19.8 GV~6ErW474 - K23D00W KC2023 02 26.51607410 36 30.95 -09 59 00.8 19.4 GV~6ErW474 - K23D00W KC2023 02 26.51669210 36 30.39 -09 58 58.4 19.3 GV~6ErW474 - K23D00W KC2023 02 26.51792810 36 29.37 -09 58 53.8 19.4 GV~6ErW474 - K23D00W KC2023 02 26.99237710 30 19.04 -09 33 13.0 17.8 GX~6ErW958 - K23D00W KC2023 02 26.99624310 30 15.97 -09 33 00.0 18.3 GX~6ErW958 - K23D00W KC2023 02 27.00003610 30 12.92 -09 32 47.1 18.3 GX~6ErW958 - K23D00W KC2023 02 27.01955810 29 57.533-09 31 45.01 19.1 GV~6ErWJ95 - K23D00W KC2023 02 27.02274710 29 54.974-09 31 34.21 19.5 GV~6ErWJ95 - K23D00W KC2023 02 27.02670610 29 51.854-09 31 19.81 19.2 GV~6ErWJ95 - K23D00W |C2023 02 27.09047 10 29 08.49 -09 25 07.5 19.8 Vu~6ErW807 - K23D00W |C2023 02 27.09529 10 29 04.64 -09 24 50.4 19.8 Vu~6ErW807 - K23D00W |C2023 02 27.10011 10 29 00.88 -09 24 33.8 19.8 Vu~6ErW807 - K23D00W KC2023 02 27.37331910 25 38.34 -09 08 10.1 19.9 GV~6ErW474 - K23D00W KC2023 02 27.37513610 25 36.96 -09 08 04.3 19.8 GV~6ErW474 - K23D00W KC2023 02 27.37604510 25 36.31 -09 08 01.0 19.6 GV~6ErW474 - K23D00W KC2023 02 27.37786310 25 34.92 -09 07 54.8 20.1 GV~6ErW474 - K23D00W KC2023 02 27.84406510 20 00.514-08 43 47.28 19.8 rZ~6IqML34 - K23D00W KC2023 02 28.08327810 17 08.954-08 30 39.56 19.8 GV~6ErWJ95 - K23D00W KC2023 02 28.09127410 17 03.338-08 30 12.56 19.7 GV~6ErWJ95 - K23D00W KC2023 02 28.09176410 17 02.46 -08 30 03.4 20.0 GX~6ErWI93 - K23D00W KC2023 02 28.09557210 16 59.74 -08 29 50.8 19.3 GX~6ErWI93 - K23D00W KC2023 02 28.09926010 16 57.11 -08 29 38.3 20.0 GX~6ErWI93 - K23D00W KC2023 02 28.10219610 16 55.567-08 29 36.02 19.7 GV~6ErWJ95 - K23D00W KC2023 02 28.15117 10 16 28.89 -08 26 37.5 19.6 Vq~6ErWH36 - K23D00W KC2023 02 28.15916 10 16 23.19 -08 26 10.6 19.6 Vq~6ErWH36 - K23D00W mC2023 02 28.16844010 16 18.232-08 25 29.46 19.78GV~6ErWI52 - K23D00W mC2023 02 28.17101110 16 16.399-08 25 21.61 19.99GV~6ErWI52 - K23D00W mC2023 02 28.17381110 16 14.419-08 25 11.57 19.53GV~6ErWI52 - K23D00W mC2023 02 28.17638210 16 12.673-08 25 03.54 19.74GV~6ErWI52 - K23D00W KC2023 02 28.30056 10 14 44.76 -08 18 16.0 19.1 RV~6ErW691 - K23D00W KC2023 02 28.31214 10 14 36.61 -08 17 37.9 19.2 RV~6ErW691 - K23D00W KC2023 02 28.88605510 08 28.10 -07 46 58.9 19.5 GU~6IqML06 - K23D00W KC2023 02 28.88633110 08 27.87 -07 46 58.4 19.6 GU~6IqML06 - K23D00W KC2023 03 01.09750210 06 14.926-07 34 04.87 19.7 GX~6ErWY00 - K23D00W KC2023 03 01.11043910 06 06.437-07 33 23.88 20.0 GX~6ErWY00 - K23D00W KC2023 03 01.12317910 05 58.113-07 32 44.46 20.4 GX~6ErWY00 - K23D00W |C2023 03 01.21364 10 05 02.22 -07 27 46.4 19.8 Vu~6IqM807 - K23D00W |C2023 03 01.21720 10 04 59.98 -07 27 34.9 20.1 Vu~6IqM807 - K23D00W |C2023 03 01.22452 10 04 55.23 -07 27 12.2 19.8 Vu~6IqM807 - K23D00W KC2023 03 01.29513 10 04 14.27 -07 25 22.0 19.9 RV~6ErW691 - K23D00W KC2023 03 01.30289 10 04 09.32 -07 24 57.7 19.2 RV~6ErW691 - K23D00W KC2023 03 01.31066 10 04 04.34 -07 24 34.5 19.6 RV~6ErW691 - K23D00W .C2023 03 02.03196 09 57 07.53 -06 48 20.8 19.1 RV~6IqM950 - K23D00W .C2023 03 02.04667 09 56 58.80 -06 47 37.6 19.1 RV~6IqM950 - K23D00W .C2023 03 02.06140 09 56 50.06 -06 46 54.4 19.1 RV~6IqM950 - K23D00W 1C2023 03 02.85549909 49 52.127-06 09 26.45 20.2 GV~6IqMZ84 - K23D00W 1C2023 03 02.85820109 49 50.695-06 09 19.44 20.3 GV~6IqMZ84 - K23D00W 1C2023 03 02.86090109 49 49.235-06 09 11.73 19.9 GV~6IqMZ84 - K23D00W KC2023 03 04.24171 09 38 50.70 -05 08 48.6 20.3 RV~6IqM291 - K23D00W KC2023 03 04.26765 09 38 38.43 -05 07 44.0 V~6IqM291 - K23D00W KC2023 03 04.97492809 33 37.19 -04 39 30.8 20.2 GU~6IqML06 - K23D00W KC2023 03 04.97633409 33 36.56 -04 39 27.6 19.9 GU~6IqML06 - K23D00W 4C2023 03 09.05679509 11 01.665-02 20 50.12 20.9 GV~6VNlW85 - K23D00W 4C2023 03 09.06694609 10 58.684-02 20 32.84 20.8 GV~6VNlW85 - K23D00W 4C2023 03 09.07580009 10 56.116-02 20 17.70 21.2 GV~6VNlW85 - K23D00W KC2023 03 10.07650409 06 42.51 -01 54 07.0 X~6VNlW62 - K23D00W KC2023 03 10.09679709 06 37.17 -01 53 34.7 20.5 GX~6VNlW62 - K23D00W KC2023 03 10.11709909 06 31.85 -01 53 02.4 20.6 GX~6VNlW62 - K23D00W KC2023 03 10.87422 09 03 36.955-01 32 20.90 21.2 GX~6VNlL87 - K23D00W KC2023 03 10.88471 09 03 34.411-01 32 06.36 20.4 GX~6VNlL87 - K23D00W KC2023 03 11.21539 09 02 23.09 -01 24 58.1 21.5 Ro~6VNl291 - K23D00W KC2023 03 11.23274 09 02 18.97 -01 24 33.0 o~6VNl291 - K23D00W 2C2023 03 11.88641909 00 03.510-01 07 48.54 21.7 GV~6VNlK92 - K23D00W 2C2023 03 11.89503709 00 01.624-01 07 37.03 21.4 GV~6VNlK92 - K23D00W 2C2023 03 11.90366008 59 59.712-01 07 24.83 21.6 GV~6VNlK92 - K23D00W KC2023 03 11.93841 08 59 52.205-01 06 45.32 20.3 GX~6VNlL87 - K23D00W KC2023 03 11.93961 08 59 51.926-01 06 44.03 20.2 GX~6VNlL87 - K23D00W KC2023 03 12.81534 08 57 08.904-00 47 05.10 X~6VNlL87 - K23D00W KC2023 03 12.82659 08 57 06.610-00 46 49.94 20.4 GX~6VNlL87 - K23D00W KC2023 03 12.83793 08 57 04.255-00 46 35.08 20.0 GX~6VNlL87 - K23D00W 2C2023 03 13.05856408 56 25.317-00 41 43.43 21.8 GV~6VNlW86 - K23D00W 2C2023 03 13.07094308 56 22.864-00 41 27.63 21.8 GV~6VNlW86 - K23D00W 2C2023 03 13.08487308 56 20.082-00 41 09.71 21.6 GV~6VNlW86 - K23D00W KC2023 03 13.11090 08 56 16.38 -00 41 45.8 21.8 Vq~6VNlH36 - K23D00W KC2023 03 13.12641 08 56 13.38 -00 41 26.3 22.0 Vq~6VNl734 - K23D00W C2023 03 13.13945608 56 11.493-00 41 05.78 21.4 GV~6VNlH01 - K23D00W KC2023 03 13.14195 08 56 10.32 -00 41 06.7 q~6VNlH36 - K23D00W C2023 03 13.14286308 56 10.830-00 41 01.42 21.6 GV~6VNlH01 - K23D00W KC2023 03 13.14821 08 56 09.06 -00 40 58.7 21.8 Vq~6VNl734 - K23D00W C2023 03 13.15637208 56 08.190-00 40 44.18 21.4 GV~6VNlH01 - K23D00W KC2023 03 13.16090 08 56 07.59 -00 40 36.8 o~6VNl291 - K23D00W C2023 03 13.16255608 56 06.979-00 40 36.27 21.3 GV~6VNlH01 - K23D00W KC2023 03 13.17151 08 56 05.48 -00 40 22.8 21.4 Ro~6VNl291 - K23D00W KC2023 03 13.18212 08 56 03.40 -00 40 09.8 21.4 Ro~6VNl291 - K23D00W KC2023 03 13.89706 08 54 01.882-00 24 25.13 20.4 GX~6VNlL87 - K23D00W KC2023 03 13.90587 08 54 00.266-00 24 14.65 21.0 GX~6VNlL87 - K23D00W KC2023 03 13.91447 08 53 58.646-00 24 04.61 20.3 GX~6VNlL87 - K23D00W LC2023 03 14.04842008 53 39.687-00 21 17.57 21.3 GX~6VNl807 - K23D00W LC2023 03 14.05993108 53 37.550-00 21 02.85 21.6 GX~6VNl807 - K23D00W KC2023 03 14.17439 08 53 19.48 -00 19 48.1 21.8 Ro~6VNl291 - K23D00W KC2023 03 14.21103 08 53 13.00 -00 19 04.8 o~6VNl291 - K23D00W 2C2023 03 15.04936308 51 08.796-00 01 58.62 21.9 GV~6VNlW86 - K23D00W 2C2023 03 15.05826008 51 07.335-00 01 48.69 22.0 GV~6VNlW86 - K23D00W KC2023 03 15.06387908 51 07.24 -00 02 48.0 21.9 GV~6VNlH21 - K23D00W 2C2023 03 15.06716808 51 05.881-00 01 38.66 21.7 GV~6VNlW86 - K23D00W KC2023 03 15.06822008 51 06.55 -00 02 43.0 22.0 GV~6VNlH21 - K23D00W (C2023 03 15.55940908 49 55.602+00 07 22.75 22.4 GV~6VNlE10 - K23D00W (C2023 03 15.56530608 49 54.700+00 07 29.00 21.9 GV~6VNlE10 - K23D00W (C2023 03 15.57051908 49 53.913+00 07 34.74 22.1 GV~6VNlE10 - K23D00W 1C2023 03 15.89724 08 49 11.91 +00 12 11.0 22.1 VX~6VNl033 - K23D00W 1C2023 03 15.90083 08 49 11.41 +00 12 15.2 22.2 VX~6VNl033 - K23D00W 1C2023 03 15.90441 08 49 10.88 +00 12 18.9 22.0 VX~6VNl033 - K23D00W KC2023 03 16.06829508 48 51.01 +00 15 17.4 21.2 GX~6VNlW62 - K23D00W KC2023 03 16.07698908 48 49.78 +00 15 26.7 21.3 GX~6VNlW62 - K23D00W KC2023 03 16.08568908 48 48.49 +00 15 35.8 X~6VNlW62 - K23D00W 0C2023 03 18.45831608 44 21.170+00 54 05.97 22.54GV~6VNlT12 - K23D00W 0C2023 03 18.46207108 44 20.761+00 54 09.28 22.60GV~6VNlT12 - K23D00W 0C2023 03 18.46589808 44 20.354+00 54 12.69 22.53GV~6VNlT12 - K23D00W &C2023 03 19.00066008 43 34.315+01 02 40.16 22.8 GV~6VNl309 - K23D00W &C2023 03 19.00265708 43 34.098+01 02 41.96 22.5 GV~6VNl309 - K23D00W &C2023 03 19.00472108 43 33.876+01 02 43.68 22.7 GV~6VNl309 - K23D00W &C2023 03 19.00688808 43 33.639+01 02 45.50 22.6 GV~6VNl309 - K23D00W &C2023 03 19.00888608 43 33.425+01 02 47.29 22.7 GV~6VNl309 + K23D00W*KC2023 02 26.12762 10 41 50.04 -10 23 20.0 18.2 GV~6ErWW94 + K23D00W KC2023 02 26.13393 10 41 44.54 -10 22 57.3 19.2 GV~6ErWW94 + K23D00W KC2023 02 26.14029 10 41 38.99 -10 22 33.9 19.5 GV~6ErWW94 + K23D00W KC2023 02 26.21229 10 40 36.05 -10 18 10.5 20.0 GV~6ErWW95 + K23D00W KC2023 02 26.21785 10 40 31.20 -10 17 50.3 20.0 GV~6ErWW95 + K23D00W KC2023 02 26.22336 10 40 26.36 -10 17 29.8 20.2 GV~6ErWW95 + K23D00W KC2023 02 26.29905010 39 23.74 -10 14 50.8 19.6 GV~6ErWH21 + K23D00W KC2023 02 26.30072610 39 22.31 -10 14 44.6 19.5 GV~6ErWH21 + K23D00W KC2023 02 26.30268310 39 20.64 -10 14 37.5 19.4 GV~6ErWH21 + K23D00W KC2023 02 26.51483810 36 31.98 -09 59 04.9 19.8 GV~6ErW474 + K23D00W KC2023 02 26.51607410 36 30.95 -09 59 00.8 19.4 GV~6ErW474 + K23D00W KC2023 02 26.51669210 36 30.39 -09 58 58.4 19.3 GV~6ErW474 + K23D00W KC2023 02 26.51792810 36 29.37 -09 58 53.8 19.4 GV~6ErW474 + K23D00W KC2023 02 26.99237710 30 19.04 -09 33 13.0 17.8 GX~6ErW958 + K23D00W KC2023 02 26.99624310 30 15.97 -09 33 00.0 18.3 GX~6ErW958 + K23D00W KC2023 02 27.00003610 30 12.92 -09 32 47.1 18.3 GX~6ErW958 + K23D00W KC2023 02 27.01955810 29 57.533-09 31 45.01 19.1 GV~6ErWJ95 + K23D00W KC2023 02 27.02274710 29 54.974-09 31 34.21 19.5 GV~6ErWJ95 + K23D00W KC2023 02 27.02670610 29 51.854-09 31 19.81 19.2 GV~6ErWJ95 + K23D00W |C2023 02 27.09047 10 29 08.49 -09 25 07.5 19.8 Vu~6ErW807 + K23D00W |C2023 02 27.09529 10 29 04.64 -09 24 50.4 19.8 Vu~6ErW807 + K23D00W |C2023 02 27.10011 10 29 00.88 -09 24 33.8 19.8 Vu~6ErW807 + K23D00W KC2023 02 27.37331910 25 38.34 -09 08 10.1 19.9 GV~6ErW474 + K23D00W KC2023 02 27.37513610 25 36.96 -09 08 04.3 19.8 GV~6ErW474 + K23D00W KC2023 02 27.37604510 25 36.31 -09 08 01.0 19.6 GV~6ErW474 + K23D00W KC2023 02 27.37786310 25 34.92 -09 07 54.8 20.1 GV~6ErW474 + K23D00W KC2023 02 27.84406510 20 00.514-08 43 47.28 19.8 rZ~6IqML34 + K23D00W KC2023 02 28.08327810 17 08.954-08 30 39.56 19.8 GV~6ErWJ95 + K23D00W KC2023 02 28.09127410 17 03.338-08 30 12.56 19.7 GV~6ErWJ95 + K23D00W KC2023 02 28.09176410 17 02.46 -08 30 03.4 20.0 GX~6ErWI93 + K23D00W KC2023 02 28.09557210 16 59.74 -08 29 50.8 19.3 GX~6ErWI93 + K23D00W KC2023 02 28.09926010 16 57.11 -08 29 38.3 20.0 GX~6ErWI93 + K23D00W KC2023 02 28.10219610 16 55.567-08 29 36.02 19.7 GV~6ErWJ95 + K23D00W KC2023 02 28.15117 10 16 28.89 -08 26 37.5 19.6 Vq~6ErWH36 + K23D00W KC2023 02 28.15916 10 16 23.19 -08 26 10.6 19.6 Vq~6ErWH36 + K23D00W mC2023 02 28.16844010 16 18.232-08 25 29.46 19.78GV~6ErWI52 + K23D00W mC2023 02 28.17101110 16 16.399-08 25 21.61 19.99GV~6ErWI52 + K23D00W mC2023 02 28.17381110 16 14.419-08 25 11.57 19.53GV~6ErWI52 + K23D00W mC2023 02 28.17638210 16 12.673-08 25 03.54 19.74GV~6ErWI52 + K23D00W KC2023 02 28.30056 10 14 44.76 -08 18 16.0 19.1 RV~6ErW691 + K23D00W KC2023 02 28.31214 10 14 36.61 -08 17 37.9 19.2 RV~6ErW691 + K23D00W KC2023 02 28.88605510 08 28.10 -07 46 58.9 19.5 GU~6IqML06 + K23D00W KC2023 02 28.88633110 08 27.87 -07 46 58.4 19.6 GU~6IqML06 + K23D00W KC2023 03 01.09750210 06 14.926-07 34 04.87 19.7 GX~6ErWY00 + K23D00W KC2023 03 01.11043910 06 06.437-07 33 23.88 20.0 GX~6ErWY00 + K23D00W KC2023 03 01.12317910 05 58.113-07 32 44.46 20.4 GX~6ErWY00 + K23D00W |C2023 03 01.21364 10 05 02.22 -07 27 46.4 19.8 Vu~6IqM807 + K23D00W |C2023 03 01.21720 10 04 59.98 -07 27 34.9 20.1 Vu~6IqM807 + K23D00W |C2023 03 01.22452 10 04 55.23 -07 27 12.2 19.8 Vu~6IqM807 + K23D00W KC2023 03 01.29513 10 04 14.27 -07 25 22.0 19.9 RV~6ErW691 + K23D00W KC2023 03 01.30289 10 04 09.32 -07 24 57.7 19.2 RV~6ErW691 + K23D00W KC2023 03 01.31066 10 04 04.34 -07 24 34.5 19.6 RV~6ErW691 + K23D00W .C2023 03 02.03196 09 57 07.53 -06 48 20.8 19.1 RV~6IqM950 + K23D00W .C2023 03 02.04667 09 56 58.80 -06 47 37.6 19.1 RV~6IqM950 + K23D00W .C2023 03 02.06140 09 56 50.06 -06 46 54.4 19.1 RV~6IqM950 + K23D00W 1C2023 03 02.85549909 49 52.127-06 09 26.45 20.2 GV~6IqMZ84 + K23D00W 1C2023 03 02.85820109 49 50.695-06 09 19.44 20.3 GV~6IqMZ84 + K23D00W 1C2023 03 02.86090109 49 49.235-06 09 11.73 19.9 GV~6IqMZ84 + K23D00W KC2023 03 04.24171 09 38 50.70 -05 08 48.6 20.3 RV~6IqM291 + K23D00W KC2023 03 04.26765 09 38 38.43 -05 07 44.0 V~6IqM291 + K23D00W KC2023 03 04.97492809 33 37.19 -04 39 30.8 20.2 GU~6IqML06 + K23D00W KC2023 03 04.97633409 33 36.56 -04 39 27.6 19.9 GU~6IqML06 + K23D00W 4C2023 03 09.05679509 11 01.665-02 20 50.12 20.9 GV~6VNlW85 + K23D00W 4C2023 03 09.06694609 10 58.684-02 20 32.84 20.8 GV~6VNlW85 + K23D00W 4C2023 03 09.07580009 10 56.116-02 20 17.70 21.2 GV~6VNlW85 + K23D00W KC2023 03 10.07650409 06 42.51 -01 54 07.0 X~6VNlW62 + K23D00W KC2023 03 10.09679709 06 37.17 -01 53 34.7 20.5 GX~6VNlW62 + K23D00W KC2023 03 10.11709909 06 31.85 -01 53 02.4 20.6 GX~6VNlW62 + K23D00W KC2023 03 10.87422 09 03 36.955-01 32 20.90 21.2 GX~6VNlL87 + K23D00W KC2023 03 10.88471 09 03 34.411-01 32 06.36 20.4 GX~6VNlL87 + K23D00W KC2023 03 11.21539 09 02 23.09 -01 24 58.1 21.5 Ro~6VNl291 + K23D00W KC2023 03 11.23274 09 02 18.97 -01 24 33.0 o~6VNl291 + K23D00W 2C2023 03 11.88641909 00 03.510-01 07 48.54 21.7 GV~6VNlK92 + K23D00W 2C2023 03 11.89503709 00 01.624-01 07 37.03 21.4 GV~6VNlK92 + K23D00W 2C2023 03 11.90366008 59 59.712-01 07 24.83 21.6 GV~6VNlK92 + K23D00W KC2023 03 11.93841 08 59 52.205-01 06 45.32 20.3 GX~6VNlL87 + K23D00W KC2023 03 11.93961 08 59 51.926-01 06 44.03 20.2 GX~6VNlL87 + K23D00W KC2023 03 12.81534 08 57 08.904-00 47 05.10 X~6VNlL87 + K23D00W KC2023 03 12.82659 08 57 06.610-00 46 49.94 20.4 GX~6VNlL87 + K23D00W KC2023 03 12.83793 08 57 04.255-00 46 35.08 20.0 GX~6VNlL87 + K23D00W 2C2023 03 13.05856408 56 25.317-00 41 43.43 21.8 GV~6VNlW86 + K23D00W 2C2023 03 13.07094308 56 22.864-00 41 27.63 21.8 GV~6VNlW86 + K23D00W 2C2023 03 13.08487308 56 20.082-00 41 09.71 21.6 GV~6VNlW86 + K23D00W KC2023 03 13.11090 08 56 16.38 -00 41 45.8 21.8 Vq~6VNlH36 + K23D00W KC2023 03 13.12641 08 56 13.38 -00 41 26.3 22.0 Vq~6VNl734 + K23D00W C2023 03 13.13945608 56 11.493-00 41 05.78 21.4 GV~6VNlH01 + K23D00W KC2023 03 13.14195 08 56 10.32 -00 41 06.7 q~6VNlH36 + K23D00W C2023 03 13.14286308 56 10.830-00 41 01.42 21.6 GV~6VNlH01 + K23D00W KC2023 03 13.14821 08 56 09.06 -00 40 58.7 21.8 Vq~6VNl734 + K23D00W C2023 03 13.15637208 56 08.190-00 40 44.18 21.4 GV~6VNlH01 + K23D00W KC2023 03 13.16090 08 56 07.59 -00 40 36.8 o~6VNl291 + K23D00W C2023 03 13.16255608 56 06.979-00 40 36.27 21.3 GV~6VNlH01 + K23D00W KC2023 03 13.17151 08 56 05.48 -00 40 22.8 21.4 Ro~6VNl291 + K23D00W KC2023 03 13.18212 08 56 03.40 -00 40 09.8 21.4 Ro~6VNl291 + K23D00W KC2023 03 13.89706 08 54 01.882-00 24 25.13 20.4 GX~6VNlL87 + K23D00W KC2023 03 13.90587 08 54 00.266-00 24 14.65 21.0 GX~6VNlL87 + K23D00W KC2023 03 13.91447 08 53 58.646-00 24 04.61 20.3 GX~6VNlL87 + K23D00W LC2023 03 14.04842008 53 39.687-00 21 17.57 21.3 GX~6VNl807 + K23D00W LC2023 03 14.05993108 53 37.550-00 21 02.85 21.6 GX~6VNl807 + K23D00W KC2023 03 14.17439 08 53 19.48 -00 19 48.1 21.8 Ro~6VNl291 + K23D00W KC2023 03 14.21103 08 53 13.00 -00 19 04.8 o~6VNl291 + K23D00W 2C2023 03 15.04936308 51 08.796-00 01 58.62 21.9 GV~6VNlW86 + K23D00W 2C2023 03 15.05826008 51 07.335-00 01 48.69 22.0 GV~6VNlW86 + K23D00W KC2023 03 15.06387908 51 07.24 -00 02 48.0 21.9 GV~6VNlH21 + K23D00W 2C2023 03 15.06716808 51 05.881-00 01 38.66 21.7 GV~6VNlW86 + K23D00W KC2023 03 15.06822008 51 06.55 -00 02 43.0 22.0 GV~6VNlH21 + K23D00W (C2023 03 15.55940908 49 55.602+00 07 22.75 22.4 GV~6VNlE10 + K23D00W (C2023 03 15.56530608 49 54.700+00 07 29.00 21.9 GV~6VNlE10 + K23D00W (C2023 03 15.57051908 49 53.913+00 07 34.74 22.1 GV~6VNlE10 + K23D00W 1C2023 03 15.89724 08 49 11.91 +00 12 11.0 22.1 VX~6VNl033 + K23D00W 1C2023 03 15.90083 08 49 11.41 +00 12 15.2 22.2 VX~6VNl033 + K23D00W 1C2023 03 15.90441 08 49 10.88 +00 12 18.9 22.0 VX~6VNl033 + K23D00W KC2023 03 16.06829508 48 51.01 +00 15 17.4 21.2 GX~6VNlW62 + K23D00W KC2023 03 16.07698908 48 49.78 +00 15 26.7 21.3 GX~6VNlW62 + K23D00W KC2023 03 16.08568908 48 48.49 +00 15 35.8 X~6VNlW62 + K23D00W 0C2023 03 18.45831608 44 21.170+00 54 05.97 22.54GV~6VNlT12 + K23D00W 0C2023 03 18.46207108 44 20.761+00 54 09.28 22.60GV~6VNlT12 + K23D00W 0C2023 03 18.46589808 44 20.354+00 54 12.69 22.53GV~6VNlT12 + K23D00W &C2023 03 19.00066008 43 34.315+01 02 40.16 22.8 GV~6VNl309 + K23D00W &C2023 03 19.00265708 43 34.098+01 02 41.96 22.5 GV~6VNl309 + K23D00W &C2023 03 19.00472108 43 33.876+01 02 43.68 22.7 GV~6VNl309 + K23D00W &C2023 03 19.00688808 43 33.639+01 02 45.50 22.6 GV~6VNl309 + K23D00W &C2023 03 19.00888608 43 33.425+01 02 47.29 22.7 GV~6VNl309 diff --git a/test/extensions.jl b/test/extensions.jl old mode 100755 new mode 100644 index f5d5a527..c0512ff4 --- a/test/extensions.jl +++ b/test/extensions.jl @@ -1,52 +1,52 @@ -using NEOs -using Dates -using Tables -using DataFrames -using Query -using Test - -using NEOs: read_radec_mpc, RadecMPC, read_radar_jpl, RadarJPL - -@testset "DataFramesExt" begin - - # RadecMPC - radec_2023DW = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) - - df_2023DW = DataFrame(radec_2023DW) - - @test nrow(df_2023DW) == length(radec_2023DW) - @test all(names(df_2023DW) .== String.(fieldnames(RadecMPC{Float64}))) - @test all(eltype.(eachcol(df_2023DW)) .== fieldtypes(RadecMPC{Float64})) - - recovered_2023DW = Vector{RadecMPC{Float64}}(df_2023DW) - - @test recovered_2023DW == radec_2023DW - - # Query RadecMPC - I52_2023_02_28 = radec_2023DW |> @filter(Date(date(_)) == Date(2023, 2, 28) && observatory(_) == search_obs_code("I52")) |> DataFrame - - @test nrow(I52_2023_02_28) == 4 - @test all(Date.(I52_2023_02_28.date) .== Date(2023, 2, 28)) - @test allequal(I52_2023_02_28.observatory) && I52_2023_02_28.observatory[1] == search_obs_code("I52") - - # RadarJPL - radar_Apophis = read_radar_jpl(joinpath("data", "99942_RADAR_2005_2013.dat")) - - df_Apophis = DataFrame(radar_Apophis) - - @test nrow(df_Apophis) == length(radar_Apophis) - @test all(names(df_Apophis) .== String.(fieldnames(RadarJPL{Float64}))) - @test all(eltype.(eachcol(df_Apophis)) .== fieldtypes(RadarJPL{Float64})) - - recovered_Apophis = Vector{RadarJPL{Float64}}(df_Apophis) - - @test recovered_Apophis == radar_Apophis - - # Query RadarJPL - _251_before_2013 = radar_Apophis |> @filter(date(_) < Date(2013) && rcvr(_) == search_obs_code("251")) |> DataFrame - - @test nrow(_251_before_2013) == 5 - @test all(_251_before_2013.date .< Date(2013)) - @test allequal(_251_before_2013.rcvr) && _251_before_2013.rcvr[1] == search_obs_code("251") - +using NEOs +using Dates +using Tables +using DataFrames +using Query +using Test + +using NEOs: read_radec_mpc, RadecMPC, read_radar_jpl, RadarJPL + +@testset "DataFramesExt" begin + + # RadecMPC + radec_2023DW = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) + + df_2023DW = DataFrame(radec_2023DW) + + @test nrow(df_2023DW) == length(radec_2023DW) + @test all(names(df_2023DW) .== String.(fieldnames(RadecMPC{Float64}))) + @test all(eltype.(eachcol(df_2023DW)) .== fieldtypes(RadecMPC{Float64})) + + recovered_2023DW = Vector{RadecMPC{Float64}}(df_2023DW) + + @test recovered_2023DW == radec_2023DW + + # Query RadecMPC + I52_2023_02_28 = radec_2023DW |> @filter(Date(date(_)) == Date(2023, 2, 28) && observatory(_) == search_obs_code("I52")) |> DataFrame + + @test nrow(I52_2023_02_28) == 4 + @test all(Date.(I52_2023_02_28.date) .== Date(2023, 2, 28)) + @test allequal(I52_2023_02_28.observatory) && I52_2023_02_28.observatory[1] == search_obs_code("I52") + + # RadarJPL + radar_Apophis = read_radar_jpl(joinpath("data", "99942_RADAR_2005_2013.dat")) + + df_Apophis = DataFrame(radar_Apophis) + + @test nrow(df_Apophis) == length(radar_Apophis) + @test all(names(df_Apophis) .== String.(fieldnames(RadarJPL{Float64}))) + @test all(eltype.(eachcol(df_Apophis)) .== fieldtypes(RadarJPL{Float64})) + + recovered_Apophis = Vector{RadarJPL{Float64}}(df_Apophis) + + @test recovered_Apophis == radar_Apophis + + # Query RadarJPL + _251_before_2013 = radar_Apophis |> @filter(date(_) < Date(2013) && rcvr(_) == search_obs_code("251")) |> DataFrame + + @test nrow(_251_before_2013) == 5 + @test all(_251_before_2013.date .< Date(2013)) + @test allequal(_251_before_2013.rcvr) && _251_before_2013.rcvr[1] == search_obs_code("251") + end \ No newline at end of file diff --git a/test/osculating.jl b/test/osculating.jl old mode 100755 new mode 100644 index 68c4c928..6cf5e078 --- a/test/osculating.jl +++ b/test/osculating.jl @@ -1,16 +1,16 @@ -using NEOs -using Dates -using Test -using LinearAlgebra: norm - -@testset "Keplerian osculating elements" begin - q = [-9.759018085743707E-01, 3.896554445697074E-01, 1.478066121706831E-01, -9.071450085084557E-03, -9.353197026254517E-03, -5.610023032269034E-03] - kep = pv2kep(q) - jd2000 = datetime2julian(DateTime(2000,1,1,12)) - @test norm(kep(jd2000) - q, Inf) < 1e-10 - - qa = [-1.0506628055913627, -0.06064314196134998, -0.04997102228887035, 0.0029591421121582077, -0.01423233538611057, -0.005218412537773594] - jda = datetime2julian(DateTime(2004,6,1)) - kepa = pv2kep(qa) - @test norm(kepa(jd2000) - qa, Inf) < 1e-10 +using NEOs +using Dates +using Test +using LinearAlgebra: norm + +@testset "Keplerian osculating elements" begin + q = [-9.759018085743707E-01, 3.896554445697074E-01, 1.478066121706831E-01, -9.071450085084557E-03, -9.353197026254517E-03, -5.610023032269034E-03] + kep = pv2kep(q) + jd2000 = datetime2julian(DateTime(2000,1,1,12)) + @test norm(kep(jd2000) - q, Inf) < 1e-10 + + qa = [-1.0506628055913627, -0.06064314196134998, -0.04997102228887035, 0.0029591421121582077, -0.01423233538611057, -0.005218412537773594] + jda = datetime2julian(DateTime(2004,6,1)) + kepa = pv2kep(qa) + @test norm(kepa(jd2000) - qa, Inf) < 1e-10 end \ No newline at end of file From 5e04e42f23a966e9a15c58f900668a835e57ceb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 18 Jan 2024 13:10:23 -0600 Subject: [PATCH 107/173] Reset src/ to origin/main --- src/propagation/serialization.jl | 406 +++++++++++++++---------------- 1 file changed, 203 insertions(+), 203 deletions(-) mode change 100755 => 100644 src/propagation/serialization.jl diff --git a/src/propagation/serialization.jl b/src/propagation/serialization.jl old mode 100755 new mode 100644 index 78c33eee..8be73c35 --- a/src/propagation/serialization.jl +++ b/src/propagation/serialization.jl @@ -1,204 +1,204 @@ -@doc raw""" - TaylorInterpolantNSerialization{T} - -Custom serialization struct to save a `TaylorInterpolant{T, TaylorN{T}, 2}` to a `.jld2` file. - -# Fields -- `vars::Vector{String}`: jet transport variables. -- `order::Int`: order of Taylor polynomials w.r.t time. -- `varorder::Int`: order of jet transport perturbations. -- `dims::Tuple{Int, Int}`: matrix dimensions. -- `t0::T`: initial time. -- `t::Vector{T}`: vector of times. -- `x::Vector{T}`: vector of coefficients. -""" -struct TaylorInterpolantNSerialization{T} - vars::Vector{String} - order::Int - varorder::Int - dims::Tuple{Int, Int} - t0::T - t::Vector{T} - x::Vector{T} -end - -# Tell JLD2 to save TaylorInterpolant{T, TaylorN{T}, 2} as TaylorInterpolantNSerialization{T} -writeas(::Type{TaylorInterpolant{T, TaylorN{T}, 2}}) where {T} = TaylorInterpolantNSerialization{T} - -# Convert method to write .jld2 files -function convert(::Type{TaylorInterpolantNSerialization{T}}, eph::TaylorInterpolant{T, TaylorN{T}, 2}) where {T} - # Variables - vars = TS.get_variable_names() - # Number of variables - n = length(vars) - # Matrix dimensions - dims = size(eph.x) - # Number of elements in matrix - N = length(eph.x) - # Taylor1 order - order = eph.x[1, 1].order - # Number of coefficients in each Taylor1 - k = order + 1 - # TaylorN order - varorder = eph.x[1, 1].coeffs[1].order - # Number of coefficients in each TaylorN - L = varorder + 1 - # Number of coefficients in each HomogeneousPolynomial - M = binomial(n + varorder, varorder) - # M = sum(binomial(n + i_3 - 1, i_3) for i_3 in 0:varorder) - - # Vector of coefficients - x = Vector{T}(undef, N * k * M) - - # Save coefficients - i = 1 - # Iterate over matrix elements - for i_1 in 1:N - # Iterate over Taylor1 coefficients - for i_2 in 1:k - # Iterate over TaylorN coefficients - for i_3 in 0:varorder - # Iterate over i_3 order HomogeneousPolynomial - for i_4 in 1:binomial(n + i_3 - 1, i_3) - x[i] = eph.x[i_1].coeffs[i_2].coeffs[i_3+1].coeffs[i_4] - i += 1 - end - end - end - end - - return TaylorInterpolantNSerialization{T}(vars, order, varorder, dims, eph.t0, eph.t, x) -end - -# Convert method to read .jld2 files -function convert(::Type{TaylorInterpolant{T, TaylorN{T}, 2}}, eph::TaylorInterpolantNSerialization{T}) where {T} - # Variables - vars = eph.vars - # Number of variables - n = length(vars) - # Matrix dimensions - dims = eph.dims - # Number of elements in matrix - N = dims[1] * dims[2] - # Taylor1 order - order = eph.order - # Number of coefficients in each Taylor1 - k = order + 1 - # TaylorN order - varorder = eph.varorder - # Number of coefficients in each TaylorN - L = varorder + 1 - # Number of coefficients in each HomogeneousPolynomial - M = binomial(n + varorder, varorder) - # M = sum(binomial(n + i_3 - 1, i_3) for i_3 in 0:varorder) - - # Set variables - if TS.get_variable_names() != vars - TS.set_variables(T, vars, order = varorder) - end - - # Matrix of Taylor polynomials - x = Matrix{Taylor1{TaylorN{T}}}(undef, dims[1], dims[2]) - - # Reconstruct Taylor polynomials - i = 1 - # Iterate over matrix elements - for i_1 in 1:N - # Reconstruct Taylor1s - Taylor1_coeffs = Vector{TaylorN{T}}(undef, k) - for i_2 in 1:k - # Reconstruct TaylorNs - TaylorN_coeffs = Vector{HomogeneousPolynomial{T}}(undef, L) - # Reconstruct HomogeneousPolynomials - for i_3 in 0:varorder - TaylorN_coeffs[i_3 + 1] = HomogeneousPolynomial(eph.x[i : i + binomial(n + i_3 - 1, i_3)-1], i_3) - i += binomial(n + i_3 - 1, i_3) - end - Taylor1_coeffs[i_2] = TaylorN(TaylorN_coeffs, varorder) - end - x[i_1] = Taylor1{TaylorN{T}}(Taylor1_coeffs, order) - end - - return TaylorInterpolant{T, TaylorN{T}, 2}(eph.t0, eph.t, x) -end - -@doc raw""" - TaylorNSerialization{T} - -Custom serialization struct to save a `TaylorN{T}` to a `.jld2` file. - -# Fields -- `vars::Vector{String}`: jet transport variables. -- `varorder::Int`: order of jet transport perturbations. -- `x::Vector{T}`: vector of coefficients. -""" -struct TaylorNSerialization{T} - vars::Vector{String} - varorder::Int - x::Vector{T} -end - -# Tell JLD2 to save TaylorN{T} as TaylorNSerialization{T} -writeas(::Type{TaylorN{T}}) where {T} = TaylorNSerialization{T} - -# Convert method to write .jld2 files -function convert(::Type{TaylorNSerialization{T}}, eph::TaylorN{T}) where {T} - # Variables - vars = TS.get_variable_names() - # Number of variables - n = length(vars) - # TaylorN order - varorder = eph.order - # Number of coefficients in each TaylorN - L = varorder + 1 - # Number of coefficients in each HomogeneousPolynomial - M = binomial(n + varorder, varorder) - # M = sum(binomial(n + i_3 - 1, i_3) for i_3 in 0:varorder) - - # Vector of coefficients - x = Vector{T}(undef, M) - - # Save coefficients - i = 1 - for i_1 in 0:varorder - # Iterate over i_1 order HomogeneousPolynomial - for i_2 in 1:binomial(n + i_1 - 1, i_1) - x[i] = eph.coeffs[i_1+1].coeffs[i_2] - i += 1 - end - end - - return TaylorNSerialization{T}(vars, varorder, x) -end - -# Convert method to read .jld2 files -function convert(::Type{TaylorN{T}}, eph::TaylorNSerialization{T}) where {T} - # Variables - vars = eph.vars - # Number of variables - n = length(vars) - # TaylorN order - varorder = eph.varorder - # Number of coefficients in each TaylorN - L = varorder + 1 - # Number of coefficients in each HomogeneousPolynomial - M = binomial(n + varorder, varorder) - # M = sum(binomial(n + i_1 - 1, i_1) for i_1 in 0:varorder) - - # Set variables - if TS.get_variable_names() != vars - TS.set_variables(T, vars, order = varorder) - end - - # Reconstruct TaylorN - i = 1 - TaylorN_coeffs = Vector{HomogeneousPolynomial{T}}(undef, L) - for i_1 in 0:varorder - # Reconstruct HomogeneousPolynomials - TaylorN_coeffs[i_1 + 1] = HomogeneousPolynomial(eph.x[i : i + binomial(n + i_1 - 1, i_1)-1], i_1) - i += binomial(n + i_1 - 1, i_1) - end - x = TaylorN{T}(TaylorN_coeffs, varorder) - - return x +@doc raw""" + TaylorInterpolantNSerialization{T} + +Custom serialization struct to save a `TaylorInterpolant{T, TaylorN{T}, 2}` to a `.jld2` file. + +# Fields +- `vars::Vector{String}`: jet transport variables. +- `order::Int`: order of Taylor polynomials w.r.t time. +- `varorder::Int`: order of jet transport perturbations. +- `dims::Tuple{Int, Int}`: matrix dimensions. +- `t0::T`: initial time. +- `t::Vector{T}`: vector of times. +- `x::Vector{T}`: vector of coefficients. +""" +struct TaylorInterpolantNSerialization{T} + vars::Vector{String} + order::Int + varorder::Int + dims::Tuple{Int, Int} + t0::T + t::Vector{T} + x::Vector{T} +end + +# Tell JLD2 to save TaylorInterpolant{T, TaylorN{T}, 2} as TaylorInterpolantNSerialization{T} +writeas(::Type{TaylorInterpolant{T, TaylorN{T}, 2}}) where {T} = TaylorInterpolantNSerialization{T} + +# Convert method to write .jld2 files +function convert(::Type{TaylorInterpolantNSerialization{T}}, eph::TaylorInterpolant{T, TaylorN{T}, 2}) where {T} + # Variables + vars = TS.get_variable_names() + # Number of variables + n = length(vars) + # Matrix dimensions + dims = size(eph.x) + # Number of elements in matrix + N = length(eph.x) + # Taylor1 order + order = eph.x[1, 1].order + # Number of coefficients in each Taylor1 + k = order + 1 + # TaylorN order + varorder = eph.x[1, 1].coeffs[1].order + # Number of coefficients in each TaylorN + L = varorder + 1 + # Number of coefficients in each HomogeneousPolynomial + M = binomial(n + varorder, varorder) + # M = sum(binomial(n + i_3 - 1, i_3) for i_3 in 0:varorder) + + # Vector of coefficients + x = Vector{T}(undef, N * k * M) + + # Save coefficients + i = 1 + # Iterate over matrix elements + for i_1 in 1:N + # Iterate over Taylor1 coefficients + for i_2 in 1:k + # Iterate over TaylorN coefficients + for i_3 in 0:varorder + # Iterate over i_3 order HomogeneousPolynomial + for i_4 in 1:binomial(n + i_3 - 1, i_3) + x[i] = eph.x[i_1].coeffs[i_2].coeffs[i_3+1].coeffs[i_4] + i += 1 + end + end + end + end + + return TaylorInterpolantNSerialization{T}(vars, order, varorder, dims, eph.t0, eph.t, x) +end + +# Convert method to read .jld2 files +function convert(::Type{TaylorInterpolant{T, TaylorN{T}, 2}}, eph::TaylorInterpolantNSerialization{T}) where {T} + # Variables + vars = eph.vars + # Number of variables + n = length(vars) + # Matrix dimensions + dims = eph.dims + # Number of elements in matrix + N = dims[1] * dims[2] + # Taylor1 order + order = eph.order + # Number of coefficients in each Taylor1 + k = order + 1 + # TaylorN order + varorder = eph.varorder + # Number of coefficients in each TaylorN + L = varorder + 1 + # Number of coefficients in each HomogeneousPolynomial + M = binomial(n + varorder, varorder) + # M = sum(binomial(n + i_3 - 1, i_3) for i_3 in 0:varorder) + + # Set variables + if TS.get_variable_names() != vars + TS.set_variables(T, vars, order = varorder) + end + + # Matrix of Taylor polynomials + x = Matrix{Taylor1{TaylorN{T}}}(undef, dims[1], dims[2]) + + # Reconstruct Taylor polynomials + i = 1 + # Iterate over matrix elements + for i_1 in 1:N + # Reconstruct Taylor1s + Taylor1_coeffs = Vector{TaylorN{T}}(undef, k) + for i_2 in 1:k + # Reconstruct TaylorNs + TaylorN_coeffs = Vector{HomogeneousPolynomial{T}}(undef, L) + # Reconstruct HomogeneousPolynomials + for i_3 in 0:varorder + TaylorN_coeffs[i_3 + 1] = HomogeneousPolynomial(eph.x[i : i + binomial(n + i_3 - 1, i_3)-1], i_3) + i += binomial(n + i_3 - 1, i_3) + end + Taylor1_coeffs[i_2] = TaylorN(TaylorN_coeffs, varorder) + end + x[i_1] = Taylor1{TaylorN{T}}(Taylor1_coeffs, order) + end + + return TaylorInterpolant{T, TaylorN{T}, 2}(eph.t0, eph.t, x) +end + +@doc raw""" + TaylorNSerialization{T} + +Custom serialization struct to save a `TaylorN{T}` to a `.jld2` file. + +# Fields +- `vars::Vector{String}`: jet transport variables. +- `varorder::Int`: order of jet transport perturbations. +- `x::Vector{T}`: vector of coefficients. +""" +struct TaylorNSerialization{T} + vars::Vector{String} + varorder::Int + x::Vector{T} +end + +# Tell JLD2 to save TaylorN{T} as TaylorNSerialization{T} +writeas(::Type{TaylorN{T}}) where {T} = TaylorNSerialization{T} + +# Convert method to write .jld2 files +function convert(::Type{TaylorNSerialization{T}}, eph::TaylorN{T}) where {T} + # Variables + vars = TS.get_variable_names() + # Number of variables + n = length(vars) + # TaylorN order + varorder = eph.order + # Number of coefficients in each TaylorN + L = varorder + 1 + # Number of coefficients in each HomogeneousPolynomial + M = binomial(n + varorder, varorder) + # M = sum(binomial(n + i_3 - 1, i_3) for i_3 in 0:varorder) + + # Vector of coefficients + x = Vector{T}(undef, M) + + # Save coefficients + i = 1 + for i_1 in 0:varorder + # Iterate over i_1 order HomogeneousPolynomial + for i_2 in 1:binomial(n + i_1 - 1, i_1) + x[i] = eph.coeffs[i_1+1].coeffs[i_2] + i += 1 + end + end + + return TaylorNSerialization{T}(vars, varorder, x) +end + +# Convert method to read .jld2 files +function convert(::Type{TaylorN{T}}, eph::TaylorNSerialization{T}) where {T} + # Variables + vars = eph.vars + # Number of variables + n = length(vars) + # TaylorN order + varorder = eph.varorder + # Number of coefficients in each TaylorN + L = varorder + 1 + # Number of coefficients in each HomogeneousPolynomial + M = binomial(n + varorder, varorder) + # M = sum(binomial(n + i_1 - 1, i_1) for i_1 in 0:varorder) + + # Set variables + if TS.get_variable_names() != vars + TS.set_variables(T, vars, order = varorder) + end + + # Reconstruct TaylorN + i = 1 + TaylorN_coeffs = Vector{HomogeneousPolynomial{T}}(undef, L) + for i_1 in 0:varorder + # Reconstruct HomogeneousPolynomials + TaylorN_coeffs[i_1 + 1] = HomogeneousPolynomial(eph.x[i : i + binomial(n + i_1 - 1, i_1)-1], i_1) + i += binomial(n + i_1 - 1, i_1) + end + x = TaylorN{T}(TaylorN_coeffs, varorder) + + return x end \ No newline at end of file From add09b1614d3da189765ca454123126b4ba554bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 18 Jan 2024 16:18:12 -0600 Subject: [PATCH 108/173] Remove .DS_Store --- pha/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 pha/.DS_Store diff --git a/pha/.DS_Store b/pha/.DS_Store deleted file mode 100644 index ec740ebd5536b6621b1631b3707134d3820b1c7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%}T>S5dKDcDC(g{FTy@S!8Zt{9=r*@fTjvsQX|^lbN69FGk(n^_ zO?GE?vma!42Y@VgH>bc1z?7;e>Wqjsk9O@v@IFy&j62-p8FQ@Bj12S_oAlccaE(W_ z)GyzE-n6T_X>0Z?Ij_|Dn+ZK7q{b~C`0RYW{dhSU#2?`TPn=`TtQEG*+460JW{~$X z$kVw}l7VC(8At|_fuCf6XST}p&@pW?kPIXPpA6{!P^gMkVCQIC2aS~g#0i^C=<9V^ zb4p+p*g3L?BA!b0REZKpJe}<&;;O*T(bFMOd`QgvQM`!F&hd+dLn_C#$v`sDXFzLT z%1qDyGyXE8MZSfkNd}UE|H^<&mY2%~R~KjNw{_}STc}r56^-lEq0sML0{Ei)$gy>L be^H-tRbc0+qiDOO6Z0ZqgrrFZeu05^L^(DD From 635c4d8514e6e218826acc4b499d58201aca63cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 23 Jan 2024 13:18:08 -0600 Subject: [PATCH 109/173] OrbitFit -> LeastSquaresFit --- src/NEOs.jl | 2 +- .../least_squares.jl | 46 +++++++++---------- .../neosolution.jl | 15 +++--- .../orbit_determination.jl | 2 + 4 files changed, 32 insertions(+), 33 deletions(-) rename src/{postprocessing => orbit_determination}/least_squares.jl (91%) rename src/{postprocessing => orbit_determination}/neosolution.jl (89%) diff --git a/src/NEOs.jl b/src/NEOs.jl index a48fb4ae..8176a55c 100755 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -76,7 +76,7 @@ export issinglearc, istsa, orbitdetermination include("constants.jl") include("observations/process_radar.jl") include("propagation/propagation.jl") -include("postprocessing/neosolution.jl") +include("postprocessing/b_plane.jl") include("orbit_determination/orbit_determination.jl") include("init.jl") diff --git a/src/postprocessing/least_squares.jl b/src/orbit_determination/least_squares.jl similarity index 91% rename from src/postprocessing/least_squares.jl rename to src/orbit_determination/least_squares.jl index 22f07251..8d964acf 100755 --- a/src/postprocessing/least_squares.jl +++ b/src/orbit_determination/least_squares.jl @@ -1,5 +1,5 @@ @doc raw""" - OrbitFit{T <: Real} + LeastSquaresFit{T <: Real} A least squares fit. @@ -9,28 +9,28 @@ A least squares fit. - `Γ::Matrix{T}`: covariance matrix. - `routine::Symbol`: minimization routine (`:newton` or `:diffcorr`). """ -@auto_hash_equals struct OrbitFit{T <: Real} +@auto_hash_equals struct LeastSquaresFit{T <: Real} success::Bool x::Vector{T} Γ::Matrix{T} routine::Symbol # Inner constructor - function OrbitFit{T}(success::Bool, x::Vector{T}, Γ::Matrix{T}, + function LeastSquaresFit{T}(success::Bool, x::Vector{T}, Γ::Matrix{T}, routine::Symbol) where {T <: Real} return new{T}(success, x, Γ, routine) end end # Outer constructor -function OrbitFit(success::Bool, x::Vector{T}, Γ::Matrix{T}, +function LeastSquaresFit(success::Bool, x::Vector{T}, Γ::Matrix{T}, routine::Symbol) where {T <: Real} - return OrbitFit{T}(success, x, Γ, routine) + return LeastSquaresFit{T}(success, x, Γ, routine) end -# Print method for OrbitFit +# Print method for LeastSquaresFit # Examples: # Succesful Newton # Succesful differential corrections -function show(io::IO, fit::OrbitFit{T}) where {T <: Real} +function show(io::IO, fit::LeastSquaresFit{T}) where {T <: Real} success_s = fit.success ? "Succesful" : "Unsuccesful" routine_s = fit.routine == :newton ? "Newton" : "differential corrections" print(io, success_s, " ", routine_s) @@ -47,7 +47,7 @@ Fudge term for rejection condition in [`outlier_rejection`](@ref). carpino_smoothing(n::T) where {T <: Real} = 400*(1.2)^(-n) @doc raw""" - outlier_rejection(ξs::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}; + outlier_rejection(ξs::Vector{OpticalResidual{T, TaylorN{T}}}, fit::LeastSquaresFit{T}; χ2_rec::T = 7.0, χ2_rej::T = 8.0, α::T = 0.25, max_per::T = 10.) where {T <: Real} Outlier rejection algorithm. @@ -55,7 +55,7 @@ Outlier rejection algorithm. # Arguments - `ξs::Vector{OpticalResidual{T}}`: vector of residuals. -- `fit::OrbitFit{T}`: least squares fit. +- `fit::LeastSquaresFit{T}`: least squares fit. - `χ2_rec::T`: recovery condition. - `χ2_rej::T`: rejection condition. - `α::T`: scaling factor for maximum chi. @@ -64,7 +64,7 @@ Outlier rejection algorithm. !!! reference See https://doi.org/10.1016/S0019-1035(03)00051-4. """ -function outlier_rejection(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}; +function outlier_rejection(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::LeastSquaresFit{T}; χ2_rec::T = 7., χ2_rej::T = 8., α::T = 0.25, max_per::T = 10.) where {T <: Real} # Number of residuals @@ -129,11 +129,11 @@ function outlier_rejection(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::Orb end @doc raw""" - project(y::Vector{TaylorN{T}}, fit::OrbitFit{T}) where {T <: Real} + project(y::Vector{TaylorN{T}}, fit::LeastSquaresFit{T}) where {T <: Real} Project `fit`'s covariance matrix into `y`. """ -function project(y::Vector{TaylorN{T}}, fit::OrbitFit{T}) where {T <: Real} +function project(y::Vector{TaylorN{T}}, fit::LeastSquaresFit{T}) where {T <: Real} J = Matrix{T}(undef, get_numvars(), length(y)) for i in eachindex(y) J[:, i] = TS.gradient(y[i])(fit.x) @@ -183,7 +183,7 @@ end @doc raw""" nrms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} nrms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} - nrms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}) where {T <: Real} + nrms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::LeastSquaresFit{T}) where {T <: Real} Returns the normalized root mean square error ```math @@ -198,7 +198,7 @@ See also [`chi2`](@ref). - `res::Vector{U}/Vector{OpticalResidual{T, U}}`: Vector of residuals. - `w::Vector{T}`: Vector of weights. -- `fit::OrbitFit{T}`: least squares fit. +- `fit::LeastSquaresFit{T}`: least squares fit. """ function nrms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} @@ -213,7 +213,7 @@ function nrms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} return nrms(_res_, _w_) end -function nrms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::OrbitFit{T}) where {T <: Real} +function nrms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::LeastSquaresFit{T}) where {T <: Real} _res_, _w_ = unfold(res) return nrms(_res_(fit.x), _w_) end @@ -310,7 +310,7 @@ end niters::Int = 5) where {T <: Real} Differential corrections subroutine for least-squares fitting. Returns an -`OrbitFit` with the `niters`-th +`LeastSquaresFit` with the `niters`-th correction ```math \mathbf{x}_{k+1} = \mathbf{x}_k - \mathbf{C}^{-1}\mathbf{D}, @@ -371,7 +371,7 @@ function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, error[i+1] = sqrt(error2) # The method do not converge else - return OrbitFit(false, x[:, i+1], inv(C), :diffcorr) + return LeastSquaresFit(false, x[:, i+1], inv(C), :diffcorr) end end # Index with the lowest error @@ -384,9 +384,9 @@ function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, Γ = inv(C) if any(diag(Γ) .< 0) - return OrbitFit(false, x_new, Γ, :diffcorr) + return LeastSquaresFit(false, x_new, Γ, :diffcorr) else - return OrbitFit(true, x_new, Γ, :diffcorr) + return LeastSquaresFit(true, x_new, Γ, :diffcorr) end end @@ -404,7 +404,7 @@ end newtonls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, niters::Int = 5) where {T <: Real} -Newton method subroutine for least-squares fitting. Returns an `OrbitFit` +Newton method subroutine for least-squares fitting. Returns an `LeastSquaresFit` with the `niters`-th iteration ```math \mathbf{x}_{k+1} = \mathbf{x}_k - @@ -467,7 +467,7 @@ function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, error[i+1] = sqrt(error2) # The method do not converge else - return OrbitFit(false, x[:, i+1], inv(C), :newton) + return LeastSquaresFit(false, x[:, i+1], inv(C), :newton) end end # TO DO: study Gauss method solution dependence on jt order @@ -484,9 +484,9 @@ function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, Γ = inv(C) if any(diag(Γ) .< 0) - return OrbitFit(false, x_new, Γ, :newton) + return LeastSquaresFit(false, x_new, Γ, :newton) else - return OrbitFit(true, x_new, Γ, :newton) + return LeastSquaresFit(true, x_new, Γ, :newton) end end diff --git a/src/postprocessing/neosolution.jl b/src/orbit_determination/neosolution.jl similarity index 89% rename from src/postprocessing/neosolution.jl rename to src/orbit_determination/neosolution.jl index be8f779a..d0093a82 100755 --- a/src/postprocessing/neosolution.jl +++ b/src/orbit_determination/neosolution.jl @@ -1,6 +1,3 @@ -include("b_plane.jl") -include("least_squares.jl") - @doc raw""" NEOSolution{T <: Real, U <: Number} @@ -14,7 +11,7 @@ The outcome of the orbit determination process for a NEO. - `x_bwd/x_fwd::Vector{U}`: state vector at Earth close approach. - `g_bwd/g_fwd::Vector{U}`: geocentric distance at close approach. - `res::Vector{OpticalResidual{T, U}}`: vector of optical residuals. -- `fit::OrbitFit{T}`: least squares fit. +- `fit::LeastSquaresFit{T}`: least squares fit. - `scalings::Vector{T}`: jet transport scaling factors. """ @auto_hash_equals struct NEOSolution{T <: Real, U <: Number} @@ -28,14 +25,14 @@ The outcome of the orbit determination process for a NEO. x_fwd::Matrix{U} g_fwd::Vector{U} res::Vector{OpticalResidual{T, U}} - fit::OrbitFit{T} + fit::LeastSquaresFit{T} scalings::Vector{T} # Inner constructor function NEOSolution{T, U}( nights::Vector{ObservationNight{T}}, bwd::TaylorInterpolant{T, U, 2}, t_bwd::Vector{U}, x_bwd::Matrix{U}, g_bwd::Vector{U}, fwd::TaylorInterpolant{T, U, 2}, t_fwd::Vector{U}, x_fwd::Matrix{U}, g_fwd::Vector{U}, - res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}, scalings::Vector{T} + res::Vector{OpticalResidual{T, U}}, fit::LeastSquaresFit{T}, scalings::Vector{T} ) where {T <: Real, U <: Number} @assert bwd.t0 == fwd.t0 "Backward and forward propagation initial times must match" new{T, U}( @@ -51,7 +48,7 @@ function NEOSolution( nights::Vector{ObservationNight{T}}, bwd::TaylorInterpolant{T, U, 2}, t_bwd::Vector{U}, x_bwd::Matrix{U}, g_bwd::Vector{U}, fwd::TaylorInterpolant{T, U, 2}, t_fwd::Vector{U}, x_fwd::Matrix{U}, g_fwd::Vector{U}, - res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}, scalings::Vector{T} + res::Vector{OpticalResidual{T, U}}, fit::LeastSquaresFit{T}, scalings::Vector{T} ) where {T <: Real, U <: Number} NEOSolution{T, U}( nights, @@ -64,7 +61,7 @@ end function NEOSolution( nights::Vector{ObservationNight{T}}, bwd::TaylorInterpolant{T, U, 2}, fwd::TaylorInterpolant{T, U, 2}, - res::Vector{OpticalResidual{T, U}}, fit::OrbitFit{T}, scalings::Vector{T} + res::Vector{OpticalResidual{T, U}}, fit::LeastSquaresFit{T}, scalings::Vector{T} ) where {T <: Real, U <: Number} # Backward roots t_bwd = Vector{U}(undef, 0) @@ -140,7 +137,7 @@ function zero(::Type{NEOSolution{T, U}}) where {T <: Real, U <: Number} x_fwd = Matrix{U}(undef, 0, 0) g_fwd = Vector{U}(undef, 0) res = Vector{OpticalResidual{T, U}}(undef, 0) - fit = OrbitFit{T}(false, Vector{T}(undef, 0), Matrix{T}(undef, 0, 0), :newton) + fit = LeastSquaresFit{T}(false, Vector{T}(undef, 0), Matrix{T}(undef, 0, 0), :newton) scalings = Vector{T}(undef, 0) NEOSolution{T, U}( diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index 16e8290e..627e8d54 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -1,4 +1,6 @@ include("osculating.jl") +include("least_squares.jl") +include("neosolution.jl") include("tooshortarc.jl") include("gauss_method.jl") include("outlier_rejection.jl") From eb903e8312652774c57cae1ba43e41295b809cb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 23 Jan 2024 13:30:30 -0600 Subject: [PATCH 110/173] Parameters -> NEOParameters --- src/NEOs.jl | 2 +- src/orbit_determination/gauss_method.jl | 6 +++--- src/orbit_determination/orbit_determination.jl | 8 ++++---- src/orbit_determination/outlier_rejection.jl | 6 +++--- src/orbit_determination/tooshortarc.jl | 16 ++++++++-------- src/propagation/parameters.jl | 18 +++++++++--------- src/propagation/propagation.jl | 18 +++++++++--------- test/orbit_determination.jl | 6 +++--- test/propagation.jl | 14 +++++++------- 9 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index 8176a55c..148d7dad 100755 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -57,7 +57,7 @@ export compute_delay, radar_astrometry # Asteroid dynamical models export RNp1BP_pN_A_J23E_J2S_ng_eph_threads!, RNp1BP_pN_A_J23E_J2S_eph_threads! # Propagate -export Parameters, propagate, propagate_lyap, propagate_root +export NEOParameters, propagate, propagate_lyap, propagate_root # B plane export valsecchi_circle, bopik # Least squares diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 09e44c04..ee23d9a0 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -415,7 +415,7 @@ end @doc raw""" gaussinitcond(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, - params::Parameters{T}) where {T <: AbstractFloat} + params::NEOParameters{T}) where {T <: AbstractFloat} Return initial conditions via Gauss Method. @@ -425,13 +425,13 @@ See also [`gauss_method`](@ref). - `radec::Vector{RadecMPC{T}}`: vector of observations. - `nights::Vector{ObservationNight{T}},`: vector of observation nights. -- `params::Parameters{T}`: see `Gauss Method Parameters` of [`Parameters`](@ref). +- `params::NEOParameters{T}`: see `Gauss Method Parameters` of [`NEOParameters`](@ref). !!! warning This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. """ function gaussinitcond(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, - params::Parameters{T}) where {T <: AbstractFloat} + params::NEOParameters{T}) where {T <: AbstractFloat} # Allocate memory for initial conditions best_sol = zero(NEOSolution{T, T}) diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index 627e8d54..fef9b284 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -65,21 +65,21 @@ function adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFlo end @doc raw""" - orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}) where {T <: AbstractFloat} + orbitdetermination(radec::Vector{RadecMPC{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} Initial Orbit Determination (IOD) routine. # Arguments - `radec::Vector{RadecMPC{T}}`: vector of observations. -- `params::Parameters{T}`: see [`Parameters`](@ref). +- `params::NEOParameters{T}`: see [`NEOParameters`](@ref). """ -function orbitdetermination(radec::Vector{RadecMPC{T}}, params::Parameters{T}) where {T <: AbstractFloat} +function orbitdetermination(radec::Vector{RadecMPC{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} # Allocate memory for output sol = zero(NEOSolution{T, T}) # Maximum number of steps - params = Parameters(params; maxsteps = adaptative_maxsteps(radec)) + params = NEOParameters(params; maxsteps = adaptative_maxsteps(radec)) # Eliminate observatories without coordinates filter!(x -> hascoord(observatory(x)), radec) # Cannot handle zero observations or multiple arcs diff --git a/src/orbit_determination/outlier_rejection.jl b/src/orbit_determination/outlier_rejection.jl index 962db8cf..57a92b7b 100644 --- a/src/orbit_determination/outlier_rejection.jl +++ b/src/orbit_determination/outlier_rejection.jl @@ -7,7 +7,7 @@ residual_norm(x::OpticalResidual{T, T}) where {T <: Real} = x.w_α * x.ξ_α^2 / @doc raw""" outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, - params::Parameters{T}) where {T <: AbstractFloat} + params::NEOParameters{T}) where {T <: AbstractFloat} Refine an orbit, computed by [`tooshortarc`](@ref) or [`gaussinitcond`](@ref), via propagation and/or outlier rejection. @@ -16,13 +16,13 @@ via propagation and/or outlier rejection. - `radec::Vector{RadecMPC{T}}`: vector of observations. - `sol::NEOSolution{T, T}`: orbit to be refined. -- `params::Parameters{T}`: see `Outlier Rejection Parameters` of [`Parameters`](@ref). +- `params::NEOParameters{T}`: see `Outlier Rejection Parameters` of [`NEOParameters`](@ref). !!! warning This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. """ function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, - params::Parameters{T}) where {T <: AbstractFloat} + params::NEOParameters{T}) where {T <: AbstractFloat} # Sun's ephemeris eph_su = selecteph(sseph, su) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index d862a22a..ee6e1001 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -317,7 +317,7 @@ end # Propagate an orbit and compute residuals function propres(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{U}, - params::Parameters{T}) where {T <: AbstractFloat, U <: Number} + params::NEOParameters{T}) where {T <: AbstractFloat, U <: Number} # Time of first (last) observation t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) # Years in backward (forward) integration @@ -343,7 +343,7 @@ end @doc raw""" adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; η::T = 25.0, μ::T = 0.75, ν::T = 0.9, + params::NEOParameters{T}; η::T = 25.0, μ::T = 0.75, ν::T = 0.9, ϵ::T = 1e-8, Qtol::T = 0.001) where {T <: AbstractFloat} Adaptative moment estimation (ADAM) minimizer of normalized mean square @@ -356,7 +356,7 @@ residual over and admissible region `A`. See Algorithm 1 of https://doi.org/10.48550/arXiv.1412.6980. """ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::Parameters{T}; η::T = 25.0, μ::T = 0.75, ν::T = 0.9, + params::NEOParameters{T}; η::T = 25.0, μ::T = 0.75, ν::T = 0.9, ϵ::T = 1e-8, Qtol::T = 0.001) where {T <: AbstractFloat} # Initial time of integration [julian days] jd0 = datetime2julian(A.date) @@ -416,7 +416,7 @@ end @doc raw""" tsals(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, - jd0::T, q0::Vector{T}, params::Parameters{T}; maxiter::Int = 5, + jd0::T, q0::Vector{T}, params::NEOParameters{T}; maxiter::Int = 5, Qtol::T = 0.1) where {T <: AbstractFloat} Used within [`tooshortarc`](@ref) to compute an orbit from a point in an @@ -426,7 +426,7 @@ admissible region via least squares. This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. """ function tsals(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, - jd0::T, q0::Vector{T}, params::Parameters{T}; maxiter::Int = 5, + jd0::T, q0::Vector{T}, params::NEOParameters{T}; maxiter::Int = 5, Qtol::T = 0.1) where {T <: AbstractFloat} # Scaling factors scalings = abs.(q0) ./ 10^5 @@ -478,7 +478,7 @@ end @doc raw""" tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, - params::Parameters{T}) where {T <: AbstractFloat} + params::NEOParameters{T}) where {T <: AbstractFloat} Return initial conditions by minimizing the normalized root mean square residual over the admissible region. @@ -487,13 +487,13 @@ over the admissible region. - `radec::Vector{RadecMPC{T}}`: vector of observations. - `nights::Vector{ObservationNight{T}},`: vector of observation nights. -- `params::Parameters{T}`: see `Admissible Region Parameters` of [`Parameters`](@ref). +- `params::NEOParameters{T}`: see `Admissible Region Parameters` of [`NEOParameters`](@ref). !!! warning This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. """ function tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, - params::Parameters{T}) where {T <: AbstractFloat} + params::NEOParameters{T}) where {T <: AbstractFloat} # Allocate memory for output best_sol = zero(NEOSolution{T, T}) diff --git a/src/propagation/parameters.jl b/src/propagation/parameters.jl index 72dda533..5b69756c 100644 --- a/src/propagation/parameters.jl +++ b/src/propagation/parameters.jl @@ -1,4 +1,4 @@ -struct Parameters{T <: AbstractFloat} +struct NEOParameters{T <: AbstractFloat} # Propagation parameters maxsteps::Int μ_ast::Vector{T} @@ -26,7 +26,7 @@ end # Outer constructors @doc raw""" - Parameters([params::Parameters{T};] kwargs...) where {T <: AbstractFloat} + NEOParameters([params::NEOParameters{T};] kwargs...) where {T <: AbstractFloat} Parameters for all orbit determination functions. @@ -63,21 +63,21 @@ Parameters for all orbit determination functions. - `max_per::T`: maximum allowed rejection percentage (default: `18.0`). """ -function Parameters(; maxsteps::Int = 500, μ_ast::Vector{T} = μ_ast343_DE430[1:end], +function NEOParameters(; maxsteps::Int = 500, μ_ast::Vector{T} = μ_ast343_DE430[1:end], order::Int = 25, abstol::T = 1e-20, parse_eqs::Bool = true, debias_table::String = "2018", niter::Int = 5, max_triplets::Int = 10, varorder::Int = 5, Q_max::T = 5.0, maxiter::Int = 100, max_per::T = 18.0) where {T <: AbstractFloat} # Unfold debiasing matrix mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) - # Assemble Parameters - return Parameters{T}(maxsteps, μ_ast, order, abstol, parse_eqs, mpc_catalogue_codes_201X, + # Assemble NEOParameters + return NEOParameters{T}(maxsteps, μ_ast, order, abstol, parse_eqs, mpc_catalogue_codes_201X, truth, resol, bias_matrix, niter, max_triplets, varorder, Q_max, maxiter, max_per) end -function Parameters(params::Parameters{T}; kwargs...) where {T <: AbstractFloat} - fields = fieldnames(Parameters{T}) +function NEOParameters(params::NEOParameters{T}; kwargs...) where {T <: AbstractFloat} + fields = fieldnames(NEOParameters{T}) vals = Vector{Any}(undef, length(fields)) for i in eachindex(vals) if fields[i] in keys(kwargs) @@ -87,10 +87,10 @@ function Parameters(params::Parameters{T}; kwargs...) where {T <: AbstractFloat} end end - return Parameters{T}(vals...) + return NEOParameters{T}(vals...) end -function residuals(obs::Vector{RadecMPC{T}}, params::Parameters{T}; kwargs...) where {T <: AbstractFloat} +function residuals(obs::Vector{RadecMPC{T}}, params::NEOParameters{T}; kwargs...) where {T <: AbstractFloat} return residuals(obs, params.mpc_catalogue_codes_201X, params.truth, params.resol, params.bias_matrix; kwargs...) end \ No newline at end of file diff --git a/src/propagation/propagation.jl b/src/propagation/propagation.jl index 03163959..663b1592 100755 --- a/src/propagation/propagation.jl +++ b/src/propagation/propagation.jl @@ -128,7 +128,7 @@ end @doc raw""" propagate(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, - params::Parameters{T}) where {T <: Real, U <: Number, D} + params::NEOParameters{T}) where {T <: Real, U <: Number, D} Integrate the orbit of a NEO via the Taylor method. @@ -138,10 +138,10 @@ Integrate the orbit of a NEO via the Taylor method. - `jd0::T`: initial Julian date. - `tspan::T`: time span of the integration [in years]. - `q0::Vector{U}`: vector of initial conditions. -- `params::Parameters{T}`: see [`Parameters`](@ref). +- `params::NEOParameters{T}`: see [`NEOParameters`](@ref). """ function propagate(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, - params::Parameters{T}) where {T <: Real, U <: Number, D} + params::NEOParameters{T}) where {T <: Real, U <: Number, D} # Unfold maxsteps, μ_ast, order, abstol, parse_eqs = params.maxsteps, params.μ_ast, params.order, @@ -170,7 +170,7 @@ end @doc raw""" propagate_root(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, - params::Parameters{T}; eventorder::Int = 0, newtoniter::Int = 10, + params::NEOParameters{T}; eventorder::Int = 0, newtoniter::Int = 10, nrabstol::T = eps(T)) where {T <: Real, U <: Number, D} Integrate the orbit of a NEO via the Taylor method while finding the zeros of @@ -182,7 +182,7 @@ Integrate the orbit of a NEO via the Taylor method while finding the zeros of - `jd0::T`: initial Julian date. - `tspan::T`: time span of the integration [in years]. - `q0::Vector{U}`: vector of initial conditions. -- `params::Parameters{T}`: see [`Parameters`](@ref). +- `params::NEOParameters{T}`: see [`NEOParameters`](@ref). # Keyword arguments @@ -191,7 +191,7 @@ Integrate the orbit of a NEO via the Taylor method while finding the zeros of - `nrabstol::T`: allowed tolerance for the Newton-Raphson process. """ function propagate_root(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, - params::Parameters{T}; eventorder::Int = 0, newtoniter::Int = 10, + params::NEOParameters{T}; eventorder::Int = 0, newtoniter::Int = 10, nrabstol::T = eps(T)) where {T <: Real, U <: Number, D} # Unfold @@ -214,7 +214,7 @@ end @doc raw""" propagate_lyap(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, - params::Parameters{T}) where {T <: Real, U <: Number} + params::NEOParameters{T}) where {T <: Real, U <: Number} Compute the Lyapunov spectrum of a NEO. @@ -224,10 +224,10 @@ Compute the Lyapunov spectrum of a NEO. - `jd0::T`: initial Julian date. - `tspan::T`: time span of the integration [in Julian days]. - `q0::Vector{U}`: vector of initial conditions. -- `params::Parameters{T}`: see [`Parameters`](@ref). +- `params::NEOParameters{T}`: see [`NEOParameters`](@ref). """ function propagate_lyap(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, - params::Parameters{T}) where {T <: Real, U <: Number, D} + params::NEOParameters{T}) where {T <: Real, U <: Number, D} # Unfold maxsteps, μ_ast, order, abstol, parse_eqs = params.maxsteps, params.μ_ast, params.order, diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index 09581b60..d816c88c 100755 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -12,7 +12,7 @@ using NEOs: NEOSolution, numberofdays # Load observations radec = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) # Parameters - params = Parameters(abstol = 1e-20, order = 25, parse_eqs = true) + params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true) # Orbit Determination sol = orbitdetermination(radec, params) @@ -58,7 +58,7 @@ using NEOs: NEOSolution, numberofdays # Delete astrometry file rm(filename) # Parameters - params = Parameters(abstol = 1e-20, order = 25, parse_eqs = true) + params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true) # Orbit Determination sol = orbitdetermination(radec, params) @@ -104,7 +104,7 @@ using NEOs: NEOSolution, numberofdays # Delete astrometry file rm(filename) # Parameters - params = Parameters(abstol = 1e-20, order = 25, parse_eqs = true) + params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true) # Orbit Determination sol = orbitdetermination(radec, params) diff --git a/test/propagation.jl b/test/propagation.jl index 5761a59f..e87f4305 100755 --- a/test/propagation.jl +++ b/test/propagation.jl @@ -37,7 +37,7 @@ using InteractiveUtils: methodswith q0 = [-9.759018085743707E-01, 3.896554445697074E-01, 1.478066121706831E-01, -9.071450085084557E-03, -9.353197026254517E-03, -5.610023032269034E-03] # Propagation parameters - params = Parameters(maxsteps = 1, order = 25, abstol = 1e-20, + params = NEOParameters(maxsteps = 1, order = 25, abstol = 1e-20, parse_eqs = true) # Initial time [days since J2000] @@ -58,7 +58,7 @@ using InteractiveUtils: methodswith params ) # Propagate orbit - params = Parameters(params; maxsteps = 1_000) + params = NEOParameters(params; maxsteps = 1_000) sol_bwd = NEOs.propagate( dynamics, jd0, @@ -163,7 +163,7 @@ using InteractiveUtils: methodswith 0.0029591421121582077, -0.01423233538611057, -0.005218412537773594, -5.592839897872e-14, 0.0] # Propagation parameters - params = Parameters(maxsteps = 1, order = 25, abstol = 1e-20, + params = NEOParameters(maxsteps = 1, order = 25, abstol = 1e-20, parse_eqs = true) # Initial time [days since J2000] @@ -184,7 +184,7 @@ using InteractiveUtils: methodswith params ) # Propagate orbit - params = Parameters(params, maxsteps = 5_000) + params = NEOParameters(params, maxsteps = 5_000) sol = NEOs.propagate( dynamics, jd0, @@ -275,7 +275,7 @@ using InteractiveUtils: methodswith q0 = [-0.9170913888342959, -0.37154308794738056, -0.1610606989484252, 0.009701519087787077, -0.012766026792868212, -0.0043488589639194275] .+ dq # Propagation parameters - params = Parameters(maxsteps = 10, order = 25, abstol = 1e-20, parse_eqs = true) + params = NEOParameters(maxsteps = 10, order = 25, abstol = 1e-20, parse_eqs = true) # Propagate orbit sol = NEOs.propagate(dynamics, jd0, nyears, q0, params) @@ -284,7 +284,7 @@ using InteractiveUtils: methodswith @test sol == recovered_sol rm("test.jld2") - params = Parameters(params; maxsteps = 1) + params = NEOParameters(params; maxsteps = 1) sol, tvS, xvS, gvS = NEOs.propagate_root(dynamics, jd0, nyears, q0, params) jldsave("test.jld2"; sol, tvS, xvS, gvS) @@ -324,7 +324,7 @@ using InteractiveUtils: methodswith dq::Vector{TaylorN{Float64}} = NEOs.scaled_variables("δx", vcat(fill(1e-8, 6), 1e-14), order = varorder) q0::Vector{TaylorN{Float64}} = q00 .+ vcat(dq, 0dq[1]) # Propagation parameters - params = Parameters(maxsteps = 2_000, order = 25, abstol = 1e-20, parse_eqs = true) + params = NEOParameters(maxsteps = 2_000, order = 25, abstol = 1e-20, parse_eqs = true) # Propagate orbit sol = NEOs.propagate( From 02190a4278a675bcaede4003ffb602b751d2ea0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 24 Jan 2024 16:27:02 -0600 Subject: [PATCH 111/173] issuccessfulprop --- src/orbit_determination/gauss_method.jl | 4 ++-- src/orbit_determination/outlier_rejection.jl | 4 ++-- src/orbit_determination/tooshortarc.jl | 2 +- src/propagation/propagation.jl | 25 ++++++++++++++------ 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index ee23d9a0..cbbdca55 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -485,7 +485,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNig bwd::TaylorInterpolant{T, TaylorN{T}, 2} = propagate( RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q0, params ) - if unsuccessful_propagation(bwd, t0 - jd0) + if !issuccessfulprop(bwd, t0 - jd0) continue end @@ -493,7 +493,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNig fwd::TaylorInterpolant{T, TaylorN{T}, 2} = propagate( RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q0, params ) - if unsuccessful_propagation(fwd, tf - jd0) + if !issuccessfulprop(fwd, tf - jd0) continue end diff --git a/src/orbit_determination/outlier_rejection.jl b/src/orbit_determination/outlier_rejection.jl index 57a92b7b..221230d7 100644 --- a/src/orbit_determination/outlier_rejection.jl +++ b/src/orbit_determination/outlier_rejection.jl @@ -52,14 +52,14 @@ function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, # Backward integration bwd = propagate(dynamics, jd0, nyears_bwd, q, params) - if unsuccessful_propagation(bwd, t0 - jd0) + if !issuccessfulprop(bwd, t0 - jd0) return zero(NEOSolution{T, T}) end # Forward integration fwd = propagate(dynamics, jd0, nyears_fwd, q, params) - if unsuccessful_propagation(fwd, tf - jd0) + if !issuccessfulprop(fwd, tf - jd0) return zero(NEOSolution{T, T}) end diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index ee6e1001..8fcab58f 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -326,7 +326,7 @@ function propres(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{U}, # Backward (forward) integration bwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q0, params) fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q0, params) - if unsuccessful_propagation(bwd, t0 - jd0) || unsuccessful_propagation(fwd, tf - jd0) + if !issuccessfulprop(bwd, t0 - jd0) || !issuccessfulprop(fwd, tf - jd0) return bwd, fwd, Vector{OpticalResidual{T, U}}(undef, 0) end # Sun (Earth) ephemeris diff --git a/src/propagation/propagation.jl b/src/propagation/propagation.jl index 663b1592..e8bb86d3 100755 --- a/src/propagation/propagation.jl +++ b/src/propagation/propagation.jl @@ -49,17 +49,28 @@ end iszero(x::TaylorInterpolant{T, U, 2}) where {T <: Real, U <: Number} = x == zero(TaylorInterpolant{T, U, 2}) -function unsuccessful_propagation(sol::TaylorInterpolant{T, U, 2}, t::T) where {T <: Real, U <: Number} - +function issuccessfulprop(sol::TaylorInterpolant{T, U, 2}, t::T; + tol::T = 10.0) where {T <: Real, U <: Number} + # Zero TaylorInterpolant + iszero(sol) && return false + # Forward integration if issorted(sol.t) - c = sol.t[end] < t + # Insufficient steps + sol.t[end] < t && return false + # Step that covers t + i = searchsortedfirst(sol.t, t) - 1 + # Backward integration elseif issorted(sol.t, rev = true) - c = sol.t[end] > t + # Insufficient steps + sol.t[end] > t && return false + # Step that covers t + i = searchsortedfirst(sol.t, t, lt = !isless) - 1 + # This case should never happen else - c = true + return false end - - return iszero(sol) || any(norm.(sol.x, Inf) .> 10) || c + # All coefficients are below tol + return all( norm.(view(sol.x, 1:i, :), Inf) .< tol ) end @doc raw""" From c81d6c4fbe5a489caf6f54c906b9a44cb016ba62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 26 Jan 2024 10:12:31 -0600 Subject: [PATCH 112/173] ObservationNight -> Tracklet --- src/observations/observation_night.jl | 58 +++++++++---------- src/orbit_determination/gauss_method.jl | 10 ++-- src/orbit_determination/neosolution.jl | 12 ++-- .../orbit_determination.jl | 2 +- src/orbit_determination/tooshortarc.jl | 14 ++--- test/observations.jl | 2 +- 6 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/observations/observation_night.jl b/src/observations/observation_night.jl index b8a2fa76..31bc4957 100644 --- a/src/observations/observation_night.jl +++ b/src/observations/observation_night.jl @@ -1,5 +1,5 @@ @doc raw""" - ObservationNight{T <: AbstractFloat} + Tracklet{T <: AbstractFloat} A set of optical observations taken by the same observatory on the same night. @@ -17,7 +17,7 @@ A set of optical observations taken by the same observatory on the same night. - `nobs::Int`: number of observations. - `idxs::Vector{Int}`: indices of original `radec` that entered the night. """ -@auto_hash_equals struct ObservationNight{T <: AbstractFloat} +@auto_hash_equals struct Tracklet{T <: AbstractFloat} radec::Vector{RadecMPC{T}} observatory::ObservatoryMPC{T} night::TimeOfDay @@ -30,7 +30,7 @@ A set of optical observations taken by the same observatory on the same night. nobs::Int indices::Vector{Int} # Inner constructor - function ObservationNight{T}(radec::Vector{RadecMPC{T}}, observatory::ObservatoryMPC{T}, + function Tracklet{T}(radec::Vector{RadecMPC{T}}, observatory::ObservatoryMPC{T}, night::TimeOfDay, date::DateTime, α::T, δ::T, v_α::T, v_δ::T, mag::T, nobs::Int, indices::Vector{Int}) where {T <: AbstractFloat} @@ -38,26 +38,26 @@ A set of optical observations taken by the same observatory on the same night. end end -# Functions to get specific fields of a ObservationNight object -date(x::ObservationNight{T}) where {T <: AbstractFloat} = x.date -ra(x::ObservationNight{T}) where {T <: AbstractFloat} = x.α -dec(x::ObservationNight{T}) where {T <: AbstractFloat} = x.δ -observatory(x::ObservationNight{T}) where {T <: AbstractFloat} = x.observatory -vra(x::ObservationNight{T}) where {T <: AbstractFloat} = x.v_α -vdec(x::ObservationNight{T}) where {T <: AbstractFloat} = x.v_δ -mag(x::ObservationNight{T}) where {T <: AbstractFloat} = x.mag -indices(x::ObservationNight{T}) where {T <: AbstractFloat} = x.indices - -# Print method for ObservationNight{T} +# Functions to get specific fields of a Tracklet object +date(x::Tracklet{T}) where {T <: AbstractFloat} = x.date +ra(x::Tracklet{T}) where {T <: AbstractFloat} = x.α +dec(x::Tracklet{T}) where {T <: AbstractFloat} = x.δ +observatory(x::Tracklet{T}) where {T <: AbstractFloat} = x.observatory +vra(x::Tracklet{T}) where {T <: AbstractFloat} = x.v_α +vdec(x::Tracklet{T}) where {T <: AbstractFloat} = x.v_δ +mag(x::Tracklet{T}) where {T <: AbstractFloat} = x.mag +indices(x::Tracklet{T}) where {T <: AbstractFloat} = x.indices + +# Print method for Tracklet{T} # Examples: -# 3 observation night around 2023-11-18T19:59:55.392 at WFST, Lenghu -# 4 observation night around 2023-11-22T08:07:46.336 at Mt. Lemmon Survey -function show(io::IO, x::ObservationNight{T}) where {T <: AbstractFloat} - print(io, x.nobs, " observation night around ", x.date, " at ", x.observatory.name) +# 3 observation tracklet around 2023-11-18T19:59:55.392 at WFST, Lenghu +# 4 observation tracklet around 2023-11-22T08:07:46.336 at Mt. Lemmon Survey +function show(io::IO, x::Tracklet{T}) where {T <: AbstractFloat} + print(io, x.nobs, " observation tracklet around ", x.date, " at ", x.observatory.name) end -# Order in ObservationNight is given by date -isless(a::ObservationNight{T}, b::ObservationNight{T}) where {T <: AbstractFloat} = a.date < b.date +# Order in Tracklet is given by date +isless(a::Tracklet{T}, b::Tracklet{T}) where {T <: AbstractFloat} = a.date < b.date # Evaluate a polynomial with coefficients p in every element of x polymodel(x, p) = map(y -> evalpoly(y, p), x) @@ -99,8 +99,8 @@ function diffcoeffs(x::Vector{T}) where {T <: AbstractFloat} end # Outer constructor -function ObservationNight(radec::Vector{RadecMPC{T}}, df::AbstractDataFrame) where {T <: AbstractFloat} - # Defining quantities of an ObservationNight +function Tracklet(radec::Vector{RadecMPC{T}}, df::AbstractDataFrame) where {T <: AbstractFloat} + # Defining quantities of a Tracklet observatory = df.observatory[1] night = df.TimeOfDay[1] nobs = nrow(df) @@ -111,7 +111,7 @@ function ObservationNight(radec::Vector{RadecMPC{T}}, df::AbstractDataFrame) whe α, δ = df.α[1], df.δ[1] v_α, v_δ = zero(T), zero(T) mag = df.mag[1] - return ObservationNight{T}(radec, observatory, night, date, α, + return Tracklet{T}(radec, observatory, night, date, α, δ, v_α, v_δ, mag, nobs, indices) end @@ -150,16 +150,16 @@ function ObservationNight(radec::Vector{RadecMPC{T}}, df::AbstractDataFrame) whe # Mean apparent magnitude mag = mean(filter(!isnan, df.mag)) - return ObservationNight{T}(radec, observatory, night, date, α, δ, v_α, + return Tracklet{T}(radec, observatory, night, date, α, δ, v_α, v_δ, mag, nobs, indices) end @doc raw""" reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} -Return a `Vector{ObservationNight{T}}` where each eleement corresponds to a batch of -observations taken by the same observatory on the same night. -The reduction is performed via linear regression. +Return a `Vector{Tracklet{T}}` where each element corresponds to a batch of +observations taken by the same observatory on the same night. The reduction +is performed via polynomial regression. """ function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} # Convert to DataFrame @@ -169,11 +169,11 @@ function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} # Group by observatory and TimeOfDay gdf = groupby(df, [:observatory, :TimeOfDay]) # Allocate memmory for nights vector - nights = Vector{ObservationNight{T}}(undef, gdf.ngroups) + nights = Vector{Tracklet{T}}(undef, gdf.ngroups) # Reduce nights Threads.@threads for i in 1:gdf.ngroups rows = getfield(gdf[i], :rows) - nights[i] = ObservationNight(radec[rows], gdf[i]) + nights[i] = Tracklet(radec[rows], gdf[i]) end # Sort by date sort!(nights) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index cbbdca55..b45c21c9 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -339,7 +339,7 @@ end @doc raw""" numberofdays(dates::Vector{DateTime}) numberofdays(dates::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - numberofdays(dates::Vector{ObservationNight{T}}) where {T <: AbstractFloat} + numberofdays(dates::Vector{Tracklet{T}}) where {T <: AbstractFloat} Return the time span of `dates` in days. The function assumes `dates` is sorted. """ @@ -349,7 +349,7 @@ function numberofdays(dates::Vector{RadecMPC{T}}) where {T <: AbstractFloat} return (dates[end].date - dates[1].date).value / 86_400_000 end -function numberofdays(dates::Vector{ObservationNight{T}}) where {T <: AbstractFloat} +function numberofdays(dates::Vector{Tracklet{T}}) where {T <: AbstractFloat} return (dates[end].radec[end].date - dates[1].radec[1].date).value / 86_400_000 end @@ -414,7 +414,7 @@ function gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_ite end @doc raw""" - gaussinitcond(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, + gaussinitcond(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} Return initial conditions via Gauss Method. @@ -424,13 +424,13 @@ See also [`gauss_method`](@ref). # Arguments - `radec::Vector{RadecMPC{T}}`: vector of observations. -- `nights::Vector{ObservationNight{T}},`: vector of observation nights. +- `nights::Vector{Tracklet{T}},`: vector of observation nights. - `params::NEOParameters{T}`: see `Gauss Method Parameters` of [`NEOParameters`](@ref). !!! warning This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. """ -function gaussinitcond(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, +function gaussinitcond(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} # Allocate memory for initial conditions diff --git a/src/orbit_determination/neosolution.jl b/src/orbit_determination/neosolution.jl index d0093a82..25c139b5 100755 --- a/src/orbit_determination/neosolution.jl +++ b/src/orbit_determination/neosolution.jl @@ -5,7 +5,7 @@ The outcome of the orbit determination process for a NEO. # Fields -- `nights::Vector{ObservationNight{T}}`: vector of observation nights. +- `nights::Vector{Tracklet{T}}`: vector of observation nights. - `bwd/fwd::TaylorInterpolant{T, U, 2}`: backward (forward) integration. - `t_bwd/t_fwd::Vector{U}`: time of Earth close approach. - `x_bwd/x_fwd::Vector{U}`: state vector at Earth close approach. @@ -15,7 +15,7 @@ The outcome of the orbit determination process for a NEO. - `scalings::Vector{T}`: jet transport scaling factors. """ @auto_hash_equals struct NEOSolution{T <: Real, U <: Number} - nights::Vector{ObservationNight{T}} + nights::Vector{Tracklet{T}} bwd::TaylorInterpolant{T, U, 2} t_bwd::Vector{U} x_bwd::Matrix{U} @@ -29,7 +29,7 @@ The outcome of the orbit determination process for a NEO. scalings::Vector{T} # Inner constructor function NEOSolution{T, U}( - nights::Vector{ObservationNight{T}}, + nights::Vector{Tracklet{T}}, bwd::TaylorInterpolant{T, U, 2}, t_bwd::Vector{U}, x_bwd::Matrix{U}, g_bwd::Vector{U}, fwd::TaylorInterpolant{T, U, 2}, t_fwd::Vector{U}, x_fwd::Matrix{U}, g_fwd::Vector{U}, res::Vector{OpticalResidual{T, U}}, fit::LeastSquaresFit{T}, scalings::Vector{T} @@ -45,7 +45,7 @@ The outcome of the orbit determination process for a NEO. end # Outer constructors function NEOSolution( - nights::Vector{ObservationNight{T}}, + nights::Vector{Tracklet{T}}, bwd::TaylorInterpolant{T, U, 2}, t_bwd::Vector{U}, x_bwd::Matrix{U}, g_bwd::Vector{U}, fwd::TaylorInterpolant{T, U, 2}, t_fwd::Vector{U}, x_fwd::Matrix{U}, g_fwd::Vector{U}, res::Vector{OpticalResidual{T, U}}, fit::LeastSquaresFit{T}, scalings::Vector{T} @@ -59,7 +59,7 @@ function NEOSolution( end function NEOSolution( - nights::Vector{ObservationNight{T}}, + nights::Vector{Tracklet{T}}, bwd::TaylorInterpolant{T, U, 2}, fwd::TaylorInterpolant{T, U, 2}, res::Vector{OpticalResidual{T, U}}, fit::LeastSquaresFit{T}, scalings::Vector{T} ) where {T <: Real, U <: Number} @@ -127,7 +127,7 @@ end # Definition of zero NEOSolution function zero(::Type{NEOSolution{T, U}}) where {T <: Real, U <: Number} - nights = Vector{ObservationNight{T}}(undef, 0) + nights = Vector{Tracklet{T}}(undef, 0) bwd = TaylorInterpolant{T, U, 2}(zero(T), zeros(T, 1), Matrix{Taylor1{U}}(undef, 0, 0)) t_bwd = Vector{U}(undef, 0) x_bwd = Matrix{U}(undef, 0, 0) diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index fef9b284..4fd75343 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -26,7 +26,7 @@ end Check whether `sol` was computed via [`tooshortarc`](@ref) (`true`) or via [`gaussinitcond`](@ref) (`false`). """ -function istsa(nights::Vector{ObservationNight{T}}) where {T <: AbstractFloat} +function istsa(nights::Vector{Tracklet{T}}) where {T <: AbstractFloat} # Observing stations obs = observatory.(nights) # Satellite observatories can only be handled by Gauss diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 8fcab58f..f7dfca66 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -51,7 +51,7 @@ end iszero(x::AdmissibleRegion{T}) where {T <: AbstractFloat} = x == zero(AdmissibleRegion{T}) # Outer constructor -function AdmissibleRegion(night::ObservationNight{T}) where {T <: AbstractFloat} +function AdmissibleRegion(night::Tracklet{T}) where {T <: AbstractFloat} # Unfold obs, t_datetime, α, δ = observatory(night), date(night), ra(night), dec(night) v_α, v_δ, h = vra(night), vdec(night), mag(night) @@ -415,7 +415,7 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T end @doc raw""" - tsals(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, + tsals(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, jd0::T, q0::Vector{T}, params::NEOParameters{T}; maxiter::Int = 5, Qtol::T = 0.1) where {T <: AbstractFloat} @@ -425,7 +425,7 @@ admissible region via least squares. !!! warning This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. """ -function tsals(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, +function tsals(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, jd0::T, q0::Vector{T}, params::NEOParameters{T}; maxiter::Int = 5, Qtol::T = 0.1) where {T <: AbstractFloat} # Scaling factors @@ -468,7 +468,7 @@ function tsals(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, end # Order in which to check nights in tooshortarc -function tsanightorder(x::ObservationNight{T}, y::ObservationNight{T}) where {T <: AbstractFloat} +function tsanightorder(x::Tracklet{T}, y::Tracklet{T}) where {T <: AbstractFloat} if x.nobs == y.nobs return x.date > y.date else @@ -477,7 +477,7 @@ function tsanightorder(x::ObservationNight{T}, y::ObservationNight{T}) where {T end @doc raw""" - tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, + tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} Return initial conditions by minimizing the normalized root mean square residual @@ -486,13 +486,13 @@ over the admissible region. # Arguments - `radec::Vector{RadecMPC{T}}`: vector of observations. -- `nights::Vector{ObservationNight{T}},`: vector of observation nights. +- `nights::Vector{Tracklet{T}},`: vector of observation nights. - `params::NEOParameters{T}`: see `Admissible Region Parameters` of [`NEOParameters`](@ref). !!! warning This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. """ -function tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{ObservationNight{T}}, +function tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} # Allocate memory for output diff --git a/test/observations.jl b/test/observations.jl index 3734e15f..9d4e05eb 100755 --- a/test/observations.jl +++ b/test/observations.jl @@ -283,7 +283,7 @@ using NEOs: src_path end - @testset "ObservationNight" begin + @testset "Tracklet" begin using NEOs: reduce_nights # Choose this example because of the discontinuity in α From 5157a2f1e7a2ca37e4b71cc3f8475d8221d0af5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 26 Jan 2024 10:26:35 -0600 Subject: [PATCH 113/173] Change all night refs to tracklet --- src/observations/process_radar.jl | 2 +- src/observations/process_radec.jl | 2 +- .../{observation_night.jl => tracklet.jl} | 18 +++++----- src/orbit_determination/gauss_method.jl | 18 +++++----- src/orbit_determination/neosolution.jl | 22 ++++++------ .../orbit_determination.jl | 23 +++++++------ src/orbit_determination/outlier_rejection.jl | 6 ++-- src/orbit_determination/tooshortarc.jl | 34 +++++++++---------- test/observations.jl | 16 ++++----- test/orbit_determination.jl | 30 ++++++++-------- 10 files changed, 86 insertions(+), 85 deletions(-) rename src/observations/{observation_night.jl => tracklet.jl} (93%) diff --git a/src/observations/process_radar.jl b/src/observations/process_radar.jl index 24de6d13..217a2db9 100755 --- a/src/observations/process_radar.jl +++ b/src/observations/process_radar.jl @@ -5,7 +5,7 @@ include("radar_jpl.jl") include("units.jl") include("jpl_eph.jl") include("topocentric.jl") -include("observation_night.jl") +include("tracklet.jl") include("process_radec.jl") @doc raw""" diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index d59d2dda..a20563c0 100755 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -493,7 +493,7 @@ function relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} # Group by observatory and TimeOfDay df.TimeOfDay = TimeOfDay.(radec) gdf = groupby(df, [:observatory, :TimeOfDay]) - # Interpolate observation nights + # Number of observations per tracklet cdf = combine(gdf, nrow) # Count observations in each group Nv = cdf[gdf.groups, :nrow] diff --git a/src/observations/observation_night.jl b/src/observations/tracklet.jl similarity index 93% rename from src/observations/observation_night.jl rename to src/observations/tracklet.jl index 31bc4957..d88dbd25 100644 --- a/src/observations/observation_night.jl +++ b/src/observations/tracklet.jl @@ -15,7 +15,7 @@ A set of optical observations taken by the same observatory on the same night. - `v_δ::T`: mean declination velocity. - `mag::T`: mean apparent magnitude. - `nobs::Int`: number of observations. -- `idxs::Vector{Int}`: indices of original `radec` that entered the night. +- `idxs::Vector{Int}`: indices of original `radec` that entered the tracklet. """ @auto_hash_equals struct Tracklet{T <: AbstractFloat} radec::Vector{RadecMPC{T}} @@ -155,28 +155,28 @@ function Tracklet(radec::Vector{RadecMPC{T}}, df::AbstractDataFrame) where {T <: end @doc raw""" - reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + reduce_tracklets(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} Return a `Vector{Tracklet{T}}` where each element corresponds to a batch of observations taken by the same observatory on the same night. The reduction is performed via polynomial regression. """ -function reduce_nights(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} +function reduce_tracklets(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} # Convert to DataFrame df = DataFrame(radec) # Compute TimeOfDay df.TimeOfDay = TimeOfDay.(radec) # Group by observatory and TimeOfDay gdf = groupby(df, [:observatory, :TimeOfDay]) - # Allocate memmory for nights vector - nights = Vector{Tracklet{T}}(undef, gdf.ngroups) - # Reduce nights + # Allocate memmory for tracklets vector + tracklets = Vector{Tracklet{T}}(undef, gdf.ngroups) + # Reduce tracklets Threads.@threads for i in 1:gdf.ngroups rows = getfield(gdf[i], :rows) - nights[i] = Tracklet(radec[rows], gdf[i]) + tracklets[i] = Tracklet(radec[rows], gdf[i]) end # Sort by date - sort!(nights) + sort!(tracklets) - return nights + return tracklets end \ No newline at end of file diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index b45c21c9..429dd480 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -414,7 +414,7 @@ function gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_ite end @doc raw""" - gaussinitcond(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, + gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} Return initial conditions via Gauss Method. @@ -424,19 +424,19 @@ See also [`gauss_method`](@ref). # Arguments - `radec::Vector{RadecMPC{T}}`: vector of observations. -- `nights::Vector{Tracklet{T}},`: vector of observation nights. +- `tracklets::Vector{Tracklet{T}},`: vector of tracklets. - `params::NEOParameters{T}`: see `Gauss Method Parameters` of [`NEOParameters`](@ref). !!! warning This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. """ -function gaussinitcond(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, +function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} # Allocate memory for initial conditions best_sol = zero(NEOSolution{T, T}) # Unfold - observatories, dates, α, δ = observatory.(nights), date.(nights), ra.(nights), dec.(nights) + observatories, dates, α, δ = observatory.(tracklets), date.(tracklets), ra.(tracklets), dec.(tracklets) # Observations triplets triplets = gauss_triplets(dates, params.max_triplets) # Julian day of first (last) observation @@ -508,15 +508,15 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, # Subset of radec for orbit fit g_0 = triplet[1] g_f = triplet[3] - idxs = reduce(vcat, indices.(nights[g_0:g_f])) + idxs = reduce(vcat, indices.(tracklets[g_0:g_f])) sort!(idxs) # Orbit fit fit = tryls(res[idxs], x0, params.niter) !fit.success && continue # Right iteration - for k in g_f+1:length(nights) - extra = indices(nights[k]) + for k in g_f+1:length(tracklets) + extra = indices(tracklets[k]) fit_new = tryls(res[idxs ∪ extra], x0, params.niter) if fit_new.success fit = fit_new @@ -529,7 +529,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, # Left iteration for k in g_0-1:-1:1 - extra = indices(nights[k]) + extra = indices(tracklets[k]) fit_new = tryls(res[idxs ∪ extra], x0, params.niter) if fit_new.success fit = fit_new @@ -547,7 +547,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, # Update NRMS and initial conditions if Q < best_Q best_Q = Q - best_sol = evalfit(NEOSolution(nights, bwd, fwd, res[idxs], + best_sol = evalfit(NEOSolution(tracklets, bwd, fwd, res[idxs], fit, scalings)) end # Break condition diff --git a/src/orbit_determination/neosolution.jl b/src/orbit_determination/neosolution.jl index 25c139b5..a94dbfef 100755 --- a/src/orbit_determination/neosolution.jl +++ b/src/orbit_determination/neosolution.jl @@ -5,7 +5,7 @@ The outcome of the orbit determination process for a NEO. # Fields -- `nights::Vector{Tracklet{T}}`: vector of observation nights. +- `tracklets::Vector{Tracklet{T}}`: vector of tracklets. - `bwd/fwd::TaylorInterpolant{T, U, 2}`: backward (forward) integration. - `t_bwd/t_fwd::Vector{U}`: time of Earth close approach. - `x_bwd/x_fwd::Vector{U}`: state vector at Earth close approach. @@ -15,7 +15,7 @@ The outcome of the orbit determination process for a NEO. - `scalings::Vector{T}`: jet transport scaling factors. """ @auto_hash_equals struct NEOSolution{T <: Real, U <: Number} - nights::Vector{Tracklet{T}} + tracklets::Vector{Tracklet{T}} bwd::TaylorInterpolant{T, U, 2} t_bwd::Vector{U} x_bwd::Matrix{U} @@ -29,14 +29,14 @@ The outcome of the orbit determination process for a NEO. scalings::Vector{T} # Inner constructor function NEOSolution{T, U}( - nights::Vector{Tracklet{T}}, + tracklets::Vector{Tracklet{T}}, bwd::TaylorInterpolant{T, U, 2}, t_bwd::Vector{U}, x_bwd::Matrix{U}, g_bwd::Vector{U}, fwd::TaylorInterpolant{T, U, 2}, t_fwd::Vector{U}, x_fwd::Matrix{U}, g_fwd::Vector{U}, res::Vector{OpticalResidual{T, U}}, fit::LeastSquaresFit{T}, scalings::Vector{T} ) where {T <: Real, U <: Number} @assert bwd.t0 == fwd.t0 "Backward and forward propagation initial times must match" new{T, U}( - nights, + tracklets, bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, res, fit, scalings @@ -45,13 +45,13 @@ The outcome of the orbit determination process for a NEO. end # Outer constructors function NEOSolution( - nights::Vector{Tracklet{T}}, + tracklets::Vector{Tracklet{T}}, bwd::TaylorInterpolant{T, U, 2}, t_bwd::Vector{U}, x_bwd::Matrix{U}, g_bwd::Vector{U}, fwd::TaylorInterpolant{T, U, 2}, t_fwd::Vector{U}, x_fwd::Matrix{U}, g_fwd::Vector{U}, res::Vector{OpticalResidual{T, U}}, fit::LeastSquaresFit{T}, scalings::Vector{T} ) where {T <: Real, U <: Number} NEOSolution{T, U}( - nights, + tracklets, bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, res, fit, scalings @@ -59,7 +59,7 @@ function NEOSolution( end function NEOSolution( - nights::Vector{Tracklet{T}}, + tracklets::Vector{Tracklet{T}}, bwd::TaylorInterpolant{T, U, 2}, fwd::TaylorInterpolant{T, U, 2}, res::Vector{OpticalResidual{T, U}}, fit::LeastSquaresFit{T}, scalings::Vector{T} ) where {T <: Real, U <: Number} @@ -73,7 +73,7 @@ function NEOSolution( g_fwd = Vector{U}(undef, 0) NEOSolution{T, U}( - nights, + tracklets, bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, res, fit, scalings @@ -118,7 +118,7 @@ function evalfit(sol::NEOSolution{T, TaylorN{T}}) where {T <: Real} new_res = sol.res(δs) NEOSolution{T, T}( - sol.nights, + sol.tracklets, new_bwd, new_t_bwd, new_x_bwd, new_g_bwd, new_fwd, new_t_fwd, new_x_fwd, new_g_fwd, new_res, sol.fit, sol.scalings @@ -127,7 +127,7 @@ end # Definition of zero NEOSolution function zero(::Type{NEOSolution{T, U}}) where {T <: Real, U <: Number} - nights = Vector{Tracklet{T}}(undef, 0) + tracklets = Vector{Tracklet{T}}(undef, 0) bwd = TaylorInterpolant{T, U, 2}(zero(T), zeros(T, 1), Matrix{Taylor1{U}}(undef, 0, 0)) t_bwd = Vector{U}(undef, 0) x_bwd = Matrix{U}(undef, 0, 0) @@ -141,7 +141,7 @@ function zero(::Type{NEOSolution{T, U}}) where {T <: Real, U <: Number} scalings = Vector{T}(undef, 0) NEOSolution{T, U}( - nights, + tracklets, bwd, t_bwd, x_bwd, g_bwd, fwd, t_fwd, x_fwd, g_fwd, res, fit, scalings diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index 4fd75343..b484a175 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -21,27 +21,28 @@ function issinglearc(radec::Vector{RadecMPC{T}}, arc::Day = Day(30)) where {T <: end @doc raw""" + istsa(tracklets::Vector{Tracklet{T}}) where {T <: AbstractFloat} istsa(sol::NEOSolution{T, T}) where {T <: AbstractFloat} Check whether `sol` was computed via [`tooshortarc`](@ref) (`true`) or via [`gaussinitcond`](@ref) (`false`). """ -function istsa(nights::Vector{Tracklet{T}}) where {T <: AbstractFloat} +function istsa(tracklets::Vector{Tracklet{T}}) where {T <: AbstractFloat} # Observing stations - obs = observatory.(nights) + obs = observatory.(tracklets) # Satellite observatories can only be handled by Gauss any(issatellite.(obs)) && return false - # Gauss cannot handle less than 3 observation nights - length(nights) < 3 && return true + # Gauss cannot handle less than 3 tracklets + length(tracklets) < 3 && return true # Time span - Δ = numberofdays(nights) + Δ = numberofdays(tracklets) # Gauss aproximation do not work with less than 1 day Δ < 1 && return true # All observations come from the same observatory return allequal(obs) && Δ < 5 end -istsa(sol::NEOSolution{T, T}) where {T <: AbstractFloat} = istsa(sol.nights) +istsa(sol::NEOSolution{T, T}) where {T <: AbstractFloat} = istsa(sol.tracklets) @doc raw""" adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} @@ -86,14 +87,14 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, params::NEOParameters{T} if iszero(length(radec)) || !issinglearc(radec) return sol::NEOSolution{T, T} end - # Reduce observation nights by linear regression - nights = reduce_nights(radec) + # Reduce tracklets by polynomial regression + tracklets = reduce_tracklets(radec) # Case 1: Too Short Arc (TSA) - if istsa(nights) - sol = tooshortarc(radec, nights, params) + if istsa(tracklets) + sol = tooshortarc(radec, tracklets, params) # Case 2: Gauss Method else - sol = gaussinitcond(radec, nights, params) + sol = gaussinitcond(radec, tracklets, params) end # Outlier rejection (if needed) if nrms(sol) > 1 && !iszero(sol) diff --git a/src/orbit_determination/outlier_rejection.jl b/src/orbit_determination/outlier_rejection.jl index 221230d7..d1ab00eb 100644 --- a/src/orbit_determination/outlier_rejection.jl +++ b/src/orbit_determination/outlier_rejection.jl @@ -75,7 +75,7 @@ function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, Q_0 = nrms(res, fit) if Q_0 < 1 - return evalfit(NEOSolution(sol.nights, bwd, fwd, res, fit, scalings)) + return evalfit(NEOSolution(sol.tracklets, bwd, fwd, res, fit, scalings)) end # Number of observations @@ -149,7 +149,7 @@ function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, # Update fit fit = tryls(res, x0, params.niter) - return evalfit(NEOSolution(sol.nights, bwd, fwd, res, fit, scalings)) + return evalfit(NEOSolution(sol.tracklets, bwd, fwd, res, fit, scalings)) end if max_drop > 1 @@ -179,5 +179,5 @@ function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, # Update fit fit = tryls(res, x0, params.niter) - return evalfit(NEOSolution(sol.nights, bwd, fwd, res, fit, scalings)) + return evalfit(NEOSolution(sol.tracklets, bwd, fwd, res, fit, scalings)) end \ No newline at end of file diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index f7dfca66..baf74e21 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -51,10 +51,10 @@ end iszero(x::AdmissibleRegion{T}) where {T <: AbstractFloat} = x == zero(AdmissibleRegion{T}) # Outer constructor -function AdmissibleRegion(night::Tracklet{T}) where {T <: AbstractFloat} +function AdmissibleRegion(tracklet::Tracklet{T}) where {T <: AbstractFloat} # Unfold - obs, t_datetime, α, δ = observatory(night), date(night), ra(night), dec(night) - v_α, v_δ, h = vra(night), vdec(night), mag(night) + obs, t_datetime, α, δ = observatory(tracklet), date(tracklet), ra(tracklet), dec(tracklet) + v_α, v_δ, h = vra(tracklet), vdec(tracklet), mag(tracklet) # Topocentric unit vector and partials ρ, ρ_α, ρ_δ = topounitpdv(α, δ) # Time of observation [days since J2000] @@ -415,7 +415,7 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T end @doc raw""" - tsals(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, + tsals(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, jd0::T, q0::Vector{T}, params::NEOParameters{T}; maxiter::Int = 5, Qtol::T = 0.1) where {T <: AbstractFloat} @@ -425,7 +425,7 @@ admissible region via least squares. !!! warning This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. """ -function tsals(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, +function tsals(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, jd0::T, q0::Vector{T}, params::NEOParameters{T}; maxiter::Int = 5, Qtol::T = 0.1) where {T <: AbstractFloat} # Scaling factors @@ -451,7 +451,7 @@ function tsals(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, break end # Current solution - sols[t] = evalfit(NEOSolution(nights, bwd, fwd, res, fit, scalings)) + sols[t] = evalfit(NEOSolution(tracklets, bwd, fwd, res, fit, scalings)) Qs[t] = nrms(sols[t]) # Convergence conditions if t > 1 @@ -467,8 +467,8 @@ function tsals(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, return sols[t] end -# Order in which to check nights in tooshortarc -function tsanightorder(x::Tracklet{T}, y::Tracklet{T}) where {T <: AbstractFloat} +# Order in which to check tracklets in tooshortarc +function tsatrackletorder(x::Tracklet{T}, y::Tracklet{T}) where {T <: AbstractFloat} if x.nobs == y.nobs return x.date > y.date else @@ -477,7 +477,7 @@ function tsanightorder(x::Tracklet{T}, y::Tracklet{T}) where {T <: AbstractFloat end @doc raw""" - tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, + tooshortarc(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} Return initial conditions by minimizing the normalized root mean square residual @@ -486,24 +486,24 @@ over the admissible region. # Arguments - `radec::Vector{RadecMPC{T}}`: vector of observations. -- `nights::Vector{Tracklet{T}},`: vector of observation nights. +- `tracklets::Vector{Tracklet{T}},`: vector of tracklets. - `params::NEOParameters{T}`: see `Admissible Region Parameters` of [`NEOParameters`](@ref). !!! warning This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. """ -function tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, +function tooshortarc(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} # Allocate memory for output best_sol = zero(NEOSolution{T, T}) - # Sort nights by tsanightorder - idxs = sortperm(nights, lt = tsanightorder) + # Sort tracklets by tsatrackletorder + idxs = sortperm(tracklets, lt = tsatrackletorder) - # Iterate observation nights + # Iterate tracklets for i in idxs # Admissible region - A = AdmissibleRegion(nights[i]) + A = AdmissibleRegion(tracklets[i]) iszero(A) && continue # Center ρ = sum(A.ρ_domain) / 2 @@ -515,7 +515,7 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, # Initial time of integration [julian days] jd0 = datetime2julian(A.date) # 6 variables least squares - sol = tsals(radec, nights, jd0, q0, params; maxiter = 5) + sol = tsals(radec, tracklets, jd0, q0, params; maxiter = 5) # Update best solution if nrms(sol) < nrms(best_sol) best_sol = sol @@ -541,7 +541,7 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, nights::Vector{Tracklet{T}}, # Barycentric initial conditions q0 = topo2bary(A, ρ, v_ρs[t]) # 6 variables least squares - sol = tsals(radec, nights, jd0, q0, params; maxiter = 5) + sol = tsals(radec, tracklets, jd0, q0, params; maxiter = 5) # Update best solution if nrms(sol) < nrms(best_sol) best_sol = sol diff --git a/test/observations.jl b/test/observations.jl index 9d4e05eb..da804860 100755 --- a/test/observations.jl +++ b/test/observations.jl @@ -284,7 +284,7 @@ using NEOs: src_path end @testset "Tracklet" begin - using NEOs: reduce_nights + using NEOs: reduce_tracklets # Choose this example because of the discontinuity in α @@ -294,17 +294,17 @@ using NEOs: src_path get_radec_mpc("designation" => "2020 TJ6", filename) # Parse observations radec = read_radec_mpc(filename) - # Reduce observation nights - nights = reduce_nights(radec) + # Reduce tracklets + tracklets = reduce_tracklets(radec) # Remove downloaded file rm(filename) # Values by December 19, 2023 - @test length(nights) == 5 - @test getfield.(nights, :nobs) == [4, 4, 3, 4, 3] - @test nights[3].α ≈ 6.2831 atol = 1e-4 - @test nights[3].observatory == search_obs_code("J04") - @test nights[3].night.utc == -1 + @test length(tracklets) == 5 + @test getfield.(tracklets, :nobs) == [4, 4, 3, 4, 3] + @test tracklets[3].α ≈ 6.2831 atol = 1e-4 + @test tracklets[3].observatory == search_obs_code("J04") + @test tracklets[3].night.utc == -1 end end diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index d816c88c..967a4cc9 100755 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -24,11 +24,11 @@ using NEOs: NEOSolution, numberofdays @test numberofdays(radec) < 21.0 # Orbit solution @test isa(sol, NEOSolution{Float64, Float64}) - # Observation nights - @test length(sol.nights) == 44 - @test sol.nights[1].radec[1] == radec[1] - @test sol.nights[end].radec[end] == radec[end] - @test issorted(sol.nights) + # Tracklets + @test length(sol.tracklets) == 44 + @test sol.tracklets[1].radec[1] == radec[1] + @test sol.tracklets[end].radec[end] == radec[end] + @test issorted(sol.tracklets) # Backward integration @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] @test all( norm.(sol.bwd.x, Inf) .< 2 ) @@ -70,11 +70,11 @@ using NEOs: NEOSolution, numberofdays @test numberofdays(radec) < 0.05 # Orbit solution @test isa(sol, NEOSolution{Float64, Float64}) - # Observation nights - @test length(sol.nights) == 1 - @test sol.nights[1].radec[1] == radec[1] - @test sol.nights[end].radec[end] == radec[end] - @test issorted(sol.nights) + # Tracklets + @test length(sol.tracklets) == 1 + @test sol.tracklets[1].radec[1] == radec[1] + @test sol.tracklets[end].radec[end] == radec[end] + @test issorted(sol.tracklets) # Backward integration @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] @test all( norm.(sol.bwd.x, Inf) .< 2 ) @@ -116,11 +116,11 @@ using NEOs: NEOSolution, numberofdays @test numberofdays(radec) < 3.03 # Orbit solution @test isa(sol, NEOSolution{Float64, Float64}) - # Observation nights - @test length(sol.nights) == 4 - @test sol.nights[1].radec[1] == radec[1] - @test sol.nights[end].radec[end] == radec[end] - @test issorted(sol.nights) + # Tracklets + @test length(sol.tracklets) == 4 + @test sol.tracklets[1].radec[1] == radec[1] + @test sol.tracklets[end].radec[end] == radec[end] + @test issorted(sol.tracklets) # Backward integration @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] @test all( norm.(sol.bwd.x, Inf) .< 2 ) From 78a873c162f8456fa29f697e3e2f072ad658f67e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 26 Jan 2024 11:21:57 -0600 Subject: [PATCH 114/173] Add 2014 AA test --- test/orbit_determination.jl | 49 +++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index 967a4cc9..29bab1f3 100755 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -140,4 +140,53 @@ using NEOs: NEOSolution, numberofdays @test all(sol.scalings .< 8e-7) end + @testset "Interesting NEOs" begin + + # 2014 AA hit the Earth around January 2, 2014 02:49 UTC + + # Optical astrometry file + filename = joinpath("data", "2011_AA.txt") + # Download observations + get_radec_mpc("designation" => "2014 AA", filename) + # Load observations + radec = read_radec_mpc(filename) + # Delete astrometry file + rm(filename) + # Parameters + params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true) + + # Orbit Determination + sol = orbitdetermination(radec, params) + + # Values by January 26, 2024 + + # Vector of observations + @test length(radec) == 7 + @test numberofdays(radec) < 0.05 + # Orbit solution + @test isa(sol, NEOSolution{Float64, Float64}) + # Tracklets + @test length(sol.tracklets) == 1 + @test sol.tracklets[1].radec[1] == radec[1] + @test sol.tracklets[end].radec[end] == radec[end] + @test issorted(sol.tracklets) + # Backward integration + @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] + @test all( norm.(sol.bwd.x, Inf) .< 2 ) + @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) + # Forward integration + @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] + @test all( norm.(sol.fwd.x, Inf) .< 1e9 ) + @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) + # Vector of residuals + @test length(sol.res) == 7 + @test iszero(count(outlier.(sol.res))) + # Least squares fit + @test sol.fit.success + @test all( sigmas(sol) .< 1e-3 ) + @test nrms(sol) < 0.13 + # Scalig factors + @test all(sol.scalings .< 1e-5) + end + end \ No newline at end of file From 7207cb03751750d181157eabf857604f29cbed3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 26 Jan 2024 13:38:08 -0600 Subject: [PATCH 115/173] Add 2008 TC3 test --- src/orbit_determination/gauss_method.jl | 8 +- src/orbit_determination/outlier_rejection.jl | 8 +- src/orbit_determination/tooshortarc.jl | 7 +- src/propagation/parameters.jl | 20 ++-- test/orbit_determination.jl | 104 ++++++++++++++++++- 5 files changed, 127 insertions(+), 20 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 429dd480..b296f8b1 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -467,9 +467,9 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} # Julian day when to start propagation jd0 = datetime2julian(dates[triplet[2]]) # Number of years in forward integration - nyears_fwd = (tf - jd0 + 2) / yr + nyears_fwd = (tf - jd0 + params.fwdoffset) / yr # Number of years in backward integration - nyears_bwd = -(jd0 - t0 + 2) / yr + nyears_bwd = -(jd0 - t0 + params.bwdoffset) / yr # Gauss method solution sol = gauss_method(observatories[triplet], dates[triplet], α[triplet] .+ dq[1:3], δ[triplet] .+ dq[4:6]; niter = params.niter) @@ -485,7 +485,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} bwd::TaylorInterpolant{T, TaylorN{T}, 2} = propagate( RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q0, params ) - if !issuccessfulprop(bwd, t0 - jd0) + if !issuccessfulprop(bwd, t0 - jd0; tol = params.coeffstol) continue end @@ -493,7 +493,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} fwd::TaylorInterpolant{T, TaylorN{T}, 2} = propagate( RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q0, params ) - if !issuccessfulprop(fwd, tf - jd0) + if !issuccessfulprop(fwd, tf - jd0; tol = params.coeffstol) continue end diff --git a/src/orbit_determination/outlier_rejection.jl b/src/orbit_determination/outlier_rejection.jl index d1ab00eb..baf94a0a 100644 --- a/src/orbit_determination/outlier_rejection.jl +++ b/src/orbit_determination/outlier_rejection.jl @@ -35,9 +35,9 @@ function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, # Julian day of first (last) observation t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) # Number of years in forward integration - nyears_fwd = (tf - jd0 + 2) / yr + nyears_fwd = (tf - jd0 + params.fwdoffset) / yr # Number of years in backward integration - nyears_bwd = -(jd0 - t0 + 2) / yr + nyears_bwd = -(jd0 - t0 + params.bwdoffset) / yr # Dynamical function dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! # Initial conditions (T) @@ -52,14 +52,14 @@ function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, # Backward integration bwd = propagate(dynamics, jd0, nyears_bwd, q, params) - if !issuccessfulprop(bwd, t0 - jd0) + if !issuccessfulprop(bwd, t0 - jd0; tol = params.coeffstol) return zero(NEOSolution{T, T}) end # Forward integration fwd = propagate(dynamics, jd0, nyears_fwd, q, params) - if !issuccessfulprop(fwd, tf - jd0) + if !issuccessfulprop(fwd, tf - jd0; tol = params.coeffstol) return zero(NEOSolution{T, T}) end diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index baf74e21..aa371735 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -321,12 +321,13 @@ function propres(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{U}, # Time of first (last) observation t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) # Years in backward (forward) integration - nyears_bwd = -(jd0 - t0 + 0.5) / yr - nyears_fwd = (tf - jd0 + 0.5) / yr + nyears_bwd = -(jd0 - t0 + params.bwdoffset) / yr + nyears_fwd = (tf - jd0 + params.fwdoffset) / yr # Backward (forward) integration bwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q0, params) fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q0, params) - if !issuccessfulprop(bwd, t0 - jd0) || !issuccessfulprop(fwd, tf - jd0) + if !issuccessfulprop(bwd, t0 - jd0; tol = params.coeffstol) || + !issuccessfulprop(fwd, tf - jd0; tol = params.coeffstol) return bwd, fwd, Vector{OpticalResidual{T, U}}(undef, 0) end # Sun (Earth) ephemeris diff --git a/src/propagation/parameters.jl b/src/propagation/parameters.jl index 5b69756c..a1503759 100644 --- a/src/propagation/parameters.jl +++ b/src/propagation/parameters.jl @@ -5,6 +5,9 @@ struct NEOParameters{T <: AbstractFloat} order::Int abstol::T parse_eqs::Bool + bwdoffset::T + fwdoffset::T + coeffstol::T # Residuals parameters mpc_catalogue_codes_201X::Vector{String} truth::String @@ -37,6 +40,8 @@ Parameters for all orbit determination functions. - `order::Int`: order of Taylor expansions wrt time (default: 25). - `abstol::T`: absolute tolerance used to compute propagation timestep (default: `1e-20`). - `parse_eqs::Bool`: whether to use the specialized method of `jetcoeffs` or not (default: `true`). +- `bwdoffset/fwdoffset::T`: days to propagate beyond first (bwd) / last (fwd) observation (default: `0.5`). +- `coeffstol::T`: maximum size of the coefficients (default: `10.0`). # Residuals Parameters @@ -64,16 +69,17 @@ Parameters for all orbit determination functions. - `max_per::T`: maximum allowed rejection percentage (default: `18.0`). """ function NEOParameters(; maxsteps::Int = 500, μ_ast::Vector{T} = μ_ast343_DE430[1:end], - order::Int = 25, abstol::T = 1e-20, parse_eqs::Bool = true, - debias_table::String = "2018", niter::Int = 5, max_triplets::Int = 10, - varorder::Int = 5, Q_max::T = 5.0, maxiter::Int = 100, - max_per::T = 18.0) where {T <: AbstractFloat} + order::Int = 25, abstol::T = 1e-20, parse_eqs::Bool = true, bwdoffset::T = 0.5, + fwdoffset::T = 0.5, coeffstol::T = 10.0, debias_table::String = "2018", + niter::Int = 5, max_triplets::Int = 10, varorder::Int = 5, Q_max::T = 5.0, + maxiter::Int = 100, max_per::T = 18.0) where {T <: AbstractFloat} # Unfold debiasing matrix mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) # Assemble NEOParameters - return NEOParameters{T}(maxsteps, μ_ast, order, abstol, parse_eqs, mpc_catalogue_codes_201X, - truth, resol, bias_matrix, niter, max_triplets, varorder, Q_max, - maxiter, max_per) + return NEOParameters{T}(maxsteps, μ_ast, order, abstol, parse_eqs, bwdoffset, + fwdoffset, coeffstol, mpc_catalogue_codes_201X, truth, + resol, bias_matrix, niter, max_triplets, varorder, Q_max, + maxiter, max_per) end function NEOParameters(params::NEOParameters{T}; kwargs...) where {T <: AbstractFloat} diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index 29bab1f3..ec0e3ceb 100755 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -1,6 +1,7 @@ # This file is part of the NEOs.jl package; MIT licensed using NEOs +using Dates using PlanetaryEphemeris using LinearAlgebra using Test @@ -141,11 +142,12 @@ using NEOs: NEOSolution, numberofdays end @testset "Interesting NEOs" begin + using NEOs: reduce_tracklets, selecteph, sseph, propres, evalfit - # 2014 AA hit the Earth around January 2, 2014 02:49 UTC + # 2014 AA hit the Earth around January 2, 2014, 02:49 UTC # Optical astrometry file - filename = joinpath("data", "2011_AA.txt") + filename = joinpath("data", "2014_AA.txt") # Download observations get_radec_mpc("designation" => "2014 AA", filename) # Load observations @@ -187,6 +189,104 @@ using NEOs: NEOSolution, numberofdays @test nrms(sol) < 0.13 # Scalig factors @test all(sol.scalings .< 1e-5) + + # 2008 TC3 entered the Earth's atmosphere around October 7, 2008, 02:46 UTC + + # Optical astrometry file + filename = joinpath("data", "2008_TC3.txt") + # Download observations + get_radec_mpc("designation" => "2008 TC3", filename) + # Load observations + radec = read_radec_mpc(filename) + # Delete astrometry file + rm(filename) + # Parameters + params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, + coeffstol = Inf) + + # Observations before October 6, 2008, 10:00 UTC + idxs = findall(x -> date(x) < DateTime(2008, 10, 06, 10), radec) + # Restricted Orbit Determination + sol = orbitdetermination(radec[idxs], params) + + # Tracklets + tracklets = reduce_tracklets(radec) + # Time of first (last) observation [julian days] + t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) + # Sun (earth's) ephemeris + eph_su = selecteph(NEOs.sseph, su) + eph_ea = selecteph(sseph, ea) + + # Initial time of propagation [julian days] + jd0 = sol.bwd.t0 + J2000 + # Years in backward (forward) propagation + nyears_bwd = -(jd0 - t0 + 0.5) / yr + nyears_fwd = (tf - jd0 + 0.5) / yr + # Initial conditions + q0 = sol() + scalings = abs.(q0) ./ 10^6 + dq = NEOs.scaled_variables("dx", scalings, order = 5) + q = q0 + dq + # Propagation and residuals + bwd = NEOs.propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q, params) + fwd = NEOs.propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q, params) + res = residuals(radec, params; + xvs = et -> auday2kmsec(eph_su(et/daysec)), + xve = et -> auday2kmsec(eph_ea(et/daysec)), + xva = et -> bwdfwdeph(et, bwd, fwd)) + # Least squares fit + fit = tryls(res, zeros(6), params.niter) + # Orbit with all the observations + sol = evalfit(NEOSolution(tracklets, bwd, fwd, res, fit, scalings)) + + # Initial time of propagation [julian days] + jd0 = sol.bwd.t0 + J2000 + # Initial conditions + q0 = sol() + scalings = abs.(q0) ./ 10^6 + dq = NEOs.scaled_variables("dx", scalings, order = 5) + q = q0 + dq + # Propagation and residuals + bwd = NEOs.propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q, params) + fwd = NEOs.propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q, params) + res = residuals(radec, params; + xvs = et -> auday2kmsec(eph_su(et/daysec)), + xve = et -> auday2kmsec(eph_ea(et/daysec)), + xva = et -> bwdfwdeph(et, bwd, fwd)) + # Least squares fit + fit = tryls(res, zeros(6), params.niter) + # Orbit refinement + sol = evalfit(NEOSolution(tracklets, bwd, fwd, res, fit, scalings)) + + # Values by January 26, 2024 + + # Vector of observations + @test length(radec) == 883 + @test numberofdays(radec) < 0.80 + # Orbit solution + @test isa(sol, NEOSolution{Float64, Float64}) + # Tracklets + @test length(sol.tracklets) == 29 + @test sol.tracklets[1].radec[1] == radec[1] + @test sol.tracklets[end].radec[end] == radec[end] + @test issorted(sol.tracklets) + # Backward integration + @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] + @test all( norm.(sol.bwd.x, Inf) .< 2 ) + @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) + # Forward integration + @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] + @test all( norm.(sol.fwd.x, Inf) .< 1e55 ) + @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) + # Vector of residuals + @test length(sol.res) == 883 + @test iszero(count(outlier.(sol.res))) + # Least squares fit + @test sol.fit.success + @test all( sigmas(sol) .< 1e-7 ) + @test nrms(sol) < 0.61 + # Scalig factors + @test all(sol.scalings .< 1e-5) end end \ No newline at end of file From 5052462459d84e0a32fa1ce4728ebc0ede339feb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 26 Jan 2024 13:40:20 -0600 Subject: [PATCH 116/173] Minor fix --- test/orbit_determination.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index ec0e3ceb..b6cd8dfe 100755 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -286,7 +286,7 @@ using NEOs: NEOSolution, numberofdays @test all( sigmas(sol) .< 1e-7 ) @test nrms(sol) < 0.61 # Scalig factors - @test all(sol.scalings .< 1e-5) + @test all(sol.scalings .< 1e-6) end end \ No newline at end of file From baeca584ac88d22465506128d1618688be0c3b94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 28 Jan 2024 08:30:08 -0600 Subject: [PATCH 117/173] Reduce fwdoffset in 2008 TC3 test --- test/orbit_determination.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index b6cd8dfe..4e5f1ee5 100755 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -202,7 +202,7 @@ using NEOs: NEOSolution, numberofdays rm(filename) # Parameters params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, - coeffstol = Inf) + coeffstol = Inf, fwdoffset = 0.007) # Observations before October 6, 2008, 10:00 UTC idxs = findall(x -> date(x) < DateTime(2008, 10, 06, 10), radec) From eb656045f5b8bccdc9246ae20fa67733688aac6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 28 Jan 2024 14:44:58 -0600 Subject: [PATCH 118/173] Minor fix in constants.jl --- src/constants.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/constants.jl b/src/constants.jl index 7ac44a19..4f60aadb 100755 --- a/src/constants.jl +++ b/src/constants.jl @@ -133,9 +133,9 @@ const mpc_catalogue_codes_2018 = ["a", "b", "c", "d", "e", "g", "i", "j", "l", " # URLs # MPC catalogues file url -const CATALOGUES_MPC_URL = "https://minorplanetcenter.net/iau/info/CatalogueCodes.html" +const CATALOGUES_MPC_URL = "https://www.minorplanetcenter.net/iau/info/CatalogueCodes.html" # MPC observatories file url -const OBSERVATORIES_MPC_URL = "https://minorplanetcenter.net/iau/lists/ObsCodes.html" +const OBSERVATORIES_MPC_URL = "https://www.minorplanetcenter.net/iau/lists/ObsCodes.html" # MPC database search url const search_mpc_url = "https://www.minorplanetcenter.net/db_search/show_object?utf8=%E2%9C%93&object_id=" From 2ec4c573e2638a4e5a0c223e34c2cf821058c330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 1 Feb 2024 08:56:11 -0600 Subject: [PATCH 119/173] Update HORIZONS and TS --- Project.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index 3b5bd02c..172821c7 100755 --- a/Project.toml +++ b/Project.toml @@ -41,7 +41,7 @@ Clustering = "0.15" DataFrames = "1.5" DelimitedFiles = "1" Downloads = "1" -HORIZONS = "0.3" +HORIZONS = "0.4" HTTP = "1.9.5" Healpix = "4" JLD2 = "0.4" @@ -55,5 +55,5 @@ Scratch = "1.2" StatsBase = "0.33, 0.34" Tables = "1.10" TaylorIntegration = "0.14" -TaylorSeries = "0.15" +TaylorSeries = "0.16" julia = "1.6" From e28556562019ff881ff1ea1348fb8075847fb083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 1 Feb 2024 09:51:13 -0600 Subject: [PATCH 120/173] Update TaylorInterpolant --- src/constants.jl | 8 +++--- src/observations/jpl_eph.jl | 16 ++++------- src/orbit_determination/gauss_method.jl | 4 +-- src/orbit_determination/neosolution.jl | 36 +++++++++++++------------ src/propagation/propagation.jl | 19 ++----------- test/propagation.jl | 6 ++--- 6 files changed, 35 insertions(+), 54 deletions(-) diff --git a/src/constants.jl b/src/constants.jl index 4f60aadb..c3f32c7f 100755 --- a/src/constants.jl +++ b/src/constants.jl @@ -7,10 +7,10 @@ const scratch_path = Ref{String}("") # Load Solar System, accelerations, newtonian potentials and TT-TDB 2000-2100 ephemeris const sseph_artifact_path = joinpath(artifact"sseph_p100", "sseph343ast016_p100y_et.jld2") -const sseph::TaylorInterpolant{Float64, Float64, 2} = JLD2.load(sseph_artifact_path, "ss16ast_eph") -const acceph::TaylorInterpolant{Float64, Float64, 2} = JLD2.load(sseph_artifact_path, "acc_eph") -const poteph::TaylorInterpolant{Float64, Float64, 2} = JLD2.load(sseph_artifact_path, "pot_eph") -const ttmtdb::TaylorInterpolant{Float64, Float64, 1} = TaylorInterpolant(sseph.t0, sseph.t, sseph.x[:,end]) +const sseph::TaylorInterpolant{Float64, Float64, 2, Vector{Float64}, Matrix{Taylor1{Float64}}} = JLD2.load(sseph_artifact_path, "ss16ast_eph") +const acceph::TaylorInterpolant{Float64, Float64, 2, Vector{Float64}, Matrix{Taylor1{Float64}}} = JLD2.load(sseph_artifact_path, "acc_eph") +const poteph::TaylorInterpolant{Float64, Float64, 2, Vector{Float64}, Matrix{Taylor1{Float64}}} = JLD2.load(sseph_artifact_path, "pot_eph") +const ttmtdb::TaylorInterpolant{Float64, Float64, 1, Vector{Float64}, Vector{Taylor1{Float64}}} = TaylorInterpolant(sseph.t0, sseph.t, sseph.x[:,end]) # Earth orientation parameters (eop) 2000 const eop_IAU2000A::EopIau2000A = fetch_iers_eop(Val(:IAU2000A)) diff --git a/src/observations/jpl_eph.jl b/src/observations/jpl_eph.jl index 17ad9beb..dd797500 100755 --- a/src/observations/jpl_eph.jl +++ b/src/observations/jpl_eph.jl @@ -117,7 +117,7 @@ See also [`getposvel`](@ref). dtt_tdb(et) = getposvel(1000000001, 1000000000, cte(et))[4] # units: seconds/seconds @doc raw""" - loadpeeph(eph::TaylorInterpolant{Float64, Float64, 2} = sseph, t_0::T = sseph.t0, + loadpeeph(eph::TaylorInterpolant = sseph, t_0::T = sseph.t0, t_f::S = sseph.t0 + sseph.t[end]) where {T, S <: Real} Load ephemeris produced by `PlanetaryEphemeris.jl` in timerange `[t_0, t_f] ⊆ [0.0, 36525.0]` @@ -131,7 +131,7 @@ where `t` must have units of TDB days since J2000. The available options for `ep Running this function for the first time will download the `sseph_p100` artifact (885 MB) which can take several minutes. """ -function loadpeeph(eph::TaylorInterpolant{Float64, Float64, 2} = sseph, t_0::T = sseph.t0, +function loadpeeph(eph::TaylorInterpolant = sseph, t_0::T = sseph.t0, t_f::S = sseph.t0 + sseph.t[end]) where {T, S <: Real} @assert 0.0 ≤ t_0 ≤ t_f ≤ 36525.0 i_0 = searchsortedlast(eph.t, t_0) @@ -140,19 +140,13 @@ function loadpeeph(eph::TaylorInterpolant{Float64, Float64, 2} = sseph, t_0::T = end @doc raw""" - bwdfwdeph(et::Union{T, Taylor1{T}, TaylorN{T}, Taylor1{TaylorN{T}}}, - bwd::TaylorInterpolant{T, U, 2}, - fwd::TaylorInterpolant{T, U, 2} - ) where {T <: AbstractFloat, U <: Union{T, TaylorN{T}}} + bwdfwdeph(et::U, bwd::TaylorInterpolant, fwd::TaylorInterpolant) where {U <: Number} Paste a backward and a forward integration, evaluate at `et` and convert from [au, au/day] -> [km, km/sec]. """ -function bwdfwdeph(et::Union{T, Taylor1{T}, TaylorN{T}, Taylor1{TaylorN{T}}}, - bwd::TaylorInterpolant{T,U,2}, - fwd::TaylorInterpolant{T,U,2} - ) where {T <: AbstractFloat, U <: Union{T, TaylorN{T}}} - @assert bwd.t0 == fwd.t0 "Backward and forward TaylorInterpolant initial times must match" +function bwdfwdeph(et::U, bwd::TaylorInterpolant, fwd::TaylorInterpolant) where {U <: Number} + @assert bwd.t0 == fwd.t0 "Backward and forward initial times must match" t = et/daysec t0 = bwd.t0 if t <= t0 diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index b296f8b1..31abce83 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -482,7 +482,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} # Initial conditions (jet transport) q0::Vector{TaylorN{T}} = sol[i].statevect .+ eph_su(jd0 - PE.J2000) # Backward propagation - bwd::TaylorInterpolant{T, TaylorN{T}, 2} = propagate( + bwd = propagate( RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q0, params ) if !issuccessfulprop(bwd, t0 - jd0; tol = params.coeffstol) @@ -490,7 +490,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} end # Forward propagation - fwd::TaylorInterpolant{T, TaylorN{T}, 2} = propagate( + fwd = propagate( RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q0, params ) if !issuccessfulprop(fwd, tf - jd0; tol = params.coeffstol) diff --git a/src/orbit_determination/neosolution.jl b/src/orbit_determination/neosolution.jl index a94dbfef..34cf75cc 100755 --- a/src/orbit_determination/neosolution.jl +++ b/src/orbit_determination/neosolution.jl @@ -6,7 +6,7 @@ The outcome of the orbit determination process for a NEO. # Fields - `tracklets::Vector{Tracklet{T}}`: vector of tracklets. -- `bwd/fwd::TaylorInterpolant{T, U, 2}`: backward (forward) integration. +- `bwd/fwd::TaylorInterpolant{T, U, 2, Vector{T}, Matrix{Taylor1{U}}}`: backward (forward) integration. - `t_bwd/t_fwd::Vector{U}`: time of Earth close approach. - `x_bwd/x_fwd::Vector{U}`: state vector at Earth close approach. - `g_bwd/g_fwd::Vector{U}`: geocentric distance at close approach. @@ -16,11 +16,11 @@ The outcome of the orbit determination process for a NEO. """ @auto_hash_equals struct NEOSolution{T <: Real, U <: Number} tracklets::Vector{Tracklet{T}} - bwd::TaylorInterpolant{T, U, 2} + bwd::TaylorInterpolant{T, U, 2, Vector{T}, Matrix{Taylor1{U}}} t_bwd::Vector{U} x_bwd::Matrix{U} g_bwd::Vector{U} - fwd::TaylorInterpolant{T, U, 2} + fwd::TaylorInterpolant{T, U, 2, Vector{T}, Matrix{Taylor1{U}}} t_fwd::Vector{U} x_fwd::Matrix{U} g_fwd::Vector{U} @@ -30,15 +30,17 @@ The outcome of the orbit determination process for a NEO. # Inner constructor function NEOSolution{T, U}( tracklets::Vector{Tracklet{T}}, - bwd::TaylorInterpolant{T, U, 2}, t_bwd::Vector{U}, x_bwd::Matrix{U}, g_bwd::Vector{U}, - fwd::TaylorInterpolant{T, U, 2}, t_fwd::Vector{U}, x_fwd::Matrix{U}, g_fwd::Vector{U}, + bwd::TaylorInterpolant{T, U, 2, VT, X}, t_bwd::Vector{U}, x_bwd::Matrix{U}, g_bwd::Vector{U}, + fwd::TaylorInterpolant{T, U, 2, VT, X}, t_fwd::Vector{U}, x_fwd::Matrix{U}, g_fwd::Vector{U}, res::Vector{OpticalResidual{T, U}}, fit::LeastSquaresFit{T}, scalings::Vector{T} - ) where {T <: Real, U <: Number} + ) where {T <: Real, U <: Number, VT <: AbstractVector{T}, X <: AbstractMatrix{Taylor1{U}}} @assert bwd.t0 == fwd.t0 "Backward and forward propagation initial times must match" + _bwd_ = TaylorInterpolant(bwd.t0, bwd.t, collect(bwd.x)) + _fwd_ = TaylorInterpolant(fwd.t0, fwd.t, collect(fwd.x)) new{T, U}( tracklets, - bwd, t_bwd, x_bwd, g_bwd, - fwd, t_fwd, x_fwd, g_fwd, + _bwd_, t_bwd, x_bwd, g_bwd, + _fwd_, t_fwd, x_fwd, g_fwd, res, fit, scalings ) end @@ -46,10 +48,10 @@ end # Outer constructors function NEOSolution( tracklets::Vector{Tracklet{T}}, - bwd::TaylorInterpolant{T, U, 2}, t_bwd::Vector{U}, x_bwd::Matrix{U}, g_bwd::Vector{U}, - fwd::TaylorInterpolant{T, U, 2}, t_fwd::Vector{U}, x_fwd::Matrix{U}, g_fwd::Vector{U}, + bwd::TaylorInterpolant{T, U, 2, VT, X}, t_bwd::Vector{U}, x_bwd::Matrix{U}, g_bwd::Vector{U}, + fwd::TaylorInterpolant{T, U, 2, VT, X}, t_fwd::Vector{U}, x_fwd::Matrix{U}, g_fwd::Vector{U}, res::Vector{OpticalResidual{T, U}}, fit::LeastSquaresFit{T}, scalings::Vector{T} -) where {T <: Real, U <: Number} +) where {T <: Real, U <: Number, VT <: AbstractVector{T}, X <: AbstractMatrix{Taylor1{U}}} NEOSolution{T, U}( tracklets, bwd, t_bwd, x_bwd, g_bwd, @@ -60,9 +62,9 @@ end function NEOSolution( tracklets::Vector{Tracklet{T}}, - bwd::TaylorInterpolant{T, U, 2}, fwd::TaylorInterpolant{T, U, 2}, + bwd::TaylorInterpolant{T, U, 2, VT, X}, fwd::TaylorInterpolant{T, U, 2, VT, X}, res::Vector{OpticalResidual{T, U}}, fit::LeastSquaresFit{T}, scalings::Vector{T} -) where {T <: Real, U <: Number} +) where {T <: Real, U <: Number, VT <: AbstractVector{T}, X <: AbstractMatrix{Taylor1{U}}} # Backward roots t_bwd = Vector{U}(undef, 0) x_bwd = Matrix{U}(undef, 0, 0) @@ -102,14 +104,14 @@ function evalfit(sol::NEOSolution{T, TaylorN{T}}) where {T <: Real} δs = sol.fit.x # Evaluate backward integration new_bwd_x = map(x -> Taylor1(x.coeffs(δs)), sol.bwd.x); - new_bwd = TaylorInterpolant{T, T, 2}(sol.bwd.t0, sol.bwd.t, new_bwd_x) + new_bwd = TaylorInterpolant(sol.bwd.t0, sol.bwd.t, new_bwd_x) # Evaluate backward roots new_t_bwd = sol.t_bwd(δs) new_x_bwd = sol.x_bwd(δs) new_g_bwd = sol.g_bwd(δs) # Evaluate forward integration new_fwd_x = map(x -> Taylor1(x.coeffs(δs)), sol.fwd.x); - new_fwd = TaylorInterpolant{T, T, 2}(sol.fwd.t0, sol.fwd.t, new_fwd_x) + new_fwd = TaylorInterpolant(sol.fwd.t0, sol.fwd.t, new_fwd_x) # Evaluate forward roots new_t_fwd = sol.t_fwd(δs) new_x_fwd = sol.x_fwd(δs) @@ -128,11 +130,11 @@ end # Definition of zero NEOSolution function zero(::Type{NEOSolution{T, U}}) where {T <: Real, U <: Number} tracklets = Vector{Tracklet{T}}(undef, 0) - bwd = TaylorInterpolant{T, U, 2}(zero(T), zeros(T, 1), Matrix{Taylor1{U}}(undef, 0, 0)) + bwd = zero(TaylorInterpolant{T, U, 2, Vector{T}, Matrix{Taylor1{U}}}) t_bwd = Vector{U}(undef, 0) x_bwd = Matrix{U}(undef, 0, 0) g_bwd = Vector{U}(undef, 0) - fwd = TaylorInterpolant{T, U, 2}(zero(T), zeros(T, 1), Matrix{Taylor1{U}}(undef, 0, 0)) + fwd = zero(TaylorInterpolant{T, U, 2, Vector{T}, Matrix{Taylor1{U}}}) t_fwd = Vector{U}(undef, 0) x_fwd = Matrix{U}(undef, 0, 0) g_fwd = Vector{U}(undef, 0) diff --git a/src/propagation/propagation.jl b/src/propagation/propagation.jl index e8bb86d3..dc5d3b9d 100755 --- a/src/propagation/propagation.jl +++ b/src/propagation/propagation.jl @@ -42,15 +42,7 @@ function scaled_variables(names::String = "δx", c::Vector{T} = fill(1e-6, 6); o return dq end -# Definition of zero TaylorInterpolant{T, U, 2} -function zero(::Type{TaylorInterpolant{T, U, 2}}) where {T <: Real, U <: Number} - return TaylorInterpolant{T, U, 2}(zero(T), zeros(T, 1), Matrix{Taylor1{U}}(undef, 0, 0)) -end - -iszero(x::TaylorInterpolant{T, U, 2}) where {T <: Real, U <: Number} = x == zero(TaylorInterpolant{T, U, 2}) - -function issuccessfulprop(sol::TaylorInterpolant{T, U, 2}, t::T; - tol::T = 10.0) where {T <: Real, U <: Number} +function issuccessfulprop(sol::TaylorInterpolant, t::T; tol::T = 10.0) where {T <: Real} # Zero TaylorInterpolant iszero(sol) && return false # Forward integration @@ -169,14 +161,7 @@ function propagate(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, @time tv, xv, psol = taylorinteg(dynamics, _q0, _t0, _tmax, order, abstol, Val(true), _params; maxsteps = maxsteps, parse_eqs = parse_eqs) - # Assemble TaylorInterpolant - t0 = jd0 - JD_J2000 - t = tv .- tv[1] - if issorted(t) || issorted(t, rev = true) - return TaylorInterpolant{T, U, 2}(t0, t, psol) - else - return zero(TaylorInterpolant{T, U, 2}) - end + return TaylorInterpolant(jd0 - JD_J2000, tv .- tv[1], psol) end @doc raw""" diff --git a/test/propagation.jl b/test/propagation.jl index e87f4305..56dba5a4 100755 --- a/test/propagation.jl +++ b/test/propagation.jl @@ -336,11 +336,11 @@ using InteractiveUtils: methodswith ) # Solar System ephemeris - sseph_obs::TaylorInterpolant{Float64,Float64,2} = loadpeeph(NEOs.sseph, sol.t0, sol.t0 + sol.t[end]) + sseph_obs::TaylorInterpolant{Float64, Float64, 2, Vector{Float64}, Matrix{Taylor1{Float64}}} = loadpeeph(NEOs.sseph, sol.t0, sol.t0 + sol.t[end]) # Sun's ephemeris - eph_su::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph_obs, su) + eph_su::TaylorInterpolant{Float64, Float64, 2, Vector{Float64}, Matrix{Taylor1{Float64}}} = selecteph(sseph_obs, su) # Earth's ephemeris - eph_ea::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph_obs, ea) + eph_ea::TaylorInterpolant{Float64, Float64, 2, Vector{Float64}, Matrix{Taylor1{Float64}}} = selecteph(sseph_obs, ea) # Read optical astrometry file obs_radec_mpc_apophis = NEOs.read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) From 6fbd578323d3953b9e484110a1a30709cff23309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 1 Feb 2024 11:05:44 -0600 Subject: [PATCH 121/173] Minor fix --- test/propagation.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/propagation.jl b/test/propagation.jl index 56dba5a4..9dc15980 100755 --- a/test/propagation.jl +++ b/test/propagation.jl @@ -336,11 +336,11 @@ using InteractiveUtils: methodswith ) # Solar System ephemeris - sseph_obs::TaylorInterpolant{Float64, Float64, 2, Vector{Float64}, Matrix{Taylor1{Float64}}} = loadpeeph(NEOs.sseph, sol.t0, sol.t0 + sol.t[end]) + sseph_obs = loadpeeph(NEOs.sseph, sol.t0, sol.t0 + sol.t[end]) # Sun's ephemeris - eph_su::TaylorInterpolant{Float64, Float64, 2, Vector{Float64}, Matrix{Taylor1{Float64}}} = selecteph(sseph_obs, su) + eph_su = selecteph(sseph_obs, su) # Earth's ephemeris - eph_ea::TaylorInterpolant{Float64, Float64, 2, Vector{Float64}, Matrix{Taylor1{Float64}}} = selecteph(sseph_obs, ea) + eph_ea = selecteph(sseph_obs, ea) # Read optical astrometry file obs_radec_mpc_apophis = NEOs.read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) From 531c6387cdb10079291340edd700db1375513ba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 1 Feb 2024 11:42:33 -0600 Subject: [PATCH 122/173] Add eph_su(ea) to NEOParameters --- src/orbit_determination/gauss_method.jl | 59 +++++--------------- src/orbit_determination/outlier_rejection.jl | 35 ++---------- src/orbit_determination/tooshortarc.jl | 16 ++---- src/propagation/parameters.jl | 11 +++- test/orbit_determination.jl | 29 +++------- 5 files changed, 39 insertions(+), 111 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 31abce83..fd5381d3 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -184,9 +184,9 @@ function heliocentric_energy(r::Vector{T}) where {T <: Number} end @doc raw""" - gauss_method(obs::Vector{RadecMPC{T}}; niter::Int = 5) where {T <: AbstractFloat} + gauss_method(obs::Vector{RadecMPC{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{DateTime}, - α::Vector{U}, δ::Vector{U}; niter::Int = 5) where {T <: Real, U <: Number} + α::Vector{U}, δ::Vector{U}, params::NEOParameters{T}) where {T <: Real, U <: Number} Core Gauss method of Initial Orbit determination (IOD). @@ -197,12 +197,12 @@ Core Gauss method of Initial Orbit determination (IOD). - `dates::Vector{DateTime}`: times of observation. - `α::Vector{U}`: right ascension [rad]. - `δ::Vector{U}`: declination [rad]. -- `niter::Int`: number of iterations for Newton's method. +- `params::NEOParameters{T}`: see `Gauss Method Parameters` of [`NEOParameters`](@ref). !!! reference See Algorithm 5.5 in page 274 https://doi.org/10.1016/C2016-0-02107-1. """ -function gauss_method(obs::Vector{RadecMPC{T}}; niter::Int = 5) where {T <: AbstractFloat} +function gauss_method(obs::Vector{RadecMPC{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} # Make sure observations are in temporal order sort!(obs) @@ -215,11 +215,11 @@ function gauss_method(obs::Vector{RadecMPC{T}}; niter::Int = 5) where {T <: Abst # Declination δ = dec.(obs) - return gauss_method(observatories, dates, α, δ; niter = niter) + return gauss_method(observatories, dates, α, δ, params) end function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{DateTime}, - α::Vector{U}, δ::Vector{U}; niter::Int = 5) where {T <: Real, U <: Number} + α::Vector{U}, δ::Vector{U}, params::NEOParameters{T}) where {T <: Real, U <: Number} # Check we have exactly three observations @assert length(observatories) == length(dates) == length(α) == length(δ) == 3 "Gauss method requires exactly three observations" @@ -240,12 +240,8 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da ρ_vec = vectors2matrix(topounit.(α, δ)) # Geocentric state vector of the observer [au, au/day] g_vec = kmsec2auday.(obsposvelECI.(observatories, t_et)) - # Sun's ephemeris - eph_su = selecteph(sseph, su) - # Earth's ephemeris - eph_ea = selecteph(sseph, ea) # Heliocentric state vector of the Earth [au, au/day] - G_vec = eph_ea.(t_days) - eph_su.(t_days) + G_vec = params.eph_ea.(t_days) - params.eph_su.(t_days) # Observer's heliocentric positions [au, au/day] R_vec = vectors2matrix(G_vec .+ g_vec)[:, 1:3] @@ -280,7 +276,7 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da c = -(μ_S^2)*(B*B) # Solve Lagrange equation - sol = solve_lagrange(a, b, c; niter = niter) + sol = solve_lagrange(a, b, c; niter = params.niter) # Number of solutions n_sol = length(sol) @@ -439,8 +435,6 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} observatories, dates, α, δ = observatory.(tracklets), date.(tracklets), ra.(tracklets), dec.(tracklets) # Observations triplets triplets = gauss_triplets(dates, params.max_triplets) - # Julian day of first (last) observation - t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) # Julian day when to start propagation jd0 = zero(T) # Start point of LS fits @@ -450,10 +444,6 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} # Jet transport perturbation (ra/dec) dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃", scalings, order = params.varorder) - # Sun's ephemeris - eph_su = selecteph(sseph, su) - # Earth's ephemeris - eph_ea = selecteph(sseph, ea) # Normalized root mean square error (NRMS) best_Q = T(Inf) # Break flag @@ -466,13 +456,9 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} triplet = triplets[j] # Julian day when to start propagation jd0 = datetime2julian(dates[triplet[2]]) - # Number of years in forward integration - nyears_fwd = (tf - jd0 + params.fwdoffset) / yr - # Number of years in backward integration - nyears_bwd = -(jd0 - t0 + params.bwdoffset) / yr # Gauss method solution sol = gauss_method(observatories[triplet], dates[triplet], α[triplet] .+ dq[1:3], - δ[triplet] .+ dq[4:6]; niter = params.niter) + δ[triplet] .+ dq[4:6], params) # Filter Gauss solutions by heliocentric energy filter!(x -> heliocentric_energy(x.statevect) <= 0, sol) @@ -480,30 +466,11 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} for i in eachindex(sol) # Initial conditions (jet transport) - q0::Vector{TaylorN{T}} = sol[i].statevect .+ eph_su(jd0 - PE.J2000) - # Backward propagation - bwd = propagate( - RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q0, params - ) - if !issuccessfulprop(bwd, t0 - jd0; tol = params.coeffstol) - continue - end - - # Forward propagation - fwd = propagate( - RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q0, params - ) - if !issuccessfulprop(fwd, tf - jd0; tol = params.coeffstol) - continue - end + q0 = sol[i].statevect .+ params.eph_su(jd0 - PE.J2000) - # O-C residuals - res::Vector{OpticalResidual{T, TaylorN{T}}} = residuals( - radec, params; - xvs = et -> auday2kmsec(eph_su(et/daysec)), - xve = et -> auday2kmsec(eph_ea(et/daysec)), - xva = et -> bwdfwdeph(et, bwd, fwd) - ) + # Propagation and residuals + bwd, fwd, res = propres(radec, jd0, q0, params) + iszero(length(res)) && continue # Subset of radec for orbit fit g_0 = triplet[1] diff --git a/src/orbit_determination/outlier_rejection.jl b/src/orbit_determination/outlier_rejection.jl index baf94a0a..2aeb0a93 100644 --- a/src/orbit_determination/outlier_rejection.jl +++ b/src/orbit_determination/outlier_rejection.jl @@ -24,22 +24,10 @@ via propagation and/or outlier rejection. function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, params::NEOParameters{T}) where {T <: AbstractFloat} - # Sun's ephemeris - eph_su = selecteph(sseph, su) - # Earth's ephemeris - eph_ea = selecteph(sseph, ea) # Origin x0 = zeros(T, 6) # Julian day to start propagation jd0 = sol.bwd.t0 + PE.J2000 - # Julian day of first (last) observation - t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) - # Number of years in forward integration - nyears_fwd = (tf - jd0 + params.fwdoffset) / yr - # Number of years in backward integration - nyears_bwd = -(jd0 - t0 + params.bwdoffset) / yr - # Dynamical function - dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! # Initial conditions (T) q0 = sol(sol.bwd.t0) # Scaling factors @@ -49,25 +37,10 @@ function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, # Initial conditions (jet transport) q = q0 .+ dq - # Backward integration - bwd = propagate(dynamics, jd0, nyears_bwd, q, params) - - if !issuccessfulprop(bwd, t0 - jd0; tol = params.coeffstol) - return zero(NEOSolution{T, T}) - end - - # Forward integration - fwd = propagate(dynamics, jd0, nyears_fwd, q, params) - - if !issuccessfulprop(fwd, tf - jd0; tol = params.coeffstol) - return zero(NEOSolution{T, T}) - end - - # Residuals - res = residuals(radec, params; - xvs = et -> auday2kmsec(eph_su(et/daysec)), - xve = et -> auday2kmsec(eph_ea(et/daysec)), - xva = et -> bwdfwdeph(et, bwd, fwd)) + # Propagation and residuals + bwd, fwd, res = propres(radec, jd0, q, params) + iszero(length(res)) && return zero(NEOSolution{T, T}) + # Orbit fit fit = tryls(res, x0, params.niter) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index aa371735..f6f5a5e8 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -51,7 +51,7 @@ end iszero(x::AdmissibleRegion{T}) where {T <: AbstractFloat} = x == zero(AdmissibleRegion{T}) # Outer constructor -function AdmissibleRegion(tracklet::Tracklet{T}) where {T <: AbstractFloat} +function AdmissibleRegion(tracklet::Tracklet{T}, params::NEOParameters{T}) where {T <: AbstractFloat} # Unfold obs, t_datetime, α, δ = observatory(tracklet), date(tracklet), ra(tracklet), dec(tracklet) v_α, v_δ, h = vra(tracklet), vdec(tracklet), mag(tracklet) @@ -61,11 +61,8 @@ function AdmissibleRegion(tracklet::Tracklet{T}) where {T <: AbstractFloat} t_days = datetime2days(t_datetime) # Time of observation [et seconds] t_et = datetime2et(t_datetime) - # Sun (Earth) ephemeris - eph_su = selecteph(sseph, su) - eph_ea = selecteph(sseph, ea) # Heliocentric position of the observer - q = eph_ea(t_days) + kmsec2auday(obsposvelECI(obs, t_et)) - eph_su(t_days) + q = params.eph_ea(t_days) + kmsec2auday(obsposvelECI(obs, t_et)) - params.eph_su(t_days) # Admissible region coefficients coeffs = admsreg_coeffs(α, δ, v_α, v_δ, ρ, ρ_α, ρ_δ, q) # Tiny object boundary @@ -330,13 +327,10 @@ function propres(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{U}, !issuccessfulprop(fwd, tf - jd0; tol = params.coeffstol) return bwd, fwd, Vector{OpticalResidual{T, U}}(undef, 0) end - # Sun (Earth) ephemeris - eph_su = selecteph(sseph, su) - eph_ea = selecteph(sseph, ea) # O-C residuals res = residuals(radec, params; - xvs = et -> auday2kmsec(eph_su(et/daysec)), - xve = et -> auday2kmsec(eph_ea(et/daysec)), + xvs = et -> auday2kmsec(params.eph_su(et/daysec)), + xve = et -> auday2kmsec(params.eph_ea(et/daysec)), xva = et -> bwdfwdeph(et, bwd, fwd)) return bwd, fwd, res @@ -504,7 +498,7 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, # Iterate tracklets for i in idxs # Admissible region - A = AdmissibleRegion(tracklets[i]) + A = AdmissibleRegion(tracklets[i], params) iszero(A) && continue # Center ρ = sum(A.ρ_domain) / 2 diff --git a/src/propagation/parameters.jl b/src/propagation/parameters.jl index a1503759..db2438a4 100644 --- a/src/propagation/parameters.jl +++ b/src/propagation/parameters.jl @@ -13,6 +13,8 @@ struct NEOParameters{T <: AbstractFloat} truth::String resol::Resolution bias_matrix::Matrix{T} + eph_su::TaylorInterpolant{T, T, 2, Vector{T}, Matrix{Taylor1{T}}} + eph_ea::TaylorInterpolant{T, T, 2, Vector{T}, Matrix{Taylor1{T}}} # Least squares fit parameters niter::Int # Gauss Method parameters @@ -75,11 +77,16 @@ function NEOParameters(; maxsteps::Int = 500, μ_ast::Vector{T} = μ_ast343_DE43 maxiter::Int = 100, max_per::T = 18.0) where {T <: AbstractFloat} # Unfold debiasing matrix mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) + # Sun (Earth) ephemeris + _su = selecteph(sseph, su) + eph_su = TaylorInterpolant(_su.t0, _su.t, collect(_su.x)) + _ea = selecteph(sseph, ea) + eph_ea = TaylorInterpolant(_ea.t0, _ea.t, collect(_ea.x)) # Assemble NEOParameters return NEOParameters{T}(maxsteps, μ_ast, order, abstol, parse_eqs, bwdoffset, fwdoffset, coeffstol, mpc_catalogue_codes_201X, truth, - resol, bias_matrix, niter, max_triplets, varorder, Q_max, - maxiter, max_per) + resol, bias_matrix, eph_su, eph_ea, niter, max_triplets, + varorder, Q_max, maxiter, max_per) end function NEOParameters(params::NEOParameters{T}; kwargs...) where {T <: AbstractFloat} diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index 4e5f1ee5..d70b89c3 100755 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -211,29 +211,18 @@ using NEOs: NEOSolution, numberofdays # Tracklets tracklets = reduce_tracklets(radec) - # Time of first (last) observation [julian days] - t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) - # Sun (earth's) ephemeris - eph_su = selecteph(NEOs.sseph, su) - eph_ea = selecteph(sseph, ea) - # Initial time of propagation [julian days] jd0 = sol.bwd.t0 + J2000 - # Years in backward (forward) propagation - nyears_bwd = -(jd0 - t0 + 0.5) / yr - nyears_fwd = (tf - jd0 + 0.5) / yr # Initial conditions q0 = sol() scalings = abs.(q0) ./ 10^6 dq = NEOs.scaled_variables("dx", scalings, order = 5) q = q0 + dq # Propagation and residuals - bwd = NEOs.propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q, params) - fwd = NEOs.propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q, params) - res = residuals(radec, params; - xvs = et -> auday2kmsec(eph_su(et/daysec)), - xve = et -> auday2kmsec(eph_ea(et/daysec)), - xva = et -> bwdfwdeph(et, bwd, fwd)) + bwd, fwd, res = propres(radec, jd0, q, params) + + @test length(res) == 883 + # Least squares fit fit = tryls(res, zeros(6), params.niter) # Orbit with all the observations @@ -247,12 +236,10 @@ using NEOs: NEOSolution, numberofdays dq = NEOs.scaled_variables("dx", scalings, order = 5) q = q0 + dq # Propagation and residuals - bwd = NEOs.propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q, params) - fwd = NEOs.propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q, params) - res = residuals(radec, params; - xvs = et -> auday2kmsec(eph_su(et/daysec)), - xve = et -> auday2kmsec(eph_ea(et/daysec)), - xva = et -> bwdfwdeph(et, bwd, fwd)) + bwd, fwd, res = propres(radec, jd0, q, params) + + @test length(res) == 883 + # Least squares fit fit = tryls(res, zeros(6), params.niter) # Orbit refinement From 7954699724871cf5c71c43695f95876bc662918b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 1 Feb 2024 14:57:28 -0600 Subject: [PATCH 123/173] Float64 -> T in AdmissibleRegion --- src/orbit_determination/tooshortarc.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index f6f5a5e8..045bdb4e 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -74,7 +74,7 @@ function AdmissibleRegion(tracklet::Tracklet{T}, params::NEOParameters{T}) where end # Maximum range (heliocentric constraint) ρ_max = max_range(coeffs, ρ_min) - iszero(ρ_max) && return zero(AdmissibleRegion{Float64}) + iszero(ρ_max) && return zero(AdmissibleRegion{T}) # Range domain ρ_domain = [ρ_min, ρ_max] # Range rate domain @@ -83,13 +83,13 @@ function AdmissibleRegion(tracklet::Tracklet{T}, params::NEOParameters{T}) where # Range rate symmetry level v_ρ_mid = range_rate(coeffs, ρ_max)[1] # Boundary points - Fs = Matrix{Float64}(undef, 3, 2) + Fs = Matrix{T}(undef, 3, 2) Fs[1, :] .= [ρ_min, v_ρ_min] Fs[2, :] .= [ρ_min, v_ρ_max] Fs[3, :] .= [ρ_max, v_ρ_mid] - return AdmissibleRegion{Float64}(t_datetime, α, δ, v_α, v_δ, ρ, ρ_α, ρ_δ, q, - coeffs, ρ_domain, v_ρ_domain, Fs, obs) + return AdmissibleRegion{T}(t_datetime, α, δ, v_α, v_δ, ρ, ρ_α, ρ_δ, q, + coeffs, ρ_domain, v_ρ_domain, Fs, obs) end @doc raw""" From b31f8ba4be26b554895a855691858a0213bccd05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 4 Feb 2024 09:53:57 -0600 Subject: [PATCH 124/173] Minor fixes --- src/constants.jl | 2 ++ src/orbit_determination/tooshortarc.jl | 31 +++++++++++++++++--------- src/propagation/propagation.jl | 6 ++++- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/constants.jl b/src/constants.jl index c3f32c7f..8699c268 100755 --- a/src/constants.jl +++ b/src/constants.jl @@ -201,3 +201,5 @@ const ϵ0_deg = 84381.448/3_600 const k_gauss = 0.017_202_098_95 # Earth's sphere of influence radius [AU] const R_SI = 0.010044 +# Earth's physical radius [AU] +const R_EA = 4.2e-5 diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 045bdb4e..da0c348d 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -65,16 +65,25 @@ function AdmissibleRegion(tracklet::Tracklet{T}, params::NEOParameters{T}) where q = params.eph_ea(t_days) + kmsec2auday(obsposvelECI(obs, t_et)) - params.eph_su(t_days) # Admissible region coefficients coeffs = admsreg_coeffs(α, δ, v_α, v_δ, ρ, ρ_α, ρ_δ, q) - # Tiny object boundary - H_max = 32.0 # Maximum allowed absolute magnitude + # Maximum range (heliocentric constraint) + ρ_max = max_range(coeffs) + iszero(ρ_max) && return zero(AdmissibleRegion{T}) + # Minimum range if isnan(h) - ρ_min = R_SI + if R_SI < ρ_max + # Earth's sphere of influence radius + ρ_min = R_SI + else + # Earth's physical radius + ρ_min = R_EA + end else + # Maximum allowed absolute magnitude + H_max = 32.0 + # Tiny object boundary ρ_min = 10^((h - H_max)/5) end - # Maximum range (heliocentric constraint) - ρ_max = max_range(coeffs, ρ_min) - iszero(ρ_max) && return zero(AdmissibleRegion{T}) + ρ_min > ρ_max && return zero(AdmissibleRegion{T}) # Range domain ρ_domain = [ρ_min, ρ_max] # Range rate domain @@ -193,14 +202,14 @@ end range_rate(A::AdmissibleRegion{T}, ρ::S) where {T, S <: AbstractFloat} = range_rate(A.coeffs, ρ) @doc raw""" - max_range(coeffs::Vector{T}, ρ_min::T) where {T <: AbstractFloat} + max_range(coeffs::Vector{T}) where {T <: AbstractFloat} Return the maximum possible range in the boundary of an admissible region -with coefficients `coeffs` and minimum allowed range `ρ_min`. +with coefficients `coeffs`. """ -function max_range(coeffs::Vector{T}, ρ_min::T) where {T <: AbstractFloat} +function max_range(coeffs::Vector{T}) where {T <: AbstractFloat} # Initial guess - sol = find_zeros(s -> admsreg_U(coeffs, s), ρ_min, 10.0) + sol = find_zeros(s -> admsreg_U(coeffs, s), R_EA, 10.0) iszero(length(sol)) && return zero(T) ρ_max = sol[1] # Make sure U(ρ) ≥ 0 and there is at least one range_rate solution @@ -266,7 +275,7 @@ end # Check whether P is inside A's boundary function in(P::Vector{T}, A::AdmissibleRegion{T}) where {T <: AbstractFloat} @assert length(P) == 2 "Points in admissible region are of dimension 2" - if A.ρ_domain[1] <= P[1] <= A.ρ_domain[2] && A.v_ρ_domain[1] <= P[2] <= A.v_ρ_domain[2] + if A.ρ_domain[1] <= P[1] <= A.ρ_domain[2] y_range = range_rate(A, P[1]) if length(y_range) == 1 return P[2] == y_range diff --git a/src/propagation/propagation.jl b/src/propagation/propagation.jl index dc5d3b9d..d09927a0 100755 --- a/src/propagation/propagation.jl +++ b/src/propagation/propagation.jl @@ -161,7 +161,11 @@ function propagate(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, @time tv, xv, psol = taylorinteg(dynamics, _q0, _t0, _tmax, order, abstol, Val(true), _params; maxsteps = maxsteps, parse_eqs = parse_eqs) - return TaylorInterpolant(jd0 - JD_J2000, tv .- tv[1], psol) + if issorted(tv) || issorted(tv, rev = true) + return TaylorInterpolant(jd0 - JD_J2000, tv, psol) + else + return zero(TaylorInterpolant{T, U, 2, SubArray{T, 1}, SubArray{Taylor1{U}, 2}}) + end end @doc raw""" From 5406a490c82a914b87582cd00d0e50ae9c39baab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 4 Feb 2024 10:10:11 -0600 Subject: [PATCH 125/173] Light-time correction --- src/orbit_determination/gauss_method.jl | 8 ++++---- src/orbit_determination/tooshortarc.jl | 11 +++++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index fd5381d3..773bd861 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -435,8 +435,6 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} observatories, dates, α, δ = observatory.(tracklets), date.(tracklets), ra.(tracklets), dec.(tracklets) # Observations triplets triplets = gauss_triplets(dates, params.max_triplets) - # Julian day when to start propagation - jd0 = zero(T) # Start point of LS fits x0 = zeros(T, 6) # Jet transport scaling factors @@ -454,8 +452,8 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} # Current triplet triplet = triplets[j] - # Julian day when to start propagation - jd0 = datetime2julian(dates[triplet[2]]) + # Julian day of middle observation + _jd0_ = datetime2julian(dates[triplet[2]]) # Gauss method solution sol = gauss_method(observatories[triplet], dates[triplet], α[triplet] .+ dq[1:3], δ[triplet] .+ dq[4:6], params) @@ -465,6 +463,8 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} # Iterate over Gauss solutions for i in eachindex(sol) + # Light-time correction + jd0 = _jd0_ - cte(sol[i].ρ[2]) / c_au_per_day # Initial conditions (jet transport) q0 = sol[i].statevect .+ params.eph_su(jd0 - PE.J2000) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index da0c348d..06dbf71b 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -362,8 +362,6 @@ residual over and admissible region `A`. function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, params::NEOParameters{T}; η::T = 25.0, μ::T = 0.75, ν::T = 0.9, ϵ::T = 1e-8, Qtol::T = 0.001) where {T <: AbstractFloat} - # Initial time of integration [julian days] - jd0 = datetime2julian(A.date) # Scaling factors scalings = [A.ρ_domain[2] - A.ρ_domain[1], A.v_ρ_domain[2] - A.v_ρ_domain[1]] / 1_000 # Jet transport variables @@ -386,7 +384,10 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T for t in 1:maxiter+1 # Current position in admissible region ρs[t] = ρ - v_ρs[t] = v_ρ + v_ρs[t] = v_ρ + # Initial time of integration [julian days] + # (corrected for light-time) + jd0 = datetime2julian(A.date) - ρ / c_au_per_day # Current barycentric state vector q = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) # Propagation and residuals @@ -517,7 +518,8 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, # Barycentric initial conditions q0 = topo2bary(A, ρs[end], v_ρs[end]) # Initial time of integration [julian days] - jd0 = datetime2julian(A.date) + # (corrected for light-time) + jd0 = datetime2julian(A.date) - ρs[end] / c_au_per_day # 6 variables least squares sol = tsals(radec, tracklets, jd0, q0, params; maxiter = 5) # Update best solution @@ -529,6 +531,7 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, # Heel anomaly ρ = A.ρ_domain[1] v_ρs = LinRange(A.v_ρ_domain[1], A.v_ρ_domain[2], 25) + jd0 = datetime2julian(A.date) - ρ / c_au_per_day Qs = fill(Inf, 25) for i in eachindex(Qs) # Barycentric initial conditions From 62ef4fbd78900fd0c0257099d73639b948e7c2bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 4 Feb 2024 10:35:19 -0600 Subject: [PATCH 126/173] Minor fix --- src/orbit_determination/gauss_method.jl | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 773bd861..4ae40860 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -8,9 +8,10 @@ See also [`gauss_method`](@ref). # Fields - `statevect::Vector{U}`: state vector at middle observation. +- `ρ::Vector{U}`: topocentric ranges. - `D::Matrix{U}`: D matrix. - `R_vec::Matrix{T}`: observer's heliocentric positions. -- `ρ_vec::Matrix{U}`: slant ranges. +- `ρ_vec::Matrix{U}`: line of sight unit vectors. - `τ_1::T`: time between first and second observations. - `τ_3::T`: time between third and second observations. - `f_1, g_1, f_3, g_3::U`: Lagrange coefficients. @@ -20,6 +21,7 @@ See also [`gauss_method`](@ref). """ @auto_hash_equals struct GaussSolution{T <: Real, U <: Number} statevect::Vector{U} + ρ::Vector{U} D::Matrix{U} R_vec::Matrix{T} ρ_vec::Matrix{U} @@ -30,16 +32,18 @@ See also [`gauss_method`](@ref). f_3::U g_3::U # Inner constructor - function GaussSolution{T, U}(statevect::Vector{U}, D::Matrix{U}, R_vec::Matrix{T}, ρ_vec::Matrix{U}, - τ_1::T, τ_3::T, f_1::U, g_1::U, f_3::U, g_3::U) where {T <: Real, U <: Number} - return new{T, U}(statevect, D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3) + function GaussSolution{T, U}( + statevect::Vector{U}, ρ::Vector{U}, D::Matrix{U}, R_vec::Matrix{T}, + ρ_vec::Matrix{U}, τ_1::T, τ_3::T, f_1::U, g_1::U, f_3::U, g_3::U) where {T <: Real, U <: Number} + return new{T, U}(statevect, ρ, D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3) end end # Outer constructor -function GaussSolution(statevect::Vector{U}, D::Matrix{U}, R_vec::Matrix{T}, ρ_vec::Matrix{U}, τ_1::T, - τ_3::T, f_1::U, g_1::U, f_3::U, g_3::U) where {T <: Real, U <: Number} - return GaussSolution{T, U}(statevect, D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3) +function GaussSolution( + statevect::Vector{U}, ρ::Vector{U}, D::Matrix{U}, R_vec::Matrix{T}, + ρ_vec::Matrix{U}, τ_1::T, τ_3::T, f_1::U, g_1::U, f_3::U, g_3::U) where {T <: Real, U <: Number} + return GaussSolution{T, U}(statevect, ρ, D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3) end # Print method for GaussSolution @@ -322,8 +326,10 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da # Heliocentric velocity of the NEO v_2_vec = @views (- f_3 * r_vec[1, :] + f_1 * r_vec[3, :]) / (f_1*g_3 - f_3*g_1) - sol_gauss[i] = GaussSolution{T, U}(vcat(r_vec[2, :], v_2_vec), D, R_vec, ρ_vec, - τ_1, τ_3, f_1, g_1, f_3, g_3) + sol_gauss[i] = GaussSolution{T, U}( + vcat(r_vec[2, :], v_2_vec), ρ, D, R_vec, + ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3 + ) end # Sort solutions by heliocentric range return sort!(sol_gauss, by = x -> norm(cte.(x.statevect[1:3]))) From a13df5aaaf0be75e0ef675415619a113d2279d8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 4 Feb 2024 18:32:20 -0600 Subject: [PATCH 127/173] Incremental radec in TSA --- src/orbit_determination/gauss_method.jl | 6 +- src/orbit_determination/tooshortarc.jl | 185 +++++++++++++++--------- test/orbit_determination.jl | 102 ++++++------- 3 files changed, 166 insertions(+), 127 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 4ae40860..2886fbba 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -495,6 +495,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} fit = fit_new idxs = vcat(idxs, extra) sort!(idxs) + g_f = k else break end @@ -508,6 +509,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} fit = fit_new idxs = vcat(idxs, extra) sort!(idxs) + g_0 = k else break end @@ -520,8 +522,8 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} # Update NRMS and initial conditions if Q < best_Q best_Q = Q - best_sol = evalfit(NEOSolution(tracklets, bwd, fwd, res[idxs], - fit, scalings)) + best_sol = evalfit(NEOSolution(tracklets[g_0:g_f], bwd, fwd, + res[idxs], fit, scalings)) end # Break condition if Q <= params.Q_max diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 06dbf71b..60839a59 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -346,9 +346,8 @@ function propres(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{U}, end @doc raw""" - adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::NEOParameters{T}; η::T = 25.0, μ::T = 0.75, ν::T = 0.9, - ϵ::T = 1e-8, Qtol::T = 0.001) where {T <: AbstractFloat} + adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, params::NEOParameters{T}; + η::T = 25.0, μ::T = 0.75, ν::T = 0.9, ϵ::T = 1e-8, Qtol::T = 0.001) where {T <: AbstractFloat} Adaptative moment estimation (ADAM) minimizer of normalized mean square residual over and admissible region `A`. @@ -359,9 +358,13 @@ residual over and admissible region `A`. !!! reference See Algorithm 1 of https://doi.org/10.48550/arXiv.1412.6980. """ -function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, - params::NEOParameters{T}; η::T = 25.0, μ::T = 0.75, ν::T = 0.9, - ϵ::T = 1e-8, Qtol::T = 0.001) where {T <: AbstractFloat} +function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, params::NEOParameters{T}; + η::T = 25.0, μ::T = 0.75, ν::T = 0.9, ϵ::T = 1e-8, Qtol::T = 0.001) where {T <: AbstractFloat} + # Initial time of integration [julian days] + jd0 = datetime2julian(A.date) + # Center + ρ = sum(A.ρ_domain) / 2 + v_ρ = sum(A.v_ρ_domain) / 2 # Scaling factors scalings = [A.ρ_domain[2] - A.ρ_domain[1], A.v_ρ_domain[2] - A.v_ρ_domain[1]] / 1_000 # Jet transport variables @@ -385,9 +388,6 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T # Current position in admissible region ρs[t] = ρ v_ρs[t] = v_ρ - # Initial time of integration [julian days] - # (corrected for light-time) - jd0 = datetime2julian(A.date) - ρ / c_au_per_day # Current barycentric state vector q = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) # Propagation and residuals @@ -415,14 +415,45 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T end # Find point with smallest Q t = argmin(Qs) - # Return path - return view(ρs, 1:t), view(v_ρs, 1:t), view(Qs, 1:t) + + return T(ρs[t]), T(v_ρs[t]), T(Qs[t]) +end + +@doc raw""" + ρminmontecarlo(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, + params::NEOParameters{T}; N_samples::Int = 25) where {T <: AbstractFloat} + +Monte Carlo sampling over the left boundary of `A`. +""" +function ρminmontecarlo(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, + params::NEOParameters{T}; N_samples::Int = 25) where {T <: AbstractFloat} + # Initial time of integration [julian days] + jd0 = datetime2julian(A.date) + # Range lower bound + ρ = A.ρ_domain[1] + # Sample range rate + v_ρs = LinRange(A.v_ρ_domain[1], A.v_ρ_domain[2], N_samples) + # Allocate memory + Qs = fill(Inf, N_samples) + # Monte Carlo + for i in eachindex(Qs) + # Barycentric initial conditions + q = topo2bary(A, ρ, v_ρs[i]) + # Propagation & residuals + _, _, res = propres(radec, jd0, q, params) + iszero(length(res)) && continue + # NRMS + Qs[i] = nrms(res) + end + # Find solution with smallest Q + t = argmin(Qs) + + return T(ρ), T(v_ρs[t]), T(Qs[t]) end @doc raw""" - tsals(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, - jd0::T, q0::Vector{T}, params::NEOParameters{T}; maxiter::Int = 5, - Qtol::T = 0.1) where {T <: AbstractFloat} + tsals(A::AdmissibleRegion{T}, radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, + i::Int, ρ::T, v_ρ::T, params::NEOParameters{T}; maxiter::Int = 5) where {T <: AbstractFloat} Used within [`tooshortarc`](@ref) to compute an orbit from a point in an admissible region via least squares. @@ -430,46 +461,88 @@ admissible region via least squares. !!! warning This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. """ -function tsals(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, - jd0::T, q0::Vector{T}, params::NEOParameters{T}; maxiter::Int = 5, - Qtol::T = 0.1) where {T <: AbstractFloat} +function tsals(A::AdmissibleRegion{T}, radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, + i::Int, ρ::T, v_ρ::T, params::NEOParameters{T}; maxiter::Int = 5) where {T <: AbstractFloat} + # Initial time of integration [julian days] + # (corrected for light-time) + jd0 = datetime2julian(A.date) - ρ / c_au_per_day + # Barycentric initial conditions + q0 = topo2bary(A, ρ, v_ρ) # Scaling factors scalings = abs.(q0) ./ 10^5 # Jet transport variables dq = scaled_variables("dx", scalings, order = 6) - # Allocate memory - sols = zeros(NEOSolution{T, T}, maxiter+1) - Qs = fill(T(Inf), maxiter+1) # Origin x0 = zeros(T, 6) + # Subset of radec for orbit fit + g_0 = i + g_f = i + idxs = indices(tracklets[i]) + sort!(idxs) + # Allocate memory + best_sol = zero(NEOSolution{T, T}) + best_Q = T(Inf) + flag = false # Least squares - for t in 1:maxiter+1 + for _ in 1:maxiter+1 # Initial conditions q = q0 + dq # Propagation & residuals bwd, fwd, res = propres(radec, jd0, q, params) iszero(length(res)) && break - # Least squares fit - fit = tryls(res, x0, params.niter) - # Case: unsuccessful fit - if !fit.success || any(diag(fit.Γ) .< 0) - break + # Orbit fit + fit = tryls(res[idxs], x0, params.niter) + !fit.success && continue + # Right iteration + for k in g_f+1:length(tracklets) + extra = indices(tracklets[k]) + fit_new = tryls(res[idxs ∪ extra], x0, params.niter) + if fit_new.success + fit = fit_new + idxs = vcat(idxs, extra) + sort!(idxs) + g_f = k + else + break + end end - # Current solution - sols[t] = evalfit(NEOSolution(tracklets, bwd, fwd, res, fit, scalings)) - Qs[t] = nrms(sols[t]) - # Convergence conditions - if t > 1 - Qs[t] > Qs[t-1] && break - abs(Qs[t] - Qs[t-1]) < Qtol && break + # Left iteration + for k in g_0-1:-1:1 + extra = indices(tracklets[k]) + fit_new = tryls(res[idxs ∪ extra], x0, params.niter) + if fit_new.success + fit = fit_new + idxs = vcat(idxs, extra) + sort!(idxs) + g_0 = k + else + break + end end + # NRMS + Q = nrms(res, fit) + if length(idxs) == length(radec) && abs(best_Q - Q) < 0.1 + flag = true + end + # Update NRMS and initial conditions + if Q < best_Q + best_Q = Q + best_sol = evalfit(NEOSolution(tracklets[g_0:g_f], bwd, fwd, + res[idxs], fit, scalings)) + flag && break + else + break + end # Update values q0 = q(fit.x) end - # Find solution with smallest Q - t = argmin(Qs) - # Return solution - return sols[t] + # Case: all solutions were unsuccesful + if isinf(best_Q) + return zero(NEOSolution{T, T}) + # Case: at least one solution was succesful + else + return best_sol + end end # Order in which to check tracklets in tooshortarc @@ -510,45 +583,21 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, # Admissible region A = AdmissibleRegion(tracklets[i], params) iszero(A) && continue - # Center - ρ = sum(A.ρ_domain) / 2 - v_ρ = sum(A.v_ρ_domain) / 2 - # Minimization over admissible region - ρs, v_ρs, _ = adam(radec, A, ρ, v_ρ, params) - # Barycentric initial conditions - q0 = topo2bary(A, ρs[end], v_ρs[end]) - # Initial time of integration [julian days] - # (corrected for light-time) - jd0 = datetime2julian(A.date) - ρs[end] / c_au_per_day + # ADAM minimization over admissible region + ρ, v_ρ, _ = adam(radec, A, params) # 6 variables least squares - sol = tsals(radec, tracklets, jd0, q0, params; maxiter = 5) + sol = tsals(A, radec, tracklets, i, ρ, v_ρ, params; maxiter = 5) # Update best solution if nrms(sol) < nrms(best_sol) best_sol = sol # Break condition nrms(sol) < 1.5 && break end - # Heel anomaly - ρ = A.ρ_domain[1] - v_ρs = LinRange(A.v_ρ_domain[1], A.v_ρ_domain[2], 25) - jd0 = datetime2julian(A.date) - ρ / c_au_per_day - Qs = fill(Inf, 25) - for i in eachindex(Qs) - # Barycentric initial conditions - q = topo2bary(A, ρ, v_ρs[i]) - # Propagation & residuals - _, _, res = propres(radec, jd0, q, params) - iszero(length(res)) && continue - # NRMS - Qs[i] = nrms(res) - end - # Find solution with smallest Q - t = argmin(Qs) - isinf(Qs[t]) && continue - # Barycentric initial conditions - q0 = topo2bary(A, ρ, v_ρs[t]) + # Left boundary Monte Carlo + ρ, v_ρ, Q = ρminmontecarlo(radec, A, params) + isinf(Q) && continue # 6 variables least squares - sol = tsals(radec, tracklets, jd0, q0, params; maxiter = 5) + sol = tsals(A, radec, tracklets, i, ρ, v_ρ, params; maxiter = 5) # Update best solution if nrms(sol) < nrms(best_sol) best_sol = sol diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index d70b89c3..b2f6a029 100755 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -13,12 +13,13 @@ using NEOs: NEOSolution, numberofdays # Load observations radec = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) # Parameters - params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true) + params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, + bwdoffset = 0.007, fwdoffset = 0.007) # Orbit Determination sol = orbitdetermination(radec, params) - # Values by December 21, 2023 + # Values by February 4, 2024 # Vector of observations @test length(radec) == 123 @@ -47,6 +48,10 @@ using NEOs: NEOSolution, numberofdays @test nrms(sol) < 0.38 # Scalig factors @test all(sol.scalings .== 1e-6) + # Compatibility with JPL + JPL = [-1.100331943890894E+00, 2.077277940539948E-01, 4.202679172087372E-02, + -4.735673360137306E-03, -1.062665933519790E-02, -6.016253165957075E-03] + @test all(abs.(sol() - JPL) .< 27) end @testset "Too Short Arc" begin @@ -59,12 +64,13 @@ using NEOs: NEOSolution, numberofdays # Delete astrometry file rm(filename) # Parameters - params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true) + params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, + bwdoffset = 0.007, fwdoffset = 0.007) # Orbit Determination sol = orbitdetermination(radec, params) - # Values by December 22, 2023 + # Values by February 4, 2024 # Vector of observations @test length(radec) == 10 @@ -93,6 +99,10 @@ using NEOs: NEOSolution, numberofdays @test nrms(sol) < 0.85 # Scalig factors @test all(sol.scalings .< 1e-5) + # Compatibility with JPL + JPL = [-9.698293924982635E-01, 2.403718659163320E-01, 1.028928812918412E-01, + -9.512665381191419E-03, -1.532539714362475E-02, -8.094608965098163E-03] + @test all(abs.(sol() - JPL) .< 1) end @testset "Outlier Rejection" begin @@ -105,12 +115,13 @@ using NEOs: NEOSolution, numberofdays # Delete astrometry file rm(filename) # Parameters - params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true) + params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, + bwdoffset = 0.007, fwdoffset = 0.007) # Orbit Determination sol = orbitdetermination(radec, params) - # Values by December 23, 2023 + # Values by February 4, 2024 # Vector of observations @test length(radec) == 21 @@ -139,6 +150,10 @@ using NEOs: NEOSolution, numberofdays @test nrms(sol) < 0.25 # Scalig factors @test all(sol.scalings .< 8e-7) + # Compatibility with JPL + JPL = [7.673391189462907E-01, 6.484845064680100E-01, 2.932307930882956E-01, + -1.102328578432002E-02, 1.539274577937339E-02, 6.528864069204219E-03] + @test all(abs.(sol() - JPL) .< 1) end @testset "Interesting NEOs" begin @@ -155,12 +170,13 @@ using NEOs: NEOSolution, numberofdays # Delete astrometry file rm(filename) # Parameters - params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true) + params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, + bwdoffset = 0.007, fwdoffset = 0.007) # Orbit Determination sol = orbitdetermination(radec, params) - # Values by January 26, 2024 + # Values by February 4, 2024 # Vector of observations @test length(radec) == 7 @@ -189,6 +205,10 @@ using NEOs: NEOSolution, numberofdays @test nrms(sol) < 0.13 # Scalig factors @test all(sol.scalings .< 1e-5) + # Compatibility with JPL + JPL = [-1.793234664811157E-01, 8.874182631964184E-01, 3.841456198855505E-01, + -1.755789723380711E-02, -5.781199629059458E-03, -2.007345498817972E-03] + @test all(abs.(sol() - JPL) .< 1) # 2008 TC3 entered the Earth's atmosphere around October 7, 2008, 02:46 UTC @@ -204,48 +224,12 @@ using NEOs: NEOSolution, numberofdays params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, coeffstol = Inf, fwdoffset = 0.007) - # Observations before October 6, 2008, 10:00 UTC - idxs = findall(x -> date(x) < DateTime(2008, 10, 06, 10), radec) + # Observations with <1" weight + idxs = findall(x -> x < 1, w8sveres17.(radec)) # Restricted Orbit Determination sol = orbitdetermination(radec[idxs], params) - # Tracklets - tracklets = reduce_tracklets(radec) - # Initial time of propagation [julian days] - jd0 = sol.bwd.t0 + J2000 - # Initial conditions - q0 = sol() - scalings = abs.(q0) ./ 10^6 - dq = NEOs.scaled_variables("dx", scalings, order = 5) - q = q0 + dq - # Propagation and residuals - bwd, fwd, res = propres(radec, jd0, q, params) - - @test length(res) == 883 - - # Least squares fit - fit = tryls(res, zeros(6), params.niter) - # Orbit with all the observations - sol = evalfit(NEOSolution(tracklets, bwd, fwd, res, fit, scalings)) - - # Initial time of propagation [julian days] - jd0 = sol.bwd.t0 + J2000 - # Initial conditions - q0 = sol() - scalings = abs.(q0) ./ 10^6 - dq = NEOs.scaled_variables("dx", scalings, order = 5) - q = q0 + dq - # Propagation and residuals - bwd, fwd, res = propres(radec, jd0, q, params) - - @test length(res) == 883 - - # Least squares fit - fit = tryls(res, zeros(6), params.niter) - # Orbit refinement - sol = evalfit(NEOSolution(tracklets, bwd, fwd, res, fit, scalings)) - - # Values by January 26, 2024 + # Values by February 4, 2024 # Vector of observations @test length(radec) == 883 @@ -253,27 +237,31 @@ using NEOs: NEOSolution, numberofdays # Orbit solution @test isa(sol, NEOSolution{Float64, Float64}) # Tracklets - @test length(sol.tracklets) == 29 - @test sol.tracklets[1].radec[1] == radec[1] - @test sol.tracklets[end].radec[end] == radec[end] + @test length(sol.tracklets) == 2 + @test sol.tracklets[1].radec[1] == radec[idxs[1]] + @test sol.tracklets[end].radec[end] == radec[idxs[end]] @test issorted(sol.tracklets) # Backward integration - @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] + @test datetime2days(date(radec[idxs[1]])) > sol.bwd.t0 + sol.bwd.t[end] @test all( norm.(sol.bwd.x, Inf) .< 2 ) @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) # Forward integration - @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] - @test all( norm.(sol.fwd.x, Inf) .< 1e55 ) + @test datetime2days(date(radec[idxs[end]])) < sol.fwd.t0 + sol.fwd.t[end] + @test all( norm.(sol.fwd.x, Inf) .< 1e4 ) @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) # Vector of residuals - @test length(sol.res) == 883 + @test length(sol.res) == 20 @test iszero(count(outlier.(sol.res))) # Least squares fit @test sol.fit.success - @test all( sigmas(sol) .< 1e-7 ) - @test nrms(sol) < 0.61 + @test all( sigmas(sol) .< 2e-5 ) + @test nrms(sol) < 0.30 # Scalig factors - @test all(sol.scalings .< 1e-6) + @test all(sol.scalings .< 1e-5) + # Compatibility with JPL + JPL = [9.741084137931751E-01, 2.151459813682736E-01, 9.390733559030655E-02, + -7.890343235423515E-03, 1.606273839327320E-02, 6.136052979678407E-03] + @test all(abs.(sol() - JPL) .< 9) end end \ No newline at end of file From dc6b02b8834573698ec1641ec36ebf0d2b29d871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 6 Feb 2024 18:04:36 -0600 Subject: [PATCH 128/173] Minor fixes --- src/observations/topocentric.jl | 2 +- src/orbit_determination/tooshortarc.jl | 2 +- test/orbit_determination.jl | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/observations/topocentric.jl b/src/observations/topocentric.jl index 3e1dc3f1..48d00d38 100755 --- a/src/observations/topocentric.jl +++ b/src/observations/topocentric.jl @@ -149,7 +149,7 @@ function obsposECEF(observatory::ObservatoryMPC{T}; eop::Union{EopIau1980, EopIa # State vector pv_ECI = OrbitStateVector(jd_utc, posvel_ECI[1:3], posvel_ECI[4:6], zeros(3)) - # Transform position/velocity from Earth-Centered Inertial (ECI) fraom to Earth-Centered Earth-fixed (ECEF) frame + # Transform position/velocity from Earth-Centered Inertial (ECI) frame to Earth-Centered Earth-fixed (ECEF) frame # ITRF: International Terrestrial Reference Frame # GCRF: Geocentric Celestial Reference Frame pv_ECEF = sv_eci_to_ecef(pv_ECI, Val(:GCRF), Val(:ITRF), jd_utc, eop) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 60839a59..ffaa3438 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -484,7 +484,7 @@ function tsals(A::AdmissibleRegion{T}, radec::Vector{RadecMPC{T}}, tracklets::Ve best_Q = T(Inf) flag = false # Least squares - for _ in 1:maxiter+1 + for _ in 1:maxiter # Initial conditions q = q0 + dq # Propagation & residuals diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index b2f6a029..e75990fc 100755 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -51,7 +51,7 @@ using NEOs: NEOSolution, numberofdays # Compatibility with JPL JPL = [-1.100331943890894E+00, 2.077277940539948E-01, 4.202679172087372E-02, -4.735673360137306E-03, -1.062665933519790E-02, -6.016253165957075E-03] - @test all(abs.(sol() - JPL) .< 27) + @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 27) end @testset "Too Short Arc" begin @@ -102,7 +102,7 @@ using NEOs: NEOSolution, numberofdays # Compatibility with JPL JPL = [-9.698293924982635E-01, 2.403718659163320E-01, 1.028928812918412E-01, -9.512665381191419E-03, -1.532539714362475E-02, -8.094608965098163E-03] - @test all(abs.(sol() - JPL) .< 1) + @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 1) end @testset "Outlier Rejection" begin @@ -153,7 +153,7 @@ using NEOs: NEOSolution, numberofdays # Compatibility with JPL JPL = [7.673391189462907E-01, 6.484845064680100E-01, 2.932307930882956E-01, -1.102328578432002E-02, 1.539274577937339E-02, 6.528864069204219E-03] - @test all(abs.(sol() - JPL) .< 1) + @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 1) end @testset "Interesting NEOs" begin @@ -208,7 +208,7 @@ using NEOs: NEOSolution, numberofdays # Compatibility with JPL JPL = [-1.793234664811157E-01, 8.874182631964184E-01, 3.841456198855505E-01, -1.755789723380711E-02, -5.781199629059458E-03, -2.007345498817972E-03] - @test all(abs.(sol() - JPL) .< 1) + @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 1) # 2008 TC3 entered the Earth's atmosphere around October 7, 2008, 02:46 UTC @@ -261,7 +261,7 @@ using NEOs: NEOSolution, numberofdays # Compatibility with JPL JPL = [9.741084137931751E-01, 2.151459813682736E-01, 9.390733559030655E-02, -7.890343235423515E-03, 1.606273839327320E-02, 6.136052979678407E-03] - @test all(abs.(sol() - JPL) .< 9) + @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 9) end end \ No newline at end of file From f17c87c3eaa9d39398de1010cadf97a425fb75e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez?= Date: Wed, 7 Feb 2024 01:23:09 +0100 Subject: [PATCH 129/173] Add Newtonian model as default dynamics for preliminary orbit determination (#53) * Add newtonian dynamical model * Use Newtonian dynamical model throughout preliminary orbit determination methods * Make newtonian! default dynamical model for preliminary orbit determination --------- Co-authored-by: LuEdRaMo <73906617+LuEdRaMo@users.noreply.github.com> --- src/NEOs.jl | 4 +- src/orbit_determination/gauss_method.jl | 40 ++--- src/orbit_determination/least_squares.jl | 144 +++++++++--------- .../orbit_determination.jl | 13 +- src/orbit_determination/outlier_rejection.jl | 14 +- src/orbit_determination/tooshortarc.jl | 92 +++++------ src/propagation/asteroid_dynamical_models.jl | 102 +++++++++++++ test/orbit_determination.jl | 28 ++-- 8 files changed, 269 insertions(+), 168 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index 148d7dad..807f1231 100755 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -35,7 +35,7 @@ export d_EM_km, d_EM_au export unknowncat, read_catalogues_mpc, write_catalogues_mpc, update_catalogues_mpc, search_cat_code # ObservatoryMPC -export unknownobs, hascoord, read_observatories_mpc, write_observatories_mpc, +export unknownobs, hascoord, read_observatories_mpc, write_observatories_mpc, update_observatories_mpc, search_obs_code # RadecMPC export ra, dec, date, observatory, read_radec_mpc, write_radec_mpc, get_radec_mpc @@ -55,7 +55,7 @@ export compute_radec, select_debiasing_table, debiasing, w8sveres17, residuals, # Process radar export compute_delay, radar_astrometry # Asteroid dynamical models -export RNp1BP_pN_A_J23E_J2S_ng_eph_threads!, RNp1BP_pN_A_J23E_J2S_eph_threads! +export RNp1BP_pN_A_J23E_J2S_ng_eph_threads!, RNp1BP_pN_A_J23E_J2S_eph_threads!, newtonian! # Propagate export NEOParameters, propagate, propagate_lyap, propagate_root # B plane diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 2886fbba..1404c66b 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -79,7 +79,7 @@ topounit(obs::RadecMPC{T}) where {T <: AbstractFloat} = topounit(obs.α, obs.δ) Return the 1st order approximation to Lagrange's f function. """ function f_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} - r3 = r * r * r + r3 = r * r * r return 1 - μ_S * (τ^2) / 2 / r3 end @@ -89,7 +89,7 @@ end Return the 1st order approximation to Lagrange's g function. """ function g_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} - r3 = r * r * r + r3 = r * r * r return τ - μ_S * (τ^3) / 6 / r3 end @@ -121,7 +121,7 @@ Lagrange polynomial to be solved during Gauss method. function lagrange(x::T, a::U, b::U, c::U) where {T, U <: Number} # Evaluate via Horner's method x2 = x * x - x3 = x2 * x + x3 = x2 * x return c + x3 * (b + x3 * (a + x2)) end @@ -133,12 +133,12 @@ Derivative of Lagrange polynomial to be solved during Gauss method. function lagrange_derivative(x::T, a::U, b::U) where {T, U <: Number} # Evaluate via Horner's method x2 = x * x - x3 = x2 * x + x3 = x2 * x return x2 * (3*b + x3 * (6*a + 8*x2)) end # TO DO: Allow to control interval over which to look for solutions -# Currently we look between the radius of the Sun (∼0.00465047 AU) and +# Currently we look between the radius of the Sun (∼0.00465047 AU) and # the radius of the Solar System (∼40 AU) @doc raw""" @@ -182,9 +182,9 @@ Return the heliocentric energy per unit mass for heliocentric state vector `r` [ """ function heliocentric_energy(r::Vector{T}) where {T <: Number} @assert length(r) == 6 "r must have length 6" - kinetic = 0.5 * (r[4]^2 + r[5]^2 + r[6]^2) + kinetic = 0.5 * (r[4]^2 + r[5]^2 + r[6]^2) potential = k_gauss^2 / sqrt(r[1]^2 + r[2]^2 + r[3]^2) - return kinetic - potential + return kinetic - potential end @doc raw""" @@ -227,7 +227,7 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da # Check we have exactly three observations @assert length(observatories) == length(dates) == length(α) == length(δ) == 3 "Gauss method requires exactly three observations" - # Check observations are in temporal order + # Check observations are in temporal order @assert issorted(dates) "Observations must be in temporal order" # Times of observation [et] @@ -359,7 +359,7 @@ end gauss_norm(dates::Vector{DateTime}) Return a measure of how evenly distributed in time a triplet is; -used within [`gauss_triplets`](@ref) to sort triplets for Gauss method. +used within [`gauss_triplets`](@ref) to sort triplets for Gauss method. The function assumes `dates` is sorted. """ gauss_norm(dates::Vector{DateTime}) = abs( (dates[2] - dates[1]).value - (dates[3] - dates[2]).value ) / 86_400_000 @@ -372,7 +372,7 @@ to select the best observations for Gauss method. The triplets are sorted by [`g """ function gauss_triplets(dates::Vector{DateTime}, Δ_min::Period, Δ_max::Period, avoid::Vector{Vector{Int}}, max_triplets::Int) - + triplets = Vector{Vector{Int}}(undef, 0) L = length(dates) for i_1 in 1:L-2 @@ -419,7 +419,7 @@ end gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} -Return initial conditions via Gauss Method. +Return initial conditions via Gauss Method. See also [`gauss_method`](@ref). @@ -430,10 +430,10 @@ See also [`gauss_method`](@ref). - `params::NEOParameters{T}`: see `Gauss Method Parameters` of [`NEOParameters`](@ref). !!! warning - This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. + This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. """ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, - params::NEOParameters{T}) where {T <: AbstractFloat} + params::NEOParameters{T}; dynamics::D=newtonian!) where {T <: AbstractFloat, D} # Allocate memory for initial conditions best_sol = zero(NEOSolution{T, T}) @@ -460,7 +460,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} triplet = triplets[j] # Julian day of middle observation _jd0_ = datetime2julian(dates[triplet[2]]) - # Gauss method solution + # Gauss method solution sol = gauss_method(observatories[triplet], dates[triplet], α[triplet] .+ dq[1:3], δ[triplet] .+ dq[4:6], params) # Filter Gauss solutions by heliocentric energy @@ -475,7 +475,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} q0 = sol[i].statevect .+ params.eph_su(jd0 - PE.J2000) # Propagation and residuals - bwd, fwd, res = propres(radec, jd0, q0, params) + bwd, fwd, res = propres(radec, jd0, q0, params; dynamics) iszero(length(res)) && continue # Subset of radec for orbit fit @@ -496,7 +496,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} idxs = vcat(idxs, extra) sort!(idxs) g_f = k - else + else break end end @@ -510,7 +510,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} idxs = vcat(idxs, extra) sort!(idxs) g_0 = k - else + else break end end @@ -524,7 +524,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} best_Q = Q best_sol = evalfit(NEOSolution(tracklets[g_0:g_f], bwd, fwd, res[idxs], fit, scalings)) - end + end # Break condition if Q <= params.Q_max flag = true @@ -534,13 +534,13 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} if flag break end - end + end # Case: all solutions were unsuccesful if isinf(best_Q) return zero(NEOSolution{T, T}) # Case: at least one solution was succesful - else + else return best_sol end diff --git a/src/orbit_determination/least_squares.jl b/src/orbit_determination/least_squares.jl index 8d964acf..9ea40c8e 100755 --- a/src/orbit_determination/least_squares.jl +++ b/src/orbit_determination/least_squares.jl @@ -69,7 +69,7 @@ function outlier_rejection(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::Lea # Number of residuals L = length(res) - # Evaluate residuals + # Evaluate residuals eval_res = res(fit.x) # Vector of χ2 χ2s = Vector{T}(undef, L) @@ -77,7 +77,7 @@ function outlier_rejection(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::Lea χ2_max = zero(T) # Number of non outliers N_sel = 0 - + # Compute χ2s for i in eachindex(χ2s) # Weights of current residual @@ -95,7 +95,7 @@ function outlier_rejection(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::Lea # Current chi2 χ2s[i] = ξ' * inv(γ_ξ) * ξ # Update N_sel - if !res[i].outlier + if !res[i].outlier N_sel += 1 # Update maximum χ2 if χ2s[i] > χ2_max @@ -149,13 +149,13 @@ Returns the chi square ```math \chi^2 = \sum_{i=1}^m \frac{ \xi_i^2}{\sigma_i^2}, ``` -where ``\mathbf{w} = (1/\sigma_1^2,\ldots,1/\sigma_m^2)^T`` and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` -are the vectors of weights and residuals respectively. +where ``\mathbf{w} = (1/\sigma_1^2,\ldots,1/\sigma_m^2)^T`` and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` +are the vectors of weights and residuals respectively. # Arguments - `res::Vector{U}/Vector{OpticalResidual{T, U}}`: vector of residuals. -- `w::Vector{T}`: vector of weights. +- `w::Vector{T}`: vector of weights. """ function chi2(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} # Have as many residuals as weights @@ -173,7 +173,7 @@ end nms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} Return the normalized chi square. See [`chi2`](@ref). -""" +""" nms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} = chi2(res, w) / length(res) function nms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} _res_, _w_ = unfold(res) @@ -190,14 +190,14 @@ Returns the normalized root mean square error \texttt{NRMS} = \sqrt{\frac{\chi^2}{m}}, ``` where ``\chi^2`` is the chi square and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` is the vector -of residuals. +of residuals. See also [`chi2`](@ref). # Arguments - `res::Vector{U}/Vector{OpticalResidual{T, U}}`: Vector of residuals. -- `w::Vector{T}`: Vector of weights. +- `w::Vector{T}`: Vector of weights. - `fit::LeastSquaresFit{T}`: least squares fit. """ @@ -225,11 +225,11 @@ Returns the ``\mathbf{B}``, ``\mathbf{H}`` and ``\mathbf{C}`` arrays ```math \mathbf{B} = \frac{\partial\mathbf{\xi}}{\partial\mathbf{x}_0}(\mathbf{x}_0), \quad \mathbf{H} = \frac{\partial^2\mathbf{\xi}}{\partial\mathbf{x}_0^2}(\mathbf{x}_0) \quad \text{and} \quad -\mathbf{C} = \mathbf{B}^T\mathbf{W}\mathbf{B}, +\mathbf{C} = \mathbf{B}^T\mathbf{W}\mathbf{B}, ``` -where ``\mathbf{x}_0 = (x_1,\ldots,x_n)^T`` and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` -are the vectors of initial conditions and residuals respectively; and -``\mathbf{W} = \text{diag}(1/\sigma_1^2,\ldots,1/\sigma_m^2)`` is the weights matrix. +where ``\mathbf{x}_0 = (x_1,\ldots,x_n)^T`` and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` +are the vectors of initial conditions and residuals respectively; and +``\mathbf{W} = \text{diag}(1/\sigma_1^2,\ldots,1/\sigma_m^2)`` is the weights matrix. ``\mathbf{B}`` is called the design matrix and is of size ``m\times n``, ``\mathbf{H}`` is a three index array of size ``m\times n\times n`` and ``\mathbf{C}`` is called the normal matrix and is of size ``n\times n``. @@ -237,7 +237,7 @@ array of size ``m\times n\times n`` and ``\mathbf{C}`` is called the normal matr # Arguments - `res::Vector{TaylorN{T}}`: vector of residuals. -- `w::Vector{T}`: vector of weights. +- `w::Vector{T}`: vector of weights. - `npar::Int`: degrees of freedom ``n``. !!! reference @@ -261,12 +261,12 @@ function BHC(res::Vector{TaylorN{T}}, w::Vector{T}, npar::Int) where {T <: Real} for i in 1:nobs for j in 1:npar # Gradient of the (i, j)-th element of B with respect to to the initial - # conditions x_0 + # conditions x_0 H_mat[i,j,:] .= TaylorSeries.gradient(B_mat[i,j]) end end # Normal matrix C - sqrtw_B = sqrt.(w) .* B_mat + sqrtw_B = sqrt.(w) .* B_mat C_mat .= (sqrtw_B') * sqrtw_B return B_mat, H_mat, C_mat @@ -276,18 +276,18 @@ end ξTH(w, res, H_mat, npar) Returns ``\mathbf{\xi}^T\mathbf{W}\mathbf{H}``, where ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` -is the vector of residuals, ``\mathbf{W} = \text{diag}(1/\sigma_1^2,\ldots,1/\sigma_m^2)`` is +is the vector of residuals, ``\mathbf{W} = \text{diag}(1/\sigma_1^2,\ldots,1/\sigma_m^2)`` is the weights matrix and ``\mathbf{H}`` is the matrix of second derivatives of ``\mathbf{\xi}`` -with respect to the initial conditions. +with respect to the initial conditions. See also [`BHC`](@ref). -# Arguments +# Arguments - `w`: Vector of weights. - `res`: Vector or residuals. - `H_mat`: matrix of second derivatives of ``\mathbf{\xi}`` with respect to the initial conditions. -- `npar`: Degrees of freedom ``n``. +- `npar`: Degrees of freedom ``n``. """ function ξTH(w, res, H_mat, npar) # Allocate memory for output @@ -310,7 +310,7 @@ end niters::Int = 5) where {T <: Real} Differential corrections subroutine for least-squares fitting. Returns an -`LeastSquaresFit` with the `niters`-th +`LeastSquaresFit` with the `niters`-th correction ```math \mathbf{x}_{k+1} = \mathbf{x}_k - \mathbf{C}^{-1}\mathbf{D}, @@ -322,7 +322,7 @@ and the covariance matrix where ``\mathbf{C} = \mathbf{B}^T\mathbf{W}\mathbf{B}`` is the normal matrix and ``\mathbf{D} = \mathbf{B}^T\mathbf{W}\mathbf{\xi}``, with ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` the vector of residuals, ``\mathbf{B}`` the design matrix and ``\mathbf{W} = \text{diag}(1/\sigma_1^2,\ldots,1/\sigma_m^2)`` -the weights matrix. +the weights matrix. See also [`BHC`](@ref). @@ -334,7 +334,7 @@ See also [`BHC`](@ref). - `niters::Int`: number of iterations. !!! reference - See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. + See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. """ function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, niters::Int = 5) where {T <: Real} @@ -345,13 +345,13 @@ function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, # D matrix: transpose(B) * W * ξ D_mat = B_mat' * (w .* res) # ξTH_mat = ξTH(w, res, H_mat, npar) - # Vector of x - x = Matrix{T}(undef, npar, niters + 1) + # Vector of x + x = Matrix{T}(undef, npar, niters + 1) # First guess x[:, 1] = x0 - # Vector of errors + # Vector of errors error = Vector{T}(undef, niters + 1) - # Error of first guess + # Error of first guess error[1] = T(Inf) # Iteration for i in 1:niters @@ -363,26 +363,26 @@ function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, C = C_mat(xi) #.+ ξTH_mat(xi) # Update rule Δx = - inv(C)*D - # New x - x[:, i+1] = xi + Δx - # Error + # New x + x[:, i+1] = xi + Δx + # Error error2 = ( (Δx') * (C*Δx) ) / npar if error2 ≥ 0 error[i+1] = sqrt(error2) # The method do not converge - else + else return LeastSquaresFit(false, x[:, i+1], inv(C), :diffcorr) - end + end end - # Index with the lowest error + # Index with the lowest error i = argmin(error) - # x with the lowest error + # x with the lowest error x_new = x[:, i] # Normal C matrix evaluated in x_new C = C_mat(x_new) # Covariance matrix Γ = inv(C) - + if any(diag(Γ) .< 0) return LeastSquaresFit(false, x_new, Γ, :diffcorr) else @@ -394,7 +394,7 @@ function diffcorr(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, niters::Int = 5) where {T <: Real} # Unfold residuals and weights _res_, _w_ = unfold(res) - + return diffcorr(_res_, _w_, x0, niters) end @@ -407,7 +407,7 @@ end Newton method subroutine for least-squares fitting. Returns an `LeastSquaresFit` with the `niters`-th iteration ```math -\mathbf{x}_{k+1} = \mathbf{x}_k - +\mathbf{x}_{k+1} = \mathbf{x}_k - \left(\frac{\partial^2 Q}{\partial\mathbf{x}_0^2}\right)^{-1} \frac{\partial Q}{\partial\mathbf{x}_0}, ``` @@ -416,8 +416,8 @@ and the covariance matrix \mathbf{\Gamma} = \mathbf{C}^{-1}, ``` where ``\mathbf{C} = \frac{m}{2}\frac{\partial^2 Q}{\partial\mathbf{x}_0^2}`` is the normal -matrix, ``Q = \frac{\chi^2}{m}`` is the mean square residual, ``m`` is the number of -observations and ``\mathbf{x}_0 = (x_1,\ldots,x_n)`` is the vector of initial conditions. +matrix, ``Q = \frac{\chi^2}{m}`` is the mean square residual, ``m`` is the number of +observations and ``\mathbf{x}_0 = (x_1,\ldots,x_n)`` is the vector of initial conditions. See also [`chi2`](@ref). @@ -429,7 +429,7 @@ See also [`chi2`](@ref). - `niters::Int`: number of iterations. !!! reference - See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. + See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. """ function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, niters::Int = 5) where {T <: Real} @@ -439,13 +439,13 @@ function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, npar = length(x0) # Mean square residual Q = chi2(res, w)/nobs - # Vector of x - x = Matrix{T}(undef, npar, niters + 1) + # Vector of x + x = Matrix{T}(undef, npar, niters + 1) # First guess x[:, 1] = x0 - # Vector of errors + # Vector of errors error = Vector{T}(undef, niters + 1) - # Error of first guess + # Error of first guess error[1] = T(Inf) # Iteration for i in 1:niters @@ -457,26 +457,26 @@ function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, d2Q = TaylorSeries.hessian(Q, xi) # Newton update rule Δx = - inv(d2Q)*dQ - # New x + # New x x[:, i+1] = xi + Δx # Normal matrix C = d2Q/(2/nobs) # C = d2Q/(2/m) - # Error + # Error error2 = ( (Δx') * (C*Δx) ) / npar if error2 ≥ 0 error[i+1] = sqrt(error2) # The method do not converge - else + else return LeastSquaresFit(false, x[:, i+1], inv(C), :newton) - end + end end - # TO DO: study Gauss method solution dependence on jt order - # TO DO: try even varorder - # TO DO: study optimal number of iterations + # TO DO: study Gauss method solution dependence on jt order + # TO DO: try even varorder + # TO DO: study optimal number of iterations - # Index with the lowest error + # Index with the lowest error i = argmin(error) - # x with the lowest error + # x with the lowest error x_new = x[:, i] # Normal matrix C = TaylorSeries.hessian(Q, x_new)/(2/nobs) # C = d2Q/(2/m) @@ -494,7 +494,7 @@ function newtonls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, niters::Int = 5) where {T <: Real} # Unfold residuals and weights _res_, _w_ = unfold(res) - + return newtonls(_res_, _w_, x0, niters) end @@ -502,7 +502,7 @@ end tryls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, niters::Int = 5) where {T <: Real} -Return the best least squares fit between two routines: [`newtonls`](@ref) and +Return the best least squares fit between two routines: [`newtonls`](@ref) and [`diffcorr`](@ref). # Arguments @@ -540,10 +540,10 @@ end @doc raw""" newtonls_Q(Q, nobs, x0, niters=5) -Does the same as `newtonls`, but recives ``Q`` as an argument, instead of computing it. -Returns the `niters`-th iteration and the covariance matrix ``\Gamma``. +Does the same as `newtonls`, but recives ``Q`` as an argument, instead of computing it. +Returns the `niters`-th iteration and the covariance matrix ``\Gamma``. -See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. +See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. See also [`newtonls`](@ref). @@ -561,7 +561,7 @@ function newtonls_Q(Q, nobs, x0, niters=5) x_new = x0 # Iteration for i in 1:niters - # Gradient of Q with respect to x_0 + # Gradient of Q with respect to x_0 dQ = TaylorSeries.gradient(Q)(x_new) # Hessian of Q with respect to x_0 d2Q = TaylorSeries.hessian(Q, x_new) @@ -583,14 +583,14 @@ end @doc raw""" newtonls_6v(res, w, x0, niters=5) -Specialized version of `newtonls` on 6 variables for parametrized orbit determination -with respect to ``A_2`` Yarkovsky non-gravitational coefficient. Returns the `niters`-th -iteration and the covariance matrix ``\Gamma``. - -See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. - +Specialized version of `newtonls` on 6 variables for parametrized orbit determination +with respect to ``A_2`` Yarkovsky non-gravitational coefficient. Returns the `niters`-th +iteration and the covariance matrix ``\Gamma``. + +See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. + See also [`newtonls`](@ref). - + # Arguments - `res`: Vector of residuals. @@ -633,14 +633,14 @@ end @doc raw""" newtonls_A2(res, w, x0, niters=5) -Specialized version of `newtonls` with the Newton method only over the seventh degree of +Specialized version of `newtonls` with the Newton method only over the seventh degree of freedom, i.e., with respect to ``A_2`` Yarkovsky non-gravitational coefficient. Returns the -`niters`-th iteration, the covariance matrix ``\Gamma`` and the normal matrix ``C``. - -See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. - +`niters`-th iteration, the covariance matrix ``\Gamma`` and the normal matrix ``C``. + +See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. + See also [`newtonls`](@ref). - + # Arguments - `res`: Vector of residuals. diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index b484a175..f9d0d7fa 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -75,13 +75,13 @@ Initial Orbit Determination (IOD) routine. - `radec::Vector{RadecMPC{T}}`: vector of observations. - `params::NEOParameters{T}`: see [`NEOParameters`](@ref). """ -function orbitdetermination(radec::Vector{RadecMPC{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} - +function orbitdetermination(radec::Vector{RadecMPC{T}}, params::NEOParameters{T}; dynamics::D=newtonian!) where {T <: AbstractFloat, D} + # Allocate memory for output sol = zero(NEOSolution{T, T}) # Maximum number of steps params = NEOParameters(params; maxsteps = adaptative_maxsteps(radec)) - # Eliminate observatories without coordinates + # Eliminate observatories without coordinates filter!(x -> hascoord(observatory(x)), radec) # Cannot handle zero observations or multiple arcs if iszero(length(radec)) || !issinglearc(radec) @@ -91,16 +91,15 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, params::NEOParameters{T} tracklets = reduce_tracklets(radec) # Case 1: Too Short Arc (TSA) if istsa(tracklets) - sol = tooshortarc(radec, tracklets, params) + sol = tooshortarc(radec, tracklets, params; dynamics) # Case 2: Gauss Method else - sol = gaussinitcond(radec, tracklets, params) + sol = gaussinitcond(radec, tracklets, params; dynamics) end # Outlier rejection (if needed) if nrms(sol) > 1 && !iszero(sol) - sol = outlier_rejection(radec, sol, params) + sol = outlier_rejection(radec, sol, params; dynamics) end return sol::NEOSolution{T, T} end - \ No newline at end of file diff --git a/src/orbit_determination/outlier_rejection.jl b/src/orbit_determination/outlier_rejection.jl index 2aeb0a93..dcdb91bd 100644 --- a/src/orbit_determination/outlier_rejection.jl +++ b/src/orbit_determination/outlier_rejection.jl @@ -19,10 +19,10 @@ via propagation and/or outlier rejection. - `params::NEOParameters{T}`: see `Outlier Rejection Parameters` of [`NEOParameters`](@ref). !!! warning - This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. + This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. """ function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, - params::NEOParameters{T}) where {T <: AbstractFloat} + params::NEOParameters{T}; dynamics::D=newtonian!) where {T <: AbstractFloat, D} # Origin x0 = zeros(T, 6) @@ -38,9 +38,9 @@ function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, q = q0 .+ dq # Propagation and residuals - bwd, fwd, res = propres(radec, jd0, q, params) + bwd, fwd, res = propres(radec, jd0, q, params; dynamics) iszero(length(res)) && return zero(NEOSolution{T, T}) - + # Orbit fit fit = tryls(res, x0, params.niter) @@ -108,7 +108,7 @@ function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, # Update fit fit = tryls(res, x0, params.niter) end - # Add 0 outliers fit + # Add 0 outliers fit Qs[end] = Q_0 N_outliers[end] = zero(T) @@ -122,7 +122,7 @@ function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, # Update fit fit = tryls(res, x0, params.niter) - return evalfit(NEOSolution(sol.tracklets, bwd, fwd, res, fit, scalings)) + return evalfit(NEOSolution(sol.tracklets, bwd, fwd, res, fit, scalings)) end if max_drop > 1 @@ -138,7 +138,7 @@ function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, i_0 = cluster.assignments[1] # Find last fit of smallest cluster i = findfirst(x -> x != i_0, cluster.assignments) - 1 - # Update outliers indexes + # Update outliers indexes idxs = idxs[i:end] end diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index ffaa3438..638a924d 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -96,7 +96,7 @@ function AdmissibleRegion(tracklet::Tracklet{T}, params::NEOParameters{T}) where Fs[1, :] .= [ρ_min, v_ρ_min] Fs[2, :] .= [ρ_min, v_ρ_max] Fs[3, :] .= [ρ_max, v_ρ_mid] - + return AdmissibleRegion{T}(t_datetime, α, δ, v_α, v_δ, ρ, ρ_α, ρ_δ, q, coeffs, ρ_domain, v_ρ_domain, Fs, obs) end @@ -105,7 +105,7 @@ end admsreg_coeffs(α::T, δ::T, v_α::T, v_δ::T, ρ::Vector{T}, ρ_α::Vector{T}, ρ_δ::Vector{T}, q::Vector{T}) where {T <: Number} -Return the polynomial coefficients for an [`AdmissibleRegion`](@ref). +Return the polynomial coefficients for an [`AdmissibleRegion`](@ref). !!! reference See equation (8.8) of https://doi.org/10.1017/CBO9781139175371. @@ -114,11 +114,11 @@ function admsreg_coeffs(α::T, δ::T, v_α::T, v_δ::T, ρ::Vector{T}, ρ_α::Vector{T}, ρ_δ::Vector{T}, q::Vector{T}) where {T <: Number} coeffs = Vector{T}(undef, 6) coeffs[1] = dot(q[1:3], q[1:3]) - coeffs[2] = 2 * dot(q[4:6], ρ) + coeffs[2] = 2 * dot(q[4:6], ρ) coeffs[3] = v_α^2 * cos(δ)^2 + v_δ^2 - coeffs[4] = 2 * v_α * dot(q[4:6], ρ_α) + 2 * v_δ * dot(q[4:6], ρ_δ) - coeffs[5] = dot(q[4:6], q[4:6]) - coeffs[6] = 2*dot(q[1:3], ρ) + coeffs[4] = 2 * v_α * dot(q[4:6], ρ_α) + 2 * v_δ * dot(q[4:6], ρ_δ) + coeffs[5] = dot(q[4:6], q[4:6]) + coeffs[6] = 2*dot(q[1:3], ρ) return coeffs end @@ -140,53 +140,53 @@ function topounitpdv(α::T, δ::T) where {T <: Number} end @doc raw""" - admsreg_W(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} + admsreg_W(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} -W function of an [`AdmissibleRegion`](@ref). +W function of an [`AdmissibleRegion`](@ref). !!! reference See equation (8.9) of https://doi.org/10.1017/CBO9781139175371. """ -function admsreg_W(coeffs::Vector{T}, ρ::S) where {T <: AbstractFloat, S <: Number} +function admsreg_W(coeffs::Vector{T}, ρ::S) where {T <: AbstractFloat, S <: Number} return coeffs[3] * ρ^2 + coeffs[4] * ρ + coeffs[5] end admsreg_W(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} = admsreg_W(A.coeffs, ρ) @doc raw""" - admsreg_S(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} + admsreg_S(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} -S function of an [`AdmissibleRegion`](@ref). +S function of an [`AdmissibleRegion`](@ref). !!! reference See equation (8.9) of https://doi.org/10.1017/CBO9781139175371. """ -function admsreg_S(coeffs::Vector{T}, ρ::S) where {T <: AbstractFloat, S <: Number} +function admsreg_S(coeffs::Vector{T}, ρ::S) where {T <: AbstractFloat, S <: Number} return ρ^2 + coeffs[6] * ρ + coeffs[1] end admsreg_S(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} = admsreg_S(A.coeffs, ρ) @doc raw""" - admsreg_U(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} + admsreg_U(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} -U function of an [`AdmissibleRegion`](@ref). +U function of an [`AdmissibleRegion`](@ref). !!! reference See second equation after (8.9) of https://doi.org/10.1017/CBO9781139175371. """ -function admsreg_U(coeffs::Vector{T}, ρ::S) where {T <: AbstractFloat, S <: Number} +function admsreg_U(coeffs::Vector{T}, ρ::S) where {T <: AbstractFloat, S <: Number} return coeffs[2]^2/4 - admsreg_W(coeffs, ρ) + 2*k_gauss^2/sqrt(admsreg_S(coeffs, ρ)) end admsreg_U(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} = admsreg_U(A.coeffs, ρ) @doc raw""" - admsreg_V(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} + admsreg_V(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} -V function of an [`AdmissibleRegion`](@ref). +V function of an [`AdmissibleRegion`](@ref). !!! reference See first equation after (8.9) of https://doi.org/10.1017/CBO9781139175371. """ -function admsreg_V(coeffs::Vector{T}, ρ::S, v_ρ::S) where {T <: AbstractFloat, S <: Number} +function admsreg_V(coeffs::Vector{T}, ρ::S, v_ρ::S) where {T <: AbstractFloat, S <: Number} return v_ρ^2 + coeffs[2] * v_ρ + admsreg_W(coeffs, ρ) - 2*k_gauss^2/sqrt(admsreg_S(coeffs, ρ)) end admsreg_V(A::AdmissibleRegion{T}, ρ::S, v_ρ::S) where {T <: AbstractFloat, S <: Number} = admsreg_V(A.coeffs, ρ, v_ρ) @@ -237,7 +237,7 @@ function boundary(A::AdmissibleRegion{T}, t::S) where {T <: AbstractFloat, S <: # ρ = x_min if 0.0 <= t <= 1.0 return [x_min, y_min + t * (y_max - y_min)] - else + else # Upper curve if 1.0 <= t <= 2.0 ρ = x_min + (t-1)*(x_max - x_min) @@ -247,7 +247,7 @@ function boundary(A::AdmissibleRegion{T}, t::S) where {T <: AbstractFloat, S <: ρ = x_max - (t-2)*(x_max - x_min) v_ρ = range_rate(A, ρ)[1] end - return [ρ, v_ρ] + return [ρ, v_ρ] end end @@ -282,7 +282,7 @@ function in(P::Vector{T}, A::AdmissibleRegion{T}) where {T <: AbstractFloat} else return y_range[1] <= P[2] <= y_range[2] end - else + else return false end end @@ -297,7 +297,7 @@ function topo2bary(A::AdmissibleRegion{T}, ρ::U, v_ρ::U) where {T <: AbstractF # Barycentric position r = A.q[1:3] + ρ * A.ρ_unit + sseph(su, datetime2days(A.date))[1:3] # Barycentric velocity - v = A.q[4:6] + v_ρ * A.ρ_unit + ρ * A.v_α * A.ρ_α + ρ * A.v_δ * A.ρ_δ + v = A.q[4:6] + v_ρ * A.ρ_unit + ρ * A.v_α * A.ρ_α + ρ * A.v_δ * A.ρ_δ + sseph(su, datetime2days(A.date))[4:6] # Barycentric state vector return vcat(r, v) @@ -315,7 +315,7 @@ function bary2topo(A::AdmissibleRegion{T}, q0::Vector{U}) where {T <: AbstractFl # Topocentric range ρ = norm((r - A.q)[1:3]) # Topocentric range rate - v_ρ = dot(r[4:6], A.ρ_unit) - dot(A.q[4:6], A.ρ_unit) - ρ * A.v_α * dot(A.ρ_α, A.ρ_unit) + v_ρ = dot(r[4:6], A.ρ_unit) - dot(A.q[4:6], A.ρ_unit) - ρ * A.v_α * dot(A.ρ_α, A.ρ_unit) - ρ * A.v_δ * dot(A.ρ_δ, A.ρ_unit) return ρ, v_ρ @@ -323,16 +323,16 @@ end # Propagate an orbit and compute residuals function propres(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{U}, - params::NEOParameters{T}) where {T <: AbstractFloat, U <: Number} + params::NEOParameters{T}; dynamics::D=newtonian!) where {D, T <: AbstractFloat, U <: Number} # Time of first (last) observation t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) # Years in backward (forward) integration nyears_bwd = -(jd0 - t0 + params.bwdoffset) / yr nyears_fwd = (tf - jd0 + params.fwdoffset) / yr # Backward (forward) integration - bwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_bwd, q0, params) - fwd = propagate(RNp1BP_pN_A_J23E_J2S_eph_threads!, jd0, nyears_fwd, q0, params) - if !issuccessfulprop(bwd, t0 - jd0; tol = params.coeffstol) || + bwd = propagate(dynamics, jd0, nyears_bwd, q0, params) + fwd = propagate(dynamics, jd0, nyears_fwd, q0, params) + if !issuccessfulprop(bwd, t0 - jd0; tol = params.coeffstol) || !issuccessfulprop(fwd, tf - jd0; tol = params.coeffstol) return bwd, fwd, Vector{OpticalResidual{T, U}}(undef, 0) end @@ -341,7 +341,7 @@ function propres(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{U}, xvs = et -> auday2kmsec(params.eph_su(et/daysec)), xve = et -> auday2kmsec(params.eph_ea(et/daysec)), xva = et -> bwdfwdeph(et, bwd, fwd)) - + return bwd, fwd, res end @@ -353,13 +353,13 @@ Adaptative moment estimation (ADAM) minimizer of normalized mean square residual over and admissible region `A`. !!! warning - This function will set the (global) `TaylorSeries` variables to `δρ δvρ`. + This function will set the (global) `TaylorSeries` variables to `δρ δvρ`. !!! reference See Algorithm 1 of https://doi.org/10.48550/arXiv.1412.6980. """ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, params::NEOParameters{T}; - η::T = 25.0, μ::T = 0.75, ν::T = 0.9, ϵ::T = 1e-8, Qtol::T = 0.001) where {T <: AbstractFloat} + η::T = 25.0, μ::T = 0.75, ν::T = 0.9, ϵ::T = 1e-8, Qtol::T = 0.001, dynamics::D=newtonian!) where {T <: AbstractFloat, D} # Initial time of integration [julian days] jd0 = datetime2julian(A.date) # Center @@ -391,7 +391,7 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, params::NEOPar # Current barycentric state vector q = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) # Propagation and residuals - _, _, res = propres(radec, jd0, q, params) + _, _, res = propres(radec, jd0, q, params; dynamics) iszero(length(res)) && break # Current Q Q = nms(res) @@ -426,7 +426,7 @@ end Monte Carlo sampling over the left boundary of `A`. """ function ρminmontecarlo(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, - params::NEOParameters{T}; N_samples::Int = 25) where {T <: AbstractFloat} + params::NEOParameters{T}; N_samples::Int = 25, dynamics::D=newtonian!) where {T <: AbstractFloat, D} # Initial time of integration [julian days] jd0 = datetime2julian(A.date) # Range lower bound @@ -440,10 +440,10 @@ function ρminmontecarlo(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, # Barycentric initial conditions q = topo2bary(A, ρ, v_ρs[i]) # Propagation & residuals - _, _, res = propres(radec, jd0, q, params) + _, _, res = propres(radec, jd0, q, params; dynamics) iszero(length(res)) && continue # NRMS - Qs[i] = nrms(res) + Qs[i] = nrms(res) end # Find solution with smallest Q t = argmin(Qs) @@ -459,10 +459,10 @@ Used within [`tooshortarc`](@ref) to compute an orbit from a point in an admissible region via least squares. !!! warning - This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. + This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. """ function tsals(A::AdmissibleRegion{T}, radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, - i::Int, ρ::T, v_ρ::T, params::NEOParameters{T}; maxiter::Int = 5) where {T <: AbstractFloat} + i::Int, ρ::T, v_ρ::T, params::NEOParameters{T}; maxiter::Int = 5, dynamics::D=newtonian!) where {T <: AbstractFloat, D} # Initial time of integration [julian days] # (corrected for light-time) jd0 = datetime2julian(A.date) - ρ / c_au_per_day @@ -488,7 +488,7 @@ function tsals(A::AdmissibleRegion{T}, radec::Vector{RadecMPC{T}}, tracklets::Ve # Initial conditions q = q0 + dq # Propagation & residuals - bwd, fwd, res = propres(radec, jd0, q, params) + bwd, fwd, res = propres(radec, jd0, q, params; dynamics) iszero(length(res)) && break # Orbit fit fit = tryls(res[idxs], x0, params.niter) @@ -502,7 +502,7 @@ function tsals(A::AdmissibleRegion{T}, radec::Vector{RadecMPC{T}}, tracklets::Ve idxs = vcat(idxs, extra) sort!(idxs) g_f = k - else + else break end end @@ -515,7 +515,7 @@ function tsals(A::AdmissibleRegion{T}, radec::Vector{RadecMPC{T}}, tracklets::Ve idxs = vcat(idxs, extra) sort!(idxs) g_0 = k - else + else break end end @@ -532,7 +532,7 @@ function tsals(A::AdmissibleRegion{T}, radec::Vector{RadecMPC{T}}, tracklets::Ve flag && break else break - end + end # Update values q0 = q(fit.x) end @@ -540,7 +540,7 @@ function tsals(A::AdmissibleRegion{T}, radec::Vector{RadecMPC{T}}, tracklets::Ve if isinf(best_Q) return zero(NEOSolution{T, T}) # Case: at least one solution was succesful - else + else return best_sol end end @@ -568,10 +568,10 @@ over the admissible region. - `params::NEOParameters{T}`: see `Admissible Region Parameters` of [`NEOParameters`](@ref). !!! warning - This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. + This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. """ function tooshortarc(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, - params::NEOParameters{T}) where {T <: AbstractFloat} + params::NEOParameters{T}; dynamics::D=newtonian!) where {T <: AbstractFloat, D} # Allocate memory for output best_sol = zero(NEOSolution{T, T}) @@ -584,9 +584,9 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, A = AdmissibleRegion(tracklets[i], params) iszero(A) && continue # ADAM minimization over admissible region - ρ, v_ρ, _ = adam(radec, A, params) + ρ, v_ρ, _ = adam(radec, A, params; dynamics) # 6 variables least squares - sol = tsals(A, radec, tracklets, i, ρ, v_ρ, params; maxiter = 5) + sol = tsals(A, radec, tracklets, i, ρ, v_ρ, params; maxiter = 5, dynamics) # Update best solution if nrms(sol) < nrms(best_sol) best_sol = sol @@ -597,7 +597,7 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, ρ, v_ρ, Q = ρminmontecarlo(radec, A, params) isinf(Q) && continue # 6 variables least squares - sol = tsals(A, radec, tracklets, i, ρ, v_ρ, params; maxiter = 5) + sol = tsals(A, radec, tracklets, i, ρ, v_ρ, params; maxiter = 5, dynamics) # Update best solution if nrms(sol) < nrms(best_sol) best_sol = sol diff --git a/src/propagation/asteroid_dynamical_models.jl b/src/propagation/asteroid_dynamical_models.jl index aa0c2ac1..942d8ca0 100755 --- a/src/propagation/asteroid_dynamical_models.jl +++ b/src/propagation/asteroid_dynamical_models.jl @@ -1172,5 +1172,107 @@ function RNp1BP_pN_A_J23E_J2S_eph_threads!(dq, q, params, t) dq[5] = postNewtonY + accY dq[6] = postNewtonZ + accZ + nothing +end + +@taylorize function newtonian!(dq, q, params, t) + # Julian date of start time + local jd0 = params[4] + # Days since J2000.0 = 2.451545e6 + local dsj2k = t + (jd0 - JD_J2000) + # Solar system ephemeris at dsj2k + local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) + # Type of position / velocity components + local S = eltype(q) + # Interaction matrix with flattened bodies + local UJ_interaction = params[5] + # Number of bodies, including NEA + local N = 10 # Sun, Moon and planets # params[6] + # Number of bodies, except the asteroid + local Nm1 = N-1 + # Vector of mass parameters GM's + local μ = params[7][1:10] + + # zero(q[1]) + local zero_q_1 = auxzero(q[1]) + + #= + Point-mass accelerations + See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + + # Position of the i-th body - position of the asteroid + X = Array{S}(undef, N) # X-axis component + Y = Array{S}(undef, N) # Y-axis component + Z = Array{S}(undef, N) # Z-axis component + + # Distance between the i-th body and the asteroid + r_p2 = Array{S}(undef, N) # r_{i,asteroid}^2 + r_p3d2 = Array{S}(undef, N) # r_p2^1.5 <-> r_{i, asteroid}^3 + + # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 + newtonianCoeff = Array{S}(undef, N) + + # Newtonian coefficient * difference between two positions, i.e., + # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 + newton_acc_X = Array{S}(undef, N) # X-axis component + newton_acc_Y = Array{S}(undef, N) # Y-axis component + newton_acc_Z = Array{S}(undef, N) # Z-axis component + + # Temporary arrays for the sum of full extended body accelerations + temp_accX_i = Array{S}(undef, N) + temp_accY_i = Array{S}(undef, N) + temp_accZ_i = Array{S}(undef, N) + + # Full extended-body accelerations + accX = zero_q_1 + accY = zero_q_1 + accZ = zero_q_1 + + # Fill first 3 elements of dq with velocities + dq[1] = q[4] + dq[2] = q[5] + dq[3] = q[6] + + #= + Compute point-mass Newtonian accelerations, all bodies + See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + Threads.@threads for i in 1:Nm1 + # Position of the i-th body - position of the asteroid + X[i] = ss16asteph_t[3i-2]-q[1] # X-axis component + Y[i] = ss16asteph_t[3i-1]-q[2] # Y-axis component + Z[i] = ss16asteph_t[3i ]-q[3] # Z-axis component + + # Distance between the i-th body and the asteroid + r_p2[i] = ( (X[i]^2)+(Y[i]^2) ) + (Z[i]^2) # r_{i,asteroid}^2 + r_p3d2[i] = r_p2[i]^1.5 # r_p2^1.5 <-> r_{i, asteroid}^3 + + # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 + newtonianCoeff[i] = μ[i]/r_p3d2[i] + + # Newtonian coefficient * difference between two positions, i.e., + # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 + newton_acc_X[i] = X[i]*newtonianCoeff[i] + newton_acc_Y[i] = Y[i]*newtonianCoeff[i] + newton_acc_Z[i] = Z[i]*newtonianCoeff[i] + end + + for i in 1:Nm1 + # Newtonian point-mass accelerations + temp_accX_i[i] = accX + newton_acc_X[i] + accX = temp_accX_i[i] + temp_accY_i[i] = accY + newton_acc_Y[i] + accY = temp_accY_i[i] + temp_accZ_i[i] = accZ + newton_acc_Z[i] + accZ = temp_accZ_i[i] + end + + # Fill dq[4:6] with accelerations + # Newtonian point-mass accelerations + dq[4] = accX + dq[5] = accY + dq[6] = accZ + nothing end \ No newline at end of file diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index e75990fc..d84a9544 100755 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -10,17 +10,17 @@ using NEOs: NEOSolution, numberofdays @testset "Orbit Determination" begin @testset "Gauss Method" begin - # Load observations + # Load observations radec = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) # Parameters params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, bwdoffset = 0.007, fwdoffset = 0.007) - + # Orbit Determination sol = orbitdetermination(radec, params) - + # Values by February 4, 2024 - + # Vector of observations @test length(radec) == 123 @test numberofdays(radec) < 21.0 @@ -59,19 +59,19 @@ using NEOs: NEOSolution, numberofdays filename = joinpath("data", "2008_EK68.txt") # Download observations get_radec_mpc("designation" => "2008 EK68", filename) - # Load observations + # Load observations radec = read_radec_mpc(filename) # Delete astrometry file rm(filename) # Parameters params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, bwdoffset = 0.007, fwdoffset = 0.007) - + # Orbit Determination sol = orbitdetermination(radec, params) # Values by February 4, 2024 - + # Vector of observations @test length(radec) == 10 @test numberofdays(radec) < 0.05 @@ -110,7 +110,7 @@ using NEOs: NEOSolution, numberofdays filename = joinpath("data", "2007_VV7.txt") # Download observations get_radec_mpc("designation" => "2007 VV7", filename) - # Load observations + # Load observations radec = read_radec_mpc(filename) # Delete astrometry file rm(filename) @@ -165,19 +165,19 @@ using NEOs: NEOSolution, numberofdays filename = joinpath("data", "2014_AA.txt") # Download observations get_radec_mpc("designation" => "2014 AA", filename) - # Load observations + # Load observations radec = read_radec_mpc(filename) # Delete astrometry file rm(filename) # Parameters params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, bwdoffset = 0.007, fwdoffset = 0.007) - + # Orbit Determination sol = orbitdetermination(radec, params) # Values by February 4, 2024 - + # Vector of observations @test length(radec) == 7 @test numberofdays(radec) < 0.05 @@ -216,7 +216,7 @@ using NEOs: NEOSolution, numberofdays filename = joinpath("data", "2008_TC3.txt") # Download observations get_radec_mpc("designation" => "2008 TC3", filename) - # Load observations + # Load observations radec = read_radec_mpc(filename) # Delete astrometry file rm(filename) @@ -224,13 +224,13 @@ using NEOs: NEOSolution, numberofdays params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, coeffstol = Inf, fwdoffset = 0.007) - # Observations with <1" weight + # Observations with <1" weight idxs = findall(x -> x < 1, w8sveres17.(radec)) # Restricted Orbit Determination sol = orbitdetermination(radec[idxs], params) # Values by February 4, 2024 - + # Vector of observations @test length(radec) == 883 @test numberofdays(radec) < 0.80 From 9aef38eef8a7e658a3d2b3c6dd07a86e5e70f7cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 7 Feb 2024 07:41:36 -0600 Subject: [PATCH 130/173] fetch_radec_mpc --- src/NEOs.jl | 3 ++- src/observations/radec_mpc.jl | 18 ++++++++++++++ test/observations.jl | 10 ++------ test/orbit_determination.jl | 47 ++++++++++------------------------- test/propagation.jl | 6 ++--- 5 files changed, 38 insertions(+), 46 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index 807f1231..a0547a75 100755 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -38,7 +38,8 @@ export unknowncat, read_catalogues_mpc, write_catalogues_mpc, update_catalogues_ export unknownobs, hascoord, read_observatories_mpc, write_observatories_mpc, update_observatories_mpc, search_obs_code # RadecMPC -export ra, dec, date, observatory, read_radec_mpc, write_radec_mpc, get_radec_mpc +export ra, dec, date, observatory, read_radec_mpc, write_radec_mpc, get_radec_mpc, + fetch_radec_mpc # RadarJPL export hasdelay, hasdoppler, delay, doppler, rcvr, xmit, read_radar_jpl, write_radar_jpl # Units diff --git a/src/observations/radec_mpc.jl b/src/observations/radec_mpc.jl index be682448..797811dc 100755 --- a/src/observations/radec_mpc.jl +++ b/src/observations/radec_mpc.jl @@ -411,6 +411,24 @@ function get_radec_mpc(id::Pair{String, String}, filename::String = replace(id[2 return filename end +@doc raw""" + fetch_radec_mpc(id::Pair{String, String}) + +Download MPC optical astrometry of NEO `id` and return the output as `Vector{RadecMPC{Float64}}`. +""" +function fetch_radec_mpc(id::Pair{String, String}) + # Temporary file + f = tempname() + # Download optical astrometry + get_radec_mpc(id, f) + # Parse optical astrometry + radec = read_radec_mpc(f) + # Delete temporary file + rm(f) + + return radec +end + # Methods to convert a Vector{<:AbstractAstrometry} to a DataFrame istable(::Type{Vector{<:AbstractAstrometry}}) = true rowaccess(::Type{Vector{<:AbstractAstrometry}}) = true diff --git a/test/observations.jl b/test/observations.jl index da804860..066004f4 100755 --- a/test/observations.jl +++ b/test/observations.jl @@ -288,16 +288,10 @@ using NEOs: src_path # Choose this example because of the discontinuity in α - # Optical astrometry file - filename = joinpath("data", "2020_TJ6.txt") - # Download optical astrometry - get_radec_mpc("designation" => "2020 TJ6", filename) - # Parse observations - radec = read_radec_mpc(filename) + # Fetch optical astrometry + radec = fetch_radec_mpc("designation" => "2020 TJ6") # Reduce tracklets tracklets = reduce_tracklets(radec) - # Remove downloaded file - rm(filename) # Values by December 19, 2023 @test length(tracklets) == 5 diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index d84a9544..580b88ef 100755 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -55,14 +55,9 @@ using NEOs: NEOSolution, numberofdays end @testset "Too Short Arc" begin - # Optical astrometry file - filename = joinpath("data", "2008_EK68.txt") - # Download observations - get_radec_mpc("designation" => "2008 EK68", filename) - # Load observations - radec = read_radec_mpc(filename) - # Delete astrometry file - rm(filename) + # Fetch optical astrometry + radec = fetch_radec_mpc("designation" => "2008 EK68") + # Parameters params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, bwdoffset = 0.007, fwdoffset = 0.007) @@ -106,14 +101,9 @@ using NEOs: NEOSolution, numberofdays end @testset "Outlier Rejection" begin - # Optical astrometry file - filename = joinpath("data", "2007_VV7.txt") - # Download observations - get_radec_mpc("designation" => "2007 VV7", filename) - # Load observations - radec = read_radec_mpc(filename) - # Delete astrometry file - rm(filename) + # Fetch optical astrometry + radec = fetch_radec_mpc("designation" => "2007 VV7") + # Parameters params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, bwdoffset = 0.007, fwdoffset = 0.007) @@ -157,18 +147,12 @@ using NEOs: NEOSolution, numberofdays end @testset "Interesting NEOs" begin - using NEOs: reduce_tracklets, selecteph, sseph, propres, evalfit # 2014 AA hit the Earth around January 2, 2014, 02:49 UTC - # Optical astrometry file - filename = joinpath("data", "2014_AA.txt") - # Download observations - get_radec_mpc("designation" => "2014 AA", filename) - # Load observations - radec = read_radec_mpc(filename) - # Delete astrometry file - rm(filename) + # Fetch optical astrometry + radec = fetch_radec_mpc("designation" => "2014 AA") + # Parameters params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, bwdoffset = 0.007, fwdoffset = 0.007) @@ -212,17 +196,12 @@ using NEOs: NEOSolution, numberofdays # 2008 TC3 entered the Earth's atmosphere around October 7, 2008, 02:46 UTC - # Optical astrometry file - filename = joinpath("data", "2008_TC3.txt") - # Download observations - get_radec_mpc("designation" => "2008 TC3", filename) - # Load observations - radec = read_radec_mpc(filename) - # Delete astrometry file - rm(filename) + # Fetch optical astrometry + radec = fetch_radec_mpc("designation" => "2008 TC3") + # Parameters params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, - coeffstol = Inf, fwdoffset = 0.007) + coeffstol = Inf, bwdoffset = 0.007, fwdoffset = 0.007) # Observations with <1" weight idxs = findall(x -> x < 1, w8sveres17.(radec)) diff --git a/test/propagation.jl b/test/propagation.jl index 9dc15980..c30f6f03 100755 --- a/test/propagation.jl +++ b/test/propagation.jl @@ -96,7 +96,7 @@ using InteractiveUtils: methodswith # Read optical astrometry file - obs_radec_mpc_2023DW = NEOs.read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) + obs_radec_mpc_2023DW = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) # Compute residuals _res_ = NEOs.residuals( @@ -200,7 +200,7 @@ using InteractiveUtils: methodswith rm("test.jld2") # Read optical astrometry file - obs_radec_mpc_apophis = NEOs.read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) + obs_radec_mpc_apophis = read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) # Compute optical astrometry residuals _res_radec_ = NEOs.residuals( @@ -343,7 +343,7 @@ using InteractiveUtils: methodswith eph_ea = selecteph(sseph_obs, ea) # Read optical astrometry file - obs_radec_mpc_apophis = NEOs.read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) + obs_radec_mpc_apophis = read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) # Compute optical astrometry residuals _res_radec_ = NEOs.residuals( From 7bc8349c2822a0af4abebefb9e312edf48124db0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 7 Feb 2024 11:37:31 -0600 Subject: [PATCH 131/173] H_max to NEOParameters --- src/orbit_determination/tooshortarc.jl | 4 +--- src/propagation/parameters.jl | 6 ++++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 638a924d..b909622e 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -78,10 +78,8 @@ function AdmissibleRegion(tracklet::Tracklet{T}, params::NEOParameters{T}) where ρ_min = R_EA end else - # Maximum allowed absolute magnitude - H_max = 32.0 # Tiny object boundary - ρ_min = 10^((h - H_max)/5) + ρ_min = 10^((h - params.H_max)/5) end ρ_min > ρ_max && return zero(AdmissibleRegion{T}) # Range domain diff --git a/src/propagation/parameters.jl b/src/propagation/parameters.jl index db2438a4..67eb94ea 100644 --- a/src/propagation/parameters.jl +++ b/src/propagation/parameters.jl @@ -22,6 +22,7 @@ struct NEOParameters{T <: AbstractFloat} varorder::Int Q_max::T # Admissible Region parameters + H_max::T maxiter::Int # Outlier rejection parameters max_per::T @@ -64,6 +65,7 @@ Parameters for all orbit determination functions. # Admissible Region Parameters +- `H_max::T`: maximum absolute magnitude (default: `32.0`). - `maxiter::Int`: maximum number of iterations for admissible region `ADAM` optimizer (default: `100`). # Outlier Rejection Parameters @@ -74,7 +76,7 @@ function NEOParameters(; maxsteps::Int = 500, μ_ast::Vector{T} = μ_ast343_DE43 order::Int = 25, abstol::T = 1e-20, parse_eqs::Bool = true, bwdoffset::T = 0.5, fwdoffset::T = 0.5, coeffstol::T = 10.0, debias_table::String = "2018", niter::Int = 5, max_triplets::Int = 10, varorder::Int = 5, Q_max::T = 5.0, - maxiter::Int = 100, max_per::T = 18.0) where {T <: AbstractFloat} + H_max::T = 32.0, maxiter::Int = 100, max_per::T = 18.0) where {T <: AbstractFloat} # Unfold debiasing matrix mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) # Sun (Earth) ephemeris @@ -86,7 +88,7 @@ function NEOParameters(; maxsteps::Int = 500, μ_ast::Vector{T} = μ_ast343_DE43 return NEOParameters{T}(maxsteps, μ_ast, order, abstol, parse_eqs, bwdoffset, fwdoffset, coeffstol, mpc_catalogue_codes_201X, truth, resol, bias_matrix, eph_su, eph_ea, niter, max_triplets, - varorder, Q_max, maxiter, max_per) + varorder, Q_max, H_max, maxiter, max_per) end function NEOParameters(params::NEOParameters{T}; kwargs...) where {T <: AbstractFloat} From 3a74d5b9936f9eb07f428e29d20bfa32c5e6c002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Thu, 8 Feb 2024 08:00:46 -0600 Subject: [PATCH 132/173] nms(::NEOSolution) --- src/orbit_determination/least_squares.jl | 7 +++++++ src/orbit_determination/neosolution.jl | 8 ++++++++ src/orbit_determination/tooshortarc.jl | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/orbit_determination/least_squares.jl b/src/orbit_determination/least_squares.jl index 9ea40c8e..ce54442c 100755 --- a/src/orbit_determination/least_squares.jl +++ b/src/orbit_determination/least_squares.jl @@ -171,15 +171,22 @@ end @doc raw""" nms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} nms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + nms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::LeastSquaresFit{T}) where {T <: Real} Return the normalized chi square. See [`chi2`](@ref). """ nms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} = chi2(res, w) / length(res) + function nms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} _res_, _w_ = unfold(res) return nms(_res_, _w_) end +function nms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::LeastSquaresFit{T}) where {T <: Real} + _res_, _w_ = unfold(res) + return nms(_res_(fit.x), _w_) +end + @doc raw""" nrms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} nrms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} diff --git a/src/orbit_determination/neosolution.jl b/src/orbit_determination/neosolution.jl index 34cf75cc..80498ccc 100755 --- a/src/orbit_determination/neosolution.jl +++ b/src/orbit_determination/neosolution.jl @@ -160,5 +160,13 @@ function nrms(sol::NEOSolution{T, T}) where {T <: Real} return nrms(sol.res) end end +# Normalized Mean Square Error +function nms(sol::NEOSolution{T, T}) where {T <: Real} + if iszero(sol) + return T(Inf) + else + return nms(sol.res) + end +end sigmas(sol::NEOSolution{T, T}) where {T <: Real} = sqrt.(diag(sol.fit.Γ)) .* sol.scalings \ No newline at end of file diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index b909622e..dc698ff9 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -490,7 +490,7 @@ function tsals(A::AdmissibleRegion{T}, radec::Vector{RadecMPC{T}}, tracklets::Ve iszero(length(res)) && break # Orbit fit fit = tryls(res[idxs], x0, params.niter) - !fit.success && continue + !fit.success && break # Right iteration for k in g_f+1:length(tracklets) extra = indices(tracklets[k]) From 71f7d512c4d5c43ceb3e4980fc373614365d8e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 11 Feb 2024 11:39:31 -0600 Subject: [PATCH 133/173] log adam --- src/orbit_determination/tooshortarc.jl | 95 +++++++++++++++++--------- 1 file changed, 62 insertions(+), 33 deletions(-) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index dc698ff9..5be564d9 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -344,29 +344,41 @@ function propres(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{U}, end @doc raw""" - adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, params::NEOParameters{T}; - η::T = 25.0, μ::T = 0.75, ν::T = 0.9, ϵ::T = 1e-8, Qtol::T = 0.001) where {T <: AbstractFloat} + adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, + params::NEOParameters{T}; scale::Symbol = :linear, η::T = 25.0, + μ::T = 0.75, ν::T = 0.9, ϵ::T = 1e-8, Qtol::T = 0.001, + dynamics::D = newtonian!) where {T <: AbstractFloat, D} Adaptative moment estimation (ADAM) minimizer of normalized mean square residual over and admissible region `A`. !!! warning - This function will set the (global) `TaylorSeries` variables to `δρ δvρ`. + This function will set the (global) `TaylorSeries` variables to `dx dy`. !!! reference See Algorithm 1 of https://doi.org/10.48550/arXiv.1412.6980. """ -function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, params::NEOParameters{T}; - η::T = 25.0, μ::T = 0.75, ν::T = 0.9, ϵ::T = 1e-8, Qtol::T = 0.001, dynamics::D=newtonian!) where {T <: AbstractFloat, D} +function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, + params::NEOParameters{T}; scale::Symbol = :linear, η::T = 25.0, + μ::T = 0.75, ν::T = 0.9, ϵ::T = 1e-8, Qtol::T = 0.001, + dynamics::D = newtonian!) where {T <: AbstractFloat, D} # Initial time of integration [julian days] jd0 = datetime2julian(A.date) - # Center - ρ = sum(A.ρ_domain) / 2 - v_ρ = sum(A.v_ρ_domain) / 2 # Scaling factors - scalings = [A.ρ_domain[2] - A.ρ_domain[1], A.v_ρ_domain[2] - A.v_ρ_domain[1]] / 1_000 + if scale == :linear + scalings = [ + A.ρ_domain[2] - A.ρ_domain[1], + A.v_ρ_domain[2] - A.v_ρ_domain[1] + ] / 1_000 + elseif scale == :log + x = log10(ρ) + scalings = [ + log10(A.ρ_domain[2]) - log10(A.ρ_domain[1]), + A.v_ρ_domain[2] - A.v_ρ_domain[1] + ] / 1_000 + end # Jet transport variables - dq = scaled_variables("dρ dvρ", scalings, order = 1) + dq = scaled_variables("dx dy", scalings, order = 1) # Maximum number of iterations maxiter = params.maxiter # Allocate memory @@ -387,7 +399,11 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, params::NEOPar ρs[t] = ρ v_ρs[t] = v_ρ # Current barycentric state vector - q = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) + if scale == :linear + q = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) + elseif scale == :log + q = topo2bary(A, 10^(x + dq[1]), v_ρ + dq[2]) + end # Propagation and residuals _, _, res = propres(radec, jd0, q, params; dynamics) iszero(length(res)) && break @@ -410,6 +426,9 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, params::NEOPar ρ, v_ρ = bary2topo(A, q(x1)) # Projection ρ, v_ρ = boundary_projection(A, ρ, v_ρ) + if scale == :log + x = log10(ρ) + end end # Find point with smallest Q t = argmin(Qs) @@ -457,7 +476,7 @@ Used within [`tooshortarc`](@ref) to compute an orbit from a point in an admissible region via least squares. !!! warning - This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. + This function will set the (global) `TaylorSeries` variables to `dx₁ dx₂ dx₃ dx₄ dx₅ dx₆`. """ function tsals(A::AdmissibleRegion{T}, radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, i::Int, ρ::T, v_ρ::T, params::NEOParameters{T}; maxiter::Int = 5, dynamics::D=newtonian!) where {T <: AbstractFloat, D} @@ -554,7 +573,7 @@ end @doc raw""" tooshortarc(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, - params::NEOParameters{T}) where {T <: AbstractFloat} + params::NEOParameters{T}; dynamics::D = newtonian!) where {T <: AbstractFloat, D} Return initial conditions by minimizing the normalized root mean square residual over the admissible region. @@ -564,12 +583,13 @@ over the admissible region. - `radec::Vector{RadecMPC{T}}`: vector of observations. - `tracklets::Vector{Tracklet{T}},`: vector of tracklets. - `params::NEOParameters{T}`: see `Admissible Region Parameters` of [`NEOParameters`](@ref). +- `dynamics::D`: dynamical function. !!! warning - This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. + This function will set the (global) `TaylorSeries` variables to `dx₁ dx₂ dx₃ dx₄ dx₅ dx₆`. """ function tooshortarc(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, - params::NEOParameters{T}; dynamics::D=newtonian!) where {T <: AbstractFloat, D} + params::NEOParameters{T}; dynamics::D = newtonian!) where {T <: AbstractFloat, D} # Allocate memory for output best_sol = zero(NEOSolution{T, T}) @@ -581,26 +601,35 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, # Admissible region A = AdmissibleRegion(tracklets[i], params) iszero(A) && continue + # Center + ρ = sum(A.ρ_domain) / 2 + v_ρ = sum(A.v_ρ_domain) / 2 # ADAM minimization over admissible region - ρ, v_ρ, _ = adam(radec, A, params; dynamics) - # 6 variables least squares - sol = tsals(A, radec, tracklets, i, ρ, v_ρ, params; maxiter = 5, dynamics) - # Update best solution - if nrms(sol) < nrms(best_sol) - best_sol = sol - # Break condition - nrms(sol) < 1.5 && break + ρ, v_ρ, Q = adam(radec, A, ρ, v_ρ, params; scale = :linear, dynamics = dynamics) + if !isinf(Q) + # 6 variables least squares + sol = tsals(A, radec, tracklets, i, ρ, v_ρ, params; maxiter = 5, dynamics) + # Update best solution + if nrms(sol) < nrms(best_sol) + best_sol = sol + # Break condition + nrms(sol) < 1.5 && break + end end - # Left boundary Monte Carlo - ρ, v_ρ, Q = ρminmontecarlo(radec, A, params) - isinf(Q) && continue - # 6 variables least squares - sol = tsals(A, radec, tracklets, i, ρ, v_ρ, params; maxiter = 5, dynamics) - # Update best solution - if nrms(sol) < nrms(best_sol) - best_sol = sol - # Break condition - nrms(sol) < 1.5 && break + # Left boundary + ρ = A.ρ_domain[1] + v_ρ = sum(A.v_ρ_domain) / 2 + # ADAM minimization over admissible region + ρ, v_ρ, Q = adam(radec, A, ρ, v_ρ, params; scale = :log, dynamics = dynamics) + if !isinf(Q) + # 6 variables least squares + sol = tsals(A, radec, tracklets, i, ρ, v_ρ, params; maxiter = 5, dynamics) + # Update best solution + if nrms(sol) < nrms(best_sol) + best_sol = sol + # Break condition + nrms(sol) < 1.5 && break + end end end From 93c743d84ef70ee138df128e2e81ec1f96a210d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 11 Feb 2024 18:06:00 -0600 Subject: [PATCH 134/173] Isolate outlier_rejection --- src/NEOs.jl | 2 +- src/orbit_determination/gauss_method.jl | 5 +++-- src/orbit_determination/orbit_determination.jl | 12 +++++------- src/orbit_determination/tooshortarc.jl | 2 +- .../outlier_rejection.jl | 7 +++++-- test/orbit_determination.jl | 5 ++++- 6 files changed, 19 insertions(+), 14 deletions(-) rename src/{orbit_determination => postprocessing}/outlier_rejection.jl (96%) diff --git a/src/NEOs.jl b/src/NEOs.jl index a0547a75..9228b2e7 100755 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -77,8 +77,8 @@ export issinglearc, istsa, orbitdetermination include("constants.jl") include("observations/process_radar.jl") include("propagation/propagation.jl") -include("postprocessing/b_plane.jl") include("orbit_determination/orbit_determination.jl") +include("postprocessing/outlier_rejection.jl") include("init.jl") end \ No newline at end of file diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 1404c66b..194c561c 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -417,7 +417,7 @@ end @doc raw""" gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, - params::NEOParameters{T}) where {T <: AbstractFloat} + params::NEOParameters{T}; dynamics::D = newtonian!) where {T <: AbstractFloat, D} Return initial conditions via Gauss Method. @@ -428,12 +428,13 @@ See also [`gauss_method`](@ref). - `radec::Vector{RadecMPC{T}}`: vector of observations. - `tracklets::Vector{Tracklet{T}},`: vector of tracklets. - `params::NEOParameters{T}`: see `Gauss Method Parameters` of [`NEOParameters`](@ref). +- `dynamics::D`: dynamical model. !!! warning This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. """ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, - params::NEOParameters{T}; dynamics::D=newtonian!) where {T <: AbstractFloat, D} + params::NEOParameters{T}; dynamics::D = newtonian!) where {T <: AbstractFloat, D} # Allocate memory for initial conditions best_sol = zero(NEOSolution{T, T}) diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index f9d0d7fa..7aad0ece 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -3,7 +3,6 @@ include("least_squares.jl") include("neosolution.jl") include("tooshortarc.jl") include("gauss_method.jl") -include("outlier_rejection.jl") @doc raw""" issinglearc(radec::Vector{RadecMPC{T}}, arc::Day = Day(30)) where {T <: AbstractFloat} @@ -66,7 +65,8 @@ function adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFlo end @doc raw""" - orbitdetermination(radec::Vector{RadecMPC{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} + orbitdetermination(radec::Vector{RadecMPC{T}}, params::NEOParameters{T}; + dynamics::D = newtonian!) where {T <: AbstractFloat, D} Initial Orbit Determination (IOD) routine. @@ -74,8 +74,10 @@ Initial Orbit Determination (IOD) routine. - `radec::Vector{RadecMPC{T}}`: vector of observations. - `params::NEOParameters{T}`: see [`NEOParameters`](@ref). +- `dynamics::D`: dynamical model. """ -function orbitdetermination(radec::Vector{RadecMPC{T}}, params::NEOParameters{T}; dynamics::D=newtonian!) where {T <: AbstractFloat, D} +function orbitdetermination(radec::Vector{RadecMPC{T}}, params::NEOParameters{T}; + dynamics::D = newtonian!) where {T <: AbstractFloat, D} # Allocate memory for output sol = zero(NEOSolution{T, T}) @@ -96,10 +98,6 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, params::NEOParameters{T} else sol = gaussinitcond(radec, tracklets, params; dynamics) end - # Outlier rejection (if needed) - if nrms(sol) > 1 && !iszero(sol) - sol = outlier_rejection(radec, sol, params; dynamics) - end return sol::NEOSolution{T, T} end diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 5be564d9..973c5e29 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -583,7 +583,7 @@ over the admissible region. - `radec::Vector{RadecMPC{T}}`: vector of observations. - `tracklets::Vector{Tracklet{T}},`: vector of tracklets. - `params::NEOParameters{T}`: see `Admissible Region Parameters` of [`NEOParameters`](@ref). -- `dynamics::D`: dynamical function. +- `dynamics::D`: dynamical model. !!! warning This function will set the (global) `TaylorSeries` variables to `dx₁ dx₂ dx₃ dx₄ dx₅ dx₆`. diff --git a/src/orbit_determination/outlier_rejection.jl b/src/postprocessing/outlier_rejection.jl similarity index 96% rename from src/orbit_determination/outlier_rejection.jl rename to src/postprocessing/outlier_rejection.jl index dcdb91bd..bfd0b8f0 100644 --- a/src/orbit_determination/outlier_rejection.jl +++ b/src/postprocessing/outlier_rejection.jl @@ -1,3 +1,5 @@ +include("b_plane.jl") + @doc raw""" residual_norm(x::OpticalResidual{T, T}) where {T <: Real} @@ -7,7 +9,7 @@ residual_norm(x::OpticalResidual{T, T}) where {T <: Real} = x.w_α * x.ξ_α^2 / @doc raw""" outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, - params::NEOParameters{T}) where {T <: AbstractFloat} + params::NEOParameters{T}; dynamics::D = newtonian!) where {T <: AbstractFloat, D} Refine an orbit, computed by [`tooshortarc`](@ref) or [`gaussinitcond`](@ref), via propagation and/or outlier rejection. @@ -17,12 +19,13 @@ via propagation and/or outlier rejection. - `radec::Vector{RadecMPC{T}}`: vector of observations. - `sol::NEOSolution{T, T}`: orbit to be refined. - `params::NEOParameters{T}`: see `Outlier Rejection Parameters` of [`NEOParameters`](@ref). +- `dynamics::D`: dynamical model. !!! warning This function will set the (global) `TaylorSeries` variables to `δx₁ δx₂ δx₃ δx₄ δx₅ δx₆`. """ function outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, - params::NEOParameters{T}; dynamics::D=newtonian!) where {T <: AbstractFloat, D} + params::NEOParameters{T}; dynamics::D = newtonian!) where {T <: AbstractFloat, D} # Origin x0 = zeros(T, 6) diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index 580b88ef..9502f37f 100755 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -110,6 +110,8 @@ using NEOs: NEOSolution, numberofdays # Orbit Determination sol = orbitdetermination(radec, params) + # Outlier rejection + sol = outlier_rejection(radec, sol, params) # Values by February 4, 2024 @@ -155,7 +157,8 @@ using NEOs: NEOSolution, numberofdays # Parameters params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, - bwdoffset = 0.007, fwdoffset = 0.007) + coeffstol = Inf, bwdoffset = 0.007, fwdoffset = 0.007, + H_max = 34.0) # Orbit Determination sol = orbitdetermination(radec, params) From c8818f92b4b143c15e6a78cf6e413b60cc435d44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Mon, 12 Feb 2024 07:32:23 -0600 Subject: [PATCH 135/173] Qmax -> NEOParameters --- src/orbit_determination/gauss_method.jl | 2 +- src/orbit_determination/tooshortarc.jl | 4 ++-- src/propagation/parameters.jl | 16 +++++++++------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 194c561c..1324b95a 100755 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -527,7 +527,7 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} res[idxs], fit, scalings)) end # Break condition - if Q <= params.Q_max + if Q <= params.gaussQmax flag = true break end diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 973c5e29..b0673117 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -613,7 +613,7 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, if nrms(sol) < nrms(best_sol) best_sol = sol # Break condition - nrms(sol) < 1.5 && break + nrms(sol) < params.tsaQmax && break end end # Left boundary @@ -628,7 +628,7 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, if nrms(sol) < nrms(best_sol) best_sol = sol # Break condition - nrms(sol) < 1.5 && break + nrms(sol) < params.tsaQmax && break end end end diff --git a/src/propagation/parameters.jl b/src/propagation/parameters.jl index 67eb94ea..436e485a 100644 --- a/src/propagation/parameters.jl +++ b/src/propagation/parameters.jl @@ -20,10 +20,11 @@ struct NEOParameters{T <: AbstractFloat} # Gauss Method parameters max_triplets::Int varorder::Int - Q_max::T + gaussQmax::T # Admissible Region parameters H_max::T maxiter::Int + tsaQmax::T # Outlier rejection parameters max_per::T # Inner constructor is generated by default @@ -60,13 +61,14 @@ Parameters for all orbit determination functions. # Gauss Method Parameters - `max_triplets::Int`: maximum number of triplets to check for a solution (default: `10`). -- `varorder::Int`: order of jet transport perturbation (default: `5`). -- `Q_max::T`: maximum nrms that is considered a good enough orbit (default: `5.0`). +- `varorder::Int`: order of jet transport perturbation (default: `5`). +- `gaussQmax::T`: nrms threshold (default: `5.0`). # Admissible Region Parameters - `H_max::T`: maximum absolute magnitude (default: `32.0`). - `maxiter::Int`: maximum number of iterations for admissible region `ADAM` optimizer (default: `100`). +- `tsaQmax::T`: nrms threshold (default: `1.5`). # Outlier Rejection Parameters @@ -75,8 +77,8 @@ Parameters for all orbit determination functions. function NEOParameters(; maxsteps::Int = 500, μ_ast::Vector{T} = μ_ast343_DE430[1:end], order::Int = 25, abstol::T = 1e-20, parse_eqs::Bool = true, bwdoffset::T = 0.5, fwdoffset::T = 0.5, coeffstol::T = 10.0, debias_table::String = "2018", - niter::Int = 5, max_triplets::Int = 10, varorder::Int = 5, Q_max::T = 5.0, - H_max::T = 32.0, maxiter::Int = 100, max_per::T = 18.0) where {T <: AbstractFloat} + niter::Int = 5, max_triplets::Int = 10, varorder::Int = 5, gaussQmax::T = 5.0, + H_max::T = 32.0, maxiter::Int = 100, tsaQmax::T = 1.5, max_per::T = 18.0) where {T <: AbstractFloat} # Unfold debiasing matrix mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) # Sun (Earth) ephemeris @@ -88,8 +90,8 @@ function NEOParameters(; maxsteps::Int = 500, μ_ast::Vector{T} = μ_ast343_DE43 return NEOParameters{T}(maxsteps, μ_ast, order, abstol, parse_eqs, bwdoffset, fwdoffset, coeffstol, mpc_catalogue_codes_201X, truth, resol, bias_matrix, eph_su, eph_ea, niter, max_triplets, - varorder, Q_max, H_max, maxiter, max_per) -end + varorder, gaussQmax, H_max, maxiter, tsaQmax, max_per) +end function NEOParameters(params::NEOParameters{T}; kwargs...) where {T <: AbstractFloat} fields = fieldnames(NEOParameters{T}) From a928d57c498bec0c59e255222f35a0a9b6a72d04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Mon, 12 Feb 2024 07:46:14 -0600 Subject: [PATCH 136/173] ecef_to_geocentric(::Vector{TaylorN}}) --- src/NEOs.jl | 2 +- src/observations/topocentric.jl | 45 +++++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index 9228b2e7..c7ff65e0 100755 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -4,7 +4,7 @@ module NEOs import Base: show, string, hash, isequal, ==, isless, convert, zero, iszero, isnan, in import Tables: istable, rowaccess, rows, schema, Schema -import SatelliteToolboxTransformations: sv_ecef_to_eci, sv_ecef_to_ecef +import SatelliteToolboxTransformations: sv_ecef_to_eci, sv_ecef_to_ecef, ecef_to_geocentric import JLD2: writeas import PlanetaryEphemeris as PE diff --git a/src/observations/topocentric.jl b/src/observations/topocentric.jl index 48d00d38..c88a48b0 100755 --- a/src/observations/topocentric.jl +++ b/src/observations/topocentric.jl @@ -3,8 +3,8 @@ Day/night at a particular timezone. -# Fields -- `light::Symbol`: +# Fields +- `light::Symbol`: - for ground observatories: `:day` or `:night`, - for space observatories: `:space`. - `start::DateTime`. @@ -15,7 +15,7 @@ Day/night at a particular timezone. light::Symbol start::DateTime stop::DateTime - utc::Int + utc::Int function TimeOfDay(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} if issatellite(observatory) return new(:space, date, date, 0) @@ -24,7 +24,7 @@ Day/night at a particular timezone. utc = hours_from_UTC(observatory) # Today's sunrise / sunset today = sunriseset(date, observatory) - # Yesterday's sunrise / sunset + # Yesterday's sunrise / sunset yesterday = sunriseset(date - Day(1), observatory) # Tomorrow's sunrise / sunset tomorrow = sunriseset(date + Day(1), observatory) @@ -60,7 +60,7 @@ end Return the naive hour difference between longitude `lon` [rad] and UTC. """ hours_from_UTC(lon::T) where {T <: Real} = ceil(Int, 12*lon/π - 0.5) -function hours_from_UTC(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} +function hours_from_UTC(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} lon, _ = lonlat(observatory) return hours_from_UTC(lon) end @@ -79,7 +79,7 @@ function lonlat(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} lat_geocentric, _ = geodetic_to_geocentric(lat_geodetic, altitude) return lon, lat_geocentric -end +end @doc raw""" sunriseset(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} @@ -112,7 +112,7 @@ function sunriseset(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: # UTC time of sunrise [DateTime] sunrise = day + Microsecond(round(Int, sunrise_min*6e7)) # UTC time of sunset [min] - sunset_min = 720 - 4*(rad2deg(lon) + ha_sunset) - eqtime + sunset_min = 720 - 4*(rad2deg(lon) + ha_sunset) - eqtime # UTC time of sunset [DateTime] sunset = day + Microsecond(round(Int, sunset_min*6e7)) @@ -156,9 +156,9 @@ function obsposECEF(observatory::ObservatoryMPC{T}; eop::Union{EopIau1980, EopIa # ECEF position pos_ECEF = convert(Vector{eltype(pv_ECEF.r)}, pv_ECEF.r) - + return pos_ECEF - else + else # λ_deg: longitude [degrees east of Greenwich] # u: distance from spin axis [km], u = ρ*cos(ϕ') # v: height above equatorial plane [km], v = ρ*sin(ϕ'), @@ -254,7 +254,7 @@ models, such as the IAU1976/80 model, can be used by importing the `SatelliteToolboxTransformations.EopIau1980` type and passing it to the `eop` keyword argument in the function call. -See also [`SatelliteToolboxBase.OrbitStateVector`](@ref) and +See also [`SatelliteToolboxBase.OrbitStateVector`](@ref) and [`SatelliteToolboxTransformations.sv_ecef_to_eci`](@ref). # Arguments @@ -269,7 +269,7 @@ See also [`SatelliteToolboxBase.OrbitStateVector`](@ref) and """ function obsposvelECI(observatory::ObservatoryMPC{T}, et::U; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat, U <: Number} - + # Make sure observatory has coordinates @assert hascoord(observatory) "Cannot compute position for observatory [$(observatory.code)] without coordinates" # One with correct type @@ -279,7 +279,7 @@ function obsposvelECI(observatory::ObservatoryMPC{T}, et::U; # @assert datetime2et(observatory.date) == cte(et) return [observatory.long * oneU, observatory.cos * oneU, observatory.sin * oneU, zero(et), zero(et), zero(et)] - else + else # Earth-Centered Earth-Fixed position position of observer pos_ECEF = obsposECEF(observatory) @@ -305,7 +305,7 @@ function obsposvelECI(observatory::ObservatoryMPC{T}, et::U; for i in eachindex(pv_ECI.v) r_ECI[i+3] = pv_ECI.v[i] * oneU end - + return r_ECI end end @@ -316,3 +316,22 @@ end function obsposvelECI(x::RadarJPL{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} return obsposvelECI(x.rcvr, datetime2et(x.date); eop) end + +# Special method of SatelliteToolboxTransformations.ecef_to_geocentric for Vector{TaylorN{T}} +# See https://github.com/JuliaSpace/SatelliteToolboxTransformations.jl/blob/b7790389407a207499d343aa6d546ef54990baa2/src/reference_frames/geodetic_geocentric.jl#L31-L60 +function ecef_to_geocentric(r_e::Vector{TaylorN{T}}) where {T<:AbstractFloat} + + # Auxiliary variables. + x = r_e[1] + y = r_e[2] + z = r_e[3] + x² = x^2 + y² = y^2 + z² = z^2 + + lat = atan(z, √(x² + y²)) + lon = atan(y, x) + r = √(x² + y² + z²) + + return lat, lon, r +end \ No newline at end of file From a1cebd7a715817b2b7c169c8ef69bb8913cbfd8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 13 Feb 2024 10:52:59 -0600 Subject: [PATCH 137/173] Require julia v1.9+ --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 46ce450e..479d716b 100755 --- a/Project.toml +++ b/Project.toml @@ -56,4 +56,4 @@ StatsBase = "0.33, 0.34" Tables = "1.10" TaylorIntegration = "0.14" TaylorSeries = "0.16" -julia = "1.6" +julia = "1.9" From c5498777da98431f13b691c0a356e421470ece3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Tue, 13 Feb 2024 10:54:16 -0600 Subject: [PATCH 138/173] Bump minor version --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 479d716b..63eed1a8 100755 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "NEOs" uuid = "b41c07a2-2abb-11e9-070a-c3c1b239e7df" authors = ["Jorge A. Pérez Hernández", "Luis Benet", "Luis Eduardo Ramírez Montoya"] -version = "0.7.5" +version = "0.8.0" [deps] Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" From 01ca8292578048b73c431efc5a35c44bc10e6f60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 16 Feb 2024 15:28:10 -0600 Subject: [PATCH 139/173] Minor fixes --- src/observations/process_radar.jl | 6 +++--- src/orbit_determination/tooshortarc.jl | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/observations/process_radar.jl b/src/observations/process_radar.jl index 217a2db9..7c77080d 100755 --- a/src/observations/process_radar.jl +++ b/src/observations/process_radar.jl @@ -86,7 +86,7 @@ the solar latitude, and ``A``, ``a``, ``b`` are the solar corona parameters. !!! reference See (Explanatory Supplement to the Astronomical Almanac 2014, p. 323, Sec. 8.7.5, Eq. 8.22). ESAA 2014 in turn refers to Muhleman and Anderson (1981). Ostro (1993) gives a reference to - Anderson (1978), where this model is fitted to Mariner 9 ranging data. Reading + Anderson (1978), where this model is fitted to Mariner 9 ranging data. Reading https://gssc.esa.int/navipedia/index.php/Ionospheric_Delay helped a lot to clarify things, especially the 40.3, although they talk about Earth's ionosphere. Another valuable source is Standish, E.M., Astron. Astrophys. 233, 252-271 (1990). @@ -264,7 +264,7 @@ motion. - `observatory::ObservatoryMPC{T}`: observing station. - `t_r_utc::DateTime`: UTC time of echo reception. -# Keyword arguments +# Keyword arguments - `tord::Int = 5`: order of Taylor expansions. - `niter::Int = 10`: number of light-time solution iterations. @@ -480,7 +480,7 @@ end radar_astrometry(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real; kwargs...) where {T <: AbstractFloat} radar_astrometry(radar::RadarJPL{T}; kwargs...) where {T <: AbstractFloat} radar_astrometry(astradarfile::String; kwargs...) - radar_astrometry(astradardata::Vector{RadarJPL}; kwargs...) where {T <: AbstractFloat} + radar_astrometry(astradardata::Vector{RadarJPL}; kwargs...) where {T <: AbstractFloat} Return time-delay and Doppler shift. diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index b0673117..04b88605 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -207,7 +207,7 @@ with coefficients `coeffs`. """ function max_range(coeffs::Vector{T}) where {T <: AbstractFloat} # Initial guess - sol = find_zeros(s -> admsreg_U(coeffs, s), R_EA, 10.0) + sol = find_zeros(s -> admsreg_U(coeffs, s), R_EA, 100.0) iszero(length(sol)) && return zero(T) ρ_max = sol[1] # Make sure U(ρ) ≥ 0 and there is at least one range_rate solution From 75ba60d3c1e90c2f9af5cb1c330b7f093706e8cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 24 Feb 2024 10:13:59 -0600 Subject: [PATCH 140/173] Add a_max to NEOParameters --- src/observations/process_radec.jl | 22 +++++----- src/orbit_determination/least_squares.jl | 8 +++- src/orbit_determination/tooshortarc.jl | 55 ++++++++++++++---------- src/propagation/parameters.jl | 26 ++++++----- 4 files changed, 66 insertions(+), 45 deletions(-) diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index a20563c0..6ceadcd2 100755 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -1,7 +1,7 @@ @doc raw""" OpticalResidual{T <: Real, U <: Number} -An astrometric optical observed minus computed residual. +An astrometric optical observed minus computed residual. # Fields @@ -120,7 +120,7 @@ computations. - `xvs::SunEph = sunposvel`: Sun ephemeris. - `xva::AstEph`: asteroid ephemeris. -All ephemeris must take [et seconds since J2000] and return [barycentric position in km +All ephemeris must take [et seconds since J2000] and return [barycentric position in km and velocity in km/sec]. """ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter::Int = 5, @@ -142,7 +142,7 @@ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter: R_r = RV_r[1:3] # Receiver barycentric position and velocity at receive time r_r_t_r = r_e_t_r + R_r - + # Down-leg iteration # τ_D first approximation # See equation (1) of https://doi.org/10.1086/116062 @@ -488,12 +488,12 @@ observations taken on the same night by the same observatory. See https://doi.org/10.1016/j.icarus.2017.05.021. """ function relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - # Convert to DataFrame + # Convert to DataFrame df = DataFrame(radec) - # Group by observatory and TimeOfDay + # Group by observatory and TimeOfDay df.TimeOfDay = TimeOfDay.(radec) gdf = groupby(df, [:observatory, :TimeOfDay]) - # Number of observations per tracklet + # Number of observations per tracklet cdf = combine(gdf, nrow) # Count observations in each group Nv = cdf[gdf.groups, :nrow] @@ -506,12 +506,12 @@ end function anglediff(x::T, y::S) where {T, S <: Number} # Signed difference Δ = x - y - # Absolute difference + # Absolute difference Δ_abs = abs(Δ) # Reflection if Δ_abs > 648_000 # Half circle in arcsec - return -sign(cte(Δ)) * (1_296_000 - Δ_abs) - else + return -sign(cte(Δ)) * (1_296_000 - Δ_abs) + else return Δ end end @@ -540,7 +540,7 @@ See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and - `xvs::SunEph = sunposvel`: Sun ephemeris. - `xva::AstEph`: asteroid ephemeris. -All ephemeris must take [et seconds since J2000] and return [barycentric position in km +All ephemeris must take [et seconds since J2000] and return [barycentric position in km and velocity in km/sec]. """ function residuals(obs::Vector{RadecMPC{T}}; debias_table::String = "2018", xva::AstEph, @@ -563,7 +563,7 @@ function residuals(obs::Vector{RadecMPC{T}}, mpc_catalogue_codes_201X::Vector{St # Type of asteroid ephemeris S = typeof(a1_et1) - # Relax factors + # Relax factors rex = relax_factor(obs) # Vector of residuals diff --git a/src/orbit_determination/least_squares.jl b/src/orbit_determination/least_squares.jl index ce54442c..bc4cae11 100755 --- a/src/orbit_determination/least_squares.jl +++ b/src/orbit_determination/least_squares.jl @@ -32,7 +32,13 @@ end # Succesful differential corrections function show(io::IO, fit::LeastSquaresFit{T}) where {T <: Real} success_s = fit.success ? "Succesful" : "Unsuccesful" - routine_s = fit.routine == :newton ? "Newton" : "differential corrections" + if fit.routine == :newton + routine_s = "Newton" + elseif fit.routine == :diffcorr + routine_s = "Differential corrections" + elseif fit.routine == :levmar + routine_s = "Levenberg-Marquardt" + end print(io, success_s, " ", routine_s) end diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 04b88605..99aba33e 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -11,6 +11,8 @@ some dynamical constrainits on a too short arc. - `δ::T`: declination. - `v_α::T`: right ascension velocity. - `v_δ::T`: declination velocity. +- `H_max::T`: maximum absolute magnitude. +- `a_max::T`: maximum semimajor axis. - `ρ_unit, ρ_α, ρ_δ::Vector{T}`: topocentric unit vector and its partials. - `q::Vector{T}`: heliocentric position of observer. - `coeffs::Vector{T}`: polynomial coefficients. @@ -28,6 +30,8 @@ some dynamical constrainits on a too short arc. δ::T v_α::T v_δ::T + H_max::T + a_max::T ρ_unit::Vector{T} ρ_α::Vector{T} ρ_δ::Vector{T} @@ -42,9 +46,10 @@ end # Definition of zero AdmissibleRegion{T} function zero(::Type{AdmissibleRegion{T}}) where {T <: AbstractFloat} return AdmissibleRegion{T}( - DateTime(2000), zero(T), zero(T), zero(T), zero(T), Vector{T}(undef, 0), - Vector{T}(undef, 0), Vector{T}(undef, 0), Vector{T}(undef, 0), Vector{T}(undef, 0), - Vector{T}(undef, 0), Vector{T}(undef, 0), Matrix{T}(undef, 0, 0), unknownobs() + DateTime(2000), zero(T), zero(T), zero(T), zero(T), zero(T), zero(T), + Vector{T}(undef, 0), Vector{T}(undef, 0), Vector{T}(undef, 0), + Vector{T}(undef, 0), Vector{T}(undef, 0), Vector{T}(undef, 0), + Vector{T}(undef, 0), Matrix{T}(undef, 0, 0), unknownobs() ) end @@ -55,6 +60,7 @@ function AdmissibleRegion(tracklet::Tracklet{T}, params::NEOParameters{T}) where # Unfold obs, t_datetime, α, δ = observatory(tracklet), date(tracklet), ra(tracklet), dec(tracklet) v_α, v_δ, h = vra(tracklet), vdec(tracklet), mag(tracklet) + H_max, a_max = params.H_max, params.a_max # Topocentric unit vector and partials ρ, ρ_α, ρ_δ = topounitpdv(α, δ) # Time of observation [days since J2000] @@ -66,7 +72,7 @@ function AdmissibleRegion(tracklet::Tracklet{T}, params::NEOParameters{T}) where # Admissible region coefficients coeffs = admsreg_coeffs(α, δ, v_α, v_δ, ρ, ρ_α, ρ_δ, q) # Maximum range (heliocentric constraint) - ρ_max = max_range(coeffs) + ρ_max = max_range(coeffs, a_max) iszero(ρ_max) && return zero(AdmissibleRegion{T}) # Minimum range if isnan(h) @@ -79,7 +85,7 @@ function AdmissibleRegion(tracklet::Tracklet{T}, params::NEOParameters{T}) where end else # Tiny object boundary - ρ_min = 10^((h - params.H_max)/5) + ρ_min = 10^((h - H_max)/5) end ρ_min > ρ_max && return zero(AdmissibleRegion{T}) # Range domain @@ -95,8 +101,9 @@ function AdmissibleRegion(tracklet::Tracklet{T}, params::NEOParameters{T}) where Fs[2, :] .= [ρ_min, v_ρ_max] Fs[3, :] .= [ρ_max, v_ρ_mid] - return AdmissibleRegion{T}(t_datetime, α, δ, v_α, v_δ, ρ, ρ_α, ρ_δ, q, - coeffs, ρ_domain, v_ρ_domain, Fs, obs) + return AdmissibleRegion{T}(t_datetime, α, δ, v_α, v_δ, H_max, a_max, + ρ, ρ_α, ρ_δ, q, coeffs, ρ_domain, v_ρ_domain, + Fs, obs) end @doc raw""" @@ -171,10 +178,11 @@ U function of an [`AdmissibleRegion`](@ref). !!! reference See second equation after (8.9) of https://doi.org/10.1017/CBO9781139175371. """ -function admsreg_U(coeffs::Vector{T}, ρ::S) where {T <: AbstractFloat, S <: Number} +function admsreg_U(coeffs::Vector{T}, a_max::T, ρ::S) where {T <: AbstractFloat, S <: Number} return coeffs[2]^2/4 - admsreg_W(coeffs, ρ) + 2*k_gauss^2/sqrt(admsreg_S(coeffs, ρ)) + - k_gauss^2/a_max end -admsreg_U(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} = admsreg_U(A.coeffs, ρ) +admsreg_U(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} = admsreg_U(A.coeffs, A.a_max, ρ) @doc raw""" admsreg_V(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} @@ -184,30 +192,31 @@ V function of an [`AdmissibleRegion`](@ref). !!! reference See first equation after (8.9) of https://doi.org/10.1017/CBO9781139175371. """ -function admsreg_V(coeffs::Vector{T}, ρ::S, v_ρ::S) where {T <: AbstractFloat, S <: Number} +function admsreg_V(coeffs::Vector{T}, a_max::T, ρ::S, v_ρ::S) where {T <: AbstractFloat, S <: Number} return v_ρ^2 + coeffs[2] * v_ρ + admsreg_W(coeffs, ρ) - 2*k_gauss^2/sqrt(admsreg_S(coeffs, ρ)) + + k_gauss^2/a_max end -admsreg_V(A::AdmissibleRegion{T}, ρ::S, v_ρ::S) where {T <: AbstractFloat, S <: Number} = admsreg_V(A.coeffs, ρ, v_ρ) +admsreg_V(A::AdmissibleRegion{T}, ρ::S, v_ρ::S) where {T <: AbstractFloat, S <: Number} = admsreg_V(A.coeffs, A.a_max, ρ, v_ρ) @doc raw""" range_rate(A::AdmissibleRegion{T}, ρ::S) where {T, S <: AbstractFloat} Return the two possible range rates in the boundary of `A` for a given range `ρ`. """ -function range_rate(coeffs::Vector{T}, ρ::S) where {T, S <: AbstractFloat} - return find_zeros(s -> admsreg_V(coeffs, ρ, s), -10.0, 10.0) +function range_rate(coeffs::Vector{T}, a_max::T, ρ::S) where {T, S <: AbstractFloat} + return find_zeros(s -> admsreg_V(coeffs, a_max, ρ, s), -10.0, 10.0) end -range_rate(A::AdmissibleRegion{T}, ρ::S) where {T, S <: AbstractFloat} = range_rate(A.coeffs, ρ) +range_rate(A::AdmissibleRegion{T}, ρ::S) where {T, S <: AbstractFloat} = range_rate(A.coeffs, A.a_max, ρ) @doc raw""" - max_range(coeffs::Vector{T}) where {T <: AbstractFloat} + max_range(coeffs::Vector{T}, a_max::T) where {T <: AbstractFloat} Return the maximum possible range in the boundary of an admissible region -with coefficients `coeffs`. +with coefficients `coeffs` and maximum semimajor axis `a_max`. """ -function max_range(coeffs::Vector{T}) where {T <: AbstractFloat} +function max_range(coeffs::Vector{T}, a_max::T) where {T <: AbstractFloat} # Initial guess - sol = find_zeros(s -> admsreg_U(coeffs, s), R_EA, 100.0) + sol = find_zeros(s -> admsreg_U(coeffs, a_max, s), R_EA, 100.0) iszero(length(sol)) && return zero(T) ρ_max = sol[1] # Make sure U(ρ) ≥ 0 and there is at least one range_rate solution @@ -276,7 +285,7 @@ function in(P::Vector{T}, A::AdmissibleRegion{T}) where {T <: AbstractFloat} if A.ρ_domain[1] <= P[1] <= A.ρ_domain[2] y_range = range_rate(A, P[1]) if length(y_range) == 1 - return P[2] == y_range + return P[2] == y_range[1] else return y_range[1] <= P[2] <= y_range[2] end @@ -311,10 +320,10 @@ function bary2topo(A::AdmissibleRegion{T}, q0::Vector{U}) where {T <: AbstractFl # Heliocentric state vector r = q0 - sseph(su, datetime2days(A.date)) # Topocentric range - ρ = norm((r - A.q)[1:3]) + ρ = euclid3D(r - A.q) # Topocentric range rate - v_ρ = dot(r[4:6], A.ρ_unit) - dot(A.q[4:6], A.ρ_unit) - ρ * A.v_α * dot(A.ρ_α, A.ρ_unit) - - ρ * A.v_δ * dot(A.ρ_δ, A.ρ_unit) + v_ρ = dot3D(r[4:6], A.ρ_unit) - dot3D(A.q[4:6], A.ρ_unit) - ρ * A.v_α * dot3D(A.ρ_α, A.ρ_unit) + - ρ * A.v_δ * dot3D(A.ρ_δ, A.ρ_unit) return ρ, v_ρ end @@ -405,7 +414,7 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T q = topo2bary(A, 10^(x + dq[1]), v_ρ + dq[2]) end # Propagation and residuals - _, _, res = propres(radec, jd0, q, params; dynamics) + _, _, res = propres(radec, jd0 - ρ/c_au_per_day, q, params; dynamics) iszero(length(res)) && break # Current Q Q = nms(res) diff --git a/src/propagation/parameters.jl b/src/propagation/parameters.jl index 436e485a..67504441 100644 --- a/src/propagation/parameters.jl +++ b/src/propagation/parameters.jl @@ -23,6 +23,7 @@ struct NEOParameters{T <: AbstractFloat} gaussQmax::T # Admissible Region parameters H_max::T + a_max::T maxiter::Int tsaQmax::T # Outlier rejection parameters @@ -66,7 +67,8 @@ Parameters for all orbit determination functions. # Admissible Region Parameters -- `H_max::T`: maximum absolute magnitude (default: `32.0`). +- `H_max::T`: maximum absolute magnitude (default: `34.5`). +- `a_max::T`: maximum semimajor axis (default: `100.0`). - `maxiter::Int`: maximum number of iterations for admissible region `ADAM` optimizer (default: `100`). - `tsaQmax::T`: nrms threshold (default: `1.5`). @@ -74,11 +76,13 @@ Parameters for all orbit determination functions. - `max_per::T`: maximum allowed rejection percentage (default: `18.0`). """ -function NEOParameters(; maxsteps::Int = 500, μ_ast::Vector{T} = μ_ast343_DE430[1:end], - order::Int = 25, abstol::T = 1e-20, parse_eqs::Bool = true, bwdoffset::T = 0.5, - fwdoffset::T = 0.5, coeffstol::T = 10.0, debias_table::String = "2018", - niter::Int = 5, max_triplets::Int = 10, varorder::Int = 5, gaussQmax::T = 5.0, - H_max::T = 32.0, maxiter::Int = 100, tsaQmax::T = 1.5, max_per::T = 18.0) where {T <: AbstractFloat} +function NEOParameters(; + maxsteps::Int = 500, μ_ast::Vector{T} = μ_ast343_DE430[1:end], order::Int = 25, + abstol::T = 1e-20, parse_eqs::Bool = true, bwdoffset::T = 0.5, fwdoffset::T = 0.5, + coeffstol::T = 10.0, debias_table::String = "2018", niter::Int = 5, + max_triplets::Int = 10, varorder::Int = 5, gaussQmax::T = 5.0, H_max::T = 34.5, + a_max::T = 100.0, maxiter::Int = 100, tsaQmax::T = 1.5, max_per::T = 18.0 + ) where {T <: AbstractFloat} # Unfold debiasing matrix mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) # Sun (Earth) ephemeris @@ -87,10 +91,12 @@ function NEOParameters(; maxsteps::Int = 500, μ_ast::Vector{T} = μ_ast343_DE43 _ea = selecteph(sseph, ea) eph_ea = TaylorInterpolant(_ea.t0, _ea.t, collect(_ea.x)) # Assemble NEOParameters - return NEOParameters{T}(maxsteps, μ_ast, order, abstol, parse_eqs, bwdoffset, - fwdoffset, coeffstol, mpc_catalogue_codes_201X, truth, - resol, bias_matrix, eph_su, eph_ea, niter, max_triplets, - varorder, gaussQmax, H_max, maxiter, tsaQmax, max_per) + return NEOParameters{T}( + maxsteps, μ_ast, order, abstol, parse_eqs, bwdoffset, fwdoffset, + coeffstol, mpc_catalogue_codes_201X, truth, resol, bias_matrix, + eph_su, eph_ea, niter, max_triplets, varorder, gaussQmax, H_max, + a_max, maxiter, tsaQmax, max_per + ) end function NEOParameters(params::NEOParameters{T}; kwargs...) where {T <: AbstractFloat} From d97c7b5b65c9c8532e20a7a2754cd88b6f64d32c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 24 Feb 2024 10:30:56 -0600 Subject: [PATCH 141/173] Minor fix --- src/orbit_determination/tooshortarc.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 99aba33e..896baeba 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -221,7 +221,7 @@ function max_range(coeffs::Vector{T}, a_max::T) where {T <: AbstractFloat} ρ_max = sol[1] # Make sure U(ρ) ≥ 0 and there is at least one range_rate solution niter = 0 - while admsreg_U(coeffs, ρ_max) < 0 || length(range_rate(coeffs, ρ_max)) == 0 + while admsreg_U(coeffs, a_max, ρ_max) < 0 || length(range_rate(coeffs, ρ_max)) == 0 niter += 1 ρ_max = prevfloat(ρ_max) niter > 1_000 && break From 1db313f7bc3b5e6382d92e42ea22c93d3b97039d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 24 Feb 2024 10:36:47 -0600 Subject: [PATCH 142/173] Another minor fix --- src/orbit_determination/tooshortarc.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 896baeba..118716f1 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -221,7 +221,7 @@ function max_range(coeffs::Vector{T}, a_max::T) where {T <: AbstractFloat} ρ_max = sol[1] # Make sure U(ρ) ≥ 0 and there is at least one range_rate solution niter = 0 - while admsreg_U(coeffs, a_max, ρ_max) < 0 || length(range_rate(coeffs, ρ_max)) == 0 + while admsreg_U(coeffs, a_max, ρ_max) < 0 || length(range_rate(coeffs, a_max, ρ_max)) == 0 niter += 1 ρ_max = prevfloat(ρ_max) niter > 1_000 && break From aebe00f4c43130f6629b4c7c990283cccfd915bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 24 Feb 2024 10:43:00 -0600 Subject: [PATCH 143/173] Yet more minor fixes --- src/orbit_determination/tooshortarc.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 118716f1..737cc987 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -91,10 +91,10 @@ function AdmissibleRegion(tracklet::Tracklet{T}, params::NEOParameters{T}) where # Range domain ρ_domain = [ρ_min, ρ_max] # Range rate domain - v_ρ_min, v_ρ_max = range_rate(coeffs, ρ_min)[1:2] + v_ρ_min, v_ρ_max = range_rate(coeffs, a_max, ρ_min)[1:2] v_ρ_domain = [v_ρ_min, v_ρ_max] # Range rate symmetry level - v_ρ_mid = range_rate(coeffs, ρ_max)[1] + v_ρ_mid = range_rate(coeffs, a_max, ρ_max)[1] # Boundary points Fs = Matrix{T}(undef, 3, 2) Fs[1, :] .= [ρ_min, v_ρ_min] From ac69f0e19af235ca00ce02eff2df035414e18787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 24 Feb 2024 17:25:47 -0600 Subject: [PATCH 144/173] Levenberg-Marquardt --- src/orbit_determination/least_squares.jl | 174 +++++++++++++++++++---- src/orbit_determination/tooshortarc.jl | 134 +++++++++++------ 2 files changed, 237 insertions(+), 71 deletions(-) diff --git a/src/orbit_determination/least_squares.jl b/src/orbit_determination/least_squares.jl index bc4cae11..49a63ea6 100755 --- a/src/orbit_determination/least_squares.jl +++ b/src/orbit_determination/least_squares.jl @@ -26,6 +26,11 @@ function LeastSquaresFit(success::Bool, x::Vector{T}, Γ::Matrix{T}, return LeastSquaresFit{T}(success, x, Γ, routine) end +# Definition of zero LeastSquaresFit{T} +function zero(::Type{LeastSquaresFit{T}}) where {T <: Real} + return LeastSquaresFit{T}(false, Vector{T}(undef, 0), Matrix{T}(undef, 0, 0), :zero) +end + # Print method for LeastSquaresFit # Examples: # Succesful Newton @@ -35,9 +40,11 @@ function show(io::IO, fit::LeastSquaresFit{T}) where {T <: Real} if fit.routine == :newton routine_s = "Newton" elseif fit.routine == :diffcorr - routine_s = "Differential corrections" - elseif fit.routine == :levmar + routine_s = "Differential Corrections" + elseif fit.routine == :lm routine_s = "Levenberg-Marquardt" + else + routine_s = "Least Squares" end print(io, success_s, " ", routine_s) end @@ -445,7 +452,7 @@ See also [`chi2`](@ref). See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. """ function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, - niters::Int = 5) where {T <: Real} + niters::Int = 5, idxs::AbstractVector{Int} = eachindex(x0)) where {T <: Real} # Number of observations nobs = length(res) # Degrees of freedom @@ -453,7 +460,7 @@ function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, # Mean square residual Q = chi2(res, w)/nobs # Vector of x - x = Matrix{T}(undef, npar, niters + 1) + x = zeros(T, npar, niters + 1) # First guess x[:, 1] = x0 # Vector of errors @@ -465,13 +472,13 @@ function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, # Current x xi = x[:, i] # Gradient of Q with respect to x - dQ = TaylorSeries.gradient(Q)(xi) + dQ = TaylorSeries.gradient(Q)(xi)[idxs] # Hessian of Q with respect to x - d2Q = TaylorSeries.hessian(Q, xi) + d2Q = TaylorSeries.hessian(Q, xi)[idxs, idxs] # Newton update rule Δx = - inv(d2Q)*dQ # New x - x[:, i+1] = xi + Δx + x[idxs, i+1] = xi[idxs] + Δx # Normal matrix C = d2Q/(2/nobs) # C = d2Q/(2/m) # Error @@ -494,7 +501,7 @@ function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, # Normal matrix C = TaylorSeries.hessian(Q, x_new)/(2/nobs) # C = d2Q/(2/m) # Covariance matrix - Γ = inv(C) + Γ = inv(C[idxs, idxs]) if any(diag(Γ) .< 0) return LeastSquaresFit(false, x_new, Γ, :newton) @@ -504,11 +511,126 @@ function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, end function newtonls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, - niters::Int = 5) where {T <: Real} + niters::Int = 5, idxs::AbstractVector{Int} = eachindex(x0)) where {T <: Real} # Unfold residuals and weights _res_, _w_ = unfold(res) - return newtonls(_res_, _w_, x0, niters) + return newtonls(_res_, _w_, x0, niters, idxs) +end + +# In-place Levenberg-Marquardt hessian +function lmhessian!(_d2Q_::AbstractMatrix{T}, d2Q::AbstractMatrix{T}, λ::T) where {T <: AbstractFloat} + k = 1 + λ + for j in axes(d2Q, 2) + for i in axes(d2Q, 1) + if i == j + _d2Q_[i, j] = k * d2Q[i, j] + else + _d2Q_[i, j] = d2Q[i, j] + end + end + end + return nothing +end + +@doc raw""" + levenbergmarquardt(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, + niters::Int = 500) where {T <: Real} + levenbergmarquardt(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, + niters::Int = 500) where {T <: Real} + +Levenberg-Marquardt method subroutine for least-squares fitting. Returns an `LeastSquaresFit` +with the best iteration of `niters` iterations. + +See also [`chi2`](@ref). + +# Arguments + +- `res::Vector{TaylorN{T}/Vector{OpticalResidual{T, TaylorN{T}}}`: vector of residuals. +- `w::Vector{T}`: vector of weights. +- `x_0::Vector{T}`: first guess. +- `niters::Int`: number of iterations. + +!!! reference + See section 15.5.2 of https://books.google.com.mx/books?id=1aAOdzK3FegC&lpg=PP1&pg=PP1#v=onepage&q&f=false. +""" +function levenbergmarquardt(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, + niters::Int = 500, idxs::AbstractVector{Int} = eachindex(x0), + λ::T = 0.001) where {T <: Real} + # Number of observations + nobs = length(res) + # Degrees of freedom + npar = length(x0) + # Normalized mean square residual + Q = chi2(res, w)/nobs + # Vector of Qs + Qs = fill(T(Inf), niters + 1) + # Gradient of Q with respect to x + dQ = TaylorSeries.gradient(Q) + # Pre-allocate memory + _dQ_ = zeros(T, npar) + _d2Q_ = zeros(T, npar, npar) + x = zeros(T, npar, niters + 1) + # First guess + x[:, 1] = x0 + # Iteration + for i in 1:niters + # Current x + xi = x[:, i] + # Current Q + Qs[i] = Q(xi) + # Convergence condition + i > 1 && abs(Qs[i] - Qs[i-1]) / Qs[i-1] < 0.001 && break + # Gradient of Q with respect to x + _dQ_ .= dQ(xi) + # Hessian of Q with respect to x + d2Q = TaylorSeries.hessian(Q, xi) + # Choose λ + for _ in 1:niters + # Modified Hessian + lmhessian!(_d2Q_, d2Q, λ) + # Levenberg-Marquardt step + Δx = - inv(_d2Q_[idxs, idxs]) * _dQ_[idxs] + + if 0 < Q(xi[idxs] + Δx) < Qs[i] && isposdef(_d2Q_[idxs, idxs]) + λ /= 10 + x[idxs, i+1] = xi[idxs] + Δx + break + else + λ *= 10 + end + end + end + # Index with the lowest error + i = argmin(Qs) + # x with the lowest error + x_new = x[:, i] + # Hessian of Q with respect to x + d2Q = TaylorSeries.hessian(Q, x_new) + # Normal matrix + if isposdef(d2Q) + C = d2Q/(2/nobs) + else + lmhessian!(_d2Q_, d2Q, λ) + C = _d2Q_/(2/nobs) # C = d2Q/(2/m) + end + # Covariance matrix + Γ = inv(C[idxs, idxs]) + + if any(diag(Γ) .< 0) + return LeastSquaresFit(false, x_new, Γ, :lm) + else + return LeastSquaresFit(true, x_new, Γ, :lm) + end +end + +function levenbergmarquardt(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, + niters::Int = 500, idxs::AbstractVector{Int} = eachindex(x0), + λ::T = 0.001) where {T <: Real} + # Unfold residuals and weights + _res_, _w_ = unfold(res) + + return levenbergmarquardt(_res_, _w_, x0, niters, idxs, λ) end @doc raw""" @@ -525,27 +647,23 @@ Return the best least squares fit between two routines: [`newtonls`](@ref) and - `niters::Int`: number of iterations. """ function tryls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, - niters::Int = 5) where {T <: Real} - # Newton's method - fit_1 = newtonls(res, x0, niters) - # Differential corrections - fit_2 = diffcorr(res, x0, niters) - if fit_1.success && fit_2.success - Q_1 = nrms(res, fit_1) - Q_2 = nrms(res, fit_2) - if Q_1 <= Q_2 - return fit_1 - else - return fit_2 + niters::Int = 5, idxs::AbstractVector{Int} = eachindex(x0), + order::Vector{Symbol} = [:newton, :lm, :diffcorr]) where {T <: Real} + # Allocate memory + fit = zero(LeastSquaresFit{T}) + # Least squares methods in order + for i in eachindex(order) + if order[i] == :newton + fit = newtonls(res, x0, niters, idxs) + elseif order[i] == :lm + fit = levenbergmarquardt(res, x0, niters, idxs) + elseif order[i] == :diffcorr + fit = diffcorr(res, x0, niters, idxs) end - elseif fit_1.success - return fit_1 - elseif fit_2.success - return fit_2 - else - return fit_1 + fit.success && break end + return fit end # TO DO: update / deprecate the following three functions diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 737cc987..8a32b64d 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -328,6 +328,25 @@ function bary2topo(A::AdmissibleRegion{T}, q0::Vector{U}) where {T <: AbstractFl return ρ, v_ρ end +@doc raw""" + attr2bary(A::AdmissibleRegion{T}, a::Vector{U}) where {T <: AbstractFloat, U <: Number} + +Convert attributable elements `a` to to barycentric cartesian coordinates. +`A` fixes the observer. +""" +function attr2bary(A::AdmissibleRegion{T}, a::Vector{U}) where {T <: AbstractFloat, U <: Number} + # Unfold + α, δ, v_α, v_δ, ρ, v_ρ = a + ρ_unit, ρ_α, ρ_δ = topounitpdv(α, δ) + # Barycentric position + r = A.q[1:3] + ρ * ρ_unit + sseph(su, datetime2days(A.date))[1:3] + # Barycentric velocity + v = A.q[4:6] + v_ρ * ρ_unit + ρ * v_α * ρ_α + ρ * v_δ * ρ_δ + + sseph(su, datetime2days(A.date))[4:6] + # Barycentric state vector + return vcat(r, v) +end + # Propagate an orbit and compute residuals function propres(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{U}, params::NEOParameters{T}; dynamics::D=newtonian!) where {D, T <: AbstractFloat, U <: Number} @@ -373,21 +392,20 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T dynamics::D = newtonian!) where {T <: AbstractFloat, D} # Initial time of integration [julian days] jd0 = datetime2julian(A.date) + # Nominal Line-Of-Sight + LOS = [A.α, A.δ, A.v_α, A.v_δ] # Scaling factors + scalings = Vector{T}(undef, 6) + scalings[1:4] .= LOS ./ 1e6 if scale == :linear - scalings = [ - A.ρ_domain[2] - A.ρ_domain[1], - A.v_ρ_domain[2] - A.v_ρ_domain[1] - ] / 1_000 + scalings[5] = (A.ρ_domain[2] - A.ρ_domain[1]) / 1_000 elseif scale == :log x = log10(ρ) - scalings = [ - log10(A.ρ_domain[2]) - log10(A.ρ_domain[1]), - A.v_ρ_domain[2] - A.v_ρ_domain[1] - ] / 1_000 + scalings[5] = (log10(A.ρ_domain[2]) - log10(A.ρ_domain[1])) / 1_000 end + scalings[6] = (A.v_ρ_domain[2] - A.v_ρ_domain[1]) / 1_000 # Jet transport variables - dq = scaled_variables("dx dy", scalings, order = 1) + dq = scaled_variables("dx", scalings, order = 2) # Maximum number of iterations maxiter = params.maxiter # Allocate memory @@ -395,7 +413,8 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T v_ρs = Vector{T}(undef, maxiter+1) Qs = fill(T(Inf), maxiter+1) # Origin - x0 = zeros(T, 2) + x0 = zeros(T, 6) + x1 = zeros(T, 6) # First momentum m = zeros(T, 2) _m_ = zeros(T, 2) @@ -407,12 +426,24 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T # Current position in admissible region ρs[t] = ρ v_ρs[t] = v_ρ - # Current barycentric state vector + # Attributable elements + a = vcat(LOS + dq[1:4], ρ, v_ρ) + # Barycentric state vector + q = attr2bary(A, a) + # Propagation and residuals + _, _, res = propres(radec, jd0 - ρ/c_au_per_day, q, params; dynamics) + # Least squares fit + fit = tryls(res, x0, 5, 1:4) + # Minimized attributable elements + a0 = a(fit.x) + # Attributable elements if scale == :linear - q = topo2bary(A, ρ + dq[1], v_ρ + dq[2]) + a = vcat(a0[1:4], ρ + dq[5], v_ρ + dq[6]) elseif scale == :log - q = topo2bary(A, 10^(x + dq[1]), v_ρ + dq[2]) + a = vcat(a0[1:4], 10^(x + dq[5]), v_ρ + dq[6]) end + # Barycentric state vector + q = attr2bary(A, a) # Propagation and residuals _, _, res = propres(radec, jd0 - ρ/c_au_per_day, q, params; dynamics) iszero(length(res)) && break @@ -422,7 +453,7 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T # Convergence condition t > 1 && abs(Qs[t] - Qs[t-1]) / Qs[t] < Qtol && break # Gradient of objective function - g_t = TaylorSeries.gradient(Q)(x0) + g_t = TaylorSeries.gradient(Q)(x0)[5:6] # First momentum m .= μ * m + (1 - μ) * g_t _m_ .= m / (1 - μ^t) @@ -430,7 +461,7 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T n .= ν * n + (1 - ν) * g_t .^ 2 _n_ .= n / (1 - ν^t) # Step - x1 = x0 - η * _m_ ./ (sqrt.(_n_) .+ ϵ) + x1[5:6] = x0[5:6] - η * _m_ ./ (sqrt.(_n_) .+ ϵ) # Update values ρ, v_ρ = bary2topo(A, q(x1)) # Projection @@ -580,6 +611,27 @@ function tsatrackletorder(x::Tracklet{T}, y::Tracklet{T}) where {T <: AbstractFl end end +# Point in admissible region -> NEOSolution{T, T} +function _tooshortarc(A::AdmissibleRegion{T}, radec::Vector{RadecMPC{T}}, + tracklets::Vector{Tracklet{T}}, i::Int, params::NEOParameters{T}; + dynamics::D = newtonian!, scale::Symbol = :log) where {T <: AbstractFloat, D} + # Center + if scale == :linear + ρ = sum(A.ρ_domain) / 2 + elseif scale == :log + ρ = 10^sum(log10.(A.ρ_domain)) / 2 + end + v_ρ = sum(A.v_ρ_domain) / 2 + # ADAM minimization over admissible region + ρ, v_ρ, Q = adam(radec, A, ρ, v_ρ, params; scale = :linear, dynamics = dynamics) + if isinf(Q) + return zero(NEOSolution{T, T}) + else + # 6 variables least squares + return tsals(A, radec, tracklets, i, ρ, v_ρ, params; maxiter = 5, dynamics) + end +end + @doc raw""" tooshortarc(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, params::NEOParameters{T}; dynamics::D = newtonian!) where {T <: AbstractFloat, D} @@ -610,35 +662,31 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, # Admissible region A = AdmissibleRegion(tracklets[i], params) iszero(A) && continue - # Center - ρ = sum(A.ρ_domain) / 2 - v_ρ = sum(A.v_ρ_domain) / 2 - # ADAM minimization over admissible region - ρ, v_ρ, Q = adam(radec, A, ρ, v_ρ, params; scale = :linear, dynamics = dynamics) - if !isinf(Q) - # 6 variables least squares - sol = tsals(A, radec, tracklets, i, ρ, v_ρ, params; maxiter = 5, dynamics) - # Update best solution - if nrms(sol) < nrms(best_sol) - best_sol = sol - # Break condition - nrms(sol) < params.tsaQmax && break - end + # See Table 1 of https://doi.org/10.1051/0004-6361/201732104 + if A.ρ_domain[2] < sqrt(10) + sol1 = _tooshortarc(A, radec, tracklets, i, params; + dynamics = dynamics, scale = :log) + # Break condition + nrms(sol1) < params.tsaQmax && break + sol2 = _tooshortarc(A, radec, tracklets, i, params; + dynamics = dynamics, scale = :linear) + # Break condition + nrms(sol2) < params.tsaQmax && break + else + sol1 = _tooshortarc(A, radec, tracklets, i, params; + dynamics = dynamics, scale = :linear) + # Break condition + nrms(sol1) < params.tsaQmax && break + sol2 = _tooshortarc(A, radec, tracklets, i, params; + dynamics = dynamics, scale = :log) + # Break condition + nrms(sol2) < params.tsaQmax && break end - # Left boundary - ρ = A.ρ_domain[1] - v_ρ = sum(A.v_ρ_domain) / 2 - # ADAM minimization over admissible region - ρ, v_ρ, Q = adam(radec, A, ρ, v_ρ, params; scale = :log, dynamics = dynamics) - if !isinf(Q) - # 6 variables least squares - sol = tsals(A, radec, tracklets, i, ρ, v_ρ, params; maxiter = 5, dynamics) - # Update best solution - if nrms(sol) < nrms(best_sol) - best_sol = sol - # Break condition - nrms(sol) < params.tsaQmax && break - end + # Update best solution + if nrms(sol1) < nrms(best_sol) + best_sol = sol1 + elseif nrms(sol2) < nrms(best_sol) + best_sol = sol2 end end From b07d4f35df9d931381e1cb438197c41df4ec5443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 24 Feb 2024 18:04:32 -0600 Subject: [PATCH 145/173] Update OD tests --- src/NEOs.jl | 2 +- src/orbit_determination/least_squares.jl | 3 +- src/orbit_determination/tooshortarc.jl | 23 +++++----- test/orbit_determination.jl | 56 +++++++++++------------- 4 files changed, 40 insertions(+), 44 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index c7ff65e0..359696a5 100755 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -62,7 +62,7 @@ export NEOParameters, propagate, propagate_lyap, propagate_root # B plane export valsecchi_circle, bopik # Least squares -export project, chi2, nms, nrms, diffcorr, newtonls, tryls, sigmas +export project, chi2, nms, nrms, diffcorr, newtonls, levenbergmarquardt, tryls, sigmas # Osculating export pv2kep, yarkp2adot # Too Short Arc diff --git a/src/orbit_determination/least_squares.jl b/src/orbit_determination/least_squares.jl index 49a63ea6..93cb0659 100755 --- a/src/orbit_determination/least_squares.jl +++ b/src/orbit_determination/least_squares.jl @@ -358,6 +358,7 @@ See also [`BHC`](@ref). """ function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, niters::Int = 5) where {T <: Real} + # TO DO: Adapt diffcorr for idxs # Degrees of freedom npar = length(x0) # Design matrix B, H array and normal matrix C @@ -648,7 +649,7 @@ Return the best least squares fit between two routines: [`newtonls`](@ref) and """ function tryls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, niters::Int = 5, idxs::AbstractVector{Int} = eachindex(x0), - order::Vector{Symbol} = [:newton, :lm, :diffcorr]) where {T <: Real} + order::Vector{Symbol} = [:newton, :lm]) where {T <: Real} # Allocate memory fit = zero(LeastSquaresFit{T}) # Least squares methods in order diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 8a32b64d..d7b3ee78 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -432,6 +432,7 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T q = attr2bary(A, a) # Propagation and residuals _, _, res = propres(radec, jd0 - ρ/c_au_per_day, q, params; dynamics) + iszero(length(res)) && break # Least squares fit fit = tryls(res, x0, 5, 1:4) # Minimized attributable elements @@ -614,16 +615,16 @@ end # Point in admissible region -> NEOSolution{T, T} function _tooshortarc(A::AdmissibleRegion{T}, radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, i::Int, params::NEOParameters{T}; - dynamics::D = newtonian!, scale::Symbol = :log) where {T <: AbstractFloat, D} + scale::Symbol = :log, dynamics::D = newtonian!) where {T <: AbstractFloat, D} # Center if scale == :linear ρ = sum(A.ρ_domain) / 2 elseif scale == :log - ρ = 10^sum(log10.(A.ρ_domain)) / 2 + ρ = A.ρ_domain[1] end v_ρ = sum(A.v_ρ_domain) / 2 # ADAM minimization over admissible region - ρ, v_ρ, Q = adam(radec, A, ρ, v_ρ, params; scale = :linear, dynamics = dynamics) + ρ, v_ρ, Q = adam(radec, A, ρ, v_ρ, params; scale, dynamics) if isinf(Q) return zero(NEOSolution{T, T}) else @@ -665,22 +666,22 @@ function tooshortarc(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, # See Table 1 of https://doi.org/10.1051/0004-6361/201732104 if A.ρ_domain[2] < sqrt(10) sol1 = _tooshortarc(A, radec, tracklets, i, params; - dynamics = dynamics, scale = :log) + scale = :log, dynamics) # Break condition - nrms(sol1) < params.tsaQmax && break + nrms(sol1) < params.tsaQmax && return sol1 sol2 = _tooshortarc(A, radec, tracklets, i, params; - dynamics = dynamics, scale = :linear) + scale = :linear, dynamics) # Break condition - nrms(sol2) < params.tsaQmax && break + nrms(sol2) < params.tsaQmax && return sol2 else sol1 = _tooshortarc(A, radec, tracklets, i, params; - dynamics = dynamics, scale = :linear) + scale = :linear, dynamics) # Break condition - nrms(sol1) < params.tsaQmax && break + nrms(sol1) < params.tsaQmax && return sol1 sol2 = _tooshortarc(A, radec, tracklets, i, params; - dynamics = dynamics, scale = :log) + scale = :log, dynamics) # Break condition - nrms(sol2) < params.tsaQmax && break + nrms(sol2) < params.tsaQmax && return sol2 end # Update best solution if nrms(sol1) < nrms(best_sol) diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index 9502f37f..8633424b 100755 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -13,13 +13,12 @@ using NEOs: NEOSolution, numberofdays # Load observations radec = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) # Parameters - params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, - bwdoffset = 0.007, fwdoffset = 0.007) + params = NEOParameters(bwdoffset = 0.007, fwdoffset = 0.007) # Orbit Determination sol = orbitdetermination(radec, params) - # Values by February 4, 2024 + # Values by February 24, 2024 # Vector of observations @test length(radec) == 123 @@ -49,9 +48,9 @@ using NEOs: NEOSolution, numberofdays # Scalig factors @test all(sol.scalings .== 1e-6) # Compatibility with JPL - JPL = [-1.100331943890894E+00, 2.077277940539948E-01, 4.202679172087372E-02, - -4.735673360137306E-03, -1.062665933519790E-02, -6.016253165957075E-03] - @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 27) + JPL = [-1.1003339484439327, 0.20772201506095814, 0.04202338912370205, + -0.004735538686138557, -0.010626685053348663, -0.006016258344003866] + @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 6) end @testset "Too Short Arc" begin @@ -59,13 +58,12 @@ using NEOs: NEOSolution, numberofdays radec = fetch_radec_mpc("designation" => "2008 EK68") # Parameters - params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, - bwdoffset = 0.007, fwdoffset = 0.007) + params = NEOParameters(bwdoffset = 0.007, fwdoffset = 0.007) # Orbit Determination sol = orbitdetermination(radec, params) - # Values by February 4, 2024 + # Values by February 24, 2024 # Vector of observations @test length(radec) == 10 @@ -95,9 +93,9 @@ using NEOs: NEOSolution, numberofdays # Scalig factors @test all(sol.scalings .< 1e-5) # Compatibility with JPL - JPL = [-9.698293924982635E-01, 2.403718659163320E-01, 1.028928812918412E-01, - -9.512665381191419E-03, -1.532539714362475E-02, -8.094608965098163E-03] - @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 1) + JPL = [-0.9698333701500199, 0.24036461256880043, 0.10288887522619743, + -0.009512521373861719, -0.015325432152904881, -0.008094623534198382] + @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 0.1) end @testset "Outlier Rejection" begin @@ -105,15 +103,14 @@ using NEOs: NEOSolution, numberofdays radec = fetch_radec_mpc("designation" => "2007 VV7") # Parameters - params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, - bwdoffset = 0.007, fwdoffset = 0.007) + params = NEOParameters(bwdoffset = 0.007, fwdoffset = 0.007) # Orbit Determination sol = orbitdetermination(radec, params) # Outlier rejection sol = outlier_rejection(radec, sol, params) - # Values by February 4, 2024 + # Values by February 24, 2024 # Vector of observations @test length(radec) == 21 @@ -143,9 +140,9 @@ using NEOs: NEOSolution, numberofdays # Scalig factors @test all(sol.scalings .< 8e-7) # Compatibility with JPL - JPL = [7.673391189462907E-01, 6.484845064680100E-01, 2.932307930882956E-01, - -1.102328578432002E-02, 1.539274577937339E-02, 6.528864069204219E-03] - @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 1) + JPL = [0.7673358221902306, 0.6484904294813807, 0.2932331617634889, + -0.011023358761553661, 0.015392684491034429, 0.006528836324700449] + @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 0.1) end @testset "Interesting NEOs" begin @@ -156,14 +153,12 @@ using NEOs: NEOSolution, numberofdays radec = fetch_radec_mpc("designation" => "2014 AA") # Parameters - params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, - coeffstol = Inf, bwdoffset = 0.007, fwdoffset = 0.007, - H_max = 34.0) + params = NEOParameters(coeffstol = Inf, bwdoffset = 0.007, fwdoffset = 0.007) # Orbit Determination sol = orbitdetermination(radec, params) - # Values by February 4, 2024 + # Values by February 24, 2024 # Vector of observations @test length(radec) == 7 @@ -193,9 +188,9 @@ using NEOs: NEOSolution, numberofdays # Scalig factors @test all(sol.scalings .< 1e-5) # Compatibility with JPL - JPL = [-1.793234664811157E-01, 8.874182631964184E-01, 3.841456198855505E-01, - -1.755789723380711E-02, -5.781199629059458E-03, -2.007345498817972E-03] - @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 1) + JPL = [-0.17932853771087842, 0.8874166708545763, 0.38414497114153867, + -0.01755788350351527, -0.005781328974619869, -0.0020073946363600814] + @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 0.3) # 2008 TC3 entered the Earth's atmosphere around October 7, 2008, 02:46 UTC @@ -203,15 +198,14 @@ using NEOs: NEOSolution, numberofdays radec = fetch_radec_mpc("designation" => "2008 TC3") # Parameters - params = NEOParameters(abstol = 1e-20, order = 25, parse_eqs = true, - coeffstol = Inf, bwdoffset = 0.007, fwdoffset = 0.007) + params = NEOParameters(coeffstol = Inf, bwdoffset = 0.007, fwdoffset = 0.007) # Observations with <1" weight idxs = findall(x -> x < 1, w8sveres17.(radec)) # Restricted Orbit Determination sol = orbitdetermination(radec[idxs], params) - # Values by February 4, 2024 + # Values by February 24, 2024 # Vector of observations @test length(radec) == 883 @@ -241,9 +235,9 @@ using NEOs: NEOSolution, numberofdays # Scalig factors @test all(sol.scalings .< 1e-5) # Compatibility with JPL - JPL = [9.741084137931751E-01, 2.151459813682736E-01, 9.390733559030655E-02, - -7.890343235423515E-03, 1.606273839327320E-02, 6.136052979678407E-03] - @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 9) + JPL = [0.9741070119227359, 0.21515061351517384, 0.09390897837680391, + -0.007890445009307178, 0.016062726197198392, 0.006136042043681892] + @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 0.3) end end \ No newline at end of file From 1b8ae10b7c14a3c5c6aae02cfceaa1880f184c9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 24 Feb 2024 18:38:47 -0600 Subject: [PATCH 146/173] Minor fix --- src/orbit_determination/least_squares.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/orbit_determination/least_squares.jl b/src/orbit_determination/least_squares.jl index 93cb0659..d862c4b2 100755 --- a/src/orbit_determination/least_squares.jl +++ b/src/orbit_determination/least_squares.jl @@ -592,8 +592,10 @@ function levenbergmarquardt(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T} lmhessian!(_d2Q_, d2Q, λ) # Levenberg-Marquardt step Δx = - inv(_d2Q_[idxs, idxs]) * _dQ_[idxs] - - if 0 < Q(xi[idxs] + Δx) < Qs[i] && isposdef(_d2Q_[idxs, idxs]) + # Update point + x[idxs, i+1] = xi[idxs] + Δx + # Choose λ + if 0 < Q(x[:, i+1]) < Qs[i] && isposdef(_d2Q_[idxs, idxs]) λ /= 10 x[idxs, i+1] = xi[idxs] + Δx break From e8bf9bb596236269685ab95f01e486a8ccf69003 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez?= Date: Sun, 25 Feb 2024 17:38:37 +0100 Subject: [PATCH 147/173] Some aesthetic fixes (#54) * Change end of line sequence * Add NEOParameters test * NEOParameters fix * Try mode change * More mode changes * More mode changes * Add remaining mode changes * Update least_squares.jl * Revert undesired changes --- .gitignore | 22 +- Project.toml | 0 pha/apophis.jl | 700 +- src/NEOs.jl | 166 +- src/constants.jl | 410 +- src/init.jl | 44 +- src/observations/catalogue_mpc.jl | 374 +- src/observations/jpl_eph.jl | 314 +- src/observations/observatory_mpc.jl | 586 +- src/observations/process_radar.jl | 1240 ++-- src/observations/process_radec.jl | 1202 ++-- src/observations/radar_jpl.jl | 698 +- src/observations/radec_mpc.jl | 898 +-- src/observations/topocentric.jl | 672 +- src/observations/tracklet.jl | 14 +- src/observations/units.jl | 360 +- src/orbit_determination/gauss_method.jl | 1094 ++-- src/orbit_determination/least_squares.jl | 1630 ++--- src/orbit_determination/neosolution.jl | 342 +- src/orbit_determination/osculating.jl | 372 +- src/postprocessing/b_plane.jl | 416 +- src/propagation/asteroid_dynamical_models.jl | 2554 ++++---- src/propagation/jetcoeffs.jl | 5984 +++++++++--------- src/propagation/parameters.jl | 2 +- src/propagation/propagation.jl | 0 test/observations.jl | 608 +- test/orbit_determination.jl | 485 +- test/propagation.jl | 808 +-- test/runtests.jl | 24 +- 29 files changed, 11010 insertions(+), 11009 deletions(-) mode change 100755 => 100644 .gitignore mode change 100755 => 100644 Project.toml mode change 100755 => 100644 pha/apophis.jl mode change 100755 => 100644 src/NEOs.jl mode change 100755 => 100644 src/constants.jl mode change 100755 => 100644 src/init.jl mode change 100755 => 100644 src/observations/catalogue_mpc.jl mode change 100755 => 100644 src/observations/jpl_eph.jl mode change 100755 => 100644 src/observations/observatory_mpc.jl mode change 100755 => 100644 src/observations/process_radar.jl mode change 100755 => 100644 src/observations/process_radec.jl mode change 100755 => 100644 src/observations/radar_jpl.jl mode change 100755 => 100644 src/observations/radec_mpc.jl mode change 100755 => 100644 src/observations/topocentric.jl mode change 100755 => 100644 src/observations/units.jl mode change 100755 => 100644 src/orbit_determination/gauss_method.jl mode change 100755 => 100644 src/orbit_determination/least_squares.jl mode change 100755 => 100644 src/orbit_determination/neosolution.jl mode change 100755 => 100644 src/orbit_determination/osculating.jl mode change 100755 => 100644 src/postprocessing/b_plane.jl mode change 100755 => 100644 src/propagation/asteroid_dynamical_models.jl mode change 100755 => 100644 src/propagation/jetcoeffs.jl mode change 100755 => 100644 src/propagation/propagation.jl mode change 100755 => 100644 test/observations.jl mode change 100755 => 100644 test/orbit_determination.jl mode change 100755 => 100644 test/propagation.jl mode change 100755 => 100644 test/runtests.jl diff --git a/.gitignore b/.gitignore old mode 100755 new mode 100644 index 1a18b9f6..de1ec3b5 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,11 @@ -*.jld -*.jld2 -*.bsp -*.out -*.err -notebooks/.ipynb_checkpoints -jldeph/ -notebooks/figs -EOP_IAU*.TXT -Manifest.toml -*.DS_Store +*.jld +*.jld2 +*.bsp +*.out +*.err +notebooks/.ipynb_checkpoints +jldeph/ +notebooks/figs +EOP_IAU*.TXT +Manifest.toml +*.DS_Store diff --git a/Project.toml b/Project.toml old mode 100755 new mode 100644 diff --git a/pha/apophis.jl b/pha/apophis.jl old mode 100755 new mode 100644 index d8b00694..71b8854c --- a/pha/apophis.jl +++ b/pha/apophis.jl @@ -1,351 +1,351 @@ -# This file is part of the NEOs.jl package; MIT licensed - -### This script can be run either as a standalone script or via ArgParse. In any case, -### this folder's Project.toml environment has to be already active and instantiated -### before running this script. Uncomment the following three lines to activate and -### instantiate this folder's environment: - -# import Pkg -# Pkg.activate(".") -# Pkg.instantiate() - -### If ran as a standalone and the environment defined in this folder's Project.toml is -### already active and instantiated, then this script can be run from this folder with the -### default settings simply as: -### $ julia -t --project=. apophis.jl -### Finally, this script can be run via the ArgParse mechanism. Help can be displayed doing: -### $ julia --project=. apophis.jl --help - -using ArgParse -using NEOs -using Dates -using TaylorIntegration -using JLD2 -using PlanetaryEphemeris -using DataFrames -using DelimitedFiles -using LinearAlgebra: diag -using Statistics -using StatsBase - -# Load JPL ephemeris -loadjpleph() - -function parse_commandline() - s = ArgParseSettings() - - # Program name (for usage & help screen) - s.prog = "apophis.jl" - # Desciption (for help screen) - s.description = "Propagates Apophis orbit via jet transport" - - @add_arg_table! s begin - "--jd0" - help = "Initial date" - arg_type = DateTime - default = DateTime(2020, 12, 17) - "--varorder" - help = "Order of the jet transport perturbation" - arg_type = Int - default = 5 - "--maxsteps" - help = "Maximum number of steps during integration" - arg_type = Int - default = 10_000 - "--nyears_bwd" - help = "Years in backward integration" - arg_type = Float64 - default = -17.0 - "--nyears_fwd" - help = "Years in forward integration" - arg_type = Float64 - default = 9.0 - "--order" - help = "Order of Taylor polynomials expansions during integration" - arg_type = Int - default = 25 - "--abstol" - help = "Absolute tolerance" - arg_type = Float64 - default = 1.0E-20 - "--parse_eqs" - help = "Whether to use the taylorized method of jetcoeffs or not" - arg_type = Bool - default = true - end - - s.epilog = """ - Examples (run from the `pha` folder):\n - \n - # Multi-threaded\n - julia -t 4 --project=. apophis.jl --maxsteps 100 --nyears_bwd -0.02 --nyears_fwd 0.02 --parse_eqs true\n - \n - # Single-threaded\n - julia --project=. apophis.jl --maxsteps 100 --nyears_bwd -0.02 --nyears_fwd 0.02 --parse_eqs true\n - \n - """ - - return parse_args(s) -end - -function print_header(header::String, level::Int = 1) - L = length(header) - if level == 1 - c = "=" - else - c = "-" - end - println(repeat(c, L)) - println(header) - println(repeat(c, L)) -end - -function main(dynamics::D, maxsteps::Int, jd0_datetime::DateTime, nyears_bwd::T, nyears_fwd::T, order::Int, varorder::Int, - abstol::T, parse_eqs::Bool) where {T <: Real, D} - - # Initial conditions from Apophis JPL solution #197 - q00 = kmsec2auday(apophisposvel197(datetime2et(jd0_datetime))) - - # Perturbation to nominal initial condition (Taylor1 jet transport) - # vcat(fill(1e-8, 6), 1e-14, 1e-15) are the scaling factors for jet transport perturbation, - # these are needed to ensure expansion coefficients remain small. - # The magnitudes correspond to the typical order of magnitude of errors in - # position/velocity (1e-8), Yarkovsky (1e-14) and radiation pressure (1e-15) - scalings = vcat(fill(1e-8, 6), 1e-14, 1e-15) - if varorder == 0 - dq = zeros(8) - else - dq = NEOs.scaled_variables("δx", scalings, order = varorder) - end - - q0 = vcat(q00, 0.0, 0.0) .+ dq - - # Initial date (in Julian days) - jd0 = datetime2julian(jd0_datetime) - - print_header("Integrator warmup", 2) - _ = NEOs.propagate(dynamics, 1, jd0, nyears_fwd, q0, Val(true); - order, abstol, parse_eqs) - _ = NEOs.propagate_root(dynamics, 1, jd0, nyears_fwd, q0, Val(true); - order, abstol, parse_eqs) - println() - - print_header("Main integration", 2) - tmax = nyears_bwd*yr - println("• Initial time of integration: ", string(jd0_datetime)) - println("• Final time of integration: ", julian2datetime(jd0 + tmax)) - - sol_bwd = NEOs.propagate(dynamics, maxsteps, jd0, nyears_bwd, q0, Val(true); - order, abstol, parse_eqs) - jldsave("Apophis_bwd.jld2"; sol_bwd) - # sol_bwd = JLD2.load("Apophis_bwd.jld2", "sol_bwd") - - tmax = nyears_fwd*yr - println("• Initial time of integration: ", string(jd0_datetime)) - println("• Final time of integration: ", julian2datetime(jd0 + tmax)) - - sol_fwd, tvS, xvS, gvS = NEOs.propagate_root(dynamics, maxsteps, jd0, nyears_fwd, q0, Val(true); - order, abstol, parse_eqs) - jldsave("Apophis_fwd.jld2"; sol_fwd, tvS, xvS, gvS) - # sol_fwd = JLD2.load("Apophis_fwd.jld2", "sol_bwd") - println() - - # load Solar System ephemeris - sseph::TaylorInterpolant{Float64,Float64,2} = loadpeeph(NEOs.sseph, sol_bwd.t0+sol_bwd.t[end], sol_fwd.t0+sol_fwd.t[end]) - eph_su::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, su) - eph_ea::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, ea) - - # NEO - # Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec - xva_bwd(et) = auday2kmsec(sol_bwd(et/daysec)[1:6]) - xva_fwd(et) = auday2kmsec(sol_fwd(et/daysec)[1:6]) - xva(et) = bwdfwdeph(et, sol_bwd, sol_fwd) - # Earth - # Change x, v units, resp., from au, au/day to km, km/sec - xve(et) = auday2kmsec(eph_ea(et/daysec)) - # Sun - # Change x, v units, resp., from au, au/day to km, km/sec - xvs(et) = auday2kmsec(eph_su(et/daysec)) - - - radec_2004_2020 = read_radec_mpc(joinpath(pkgdir(NEOs), "data", "99942_2004_2020.dat")) - radec_2020_2021 = read_radec_mpc(joinpath(pkgdir(NEOs), "data", "99942_2020_2021.dat")) - radec = vcat(radec_2004_2020,radec_2020_2021) - - deldop_2005_2013 = read_radar_jpl(joinpath(pkgdir(NEOs), "data", "99942_RADAR_2005_2013.dat")) - deldop_2021 = read_radar_jpl(joinpath(pkgdir(NEOs), "data", "99942_RADAR_2021.dat")) - deldop = vcat(deldop_2005_2013,deldop_2021) - - # Compute optical residuals - res_radec_all, w_radec_all = NEOs.residuals(radec; xvs, xve, xva) - jldsave("Apophis_res_w_radec.jld2"; res_radec_all, w_radec_all) - # JLD2.@load "Apophis_res_w_radec.jld2" - - # Compute radar residuals - res_del, w_del, res_dop, w_dop = NEOs.residuals(deldop; xvs, xve, xva, niter=10, tord=10) - jldsave("Apophis_res_w_deldop.jld2"; res_del, w_del, res_dop, w_dop) - # JLD2.@load "Apophis_res_w_deldop.jld2" - - ### Process optical astrometry (filter, weight, debias) - - # filter out biased observations from observatory 217 on 28-Jan-2021 - df_radec = DataFrame(radec) - # add residuals and weights to optical astrometry DataFrame - df_radec[!, :res_α] .= res_radec_all[1:round(Int,length(res_radec_all)/2)] - df_radec[!, :res_δ] .= res_radec_all[1+round(Int,length(res_radec_all)/2):end] - df_radec[!, :w_α] .= w_radec_all[1:round(Int,length(res_radec_all)/2)] - df_radec[!, :w_δ] .= w_radec_all[1+round(Int,length(res_radec_all)/2):end] - filter!( - x->(Date(x.date) != Date(2021, 1, 28)), - df_radec - ) - - # read astrometric errors from Tholen et al. (2013) - tho13_errors = readdlm(joinpath(pkgdir(NEOs), "data", "tholenetal2013_opterror.dat"), ',') - # compute weights - w_α_tho13 = 1 ./ (tho13_errors[:,1].^2 .+ tho13_errors[:,3].^2 .+ tho13_errors[:,5].^2) - w_δ_tho13 = 1 ./ (tho13_errors[:,2].^2 .+ tho13_errors[:,4].^2 .+ tho13_errors[:,6].^2) - # Tholen et al. (2013) obs table - radec_tho13 = DataFrame(read_radec_mpc(joinpath(pkgdir(NEOs), "test", "data", "99942_Tholen_etal_2013.dat"))) - # vector of RA values from Tholen et al. (2013) observations (used for filtering) - tho13_α = radec_tho13[!,:α] - # set weights in Tholen et al. (2013) astrometry corresponding to associated uncertainties - df_radec[in.(df_radec.α, Ref(tho13_α)),:w_α] = w_α_tho13 - df_radec[in.(df_radec.α, Ref(tho13_α)),:w_δ] = w_δ_tho13 - - # Relaxation factor (account for correlations in optical astrometry data) - # for each observation batch, count the number of observations made in - # the same night by the same observatory - # Ref: Veres et al. (2017) - date_site_v = select(df_radec, :date => ByRow(Date), :observatory) - Nv = [count(x->x.date_Date==i.date_Date && x.observatory==i.observatory, eachrow(date_site_v)) for i in eachrow(date_site_v)] - relax_factor = map(x->x>4.0 ? x/4.0 : 1.0, Nv) - # inflate uncertainties (i.e., relax weights) by relaxation factor - df_radec[!, :w_α] .= (df_radec.w_α)./relax_factor - df_radec[!, :w_δ] .= (df_radec.w_δ)./relax_factor - - # update optical residuals and weights - res_radec = vcat(df_radec.res_α, df_radec.res_δ) - w_radec = vcat(df_radec.w_α, df_radec.w_δ) - - ### Perform orbital fit to optical and radar astrometry data - - res = vcat(res_radec, res_del, res_dop) - w = vcat(w_radec, w_del, w_dop) - - fit_OR8 = newtonls(res, w, zeros(get_numvars()), 10) - x_OR8 = sol_fwd(sol_fwd.t0)(fit_OR8.x) - σ_OR8 = sqrt.(diag(fit_OR8.Γ)).*scalings - - nradec = length(res_radec) - res_ra = view(res_radec, 1:nradec÷2) - res_dec = view(res_radec, 1+nradec÷2:nradec) - w_ra = view(w_radec, 1:nradec÷2) - w_dec = view(w_radec, 1+nradec÷2:nradec) - - ### Print results - - print_header("Orbital fit (8-DOF) and post-fit statistics", 2) - - # orbital fit - println("Success flag : ", fit_OR8.success, "\n") - println("Nominal solution [au,au,au,au/d,au/d,au/d,au/d²,au/d²]: ", x_OR8, "\n") - println("1-sigma formal uncertainties [au,au,au,au/d,au/d,au/d,au/d²,au/d²]: ", σ_OR8, "\n") - - # post-fit statistics - println("Normalized RMS (optical-only) [adimensional] : ", nrms(res_radec(fit_OR8.x),w_radec)) - println("Normalized RMS (radar-only) [adimensional] : ", nrms(vcat(res_del,res_dop)(fit_OR8.x),vcat(w_del,w_dop))) - println("Normalized RMS (combined optical and radar) [adimensional] : ", nrms(res(fit_OR8.x),w), "\n") - println("Mean weighted right-ascension residual [arcseconds] : ", mean(res_ra(fit_OR8.x), weights(w_ra))) - println("Mean weighted declination residual [arcseconds] : ", mean(res_dec(fit_OR8.x), weights(w_dec))) - println("Mean weighted time-delay residual [micro-seconds]: ", mean(res_del(fit_OR8.x), weights(w_del))) - println("Mean weighted Doppler-shift residual [Hz] : ", mean(res_dop(fit_OR8.x), weights(w_dop)), "\n") - println("Chi-squared statistic (χ²): [adimensional] : ", chi2(res(fit_OR8.x),w)) - - return sol_bwd, sol_fwd, res_radec, res_del, res_dop, w_radec, w_del, w_dop -end - -function main() - - # Parse arguments from commandline - parsed_args = parse_commandline() - - print_header("Asteroid Apophis") - println() - print_header("General parameters", 2) - - # Number of threads - N_threads = Threads.nthreads() - println("• Number of threads: ", N_threads) - - # Dynamical function - dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! - - println("• Dynamical function: ", dynamics) - - # Maximum number of steps - maxsteps = parsed_args["maxsteps"] - println("• Maximum number of steps: ", maxsteps) - - # Initial date - jd0_datetime = parsed_args["jd0"] - - # Number of years in backward integration - nyears_bwd = parsed_args["nyears_bwd"] - - # Number of years in forward integration - nyears_fwd = parsed_args["nyears_fwd"] - - # Order of Taylor polynomials - order = parsed_args["order"] - println("• Order of Taylor polynomials: ", order) - - # Order of jet transport perturbation - varorder = parsed_args["varorder"] - println("• Order of jet transport perturbation: ", varorder) - - # Absolute tolerance - abstol = parsed_args["abstol"] - println("• Absolute tolerance: ", abstol) - - # Whether to use @taylorize or not - parse_eqs = parsed_args["parse_eqs"] - println("• Use @taylorize: ", parse_eqs, "\n") - - main(dynamics, maxsteps, jd0_datetime, nyears_bwd, nyears_fwd, order, varorder, abstol, parse_eqs) -end - -main() - -#= --0.18034827489412805 -0.9406910783153754 -0.3457360118643932 --0.016265940057745887 -4.3915296805381036e-5 --0.0003952032399008921 --2.883842658925719e-14 --1.6977850502837174e-11 - - -6.991681792970175e-9 -3.3210758500485412e-9 -8.763895947794195e-9 -5.485729074188412e-11 -9.846074910774499e-11 -1.3782767177665416e-10 -2.525644870489942e-16 -3.2193289354129716e-12 - -Normalized RMS (optical-only) [adimensional] : 0.4365429773707507 -Normalized RMS (radar-only) [adimensional] : 0.5421268387032326 -Normalized RMS (combined optical and radar) [adimensional] : 0.43685679642513925 - -Mean weighted right-ascension residual [arcseconds] : -0.002787272519210798 -Mean weighted declination residual [arcseconds] : -0.003376099885054764 -Mean weighted time-delay residual [micro-seconds]: -0.0007329351962194035 -Mean weighted Doppler-shift residual [Hz] : -0.03025601266756564 - -Chi-squared statistic (χ²): [adimensional] : 3597.4067719864497 - +# This file is part of the NEOs.jl package; MIT licensed + +### This script can be run either as a standalone script or via ArgParse. In any case, +### this folder's Project.toml environment has to be already active and instantiated +### before running this script. Uncomment the following three lines to activate and +### instantiate this folder's environment: + +# import Pkg +# Pkg.activate(".") +# Pkg.instantiate() + +### If ran as a standalone and the environment defined in this folder's Project.toml is +### already active and instantiated, then this script can be run from this folder with the +### default settings simply as: +### $ julia -t --project=. apophis.jl +### Finally, this script can be run via the ArgParse mechanism. Help can be displayed doing: +### $ julia --project=. apophis.jl --help + +using ArgParse +using NEOs +using Dates +using TaylorIntegration +using JLD2 +using PlanetaryEphemeris +using DataFrames +using DelimitedFiles +using LinearAlgebra: diag +using Statistics +using StatsBase + +# Load JPL ephemeris +loadjpleph() + +function parse_commandline() + s = ArgParseSettings() + + # Program name (for usage & help screen) + s.prog = "apophis.jl" + # Desciption (for help screen) + s.description = "Propagates Apophis orbit via jet transport" + + @add_arg_table! s begin + "--jd0" + help = "Initial date" + arg_type = DateTime + default = DateTime(2020, 12, 17) + "--varorder" + help = "Order of the jet transport perturbation" + arg_type = Int + default = 5 + "--maxsteps" + help = "Maximum number of steps during integration" + arg_type = Int + default = 10_000 + "--nyears_bwd" + help = "Years in backward integration" + arg_type = Float64 + default = -17.0 + "--nyears_fwd" + help = "Years in forward integration" + arg_type = Float64 + default = 9.0 + "--order" + help = "Order of Taylor polynomials expansions during integration" + arg_type = Int + default = 25 + "--abstol" + help = "Absolute tolerance" + arg_type = Float64 + default = 1.0E-20 + "--parse_eqs" + help = "Whether to use the taylorized method of jetcoeffs or not" + arg_type = Bool + default = true + end + + s.epilog = """ + Examples (run from the `pha` folder):\n + \n + # Multi-threaded\n + julia -t 4 --project=. apophis.jl --maxsteps 100 --nyears_bwd -0.02 --nyears_fwd 0.02 --parse_eqs true\n + \n + # Single-threaded\n + julia --project=. apophis.jl --maxsteps 100 --nyears_bwd -0.02 --nyears_fwd 0.02 --parse_eqs true\n + \n + """ + + return parse_args(s) +end + +function print_header(header::String, level::Int = 1) + L = length(header) + if level == 1 + c = "=" + else + c = "-" + end + println(repeat(c, L)) + println(header) + println(repeat(c, L)) +end + +function main(dynamics::D, maxsteps::Int, jd0_datetime::DateTime, nyears_bwd::T, nyears_fwd::T, order::Int, varorder::Int, + abstol::T, parse_eqs::Bool) where {T <: Real, D} + + # Initial conditions from Apophis JPL solution #197 + q00 = kmsec2auday(apophisposvel197(datetime2et(jd0_datetime))) + + # Perturbation to nominal initial condition (Taylor1 jet transport) + # vcat(fill(1e-8, 6), 1e-14, 1e-15) are the scaling factors for jet transport perturbation, + # these are needed to ensure expansion coefficients remain small. + # The magnitudes correspond to the typical order of magnitude of errors in + # position/velocity (1e-8), Yarkovsky (1e-14) and radiation pressure (1e-15) + scalings = vcat(fill(1e-8, 6), 1e-14, 1e-15) + if varorder == 0 + dq = zeros(8) + else + dq = NEOs.scaled_variables("δx", scalings, order = varorder) + end + + q0 = vcat(q00, 0.0, 0.0) .+ dq + + # Initial date (in Julian days) + jd0 = datetime2julian(jd0_datetime) + + print_header("Integrator warmup", 2) + _ = NEOs.propagate(dynamics, 1, jd0, nyears_fwd, q0, Val(true); + order, abstol, parse_eqs) + _ = NEOs.propagate_root(dynamics, 1, jd0, nyears_fwd, q0, Val(true); + order, abstol, parse_eqs) + println() + + print_header("Main integration", 2) + tmax = nyears_bwd*yr + println("• Initial time of integration: ", string(jd0_datetime)) + println("• Final time of integration: ", julian2datetime(jd0 + tmax)) + + sol_bwd = NEOs.propagate(dynamics, maxsteps, jd0, nyears_bwd, q0, Val(true); + order, abstol, parse_eqs) + jldsave("Apophis_bwd.jld2"; sol_bwd) + # sol_bwd = JLD2.load("Apophis_bwd.jld2", "sol_bwd") + + tmax = nyears_fwd*yr + println("• Initial time of integration: ", string(jd0_datetime)) + println("• Final time of integration: ", julian2datetime(jd0 + tmax)) + + sol_fwd, tvS, xvS, gvS = NEOs.propagate_root(dynamics, maxsteps, jd0, nyears_fwd, q0, Val(true); + order, abstol, parse_eqs) + jldsave("Apophis_fwd.jld2"; sol_fwd, tvS, xvS, gvS) + # sol_fwd = JLD2.load("Apophis_fwd.jld2", "sol_bwd") + println() + + # load Solar System ephemeris + sseph::TaylorInterpolant{Float64,Float64,2} = loadpeeph(NEOs.sseph, sol_bwd.t0+sol_bwd.t[end], sol_fwd.t0+sol_fwd.t[end]) + eph_su::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, su) + eph_ea::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, ea) + + # NEO + # Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec + xva_bwd(et) = auday2kmsec(sol_bwd(et/daysec)[1:6]) + xva_fwd(et) = auday2kmsec(sol_fwd(et/daysec)[1:6]) + xva(et) = bwdfwdeph(et, sol_bwd, sol_fwd) + # Earth + # Change x, v units, resp., from au, au/day to km, km/sec + xve(et) = auday2kmsec(eph_ea(et/daysec)) + # Sun + # Change x, v units, resp., from au, au/day to km, km/sec + xvs(et) = auday2kmsec(eph_su(et/daysec)) + + + radec_2004_2020 = read_radec_mpc(joinpath(pkgdir(NEOs), "data", "99942_2004_2020.dat")) + radec_2020_2021 = read_radec_mpc(joinpath(pkgdir(NEOs), "data", "99942_2020_2021.dat")) + radec = vcat(radec_2004_2020,radec_2020_2021) + + deldop_2005_2013 = read_radar_jpl(joinpath(pkgdir(NEOs), "data", "99942_RADAR_2005_2013.dat")) + deldop_2021 = read_radar_jpl(joinpath(pkgdir(NEOs), "data", "99942_RADAR_2021.dat")) + deldop = vcat(deldop_2005_2013,deldop_2021) + + # Compute optical residuals + res_radec_all, w_radec_all = NEOs.residuals(radec; xvs, xve, xva) + jldsave("Apophis_res_w_radec.jld2"; res_radec_all, w_radec_all) + # JLD2.@load "Apophis_res_w_radec.jld2" + + # Compute radar residuals + res_del, w_del, res_dop, w_dop = NEOs.residuals(deldop; xvs, xve, xva, niter=10, tord=10) + jldsave("Apophis_res_w_deldop.jld2"; res_del, w_del, res_dop, w_dop) + # JLD2.@load "Apophis_res_w_deldop.jld2" + + ### Process optical astrometry (filter, weight, debias) + + # filter out biased observations from observatory 217 on 28-Jan-2021 + df_radec = DataFrame(radec) + # add residuals and weights to optical astrometry DataFrame + df_radec[!, :res_α] .= res_radec_all[1:round(Int,length(res_radec_all)/2)] + df_radec[!, :res_δ] .= res_radec_all[1+round(Int,length(res_radec_all)/2):end] + df_radec[!, :w_α] .= w_radec_all[1:round(Int,length(res_radec_all)/2)] + df_radec[!, :w_δ] .= w_radec_all[1+round(Int,length(res_radec_all)/2):end] + filter!( + x->(Date(x.date) != Date(2021, 1, 28)), + df_radec + ) + + # read astrometric errors from Tholen et al. (2013) + tho13_errors = readdlm(joinpath(pkgdir(NEOs), "data", "tholenetal2013_opterror.dat"), ',') + # compute weights + w_α_tho13 = 1 ./ (tho13_errors[:,1].^2 .+ tho13_errors[:,3].^2 .+ tho13_errors[:,5].^2) + w_δ_tho13 = 1 ./ (tho13_errors[:,2].^2 .+ tho13_errors[:,4].^2 .+ tho13_errors[:,6].^2) + # Tholen et al. (2013) obs table + radec_tho13 = DataFrame(read_radec_mpc(joinpath(pkgdir(NEOs), "test", "data", "99942_Tholen_etal_2013.dat"))) + # vector of RA values from Tholen et al. (2013) observations (used for filtering) + tho13_α = radec_tho13[!,:α] + # set weights in Tholen et al. (2013) astrometry corresponding to associated uncertainties + df_radec[in.(df_radec.α, Ref(tho13_α)),:w_α] = w_α_tho13 + df_radec[in.(df_radec.α, Ref(tho13_α)),:w_δ] = w_δ_tho13 + + # Relaxation factor (account for correlations in optical astrometry data) + # for each observation batch, count the number of observations made in + # the same night by the same observatory + # Ref: Veres et al. (2017) + date_site_v = select(df_radec, :date => ByRow(Date), :observatory) + Nv = [count(x->x.date_Date==i.date_Date && x.observatory==i.observatory, eachrow(date_site_v)) for i in eachrow(date_site_v)] + relax_factor = map(x->x>4.0 ? x/4.0 : 1.0, Nv) + # inflate uncertainties (i.e., relax weights) by relaxation factor + df_radec[!, :w_α] .= (df_radec.w_α)./relax_factor + df_radec[!, :w_δ] .= (df_radec.w_δ)./relax_factor + + # update optical residuals and weights + res_radec = vcat(df_radec.res_α, df_radec.res_δ) + w_radec = vcat(df_radec.w_α, df_radec.w_δ) + + ### Perform orbital fit to optical and radar astrometry data + + res = vcat(res_radec, res_del, res_dop) + w = vcat(w_radec, w_del, w_dop) + + fit_OR8 = newtonls(res, w, zeros(get_numvars()), 10) + x_OR8 = sol_fwd(sol_fwd.t0)(fit_OR8.x) + σ_OR8 = sqrt.(diag(fit_OR8.Γ)).*scalings + + nradec = length(res_radec) + res_ra = view(res_radec, 1:nradec÷2) + res_dec = view(res_radec, 1+nradec÷2:nradec) + w_ra = view(w_radec, 1:nradec÷2) + w_dec = view(w_radec, 1+nradec÷2:nradec) + + ### Print results + + print_header("Orbital fit (8-DOF) and post-fit statistics", 2) + + # orbital fit + println("Success flag : ", fit_OR8.success, "\n") + println("Nominal solution [au,au,au,au/d,au/d,au/d,au/d²,au/d²]: ", x_OR8, "\n") + println("1-sigma formal uncertainties [au,au,au,au/d,au/d,au/d,au/d²,au/d²]: ", σ_OR8, "\n") + + # post-fit statistics + println("Normalized RMS (optical-only) [adimensional] : ", nrms(res_radec(fit_OR8.x),w_radec)) + println("Normalized RMS (radar-only) [adimensional] : ", nrms(vcat(res_del,res_dop)(fit_OR8.x),vcat(w_del,w_dop))) + println("Normalized RMS (combined optical and radar) [adimensional] : ", nrms(res(fit_OR8.x),w), "\n") + println("Mean weighted right-ascension residual [arcseconds] : ", mean(res_ra(fit_OR8.x), weights(w_ra))) + println("Mean weighted declination residual [arcseconds] : ", mean(res_dec(fit_OR8.x), weights(w_dec))) + println("Mean weighted time-delay residual [micro-seconds]: ", mean(res_del(fit_OR8.x), weights(w_del))) + println("Mean weighted Doppler-shift residual [Hz] : ", mean(res_dop(fit_OR8.x), weights(w_dop)), "\n") + println("Chi-squared statistic (χ²): [adimensional] : ", chi2(res(fit_OR8.x),w)) + + return sol_bwd, sol_fwd, res_radec, res_del, res_dop, w_radec, w_del, w_dop +end + +function main() + + # Parse arguments from commandline + parsed_args = parse_commandline() + + print_header("Asteroid Apophis") + println() + print_header("General parameters", 2) + + # Number of threads + N_threads = Threads.nthreads() + println("• Number of threads: ", N_threads) + + # Dynamical function + dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! + + println("• Dynamical function: ", dynamics) + + # Maximum number of steps + maxsteps = parsed_args["maxsteps"] + println("• Maximum number of steps: ", maxsteps) + + # Initial date + jd0_datetime = parsed_args["jd0"] + + # Number of years in backward integration + nyears_bwd = parsed_args["nyears_bwd"] + + # Number of years in forward integration + nyears_fwd = parsed_args["nyears_fwd"] + + # Order of Taylor polynomials + order = parsed_args["order"] + println("• Order of Taylor polynomials: ", order) + + # Order of jet transport perturbation + varorder = parsed_args["varorder"] + println("• Order of jet transport perturbation: ", varorder) + + # Absolute tolerance + abstol = parsed_args["abstol"] + println("• Absolute tolerance: ", abstol) + + # Whether to use @taylorize or not + parse_eqs = parsed_args["parse_eqs"] + println("• Use @taylorize: ", parse_eqs, "\n") + + main(dynamics, maxsteps, jd0_datetime, nyears_bwd, nyears_fwd, order, varorder, abstol, parse_eqs) +end + +main() + +#= +-0.18034827489412805 +0.9406910783153754 +0.3457360118643932 +-0.016265940057745887 +4.3915296805381036e-5 +-0.0003952032399008921 +-2.883842658925719e-14 +-1.6977850502837174e-11 + + +6.991681792970175e-9 +3.3210758500485412e-9 +8.763895947794195e-9 +5.485729074188412e-11 +9.846074910774499e-11 +1.3782767177665416e-10 +2.525644870489942e-16 +3.2193289354129716e-12 + +Normalized RMS (optical-only) [adimensional] : 0.4365429773707507 +Normalized RMS (radar-only) [adimensional] : 0.5421268387032326 +Normalized RMS (combined optical and radar) [adimensional] : 0.43685679642513925 + +Mean weighted right-ascension residual [arcseconds] : -0.002787272519210798 +Mean weighted declination residual [arcseconds] : -0.003376099885054764 +Mean weighted time-delay residual [micro-seconds]: -0.0007329351962194035 +Mean weighted Doppler-shift residual [Hz] : -0.03025601266756564 + +Chi-squared statistic (χ²): [adimensional] : 3597.4067719864497 + =# \ No newline at end of file diff --git a/src/NEOs.jl b/src/NEOs.jl old mode 100755 new mode 100644 index 359696a5..606cd9b7 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -1,84 +1,84 @@ -module NEOs - -# __precompile__(false) - -import Base: show, string, hash, isequal, ==, isless, convert, zero, iszero, isnan, in -import Tables: istable, rowaccess, rows, schema, Schema -import SatelliteToolboxTransformations: sv_ecef_to_eci, sv_ecef_to_ecef, ecef_to_geocentric -import JLD2: writeas -import PlanetaryEphemeris as PE - -import Downloads - -using AutoHashEquals, Dates, Printf, JSON, SatelliteToolboxTransformations, TaylorSeries, - TaylorIntegration, SPICE, JLD2, LazyArtifacts, LinearAlgebra, LinearAlgebra, - DelimitedFiles, Scratch, Quadmath, Test, InteractiveUtils, Distributed -using HTTP: get -using DataFrames: DataFrame, nrow, eachcol, eachrow, groupby, combine, AbstractDataFrame, - DataFrameRow, GroupedDataFrame -using PlanetaryEphemeris: daysec, yr, TaylorInterpolant, auday2kmsec, su, ea, au, - c_au_per_day, α_p_sun, δ_p_sun, pole_rotation, c_cm_per_sec, c_au_per_sec, - t2c_jpl_de430, R_sun, RE, Rx, Ry, Rz, semimajoraxis, eccentricity, inclination, - longascnode, argperi, timeperipass, nbodyind, numberofbodies, kmsec2auday, - meanmotion, meananomaly, selecteph -using Healpix: ang2pixRing, Resolution -using StatsBase: mean, std -using LsqFit: curve_fit -using Roots: find_zeros -using Clustering: kmeans - -using Downloads: download - -# Constants -export d_EM_km, d_EM_au -# CatalogueMPC -export unknowncat, read_catalogues_mpc, write_catalogues_mpc, update_catalogues_mpc, - search_cat_code -# ObservatoryMPC -export unknownobs, hascoord, read_observatories_mpc, write_observatories_mpc, - update_observatories_mpc, search_obs_code -# RadecMPC -export ra, dec, date, observatory, read_radec_mpc, write_radec_mpc, get_radec_mpc, - fetch_radec_mpc -# RadarJPL -export hasdelay, hasdoppler, delay, doppler, rcvr, xmit, read_radar_jpl, write_radar_jpl -# Units -export julian2etsecs, etsecs2julian, datetime2et, et_to_200X, days_to_200X, datetime_to_200X, - datetime2days, days2datetime, rad2arcsec, arcsec2rad, mas2rad -# JPL Ephemerides -export loadjpleph, sunposvel, earthposvel, moonposvel, apophisposvel197, apophisposvel199, - loadpeeph, bwdfwdeph -# Topocentric -export obsposECEF, obsposvelECI -# Process radec -export compute_radec, select_debiasing_table, debiasing, w8sveres17, residuals, unfold, - relax_factor, outlier -# Process radar -export compute_delay, radar_astrometry -# Asteroid dynamical models -export RNp1BP_pN_A_J23E_J2S_ng_eph_threads!, RNp1BP_pN_A_J23E_J2S_eph_threads!, newtonian! -# Propagate -export NEOParameters, propagate, propagate_lyap, propagate_root -# B plane -export valsecchi_circle, bopik -# Least squares -export project, chi2, nms, nrms, diffcorr, newtonls, levenbergmarquardt, tryls, sigmas -# Osculating -export pv2kep, yarkp2adot -# Too Short Arc -export tooshortarc -# Gauss method -export gauss_method, gaussinitcond, gauss_refinement -# Outlier rejection -export outlier_rejection -# Orbit determination -export issinglearc, istsa, orbitdetermination - -include("constants.jl") -include("observations/process_radar.jl") -include("propagation/propagation.jl") -include("orbit_determination/orbit_determination.jl") -include("postprocessing/outlier_rejection.jl") -include("init.jl") - +module NEOs + +# __precompile__(false) + +import Base: show, string, hash, isequal, ==, isless, convert, zero, iszero, isnan, in +import Tables: istable, rowaccess, rows, schema, Schema +import SatelliteToolboxTransformations: sv_ecef_to_eci, sv_ecef_to_ecef, ecef_to_geocentric +import JLD2: writeas +import PlanetaryEphemeris as PE + +import Downloads + +using AutoHashEquals, Dates, Printf, JSON, SatelliteToolboxTransformations, TaylorSeries, + TaylorIntegration, SPICE, JLD2, LazyArtifacts, LinearAlgebra, LinearAlgebra, + DelimitedFiles, Scratch, Quadmath, Test, InteractiveUtils, Distributed +using HTTP: get +using DataFrames: DataFrame, nrow, eachcol, eachrow, groupby, combine, AbstractDataFrame, + DataFrameRow, GroupedDataFrame +using PlanetaryEphemeris: daysec, yr, TaylorInterpolant, auday2kmsec, su, ea, au, + c_au_per_day, α_p_sun, δ_p_sun, pole_rotation, c_cm_per_sec, c_au_per_sec, + t2c_jpl_de430, R_sun, RE, Rx, Ry, Rz, semimajoraxis, eccentricity, inclination, + longascnode, argperi, timeperipass, nbodyind, numberofbodies, kmsec2auday, + meanmotion, meananomaly, selecteph +using Healpix: ang2pixRing, Resolution +using StatsBase: mean, std +using LsqFit: curve_fit +using Roots: find_zeros +using Clustering: kmeans + +using Downloads: download + +# Constants +export d_EM_km, d_EM_au +# CatalogueMPC +export unknowncat, read_catalogues_mpc, write_catalogues_mpc, update_catalogues_mpc, + search_cat_code +# ObservatoryMPC +export unknownobs, hascoord, read_observatories_mpc, write_observatories_mpc, + update_observatories_mpc, search_obs_code +# RadecMPC +export ra, dec, date, observatory, read_radec_mpc, write_radec_mpc, get_radec_mpc, + fetch_radec_mpc +# RadarJPL +export hasdelay, hasdoppler, delay, doppler, rcvr, xmit, read_radar_jpl, write_radar_jpl +# Units +export julian2etsecs, etsecs2julian, datetime2et, et_to_200X, days_to_200X, datetime_to_200X, + datetime2days, days2datetime, rad2arcsec, arcsec2rad, mas2rad +# JPL Ephemerides +export loadjpleph, sunposvel, earthposvel, moonposvel, apophisposvel197, apophisposvel199, + loadpeeph, bwdfwdeph +# Topocentric +export obsposECEF, obsposvelECI +# Process radec +export compute_radec, select_debiasing_table, debiasing, w8sveres17, residuals, unfold, + relax_factor, outlier +# Process radar +export compute_delay, radar_astrometry +# Asteroid dynamical models +export RNp1BP_pN_A_J23E_J2S_ng_eph_threads!, RNp1BP_pN_A_J23E_J2S_eph_threads!, newtonian! +# Propagate +export NEOParameters, propagate, propagate_lyap, propagate_root +# B plane +export valsecchi_circle, bopik +# Least squares +export project, chi2, nms, nrms, diffcorr, newtonls, levenbergmarquardt, tryls, sigmas +# Osculating +export pv2kep, yarkp2adot +# Too Short Arc +export tooshortarc +# Gauss method +export gauss_method, gaussinitcond, gauss_refinement +# Outlier rejection +export outlier_rejection +# Orbit determination +export issinglearc, istsa, orbitdetermination + +include("constants.jl") +include("observations/process_radar.jl") +include("propagation/propagation.jl") +include("orbit_determination/orbit_determination.jl") +include("postprocessing/outlier_rejection.jl") +include("init.jl") + end \ No newline at end of file diff --git a/src/constants.jl b/src/constants.jl old mode 100755 new mode 100644 index 8699c268..23bcd43e --- a/src/constants.jl +++ b/src/constants.jl @@ -1,205 +1,205 @@ -# Internal paths - -# Path to NEOs src directory -const src_path = dirname(pathof(NEOs)) -# Path to scratch space -const scratch_path = Ref{String}("") - -# Load Solar System, accelerations, newtonian potentials and TT-TDB 2000-2100 ephemeris -const sseph_artifact_path = joinpath(artifact"sseph_p100", "sseph343ast016_p100y_et.jld2") -const sseph::TaylorInterpolant{Float64, Float64, 2, Vector{Float64}, Matrix{Taylor1{Float64}}} = JLD2.load(sseph_artifact_path, "ss16ast_eph") -const acceph::TaylorInterpolant{Float64, Float64, 2, Vector{Float64}, Matrix{Taylor1{Float64}}} = JLD2.load(sseph_artifact_path, "acc_eph") -const poteph::TaylorInterpolant{Float64, Float64, 2, Vector{Float64}, Matrix{Taylor1{Float64}}} = JLD2.load(sseph_artifact_path, "pot_eph") -const ttmtdb::TaylorInterpolant{Float64, Float64, 1, Vector{Float64}, Vector{Taylor1{Float64}}} = TaylorInterpolant(sseph.t0, sseph.t, sseph.x[:,end]) - -# Earth orientation parameters (eop) 2000 -const eop_IAU2000A::EopIau2000A = fetch_iers_eop(Val(:IAU2000A)) - -# Parsing - -# Regular expression to parse a catalogue in MPC format -const CATALOGUE_MPC_REGEX = r"\s{2}(?P\w{1})\s{4}(?P.*)" -# Header of MPC catalogues file -const CATALOGUES_MPC_HEADER = "Char Catalogue" -# Regular expression to parse an observatory in MPC format -const OBSERVATORY_MPC_REGEX = Regex(string( - # Code regex + space (columns 1-3) - raw"(?P[A-Z\d]{3})", - # Longitude regex (columns 4-13) - raw"(?P[\.\d\s]{10})", - # Cosine regex + space (column 14-21) - raw"(?P[\.\d\s]{8})", - # Sine regex (column 22-30) - raw"(?P[\+\-\.\d\s]{9})", - # Name regex (columns 31-80) - raw"(?P.*)", -)) -# Header of MPC observatories file -const OBSERVATORIES_MPC_HEADER = "Code Long. cos sin Name" -# Regular expression to parse an optical measurement in MPC format -const RADEC_MPC_REGEX = Regex(string( - # Number regex (columns 1-5) - raw"(?P.{5})", - # Temporary designation regex (columns 6-12) - raw"(?P.{7})", - # Discovery asterisk regex (column 13) - raw"(?P[\*\s]{1})", - # Publishable note regex (column 14) - raw"(?P.{1})", - # Observation technique regex (column 15) - raw"(?P[^xX]{1})", - # Date of observation regex (columns 16-32) - raw"(?P\d{4}\s\d{2}\s\d{2}\.[\d\s]{6})", - # Right ascension regex (columns 33-44) - raw"(?P<α>\d{2}\s\d{2}\s\d{2}\.[\d\s]{3})", - # Declination regex (columns 45-56) - raw"(?P<δ>[\+|\-]{1}\d{2}\s\d{2}\s\d{2}\.[\d\s]{2})", - # Info 1 regex (columns 57-65) - raw"(?P.{9})", - # Magnitude regex (columns 66-70) - raw"(?P[\.\s\d]{5})", - # Band regex (column 71) - raw"(?P[\w\s]{1})", - # Catalogue regex (column 72) - raw"(?P[\w\s]{1})", - # Info 2 regex (columns 73-77) - raw"(?P.{5})", - # Observatory code regex (columns 78-80) - raw"(?P\w{3})", - # Optional fields (in case of satellite observations) - # Breakline regex - raw"(?:\n)?", - # Number regex (columns 1-5) - raw"(?(?P<_num_>.{5})?", - # Temporary designation regex (columns 6-12) - raw"(?P<_tmpdesig_>.{7})?", - # Blank space regex (column 13) - raw"(?P<_discovery_>\s)?", - # Publishable note regex (column 14) - raw"(?P<_publishnote_>.{1})?", - # s regex (column 15) - raw"(?P<_obstech_>s)?", - # Date of observation regex (columns 16-32) - raw"(?P<_date_>\d{4}\s\d{2}\s\d{2}\.[\d\s]{6})", - # Units + space regex (columns 33-34) - raw"(?P<_units_>\d\s)", - # X component of geocentric vector (columns 35-46) - raw"(?P<_x_>[\-\+]{1}[\.\d\s]{11})", - # Y component of geocentric vector (columns 47-58) - raw"(?P<_y_>[\-\+]{1}[\.\d\s]{11})", - # Z component of geocentric vector (columns 59-70) - raw"(?P<_z_>[\-\+]{1}[\.\d\s]{11})", - # Band regex (column 71) - raw"(?P<_band_>[\w\s]{1})?", - # Catalogue regex (column 72) - raw"(?P<_catalogue_>[\w\s]{1})?", - # Info 2 regex (columns 73-77) - raw"(?P<_info2_>.{5})?", - # Observatory code regex (columns 78-80) - raw"(?P<_obscode_>\w{3})?)?", -)) -# Regular expression to parse a radar measurement in JPL format -const RADAR_JPL_REGEX = Regex(string( - # ID regex + tab - raw"(?P.*)\t", - # Date regex + tab - raw"(?P.*)\t", - # Measurement regex + tab - raw"(?P.*)\t", - # Uncertainty regex + tab - raw"(?P.*)\t", - # Units regex + tab - raw"(?P.*)\t", - # Frequency regex + tab - raw"(?P.*)\t", - # Reciever regex + tab - raw"(?P.*)\t", - # Emitter regex + tab - raw"(?P.*)\t", - # Bouncepoint regex + end of line - raw"(?P.*)" -)) -# Format of date in JPL radar data files -const RADAR_JPL_DATEFORMAT = "yyyy-mm-dd HH:MM:SS" - -# MPC catalogues corresponding to debiasing tables included in https://doi.org/10.1016/j.icarus.2014.07.033 -const mpc_catalogue_codes_2014 = ["a", "b", "c", "d", "e", "g", "i", "j", "l", "m", "o", "p", "q", "r", - "u", "v", "w", "L", "N"] - -# MPC catalogues corresponding to debiasing tables included in https://doi.org/10.1016/j.icarus.2019.113596 -const mpc_catalogue_codes_2018 = ["a", "b", "c", "d", "e", "g", "i", "j", "l", "m", "n", "o", "p", "q", - "r", "t", "u", "v", "w", "L", "N", "Q", "R", "S", "U", "W"] - -# URLs - -# MPC catalogues file url -const CATALOGUES_MPC_URL = "https://www.minorplanetcenter.net/iau/info/CatalogueCodes.html" -# MPC observatories file url -const OBSERVATORIES_MPC_URL = "https://www.minorplanetcenter.net/iau/lists/ObsCodes.html" - -# MPC database search url -const search_mpc_url = "https://www.minorplanetcenter.net/db_search/show_object?utf8=%E2%9C%93&object_id=" -# MPC observations url -const obs_mpc_url = "https://www.minorplanetcenter.net/tmp2/" - -# Abbreviations -const cte = constant_term - -# Integration parameters -const order = 30 -const abstol = 1.0E-30 - -# Vector of GM's (DE430 values) [au^2 / day^3] -const μ_DE430 = PE.μ -const μ_B16_DE430 = μ_DE430[12:27] # DE430 GM's of 16 most massive asteroids -const μ_ast343_DE430 = μ_DE430[12:end] # DE430 GM's of 343 main belt asteroids included in DE430 integration -# Gravitational parameter of the Sun [au^2 / day^3] -const μ_S = PE.GMS - -# Standard value of nominal mean angular velocity of Earth (rad/sec) -# See Explanatory Supplement to the Astronomical Almanac 2014 Sec 7.4.3.3 p. 296 -const ω = 7.2921151467e-5 # 7.292115e-5 rad/sec - -# Solar corona parameters -# See Table 8.5 in page 329 of Explanatory Supplement to the Astronomical Almanac 2014 -const A_sun = 1.06e8 # [cm^-3] -const a_sun = 4.89e5 # [cm^-3] -const b_sun = 3.91e5 # [cm^-3] - -# Sun radiated power intensity at photosphere surface, Watt/meter^2 -const S0_sun = 63.15E6 -# Conversion factor from m^2/sec^3 to au^2/day^3 -const m2_s3_to_au2_day3 = 1e-6daysec^3/au^2 - -# Vector of J_2*R^2 values -# J_2: second zonal harmonic coefficient -# R: radius of the body -const Λ2 = zeros(11) -Λ2[ea] = 1.9679542578489185e-12 # Earth -# Vector of J_3*R^3 values -# J_3: third zonal harmonic coefficient -# R: radius of the body -const Λ3 = zeros(11) -Λ3[ea] = -1.962633335678878e-19 # Earth - -# Speed of light -const clightkms = 2.99792458E5 # km/sec -# Parameters related to speed of light, c -const c_p2 = 29979.063823897606 # c^2 = 29979.063823897606 au^2/d^2 -const c_m2 = 3.3356611996764786e-5 # c^-2 = 3.3356611996764786e-5 d^2/au^2 - -# Earth-Moon distance in [km] -const d_EM_km = 384_400 -# Earth-Moon distance in [au] -const d_EM_au = 384_400 / au - -# Zeroth order obliquity of the ecliptic in degrees -# See equation (5-153) in page 5-61 of https://doi.org/10.1002/0471728470. -const ϵ0_deg = 84381.448/3_600 - -# Gauss gravitational constant -const k_gauss = 0.017_202_098_95 -# Earth's sphere of influence radius [AU] -const R_SI = 0.010044 -# Earth's physical radius [AU] -const R_EA = 4.2e-5 +# Internal paths + +# Path to NEOs src directory +const src_path = dirname(pathof(NEOs)) +# Path to scratch space +const scratch_path = Ref{String}("") + +# Load Solar System, accelerations, newtonian potentials and TT-TDB 2000-2100 ephemeris +const sseph_artifact_path = joinpath(artifact"sseph_p100", "sseph343ast016_p100y_et.jld2") +const sseph::TaylorInterpolant{Float64, Float64, 2, Vector{Float64}, Matrix{Taylor1{Float64}}} = JLD2.load(sseph_artifact_path, "ss16ast_eph") +const acceph::TaylorInterpolant{Float64, Float64, 2, Vector{Float64}, Matrix{Taylor1{Float64}}} = JLD2.load(sseph_artifact_path, "acc_eph") +const poteph::TaylorInterpolant{Float64, Float64, 2, Vector{Float64}, Matrix{Taylor1{Float64}}} = JLD2.load(sseph_artifact_path, "pot_eph") +const ttmtdb::TaylorInterpolant{Float64, Float64, 1, Vector{Float64}, Vector{Taylor1{Float64}}} = TaylorInterpolant(sseph.t0, sseph.t, sseph.x[:,end]) + +# Earth orientation parameters (eop) 2000 +const eop_IAU2000A::EopIau2000A = fetch_iers_eop(Val(:IAU2000A)) + +# Parsing + +# Regular expression to parse a catalogue in MPC format +const CATALOGUE_MPC_REGEX = r"\s{2}(?P\w{1})\s{4}(?P.*)" +# Header of MPC catalogues file +const CATALOGUES_MPC_HEADER = "Char Catalogue" +# Regular expression to parse an observatory in MPC format +const OBSERVATORY_MPC_REGEX = Regex(string( + # Code regex + space (columns 1-3) + raw"(?P[A-Z\d]{3})", + # Longitude regex (columns 4-13) + raw"(?P[\.\d\s]{10})", + # Cosine regex + space (column 14-21) + raw"(?P[\.\d\s]{8})", + # Sine regex (column 22-30) + raw"(?P[\+\-\.\d\s]{9})", + # Name regex (columns 31-80) + raw"(?P.*)", +)) +# Header of MPC observatories file +const OBSERVATORIES_MPC_HEADER = "Code Long. cos sin Name" +# Regular expression to parse an optical measurement in MPC format +const RADEC_MPC_REGEX = Regex(string( + # Number regex (columns 1-5) + raw"(?P.{5})", + # Temporary designation regex (columns 6-12) + raw"(?P.{7})", + # Discovery asterisk regex (column 13) + raw"(?P[\*\s]{1})", + # Publishable note regex (column 14) + raw"(?P.{1})", + # Observation technique regex (column 15) + raw"(?P[^xX]{1})", + # Date of observation regex (columns 16-32) + raw"(?P\d{4}\s\d{2}\s\d{2}\.[\d\s]{6})", + # Right ascension regex (columns 33-44) + raw"(?P<α>\d{2}\s\d{2}\s\d{2}\.[\d\s]{3})", + # Declination regex (columns 45-56) + raw"(?P<δ>[\+|\-]{1}\d{2}\s\d{2}\s\d{2}\.[\d\s]{2})", + # Info 1 regex (columns 57-65) + raw"(?P.{9})", + # Magnitude regex (columns 66-70) + raw"(?P[\.\s\d]{5})", + # Band regex (column 71) + raw"(?P[\w\s]{1})", + # Catalogue regex (column 72) + raw"(?P[\w\s]{1})", + # Info 2 regex (columns 73-77) + raw"(?P.{5})", + # Observatory code regex (columns 78-80) + raw"(?P\w{3})", + # Optional fields (in case of satellite observations) + # Breakline regex + raw"(?:\n)?", + # Number regex (columns 1-5) + raw"(?(?P<_num_>.{5})?", + # Temporary designation regex (columns 6-12) + raw"(?P<_tmpdesig_>.{7})?", + # Blank space regex (column 13) + raw"(?P<_discovery_>\s)?", + # Publishable note regex (column 14) + raw"(?P<_publishnote_>.{1})?", + # s regex (column 15) + raw"(?P<_obstech_>s)?", + # Date of observation regex (columns 16-32) + raw"(?P<_date_>\d{4}\s\d{2}\s\d{2}\.[\d\s]{6})", + # Units + space regex (columns 33-34) + raw"(?P<_units_>\d\s)", + # X component of geocentric vector (columns 35-46) + raw"(?P<_x_>[\-\+]{1}[\.\d\s]{11})", + # Y component of geocentric vector (columns 47-58) + raw"(?P<_y_>[\-\+]{1}[\.\d\s]{11})", + # Z component of geocentric vector (columns 59-70) + raw"(?P<_z_>[\-\+]{1}[\.\d\s]{11})", + # Band regex (column 71) + raw"(?P<_band_>[\w\s]{1})?", + # Catalogue regex (column 72) + raw"(?P<_catalogue_>[\w\s]{1})?", + # Info 2 regex (columns 73-77) + raw"(?P<_info2_>.{5})?", + # Observatory code regex (columns 78-80) + raw"(?P<_obscode_>\w{3})?)?", +)) +# Regular expression to parse a radar measurement in JPL format +const RADAR_JPL_REGEX = Regex(string( + # ID regex + tab + raw"(?P.*)\t", + # Date regex + tab + raw"(?P.*)\t", + # Measurement regex + tab + raw"(?P.*)\t", + # Uncertainty regex + tab + raw"(?P.*)\t", + # Units regex + tab + raw"(?P.*)\t", + # Frequency regex + tab + raw"(?P.*)\t", + # Reciever regex + tab + raw"(?P.*)\t", + # Emitter regex + tab + raw"(?P.*)\t", + # Bouncepoint regex + end of line + raw"(?P.*)" +)) +# Format of date in JPL radar data files +const RADAR_JPL_DATEFORMAT = "yyyy-mm-dd HH:MM:SS" + +# MPC catalogues corresponding to debiasing tables included in https://doi.org/10.1016/j.icarus.2014.07.033 +const mpc_catalogue_codes_2014 = ["a", "b", "c", "d", "e", "g", "i", "j", "l", "m", "o", "p", "q", "r", + "u", "v", "w", "L", "N"] + +# MPC catalogues corresponding to debiasing tables included in https://doi.org/10.1016/j.icarus.2019.113596 +const mpc_catalogue_codes_2018 = ["a", "b", "c", "d", "e", "g", "i", "j", "l", "m", "n", "o", "p", "q", + "r", "t", "u", "v", "w", "L", "N", "Q", "R", "S", "U", "W"] + +# URLs + +# MPC catalogues file url +const CATALOGUES_MPC_URL = "https://www.minorplanetcenter.net/iau/info/CatalogueCodes.html" +# MPC observatories file url +const OBSERVATORIES_MPC_URL = "https://www.minorplanetcenter.net/iau/lists/ObsCodes.html" + +# MPC database search url +const search_mpc_url = "https://www.minorplanetcenter.net/db_search/show_object?utf8=%E2%9C%93&object_id=" +# MPC observations url +const obs_mpc_url = "https://www.minorplanetcenter.net/tmp2/" + +# Abbreviations +const cte = constant_term + +# Integration parameters +const order = 30 +const abstol = 1.0E-30 + +# Vector of GM's (DE430 values) [au^2 / day^3] +const μ_DE430 = PE.μ +const μ_B16_DE430 = μ_DE430[12:27] # DE430 GM's of 16 most massive asteroids +const μ_ast343_DE430 = μ_DE430[12:end] # DE430 GM's of 343 main belt asteroids included in DE430 integration +# Gravitational parameter of the Sun [au^2 / day^3] +const μ_S = PE.GMS + +# Standard value of nominal mean angular velocity of Earth (rad/sec) +# See Explanatory Supplement to the Astronomical Almanac 2014 Sec 7.4.3.3 p. 296 +const ω = 7.2921151467e-5 # 7.292115e-5 rad/sec + +# Solar corona parameters +# See Table 8.5 in page 329 of Explanatory Supplement to the Astronomical Almanac 2014 +const A_sun = 1.06e8 # [cm^-3] +const a_sun = 4.89e5 # [cm^-3] +const b_sun = 3.91e5 # [cm^-3] + +# Sun radiated power intensity at photosphere surface, Watt/meter^2 +const S0_sun = 63.15E6 +# Conversion factor from m^2/sec^3 to au^2/day^3 +const m2_s3_to_au2_day3 = 1e-6daysec^3/au^2 + +# Vector of J_2*R^2 values +# J_2: second zonal harmonic coefficient +# R: radius of the body +const Λ2 = zeros(11) +Λ2[ea] = 1.9679542578489185e-12 # Earth +# Vector of J_3*R^3 values +# J_3: third zonal harmonic coefficient +# R: radius of the body +const Λ3 = zeros(11) +Λ3[ea] = -1.962633335678878e-19 # Earth + +# Speed of light +const clightkms = 2.99792458E5 # km/sec +# Parameters related to speed of light, c +const c_p2 = 29979.063823897606 # c^2 = 29979.063823897606 au^2/d^2 +const c_m2 = 3.3356611996764786e-5 # c^-2 = 3.3356611996764786e-5 d^2/au^2 + +# Earth-Moon distance in [km] +const d_EM_km = 384_400 +# Earth-Moon distance in [au] +const d_EM_au = 384_400 / au + +# Zeroth order obliquity of the ecliptic in degrees +# See equation (5-153) in page 5-61 of https://doi.org/10.1002/0471728470. +const ϵ0_deg = 84381.448/3_600 + +# Gauss gravitational constant +const k_gauss = 0.017_202_098_95 +# Earth's sphere of influence radius [AU] +const R_SI = 0.010044 +# Earth's physical radius [AU] +const R_EA = 4.2e-5 diff --git a/src/init.jl b/src/init.jl old mode 100755 new mode 100644 index 8f3e57e9..a35af112 --- a/src/init.jl +++ b/src/init.jl @@ -1,23 +1,23 @@ -# List of MPC catalogues -const CATALOGUES_MPC = Ref{Vector{CatalogueMPC}}([unknowncat()]) -# List of MPC observatories -const OBSERVATORIES_MPC = Ref{Vector{ObservatoryMPC{Float64}}}([unknownobs()]) - -function __init__() - # Initialize scratch space - global scratch_path[] = @get_scratch!("NEOsScratch") - # Load catalogues - CatalogueCodes_path = joinpath(scratch_path[], "CatalogueCodes.txt") - if isfile(CatalogueCodes_path) - global CATALOGUES_MPC[] = read_catalogues_mpc(CatalogueCodes_path) - else - update_catalogues_mpc() - end - # Load observatories - ObsCodes_path = joinpath(scratch_path[], "ObsCodes.txt") - if isfile(ObsCodes_path) - global OBSERVATORIES_MPC[] = read_observatories_mpc(ObsCodes_path) - else - update_observatories_mpc() - end +# List of MPC catalogues +const CATALOGUES_MPC = Ref{Vector{CatalogueMPC}}([unknowncat()]) +# List of MPC observatories +const OBSERVATORIES_MPC = Ref{Vector{ObservatoryMPC{Float64}}}([unknownobs()]) + +function __init__() + # Initialize scratch space + global scratch_path[] = @get_scratch!("NEOsScratch") + # Load catalogues + CatalogueCodes_path = joinpath(scratch_path[], "CatalogueCodes.txt") + if isfile(CatalogueCodes_path) + global CATALOGUES_MPC[] = read_catalogues_mpc(CatalogueCodes_path) + else + update_catalogues_mpc() + end + # Load observatories + ObsCodes_path = joinpath(scratch_path[], "ObsCodes.txt") + if isfile(ObsCodes_path) + global OBSERVATORIES_MPC[] = read_observatories_mpc(ObsCodes_path) + else + update_observatories_mpc() + end end \ No newline at end of file diff --git a/src/observations/catalogue_mpc.jl b/src/observations/catalogue_mpc.jl old mode 100755 new mode 100644 index 1e5a43b7..8271edf9 --- a/src/observations/catalogue_mpc.jl +++ b/src/observations/catalogue_mpc.jl @@ -1,188 +1,188 @@ -@doc raw""" - CatalogueMPC - -An astrometric reference catalogue in MPC format. - -# Fields - -- `code::String`: catalogue's single character identifier. -- `name::String`: catalogue's name. - -!!! reference - The format is described in https://minorplanetcenter.net/iau/info/CatalogueCodes.html. -""" -@auto_hash_equals struct CatalogueMPC - code::String - name::String - # Inner constructor - function CatalogueMPC(code::String, name::String) - return new(code, name) - end -end - -@doc raw""" - unknowncat() - -Return a `CatalogueMPC` with no code or name. -""" -function unknowncat() - return CatalogueMPC("", "") -end - -@doc raw""" - isunknown(m::CatalogueMPC) - -Check whether `m` equals `unknowncat()`. -""" -function isunknown(m::CatalogueMPC) - return m == unknowncat() -end - -# Print method for CatalogueMPC -# Examples: -# Unknown catalogue -# USNO-A1.0 [a] -function show(io::IO, m::CatalogueMPC) - if isunknown(m) - print(io, "Unknown catalogue") - else - print(io, m.name, " [", m.code, "]") - end -end - -neoparse(x::RegexMatch, i::Int, ::Type{String}) = String(strip(x[i])) - -@doc raw""" - CatalogueMPC(m::RegexMatch) - -Convert a match of `NEOs.CATALOGUE_MPC_REGEX` to `CatalogueMPC`. -""" -function CatalogueMPC(m::RegexMatch) - # Check that matched regex is correct - @assert m.regex == CATALOGUE_MPC_REGEX "Only matches of `NEOs.CATALOGUE_MPC_REGEX` can be converted to `CatalogueMPC`." - # Field types - types = fieldtypes(CatalogueMPC) - # CatalogueMPC fields - args = map(i -> neoparse(m, i, types[i]), 1:length(types)) - - return CatalogueMPC(args...) -end - -@doc raw""" - read_catalogues_mpc(s::String) - -Return the matches of `NEOs.CATALOGUE_MPC_REGEX` in `s` as `Vector{CatalogueMPC}`. -`s` can be either a filename or a text. -""" -function read_catalogues_mpc(s::String) - if !contains(s, "\n") && isfile(s) - # Read MPC formatted file - s = String(read(s)) - end - # Remove header - s = replace(s, CATALOGUES_MPC_HEADER => "") - # Vector of MPC catalogues - cats = Vector{CatalogueMPC}(undef, 0) - # Iterate over the matches - for m in eachmatch(CATALOGUE_MPC_REGEX, s) - push!(cats, CatalogueMPC(m)) - end - # Eliminate repeated entries - unique!(cats) - - return cats -end - -# Convert `cat` to a string according to MPC format. -function string(cat::CatalogueMPC) - if isunknown(cat) - return "" - else - # Code string - code_s = string(" ", cat.code, " ") - # Join everything - cat_s = string(code_s, cat.name) - - return cat_s - end -end - -@doc raw""" - write_catalogues_mpc(cats::Vector{CatalogueMPC}, filename::String) - -Write `cats` to `filename` in MPC format. -""" -function write_catalogues_mpc(cats::Vector{CatalogueMPC}, filename::String) - open(filename, "w") do file - # Header - write(file, CATALOGUES_MPC_HEADER, "\n") - # Write observatories - for i in eachindex(cats) - line = string(cats[i]) - write(file, line, "\n") - end - end -end - -@doc raw""" - download_scratch(url::String, filename::String; connect_timeout = 180, readtimeout = 180) - -Download `url` and save the output to NEOs scratch space as `filename`. Return the local -path and the contents of the file as a `String`. -""" -function download_scratch(url::String, filename::String; connect_timeout = 180, readtimeout = 180) - # Local file - path = joinpath(scratch_path[], filename) - # Get raw html (HTTP.get retries four times by default) - resp = get(url; connect_timeout, readtimeout) - # Read local file - txt = String(resp.body) - - return path, txt -end - -@doc raw""" - update_catalogues_mpc() - -Update the local catalogues file. -""" -function update_catalogues_mpc() - # Download and read catalogues file - CatalogueCodes_path, txt = download_scratch(CATALOGUES_MPC_URL, "CatalogueCodes.txt") - # Parse catalogues - cats = read_catalogues_mpc(txt) - # Write catalogues to local file - write_catalogues_mpc(cats, CatalogueCodes_path) - # Update global variable - global CATALOGUES_MPC[] = read_catalogues_mpc(CatalogueCodes_path) - - return nothing -end - -@doc raw""" - search_cat_code(catcode::String) - -Return the catalogue in `NEOs.CATALOGUES_MPC` that matches `catcode`. -""" -function search_cat_code(catcode::String) - - # Find indexes in mpc_catalogues that match catcode - idxs = findall(x -> x.code == catcode, CATALOGUES_MPC[]) - L_i = length(idxs) - - # No catalog matches catcode - if L_i == 0 - catalogue = unknowncat() - # Exactly one catalogue matches catcode - else - catalogue = CATALOGUES_MPC[][idxs[1]] - # More than one catalogue matches catcode - if L_i > 1 - @warn("""More than one catalogue $(CATALOGUES_MPC[][idxs]) has code $catcode, - selecting first: $(catalogue.name)""") - end - end - - return catalogue - +@doc raw""" + CatalogueMPC + +An astrometric reference catalogue in MPC format. + +# Fields + +- `code::String`: catalogue's single character identifier. +- `name::String`: catalogue's name. + +!!! reference + The format is described in https://minorplanetcenter.net/iau/info/CatalogueCodes.html. +""" +@auto_hash_equals struct CatalogueMPC + code::String + name::String + # Inner constructor + function CatalogueMPC(code::String, name::String) + return new(code, name) + end +end + +@doc raw""" + unknowncat() + +Return a `CatalogueMPC` with no code or name. +""" +function unknowncat() + return CatalogueMPC("", "") +end + +@doc raw""" + isunknown(m::CatalogueMPC) + +Check whether `m` equals `unknowncat()`. +""" +function isunknown(m::CatalogueMPC) + return m == unknowncat() +end + +# Print method for CatalogueMPC +# Examples: +# Unknown catalogue +# USNO-A1.0 [a] +function show(io::IO, m::CatalogueMPC) + if isunknown(m) + print(io, "Unknown catalogue") + else + print(io, m.name, " [", m.code, "]") + end +end + +neoparse(x::RegexMatch, i::Int, ::Type{String}) = String(strip(x[i])) + +@doc raw""" + CatalogueMPC(m::RegexMatch) + +Convert a match of `NEOs.CATALOGUE_MPC_REGEX` to `CatalogueMPC`. +""" +function CatalogueMPC(m::RegexMatch) + # Check that matched regex is correct + @assert m.regex == CATALOGUE_MPC_REGEX "Only matches of `NEOs.CATALOGUE_MPC_REGEX` can be converted to `CatalogueMPC`." + # Field types + types = fieldtypes(CatalogueMPC) + # CatalogueMPC fields + args = map(i -> neoparse(m, i, types[i]), 1:length(types)) + + return CatalogueMPC(args...) +end + +@doc raw""" + read_catalogues_mpc(s::String) + +Return the matches of `NEOs.CATALOGUE_MPC_REGEX` in `s` as `Vector{CatalogueMPC}`. +`s` can be either a filename or a text. +""" +function read_catalogues_mpc(s::String) + if !contains(s, "\n") && isfile(s) + # Read MPC formatted file + s = String(read(s)) + end + # Remove header + s = replace(s, CATALOGUES_MPC_HEADER => "") + # Vector of MPC catalogues + cats = Vector{CatalogueMPC}(undef, 0) + # Iterate over the matches + for m in eachmatch(CATALOGUE_MPC_REGEX, s) + push!(cats, CatalogueMPC(m)) + end + # Eliminate repeated entries + unique!(cats) + + return cats +end + +# Convert `cat` to a string according to MPC format. +function string(cat::CatalogueMPC) + if isunknown(cat) + return "" + else + # Code string + code_s = string(" ", cat.code, " ") + # Join everything + cat_s = string(code_s, cat.name) + + return cat_s + end +end + +@doc raw""" + write_catalogues_mpc(cats::Vector{CatalogueMPC}, filename::String) + +Write `cats` to `filename` in MPC format. +""" +function write_catalogues_mpc(cats::Vector{CatalogueMPC}, filename::String) + open(filename, "w") do file + # Header + write(file, CATALOGUES_MPC_HEADER, "\n") + # Write observatories + for i in eachindex(cats) + line = string(cats[i]) + write(file, line, "\n") + end + end +end + +@doc raw""" + download_scratch(url::String, filename::String; connect_timeout = 180, readtimeout = 180) + +Download `url` and save the output to NEOs scratch space as `filename`. Return the local +path and the contents of the file as a `String`. +""" +function download_scratch(url::String, filename::String; connect_timeout = 180, readtimeout = 180) + # Local file + path = joinpath(scratch_path[], filename) + # Get raw html (HTTP.get retries four times by default) + resp = get(url; connect_timeout, readtimeout) + # Read local file + txt = String(resp.body) + + return path, txt +end + +@doc raw""" + update_catalogues_mpc() + +Update the local catalogues file. +""" +function update_catalogues_mpc() + # Download and read catalogues file + CatalogueCodes_path, txt = download_scratch(CATALOGUES_MPC_URL, "CatalogueCodes.txt") + # Parse catalogues + cats = read_catalogues_mpc(txt) + # Write catalogues to local file + write_catalogues_mpc(cats, CatalogueCodes_path) + # Update global variable + global CATALOGUES_MPC[] = read_catalogues_mpc(CatalogueCodes_path) + + return nothing +end + +@doc raw""" + search_cat_code(catcode::String) + +Return the catalogue in `NEOs.CATALOGUES_MPC` that matches `catcode`. +""" +function search_cat_code(catcode::String) + + # Find indexes in mpc_catalogues that match catcode + idxs = findall(x -> x.code == catcode, CATALOGUES_MPC[]) + L_i = length(idxs) + + # No catalog matches catcode + if L_i == 0 + catalogue = unknowncat() + # Exactly one catalogue matches catcode + else + catalogue = CATALOGUES_MPC[][idxs[1]] + # More than one catalogue matches catcode + if L_i > 1 + @warn("""More than one catalogue $(CATALOGUES_MPC[][idxs]) has code $catcode, + selecting first: $(catalogue.name)""") + end + end + + return catalogue + end \ No newline at end of file diff --git a/src/observations/jpl_eph.jl b/src/observations/jpl_eph.jl old mode 100755 new mode 100644 index dd797500..88ad4938 --- a/src/observations/jpl_eph.jl +++ b/src/observations/jpl_eph.jl @@ -1,157 +1,157 @@ -# Load TT-TDB (ttmtdb) from jld2 file -@doc raw""" - loadjpleph() - -Load JPL ephemerides (NAIF IDs, DE430 TT-TDB and ephemerides, #197 and #199 solutions for -Apophis). - -See also [`SPICE.furnsh`](@ref). -""" -function loadjpleph() - furnsh( - # JPL DE430 TT-TDB - joinpath(artifact"TTmTDBde430", "TTmTDB.de430.19feb2015.bsp"), - # JPL DE430 ephemerides - joinpath(artifact"de430", "de430_1850-2150.bsp"), - # JPL #197 solution for Apophis - joinpath(artifact"a99942", "a99942_s197.bsp"), - # JPL #199 solution for Apophis - joinpath(artifact"a99942", "a99942_s199.bsp"), - ) -end - -@doc raw""" - getposvel(target::Int, observer::Int, et) - -Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) at -TDB instant `et` from SPK-formatted ephemeris file with respect to J2000 frame. - -See also [`SPICE.spkgeo`](@ref). -""" -function getposvel(target::Int, observer::Int, et) - return spkgeo(target, et, "J2000", observer)[1] # units: km,km/sec -end - -# NAIF IDs: -# 0: Solar System Barycenter -# 10: Sun (heliocenter) -# 2099942: Apophis -# 399: Earth (geocenter) -# 301: Moon -# 1000000001 from body 1000000000: TT-TDB -# Here, we follow the convention from the CSPICE, library, that the ephemeris -# time is referred to the J2000 frame epoch: -# https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/spk.html#Terminology -# argument `et` represents "ephemeris seconds" (TDB seconds) since J2000.0 TDB epoch -# position and velocity are assumed to be returned in km, km/sec, resp., by spkgeo -# https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/spkgeo_c.html (see: Detailed ouput section) - -@doc raw""" - sunposvel(et) - -Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) -of the Sun at TDB instant `et` with respect to J2000 frame. - -See also [`getposvel`](@ref). -""" -sunposvel(et) = getposvel(10, 0, cte(et)) # units: km, km/second - -@doc raw""" - earthposvel(et) - -Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) -of the Earth at TDB instant `et` with respect to J2000 frame. - -See also [`getposvel`](@ref). -""" -earthposvel(et) = getposvel(399, 0, cte(et)) # units: km, km/second - -@doc raw""" - moonposvel(et) - -Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) -of the Moon at TDB instant `et` with respect to J2000 frame. - -See also [`getposvel`](@ref). -""" -moonposvel(et) = getposvel(301, 0, cte(et)) # units: km, km/second - -@doc raw""" - apophisposvel197(et) - -Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) -of Apophis at TDB instant `et` from JPL #197 solution with respect to J2000 frame. - -See also [`getposvel`](@ref). -""" -apophisposvel197(et) = getposvel(9904406, 0, cte(et)) # units: km, km/second - -@doc raw""" - apophisposvel199(et) - -Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) -of Apophis at TDB instant `et` from JPL #199 solution with respect to J2000 frame. - -See also [`getposvel`](@ref). -""" -apophisposvel199(et) = getposvel(2099942, 0, cte(et)) # units: km, km/second - -@doc raw""" - tt_tdb(et) - -Return the difference TT-TDB (in units of sec) at TDB instant `et` with respect to J2000 -frame. - -See also [`getposvel`](@ref). -""" -tt_tdb(et) = getposvel(1000000001, 1000000000, cte(et))[1] # units: seconds - -@doc raw""" - dtt_tdb(et) - -Return the rate of change of TT-TDB (in units of sec/sec) at TDB instant `et` with respect -to J2000 frame. - -See also [`getposvel`](@ref). -""" -dtt_tdb(et) = getposvel(1000000001, 1000000000, cte(et))[4] # units: seconds/seconds - -@doc raw""" - loadpeeph(eph::TaylorInterpolant = sseph, t_0::T = sseph.t0, - t_f::S = sseph.t0 + sseph.t[end]) where {T, S <: Real} - -Load ephemeris produced by `PlanetaryEphemeris.jl` in timerange `[t_0, t_f] ⊆ [0.0, 36525.0]` -where `t` must have units of TDB days since J2000. The available options for `eph` are: - -- `NEOs.sseph`: Solar system ephemeris. -- `NEOs.acceph`: accelerations ephemeris. -- `NEOs.poteph`: newtonian potentials ephemeris. - -!!! warning - Running this function for the first time will download the `sseph_p100` artifact (885 MB) - which can take several minutes. -""" -function loadpeeph(eph::TaylorInterpolant = sseph, t_0::T = sseph.t0, - t_f::S = sseph.t0 + sseph.t[end]) where {T, S <: Real} - @assert 0.0 ≤ t_0 ≤ t_f ≤ 36525.0 - i_0 = searchsortedlast(eph.t, t_0) - i_f = searchsortedfirst(eph.t, t_f) - return TaylorInterpolant(eph.t0, eph.t[i_0:i_f], eph.x[i_0:i_f-1, :]) -end - -@doc raw""" - bwdfwdeph(et::U, bwd::TaylorInterpolant, fwd::TaylorInterpolant) where {U <: Number} - -Paste a backward and a forward integration, evaluate at `et` and convert from -[au, au/day] -> [km, km/sec]. -""" -function bwdfwdeph(et::U, bwd::TaylorInterpolant, fwd::TaylorInterpolant) where {U <: Number} - @assert bwd.t0 == fwd.t0 "Backward and forward initial times must match" - t = et/daysec - t0 = bwd.t0 - if t <= t0 - return auday2kmsec(bwd(t)) - else - return auday2kmsec(fwd(t)) - end -end +# Load TT-TDB (ttmtdb) from jld2 file +@doc raw""" + loadjpleph() + +Load JPL ephemerides (NAIF IDs, DE430 TT-TDB and ephemerides, #197 and #199 solutions for +Apophis). + +See also [`SPICE.furnsh`](@ref). +""" +function loadjpleph() + furnsh( + # JPL DE430 TT-TDB + joinpath(artifact"TTmTDBde430", "TTmTDB.de430.19feb2015.bsp"), + # JPL DE430 ephemerides + joinpath(artifact"de430", "de430_1850-2150.bsp"), + # JPL #197 solution for Apophis + joinpath(artifact"a99942", "a99942_s197.bsp"), + # JPL #199 solution for Apophis + joinpath(artifact"a99942", "a99942_s199.bsp"), + ) +end + +@doc raw""" + getposvel(target::Int, observer::Int, et) + +Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) at +TDB instant `et` from SPK-formatted ephemeris file with respect to J2000 frame. + +See also [`SPICE.spkgeo`](@ref). +""" +function getposvel(target::Int, observer::Int, et) + return spkgeo(target, et, "J2000", observer)[1] # units: km,km/sec +end + +# NAIF IDs: +# 0: Solar System Barycenter +# 10: Sun (heliocenter) +# 2099942: Apophis +# 399: Earth (geocenter) +# 301: Moon +# 1000000001 from body 1000000000: TT-TDB +# Here, we follow the convention from the CSPICE, library, that the ephemeris +# time is referred to the J2000 frame epoch: +# https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/spk.html#Terminology +# argument `et` represents "ephemeris seconds" (TDB seconds) since J2000.0 TDB epoch +# position and velocity are assumed to be returned in km, km/sec, resp., by spkgeo +# https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/spkgeo_c.html (see: Detailed ouput section) + +@doc raw""" + sunposvel(et) + +Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) +of the Sun at TDB instant `et` with respect to J2000 frame. + +See also [`getposvel`](@ref). +""" +sunposvel(et) = getposvel(10, 0, cte(et)) # units: km, km/second + +@doc raw""" + earthposvel(et) + +Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) +of the Earth at TDB instant `et` with respect to J2000 frame. + +See also [`getposvel`](@ref). +""" +earthposvel(et) = getposvel(399, 0, cte(et)) # units: km, km/second + +@doc raw""" + moonposvel(et) + +Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) +of the Moon at TDB instant `et` with respect to J2000 frame. + +See also [`getposvel`](@ref). +""" +moonposvel(et) = getposvel(301, 0, cte(et)) # units: km, km/second + +@doc raw""" + apophisposvel197(et) + +Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) +of Apophis at TDB instant `et` from JPL #197 solution with respect to J2000 frame. + +See also [`getposvel`](@ref). +""" +apophisposvel197(et) = getposvel(9904406, 0, cte(et)) # units: km, km/second + +@doc raw""" + apophisposvel199(et) + +Return the `[x, y, z, v_x, v_y, v_z]` state vector (in units of km, km/sec) +of Apophis at TDB instant `et` from JPL #199 solution with respect to J2000 frame. + +See also [`getposvel`](@ref). +""" +apophisposvel199(et) = getposvel(2099942, 0, cte(et)) # units: km, km/second + +@doc raw""" + tt_tdb(et) + +Return the difference TT-TDB (in units of sec) at TDB instant `et` with respect to J2000 +frame. + +See also [`getposvel`](@ref). +""" +tt_tdb(et) = getposvel(1000000001, 1000000000, cte(et))[1] # units: seconds + +@doc raw""" + dtt_tdb(et) + +Return the rate of change of TT-TDB (in units of sec/sec) at TDB instant `et` with respect +to J2000 frame. + +See also [`getposvel`](@ref). +""" +dtt_tdb(et) = getposvel(1000000001, 1000000000, cte(et))[4] # units: seconds/seconds + +@doc raw""" + loadpeeph(eph::TaylorInterpolant = sseph, t_0::T = sseph.t0, + t_f::S = sseph.t0 + sseph.t[end]) where {T, S <: Real} + +Load ephemeris produced by `PlanetaryEphemeris.jl` in timerange `[t_0, t_f] ⊆ [0.0, 36525.0]` +where `t` must have units of TDB days since J2000. The available options for `eph` are: + +- `NEOs.sseph`: Solar system ephemeris. +- `NEOs.acceph`: accelerations ephemeris. +- `NEOs.poteph`: newtonian potentials ephemeris. + +!!! warning + Running this function for the first time will download the `sseph_p100` artifact (885 MB) + which can take several minutes. +""" +function loadpeeph(eph::TaylorInterpolant = sseph, t_0::T = sseph.t0, + t_f::S = sseph.t0 + sseph.t[end]) where {T, S <: Real} + @assert 0.0 ≤ t_0 ≤ t_f ≤ 36525.0 + i_0 = searchsortedlast(eph.t, t_0) + i_f = searchsortedfirst(eph.t, t_f) + return TaylorInterpolant(eph.t0, eph.t[i_0:i_f], eph.x[i_0:i_f-1, :]) +end + +@doc raw""" + bwdfwdeph(et::U, bwd::TaylorInterpolant, fwd::TaylorInterpolant) where {U <: Number} + +Paste a backward and a forward integration, evaluate at `et` and convert from +[au, au/day] -> [km, km/sec]. +""" +function bwdfwdeph(et::U, bwd::TaylorInterpolant, fwd::TaylorInterpolant) where {U <: Number} + @assert bwd.t0 == fwd.t0 "Backward and forward initial times must match" + t = et/daysec + t0 = bwd.t0 + if t <= t0 + return auday2kmsec(bwd(t)) + else + return auday2kmsec(fwd(t)) + end +end diff --git a/src/observations/observatory_mpc.jl b/src/observations/observatory_mpc.jl old mode 100755 new mode 100644 index 89ef2932..d0be2709 --- a/src/observations/observatory_mpc.jl +++ b/src/observations/observatory_mpc.jl @@ -1,294 +1,294 @@ -@doc raw""" - ObservatoryMPC{T <: AbstractFloat} - -An observatory in MPC format. - -# Fields - -- `code::String`: observatory's three character identifier. -- `long::T`, `cos::T`, `sin::T`: - - For ground-based observatories: longitude [degrees east of Greenwich], - `ρ*cos(ϕ')` and `ρ*sin(ϕ')`, where `ϕ'` is the geocentric latitude and - `ρ` is the geocentric distance in earth radii. - - For space-based observatories: `x`, `y` and `z` geocentric coordinates. -- `name::String`: observatory's name. -- `date::DateTime`: time of observation (for `:satellite`/`:occultation` observatories). -- `type::Symbol`: `:ground`, `:satellite` or `:occultation`. -- `units::Int`: whether position is encrypted in AU (1) or KM (2). - -!!! reference - The format is described in https://minorplanetcenter.net/iau/lists/ObsCodesF.html. -""" -struct ObservatoryMPC{T <: AbstractFloat} - code::String - long::T - cos::T - sin::T - name::String - date::DateTime - type::Symbol - units::Int - # Inner constructor - function ObservatoryMPC{T}(code::String, long::T, cos::T, sin::T, name::String, date::DateTime = DateTime(2000, 1, 1), - type::Symbol = :ground, units::Int = 0) where {T <: AbstractFloat} - return new{T}(code, long, cos, sin, name, date, type, units) - end -end - -# Outer constructor -function ObservatoryMPC(code::String, long::T, cos::T, sin::T, name::String, date::DateTime = DateTime(2000, 1, 1), - type::Symbol = :ground, units::Int = 0) where {T <: AbstractFloat} - return ObservatoryMPC{T}(code, long, cos, sin, name, date, type, units) -end - -# TO DO: This could be done with a more recent version of AutoHasEquals -function Base.hash(x::ObservatoryMPC{T}, h::UInt) where {T <: AbstractFloat} - Base.hash(x.code, Base.hash(:(ObservatoryMPC{T}), h)) -end -function Base.isequal(a::ObservatoryMPC{T}, b::ObservatoryMPC{T}) where {T <: AbstractFloat} - Base.isequal(a.code, b.code) -end -# Returns `false` if any two fields compare as false; otherwise, `missing` if at least -# one comparison is missing. Otherwise `true`. -# This matches the semantics of `==` for Tuple's and NamedTuple's. -function Base.:(==)(a::ObservatoryMPC{T}, b::ObservatoryMPC{T}) where {T <: AbstractFloat} - found_missing = false - cmp = a.code == b.code - cmp === false && return false - if ismissing(cmp) - found_missing = true - end - found_missing && return missing - return true -end - -@doc raw""" - unknownobs() - -Return a `ObservatoryMPC` with no code, coordinates or name. -""" -unknownobs() = ObservatoryMPC("", NaN, NaN, NaN, "") - -@doc raw""" - isunknown(m::ObservatoryMPC{T}) where {T <: AbstractFloat} - -Check whether `m` equals `unknownobs()`. -""" -function isunknown(m::ObservatoryMPC{T}) where {T <: AbstractFloat} - return m == unknownobs() -end - -isground(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :ground -issatellite(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :satellite -isoccultation(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :occultation - -@doc raw""" - hascoord(m::ObservatoryMPC{T}) where {T <: AbstractFloat} - -Check whether `m` has non `NaN` coordinates. -""" -function hascoord(m::ObservatoryMPC{T}) where {T <: AbstractFloat} - return !isnan(m.long) && !isnan(m.cos) && !isnan(m.sin) -end - -# Print method for ObservatoryMPC -# Examples: -# Unknown observatory -# Spitzer Space Telescope [245] -# Greenwich [000] long: 0.0 cos: 0.62411 sin: 0.77873 -function show(io::IO, m::ObservatoryMPC{T}) where {T <: AbstractFloat} - if isunknown(m) - print(io, "Unknown observatory") - elseif isground(m) - print(io, m.name, " [", m.code, "] long: ", m.long, " cos: ", m.cos, " sin: ", m.sin) - else - print(io, m.name, " [", m.code, "]") - end -end - -function neoparse(x::RegexMatch, i::Int, ::Type{Float64}) - y = tryparse(Float64, replace(x[i], " " => "")) - if isnothing(y) - return NaN - else - return y - end -end - -@doc raw""" - ObservatoryMPC(m::RegexMatch) - -Convert a match of `NEOs.OBSERVATORY_MPC_REGEX` to `ObservatoryMPC`. -""" -function ObservatoryMPC(m::RegexMatch) - # Check that matched regex is correct - @assert m.regex == OBSERVATORY_MPC_REGEX "Only matches of `NEOs.OBSERVATORY_MPC_REGEX` can be converted to `ObservatoryMPC`." - # Field types - types = fieldtypes(ObservatoryMPC{Float64}) - # ObservatoryMPC{Float64} fields - args = map(i -> neoparse(m, i, types[i]), 1:5) - - if isnan(args[2]) && isnan(args[3]) && isnan(args[4]) - return ObservatoryMPC(args..., DateTime(2000, 1, 1), :satellite, 0) - else - return ObservatoryMPC(args...) - end -end - -@doc raw""" - read_observatories_mpc(s::String) - -Return the matches of `NEOs.OBSERVATORY_MPC_REGEX` in `s` as `Vector{ObservatoryMPC{Float64}}`. -`s` can be either a filename or a text. -""" -function read_observatories_mpc(s::String) - if !contains(s, "\n") && isfile(s) - # Read MPC formatted file - s = String(read(s)) - end - # Remove header - s = replace(s, OBSERVATORIES_MPC_HEADER => "") - # Vector of MPC observatories - obs = Vector{ObservatoryMPC{Float64}}(undef, 0) - # Iterate over the matches - for m in eachmatch(OBSERVATORY_MPC_REGEX, s) - push!(obs, ObservatoryMPC(m)) - end - # Eliminate repeated entries - unique!(obs) - - return obs -end - -@doc raw""" - mpc_long_str(x::T) where {T <: AbstractFloat} - -Convert `x` to a string according to the `long` field in MPC format. -""" -function mpc_long_str(x::T) where {T <: AbstractFloat} - # NaN => empty string - if isnan(x) - long_s = repeat(" ", 10) - else - long_s = @sprintf("%3.5f", x) - long_s = lpad(long_s, 10) - end - return long_s -end - -@doc raw""" - mpc_cos_str(x::T) where {T <: AbstractFloat} - -Convert `x` to a string according to the `cos` field in MPC format. -""" -function mpc_cos_str(x::T) where {T <: AbstractFloat} - # NaN => empty string - if isnan(x) - cos_s = repeat(" ", 8) - else - cos_s = @sprintf("%1.6f", x) - end - return cos_s -end - -@doc raw""" - mpc_sin_str(x::T) where {T <: AbstractFloat} - -Convert `x` to a string according to the `sin` field in MPC format. -""" -function mpc_sin_str(x::T) where {T <: AbstractFloat} - # NaN => empty string - if isnan(x) - sin_s = repeat(" ", 9) - else - sin_s = @sprintf("%1.6f", abs(x)) - if x ≥ 0 - sin_s = string("+", sin_s) - else - sin_s = string("-", sin_s) - end - end - - return sin_s -end - -# Convert `obs` to a string according to MPC format. -function string(obs::ObservatoryMPC{T}) where {T <: AbstractFloat} - if isunknown(obs) - return "" - else - # Longitude string - long_s = mpc_long_str(obs.long) - # Cosine string - cos_s = mpc_cos_str(obs.cos) - # Sine string string - sin_s = mpc_sin_str(obs.sin) - # Join everything - obs_s = string(obs.code, long_s, cos_s, sin_s, obs.name) - end - - return obs_s -end - -@doc raw""" - write_observatories_mpc(obs::Vector{ObservatoryMPC{T}}, filename::String) where {T <: AbstractFloat} - -Write `obs` to `filename` in MPC format. -""" -function write_observatories_mpc(obs::Vector{ObservatoryMPC{T}}, filename::String) where {T <: AbstractFloat} - open(filename, "w") do file - # Header - write(file, OBSERVATORIES_MPC_HEADER, "\n") - # Write observatories - for i in eachindex(obs) - line = string(obs[i]) - write(file, line, "\n") - end - end -end - -@doc raw""" - update_observatories_mpc() - -Update the local observatories file. -""" -function update_observatories_mpc() - # Download and read observatories file - ObsCodes_path, txt = download_scratch(OBSERVATORIES_MPC_URL, "ObsCodes.txt") - # Parse observatories - obs = read_observatories_mpc(txt) - # Write observatories to local file - write_observatories_mpc(obs, ObsCodes_path) - # Update global variable - global OBSERVATORIES_MPC[] = read_observatories_mpc(ObsCodes_path) - - return nothing -end - -@doc raw""" - search_obs_code(obscode::String) - -Return the observatory in `NEOs.OBSERVATORIES_MPC` that matches `obscode`. -""" -function search_obs_code(obscode::String) - - # Find indexes in OBSERVATORIES_MPC that match obscode - idxs = findall(x -> x.code == obscode, OBSERVATORIES_MPC[]) - L_i = length(idxs) - - # No observatory matches obscode - if L_i == 0 - observatory = unknownobs() - # At least one observatory matches obscode - else - observatory = OBSERVATORIES_MPC[][idxs[1]] - # More than one observatory matches obscode - if L_i > 1 - @warn("""More than one observatory $(OBSERVATORIES_MPC[][idxs]) has code $obscode, - selecting first: $(observatory.name)""") - end - end - - return observatory - +@doc raw""" + ObservatoryMPC{T <: AbstractFloat} + +An observatory in MPC format. + +# Fields + +- `code::String`: observatory's three character identifier. +- `long::T`, `cos::T`, `sin::T`: + - For ground-based observatories: longitude [degrees east of Greenwich], + `ρ*cos(ϕ')` and `ρ*sin(ϕ')`, where `ϕ'` is the geocentric latitude and + `ρ` is the geocentric distance in earth radii. + - For space-based observatories: `x`, `y` and `z` geocentric coordinates. +- `name::String`: observatory's name. +- `date::DateTime`: time of observation (for `:satellite`/`:occultation` observatories). +- `type::Symbol`: `:ground`, `:satellite` or `:occultation`. +- `units::Int`: whether position is encrypted in AU (1) or KM (2). + +!!! reference + The format is described in https://minorplanetcenter.net/iau/lists/ObsCodesF.html. +""" +struct ObservatoryMPC{T <: AbstractFloat} + code::String + long::T + cos::T + sin::T + name::String + date::DateTime + type::Symbol + units::Int + # Inner constructor + function ObservatoryMPC{T}(code::String, long::T, cos::T, sin::T, name::String, date::DateTime = DateTime(2000, 1, 1), + type::Symbol = :ground, units::Int = 0) where {T <: AbstractFloat} + return new{T}(code, long, cos, sin, name, date, type, units) + end +end + +# Outer constructor +function ObservatoryMPC(code::String, long::T, cos::T, sin::T, name::String, date::DateTime = DateTime(2000, 1, 1), + type::Symbol = :ground, units::Int = 0) where {T <: AbstractFloat} + return ObservatoryMPC{T}(code, long, cos, sin, name, date, type, units) +end + +# TO DO: This could be done with a more recent version of AutoHasEquals +function Base.hash(x::ObservatoryMPC{T}, h::UInt) where {T <: AbstractFloat} + Base.hash(x.code, Base.hash(:(ObservatoryMPC{T}), h)) +end +function Base.isequal(a::ObservatoryMPC{T}, b::ObservatoryMPC{T}) where {T <: AbstractFloat} + Base.isequal(a.code, b.code) +end +# Returns `false` if any two fields compare as false; otherwise, `missing` if at least +# one comparison is missing. Otherwise `true`. +# This matches the semantics of `==` for Tuple's and NamedTuple's. +function Base.:(==)(a::ObservatoryMPC{T}, b::ObservatoryMPC{T}) where {T <: AbstractFloat} + found_missing = false + cmp = a.code == b.code + cmp === false && return false + if ismissing(cmp) + found_missing = true + end + found_missing && return missing + return true +end + +@doc raw""" + unknownobs() + +Return a `ObservatoryMPC` with no code, coordinates or name. +""" +unknownobs() = ObservatoryMPC("", NaN, NaN, NaN, "") + +@doc raw""" + isunknown(m::ObservatoryMPC{T}) where {T <: AbstractFloat} + +Check whether `m` equals `unknownobs()`. +""" +function isunknown(m::ObservatoryMPC{T}) where {T <: AbstractFloat} + return m == unknownobs() +end + +isground(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :ground +issatellite(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :satellite +isoccultation(m::ObservatoryMPC{T}) where {T <: AbstractFloat} = m.type == :occultation + +@doc raw""" + hascoord(m::ObservatoryMPC{T}) where {T <: AbstractFloat} + +Check whether `m` has non `NaN` coordinates. +""" +function hascoord(m::ObservatoryMPC{T}) where {T <: AbstractFloat} + return !isnan(m.long) && !isnan(m.cos) && !isnan(m.sin) +end + +# Print method for ObservatoryMPC +# Examples: +# Unknown observatory +# Spitzer Space Telescope [245] +# Greenwich [000] long: 0.0 cos: 0.62411 sin: 0.77873 +function show(io::IO, m::ObservatoryMPC{T}) where {T <: AbstractFloat} + if isunknown(m) + print(io, "Unknown observatory") + elseif isground(m) + print(io, m.name, " [", m.code, "] long: ", m.long, " cos: ", m.cos, " sin: ", m.sin) + else + print(io, m.name, " [", m.code, "]") + end +end + +function neoparse(x::RegexMatch, i::Int, ::Type{Float64}) + y = tryparse(Float64, replace(x[i], " " => "")) + if isnothing(y) + return NaN + else + return y + end +end + +@doc raw""" + ObservatoryMPC(m::RegexMatch) + +Convert a match of `NEOs.OBSERVATORY_MPC_REGEX` to `ObservatoryMPC`. +""" +function ObservatoryMPC(m::RegexMatch) + # Check that matched regex is correct + @assert m.regex == OBSERVATORY_MPC_REGEX "Only matches of `NEOs.OBSERVATORY_MPC_REGEX` can be converted to `ObservatoryMPC`." + # Field types + types = fieldtypes(ObservatoryMPC{Float64}) + # ObservatoryMPC{Float64} fields + args = map(i -> neoparse(m, i, types[i]), 1:5) + + if isnan(args[2]) && isnan(args[3]) && isnan(args[4]) + return ObservatoryMPC(args..., DateTime(2000, 1, 1), :satellite, 0) + else + return ObservatoryMPC(args...) + end +end + +@doc raw""" + read_observatories_mpc(s::String) + +Return the matches of `NEOs.OBSERVATORY_MPC_REGEX` in `s` as `Vector{ObservatoryMPC{Float64}}`. +`s` can be either a filename or a text. +""" +function read_observatories_mpc(s::String) + if !contains(s, "\n") && isfile(s) + # Read MPC formatted file + s = String(read(s)) + end + # Remove header + s = replace(s, OBSERVATORIES_MPC_HEADER => "") + # Vector of MPC observatories + obs = Vector{ObservatoryMPC{Float64}}(undef, 0) + # Iterate over the matches + for m in eachmatch(OBSERVATORY_MPC_REGEX, s) + push!(obs, ObservatoryMPC(m)) + end + # Eliminate repeated entries + unique!(obs) + + return obs +end + +@doc raw""" + mpc_long_str(x::T) where {T <: AbstractFloat} + +Convert `x` to a string according to the `long` field in MPC format. +""" +function mpc_long_str(x::T) where {T <: AbstractFloat} + # NaN => empty string + if isnan(x) + long_s = repeat(" ", 10) + else + long_s = @sprintf("%3.5f", x) + long_s = lpad(long_s, 10) + end + return long_s +end + +@doc raw""" + mpc_cos_str(x::T) where {T <: AbstractFloat} + +Convert `x` to a string according to the `cos` field in MPC format. +""" +function mpc_cos_str(x::T) where {T <: AbstractFloat} + # NaN => empty string + if isnan(x) + cos_s = repeat(" ", 8) + else + cos_s = @sprintf("%1.6f", x) + end + return cos_s +end + +@doc raw""" + mpc_sin_str(x::T) where {T <: AbstractFloat} + +Convert `x` to a string according to the `sin` field in MPC format. +""" +function mpc_sin_str(x::T) where {T <: AbstractFloat} + # NaN => empty string + if isnan(x) + sin_s = repeat(" ", 9) + else + sin_s = @sprintf("%1.6f", abs(x)) + if x ≥ 0 + sin_s = string("+", sin_s) + else + sin_s = string("-", sin_s) + end + end + + return sin_s +end + +# Convert `obs` to a string according to MPC format. +function string(obs::ObservatoryMPC{T}) where {T <: AbstractFloat} + if isunknown(obs) + return "" + else + # Longitude string + long_s = mpc_long_str(obs.long) + # Cosine string + cos_s = mpc_cos_str(obs.cos) + # Sine string string + sin_s = mpc_sin_str(obs.sin) + # Join everything + obs_s = string(obs.code, long_s, cos_s, sin_s, obs.name) + end + + return obs_s +end + +@doc raw""" + write_observatories_mpc(obs::Vector{ObservatoryMPC{T}}, filename::String) where {T <: AbstractFloat} + +Write `obs` to `filename` in MPC format. +""" +function write_observatories_mpc(obs::Vector{ObservatoryMPC{T}}, filename::String) where {T <: AbstractFloat} + open(filename, "w") do file + # Header + write(file, OBSERVATORIES_MPC_HEADER, "\n") + # Write observatories + for i in eachindex(obs) + line = string(obs[i]) + write(file, line, "\n") + end + end +end + +@doc raw""" + update_observatories_mpc() + +Update the local observatories file. +""" +function update_observatories_mpc() + # Download and read observatories file + ObsCodes_path, txt = download_scratch(OBSERVATORIES_MPC_URL, "ObsCodes.txt") + # Parse observatories + obs = read_observatories_mpc(txt) + # Write observatories to local file + write_observatories_mpc(obs, ObsCodes_path) + # Update global variable + global OBSERVATORIES_MPC[] = read_observatories_mpc(ObsCodes_path) + + return nothing +end + +@doc raw""" + search_obs_code(obscode::String) + +Return the observatory in `NEOs.OBSERVATORIES_MPC` that matches `obscode`. +""" +function search_obs_code(obscode::String) + + # Find indexes in OBSERVATORIES_MPC that match obscode + idxs = findall(x -> x.code == obscode, OBSERVATORIES_MPC[]) + L_i = length(idxs) + + # No observatory matches obscode + if L_i == 0 + observatory = unknownobs() + # At least one observatory matches obscode + else + observatory = OBSERVATORIES_MPC[][idxs[1]] + # More than one observatory matches obscode + if L_i > 1 + @warn("""More than one observatory $(OBSERVATORIES_MPC[][idxs]) has code $obscode, + selecting first: $(observatory.name)""") + end + end + + return observatory + end \ No newline at end of file diff --git a/src/observations/process_radar.jl b/src/observations/process_radar.jl old mode 100755 new mode 100644 index 7c77080d..a0e9f373 --- a/src/observations/process_radar.jl +++ b/src/observations/process_radar.jl @@ -1,620 +1,620 @@ -include("catalogue_mpc.jl") -include("observatory_mpc.jl") -include("radec_mpc.jl") -include("radar_jpl.jl") -include("units.jl") -include("jpl_eph.jl") -include("topocentric.jl") -include("tracklet.jl") -include("process_radec.jl") - -@doc raw""" - shapiro_delay(e, p, q) - -Return the relativistic (Shapiro) time-delay in seconds -```math -\Delta\tau[\text{rel}] = \frac{2\mu_\odot}{c^3}\log\left|\frac{d_{E,S} + d_{A,S} + d_{A,E}}{d_{E,S}+d_{A,S}-d_{A, E}}\right|, -``` -where ``\mu_\odot = GM_\odot`` is the gravitational parameter of the sun, and ``d_{E,S}``, ``d_{A,S}`` -and ``d_{A,E}`` are the heliocentric distance of the Earth, the asteroid's heliocentric -distance, and the asteroid's geocentric distance, respectively. - -# Arguments - -- `e`: heliocentric distance of the Earth. -- `p`: asteroid's heliocentric distance. -- `q`: asteroid's geocentric distance. - -!!! reference - See https://doi.org/10.1103/PhysRevLett.13.789. -""" -function shapiro_delay(e, p, q) - shap = 0.0 # 2μ[1]/(c_au_per_day^2) - shap_del_days = (2μ_DE430[su]/(c_au_per_day^3))*log( (e+p+q+shap)/(e+p-q+shap) ) # days - return shap_del_days*daysec # seconds -end - -@doc raw""" - shapiro_doppler(e, de, p, dp, q, dq, F_tx) - -Return the Doppler shift (in units of `F_tx`) -```math -\Delta\nu = -\nu\frac{d\Delta\tau}{dt}, -``` -where ``\nu`` is the frequency and ``\frac{d\Delta\tau}{dt}`` is the differential of the -Shapiro delay. See also [`shapiro_delay`](@ref). - -# Arguments - -- `e`: heliocentric distance of the Earth. -- `de`: differential of `e`. -- `p`: asteroid's heliocentric distance. -- `dp`: differential of `p`. -- `q`: asteroid's geocentric distance. -- `dq`: differential of `q`. -- `F_tx`: transmitter frequency (MHz). - -!!! reference - See https://doi.org/10.1103/PhysRevLett.17.933. -""" -function shapiro_doppler(e, de, p, dp, q, dq, F_tx) - # shap_del_diff = 2μ[1]*( (de+dp+dq)/(e+p+q) - (de+dp-dq)/(e+p-q) )/(c_au_per_day^3) # (adim.) - shap_del_diff = (4μ_DE430[su]/(c_au_per_day^3))*( ( dq*(e+p) - q*(de+dp) )/( (e+p)^2 - q^2 ) ) # differential of Shapiro delay (adim.) - # ν = -F_tx*dτ/dt (units of F_tx) - # See footnote 10 of https://doi.org/10.1103/PhysRevLett.17.933 - shap_dop = -F_tx*shap_del_diff - return shap_dop # (units of F_tx) -end - -@doc raw""" - Ne(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}, ds::U, ΔS::Real) where {S<:Number, U<:Number} - -Return the density of ionized electrons (in electrons/cm^3) in interplanetary medium -```math -N_e = \frac{A}{r^6} + \frac{ab/\sqrt{a^2\sin^2\beta + b^2\cos^2\beta}}{r^2}, -``` -where ``r`` is the heliocentric distance expressed in units of the solar radius, ``\beta`` is -the solar latitude, and ``A``, ``a``, ``b`` are the solar corona parameters. - -# Arguments -- `p1::Vector{S}`: signal departure point (transmitter/bounce) (au). -- `p2::Vector{S}`: signal arrival point (bounce/receiver) (au). -- `r_s_t0::Vector{S}`: Barycentric position (au) of Sun at initial time of propagation of signal path (bounce time for down-leg; transmit time for up-leg). -- `ds::U`: current distance travelled by ray from emission point (au). -- `ΔS::Real`: total distance between p1 and p2 (au). - -!!! reference - See (Explanatory Supplement to the Astronomical Almanac 2014, p. 323, Sec. 8.7.5, Eq. 8.22). - ESAA 2014 in turn refers to Muhleman and Anderson (1981). Ostro (1993) gives a reference to - Anderson (1978), where this model is fitted to Mariner 9 ranging data. Reading - https://gssc.esa.int/navipedia/index.php/Ionospheric_Delay helped a lot to clarify things, - especially the 40.3, although they talk about Earth's ionosphere. Another valuable source is - Standish, E.M., Astron. Astrophys. 233, 252-271 (1990). -""" -function Ne(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}, ds::U, ΔS::Real) where {S<:Number, U<:Number} - # s: linear parametrization of ray path, such that - # s = 0 -> point on ray path is at p1; s = 1 -> point on ray path is at p2 - s = ds/ΔS - # Rescale Taylor polynomial - s_p2_p1 = map(x->s*x, Taylor1.(p2-p1, s.order)) - # Heliocentric position (au) of point on ray path at time t_tdb_jul (Julian days) - r_vec = Taylor1.(p1, s.order) + s_p2_p1 - Taylor1.(r_s_t0, s.order) - # Heliocentric distance (au) of point on ray path at time t_tdb_jul (Julian days) - r = sqrt( r_vec[1]^2 + r_vec[2]^2 + r_vec[3]^2 ) - # Compute heliocentric position vector of point on ray path wrt Sun's rotation pole - # and equator (i.e., heliographic) - α_p_sun_rad = deg2rad(α_p_sun) - δ_p_sun_rad = deg2rad(δ_p_sun) - r_vec_heliographic = inv( pole_rotation(α_p_sun_rad, δ_p_sun_rad) )*r_vec - # Compute heliographic solar latitude (Anderson, 1978) of point on ray path - β = asin( r_vec_heliographic[3]/r ) # Ecliptic solar latitude of point on ray path (rad) - # Heliocentric distance - r_sr = r/R_sun - # First term of Ne - Ne_t1 = (A_sun/r_sr^6) - # Second term of Ne - Ne_t2 = ( (a_sun*b_sun)/sqrt((a_sun*sin(β))^2 + (b_sun*cos(β))^2) )/(r_sr^2) - # Density of ionized electrons - Ne_val = Ne_t1 + Ne_t2 - return Ne_val -end - -# TODO: @taylorize! -@doc raw""" - Ne_path_integral(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}) where {S<:Number} - -Return the path integral of the density of ionized electrons in interplanetary medium ``N_e`` -in units of electrons/cm^2, evaluated with `TaylorIntegration`. - -# Arguments - -- `p1::Vector{S}`: signal departure point (transmitter/bounce) (au). -- `p2::Vector{S}`: signal arrival point (bounce/receiver) (au). -- `r_s_t0::Vector{S}`: Barycentric position (au) of Sun at initial time of propagation of signal path (bounce time for down-leg; transmit time for up-leg). -""" -function Ne_path_integral(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}) where {S<:Number} - # Total distance between p1 and p2, in centimeters - ΔS = (100_000au)*norm(p2-p1) - # Kernel of path integral; distance parameter `s` and total distance `ΔS` is in cm - function int_kernel(x, params, s) - return Ne(p1, p2, r_s_t0, s, ΔS) - end - # Do path integral - - # Initial condition - i0 = zero(p1[1]) - iT = Taylor1(i0, 24) - # Independent variable - tT = Taylor1(24) - # Integration - TaylorIntegration.jetcoeffs!(int_kernel, tT, iT, nothing) - # Evaluate path integral in total distance ΔS - return iT(ΔS) -end - -@doc raw""" - corona_delay(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}, F_tx::U) where {S<:Number, U<:Real} - -Return the time-delay (in sec) due to thin plasma of solar corona -```math -\Delta\tau_\text{cor} = \frac{40.3}{cf^2}\int_{P_1}^{P_2}N_e \ ds, -```math -where ``c`` is the speed of light (cm/sec), ``f`` is the frequency (Hz), ``N_e`` is the density -of ionized electrons in interplanetary medium (electrons/cm^3), and ``s`` is the linear -distance (cm). ``N_e`` is computed by [`Ne`](@ref) and integrated via `TaylorIntegration` in -[`Ne_path_integral`](@ref). - -# Arguments - -- `p1::Vector{S}`: signal departure point (transmitter/bounce for up/down-link, resp.) (au). -- `p2::Vector{S}`: signal arrival point (bounce/receiver for up/down-link, resp.) (au). -- `r_s_t0::Vector{S}`: Barycentric position (au) of Sun at initial time of propagation of signal path (bounce time for down-leg; transmit time for up-leg). -- `F_tx::U`: transmitter frequency (MHz). - -!!! reference - From [Ionospheric Delay](https://gssc.esa.int/navipedia/index.php/Ionospheric_Delay) it seems - that ESAA 2014 text probably should say that in the formula for ``\Delta\tau_\text{cor}``, - the expression ``40.3 N_e/f^2`` is adimensional, where ``Ne`` is in electrons/cm^3 and ``f`` is - in Hz therefore, the integral ``(40.3/f^2)\int Ne \ ds`` is in centimeters, where ``ds`` is in - cm and the expression ``(40.3/(cf^2))\int Ne \ ds``, with ``c`` in cm/sec, is in seconds. -""" -function corona_delay(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}, F_tx::U) where {S<:Number, U<:Real} - # For the time being, we're removing the terms associated with higher-order terms in the - # variationals (ie, Yarkovsky) - int_path = Ne_path_integral(p1, p2, r_s_t0) # (electrons/cm^2) - # Time delay due to solar corona - Δτ_corona = 40.3e-6int_path/(c_cm_per_sec*(F_tx)^2) # seconds - return Δτ_corona # seconds -end - -@doc raw""" - zenith_distance(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Number, S<:Number} - -**VERY** elementary computation of zenith distance. - -# Arguments - -- `r_antenna::Vector{T}`: position of antenna at receive/transmit time in celestial frame wrt geocenter. -- `ρ_vec_ae::Vector{S}`: slant-range vector from antenna to asteroid. -""" -function zenith_distance(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Number, S<:Number} - # Magnitude of geocentric antenna position - norm_r_antenna = sqrt(r_antenna[1]^2 + r_antenna[2]^2 + r_antenna[3]^2) - # Magnitude of slant-range vector from antenna to asteroid - norm_ρ_vec_ae = sqrt(ρ_vec_ae[1]^2 + ρ_vec_ae[2]^2 + ρ_vec_ae[3]^2) - # cos( angle between r_antenna and ρ_vec_ae) - cos_antenna_slant = dot(r_antenna, ρ_vec_ae)/(norm_r_antenna*norm_ρ_vec_ae) - # zenith distance - return acos(cos_antenna_slant) -end - -@doc raw""" - tropo_delay(z) - -Return the time delay (in sec) due to Earth's troposphere for radio frequencies -```math -\Delta\tau_\text{tropo} = \frac{7 \ \text{nsec}}{\cos z + \frac{0.0014}{0.045 + \cot z}}, -``` -where ``z`` is the zenith distance at the antenna. This time delay oscillates between -0.007``\mu``s and 0.225``\mu``s for ``z`` between 0 and ``\pi/2`` rad. - -See also [`zenith_distance`](@doc). - -# Arguments - -- `z`: zenith distance (radians). -""" -tropo_delay(z) = (7e-9)/( cos(z) + 0.0014/(0.045+cot(z)) ) # seconds - -@doc raw""" - tropo_delay(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Number, S<:Number} - -Return the time delay (in sec) due to Earth's troposphere for radio frequencies. The function -first computes the zenith distance ``z`` via [`zenith_distance`](@ref) and then substitutes -into the first method of [`tropo_delay`](@ref). - -# Arguments - -- `r_antenna::Vector{T}`: position of antenna at receive/transmit time in celestial frame wrt geocenter. -- `ρ_vec_ae::Vector{S}`: slant-range vector from antenna to asteroid. -""" -function tropo_delay(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Number, S<:Number} - # zenith distance - zd = zenith_distance(r_antenna, ρ_vec_ae) # rad - # Time delay due to Earth's troposphere - return tropo_delay(zd) # seconds -end - -@doc raw""" - compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; kwargs...) where {T <: AbstractFloat} - -Compute Taylor series expansion of time-delay observable around echo reception time. This -allows to compute dopplers via automatic differentiation using -```math -\nu = -f\frac{d\tau}{dt}, -``` -where ``f`` is the transmitter frequency (MHz) and ``\tau`` is the time-delay at reception -time ``t``. Computed values include corrections due to Earth orientation, LOD and polar -motion. - -**Note:** Works only with `TaylorInterpolant` ephemeris. See [`PlanetaryEphemeris.TaylorInterpolant`](@ref). - -# Arguments - -- `observatory::ObservatoryMPC{T}`: observing station. -- `t_r_utc::DateTime`: UTC time of echo reception. - -# Keyword arguments - -- `tord::Int = 5`: order of Taylor expansions. -- `niter::Int = 10`: number of light-time solution iterations. -- `xve::EarthEph = earthposvel`: Earth ephemeris. -- `xvs::SunEph = sunposvel`: Sun ephemeris. -- `xva::AstEph`: asteroid ephemeris. - -All ephemeris must take [et seconds since J2000] and return [barycentric position in km -and velocity in km/sec]. - -!!! reference - See https://doi.org/10.1086/116062. -""" -function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; tord::Int = 5, - niter::Int = 10, xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, - xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} - - # Transform receiving time from UTC to TDB seconds since j2000 - et_r_secs_0 = datetime2et(t_r_utc) - # Auxiliary to evaluate JT ephemeris - xva1et0 = xva(et_r_secs_0)[1] - # et_r_secs_0 as a Taylor polynomial - et_r_secs = Taylor1([et_r_secs_0,one(et_r_secs_0)].*one(xva1et0), tord) - # Compute geocentric position/velocity of receiving antenna in inertial frame (km, km/sec) - RV_r = obsposvelECI(observatory, et_r_secs) - R_r = RV_r[1:3] - # Earth's barycentric position and velocity at receive time - r_e_t_r = xve(et_r_secs)[1:3] - # Receiver barycentric position and velocity at receive time - r_r_t_r = r_e_t_r + R_r - # Asteroid barycentric position and velocity at receive time - r_a_t_r = xva(et_r_secs)[1:3] - # Sun barycentric position and velocity at receive time - r_s_t_r = xvs(et_r_secs)[1:3] - - # Down-leg iteration - # τ_D first approximation - # See equation (1) of https://doi.org/10.1086/116062 - ρ_vec_r = r_a_t_r - r_r_t_r - ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) - # -R_b/c, but delay is wrt asteroid Center (Brozovic et al., 2018) - τ_D = ρ_r/clightkms # (seconds) - # Bounce time, new estimate - # See equation (2) of https://doi.org/10.1086/116062 - et_b_secs = et_r_secs - τ_D - - # Allocate memmory for time delays - Δτ_D = zero(τ_D) # Total time delay - Δτ_rel_D = zero(τ_D) # Shapiro delay - # Δτ_corona_D = zero(τ_D) # Delay due to Solar corona - Δτ_tropo_D = zero(τ_D) # Delay due to Earth's troposphere - - for i in 1:niter - # Asteroid barycentric position (in au) at bounce time (TDB) - rv_a_t_b = xva(et_b_secs) - r_a_t_b = rv_a_t_b[1:3] - v_a_t_b = rv_a_t_b[4:6] - # Estimated position of the asteroid's center of mass relative to the recieve point - # See equation (3) of https://doi.org/10.1086/116062. - ρ_vec_r = r_a_t_b - r_r_t_r - # Magnitude of ρ_vec_r - # See equation (4) of https://doi.org/10.1086/116062. - ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) - - # Compute down-leg Shapiro delay - # NOTE: when using PPN, substitute 2 -> 1+γ in expressions for Shapiro delay, - # Δτ_rel_[D|U] - - # Earth's position at t_r - e_D_vec = r_r_t_r - r_s_t_r - # Heliocentric distance of Earth at t_r - e_D = sqrt(e_D_vec[1]^2 + e_D_vec[2]^2 + e_D_vec[3]^2) - # Barycentric position of Sun at estimated bounce time - r_s_t_b = xvs(et_b_secs)[1:3] - # Heliocentric position of asteroid at t_b - p_D_vec = r_a_t_b - r_s_t_b - # Heliocentric distance of asteroid at t_b - p_D = sqrt(p_D_vec[1]^2 + p_D_vec[2]^2 + p_D_vec[3]^2) - # Signal path distance (down-leg) - q_D = ρ_r - - # Shapiro correction to time-delay - Δτ_rel_D = shapiro_delay(e_D, p_D, q_D) # seconds - # Troposphere correction to time-delay - Δτ_tropo_D = tropo_delay(R_r, ρ_vec_r) # seconds - # Solar corona correction to time-delay - # Δτ_corona_D = corona_delay(constant_term.(r_a_t_b), r_r_t_r, r_s_t_r, F_tx, station_code) # seconds - # Total time-delay - Δτ_D = Δτ_rel_D # + Δτ_tropo_D #+ Δτ_corona_D # seconds - - # New estimate - p_dot_23 = dot(ρ_vec_r, v_a_t_b)/ρ_r - # Time delay correction - Δt_2 = (τ_D - ρ_r/clightkms - Δτ_rel_D)/(1.0-p_dot_23/clightkms) - # Time delay new estimate - τ_D = τ_D - Δt_2 - # Bounce time, new estimate - # See equation (2) of https://doi.org/10.1086/116062 - et_b_secs = et_r_secs - τ_D - - end - - # Asteroid's barycentric position and velocity at bounce time t_b - rv_a_t_b = xva(et_b_secs) - r_a_t_b = rv_a_t_b[1:3] - v_a_t_b = rv_a_t_b[4:6] - - # Up-leg iteration - # τ_U first estimation - # See equation (5) of https://doi.org/10.1086/116062 - τ_U = τ_D - # Transmit time, 1st estimate - # See equation (6) of https://doi.org/10.1086/116062 - et_t_secs = et_b_secs - τ_U - # Geocentric position and velocity of transmitting antenna in inertial frame (km, km/sec) - RV_t = RV_r(et_t_secs-et_r_secs_0) - R_t = RV_t[1:3] - V_t = RV_t[4:6] - # Barycentric position and velocity of the Earth at transmit time - rv_e_t_t = xve(et_t_secs) - r_e_t_t = rv_e_t_t[1:3] - v_e_t_t = rv_e_t_t[4:6] - # Transmitter barycentric position and velocity of at transmit time - r_t_t_t = r_e_t_t + R_t - # Up-leg vector at transmit time - # See equation (7) of https://doi.org/10.1086/116062 - ρ_vec_t = r_a_t_b - r_t_t_t - # Magnitude of up-leg vector - ρ_t = sqrt(ρ_vec_t[1]^2 + ρ_vec_t[2]^2 + ρ_vec_t[3]^2) - - # Allocate memmory for time delays - Δτ_U = zero(τ_U) # Total time delay - Δτ_rel_U = zero(τ_U) # Shapiro delay - # Δτ_corona_U = zero(τ_U) # Delay due to Solar corona - Δτ_tropo_U = zero(τ_U) # Delay due to Earth's troposphere - - for i in 1:niter - # Geocentric position and velocity of transmitting antenna in inertial frame (km, km/sec) - RV_t = RV_r(et_t_secs-et_r_secs_0) - R_t = RV_t[1:3] - V_t = RV_t[4:6] - # Earth's barycentric position and velocity at transmit time - rv_e_t_t = xve(et_t_secs) - r_e_t_t = rv_e_t_t[1:3] - v_e_t_t = rv_e_t_t[4:6] - # Barycentric position and velocity of the transmitter at the transmit time - r_t_t_t = r_e_t_t + R_t - v_t_t_t = v_e_t_t + V_t - # Up-leg vector and its magnitude at transmit time - # See equation (7) of https://doi.org/10.1086/116062 - ρ_vec_t = r_a_t_b - r_t_t_t - ρ_t = sqrt(ρ_vec_t[1]^2 + ρ_vec_t[2]^2 + ρ_vec_t[3]^2) - - - # Compute up-leg Shapiro delay - - # Sun barycentric position and velocity (in km, km/sec) at transmit time (TDB) - r_s_t_t = xvs(et_t_secs)[1:3] - # Heliocentric position of Earth at t_t - e_U_vec = r_t_t_t - r_s_t_t - # Heliocentric distance of Earth at t_t - e_U = sqrt(e_U_vec[1]^2 + e_U_vec[2]^2 + e_U_vec[3]^2) - # Barycentric position/velocity of Sun at bounce time - r_s_t_b = xvs(et_b_secs)[1:3] - # Heliocentric position of asteroid at t_b - p_U_vec = r_a_t_b - r_s_t_b - # Heliocentric distance of asteroid at t_b - p_U = sqrt(p_U_vec[1]^2 + p_U_vec[2]^2 + p_U_vec[3]^2) - # Signal path distance (up-leg) - q_U = ρ_t - - # Shapiro correction to time-delay - Δτ_rel_U = shapiro_delay(e_U, p_U, q_U) # seconds - # Troposphere correction to time-delay - Δτ_tropo_U = tropo_delay(R_t, ρ_vec_t) # seconds - # Delay due to Solar corona - # Δτ_corona_U = corona_delay(constant_term.(r_t_t_t), constant_term.(r_a_t_b), constant_term.(r_s_t_b), F_tx, station_code) # seconds - # Total time delay - Δτ_U = Δτ_rel_U # + Δτ_tropo_U #+ Δτ_corona_U # seconds - - # New estimate - p_dot_12 = -dot(ρ_vec_t, v_t_t_t)/ρ_t - # Time-delay correction - Δt_1 = (τ_U - ρ_t/clightkms - Δτ_rel_U)/(1.0-p_dot_12/clightkms) - # Time delay new estimate - τ_U = τ_U - Δt_1 - # Transmit time, new estimate - # See equation (6) of https://doi.org/10.1086/116062 - et_t_secs = et_b_secs - τ_U - end - - # Compute TDB-UTC at transmit time - # Corrections to TT-TDB from Moyer (2003) / Folkner et al. (2014) due to position - # of measurement station on Earth are of order 0.01μs - # Δtt_tdb_station_t = - dot(v_e_t_t, r_t_t_t-r_e_t_t)/clightkms^2 - tdb_utc_t = tdb_utc(et_t_secs) # + Δtt_tdb_station_t - - # Compute TDB-UTC at receive time - # Corrections to TT-TDB from Moyer (2003) / Folkner et al. (2014) due to position - # of measurement station on Earth are of order 0.01μs - # Δtt_tdb_station_r = - dot(v_e_t_r, r_r_t_r-r_e_t_r)/clightkms^2 - tdb_utc_r = tdb_utc(et_r_secs) # + Δtt_tdb_station_r - - # Compute total time delay (UTC seconds); relativistic delay is already included in τ_D, τ_U - # See equation (9) of https://doi.org/10.1086/116062 - τ = (τ_D + τ_U) + (Δτ_tropo_D + Δτ_tropo_U) + (tdb_utc_t - tdb_utc_r) # seconds - - # Total signal delay (μs) - return 1e6τ -end - -@doc raw""" - radar_astrometry(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real; kwargs...) where {T <: AbstractFloat} - radar_astrometry(radar::RadarJPL{T}; kwargs...) where {T <: AbstractFloat} - radar_astrometry(astradarfile::String; kwargs...) - radar_astrometry(astradardata::Vector{RadarJPL}; kwargs...) where {T <: AbstractFloat} - -Return time-delay and Doppler shift. - -# Arguments - -- `observatory::ObservatoryMPC{T}`: observing station. -- `t_r_utc::DateTime`: UTC time of echo reception. -- `F_tx::Real`: transmitter frequency (MHz). -- `radar::RadarJPL{T}` / `astradardata::Vector{RadarJPL{T}}`: radar observation(s). -- `astradarfile::String`: file where to retrieve radar observations. - -# Keyword arguments - -- `tc::Real = 1.0`: time offset wrt echo reception time, to compute Doppler shifts by range differences (seconds). Offsets will be rounded to the nearest millisecond. -- `autodiff::Bool = true`: whether to compute Doppler shift via automatic diff of [`compute_delay`](@ref) or not. -- `tord::Int = 5`: order of Taylor expansions. -- `niter::Int = 10`: number of light-time solution iterations. -- `xve::EarthEph = earthposvel`: Earth ephemeris. -- `xvs::SunEph = sunposvel`: Sun ephemeris. -- `xva::AstEph`: asteroid ephemeris. - -All ephemeris must take [et seconds since J2000] and return [barycentric position in km -and velocity in km/sec]. -""" -function radar_astrometry(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real; - tc::Real = 1.0, autodiff::Bool = true, kwargs...) where {T <: AbstractFloat} - # Compute Doppler shift via automatic differentiation of time-delay - if autodiff - # Time delay - τ = compute_delay(observatory, t_r_utc; kwargs...) - # Time delay, Doppler shift - return τ[0], -F_tx*τ[1] - # Compute Doppler shift via numerical differentiation of time-delay - else - offset = Dates.Millisecond(1000round(tc/2, digits=3)) - τe = compute_delay(observatory, t_r_utc+offset; kwargs...) - τn = compute_delay(observatory, t_r_utc ; kwargs...) - τs = compute_delay(observatory, t_r_utc-offset; kwargs...) - # Time delay, Doppler shift - return τn[0], -F_tx*((τe[0]-τs[0])/tc) - end - -end - -function radar_astrometry(radar::RadarJPL{T}; kwargs...) where {T <: AbstractFloat} - return radar_astrometry(radar.rcvr, radar.date, radar.freq; kwargs...) -end - -function radar_astrometry(astradarfile::String; kwargs...) - # Check that astradarfile is a file - @assert isfile(astradarfile) "Cannot open file: $astradarfile" - # Read radar measurements - astradardata = read_radar_jpl(astradarfile) - return radar_astrometry(astradardata; kwargs...) -end - -function radar_astrometry(astradardata::Vector{RadarJPL{T}}; xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} - - # UTC time of first radar observation - utc1 = astradardata[1].date - # TDB seconds since J2000.0 for first astrometric observation - et1 = datetime2et(utc1) - # Asteroid ephemeris at et1 - a1_et1 = xva(et1)[1] - # Type of asteroid ephemeris - S = typeof(a1_et1) - - # Time delays - vdelay = Array{S}(undef, length(astradardata)) - # Doppler shifts - vdoppler = Array{S}(undef, length(astradardata)) - - # Iterate over the measurements - Threads.@threads for i in eachindex(astradardata) - # Compute time delay and doppler shift - vdelay[i], vdoppler[i] = radar_astrometry(astradardata[i]; xva, kwargs...) - end - # Rows with time delays - delay_index = map(x-> x.Δτ_units == "us", astradardata) - # Rows with Doppler shifts - doppler_index = map(x -> x.Δν_units == "Hz", astradardata) - - dt_utc_obs = date.(astradardata) # UTC time - Δτ_obs = delay.(astradardata) # Observed time delay - Δν_obs = doppler.(astradardata) # Observed Doppler shift - Δτ_σ = delay_sigma.(astradardata) # Observed time delay uncertainty - Δν_σ = doppler_sigma.(astradardata) # Observed Doppler shift uncertainty - τ_units = delay_units.(astradardata) # Time delay units - ν_units = doppler_units.(astradardata) # Doppler shift units - freq_ = freq.(astradardata) # Frequency - rcvr_ = rcvr.(astradardata) # Receiver antenna - xmit_ = xmit.(astradardata) # Emission antenna - bouncepoint_ = bouncepoint.(astradardata) # Bounce point - - # Return time delays / Doppler shifts table - return dt_utc_obs, Δτ_obs, Δν_obs, vdelay, vdoppler, Δτ_σ, Δν_σ, τ_units, ν_units, freq_, rcvr_, xmit_, bouncepoint_, delay_index, - doppler_index -end - -@doc raw""" - residuals(obs::Vector{RadarJPL{T}}; kwargs...) where {T <: AbstractFloat} - -Compute O-C residuals for radar astrometry, including corrections due to Earth orientation, -LOD and polar motion. - -See also [`compute_delay`](@ref) and [`radar_astrometry`](@ref). - -# Arguments - -- `obs::Vector{RadarJPL{T}}`: vector of observations. - -# Keyword arguments - -- `tc::Real = 1.0`: time offset wrt echo reception time, to compute Doppler shifts by range differences (seconds). Offsets will be rounded to the nearest millisecond. -- `autodiff::Bool = true`: whether to compute Doppler shift via automatic diff of [`compute_delay`](@ref) or not. -- `tord::Int = 5`: order of Taylor expansions. -- `niter::Int = 10`: number of light-time solution iterations. -- `xve::EarthEph = earthposvel`: Earth ephemeris. -- `xvs::SunEph = sunposvel`: Sun ephemeris. -- `xva::AstEph`: asteroid ephemeris. - -All ephemeris must take [et seconds since J2000] and return [barycentric position in km -and velocity in km/sec]. -""" -function residuals(obs::Vector{RadarJPL{T}}; kwargs...) where {T <: AbstractFloat} - # Radar delay/Doppler astrometric data - x_jt = radar_astrometry(obs; kwargs...) - # Time-delay residuals - res_τ = x_jt[2][x_jt[14]] .- x_jt[4][x_jt[14]] - # Doppler-shift residuals - res_ν = x_jt[3][x_jt[15]] .- x_jt[5][x_jt[15]] - # Weights - w_τ = 1 ./ (x_jt[6][x_jt[14]].^2) - w_ν = 1 ./ (x_jt[7][x_jt[15]].^2) - - return res_τ, w_τ, res_ν, w_ν -end +include("catalogue_mpc.jl") +include("observatory_mpc.jl") +include("radec_mpc.jl") +include("radar_jpl.jl") +include("units.jl") +include("jpl_eph.jl") +include("topocentric.jl") +include("tracklet.jl") +include("process_radec.jl") + +@doc raw""" + shapiro_delay(e, p, q) + +Return the relativistic (Shapiro) time-delay in seconds +```math +\Delta\tau[\text{rel}] = \frac{2\mu_\odot}{c^3}\log\left|\frac{d_{E,S} + d_{A,S} + d_{A,E}}{d_{E,S}+d_{A,S}-d_{A, E}}\right|, +``` +where ``\mu_\odot = GM_\odot`` is the gravitational parameter of the sun, and ``d_{E,S}``, ``d_{A,S}`` +and ``d_{A,E}`` are the heliocentric distance of the Earth, the asteroid's heliocentric +distance, and the asteroid's geocentric distance, respectively. + +# Arguments + +- `e`: heliocentric distance of the Earth. +- `p`: asteroid's heliocentric distance. +- `q`: asteroid's geocentric distance. + +!!! reference + See https://doi.org/10.1103/PhysRevLett.13.789. +""" +function shapiro_delay(e, p, q) + shap = 0.0 # 2μ[1]/(c_au_per_day^2) + shap_del_days = (2μ_DE430[su]/(c_au_per_day^3))*log( (e+p+q+shap)/(e+p-q+shap) ) # days + return shap_del_days*daysec # seconds +end + +@doc raw""" + shapiro_doppler(e, de, p, dp, q, dq, F_tx) + +Return the Doppler shift (in units of `F_tx`) +```math +\Delta\nu = -\nu\frac{d\Delta\tau}{dt}, +``` +where ``\nu`` is the frequency and ``\frac{d\Delta\tau}{dt}`` is the differential of the +Shapiro delay. See also [`shapiro_delay`](@ref). + +# Arguments + +- `e`: heliocentric distance of the Earth. +- `de`: differential of `e`. +- `p`: asteroid's heliocentric distance. +- `dp`: differential of `p`. +- `q`: asteroid's geocentric distance. +- `dq`: differential of `q`. +- `F_tx`: transmitter frequency (MHz). + +!!! reference + See https://doi.org/10.1103/PhysRevLett.17.933. +""" +function shapiro_doppler(e, de, p, dp, q, dq, F_tx) + # shap_del_diff = 2μ[1]*( (de+dp+dq)/(e+p+q) - (de+dp-dq)/(e+p-q) )/(c_au_per_day^3) # (adim.) + shap_del_diff = (4μ_DE430[su]/(c_au_per_day^3))*( ( dq*(e+p) - q*(de+dp) )/( (e+p)^2 - q^2 ) ) # differential of Shapiro delay (adim.) + # ν = -F_tx*dτ/dt (units of F_tx) + # See footnote 10 of https://doi.org/10.1103/PhysRevLett.17.933 + shap_dop = -F_tx*shap_del_diff + return shap_dop # (units of F_tx) +end + +@doc raw""" + Ne(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}, ds::U, ΔS::Real) where {S<:Number, U<:Number} + +Return the density of ionized electrons (in electrons/cm^3) in interplanetary medium +```math +N_e = \frac{A}{r^6} + \frac{ab/\sqrt{a^2\sin^2\beta + b^2\cos^2\beta}}{r^2}, +``` +where ``r`` is the heliocentric distance expressed in units of the solar radius, ``\beta`` is +the solar latitude, and ``A``, ``a``, ``b`` are the solar corona parameters. + +# Arguments +- `p1::Vector{S}`: signal departure point (transmitter/bounce) (au). +- `p2::Vector{S}`: signal arrival point (bounce/receiver) (au). +- `r_s_t0::Vector{S}`: Barycentric position (au) of Sun at initial time of propagation of signal path (bounce time for down-leg; transmit time for up-leg). +- `ds::U`: current distance travelled by ray from emission point (au). +- `ΔS::Real`: total distance between p1 and p2 (au). + +!!! reference + See (Explanatory Supplement to the Astronomical Almanac 2014, p. 323, Sec. 8.7.5, Eq. 8.22). + ESAA 2014 in turn refers to Muhleman and Anderson (1981). Ostro (1993) gives a reference to + Anderson (1978), where this model is fitted to Mariner 9 ranging data. Reading + https://gssc.esa.int/navipedia/index.php/Ionospheric_Delay helped a lot to clarify things, + especially the 40.3, although they talk about Earth's ionosphere. Another valuable source is + Standish, E.M., Astron. Astrophys. 233, 252-271 (1990). +""" +function Ne(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}, ds::U, ΔS::Real) where {S<:Number, U<:Number} + # s: linear parametrization of ray path, such that + # s = 0 -> point on ray path is at p1; s = 1 -> point on ray path is at p2 + s = ds/ΔS + # Rescale Taylor polynomial + s_p2_p1 = map(x->s*x, Taylor1.(p2-p1, s.order)) + # Heliocentric position (au) of point on ray path at time t_tdb_jul (Julian days) + r_vec = Taylor1.(p1, s.order) + s_p2_p1 - Taylor1.(r_s_t0, s.order) + # Heliocentric distance (au) of point on ray path at time t_tdb_jul (Julian days) + r = sqrt( r_vec[1]^2 + r_vec[2]^2 + r_vec[3]^2 ) + # Compute heliocentric position vector of point on ray path wrt Sun's rotation pole + # and equator (i.e., heliographic) + α_p_sun_rad = deg2rad(α_p_sun) + δ_p_sun_rad = deg2rad(δ_p_sun) + r_vec_heliographic = inv( pole_rotation(α_p_sun_rad, δ_p_sun_rad) )*r_vec + # Compute heliographic solar latitude (Anderson, 1978) of point on ray path + β = asin( r_vec_heliographic[3]/r ) # Ecliptic solar latitude of point on ray path (rad) + # Heliocentric distance + r_sr = r/R_sun + # First term of Ne + Ne_t1 = (A_sun/r_sr^6) + # Second term of Ne + Ne_t2 = ( (a_sun*b_sun)/sqrt((a_sun*sin(β))^2 + (b_sun*cos(β))^2) )/(r_sr^2) + # Density of ionized electrons + Ne_val = Ne_t1 + Ne_t2 + return Ne_val +end + +# TODO: @taylorize! +@doc raw""" + Ne_path_integral(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}) where {S<:Number} + +Return the path integral of the density of ionized electrons in interplanetary medium ``N_e`` +in units of electrons/cm^2, evaluated with `TaylorIntegration`. + +# Arguments + +- `p1::Vector{S}`: signal departure point (transmitter/bounce) (au). +- `p2::Vector{S}`: signal arrival point (bounce/receiver) (au). +- `r_s_t0::Vector{S}`: Barycentric position (au) of Sun at initial time of propagation of signal path (bounce time for down-leg; transmit time for up-leg). +""" +function Ne_path_integral(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}) where {S<:Number} + # Total distance between p1 and p2, in centimeters + ΔS = (100_000au)*norm(p2-p1) + # Kernel of path integral; distance parameter `s` and total distance `ΔS` is in cm + function int_kernel(x, params, s) + return Ne(p1, p2, r_s_t0, s, ΔS) + end + # Do path integral + + # Initial condition + i0 = zero(p1[1]) + iT = Taylor1(i0, 24) + # Independent variable + tT = Taylor1(24) + # Integration + TaylorIntegration.jetcoeffs!(int_kernel, tT, iT, nothing) + # Evaluate path integral in total distance ΔS + return iT(ΔS) +end + +@doc raw""" + corona_delay(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}, F_tx::U) where {S<:Number, U<:Real} + +Return the time-delay (in sec) due to thin plasma of solar corona +```math +\Delta\tau_\text{cor} = \frac{40.3}{cf^2}\int_{P_1}^{P_2}N_e \ ds, +```math +where ``c`` is the speed of light (cm/sec), ``f`` is the frequency (Hz), ``N_e`` is the density +of ionized electrons in interplanetary medium (electrons/cm^3), and ``s`` is the linear +distance (cm). ``N_e`` is computed by [`Ne`](@ref) and integrated via `TaylorIntegration` in +[`Ne_path_integral`](@ref). + +# Arguments + +- `p1::Vector{S}`: signal departure point (transmitter/bounce for up/down-link, resp.) (au). +- `p2::Vector{S}`: signal arrival point (bounce/receiver for up/down-link, resp.) (au). +- `r_s_t0::Vector{S}`: Barycentric position (au) of Sun at initial time of propagation of signal path (bounce time for down-leg; transmit time for up-leg). +- `F_tx::U`: transmitter frequency (MHz). + +!!! reference + From [Ionospheric Delay](https://gssc.esa.int/navipedia/index.php/Ionospheric_Delay) it seems + that ESAA 2014 text probably should say that in the formula for ``\Delta\tau_\text{cor}``, + the expression ``40.3 N_e/f^2`` is adimensional, where ``Ne`` is in electrons/cm^3 and ``f`` is + in Hz therefore, the integral ``(40.3/f^2)\int Ne \ ds`` is in centimeters, where ``ds`` is in + cm and the expression ``(40.3/(cf^2))\int Ne \ ds``, with ``c`` in cm/sec, is in seconds. +""" +function corona_delay(p1::Vector{S}, p2::Vector{S}, r_s_t0::Vector{S}, F_tx::U) where {S<:Number, U<:Real} + # For the time being, we're removing the terms associated with higher-order terms in the + # variationals (ie, Yarkovsky) + int_path = Ne_path_integral(p1, p2, r_s_t0) # (electrons/cm^2) + # Time delay due to solar corona + Δτ_corona = 40.3e-6int_path/(c_cm_per_sec*(F_tx)^2) # seconds + return Δτ_corona # seconds +end + +@doc raw""" + zenith_distance(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Number, S<:Number} + +**VERY** elementary computation of zenith distance. + +# Arguments + +- `r_antenna::Vector{T}`: position of antenna at receive/transmit time in celestial frame wrt geocenter. +- `ρ_vec_ae::Vector{S}`: slant-range vector from antenna to asteroid. +""" +function zenith_distance(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Number, S<:Number} + # Magnitude of geocentric antenna position + norm_r_antenna = sqrt(r_antenna[1]^2 + r_antenna[2]^2 + r_antenna[3]^2) + # Magnitude of slant-range vector from antenna to asteroid + norm_ρ_vec_ae = sqrt(ρ_vec_ae[1]^2 + ρ_vec_ae[2]^2 + ρ_vec_ae[3]^2) + # cos( angle between r_antenna and ρ_vec_ae) + cos_antenna_slant = dot(r_antenna, ρ_vec_ae)/(norm_r_antenna*norm_ρ_vec_ae) + # zenith distance + return acos(cos_antenna_slant) +end + +@doc raw""" + tropo_delay(z) + +Return the time delay (in sec) due to Earth's troposphere for radio frequencies +```math +\Delta\tau_\text{tropo} = \frac{7 \ \text{nsec}}{\cos z + \frac{0.0014}{0.045 + \cot z}}, +``` +where ``z`` is the zenith distance at the antenna. This time delay oscillates between +0.007``\mu``s and 0.225``\mu``s for ``z`` between 0 and ``\pi/2`` rad. + +See also [`zenith_distance`](@doc). + +# Arguments + +- `z`: zenith distance (radians). +""" +tropo_delay(z) = (7e-9)/( cos(z) + 0.0014/(0.045+cot(z)) ) # seconds + +@doc raw""" + tropo_delay(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Number, S<:Number} + +Return the time delay (in sec) due to Earth's troposphere for radio frequencies. The function +first computes the zenith distance ``z`` via [`zenith_distance`](@ref) and then substitutes +into the first method of [`tropo_delay`](@ref). + +# Arguments + +- `r_antenna::Vector{T}`: position of antenna at receive/transmit time in celestial frame wrt geocenter. +- `ρ_vec_ae::Vector{S}`: slant-range vector from antenna to asteroid. +""" +function tropo_delay(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Number, S<:Number} + # zenith distance + zd = zenith_distance(r_antenna, ρ_vec_ae) # rad + # Time delay due to Earth's troposphere + return tropo_delay(zd) # seconds +end + +@doc raw""" + compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; kwargs...) where {T <: AbstractFloat} + +Compute Taylor series expansion of time-delay observable around echo reception time. This +allows to compute dopplers via automatic differentiation using +```math +\nu = -f\frac{d\tau}{dt}, +``` +where ``f`` is the transmitter frequency (MHz) and ``\tau`` is the time-delay at reception +time ``t``. Computed values include corrections due to Earth orientation, LOD and polar +motion. + +**Note:** Works only with `TaylorInterpolant` ephemeris. See [`PlanetaryEphemeris.TaylorInterpolant`](@ref). + +# Arguments + +- `observatory::ObservatoryMPC{T}`: observing station. +- `t_r_utc::DateTime`: UTC time of echo reception. + +# Keyword arguments + +- `tord::Int = 5`: order of Taylor expansions. +- `niter::Int = 10`: number of light-time solution iterations. +- `xve::EarthEph = earthposvel`: Earth ephemeris. +- `xvs::SunEph = sunposvel`: Sun ephemeris. +- `xva::AstEph`: asteroid ephemeris. + +All ephemeris must take [et seconds since J2000] and return [barycentric position in km +and velocity in km/sec]. + +!!! reference + See https://doi.org/10.1086/116062. +""" +function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; tord::Int = 5, + niter::Int = 10, xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, + xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} + + # Transform receiving time from UTC to TDB seconds since j2000 + et_r_secs_0 = datetime2et(t_r_utc) + # Auxiliary to evaluate JT ephemeris + xva1et0 = xva(et_r_secs_0)[1] + # et_r_secs_0 as a Taylor polynomial + et_r_secs = Taylor1([et_r_secs_0,one(et_r_secs_0)].*one(xva1et0), tord) + # Compute geocentric position/velocity of receiving antenna in inertial frame (km, km/sec) + RV_r = obsposvelECI(observatory, et_r_secs) + R_r = RV_r[1:3] + # Earth's barycentric position and velocity at receive time + r_e_t_r = xve(et_r_secs)[1:3] + # Receiver barycentric position and velocity at receive time + r_r_t_r = r_e_t_r + R_r + # Asteroid barycentric position and velocity at receive time + r_a_t_r = xva(et_r_secs)[1:3] + # Sun barycentric position and velocity at receive time + r_s_t_r = xvs(et_r_secs)[1:3] + + # Down-leg iteration + # τ_D first approximation + # See equation (1) of https://doi.org/10.1086/116062 + ρ_vec_r = r_a_t_r - r_r_t_r + ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) + # -R_b/c, but delay is wrt asteroid Center (Brozovic et al., 2018) + τ_D = ρ_r/clightkms # (seconds) + # Bounce time, new estimate + # See equation (2) of https://doi.org/10.1086/116062 + et_b_secs = et_r_secs - τ_D + + # Allocate memmory for time delays + Δτ_D = zero(τ_D) # Total time delay + Δτ_rel_D = zero(τ_D) # Shapiro delay + # Δτ_corona_D = zero(τ_D) # Delay due to Solar corona + Δτ_tropo_D = zero(τ_D) # Delay due to Earth's troposphere + + for i in 1:niter + # Asteroid barycentric position (in au) at bounce time (TDB) + rv_a_t_b = xva(et_b_secs) + r_a_t_b = rv_a_t_b[1:3] + v_a_t_b = rv_a_t_b[4:6] + # Estimated position of the asteroid's center of mass relative to the recieve point + # See equation (3) of https://doi.org/10.1086/116062. + ρ_vec_r = r_a_t_b - r_r_t_r + # Magnitude of ρ_vec_r + # See equation (4) of https://doi.org/10.1086/116062. + ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) + + # Compute down-leg Shapiro delay + # NOTE: when using PPN, substitute 2 -> 1+γ in expressions for Shapiro delay, + # Δτ_rel_[D|U] + + # Earth's position at t_r + e_D_vec = r_r_t_r - r_s_t_r + # Heliocentric distance of Earth at t_r + e_D = sqrt(e_D_vec[1]^2 + e_D_vec[2]^2 + e_D_vec[3]^2) + # Barycentric position of Sun at estimated bounce time + r_s_t_b = xvs(et_b_secs)[1:3] + # Heliocentric position of asteroid at t_b + p_D_vec = r_a_t_b - r_s_t_b + # Heliocentric distance of asteroid at t_b + p_D = sqrt(p_D_vec[1]^2 + p_D_vec[2]^2 + p_D_vec[3]^2) + # Signal path distance (down-leg) + q_D = ρ_r + + # Shapiro correction to time-delay + Δτ_rel_D = shapiro_delay(e_D, p_D, q_D) # seconds + # Troposphere correction to time-delay + Δτ_tropo_D = tropo_delay(R_r, ρ_vec_r) # seconds + # Solar corona correction to time-delay + # Δτ_corona_D = corona_delay(constant_term.(r_a_t_b), r_r_t_r, r_s_t_r, F_tx, station_code) # seconds + # Total time-delay + Δτ_D = Δτ_rel_D # + Δτ_tropo_D #+ Δτ_corona_D # seconds + + # New estimate + p_dot_23 = dot(ρ_vec_r, v_a_t_b)/ρ_r + # Time delay correction + Δt_2 = (τ_D - ρ_r/clightkms - Δτ_rel_D)/(1.0-p_dot_23/clightkms) + # Time delay new estimate + τ_D = τ_D - Δt_2 + # Bounce time, new estimate + # See equation (2) of https://doi.org/10.1086/116062 + et_b_secs = et_r_secs - τ_D + + end + + # Asteroid's barycentric position and velocity at bounce time t_b + rv_a_t_b = xva(et_b_secs) + r_a_t_b = rv_a_t_b[1:3] + v_a_t_b = rv_a_t_b[4:6] + + # Up-leg iteration + # τ_U first estimation + # See equation (5) of https://doi.org/10.1086/116062 + τ_U = τ_D + # Transmit time, 1st estimate + # See equation (6) of https://doi.org/10.1086/116062 + et_t_secs = et_b_secs - τ_U + # Geocentric position and velocity of transmitting antenna in inertial frame (km, km/sec) + RV_t = RV_r(et_t_secs-et_r_secs_0) + R_t = RV_t[1:3] + V_t = RV_t[4:6] + # Barycentric position and velocity of the Earth at transmit time + rv_e_t_t = xve(et_t_secs) + r_e_t_t = rv_e_t_t[1:3] + v_e_t_t = rv_e_t_t[4:6] + # Transmitter barycentric position and velocity of at transmit time + r_t_t_t = r_e_t_t + R_t + # Up-leg vector at transmit time + # See equation (7) of https://doi.org/10.1086/116062 + ρ_vec_t = r_a_t_b - r_t_t_t + # Magnitude of up-leg vector + ρ_t = sqrt(ρ_vec_t[1]^2 + ρ_vec_t[2]^2 + ρ_vec_t[3]^2) + + # Allocate memmory for time delays + Δτ_U = zero(τ_U) # Total time delay + Δτ_rel_U = zero(τ_U) # Shapiro delay + # Δτ_corona_U = zero(τ_U) # Delay due to Solar corona + Δτ_tropo_U = zero(τ_U) # Delay due to Earth's troposphere + + for i in 1:niter + # Geocentric position and velocity of transmitting antenna in inertial frame (km, km/sec) + RV_t = RV_r(et_t_secs-et_r_secs_0) + R_t = RV_t[1:3] + V_t = RV_t[4:6] + # Earth's barycentric position and velocity at transmit time + rv_e_t_t = xve(et_t_secs) + r_e_t_t = rv_e_t_t[1:3] + v_e_t_t = rv_e_t_t[4:6] + # Barycentric position and velocity of the transmitter at the transmit time + r_t_t_t = r_e_t_t + R_t + v_t_t_t = v_e_t_t + V_t + # Up-leg vector and its magnitude at transmit time + # See equation (7) of https://doi.org/10.1086/116062 + ρ_vec_t = r_a_t_b - r_t_t_t + ρ_t = sqrt(ρ_vec_t[1]^2 + ρ_vec_t[2]^2 + ρ_vec_t[3]^2) + + + # Compute up-leg Shapiro delay + + # Sun barycentric position and velocity (in km, km/sec) at transmit time (TDB) + r_s_t_t = xvs(et_t_secs)[1:3] + # Heliocentric position of Earth at t_t + e_U_vec = r_t_t_t - r_s_t_t + # Heliocentric distance of Earth at t_t + e_U = sqrt(e_U_vec[1]^2 + e_U_vec[2]^2 + e_U_vec[3]^2) + # Barycentric position/velocity of Sun at bounce time + r_s_t_b = xvs(et_b_secs)[1:3] + # Heliocentric position of asteroid at t_b + p_U_vec = r_a_t_b - r_s_t_b + # Heliocentric distance of asteroid at t_b + p_U = sqrt(p_U_vec[1]^2 + p_U_vec[2]^2 + p_U_vec[3]^2) + # Signal path distance (up-leg) + q_U = ρ_t + + # Shapiro correction to time-delay + Δτ_rel_U = shapiro_delay(e_U, p_U, q_U) # seconds + # Troposphere correction to time-delay + Δτ_tropo_U = tropo_delay(R_t, ρ_vec_t) # seconds + # Delay due to Solar corona + # Δτ_corona_U = corona_delay(constant_term.(r_t_t_t), constant_term.(r_a_t_b), constant_term.(r_s_t_b), F_tx, station_code) # seconds + # Total time delay + Δτ_U = Δτ_rel_U # + Δτ_tropo_U #+ Δτ_corona_U # seconds + + # New estimate + p_dot_12 = -dot(ρ_vec_t, v_t_t_t)/ρ_t + # Time-delay correction + Δt_1 = (τ_U - ρ_t/clightkms - Δτ_rel_U)/(1.0-p_dot_12/clightkms) + # Time delay new estimate + τ_U = τ_U - Δt_1 + # Transmit time, new estimate + # See equation (6) of https://doi.org/10.1086/116062 + et_t_secs = et_b_secs - τ_U + end + + # Compute TDB-UTC at transmit time + # Corrections to TT-TDB from Moyer (2003) / Folkner et al. (2014) due to position + # of measurement station on Earth are of order 0.01μs + # Δtt_tdb_station_t = - dot(v_e_t_t, r_t_t_t-r_e_t_t)/clightkms^2 + tdb_utc_t = tdb_utc(et_t_secs) # + Δtt_tdb_station_t + + # Compute TDB-UTC at receive time + # Corrections to TT-TDB from Moyer (2003) / Folkner et al. (2014) due to position + # of measurement station on Earth are of order 0.01μs + # Δtt_tdb_station_r = - dot(v_e_t_r, r_r_t_r-r_e_t_r)/clightkms^2 + tdb_utc_r = tdb_utc(et_r_secs) # + Δtt_tdb_station_r + + # Compute total time delay (UTC seconds); relativistic delay is already included in τ_D, τ_U + # See equation (9) of https://doi.org/10.1086/116062 + τ = (τ_D + τ_U) + (Δτ_tropo_D + Δτ_tropo_U) + (tdb_utc_t - tdb_utc_r) # seconds + + # Total signal delay (μs) + return 1e6τ +end + +@doc raw""" + radar_astrometry(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real; kwargs...) where {T <: AbstractFloat} + radar_astrometry(radar::RadarJPL{T}; kwargs...) where {T <: AbstractFloat} + radar_astrometry(astradarfile::String; kwargs...) + radar_astrometry(astradardata::Vector{RadarJPL}; kwargs...) where {T <: AbstractFloat} + +Return time-delay and Doppler shift. + +# Arguments + +- `observatory::ObservatoryMPC{T}`: observing station. +- `t_r_utc::DateTime`: UTC time of echo reception. +- `F_tx::Real`: transmitter frequency (MHz). +- `radar::RadarJPL{T}` / `astradardata::Vector{RadarJPL{T}}`: radar observation(s). +- `astradarfile::String`: file where to retrieve radar observations. + +# Keyword arguments + +- `tc::Real = 1.0`: time offset wrt echo reception time, to compute Doppler shifts by range differences (seconds). Offsets will be rounded to the nearest millisecond. +- `autodiff::Bool = true`: whether to compute Doppler shift via automatic diff of [`compute_delay`](@ref) or not. +- `tord::Int = 5`: order of Taylor expansions. +- `niter::Int = 10`: number of light-time solution iterations. +- `xve::EarthEph = earthposvel`: Earth ephemeris. +- `xvs::SunEph = sunposvel`: Sun ephemeris. +- `xva::AstEph`: asteroid ephemeris. + +All ephemeris must take [et seconds since J2000] and return [barycentric position in km +and velocity in km/sec]. +""" +function radar_astrometry(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real; + tc::Real = 1.0, autodiff::Bool = true, kwargs...) where {T <: AbstractFloat} + # Compute Doppler shift via automatic differentiation of time-delay + if autodiff + # Time delay + τ = compute_delay(observatory, t_r_utc; kwargs...) + # Time delay, Doppler shift + return τ[0], -F_tx*τ[1] + # Compute Doppler shift via numerical differentiation of time-delay + else + offset = Dates.Millisecond(1000round(tc/2, digits=3)) + τe = compute_delay(observatory, t_r_utc+offset; kwargs...) + τn = compute_delay(observatory, t_r_utc ; kwargs...) + τs = compute_delay(observatory, t_r_utc-offset; kwargs...) + # Time delay, Doppler shift + return τn[0], -F_tx*((τe[0]-τs[0])/tc) + end + +end + +function radar_astrometry(radar::RadarJPL{T}; kwargs...) where {T <: AbstractFloat} + return radar_astrometry(radar.rcvr, radar.date, radar.freq; kwargs...) +end + +function radar_astrometry(astradarfile::String; kwargs...) + # Check that astradarfile is a file + @assert isfile(astradarfile) "Cannot open file: $astradarfile" + # Read radar measurements + astradardata = read_radar_jpl(astradarfile) + return radar_astrometry(astradardata; kwargs...) +end + +function radar_astrometry(astradardata::Vector{RadarJPL{T}}; xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} + + # UTC time of first radar observation + utc1 = astradardata[1].date + # TDB seconds since J2000.0 for first astrometric observation + et1 = datetime2et(utc1) + # Asteroid ephemeris at et1 + a1_et1 = xva(et1)[1] + # Type of asteroid ephemeris + S = typeof(a1_et1) + + # Time delays + vdelay = Array{S}(undef, length(astradardata)) + # Doppler shifts + vdoppler = Array{S}(undef, length(astradardata)) + + # Iterate over the measurements + Threads.@threads for i in eachindex(astradardata) + # Compute time delay and doppler shift + vdelay[i], vdoppler[i] = radar_astrometry(astradardata[i]; xva, kwargs...) + end + # Rows with time delays + delay_index = map(x-> x.Δτ_units == "us", astradardata) + # Rows with Doppler shifts + doppler_index = map(x -> x.Δν_units == "Hz", astradardata) + + dt_utc_obs = date.(astradardata) # UTC time + Δτ_obs = delay.(astradardata) # Observed time delay + Δν_obs = doppler.(astradardata) # Observed Doppler shift + Δτ_σ = delay_sigma.(astradardata) # Observed time delay uncertainty + Δν_σ = doppler_sigma.(astradardata) # Observed Doppler shift uncertainty + τ_units = delay_units.(astradardata) # Time delay units + ν_units = doppler_units.(astradardata) # Doppler shift units + freq_ = freq.(astradardata) # Frequency + rcvr_ = rcvr.(astradardata) # Receiver antenna + xmit_ = xmit.(astradardata) # Emission antenna + bouncepoint_ = bouncepoint.(astradardata) # Bounce point + + # Return time delays / Doppler shifts table + return dt_utc_obs, Δτ_obs, Δν_obs, vdelay, vdoppler, Δτ_σ, Δν_σ, τ_units, ν_units, freq_, rcvr_, xmit_, bouncepoint_, delay_index, + doppler_index +end + +@doc raw""" + residuals(obs::Vector{RadarJPL{T}}; kwargs...) where {T <: AbstractFloat} + +Compute O-C residuals for radar astrometry, including corrections due to Earth orientation, +LOD and polar motion. + +See also [`compute_delay`](@ref) and [`radar_astrometry`](@ref). + +# Arguments + +- `obs::Vector{RadarJPL{T}}`: vector of observations. + +# Keyword arguments + +- `tc::Real = 1.0`: time offset wrt echo reception time, to compute Doppler shifts by range differences (seconds). Offsets will be rounded to the nearest millisecond. +- `autodiff::Bool = true`: whether to compute Doppler shift via automatic diff of [`compute_delay`](@ref) or not. +- `tord::Int = 5`: order of Taylor expansions. +- `niter::Int = 10`: number of light-time solution iterations. +- `xve::EarthEph = earthposvel`: Earth ephemeris. +- `xvs::SunEph = sunposvel`: Sun ephemeris. +- `xva::AstEph`: asteroid ephemeris. + +All ephemeris must take [et seconds since J2000] and return [barycentric position in km +and velocity in km/sec]. +""" +function residuals(obs::Vector{RadarJPL{T}}; kwargs...) where {T <: AbstractFloat} + # Radar delay/Doppler astrometric data + x_jt = radar_astrometry(obs; kwargs...) + # Time-delay residuals + res_τ = x_jt[2][x_jt[14]] .- x_jt[4][x_jt[14]] + # Doppler-shift residuals + res_ν = x_jt[3][x_jt[15]] .- x_jt[5][x_jt[15]] + # Weights + w_τ = 1 ./ (x_jt[6][x_jt[14]].^2) + w_ν = 1 ./ (x_jt[7][x_jt[15]].^2) + + return res_τ, w_τ, res_ν, w_ν +end diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl old mode 100755 new mode 100644 index 6ceadcd2..038628fa --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -1,602 +1,602 @@ -@doc raw""" - OpticalResidual{T <: Real, U <: Number} - -An astrometric optical observed minus computed residual. - -# Fields - -- `ξ_α::U`: right ascension residual. -- `ξ_δ::U`: declination residual. -- `w_α::T`: right ascension weight. -- `w_δ::T`: declination weight. -- `relax_factor::T`: relaxation factor. -- `outlier::Bool`: whether the residual is an outlier or not. -""" -@auto_hash_equals struct OpticalResidual{T <: Real, U <: Number} - ξ_α::U - ξ_δ::U - w_α::T - w_δ::T - relax_factor::T - outlier::Bool - # Inner constructor - function OpticalResidual{T, U}(ξ_α::U, ξ_δ::U, w_α::T, w_δ::T, relax_factor::T = one(T), - outlier::Bool = false) where {T <: Real, U <: Number} - new{T, U}(ξ_α, ξ_δ, w_α, w_δ, relax_factor, outlier) - end -end -# Outer constructor -function OpticalResidual(ξ_α::U, ξ_δ::U, w_α::T, w_δ::T, relax_factor::T = one(T), - outlier::Bool = false) where {T <: Real, U <: Number} - return OpticalResidual{T, U}(ξ_α, ξ_δ, w_α, w_δ, relax_factor, outlier) -end - -# Evaluate methods -function evaluate(res::OpticalResidual{T, TaylorN{T}}, x::Vector{T}) where {T <: Real} - return OpticalResidual(res.ξ_α(x), res.ξ_δ(x), res.w_α, res.w_δ, res.relax_factor, res.outlier) -end -(res::OpticalResidual{T, TaylorN{T}})(x::Vector{T}) where {T <: Real} = evaluate(res, x) - -function evaluate(res::AbstractVector{OpticalResidual{T, TaylorN{T}}}, x::Vector{T}) where {T <: Real} - res_new = Vector{OpticalResidual{T, T}}(undef, length(res)) - for i in eachindex(res) - res_new[i] = evaluate(res[i], x) - end - return res_new -end -(res::AbstractVector{OpticalResidual{T, TaylorN{T}}})(x::Vector{T}) where {T <: Real} = evaluate(res, x) - -# Print method for OpticalResidual -# Examples: -# α: -138.79801 δ: -89.80025 -# α: -134.79450 δ: -91.42509 (outlier) -function show(io::IO, x::OpticalResidual{T, U}) where {T <: Real, U <: Number} - outlier_flag = outlier(x) ? " (outlier)" : "" - print(io, "α: ", @sprintf("%+.5f", cte(x.ξ_α)), " δ: ", - @sprintf("%+.5f", cte(x.ξ_δ)), outlier_flag) -end - -@doc raw""" - unfold(ξs::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} - -Concatenate right ascension and declination residuals for an orbit fit. -""" -function unfold(ξs::AbstractVector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} - # Number of non outliers - L = count(x -> !x.outlier, ξs) - # Vector of residuals - res = Vector{U}(undef, 2*L) - # Vector of weights - w = Vector{T}(undef, 2*L) - # Global counter - k = 1 - # Fill residuals and weights - for i in eachindex(ξs) - if !ξs[i].outlier - # Right ascension - res[k] = ξs[i].ξ_α - w[k] = ξs[i].w_α / ξs[i].relax_factor - # Declination - res[k+L] = ξs[i].ξ_δ - w[k+L] = ξs[i].w_δ / ξs[i].relax_factor - # Update global counter - k += 1 - end - end - - return res, w -end - -# Functions to get specific fields of a OpticalResidual object -ra(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.ξ_α -dec(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.ξ_δ -weight_ra(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.w_α -weight_dec(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.w_δ -relax_factor(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.relax_factor -outlier(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.outlier - -euclid3D(x::Vector{U}) where {U <: Number} = sqrt(x[1]*x[1] + x[2]*x[2] + x[3]*x[3]) -dot3D(x::Vector{U}, y::Vector{V}) where {U, V <: Number} = x[1]*y[1] + x[2]*y[2] + x[3]*y[3] - -@doc raw""" - compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; kwargs...) where {T <: AbstractFloat} - compute_radec(obs::RadecMPC{T}; kwargs...) where {T <: AbstractFloat} - compute_radec(obs::Vector{RadecMPC{T}}; kwargs...) where {T <: AbstractFloat} - -Compute astrometric right ascension and declination (both in arcsec) for a set of MPC-formatted -observations. Corrections due to Earth orientation, LOD, polar motion are considered in -computations. - -# Arguments - -- `observatory::ObservatoryMPC{T}`: observation site. -- `t_r_utc::DateTime`: UTC time of astrometric observation. -- `obs::Vector{RadecMPC{T}}`: optical observation(s). - -# Keyword arguments - -- `niter::Int = 5`: number of light-time solution iterations. -- `xve::EarthEph = earthposvel`: Earth ephemeris. -- `xvs::SunEph = sunposvel`: Sun ephemeris. -- `xva::AstEph`: asteroid ephemeris. - -All ephemeris must take [et seconds since J2000] and return [barycentric position in km -and velocity in km/sec]. -""" -function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter::Int = 5, - xvs::SunEph = sunposvel, xve::EarthEph = earthposvel, - xva::AstEph) where {T <: AbstractFloat, SunEph, EarthEph, AstEph} - # Transform receiving time from UTC to TDB seconds since J2000 - et_r_secs = datetime2et(t_r_utc) - # Sun barycentric position and velocity at receive time - rv_s_t_r = xvs(et_r_secs) - r_s_t_r = rv_s_t_r[1:3] - # Earth's barycentric position and velocity at receive time - rv_e_t_r = xve(et_r_secs) - r_e_t_r = rv_e_t_r[1:3] - # Asteroid barycentric position and velocity at receive time - rv_a_t_r = xva(et_r_secs) - r_a_t_r = rv_a_t_r[1:3] - # Compute geocentric position/velocity of receiving antenna in inertial frame [km, km/s] - RV_r = obsposvelECI(observatory, et_r_secs) - R_r = RV_r[1:3] - # Receiver barycentric position and velocity at receive time - r_r_t_r = r_e_t_r + R_r - - # Down-leg iteration - # τ_D first approximation - # See equation (1) of https://doi.org/10.1086/116062 - ρ_vec_r = r_a_t_r - r_r_t_r - ρ_r = euclid3D(ρ_vec_r) - # -R_b/c, but delay is wrt asteroid Center (Brozovic et al., 2018) - τ_D = ρ_r/clightkms # (seconds) - # Bounce time, new estimate - # See equation (2) of https://doi.org/10.1086/116062 - et_b_secs = et_r_secs - τ_D - - # Allocate memmory for time-delays - Δτ_D = zero(τ_D) # Total time delay - Δτ_rel_D = zero(τ_D) # Shapiro delay - # Δτ_corona_D = zero(τ_D) # Delay due to Solar corona - Δτ_tropo_D = zero(τ_D) # Delay due to Earth's troposphere - - for i in 1:niter - # Asteroid barycentric position (in km) and velocity (in km/s) at bounce time (TDB) - rv_a_t_b = xva(et_b_secs) - r_a_t_b = rv_a_t_b[1:3] - v_a_t_b = rv_a_t_b[4:6] - # Estimated position of the asteroid's center of mass relative to the recieve point - # See equation (3) of https://doi.org/10.1086/116062 - ρ_vec_r = r_a_t_b - r_r_t_r - # Magnitude of ρ_vec_r - # See equation (4) of https://doi.org/10.1086/116062 - ρ_r = euclid3D(ρ_vec_r) - - # Compute down-leg Shapiro delay - # NOTE: when using PPN, substitute 2 -> 1+γ in expressions for Shapiro delay, - # Δτ_rel_[D|U] - - # Earth's position at t_r - e_D_vec = r_r_t_r - r_s_t_r - # Heliocentric distance of Earth at t_r - e_D = euclid3D(e_D_vec) - # Barycentric position of Sun at estimated bounce time - rv_s_t_b = xvs(et_b_secs) - r_s_t_b = rv_s_t_b[1:3] - # Heliocentric position of asteroid at t_b - p_D_vec = r_a_t_b - r_s_t_b - # Heliocentric distance of asteroid at t_b - p_D = euclid3D(p_D_vec) - # Signal path distance (down-leg) - q_D = ρ_r - - # Shapiro correction to time-delay - Δτ_rel_D = shapiro_delay(e_D, p_D, q_D) # seconds - # Troposphere correction to time-delay - # Δτ_tropo_D = tropo_delay(R_r, ρ_vec_r) # seconds - # Solar corona correction to time-delay - # Δτ_corona_D = corona_delay(constant_term.(r_a_t_b), r_r_t_r, r_s_t_r, F_tx, station_code) # seconds - # Total time-delay - Δτ_D = Δτ_rel_D # + Δτ_tropo_D #+ Δτ_corona_D # seconds - - # New estimate - p_dot_23 = dot3D(ρ_vec_r, v_a_t_b)/ρ_r - # Time delay correction - Δt_2 = (τ_D - ρ_r/clightkms - Δτ_rel_D)/(1.0-p_dot_23/clightkms) - # Time delay new estimate - τ_D = τ_D - Δt_2 - # Bounce time, new estimate - # See equation (2) of https://doi.org/10.1086/116062 - et_b_secs = et_r_secs - τ_D - end - - # Asteroid barycentric position (in km) and velocity (in km/s) at bounce time (TDB) - rv_a_t_b = xva(et_b_secs) - r_a_t_b = rv_a_t_b[1:3] - v_a_t_b = rv_a_t_b[4:6] - # Estimated position of the asteroid's center of mass relative to the recieve point - # See equation (3) of https://doi.org/10.1086/116062 - ρ_vec_r = r_a_t_b - r_r_t_r - # Magnitude of ρ_vec_r - # See equation (4) of https://doi.org/10.1086/116062 - ρ_r = euclid3D(ρ_vec_r) - - # TODO: add aberration and atmospheric refraction corrections - - # Compute gravitational deflection of light - # See Explanatory Supplement to the Astronomical Almanac (ESAA) 2014 Section 7.4.1.4 - E_H_vec = r_r_t_r -r_s_t_r # ESAA 2014, equation (7.104) - U_vec = ρ_vec_r # r_a_t_b - r_e_t_r, ESAA 2014, equation (7.112) - U_norm = ρ_r # sqrt(U_vec[1]^2 + U_vec[2]^2 + U_vec[3]^2) - u_vec = U_vec/U_norm - # Barycentric position and velocity of Sun at converged bounce time - rv_s_t_b = xvs(et_b_secs) - r_s_t_b = rv_s_t_b[1:3] - Q_vec = r_a_t_b - r_s_t_b # ESAA 2014, equation (7.113) - q_vec = Q_vec/ euclid3D(Q_vec) - E_H = euclid3D(E_H_vec) - e_vec = E_H_vec/E_H - # See ESAA 2014, equation (7.115) - g1 = (2μ_DE430[su]/(c_au_per_day^2))/(E_H/au) - g2 = 1 + dot3D(q_vec, e_vec) - # See ESAA 2014, equation (7.116) - u1_vec = U_norm*( u_vec + (g1/g2)*( dot3D(u_vec,q_vec)*e_vec - dot3D(e_vec,u_vec)*q_vec ) ) - u1_norm = euclid3D(u1_vec) - - # Compute right ascension, declination angles - α_rad_ = mod2pi(atan(u1_vec[2], u1_vec[1])) - α_rad = mod2pi(α_rad_) # right ascension (rad) - δ_rad = asin(u1_vec[3]/u1_norm) # declination (rad) - - δ_as = rad2arcsec(δ_rad) # rad -> arcsec + debiasing - α_as = rad2arcsec(α_rad) # rad -> arcsec + debiasing - - return α_as, δ_as # right ascension, declination both in arcsec -end - -function compute_radec(obs::RadecMPC{T}; kwargs...) where {T <: AbstractFloat} - return compute_radec(obs.observatory, obs.date; kwargs...) -end - -function compute_radec(obs::Vector{RadecMPC{T}}; xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} - - # Number of observations - n_optical_obs = length(obs) - # UTC time of first astrometric observation - utc1 = obs[1].date - # TDB seconds since J2000.0 for first astrometric observation - et1 = datetime2et(utc1) - # Asteroid ephemeris at et1 - a1_et1 = xva(et1)[1] - # Type of asteroid ephemeris - S = typeof(a1_et1) - - # Right ascension - vra = Array{S}(undef, n_optical_obs) - # Declination - vdec = Array{S}(undef, n_optical_obs) - - # Iterate over the number of observations - for i in 1:n_optical_obs - vra[i], vdec[i] = compute_radec(obs[i]; xva = xva, kwargs...) - end - - return vra, vdec # arcsec, arcsec -end - -@doc raw""" - select_debiasing_table(debias_table::String = "2018") - -Return the catalogue codes, truth catalogue, resolution and bias matrix of the corresponding -debias table. The possible values for `debias_table` are: -- `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, -- `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, -- `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. -""" -function select_debiasing_table(debias_table::String = "2018") - # Debiasing tables are loaded "lazily" via Julia artifacts, according to rules in Artifacts.toml - if debias_table == "2018" - debias_path = artifact"debias_2018" - mpc_catalogue_codes_201X = mpc_catalogue_codes_2018 - # The healpix tesselation resolution of the bias map from https://doi.org/10.1016/j.icarus.2019.113596 - NSIDE = 64 - # In 2018 debias table Gaia DR2 catalogue is regarded as the truth - truth = "V" - elseif debias_table == "hires2018" - debias_path = artifact"debias_hires2018" - mpc_catalogue_codes_201X = mpc_catalogue_codes_2018 - # The healpix tesselation resolution of the high-resolution bias map from https://doi.org/10.1016/j.icarus.2019.113596 - NSIDE = 256 - # In 2018 debias table Gaia DR2 catalogue is regarded as the truth - truth = "V" - elseif debias_table == "2014" - debias_path = artifact"debias_2014" - mpc_catalogue_codes_201X = mpc_catalogue_codes_2014 - # The healpix tesselation resolution of the bias map from https://doi.org/10.1016/j.icarus.2014.07.033 - NSIDE= 64 - # In 2014 debias table PPMXL catalogue is regarded as the truth - truth = "t" - else - @error "Unknown bias map: $(debias_table). Possible values are `2014`, `2018` and `hires2018`." - end - - # Debias table file - bias_file = joinpath(debias_path, "bias.dat") - # Read bias matrix - bias_matrix = readdlm(bias_file, comment_char='!', comments=true) - # Initialize healpix Resolution variable - resol = Resolution(NSIDE) - # Compatibility between bias matrix and resolution - @assert size(bias_matrix) == (resol.numOfPixels, 4length(mpc_catalogue_codes_201X)) "Bias table file $bias_file dimensions do not match expected parameter NSIDE=$NSIDE and/or number of catalogs in table." - - return mpc_catalogue_codes_201X, truth, resol, bias_matrix -end - -@doc raw""" - debiasing(obs::RadecMPC{T}, mpc_catalogue_codes_201X::Vector{String}, truth::String, - resol::Resolution, bias_matrix::Matrix{T}) where {T <: AbstractFloat} - -Return total debiasing correction in right ascension and declination (both in arcsec). - -# Arguments - -- `obs::RadecMPC{T}`: optical observation. -- `mpc_catalogue_codes_201X::Vector{String}`: catalogues present in debiasing table. -- `truth::String`: truth catalogue of debiasing table. -- `resol::Resolution`: resolution. -- `bias_matrix::Matrix{T}`: debiasing table. -""" -function debiasing(obs::RadecMPC{T}, mpc_catalogue_codes_201X::Vector{String}, truth::String, - resol::Resolution, bias_matrix::Matrix{T}) where {T <: AbstractFloat} - - # Catalogue code - catcode = obs.catalogue.code - - # If star catalogue is not present in debiasing table, then set corrections equal to zero - if (catcode ∉ mpc_catalogue_codes_201X) && catcode != "Y" - # Catalogue exists in mpc_catalogues[] - if !isunknown(obs.catalogue) - # Truth catalogue is not present in debiasing table but it does not send a warning - if catcode != truth - @warn "Catalogue $(obs.catalogue.name) not found in debiasing table. Setting debiasing corrections equal to zero." - end - # Unknown catalogue - elseif catcode == "" - @warn "Catalog information not available in observation record. Setting debiasing corrections equal to zero." - # Catalogue code is not empty but it does not match an MPC catalogue code either - else - @warn "Catalog code $catcode does not correspond to MPC catalogue code. Setting debiasing corrections equal to zero." - end - α_corr = zero(T) - δ_corr = zero(T) - # If star catalogue is present in debiasing table, then compute corrections - else - # Get pixel tile index, assuming iso-latitude rings indexing, which is the formatting in `tiles.dat`. - # Substracting 1 from the returned value of `ang2pixRing` corresponds to 0-based indexing, as in `tiles.dat`; - # not substracting 1 from the returned value of `ang2pixRing` corresponds to 1-based indexing, as in Julia. - # Since we use pix_ind to get the corresponding row number in `bias.dat`, it's not necessary to substract 1. - pix_ind = ang2pixRing(resol, π/2 - obs.δ, obs.α) - - # Handle edge case: in new MPC catalogue nomenclature, "UCAC-5"->"Y"; but in debias tables "UCAC-5"->"W" - if catcode == "Y" - cat_ind = findfirst(x -> x == "W", mpc_catalogue_codes_201X) - else - cat_ind = findfirst(x -> x == catcode, mpc_catalogue_codes_201X) - end - - # Read dRA, pmRA, dDEC, pmDEC data from bias.dat - # dRA: position correction in RA * cos(DEC) at epoch J2000.0 [arcsec] - # dDEC: position correction in DEC at epoch J2000.0 [arcsec] - # pmRA: proper motion correction in RA*cos(DEC) [mas/yr] - # pmDEC: proper motion correction in DEC [mas/yr] - dRA, dDEC, pmRA, pmDEC = bias_matrix[pix_ind, 4*cat_ind-3:4*cat_ind] - # Seconds since J2000 (TDB) - et_secs_i = datetime2et(obs.date) - # Seconds sinde J2000 (TT) - tt_secs_i = et_secs_i - ttmtdb(et_secs_i/daysec) - # Years since J2000 - yrs_J2000_tt = tt_secs_i/(daysec*yr) - # Total debiasing correction in right ascension (arcsec) - α_corr = dRA + yrs_J2000_tt*pmRA/1_000 - # Total debiasing correction in declination (arcsec) - δ_corr = dDEC + yrs_J2000_tt*pmDEC/1_000 - end - - return α_corr, δ_corr -end - -@doc raw""" - w8sveres17(obs::RadecMPC{T}) where {T <: AbstractFloat} - -Return the statistical weight from Veres et al. (2017) corresponding to `obs`. -""" -function w8sveres17(obs::RadecMPC{T}) where {T <: AbstractFloat} - - obscode = obs.observatory.code - dt_utc_obs = obs.date - catalogue = obs.catalogue.code - - # Unit weight (arcseconds) - w = 1.0 - # Table 2: epoch-dependent astrometric residuals - if obscode == "703" - return Date(dt_utc_obs) < Date(2014,1,1) ? w : 0.8w - elseif obscode == "691" - return Date(dt_utc_obs) < Date(2003,1,1) ? 0.6w : 0.5w - elseif obscode == "644" - return Date(dt_utc_obs) < Date(2003,9,1) ? 0.6w : 0.4w - # Table 3: most active CCD asteroid observers - elseif obscode ∈ ("704", "C51", "J75") - return w - elseif obscode == "G96" - return 0.5w - elseif obscode == "F51" - return 0.2w - elseif obscode ∈ ("G45", "608") - return 0.6w - elseif obscode == "699" - return 0.8w - elseif obscode ∈ ("D29", "E12") - return 0.75w - # Table 4: - elseif obscode ∈ ("645", "673", "H01") - return 0.3w - elseif obscode ∈ ("J04", "K92", "K93", "Q63", "Q64", "V37", "W85", "W86", "W87", "K91", "E10", "F65") #Tenerife + Las Cumbres - return 0.4w - elseif obscode ∈ ("689", "950", "W84") - return 0.5w - #elseif obscode ∈ ("G83", "309") # Applies only to program code assigned to M. Micheli - # if catalogue ∈ ("q", "t") # "q"=>"UCAC-4", "t"=>"PPMXL" - # return 0.3w - # elseif catalogue ∈ ("U", "V") # Gaia-DR1, Gaia-DR2 - # return 0.2w - # end - elseif obscode ∈ ("Y28",) - if catalogue ∈ ("t", "U", "V") - return 0.3w - else - return w - end - elseif obscode ∈ ("568",) - if catalogue ∈ ("o", "s") # "o"=>"USNO-B1.0", "s"=>"USNO-B2.0" - return 0.5w - elseif catalogue ∈ ("U", "V") # Gaia DR1, DR2 - return 0.1w - elseif catalogue ∈ ("t",) #"t"=>"PPMXL" - return 0.2w - else - return w - end - elseif obscode ∈ ("T09", "T12", "T14") && catalogue ∈ ("U", "V") # Gaia DR1, DR2 - return 0.1w - elseif catalogue == "" - return 1.5w - elseif catalogue != "" - return w - else - return w - end -end - -@doc raw""" - relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - -Return a relax factor for each element of `radec` quantifying the correlation between -observations taken on the same night by the same observatory. - -!!! reference - See https://doi.org/10.1016/j.icarus.2017.05.021. -""" -function relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - # Convert to DataFrame - df = DataFrame(radec) - # Group by observatory and TimeOfDay - df.TimeOfDay = TimeOfDay.(radec) - gdf = groupby(df, [:observatory, :TimeOfDay]) - # Number of observations per tracklet - cdf = combine(gdf, nrow) - # Count observations in each group - Nv = cdf[gdf.groups, :nrow] - # Relaxation factor - return map(x -> x > 4.0 ? x/4.0 : 1.0, Nv) -end - -# Angle difference taking into account the discontinuity in [0, 2π] -> [0, 2π] -# x and y must be in arcsec -function anglediff(x::T, y::S) where {T, S <: Number} - # Signed difference - Δ = x - y - # Absolute difference - Δ_abs = abs(Δ) - # Reflection - if Δ_abs > 648_000 # Half circle in arcsec - return -sign(cte(Δ)) * (1_296_000 - Δ_abs) - else - return Δ - end -end - -@doc raw""" - residuals(obs::Vector{RadecMPC{T}}; kwargs...) where {T <: AbstractFloat, AstEph} - -Compute O-C residuals for optical astrometry. Corrections due to Earth orientation, LOD, -polar motion are computed by default. - -See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and -[`Healpix.ang2pixRing`](@ref). - -# Arguments - -- `obs::Vector{RadecMPC{T}}`: vector of observations. - -# Keyword arguments - -- `niter::Int = 5`: number of light-time solution iterations. -- `debias_table::String = "2018"`: possible values are: - - `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, - - `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, - - `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. -- `xve::EarthEph = earthposvel`: Earth ephemeris. -- `xvs::SunEph = sunposvel`: Sun ephemeris. -- `xva::AstEph`: asteroid ephemeris. - -All ephemeris must take [et seconds since J2000] and return [barycentric position in km -and velocity in km/sec]. -""" -function residuals(obs::Vector{RadecMPC{T}}; debias_table::String = "2018", xva::AstEph, - kwargs...) where {T <: AbstractFloat, AstEph} - mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) - return residuals(obs, mpc_catalogue_codes_201X, truth, resol, bias_matrix; xva, kwargs...) -end -function residuals(obs::Vector{RadecMPC{T}}, mpc_catalogue_codes_201X::Vector{String}, truth::String, - resol::Resolution, bias_matrix::Matrix{T}; xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} - - # Number of observations - N_obs = length(obs) - - # UTC time of first astrometric observation - utc1 = date(obs[1]) - # TDB seconds since J2000.0 for first astrometric observation - et1 = datetime2et(utc1) - # Asteroid ephemeris at et1 - a1_et1 = xva(et1)[1] - # Type of asteroid ephemeris - S = typeof(a1_et1) - - # Relax factors - rex = relax_factor(obs) - - # Vector of residuals - res = Vector{OpticalResidual{T, S}}(undef, N_obs) - - # Iterate over the observations - Threads.@threads for i in 1:N_obs - - # Observed ra/dec - α_obs = rad2arcsec(ra(obs[i])) # arcsec - δ_obs = rad2arcsec(dec(obs[i])) # arcsec - - # Computed ra/dec - α_comp, δ_comp = compute_radec(obs[i]; xva = xva, kwargs...) # arcsec - - # Debiasing corrections - α_corr, δ_corr = debiasing(obs[i], mpc_catalogue_codes_201X, truth, resol, bias_matrix) - - # Statistical weights from Veres et al. (2017) - w8 = w8sveres17(obs[i]) - - # O-C residual ra/dec - # Note: ra is multiplied by a metric factor cos(dec) to match the format of debiasing corrections - res[i] = OpticalResidual( - anglediff(α_obs, α_comp) * cos(dec(obs[i])) - α_corr, - δ_obs - δ_comp - δ_corr, - 1 / w8^2, - 1 / w8^2, - rex[i], - false - ) - - end - - return res +@doc raw""" + OpticalResidual{T <: Real, U <: Number} + +An astrometric optical observed minus computed residual. + +# Fields + +- `ξ_α::U`: right ascension residual. +- `ξ_δ::U`: declination residual. +- `w_α::T`: right ascension weight. +- `w_δ::T`: declination weight. +- `relax_factor::T`: relaxation factor. +- `outlier::Bool`: whether the residual is an outlier or not. +""" +@auto_hash_equals struct OpticalResidual{T <: Real, U <: Number} + ξ_α::U + ξ_δ::U + w_α::T + w_δ::T + relax_factor::T + outlier::Bool + # Inner constructor + function OpticalResidual{T, U}(ξ_α::U, ξ_δ::U, w_α::T, w_δ::T, relax_factor::T = one(T), + outlier::Bool = false) where {T <: Real, U <: Number} + new{T, U}(ξ_α, ξ_δ, w_α, w_δ, relax_factor, outlier) + end +end +# Outer constructor +function OpticalResidual(ξ_α::U, ξ_δ::U, w_α::T, w_δ::T, relax_factor::T = one(T), + outlier::Bool = false) where {T <: Real, U <: Number} + return OpticalResidual{T, U}(ξ_α, ξ_δ, w_α, w_δ, relax_factor, outlier) +end + +# Evaluate methods +function evaluate(res::OpticalResidual{T, TaylorN{T}}, x::Vector{T}) where {T <: Real} + return OpticalResidual(res.ξ_α(x), res.ξ_δ(x), res.w_α, res.w_δ, res.relax_factor, res.outlier) +end +(res::OpticalResidual{T, TaylorN{T}})(x::Vector{T}) where {T <: Real} = evaluate(res, x) + +function evaluate(res::AbstractVector{OpticalResidual{T, TaylorN{T}}}, x::Vector{T}) where {T <: Real} + res_new = Vector{OpticalResidual{T, T}}(undef, length(res)) + for i in eachindex(res) + res_new[i] = evaluate(res[i], x) + end + return res_new +end +(res::AbstractVector{OpticalResidual{T, TaylorN{T}}})(x::Vector{T}) where {T <: Real} = evaluate(res, x) + +# Print method for OpticalResidual +# Examples: +# α: -138.79801 δ: -89.80025 +# α: -134.79450 δ: -91.42509 (outlier) +function show(io::IO, x::OpticalResidual{T, U}) where {T <: Real, U <: Number} + outlier_flag = outlier(x) ? " (outlier)" : "" + print(io, "α: ", @sprintf("%+.5f", cte(x.ξ_α)), " δ: ", + @sprintf("%+.5f", cte(x.ξ_δ)), outlier_flag) +end + +@doc raw""" + unfold(ξs::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + +Concatenate right ascension and declination residuals for an orbit fit. +""" +function unfold(ξs::AbstractVector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + # Number of non outliers + L = count(x -> !x.outlier, ξs) + # Vector of residuals + res = Vector{U}(undef, 2*L) + # Vector of weights + w = Vector{T}(undef, 2*L) + # Global counter + k = 1 + # Fill residuals and weights + for i in eachindex(ξs) + if !ξs[i].outlier + # Right ascension + res[k] = ξs[i].ξ_α + w[k] = ξs[i].w_α / ξs[i].relax_factor + # Declination + res[k+L] = ξs[i].ξ_δ + w[k+L] = ξs[i].w_δ / ξs[i].relax_factor + # Update global counter + k += 1 + end + end + + return res, w +end + +# Functions to get specific fields of a OpticalResidual object +ra(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.ξ_α +dec(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.ξ_δ +weight_ra(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.w_α +weight_dec(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.w_δ +relax_factor(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.relax_factor +outlier(res::OpticalResidual{T, U}) where {T <: Real, U <: Number} = res.outlier + +euclid3D(x::Vector{U}) where {U <: Number} = sqrt(x[1]*x[1] + x[2]*x[2] + x[3]*x[3]) +dot3D(x::Vector{U}, y::Vector{V}) where {U, V <: Number} = x[1]*y[1] + x[2]*y[2] + x[3]*y[3] + +@doc raw""" + compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; kwargs...) where {T <: AbstractFloat} + compute_radec(obs::RadecMPC{T}; kwargs...) where {T <: AbstractFloat} + compute_radec(obs::Vector{RadecMPC{T}}; kwargs...) where {T <: AbstractFloat} + +Compute astrometric right ascension and declination (both in arcsec) for a set of MPC-formatted +observations. Corrections due to Earth orientation, LOD, polar motion are considered in +computations. + +# Arguments + +- `observatory::ObservatoryMPC{T}`: observation site. +- `t_r_utc::DateTime`: UTC time of astrometric observation. +- `obs::Vector{RadecMPC{T}}`: optical observation(s). + +# Keyword arguments + +- `niter::Int = 5`: number of light-time solution iterations. +- `xve::EarthEph = earthposvel`: Earth ephemeris. +- `xvs::SunEph = sunposvel`: Sun ephemeris. +- `xva::AstEph`: asteroid ephemeris. + +All ephemeris must take [et seconds since J2000] and return [barycentric position in km +and velocity in km/sec]. +""" +function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter::Int = 5, + xvs::SunEph = sunposvel, xve::EarthEph = earthposvel, + xva::AstEph) where {T <: AbstractFloat, SunEph, EarthEph, AstEph} + # Transform receiving time from UTC to TDB seconds since J2000 + et_r_secs = datetime2et(t_r_utc) + # Sun barycentric position and velocity at receive time + rv_s_t_r = xvs(et_r_secs) + r_s_t_r = rv_s_t_r[1:3] + # Earth's barycentric position and velocity at receive time + rv_e_t_r = xve(et_r_secs) + r_e_t_r = rv_e_t_r[1:3] + # Asteroid barycentric position and velocity at receive time + rv_a_t_r = xva(et_r_secs) + r_a_t_r = rv_a_t_r[1:3] + # Compute geocentric position/velocity of receiving antenna in inertial frame [km, km/s] + RV_r = obsposvelECI(observatory, et_r_secs) + R_r = RV_r[1:3] + # Receiver barycentric position and velocity at receive time + r_r_t_r = r_e_t_r + R_r + + # Down-leg iteration + # τ_D first approximation + # See equation (1) of https://doi.org/10.1086/116062 + ρ_vec_r = r_a_t_r - r_r_t_r + ρ_r = euclid3D(ρ_vec_r) + # -R_b/c, but delay is wrt asteroid Center (Brozovic et al., 2018) + τ_D = ρ_r/clightkms # (seconds) + # Bounce time, new estimate + # See equation (2) of https://doi.org/10.1086/116062 + et_b_secs = et_r_secs - τ_D + + # Allocate memmory for time-delays + Δτ_D = zero(τ_D) # Total time delay + Δτ_rel_D = zero(τ_D) # Shapiro delay + # Δτ_corona_D = zero(τ_D) # Delay due to Solar corona + Δτ_tropo_D = zero(τ_D) # Delay due to Earth's troposphere + + for i in 1:niter + # Asteroid barycentric position (in km) and velocity (in km/s) at bounce time (TDB) + rv_a_t_b = xva(et_b_secs) + r_a_t_b = rv_a_t_b[1:3] + v_a_t_b = rv_a_t_b[4:6] + # Estimated position of the asteroid's center of mass relative to the recieve point + # See equation (3) of https://doi.org/10.1086/116062 + ρ_vec_r = r_a_t_b - r_r_t_r + # Magnitude of ρ_vec_r + # See equation (4) of https://doi.org/10.1086/116062 + ρ_r = euclid3D(ρ_vec_r) + + # Compute down-leg Shapiro delay + # NOTE: when using PPN, substitute 2 -> 1+γ in expressions for Shapiro delay, + # Δτ_rel_[D|U] + + # Earth's position at t_r + e_D_vec = r_r_t_r - r_s_t_r + # Heliocentric distance of Earth at t_r + e_D = euclid3D(e_D_vec) + # Barycentric position of Sun at estimated bounce time + rv_s_t_b = xvs(et_b_secs) + r_s_t_b = rv_s_t_b[1:3] + # Heliocentric position of asteroid at t_b + p_D_vec = r_a_t_b - r_s_t_b + # Heliocentric distance of asteroid at t_b + p_D = euclid3D(p_D_vec) + # Signal path distance (down-leg) + q_D = ρ_r + + # Shapiro correction to time-delay + Δτ_rel_D = shapiro_delay(e_D, p_D, q_D) # seconds + # Troposphere correction to time-delay + # Δτ_tropo_D = tropo_delay(R_r, ρ_vec_r) # seconds + # Solar corona correction to time-delay + # Δτ_corona_D = corona_delay(constant_term.(r_a_t_b), r_r_t_r, r_s_t_r, F_tx, station_code) # seconds + # Total time-delay + Δτ_D = Δτ_rel_D # + Δτ_tropo_D #+ Δτ_corona_D # seconds + + # New estimate + p_dot_23 = dot3D(ρ_vec_r, v_a_t_b)/ρ_r + # Time delay correction + Δt_2 = (τ_D - ρ_r/clightkms - Δτ_rel_D)/(1.0-p_dot_23/clightkms) + # Time delay new estimate + τ_D = τ_D - Δt_2 + # Bounce time, new estimate + # See equation (2) of https://doi.org/10.1086/116062 + et_b_secs = et_r_secs - τ_D + end + + # Asteroid barycentric position (in km) and velocity (in km/s) at bounce time (TDB) + rv_a_t_b = xva(et_b_secs) + r_a_t_b = rv_a_t_b[1:3] + v_a_t_b = rv_a_t_b[4:6] + # Estimated position of the asteroid's center of mass relative to the recieve point + # See equation (3) of https://doi.org/10.1086/116062 + ρ_vec_r = r_a_t_b - r_r_t_r + # Magnitude of ρ_vec_r + # See equation (4) of https://doi.org/10.1086/116062 + ρ_r = euclid3D(ρ_vec_r) + + # TODO: add aberration and atmospheric refraction corrections + + # Compute gravitational deflection of light + # See Explanatory Supplement to the Astronomical Almanac (ESAA) 2014 Section 7.4.1.4 + E_H_vec = r_r_t_r -r_s_t_r # ESAA 2014, equation (7.104) + U_vec = ρ_vec_r # r_a_t_b - r_e_t_r, ESAA 2014, equation (7.112) + U_norm = ρ_r # sqrt(U_vec[1]^2 + U_vec[2]^2 + U_vec[3]^2) + u_vec = U_vec/U_norm + # Barycentric position and velocity of Sun at converged bounce time + rv_s_t_b = xvs(et_b_secs) + r_s_t_b = rv_s_t_b[1:3] + Q_vec = r_a_t_b - r_s_t_b # ESAA 2014, equation (7.113) + q_vec = Q_vec/ euclid3D(Q_vec) + E_H = euclid3D(E_H_vec) + e_vec = E_H_vec/E_H + # See ESAA 2014, equation (7.115) + g1 = (2μ_DE430[su]/(c_au_per_day^2))/(E_H/au) + g2 = 1 + dot3D(q_vec, e_vec) + # See ESAA 2014, equation (7.116) + u1_vec = U_norm*( u_vec + (g1/g2)*( dot3D(u_vec,q_vec)*e_vec - dot3D(e_vec,u_vec)*q_vec ) ) + u1_norm = euclid3D(u1_vec) + + # Compute right ascension, declination angles + α_rad_ = mod2pi(atan(u1_vec[2], u1_vec[1])) + α_rad = mod2pi(α_rad_) # right ascension (rad) + δ_rad = asin(u1_vec[3]/u1_norm) # declination (rad) + + δ_as = rad2arcsec(δ_rad) # rad -> arcsec + debiasing + α_as = rad2arcsec(α_rad) # rad -> arcsec + debiasing + + return α_as, δ_as # right ascension, declination both in arcsec +end + +function compute_radec(obs::RadecMPC{T}; kwargs...) where {T <: AbstractFloat} + return compute_radec(obs.observatory, obs.date; kwargs...) +end + +function compute_radec(obs::Vector{RadecMPC{T}}; xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} + + # Number of observations + n_optical_obs = length(obs) + # UTC time of first astrometric observation + utc1 = obs[1].date + # TDB seconds since J2000.0 for first astrometric observation + et1 = datetime2et(utc1) + # Asteroid ephemeris at et1 + a1_et1 = xva(et1)[1] + # Type of asteroid ephemeris + S = typeof(a1_et1) + + # Right ascension + vra = Array{S}(undef, n_optical_obs) + # Declination + vdec = Array{S}(undef, n_optical_obs) + + # Iterate over the number of observations + for i in 1:n_optical_obs + vra[i], vdec[i] = compute_radec(obs[i]; xva = xva, kwargs...) + end + + return vra, vdec # arcsec, arcsec +end + +@doc raw""" + select_debiasing_table(debias_table::String = "2018") + +Return the catalogue codes, truth catalogue, resolution and bias matrix of the corresponding +debias table. The possible values for `debias_table` are: +- `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, +- `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, +- `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. +""" +function select_debiasing_table(debias_table::String = "2018") + # Debiasing tables are loaded "lazily" via Julia artifacts, according to rules in Artifacts.toml + if debias_table == "2018" + debias_path = artifact"debias_2018" + mpc_catalogue_codes_201X = mpc_catalogue_codes_2018 + # The healpix tesselation resolution of the bias map from https://doi.org/10.1016/j.icarus.2019.113596 + NSIDE = 64 + # In 2018 debias table Gaia DR2 catalogue is regarded as the truth + truth = "V" + elseif debias_table == "hires2018" + debias_path = artifact"debias_hires2018" + mpc_catalogue_codes_201X = mpc_catalogue_codes_2018 + # The healpix tesselation resolution of the high-resolution bias map from https://doi.org/10.1016/j.icarus.2019.113596 + NSIDE = 256 + # In 2018 debias table Gaia DR2 catalogue is regarded as the truth + truth = "V" + elseif debias_table == "2014" + debias_path = artifact"debias_2014" + mpc_catalogue_codes_201X = mpc_catalogue_codes_2014 + # The healpix tesselation resolution of the bias map from https://doi.org/10.1016/j.icarus.2014.07.033 + NSIDE= 64 + # In 2014 debias table PPMXL catalogue is regarded as the truth + truth = "t" + else + @error "Unknown bias map: $(debias_table). Possible values are `2014`, `2018` and `hires2018`." + end + + # Debias table file + bias_file = joinpath(debias_path, "bias.dat") + # Read bias matrix + bias_matrix = readdlm(bias_file, comment_char='!', comments=true) + # Initialize healpix Resolution variable + resol = Resolution(NSIDE) + # Compatibility between bias matrix and resolution + @assert size(bias_matrix) == (resol.numOfPixels, 4length(mpc_catalogue_codes_201X)) "Bias table file $bias_file dimensions do not match expected parameter NSIDE=$NSIDE and/or number of catalogs in table." + + return mpc_catalogue_codes_201X, truth, resol, bias_matrix +end + +@doc raw""" + debiasing(obs::RadecMPC{T}, mpc_catalogue_codes_201X::Vector{String}, truth::String, + resol::Resolution, bias_matrix::Matrix{T}) where {T <: AbstractFloat} + +Return total debiasing correction in right ascension and declination (both in arcsec). + +# Arguments + +- `obs::RadecMPC{T}`: optical observation. +- `mpc_catalogue_codes_201X::Vector{String}`: catalogues present in debiasing table. +- `truth::String`: truth catalogue of debiasing table. +- `resol::Resolution`: resolution. +- `bias_matrix::Matrix{T}`: debiasing table. +""" +function debiasing(obs::RadecMPC{T}, mpc_catalogue_codes_201X::Vector{String}, truth::String, + resol::Resolution, bias_matrix::Matrix{T}) where {T <: AbstractFloat} + + # Catalogue code + catcode = obs.catalogue.code + + # If star catalogue is not present in debiasing table, then set corrections equal to zero + if (catcode ∉ mpc_catalogue_codes_201X) && catcode != "Y" + # Catalogue exists in mpc_catalogues[] + if !isunknown(obs.catalogue) + # Truth catalogue is not present in debiasing table but it does not send a warning + if catcode != truth + @warn "Catalogue $(obs.catalogue.name) not found in debiasing table. Setting debiasing corrections equal to zero." + end + # Unknown catalogue + elseif catcode == "" + @warn "Catalog information not available in observation record. Setting debiasing corrections equal to zero." + # Catalogue code is not empty but it does not match an MPC catalogue code either + else + @warn "Catalog code $catcode does not correspond to MPC catalogue code. Setting debiasing corrections equal to zero." + end + α_corr = zero(T) + δ_corr = zero(T) + # If star catalogue is present in debiasing table, then compute corrections + else + # Get pixel tile index, assuming iso-latitude rings indexing, which is the formatting in `tiles.dat`. + # Substracting 1 from the returned value of `ang2pixRing` corresponds to 0-based indexing, as in `tiles.dat`; + # not substracting 1 from the returned value of `ang2pixRing` corresponds to 1-based indexing, as in Julia. + # Since we use pix_ind to get the corresponding row number in `bias.dat`, it's not necessary to substract 1. + pix_ind = ang2pixRing(resol, π/2 - obs.δ, obs.α) + + # Handle edge case: in new MPC catalogue nomenclature, "UCAC-5"->"Y"; but in debias tables "UCAC-5"->"W" + if catcode == "Y" + cat_ind = findfirst(x -> x == "W", mpc_catalogue_codes_201X) + else + cat_ind = findfirst(x -> x == catcode, mpc_catalogue_codes_201X) + end + + # Read dRA, pmRA, dDEC, pmDEC data from bias.dat + # dRA: position correction in RA * cos(DEC) at epoch J2000.0 [arcsec] + # dDEC: position correction in DEC at epoch J2000.0 [arcsec] + # pmRA: proper motion correction in RA*cos(DEC) [mas/yr] + # pmDEC: proper motion correction in DEC [mas/yr] + dRA, dDEC, pmRA, pmDEC = bias_matrix[pix_ind, 4*cat_ind-3:4*cat_ind] + # Seconds since J2000 (TDB) + et_secs_i = datetime2et(obs.date) + # Seconds sinde J2000 (TT) + tt_secs_i = et_secs_i - ttmtdb(et_secs_i/daysec) + # Years since J2000 + yrs_J2000_tt = tt_secs_i/(daysec*yr) + # Total debiasing correction in right ascension (arcsec) + α_corr = dRA + yrs_J2000_tt*pmRA/1_000 + # Total debiasing correction in declination (arcsec) + δ_corr = dDEC + yrs_J2000_tt*pmDEC/1_000 + end + + return α_corr, δ_corr +end + +@doc raw""" + w8sveres17(obs::RadecMPC{T}) where {T <: AbstractFloat} + +Return the statistical weight from Veres et al. (2017) corresponding to `obs`. +""" +function w8sveres17(obs::RadecMPC{T}) where {T <: AbstractFloat} + + obscode = obs.observatory.code + dt_utc_obs = obs.date + catalogue = obs.catalogue.code + + # Unit weight (arcseconds) + w = 1.0 + # Table 2: epoch-dependent astrometric residuals + if obscode == "703" + return Date(dt_utc_obs) < Date(2014,1,1) ? w : 0.8w + elseif obscode == "691" + return Date(dt_utc_obs) < Date(2003,1,1) ? 0.6w : 0.5w + elseif obscode == "644" + return Date(dt_utc_obs) < Date(2003,9,1) ? 0.6w : 0.4w + # Table 3: most active CCD asteroid observers + elseif obscode ∈ ("704", "C51", "J75") + return w + elseif obscode == "G96" + return 0.5w + elseif obscode == "F51" + return 0.2w + elseif obscode ∈ ("G45", "608") + return 0.6w + elseif obscode == "699" + return 0.8w + elseif obscode ∈ ("D29", "E12") + return 0.75w + # Table 4: + elseif obscode ∈ ("645", "673", "H01") + return 0.3w + elseif obscode ∈ ("J04", "K92", "K93", "Q63", "Q64", "V37", "W85", "W86", "W87", "K91", "E10", "F65") #Tenerife + Las Cumbres + return 0.4w + elseif obscode ∈ ("689", "950", "W84") + return 0.5w + #elseif obscode ∈ ("G83", "309") # Applies only to program code assigned to M. Micheli + # if catalogue ∈ ("q", "t") # "q"=>"UCAC-4", "t"=>"PPMXL" + # return 0.3w + # elseif catalogue ∈ ("U", "V") # Gaia-DR1, Gaia-DR2 + # return 0.2w + # end + elseif obscode ∈ ("Y28",) + if catalogue ∈ ("t", "U", "V") + return 0.3w + else + return w + end + elseif obscode ∈ ("568",) + if catalogue ∈ ("o", "s") # "o"=>"USNO-B1.0", "s"=>"USNO-B2.0" + return 0.5w + elseif catalogue ∈ ("U", "V") # Gaia DR1, DR2 + return 0.1w + elseif catalogue ∈ ("t",) #"t"=>"PPMXL" + return 0.2w + else + return w + end + elseif obscode ∈ ("T09", "T12", "T14") && catalogue ∈ ("U", "V") # Gaia DR1, DR2 + return 0.1w + elseif catalogue == "" + return 1.5w + elseif catalogue != "" + return w + else + return w + end +end + +@doc raw""" + relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + +Return a relax factor for each element of `radec` quantifying the correlation between +observations taken on the same night by the same observatory. + +!!! reference + See https://doi.org/10.1016/j.icarus.2017.05.021. +""" +function relax_factor(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + # Convert to DataFrame + df = DataFrame(radec) + # Group by observatory and TimeOfDay + df.TimeOfDay = TimeOfDay.(radec) + gdf = groupby(df, [:observatory, :TimeOfDay]) + # Number of observations per tracklet + cdf = combine(gdf, nrow) + # Count observations in each group + Nv = cdf[gdf.groups, :nrow] + # Relaxation factor + return map(x -> x > 4.0 ? x/4.0 : 1.0, Nv) +end + +# Angle difference taking into account the discontinuity in [0, 2π] -> [0, 2π] +# x and y must be in arcsec +function anglediff(x::T, y::S) where {T, S <: Number} + # Signed difference + Δ = x - y + # Absolute difference + Δ_abs = abs(Δ) + # Reflection + if Δ_abs > 648_000 # Half circle in arcsec + return -sign(cte(Δ)) * (1_296_000 - Δ_abs) + else + return Δ + end +end + +@doc raw""" + residuals(obs::Vector{RadecMPC{T}}; kwargs...) where {T <: AbstractFloat, AstEph} + +Compute O-C residuals for optical astrometry. Corrections due to Earth orientation, LOD, +polar motion are computed by default. + +See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and +[`Healpix.ang2pixRing`](@ref). + +# Arguments + +- `obs::Vector{RadecMPC{T}}`: vector of observations. + +# Keyword arguments + +- `niter::Int = 5`: number of light-time solution iterations. +- `debias_table::String = "2018"`: possible values are: + - `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, + - `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, + - `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. +- `xve::EarthEph = earthposvel`: Earth ephemeris. +- `xvs::SunEph = sunposvel`: Sun ephemeris. +- `xva::AstEph`: asteroid ephemeris. + +All ephemeris must take [et seconds since J2000] and return [barycentric position in km +and velocity in km/sec]. +""" +function residuals(obs::Vector{RadecMPC{T}}; debias_table::String = "2018", xva::AstEph, + kwargs...) where {T <: AbstractFloat, AstEph} + mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) + return residuals(obs, mpc_catalogue_codes_201X, truth, resol, bias_matrix; xva, kwargs...) +end +function residuals(obs::Vector{RadecMPC{T}}, mpc_catalogue_codes_201X::Vector{String}, truth::String, + resol::Resolution, bias_matrix::Matrix{T}; xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} + + # Number of observations + N_obs = length(obs) + + # UTC time of first astrometric observation + utc1 = date(obs[1]) + # TDB seconds since J2000.0 for first astrometric observation + et1 = datetime2et(utc1) + # Asteroid ephemeris at et1 + a1_et1 = xva(et1)[1] + # Type of asteroid ephemeris + S = typeof(a1_et1) + + # Relax factors + rex = relax_factor(obs) + + # Vector of residuals + res = Vector{OpticalResidual{T, S}}(undef, N_obs) + + # Iterate over the observations + Threads.@threads for i in 1:N_obs + + # Observed ra/dec + α_obs = rad2arcsec(ra(obs[i])) # arcsec + δ_obs = rad2arcsec(dec(obs[i])) # arcsec + + # Computed ra/dec + α_comp, δ_comp = compute_radec(obs[i]; xva = xva, kwargs...) # arcsec + + # Debiasing corrections + α_corr, δ_corr = debiasing(obs[i], mpc_catalogue_codes_201X, truth, resol, bias_matrix) + + # Statistical weights from Veres et al. (2017) + w8 = w8sveres17(obs[i]) + + # O-C residual ra/dec + # Note: ra is multiplied by a metric factor cos(dec) to match the format of debiasing corrections + res[i] = OpticalResidual( + anglediff(α_obs, α_comp) * cos(dec(obs[i])) - α_corr, + δ_obs - δ_comp - δ_corr, + 1 / w8^2, + 1 / w8^2, + rex[i], + false + ) + + end + + return res end \ No newline at end of file diff --git a/src/observations/radar_jpl.jl b/src/observations/radar_jpl.jl old mode 100755 new mode 100644 index 58746f39..262de5d7 --- a/src/observations/radar_jpl.jl +++ b/src/observations/radar_jpl.jl @@ -1,349 +1,349 @@ -@doc raw""" - RadarJPL{T <: AbstractFloat} <: AbstractAstrometry - -A radar measurement in JPL format. - -# Fields - -- `id::String`: object's name and number. -- `date::DateTime`: date of observation. -- `Δτ::T`: time-delay. -- `Δτ_σ::T`: time-delay uncertainty. -- `Δτ_units::String`: units of time delay. -- `Δν::T`: Doppler shift. -- `Δν_σ::T`: Doppler shift uncertainty. -- `Δν_units::String`: units of Doppler shift. -- `freq::T`: frequency of the measurement. -- `rcvr::ObservatoryMPC{T}`: reciever antenna. -- `xmit::ObservatoryMPC{T}`: emission antenna. -- `bouncepoint::String`: bounce point. - ---- - - RadarJPL(delay::RegexMatch, doppler::RegexMatch) - RadarJPL(delay::RegexMatch, doppler::Val{false}) - RadarJPL(delay::Val{false}, doppler::RegexMatch) - RadarJPL(delay::Val{false}, doppler::Val{false}) - -Convert a match of `NEOs.RADAR_JPL_REGEX` to `RadarJPL`. A `Val{false}` indicates -that one or both of the measurements (time delay or Doppler shift) are missing. -""" -@auto_hash_equals struct RadarJPL{T <: AbstractFloat} <: AbstractAstrometry - id::String - date::DateTime - Δτ::T - Δτ_σ::T - Δτ_units::String - Δν::T - Δν_σ::T - Δν_units::String - freq::T - rcvr::ObservatoryMPC{T} - xmit::ObservatoryMPC{T} - bouncepoint::String - # Inner constructor - function RadarJPL{T}(id::String, date::DateTime, Δτ::T, Δτ_σ::T, Δτ_units::String, - Δν::T, Δν_σ::T, Δν_units::String, freq::T, rcvr::ObservatoryMPC{T}, - xmit::ObservatoryMPC{T}, bouncepoint::String) where {T <: AbstractFloat} - return new{T}(id, date, Δτ, Δτ_σ, Δτ_units, Δν, Δν_σ, Δν_units, freq, rcvr, - xmit, bouncepoint) - end -end - -# Outer constructor -function RadarJPL(id::String, date::DateTime, Δτ::T, Δτ_σ::T, Δτ_units::String, Δν::T, - Δν_σ::T, Δν_units::String, freq::T, rcvr::ObservatoryMPC{T}, - xmit::ObservatoryMPC{T}, bouncepoint::String) where {T <: AbstractFloat} - return RadarJPL{T}(id, date, Δτ, Δτ_σ, Δτ_units, Δν, Δν_σ, Δν_units, freq, rcvr, - xmit, bouncepoint) -end - -@doc raw""" - hasdelay(r::RadarJPL{T}) where {T <: AbstractFloat} - -Check whether `r` has a non `NaN` time delay. -""" -hasdelay(r::RadarJPL{T}) where {T <: AbstractFloat} = !isnan(r.Δτ) - -@doc raw""" - hasdoppler(r::RadarJPL{T}) where {T <: AbstractFloat} - -Check whether `r` has a non `NaN` Doppler shift. -""" -hasdoppler(r::RadarJPL{T}) where {T <: AbstractFloat} = !isnan(r.Δν) - -# Print method for RadarJPL -# Examples: -# 99942 Apophis (2004 MN4) Δτ: 1.9202850713e8 us Δν: -102512.9059 Hz t: 2005-01-29T00:00:00 -# 99942 Apophis (2004 MN4) Δν: -100849.1434 Hz t: 2005-01-27T23:31:00 -# 99942 Apophis (2004 MN4) Δτ: 9.743930871e7 us t: 2013-01-03T10:00:00 -function show(io::IO, r::RadarJPL{T}) where {T <: AbstractFloat} - - delay = hasdelay(r) - doppler = hasdoppler(r) - - if delay && doppler - measurement_s = string(" Δτ: ", string(r.Δτ), " ", r.Δτ_units, " Δν: ", - string(r.Δν), " ", r.Δν_units) - elseif delay - measurement_s = string(" Δτ: ", string(r.Δτ), " ", r.Δτ_units) - elseif doppler - measurement_s = string(" Δν: ", string(r.Δν), " ", r.Δν_units) - else - measurement_s = " No measurements " - end - - print(io, r.id, measurement_s, " t: ", r.date, " obs: ", r.rcvr.name) - -end - -# Functions to get specific fields of a RadarJPL object -delay(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δτ -delay_sigma(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δτ_σ -delay_units(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δτ_units -doppler(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δν -doppler_sigma(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δν_σ -doppler_units(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δν_units -freq(r::RadarJPL{T}) where {T <: AbstractFloat} = r.freq -rcvr(r::RadarJPL{T}) where {T <: AbstractFloat} = r.rcvr -xmit(r::RadarJPL{T}) where {T <: AbstractFloat} = r.xmit -bouncepoint(r::RadarJPL{T}) where {T <: AbstractFloat} = r.bouncepoint - -@doc raw""" - ismonostatic(rdata::RadarJPL) - -Check whether a radar astrometric observation is monostatic, i.e., receiver and transmitter are the same. -""" -ismonostatic(r::RadarJPL{T}) where {T <: AbstractFloat} = r.rcvr == r.xmit - -@doc raw""" - issband(f_MHz::T) where {T<:Real} - -Check whether the transmission frequency `f_MHz` (in MHz) belongs to the S band -(IEEE nomenclature). -""" -issband(f_MHz::T) where {T<:Real} = 2000.0 ≤ f_MHz ≤ 4000.0 - -@doc raw""" - isxband(f_MHz::T) where {T<:Real} - -Check whether the transmission frequency `f_MHz` (in MHz) belongs to the X band -(IEEE nomenclature). -""" -isxband(f_MHz::T) where {T<:Real} = 8000.0 ≤ f_MHz ≤ 12000.0 - -for (X, Y) in Iterators.product( (:(Val{false}), :(RegexMatch)), (:(Val{false}), :(RegexMatch)) ) - @eval begin - function RadarJPL(delay::$X, doppler::$Y) - - if $X == RegexMatch - id = string(delay["id"]) - elseif $Y == RegexMatch - id = string(doppler["id"]) - else - id = "" - end - - if $X == RegexMatch - date = DateTime(delay["date"], RADAR_JPL_DATEFORMAT) - elseif $Y == RegexMatch - date = DateTime(doppler["date"], RADAR_JPL_DATEFORMAT) - else - date = DateTime(2000, 1, 1) - end - - if $X == RegexMatch - Δτ = Meta.parse(delay["measurement"]) - Δτ_σ = Meta.parse(delay["uncertainty"]) - Δτ_units = string(delay["units"]) - else - Δτ = NaN - Δτ_σ = NaN - Δτ_units = "" - end - - if $Y == RegexMatch - Δν = Meta.parse(doppler["measurement"]) - Δν_σ = Meta.parse(doppler["uncertainty"]) - Δν_units = string(doppler["units"]) - else - Δν = NaN - Δν_σ = NaN - Δν_units = "" - end - - if $X == RegexMatch - freq = Float64(Meta.parse(delay["freq"])) - elseif $Y == RegexMatch - freq = Float64(Meta.parse(doppler["freq"])) - else - freq = NaN - end - - if $X == RegexMatch - rcvr = search_obs_code(string(delay["rcvr"])) - elseif $Y == RegexMatch - rcvr = search_obs_code(string(doppler["rcvr"])) - else - rcvr = unknownobs() - end - - if $X == RegexMatch - xmit = search_obs_code(string(delay["xmit"])) - elseif $Y == RegexMatch - xmit = search_obs_code(string(doppler["xmit"])) - else - xmit = unknownobs() - end - - if $X == RegexMatch - bouncepoint = string(delay["bouncepoint"]) - elseif $Y == RegexMatch - bouncepoint = string(doppler["bouncepoint"]) - else - bouncepoint = "" - end - - return RadarJPL(id, date, Δτ, Δτ_σ, Δτ_units, Δν, Δν_σ, Δν_units, freq, rcvr, xmit, bouncepoint) - end - end -end - -@doc raw""" - read_radar_jpl(filename::String) - -Return the matches of `NEOs.RADAR_JPL_REGEX` in `filename` as `Vector{RadarJPL{Float64}}`. -""" -function read_radar_jpl(filename::String) - - # Read lines of jpl formatted file - lines = readlines(filename) - # Apply regular expressions - matches = match.(RADAR_JPL_REGEX, lines) - # Eliminate nothings - filter!(!isnothing, matches) - # Number of matches - m = length(matches) - - # Dates of observation (as string) - dates = getindex.(matches, "date") - # Eliminate repeated dates - unique!(dates) - # Number of dates - m_dates = length(dates) - - # Time delays - delay = filter(x -> x["units"] == "us", matches) - # Number of time delays - m_Δτ = length(delay) - # Doppler shifts - doppler = filter(x -> x["units"] == "Hz", matches) - # Number of Doppler shifts - m_Δν = length(doppler) - - # Check if there were observations with unknown units - if m > m_Δτ + m_Δν - @warn("""$(m - m_Δτ - m_Δν) observations have units other than us (time delay) or Hz (doppler shift)""") - end - - # Vector of radar observations - radar = Vector{RadarJPL{Float64}}(undef, m_dates) - # Time delay index - i_τ = 1 - # Doppler shift index - i_ν = 1 - - # Iterate over the dates - for i in eachindex(dates) - # The i_τ-th time delay has the i-th date - if (i_τ <= m_Δτ) && (delay[i_τ]["date"] == dates[i]) - Δτ = delay[i_τ] - i_τ += 1 - flag_τ = true - else - flag_τ = false - end - - # The i_ν-th Doppler shift has the i-th date - if (i_ν <= m_Δν) && (doppler[i_ν]["date"] == dates[i]) - Δν = doppler[i_ν] - i_ν += 1 - flag_ν = true - else - flag_ν = false - end - - if flag_τ && flag_ν - radar[i] = RadarJPL(Δτ, Δν) - elseif flag_τ - radar[i] = RadarJPL(Δτ, Val(false)) - elseif flag_ν - radar[i] = RadarJPL(Val(false), Δν) - else - @warn("""Date $(dates[i]) has no time delay nor Doppler shift measurements""") - radar[i] = RadarJPL(Val(false), Val(false)) - end - - end - - # Sort radar measurements by date - sort!(radar) - - return radar -end - -# Convert `radar` to a string according to JPL format. -function string(radar::RadarJPL{T}) where {T <: AbstractFloat} - if hasdelay(radar) - delay_s = join([ - radar.id, - Dates.format(radar.date, RADAR_JPL_DATEFORMAT), - @sprintf("%.2f", radar.Δτ), - @sprintf("%1.3f", radar.Δτ_σ), - radar.Δτ_units, - @sprintf("%.0f", radar.freq), - radar.rcvr.code, - radar.xmit.code, - radar.bouncepoint, - "" - ], "\t", "\n") - else - delay_s = "" - end - - if hasdoppler(radar) - doppler_s = join([ - radar.id, - Dates.format(radar.date, RADAR_JPL_DATEFORMAT), - @sprintf("%.4f", radar.Δν), - @sprintf("%1.3f", radar.Δν_σ), - radar.Δν_units, - @sprintf("%.0f", radar.freq), - radar.rcvr.code, - radar.xmit.code, - radar.bouncepoint, - "" - ], "\t", "\n") - else - doppler_s = "" - end - - # Join everything - radar_s = string(delay_s, doppler_s) - - return radar_s -end - -@doc raw""" - write_radar_jpl(radar::Vector{RadarJPL{T}}, filename::String) where {T <: AbstractFloat} - -Write `radar` to `filename` in JPL format. -""" -function write_radar_jpl(radar::Vector{RadarJPL{T}}, filename::String) where {T <: AbstractFloat} - open(filename, "w") do file - for i in eachindex(radar) - line = string(radar[i]) - write(file, line) - end - end -end +@doc raw""" + RadarJPL{T <: AbstractFloat} <: AbstractAstrometry + +A radar measurement in JPL format. + +# Fields + +- `id::String`: object's name and number. +- `date::DateTime`: date of observation. +- `Δτ::T`: time-delay. +- `Δτ_σ::T`: time-delay uncertainty. +- `Δτ_units::String`: units of time delay. +- `Δν::T`: Doppler shift. +- `Δν_σ::T`: Doppler shift uncertainty. +- `Δν_units::String`: units of Doppler shift. +- `freq::T`: frequency of the measurement. +- `rcvr::ObservatoryMPC{T}`: reciever antenna. +- `xmit::ObservatoryMPC{T}`: emission antenna. +- `bouncepoint::String`: bounce point. + +--- + + RadarJPL(delay::RegexMatch, doppler::RegexMatch) + RadarJPL(delay::RegexMatch, doppler::Val{false}) + RadarJPL(delay::Val{false}, doppler::RegexMatch) + RadarJPL(delay::Val{false}, doppler::Val{false}) + +Convert a match of `NEOs.RADAR_JPL_REGEX` to `RadarJPL`. A `Val{false}` indicates +that one or both of the measurements (time delay or Doppler shift) are missing. +""" +@auto_hash_equals struct RadarJPL{T <: AbstractFloat} <: AbstractAstrometry + id::String + date::DateTime + Δτ::T + Δτ_σ::T + Δτ_units::String + Δν::T + Δν_σ::T + Δν_units::String + freq::T + rcvr::ObservatoryMPC{T} + xmit::ObservatoryMPC{T} + bouncepoint::String + # Inner constructor + function RadarJPL{T}(id::String, date::DateTime, Δτ::T, Δτ_σ::T, Δτ_units::String, + Δν::T, Δν_σ::T, Δν_units::String, freq::T, rcvr::ObservatoryMPC{T}, + xmit::ObservatoryMPC{T}, bouncepoint::String) where {T <: AbstractFloat} + return new{T}(id, date, Δτ, Δτ_σ, Δτ_units, Δν, Δν_σ, Δν_units, freq, rcvr, + xmit, bouncepoint) + end +end + +# Outer constructor +function RadarJPL(id::String, date::DateTime, Δτ::T, Δτ_σ::T, Δτ_units::String, Δν::T, + Δν_σ::T, Δν_units::String, freq::T, rcvr::ObservatoryMPC{T}, + xmit::ObservatoryMPC{T}, bouncepoint::String) where {T <: AbstractFloat} + return RadarJPL{T}(id, date, Δτ, Δτ_σ, Δτ_units, Δν, Δν_σ, Δν_units, freq, rcvr, + xmit, bouncepoint) +end + +@doc raw""" + hasdelay(r::RadarJPL{T}) where {T <: AbstractFloat} + +Check whether `r` has a non `NaN` time delay. +""" +hasdelay(r::RadarJPL{T}) where {T <: AbstractFloat} = !isnan(r.Δτ) + +@doc raw""" + hasdoppler(r::RadarJPL{T}) where {T <: AbstractFloat} + +Check whether `r` has a non `NaN` Doppler shift. +""" +hasdoppler(r::RadarJPL{T}) where {T <: AbstractFloat} = !isnan(r.Δν) + +# Print method for RadarJPL +# Examples: +# 99942 Apophis (2004 MN4) Δτ: 1.9202850713e8 us Δν: -102512.9059 Hz t: 2005-01-29T00:00:00 +# 99942 Apophis (2004 MN4) Δν: -100849.1434 Hz t: 2005-01-27T23:31:00 +# 99942 Apophis (2004 MN4) Δτ: 9.743930871e7 us t: 2013-01-03T10:00:00 +function show(io::IO, r::RadarJPL{T}) where {T <: AbstractFloat} + + delay = hasdelay(r) + doppler = hasdoppler(r) + + if delay && doppler + measurement_s = string(" Δτ: ", string(r.Δτ), " ", r.Δτ_units, " Δν: ", + string(r.Δν), " ", r.Δν_units) + elseif delay + measurement_s = string(" Δτ: ", string(r.Δτ), " ", r.Δτ_units) + elseif doppler + measurement_s = string(" Δν: ", string(r.Δν), " ", r.Δν_units) + else + measurement_s = " No measurements " + end + + print(io, r.id, measurement_s, " t: ", r.date, " obs: ", r.rcvr.name) + +end + +# Functions to get specific fields of a RadarJPL object +delay(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δτ +delay_sigma(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δτ_σ +delay_units(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δτ_units +doppler(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δν +doppler_sigma(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δν_σ +doppler_units(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δν_units +freq(r::RadarJPL{T}) where {T <: AbstractFloat} = r.freq +rcvr(r::RadarJPL{T}) where {T <: AbstractFloat} = r.rcvr +xmit(r::RadarJPL{T}) where {T <: AbstractFloat} = r.xmit +bouncepoint(r::RadarJPL{T}) where {T <: AbstractFloat} = r.bouncepoint + +@doc raw""" + ismonostatic(rdata::RadarJPL) + +Check whether a radar astrometric observation is monostatic, i.e., receiver and transmitter are the same. +""" +ismonostatic(r::RadarJPL{T}) where {T <: AbstractFloat} = r.rcvr == r.xmit + +@doc raw""" + issband(f_MHz::T) where {T<:Real} + +Check whether the transmission frequency `f_MHz` (in MHz) belongs to the S band +(IEEE nomenclature). +""" +issband(f_MHz::T) where {T<:Real} = 2000.0 ≤ f_MHz ≤ 4000.0 + +@doc raw""" + isxband(f_MHz::T) where {T<:Real} + +Check whether the transmission frequency `f_MHz` (in MHz) belongs to the X band +(IEEE nomenclature). +""" +isxband(f_MHz::T) where {T<:Real} = 8000.0 ≤ f_MHz ≤ 12000.0 + +for (X, Y) in Iterators.product( (:(Val{false}), :(RegexMatch)), (:(Val{false}), :(RegexMatch)) ) + @eval begin + function RadarJPL(delay::$X, doppler::$Y) + + if $X == RegexMatch + id = string(delay["id"]) + elseif $Y == RegexMatch + id = string(doppler["id"]) + else + id = "" + end + + if $X == RegexMatch + date = DateTime(delay["date"], RADAR_JPL_DATEFORMAT) + elseif $Y == RegexMatch + date = DateTime(doppler["date"], RADAR_JPL_DATEFORMAT) + else + date = DateTime(2000, 1, 1) + end + + if $X == RegexMatch + Δτ = Meta.parse(delay["measurement"]) + Δτ_σ = Meta.parse(delay["uncertainty"]) + Δτ_units = string(delay["units"]) + else + Δτ = NaN + Δτ_σ = NaN + Δτ_units = "" + end + + if $Y == RegexMatch + Δν = Meta.parse(doppler["measurement"]) + Δν_σ = Meta.parse(doppler["uncertainty"]) + Δν_units = string(doppler["units"]) + else + Δν = NaN + Δν_σ = NaN + Δν_units = "" + end + + if $X == RegexMatch + freq = Float64(Meta.parse(delay["freq"])) + elseif $Y == RegexMatch + freq = Float64(Meta.parse(doppler["freq"])) + else + freq = NaN + end + + if $X == RegexMatch + rcvr = search_obs_code(string(delay["rcvr"])) + elseif $Y == RegexMatch + rcvr = search_obs_code(string(doppler["rcvr"])) + else + rcvr = unknownobs() + end + + if $X == RegexMatch + xmit = search_obs_code(string(delay["xmit"])) + elseif $Y == RegexMatch + xmit = search_obs_code(string(doppler["xmit"])) + else + xmit = unknownobs() + end + + if $X == RegexMatch + bouncepoint = string(delay["bouncepoint"]) + elseif $Y == RegexMatch + bouncepoint = string(doppler["bouncepoint"]) + else + bouncepoint = "" + end + + return RadarJPL(id, date, Δτ, Δτ_σ, Δτ_units, Δν, Δν_σ, Δν_units, freq, rcvr, xmit, bouncepoint) + end + end +end + +@doc raw""" + read_radar_jpl(filename::String) + +Return the matches of `NEOs.RADAR_JPL_REGEX` in `filename` as `Vector{RadarJPL{Float64}}`. +""" +function read_radar_jpl(filename::String) + + # Read lines of jpl formatted file + lines = readlines(filename) + # Apply regular expressions + matches = match.(RADAR_JPL_REGEX, lines) + # Eliminate nothings + filter!(!isnothing, matches) + # Number of matches + m = length(matches) + + # Dates of observation (as string) + dates = getindex.(matches, "date") + # Eliminate repeated dates + unique!(dates) + # Number of dates + m_dates = length(dates) + + # Time delays + delay = filter(x -> x["units"] == "us", matches) + # Number of time delays + m_Δτ = length(delay) + # Doppler shifts + doppler = filter(x -> x["units"] == "Hz", matches) + # Number of Doppler shifts + m_Δν = length(doppler) + + # Check if there were observations with unknown units + if m > m_Δτ + m_Δν + @warn("""$(m - m_Δτ - m_Δν) observations have units other than us (time delay) or Hz (doppler shift)""") + end + + # Vector of radar observations + radar = Vector{RadarJPL{Float64}}(undef, m_dates) + # Time delay index + i_τ = 1 + # Doppler shift index + i_ν = 1 + + # Iterate over the dates + for i in eachindex(dates) + # The i_τ-th time delay has the i-th date + if (i_τ <= m_Δτ) && (delay[i_τ]["date"] == dates[i]) + Δτ = delay[i_τ] + i_τ += 1 + flag_τ = true + else + flag_τ = false + end + + # The i_ν-th Doppler shift has the i-th date + if (i_ν <= m_Δν) && (doppler[i_ν]["date"] == dates[i]) + Δν = doppler[i_ν] + i_ν += 1 + flag_ν = true + else + flag_ν = false + end + + if flag_τ && flag_ν + radar[i] = RadarJPL(Δτ, Δν) + elseif flag_τ + radar[i] = RadarJPL(Δτ, Val(false)) + elseif flag_ν + radar[i] = RadarJPL(Val(false), Δν) + else + @warn("""Date $(dates[i]) has no time delay nor Doppler shift measurements""") + radar[i] = RadarJPL(Val(false), Val(false)) + end + + end + + # Sort radar measurements by date + sort!(radar) + + return radar +end + +# Convert `radar` to a string according to JPL format. +function string(radar::RadarJPL{T}) where {T <: AbstractFloat} + if hasdelay(radar) + delay_s = join([ + radar.id, + Dates.format(radar.date, RADAR_JPL_DATEFORMAT), + @sprintf("%.2f", radar.Δτ), + @sprintf("%1.3f", radar.Δτ_σ), + radar.Δτ_units, + @sprintf("%.0f", radar.freq), + radar.rcvr.code, + radar.xmit.code, + radar.bouncepoint, + "" + ], "\t", "\n") + else + delay_s = "" + end + + if hasdoppler(radar) + doppler_s = join([ + radar.id, + Dates.format(radar.date, RADAR_JPL_DATEFORMAT), + @sprintf("%.4f", radar.Δν), + @sprintf("%1.3f", radar.Δν_σ), + radar.Δν_units, + @sprintf("%.0f", radar.freq), + radar.rcvr.code, + radar.xmit.code, + radar.bouncepoint, + "" + ], "\t", "\n") + else + doppler_s = "" + end + + # Join everything + radar_s = string(delay_s, doppler_s) + + return radar_s +end + +@doc raw""" + write_radar_jpl(radar::Vector{RadarJPL{T}}, filename::String) where {T <: AbstractFloat} + +Write `radar` to `filename` in JPL format. +""" +function write_radar_jpl(radar::Vector{RadarJPL{T}}, filename::String) where {T <: AbstractFloat} + open(filename, "w") do file + for i in eachindex(radar) + line = string(radar[i]) + write(file, line) + end + end +end diff --git a/src/observations/radec_mpc.jl b/src/observations/radec_mpc.jl old mode 100755 new mode 100644 index 797811dc..de5dbfb3 --- a/src/observations/radec_mpc.jl +++ b/src/observations/radec_mpc.jl @@ -1,449 +1,449 @@ -# Abstract type of RadecMPC and RadarJPL -abstract type AbstractAstrometry end -# Dummy types to parse right ascension and declination -struct RightAscension <: AbstractAstrometry end -struct Declination <: AbstractAstrometry end - -@doc raw""" - RadecMPC{T <: AbstractFloat} <: AbstractAstrometry - -An optical (right ascension, declination) measurement in MPC format. - -# Fields - -- `num::String`: object's number. -- `tmpdesig::String`: provisional / temporary designation. -- `discovery::String`: discovery asterisk. -- `publishnote::String`: publishable note. -- `obstech::String`: observation technique. -- `date::DateTime`: date of observation. -- `α::T`: right ascension [rad]. -- `δ::T`: declination [rad]. -- `info1::String`: additional information. -- `mag::T`: observed magnitude. -- `band::String`: magnitude band. -- `catalogue::CatalogueMPC`: catalogue. -- `info2::String`: additional information. -- `observatory::ObservatoryMPC{T}`: observatory. - -!!! reference - The format is described in https://minorplanetcenter.net/iau/info/OpticalObs.html - and discussed thoroughly in pages 158-181 of https://doi.org/10.1016/j.icarus.2010.06.003. -""" -@auto_hash_equals struct RadecMPC{T <: AbstractFloat} <: AbstractAstrometry - num::String - tmpdesig::String - discovery::String - publishnote::String - obstech::String - date::DateTime - α::T - δ::T - info1::String - mag::T - band::String - catalogue::CatalogueMPC - info2::String - observatory::ObservatoryMPC{T} - # Inner constructor - function RadecMPC{T}(num::String, tmpdesig::String, discovery::String, publishnote::String, - obstech::String, date::DateTime, α::T, δ::T, info1::String, mag::T, - band::String, catalogue::CatalogueMPC, info2::String, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - new{T}(num, tmpdesig, discovery, publishnote, obstech, date, α, δ, info1, mag, band, - catalogue, info2, observatory) - end -end - -# Outer constructor -function RadecMPC(num::String, tmpdesig::String, discovery::String, publishnote::String, - obstech::String, date::DateTime, α::T, δ::T, info1::String, mag::T, - band::String, catalogue::CatalogueMPC, info2::String, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - RadecMPC{T}(num, tmpdesig, discovery, publishnote, obstech, date, α, δ, info1, mag, band, - catalogue, info2, observatory) -end - -function RadecMPC(date::DateTime, α::T, δ::T, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - RadecMPC{T}("", "", "", "", "", date, α, δ, "", "", "", unknowncat(), "", observatory) -end - -# Print method for RadecMPC -# Examples: -# K08E68K α: 166.27754° δ: -0.66325° t: 2008-03-05T10:34:27.840 obs: Mt. Lemmon Survey -# 99942 α: 146.12752° δ: 13.31300° t: 2004-06-19T04:11:47.990 obs: Kitt Peak -function show(io::IO, m::RadecMPC{T}) where {T <: AbstractFloat} - # If there is no number, use temporary designation - id_str = filter(!isspace, m.num) == "" ? m.tmpdesig : m.num - - print(io, id_str, " α: ", @sprintf("%.5f", rad2deg(m.α)), "° δ: ", @sprintf("%.5f", rad2deg(m.δ)), "° t: ", m.date, - " obs: ", m.observatory.name) -end - -# Functions to get specific fields of a RadecMPC object -num(r::RadecMPC{T}) where {T <: AbstractFloat} = r.num -tmpdesig(r::RadecMPC{T}) where {T <: AbstractFloat} = r.tmpdesig -discovery(r::RadecMPC{T}) where {T <: AbstractFloat} = r.discovery -publishnote(r::RadecMPC{T}) where {T <: AbstractFloat} = r.publishnote -obstech(r::RadecMPC{T}) where {T <: AbstractFloat} = r.obstech -date(r::T) where {T <: AbstractAstrometry} = r.date -ra(r::RadecMPC{T}) where {T <: AbstractFloat} = r.α -dec(r::RadecMPC{T}) where {T <: AbstractFloat} = r.δ -info1(r::RadecMPC{T}) where {T <: AbstractFloat} = r.info1 -mag(r::RadecMPC{T}) where {T <: AbstractFloat} = r.mag -band(r::RadecMPC{T}) where {T <: AbstractFloat} = r.band -catalogue(r::RadecMPC{T}) where {T <: AbstractFloat} = r.catalogue -info2(r::RadecMPC{T}) where {T <: AbstractFloat} = r.info2 -observatory(r::RadecMPC{T}) where {T <: AbstractFloat} = r.observatory - -# Order in AbstractAstrometry is given by date -isless(a::T, b::T) where {T <: AbstractAstrometry} = a.date < b.date - -function neoparse(x::RegexMatch, i::Int, ::Type{Int64}) - y = tryparse(Int64, x[i]) - if isnothing(y) - return 0 - else - return y - end -end - -function neoparse(x::RegexMatch, i::Int, ::Type{DateTime}) - date = DateTime(x[i][1:10], "yyyy mm dd") - utc = parse(Float64, x[i][11:end]) - return date + Microsecond( round(1e6*86_400*utc) ) -end - -function neoparse(x::RegexMatch, i::Int, ::Type{RightAscension}) - # Unfold - hrs = parse(Int, x[i][1:2]) - min = parse(Int, x[i][4:5]) - sec = parse(Float64, x[i][7:end]) - # Convert hours minutes seconds to deg - α_deg = 15*(hrs + min/60 + sec/3_600) - # Convert deg to rad - α_rad = deg2rad(α_deg) - - return α_rad - -end - -function neoparse(x::RegexMatch, i::Int, ::Type{Declination}) - # Unfold - sgn = Char(x[i][1]) - deg = parse(Int, x[i][2:3]) - min = parse(Int, x[i][5:6]) - sec = parse(Float64, x[i][8:end]) - # Convert degrees minutes seconds to degrees - if sgn == '+' - δ_deg = +(deg + min/60 + sec/3_600) - elseif sgn == '-' - δ_deg = -(deg + min/60 + sec/3_600) - end - - δ_rad = deg2rad(δ_deg) - - return δ_rad -end - -neoparse(x::RegexMatch, i::Int, ::Type{CatalogueMPC}) = search_cat_code(String(x[i])) - -function neoparse(m::RegexMatch, i::Int, ::Type{ObservatoryMPC{Float64}}) - _observatory_ = search_obs_code(String(m[i])) - if isnothing(m["optional"]) - return _observatory_ - else - units = neoparse(m, 22, Int64) - x = neoparse(m, 23, Float64) - y = neoparse(m, 24, Float64) - z = neoparse(m, 25, Float64) - date = neoparse(m, 6, DateTime) - if units == 2 - x *= au - y *= au - z *= au - end - return ObservatoryMPC(_observatory_.code, x, y, z, _observatory_.name, date, :satellite, units) - end -end - -@doc raw""" - RadecMPC(m::RegexMatch) - -Convert a match of `NEOs.RADEC_MPC_REGEX` to `RadecMPC`. -""" -function RadecMPC(m::RegexMatch) - # Check that matched regex is correct - @assert m.regex == RADEC_MPC_REGEX "Only matches of `NEOs.RADEC_MPC_REGEX` can be converted to `RadecMPC`." - # Field types - types = fieldtypes(RadecMPC{Float64}) - # RadecMPC{Float64} fields - args = map(i -> begin - if i == 7 - neoparse(m, i, RightAscension) - elseif i == 8 - neoparse(m, i, Declination) - else - neoparse(m, i, types[i]) - end - end, 1:length(types)) - - return RadecMPC(args...) -end - -@doc raw""" - read_radec_mpc(s::String) - -Return the matches of `NEOs.RADEC_MPC_REGEX` in `s` as `Vector{RadecMPC{Float64}}`. -`s` can be either a filename or a text. -""" -function read_radec_mpc(s::String) - if !contains(s, "\n") && isfile(s) - # Read MPC formatted file - s = String(read(s)) - end - # Vector of observations - radec = Vector{RadecMPC{Float64}}(undef, 0) - # Iterate over the matches - for m in eachmatch(RADEC_MPC_REGEX, s) - push!(radec, RadecMPC(m)) - end - # Eliminate repeated entries - unique!(radec) - # Sort observations by date - sort!(radec) - - return radec -end - -@doc raw""" - mpc_date_str(date::DateTime) - -Return the date in MPC format. -""" -function mpc_date_str(date::DateTime) - - # Year string - year_s = lpad(Dates.year(date), 4) - # Month string - month_s = lpad(Dates.month(date), 2, "0") - # Hours [days] - hrs = Dates.hour(date) / 24 - # Minutes [days] - min = Dates.minute(date) / 24 / 60 - # Seconds [days] - sec = Dates.second(date) / 24 / 60 / 60 - # Milliseconds [days] - mls = Dates.millisecond(date) / 24 / 60 / 60 / 1_000 - # Days - day_val = Dates.day(date) + hrs + min + sec + mls - # Days string - day_s = @sprintf("%09.6f", day_val) - # Join everything - date_s = string(year_s, " ", month_s, " ", day_s) - - return date_s -end - -@doc raw""" - mpc_α_str(α::T) where {T <: Number} - -Return the right ascension [rad] in MPC format. -""" -function mpc_α_str(α::T) where {T <: Number} - # Convert rad to deg - α_deg = rad2deg(α) - # Hours - hrs_, hrs = modf(α_deg / 15) - hrs = Int(hrs) - # Hours string - hrs_s = lpad(hrs, 2, "0") - # Minutes - min_, min = modf(60 * hrs_) - min = Int(min) - # Minutes string - min_s = lpad(min, 2, "0") - # Seconds - sec = 60 * min_ - # Seconds string - sec_s = @sprintf("%06.3f", sec) - # Join everything - α_s = string(hrs_s, " ", min_s, " ", sec_s) - - return α_s -end - -@doc raw""" - mpc_δ_str(δ::T) where {T <: Number} - -Return the declination [rad] in MPC format. -""" -function mpc_δ_str(δ::T) where {T <: Number} - # Sign string - sgn_s = δ >= 0 ? "+" : "-" - # Convert rad to deg - δ_deg = abs(rad2deg(δ)) - # Degrees - deg_, deg = modf(δ_deg) - deg = Int(deg) - # Degrees string - deg_s = lpad(deg, 2, "0") - # Minutes - min_, min = modf(60 * deg_) - min = Int(min) - # Minutes string - min_s = lpad(min, 2, "0") - # Seconds - sec = 60 * min_ - # Seconds string - sec_s = @sprintf("%05.2f", sec) - # Join everything - δ_s = string(sgn_s, deg_s, " ", min_s, " ", sec_s) - - return δ_s -end - -function mpc_x_str(x::T) where {T <: AbstractFloat} - sgn = x > 0 ? "+" : "-" - y = string(abs(x)) - y = lpad(y, 10) - return string(sgn, y, " ") -end - -# Convert `obs` to a string according to MPC format. -function string(obs::RadecMPC{T}) where {T <: AbstractFloat} - # Number string - num_s = rpad(obs.num, 5) - # Temporary designation string - tmpdesig_s = rpad(obs.tmpdesig, 7) - # Discovery asterisk string - discovery_s = rpad(obs.discovery, 1) - # Publishable note string - publishnote_s = rpad(obs.publishnote, 1) - # Observation technique string - obstech_s = rpad(obs.obstech, 1) - # Date string - date_s = mpc_date_str(obs.date) - # Right ascension string - α_s = mpc_α_str(obs.α) - # Declination string - δ_s = mpc_δ_str(obs.δ) - # Info 1 string - info1_s = rpad(obs.info1, 9) - # Magnitude string - mag_s = isnan(obs.mag) ? repeat(" ", 5) : @sprintf("%.2f", obs.mag) - # Band string - band_s = rpad(obs.band, 1) - # Info 2 string - info2_s = rpad(obs.info2, 5) - # Catalogue string - catalogue_s = isunknown(obs.catalogue) ? " " : obs.catalogue.code - # Observatory string - obscode_s = isunknown(obs.observatory) ? " " : obs.observatory.code - # Join everything - obs_s = string(num_s, tmpdesig_s, discovery_s, publishnote_s, obstech_s, date_s, α_s, δ_s, - info1_s, mag_s, band_s, catalogue_s, info2_s, obscode_s) - - if issatellite(obs.observatory) - # Units string - units = obs.observatory.units - units_s = rpad(units, 1) - - x = obs.observatory.long - y = obs.observatory.cos - z = obs.observatory.sin - if units == 2 - x /= au - y /= au - z /= au - end - - # X component string - x_s = mpc_x_str(x) - # Y component string - y_s = mpc_x_str(y) - # Z component string - z_s = mpc_x_str(z) - obs_s = string(obs_s, "\n", num_s, tmpdesig_s, " ", publishnote_s, "s", date_s, - units_s, " ", x_s, y_s, z_s, " ", info2_s, obscode_s) - end - - return obs_s -end - -@doc raw""" - write_radec_mpc(obs::Vector{RadecMPC{T}}, filename::String) where {T <: AbstractFloat} - -Write `obs` to `filename` in MPC format. -""" -function write_radec_mpc(obs::Vector{RadecMPC{T}}, filename::String) where {T <: AbstractFloat} - open(filename, "w") do file - for i in eachindex(obs) - line = string(obs[i]) - write(file, line, "\n") - end - end -end - -@doc raw""" - get_radec_mpc(id::Pair{String, String}, filename::String = replace(id[2], " " => "_") * ".txt") - -Download MPC optical astrometry of NEO `id` and save the output to `filename`. -""" -function get_radec_mpc(id::Pair{String, String}, filename::String = replace(id[2], " " => "_") * ".txt") - # HTTP query - query = ["table" => "observations", id] - resp = get("http://minorplanetcenter.net/search_db"; query = query) - # Converty to String - text = String(resp.body) - # Parse JSON - obs = JSON.parse(text) - # Find matches - matches = Vector{Union{RegexMatch, Nothing}}(undef, length(obs)) - for i in eachindex(obs) - s = obs[i]["original_record"] - matches[i] = match(RADEC_MPC_REGEX, s) - end - filter!(!isnothing, matches) - # Parse RadecMPC - radec = RadecMPC.(matches) - # Write observations to file - write_radec_mpc(radec, filename) - - return filename -end - -@doc raw""" - fetch_radec_mpc(id::Pair{String, String}) - -Download MPC optical astrometry of NEO `id` and return the output as `Vector{RadecMPC{Float64}}`. -""" -function fetch_radec_mpc(id::Pair{String, String}) - # Temporary file - f = tempname() - # Download optical astrometry - get_radec_mpc(id, f) - # Parse optical astrometry - radec = read_radec_mpc(f) - # Delete temporary file - rm(f) - - return radec -end - -# Methods to convert a Vector{<:AbstractAstrometry} to a DataFrame -istable(::Type{Vector{<:AbstractAstrometry}}) = true -rowaccess(::Type{Vector{<:AbstractAstrometry}}) = true -rows(x::Vector{<:AbstractAstrometry}) = x -schema(::Vector{T}) where {T <: AbstractAstrometry} = Schema(fieldnames(T), Tuple{fieldtypes(T)...}) - -# Methods to convert a DataFrame to a Vector{<:AbstractAstrometry} -function Vector{T}(df::AbstractDataFrame) where {T <: AbstractAstrometry} - @assert all(String.(fieldnames(T)) .== names(df)) "`DataFrame` column names don't match `$T` fieldnames" - @assert all(fieldtypes(T) .== eltype.(eachcol(df))) "`DataFrame` column types don't match `$T` fieldtypes" - obs = Vector{T}(undef, nrow(df)) - for (i, row) in zip(eachindex(obs), eachrow(df)) - obs[i] = T(values(row)...) - end - return obs -end - -convert(::Type{Vector{T}}, df::DataFrame) where {T <: AbstractAstrometry} = Vector{T}(df) +# Abstract type of RadecMPC and RadarJPL +abstract type AbstractAstrometry end +# Dummy types to parse right ascension and declination +struct RightAscension <: AbstractAstrometry end +struct Declination <: AbstractAstrometry end + +@doc raw""" + RadecMPC{T <: AbstractFloat} <: AbstractAstrometry + +An optical (right ascension, declination) measurement in MPC format. + +# Fields + +- `num::String`: object's number. +- `tmpdesig::String`: provisional / temporary designation. +- `discovery::String`: discovery asterisk. +- `publishnote::String`: publishable note. +- `obstech::String`: observation technique. +- `date::DateTime`: date of observation. +- `α::T`: right ascension [rad]. +- `δ::T`: declination [rad]. +- `info1::String`: additional information. +- `mag::T`: observed magnitude. +- `band::String`: magnitude band. +- `catalogue::CatalogueMPC`: catalogue. +- `info2::String`: additional information. +- `observatory::ObservatoryMPC{T}`: observatory. + +!!! reference + The format is described in https://minorplanetcenter.net/iau/info/OpticalObs.html + and discussed thoroughly in pages 158-181 of https://doi.org/10.1016/j.icarus.2010.06.003. +""" +@auto_hash_equals struct RadecMPC{T <: AbstractFloat} <: AbstractAstrometry + num::String + tmpdesig::String + discovery::String + publishnote::String + obstech::String + date::DateTime + α::T + δ::T + info1::String + mag::T + band::String + catalogue::CatalogueMPC + info2::String + observatory::ObservatoryMPC{T} + # Inner constructor + function RadecMPC{T}(num::String, tmpdesig::String, discovery::String, publishnote::String, + obstech::String, date::DateTime, α::T, δ::T, info1::String, mag::T, + band::String, catalogue::CatalogueMPC, info2::String, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + new{T}(num, tmpdesig, discovery, publishnote, obstech, date, α, δ, info1, mag, band, + catalogue, info2, observatory) + end +end + +# Outer constructor +function RadecMPC(num::String, tmpdesig::String, discovery::String, publishnote::String, + obstech::String, date::DateTime, α::T, δ::T, info1::String, mag::T, + band::String, catalogue::CatalogueMPC, info2::String, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + RadecMPC{T}(num, tmpdesig, discovery, publishnote, obstech, date, α, δ, info1, mag, band, + catalogue, info2, observatory) +end + +function RadecMPC(date::DateTime, α::T, δ::T, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + RadecMPC{T}("", "", "", "", "", date, α, δ, "", "", "", unknowncat(), "", observatory) +end + +# Print method for RadecMPC +# Examples: +# K08E68K α: 166.27754° δ: -0.66325° t: 2008-03-05T10:34:27.840 obs: Mt. Lemmon Survey +# 99942 α: 146.12752° δ: 13.31300° t: 2004-06-19T04:11:47.990 obs: Kitt Peak +function show(io::IO, m::RadecMPC{T}) where {T <: AbstractFloat} + # If there is no number, use temporary designation + id_str = filter(!isspace, m.num) == "" ? m.tmpdesig : m.num + + print(io, id_str, " α: ", @sprintf("%.5f", rad2deg(m.α)), "° δ: ", @sprintf("%.5f", rad2deg(m.δ)), "° t: ", m.date, + " obs: ", m.observatory.name) +end + +# Functions to get specific fields of a RadecMPC object +num(r::RadecMPC{T}) where {T <: AbstractFloat} = r.num +tmpdesig(r::RadecMPC{T}) where {T <: AbstractFloat} = r.tmpdesig +discovery(r::RadecMPC{T}) where {T <: AbstractFloat} = r.discovery +publishnote(r::RadecMPC{T}) where {T <: AbstractFloat} = r.publishnote +obstech(r::RadecMPC{T}) where {T <: AbstractFloat} = r.obstech +date(r::T) where {T <: AbstractAstrometry} = r.date +ra(r::RadecMPC{T}) where {T <: AbstractFloat} = r.α +dec(r::RadecMPC{T}) where {T <: AbstractFloat} = r.δ +info1(r::RadecMPC{T}) where {T <: AbstractFloat} = r.info1 +mag(r::RadecMPC{T}) where {T <: AbstractFloat} = r.mag +band(r::RadecMPC{T}) where {T <: AbstractFloat} = r.band +catalogue(r::RadecMPC{T}) where {T <: AbstractFloat} = r.catalogue +info2(r::RadecMPC{T}) where {T <: AbstractFloat} = r.info2 +observatory(r::RadecMPC{T}) where {T <: AbstractFloat} = r.observatory + +# Order in AbstractAstrometry is given by date +isless(a::T, b::T) where {T <: AbstractAstrometry} = a.date < b.date + +function neoparse(x::RegexMatch, i::Int, ::Type{Int64}) + y = tryparse(Int64, x[i]) + if isnothing(y) + return 0 + else + return y + end +end + +function neoparse(x::RegexMatch, i::Int, ::Type{DateTime}) + date = DateTime(x[i][1:10], "yyyy mm dd") + utc = parse(Float64, x[i][11:end]) + return date + Microsecond( round(1e6*86_400*utc) ) +end + +function neoparse(x::RegexMatch, i::Int, ::Type{RightAscension}) + # Unfold + hrs = parse(Int, x[i][1:2]) + min = parse(Int, x[i][4:5]) + sec = parse(Float64, x[i][7:end]) + # Convert hours minutes seconds to deg + α_deg = 15*(hrs + min/60 + sec/3_600) + # Convert deg to rad + α_rad = deg2rad(α_deg) + + return α_rad + +end + +function neoparse(x::RegexMatch, i::Int, ::Type{Declination}) + # Unfold + sgn = Char(x[i][1]) + deg = parse(Int, x[i][2:3]) + min = parse(Int, x[i][5:6]) + sec = parse(Float64, x[i][8:end]) + # Convert degrees minutes seconds to degrees + if sgn == '+' + δ_deg = +(deg + min/60 + sec/3_600) + elseif sgn == '-' + δ_deg = -(deg + min/60 + sec/3_600) + end + + δ_rad = deg2rad(δ_deg) + + return δ_rad +end + +neoparse(x::RegexMatch, i::Int, ::Type{CatalogueMPC}) = search_cat_code(String(x[i])) + +function neoparse(m::RegexMatch, i::Int, ::Type{ObservatoryMPC{Float64}}) + _observatory_ = search_obs_code(String(m[i])) + if isnothing(m["optional"]) + return _observatory_ + else + units = neoparse(m, 22, Int64) + x = neoparse(m, 23, Float64) + y = neoparse(m, 24, Float64) + z = neoparse(m, 25, Float64) + date = neoparse(m, 6, DateTime) + if units == 2 + x *= au + y *= au + z *= au + end + return ObservatoryMPC(_observatory_.code, x, y, z, _observatory_.name, date, :satellite, units) + end +end + +@doc raw""" + RadecMPC(m::RegexMatch) + +Convert a match of `NEOs.RADEC_MPC_REGEX` to `RadecMPC`. +""" +function RadecMPC(m::RegexMatch) + # Check that matched regex is correct + @assert m.regex == RADEC_MPC_REGEX "Only matches of `NEOs.RADEC_MPC_REGEX` can be converted to `RadecMPC`." + # Field types + types = fieldtypes(RadecMPC{Float64}) + # RadecMPC{Float64} fields + args = map(i -> begin + if i == 7 + neoparse(m, i, RightAscension) + elseif i == 8 + neoparse(m, i, Declination) + else + neoparse(m, i, types[i]) + end + end, 1:length(types)) + + return RadecMPC(args...) +end + +@doc raw""" + read_radec_mpc(s::String) + +Return the matches of `NEOs.RADEC_MPC_REGEX` in `s` as `Vector{RadecMPC{Float64}}`. +`s` can be either a filename or a text. +""" +function read_radec_mpc(s::String) + if !contains(s, "\n") && isfile(s) + # Read MPC formatted file + s = String(read(s)) + end + # Vector of observations + radec = Vector{RadecMPC{Float64}}(undef, 0) + # Iterate over the matches + for m in eachmatch(RADEC_MPC_REGEX, s) + push!(radec, RadecMPC(m)) + end + # Eliminate repeated entries + unique!(radec) + # Sort observations by date + sort!(radec) + + return radec +end + +@doc raw""" + mpc_date_str(date::DateTime) + +Return the date in MPC format. +""" +function mpc_date_str(date::DateTime) + + # Year string + year_s = lpad(Dates.year(date), 4) + # Month string + month_s = lpad(Dates.month(date), 2, "0") + # Hours [days] + hrs = Dates.hour(date) / 24 + # Minutes [days] + min = Dates.minute(date) / 24 / 60 + # Seconds [days] + sec = Dates.second(date) / 24 / 60 / 60 + # Milliseconds [days] + mls = Dates.millisecond(date) / 24 / 60 / 60 / 1_000 + # Days + day_val = Dates.day(date) + hrs + min + sec + mls + # Days string + day_s = @sprintf("%09.6f", day_val) + # Join everything + date_s = string(year_s, " ", month_s, " ", day_s) + + return date_s +end + +@doc raw""" + mpc_α_str(α::T) where {T <: Number} + +Return the right ascension [rad] in MPC format. +""" +function mpc_α_str(α::T) where {T <: Number} + # Convert rad to deg + α_deg = rad2deg(α) + # Hours + hrs_, hrs = modf(α_deg / 15) + hrs = Int(hrs) + # Hours string + hrs_s = lpad(hrs, 2, "0") + # Minutes + min_, min = modf(60 * hrs_) + min = Int(min) + # Minutes string + min_s = lpad(min, 2, "0") + # Seconds + sec = 60 * min_ + # Seconds string + sec_s = @sprintf("%06.3f", sec) + # Join everything + α_s = string(hrs_s, " ", min_s, " ", sec_s) + + return α_s +end + +@doc raw""" + mpc_δ_str(δ::T) where {T <: Number} + +Return the declination [rad] in MPC format. +""" +function mpc_δ_str(δ::T) where {T <: Number} + # Sign string + sgn_s = δ >= 0 ? "+" : "-" + # Convert rad to deg + δ_deg = abs(rad2deg(δ)) + # Degrees + deg_, deg = modf(δ_deg) + deg = Int(deg) + # Degrees string + deg_s = lpad(deg, 2, "0") + # Minutes + min_, min = modf(60 * deg_) + min = Int(min) + # Minutes string + min_s = lpad(min, 2, "0") + # Seconds + sec = 60 * min_ + # Seconds string + sec_s = @sprintf("%05.2f", sec) + # Join everything + δ_s = string(sgn_s, deg_s, " ", min_s, " ", sec_s) + + return δ_s +end + +function mpc_x_str(x::T) where {T <: AbstractFloat} + sgn = x > 0 ? "+" : "-" + y = string(abs(x)) + y = lpad(y, 10) + return string(sgn, y, " ") +end + +# Convert `obs` to a string according to MPC format. +function string(obs::RadecMPC{T}) where {T <: AbstractFloat} + # Number string + num_s = rpad(obs.num, 5) + # Temporary designation string + tmpdesig_s = rpad(obs.tmpdesig, 7) + # Discovery asterisk string + discovery_s = rpad(obs.discovery, 1) + # Publishable note string + publishnote_s = rpad(obs.publishnote, 1) + # Observation technique string + obstech_s = rpad(obs.obstech, 1) + # Date string + date_s = mpc_date_str(obs.date) + # Right ascension string + α_s = mpc_α_str(obs.α) + # Declination string + δ_s = mpc_δ_str(obs.δ) + # Info 1 string + info1_s = rpad(obs.info1, 9) + # Magnitude string + mag_s = isnan(obs.mag) ? repeat(" ", 5) : @sprintf("%.2f", obs.mag) + # Band string + band_s = rpad(obs.band, 1) + # Info 2 string + info2_s = rpad(obs.info2, 5) + # Catalogue string + catalogue_s = isunknown(obs.catalogue) ? " " : obs.catalogue.code + # Observatory string + obscode_s = isunknown(obs.observatory) ? " " : obs.observatory.code + # Join everything + obs_s = string(num_s, tmpdesig_s, discovery_s, publishnote_s, obstech_s, date_s, α_s, δ_s, + info1_s, mag_s, band_s, catalogue_s, info2_s, obscode_s) + + if issatellite(obs.observatory) + # Units string + units = obs.observatory.units + units_s = rpad(units, 1) + + x = obs.observatory.long + y = obs.observatory.cos + z = obs.observatory.sin + if units == 2 + x /= au + y /= au + z /= au + end + + # X component string + x_s = mpc_x_str(x) + # Y component string + y_s = mpc_x_str(y) + # Z component string + z_s = mpc_x_str(z) + obs_s = string(obs_s, "\n", num_s, tmpdesig_s, " ", publishnote_s, "s", date_s, + units_s, " ", x_s, y_s, z_s, " ", info2_s, obscode_s) + end + + return obs_s +end + +@doc raw""" + write_radec_mpc(obs::Vector{RadecMPC{T}}, filename::String) where {T <: AbstractFloat} + +Write `obs` to `filename` in MPC format. +""" +function write_radec_mpc(obs::Vector{RadecMPC{T}}, filename::String) where {T <: AbstractFloat} + open(filename, "w") do file + for i in eachindex(obs) + line = string(obs[i]) + write(file, line, "\n") + end + end +end + +@doc raw""" + get_radec_mpc(id::Pair{String, String}, filename::String = replace(id[2], " " => "_") * ".txt") + +Download MPC optical astrometry of NEO `id` and save the output to `filename`. +""" +function get_radec_mpc(id::Pair{String, String}, filename::String = replace(id[2], " " => "_") * ".txt") + # HTTP query + query = ["table" => "observations", id] + resp = get("http://minorplanetcenter.net/search_db"; query = query) + # Converty to String + text = String(resp.body) + # Parse JSON + obs = JSON.parse(text) + # Find matches + matches = Vector{Union{RegexMatch, Nothing}}(undef, length(obs)) + for i in eachindex(obs) + s = obs[i]["original_record"] + matches[i] = match(RADEC_MPC_REGEX, s) + end + filter!(!isnothing, matches) + # Parse RadecMPC + radec = RadecMPC.(matches) + # Write observations to file + write_radec_mpc(radec, filename) + + return filename +end + +@doc raw""" + fetch_radec_mpc(id::Pair{String, String}) + +Download MPC optical astrometry of NEO `id` and return the output as `Vector{RadecMPC{Float64}}`. +""" +function fetch_radec_mpc(id::Pair{String, String}) + # Temporary file + f = tempname() + # Download optical astrometry + get_radec_mpc(id, f) + # Parse optical astrometry + radec = read_radec_mpc(f) + # Delete temporary file + rm(f) + + return radec +end + +# Methods to convert a Vector{<:AbstractAstrometry} to a DataFrame +istable(::Type{Vector{<:AbstractAstrometry}}) = true +rowaccess(::Type{Vector{<:AbstractAstrometry}}) = true +rows(x::Vector{<:AbstractAstrometry}) = x +schema(::Vector{T}) where {T <: AbstractAstrometry} = Schema(fieldnames(T), Tuple{fieldtypes(T)...}) + +# Methods to convert a DataFrame to a Vector{<:AbstractAstrometry} +function Vector{T}(df::AbstractDataFrame) where {T <: AbstractAstrometry} + @assert all(String.(fieldnames(T)) .== names(df)) "`DataFrame` column names don't match `$T` fieldnames" + @assert all(fieldtypes(T) .== eltype.(eachcol(df))) "`DataFrame` column types don't match `$T` fieldtypes" + obs = Vector{T}(undef, nrow(df)) + for (i, row) in zip(eachindex(obs), eachrow(df)) + obs[i] = T(values(row)...) + end + return obs +end + +convert(::Type{Vector{T}}, df::DataFrame) where {T <: AbstractAstrometry} = Vector{T}(df) diff --git a/src/observations/topocentric.jl b/src/observations/topocentric.jl old mode 100755 new mode 100644 index c88a48b0..742a56ac --- a/src/observations/topocentric.jl +++ b/src/observations/topocentric.jl @@ -1,337 +1,337 @@ -@doc raw""" - TimeOfDay - -Day/night at a particular timezone. - -# Fields -- `light::Symbol`: - - for ground observatories: `:day` or `:night`, - - for space observatories: `:space`. -- `start::DateTime`. -- `stop::DateTime`. -- `utc::Int`: hours from UTC. -""" -@auto_hash_equals struct TimeOfDay - light::Symbol - start::DateTime - stop::DateTime - utc::Int - function TimeOfDay(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - if issatellite(observatory) - return new(:space, date, date, 0) - end - # Hours from UTC - utc = hours_from_UTC(observatory) - # Today's sunrise / sunset - today = sunriseset(date, observatory) - # Yesterday's sunrise / sunset - yesterday = sunriseset(date - Day(1), observatory) - # Tomorrow's sunrise / sunset - tomorrow = sunriseset(date + Day(1), observatory) - # Selection - if yesterday[2] <= date <= today[1] - return new(:night, Date(yesterday[2]), Date(today[1]), utc) - elseif today[1] <= date <= today[2] - return new(:day, Date(today[1]), Date(today[2]), utc) - elseif today[2] <= date <= tomorrow[1] - return new(:night, Date(today[2]), Date(tomorrow[1]), utc) - end - - end -end - -TimeOfDay(radec::RadecMPC{T}) where {T <: AbstractFloat} = TimeOfDay(date(radec), observatory(radec)) - -isday(x::TimeOfDay) = x.light == :day -isnight(x::TimeOfDay) = x.light == :night - -# Print method for TimeOfDay -# Examples: -# Night from 2023-06-29 to 2023-06-29 at UTC-7 -# Night from 2023-06-29 to 2023-06-30 at UTC+3 -function show(io::IO, m::TimeOfDay) - print(io, uppercasefirst(string(m.light)), " from ", Date(m.start), " to ", Date(m.stop), - " at UTC", @sprintf("%+d", m.utc)) -end - -@doc raw""" - hours_from_UTC(lon::T) where {T <: Real} - -Return the naive hour difference between longitude `lon` [rad] and UTC. -""" -hours_from_UTC(lon::T) where {T <: Real} = ceil(Int, 12*lon/π - 0.5) -function hours_from_UTC(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - lon, _ = lonlat(observatory) - return hours_from_UTC(lon) -end - -@doc raw""" - lonlat(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - -Return longitude and latitude (both in rad) of an observatory. -""" -function lonlat(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - # ECEF [km] - p_ECEF = obsposECEF(observatory) - # ECEF [m] -> Geodetic [m] - lat_geodetic, lon, altitude = ecef_to_geodetic(1_000 * p_ECEF) - # Geodetic [m] -> Geocentric [m] - lat_geocentric, _ = geodetic_to_geocentric(lat_geodetic, altitude) - - return lon, lat_geocentric -end - -@doc raw""" - sunriseset(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - sunriseset(radec::RadecMPC{T}) where {T <: AbstractFloat} - -Return `DateTime` of sunrise and sunset at a particular date and location. - -!!! reference - See "General Solar Position Calculations" by NOAA at - https://gml.noaa.gov/grad/solcalc/solareqns.PDF. -""" -function sunriseset(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - # Fractional year [rad] - γ = 2π * (dayofyear(date) - 1 + (hour(date)-12)/24) / daysinyear(date) - # Equation of time [min] - eqtime = 229.18 * (0.000075 + 0.001868*cos(γ) - 0.032077*sin(γ) - 0.014615*cos(2γ) - - 0.040849*sin(2γ) ) - # Solar declination angle [rad] - δ = 0.006918 - 0.399912*cos(γ) + 0.070257*sin(γ) - 0.006758*cos(2γ) + 0.000907*sin(2γ) - - 0.002697*cos(3γ) + 0.00148*sin(3γ) - # Longitude and latitude [rad] - lon, lat = lonlat(observatory) - # Solar hour angle [deg] - ha_sunrise = acosd(cosd(90.833)/cos(lat)/cos(δ) - tan(lat)*tan(δ)) - ha_sunset = -ha_sunrise - # Day [DateTime] - day = DateTime(Date(date)) - # UTC time of sunrise [min] - sunrise_min = 720 - 4*(rad2deg(lon) + ha_sunrise) - eqtime - # UTC time of sunrise [DateTime] - sunrise = day + Microsecond(round(Int, sunrise_min*6e7)) - # UTC time of sunset [min] - sunset_min = 720 - 4*(rad2deg(lon) + ha_sunset) - eqtime - # UTC time of sunset [DateTime] - sunset = day + Microsecond(round(Int, sunset_min*6e7)) - - return sunrise, sunset -end - -sunriseset(radec::RadecMPC{T}) where {T <: AbstractFloat} = sunriseset(date(radec), observatory(radec)) - -@doc raw""" - obsposECEF(observatory::ObservatoryMPC{T}; kwarg) where {T <: AbstractFloat} - obsposECEF(x::RadecMPC{T}; kwarg) where {T <: AbstractFloat} - obsposECEF(x::RadarJPL{T}; kwarg) where {T <: AbstractFloat} - -Return the observer's geocentric `[x, y, z]` position vector in Earth-Centered Earth-Fixed -(ECEF) reference frame. - -# Keyword argument -- `eop::Union{EopIau1980, EopIau2000A}`: Earth Orientation Parameters (eop). -""" -function obsposECEF(observatory::ObservatoryMPC{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} - - # Make sure observatory has coordinates - @assert hascoord(observatory) "Cannot compute position for observatory [$(observatory.code)] without coordinates" - - if issatellite(observatory) || isoccultation(observatory) - # Ephemeris seconds since J2000 - et = datetime2et(observatory.date) - # Earth-Centered Inertial position position of observer - posvel_ECI = obsposvelECI(observatory, et; eop) - # UTC seconds - utc_secs = et - tdb_utc(et) - # Julian days UTC - jd_utc = JD_J2000 + utc_secs/daysec - # State vector - pv_ECI = OrbitStateVector(jd_utc, posvel_ECI[1:3], posvel_ECI[4:6], zeros(3)) - - # Transform position/velocity from Earth-Centered Inertial (ECI) frame to Earth-Centered Earth-fixed (ECEF) frame - # ITRF: International Terrestrial Reference Frame - # GCRF: Geocentric Celestial Reference Frame - pv_ECEF = sv_eci_to_ecef(pv_ECI, Val(:GCRF), Val(:ITRF), jd_utc, eop) - - # ECEF position - pos_ECEF = convert(Vector{eltype(pv_ECEF.r)}, pv_ECEF.r) - - return pos_ECEF - else - # λ_deg: longitude [degrees east of Greenwich] - # u: distance from spin axis [km], u = ρ*cos(ϕ') - # v: height above equatorial plane [km], v = ρ*sin(ϕ'), - # where ϕ' is the geocentric latitude and ρ is the geocentric distance in km - - # Cilindrical components of Earth-Centered Earth-Fixed position of observer - λ_deg = observatory.long # deg - u = observatory.cos * RE # km - v = observatory.sin * RE # km - - # Cartesian components of Earth-Centered Earth-Fixed position of observer - λ_rad = deg2rad(λ_deg) # rad - x_gc = u * cos(λ_rad) # km - y_gc = u * sin(λ_rad) # km - z_gc = v # km - - # Earth-Centered Earth-Fixed position position of observer - pos_ECEF = [x_gc, y_gc, z_gc] # km - - return pos_ECEF - end -end - -obsposECEF(x::RadecMPC{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} = obsposECEF(x.observatory; eop) -obsposECEF(x::RadarJPL{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} = obsposECEF(x.rcvr; eop) - -# TODO: avoid sv_ecef_to_ecef overload by defining proper product between DCMs and Taylor1/TaylorN -# method below has been adapted from SatelliteToolboxTransformations.jl, MIT-licensed -# https://github.com/JuliaSpace/SatelliteToolboxTransformations.jl -function sv_ecef_to_ecef( - sv::OrbitStateVector, - T_ECEF1::Val{:ITRF}, - T_ECEF2::Val{:TIRS}, - jd_utc::Taylor1{TaylorN{Float64}}, - eop_data::Union{Nothing, EopIau1980, EopIau2000A} = nothing -) - D = r_ecef_to_ecef(DCM, T_ECEF1, T_ECEF2, jd_utc, eop_data) - - # Since both frames does not have a significant angular velocity between - # them, then we just need to convert the representations. - r_ecef::Vector{Taylor1{TaylorN{Float64}}} = D * sv.r - v_ecef::Vector{Taylor1{TaylorN{Float64}}} = D * sv.v - a_ecef::Vector{Taylor1{TaylorN{Float64}}} = D * sv.a - return OrbitStateVector(sv.t, r_ecef, v_ecef, a_ecef) -end - -# TODO: avoid sv_ecef_to_eci overload by defining proper product between DCMs and Taylor1/TaylorN -# method below has been adapted from SatelliteToolboxTransformations.jl, MIT-licensed -# https://github.com/JuliaSpace/SatelliteToolboxTransformations.jl -function sv_ecef_to_eci( - sv::OrbitStateVector, - T_ECEF::Union{Val{:PEF}, Val{:TIRS}}, - T_ECI::Union{T_ECIs, T_ECIs_IAU_2006}, - jd_utc::Taylor1{TaylorN{Float64}}, - eop_data::Union{Nothing, EopIau1980, EopIau2000A} = nothing -) - # Get the matrix that converts the ECEF to the ECI. - if eop_data === nothing - D = r_ecef_to_eci(DCM, T_ECEF, T_ECI, jd_utc) - else - D = r_ecef_to_eci(DCM, T_ECEF, T_ECI, jd_utc, eop_data) - end - - # Since the ECI and ECEF frames have a relative velocity between them, then - # we must account from it when converting the velocity and acceleration. The - # angular velocity between those frames is computed using `we` and corrected - # by the length of day (LOD) parameter of the EOP data, if available. - ω = EARTH_ANGULAR_SPEED * (1 - (eop_data !== nothing ? eop_data.lod(jd_utc) / 86400000 : 0)) - vω = [0, 0, ω] - - # Compute the position in the ECI frame. - r_eci::Vector{Taylor1{TaylorN{Float64}}} = D * sv.r - - # Compute the velocity in the ECI frame. - vω_x_r = vω × sv.r - v_eci::Vector{Taylor1{TaylorN{Float64}}} = D * (sv.v + vω_x_r ) - - # Compute the acceleration in the ECI frame. - a_eci::Vector{Taylor1{TaylorN{Float64}}} = D * (sv.a + vω × vω_x_r + 2vω × sv.v) - - return OrbitStateVector(sv.t, r_eci, v_eci, a_eci) -end - -@doc raw""" - obsposvelECI(observatory::ObservatoryMPC{T}, et::U; kwarg) where {T <: AbstractFloat, U <: Number} - obsposvelECI(x::RadecMPC{T}; kwarg) where {T <: AbstractFloat} - obsposvelECI(x::RadarJPL{T}; kwarg) where {T <: AbstractFloat} - -Return the observer's geocentric `[x, y, z, v_x, v_y, v_z]` "state" vector in Earth-Centered -Inertial (ECI) reference frame. By default, the IAU200A Earth orientation model is used to -transform from Earth-centered, Earth-fixed (ECEF) frame to ECI frame. Other Earth orientation -models, such as the IAU1976/80 model, can be used by importing the -`SatelliteToolboxTransformations.EopIau1980` type and passing it to the `eop` keyword -argument in the function call. - -See also [`SatelliteToolboxBase.OrbitStateVector`](@ref) and -[`SatelliteToolboxTransformations.sv_ecef_to_eci`](@ref). - -# Arguments - -- `observatory::ObservatoryMPC{T}`: observation site. -- `et::U`: ephemeris time (TDB seconds since J2000.0 epoch). -- `x::RadecMPC{T}/RadarJPL{T}`: astrometric observation. - -# Keyword argument - -- `eop::Union{EopIau1980, EopIau2000A}`: Earth Orientation Parameters (eop). -""" -function obsposvelECI(observatory::ObservatoryMPC{T}, et::U; - eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat, U <: Number} - - # Make sure observatory has coordinates - @assert hascoord(observatory) "Cannot compute position for observatory [$(observatory.code)] without coordinates" - # One with correct type - oneU = one(et) - - if issatellite(observatory) || isoccultation(observatory) - # @assert datetime2et(observatory.date) == cte(et) - return [observatory.long * oneU, observatory.cos * oneU, observatory.sin * oneU, - zero(et), zero(et), zero(et)] - else - # Earth-Centered Earth-Fixed position position of observer - pos_ECEF = obsposECEF(observatory) - - # UTC seconds - utc_secs = et - tdb_utc(et) - # Julian days UTC - jd_utc = JD_J2000 + utc_secs/daysec - # State vector - pv_ECEF = OrbitStateVector(jd_utc, pos_ECEF, zeros(3), zeros(3)) - - # Transform position/velocity from Earth-Centered Earth-fixed (ECEF) frame to Earth-Centered Inertial (ECI) frame - # ITRF: International Terrestrial Reference Frame - # GCRF: Geocentric Celestial Reference Frame - pv_ECI = sv_ecef_to_eci(pv_ECEF, Val(:ITRF), Val(:GCRF), jd_utc, eop) - - # ECI state vector (of correct type) - r_ECI = Vector{U}(undef, 6) - # Inertial position - for i in eachindex(pv_ECI.r) - r_ECI[i] = pv_ECI.r[i] * oneU - end - # Inertial velocity - for i in eachindex(pv_ECI.v) - r_ECI[i+3] = pv_ECI.v[i] * oneU - end - - return r_ECI - end -end - -function obsposvelECI(x::RadecMPC{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} - return obsposvelECI(x.observatory, datetime2et(x.date); eop) -end -function obsposvelECI(x::RadarJPL{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} - return obsposvelECI(x.rcvr, datetime2et(x.date); eop) -end - -# Special method of SatelliteToolboxTransformations.ecef_to_geocentric for Vector{TaylorN{T}} -# See https://github.com/JuliaSpace/SatelliteToolboxTransformations.jl/blob/b7790389407a207499d343aa6d546ef54990baa2/src/reference_frames/geodetic_geocentric.jl#L31-L60 -function ecef_to_geocentric(r_e::Vector{TaylorN{T}}) where {T<:AbstractFloat} - - # Auxiliary variables. - x = r_e[1] - y = r_e[2] - z = r_e[3] - x² = x^2 - y² = y^2 - z² = z^2 - - lat = atan(z, √(x² + y²)) - lon = atan(y, x) - r = √(x² + y² + z²) - - return lat, lon, r +@doc raw""" + TimeOfDay + +Day/night at a particular timezone. + +# Fields +- `light::Symbol`: + - for ground observatories: `:day` or `:night`, + - for space observatories: `:space`. +- `start::DateTime`. +- `stop::DateTime`. +- `utc::Int`: hours from UTC. +""" +@auto_hash_equals struct TimeOfDay + light::Symbol + start::DateTime + stop::DateTime + utc::Int + function TimeOfDay(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + if issatellite(observatory) + return new(:space, date, date, 0) + end + # Hours from UTC + utc = hours_from_UTC(observatory) + # Today's sunrise / sunset + today = sunriseset(date, observatory) + # Yesterday's sunrise / sunset + yesterday = sunriseset(date - Day(1), observatory) + # Tomorrow's sunrise / sunset + tomorrow = sunriseset(date + Day(1), observatory) + # Selection + if yesterday[2] <= date <= today[1] + return new(:night, Date(yesterday[2]), Date(today[1]), utc) + elseif today[1] <= date <= today[2] + return new(:day, Date(today[1]), Date(today[2]), utc) + elseif today[2] <= date <= tomorrow[1] + return new(:night, Date(today[2]), Date(tomorrow[1]), utc) + end + + end +end + +TimeOfDay(radec::RadecMPC{T}) where {T <: AbstractFloat} = TimeOfDay(date(radec), observatory(radec)) + +isday(x::TimeOfDay) = x.light == :day +isnight(x::TimeOfDay) = x.light == :night + +# Print method for TimeOfDay +# Examples: +# Night from 2023-06-29 to 2023-06-29 at UTC-7 +# Night from 2023-06-29 to 2023-06-30 at UTC+3 +function show(io::IO, m::TimeOfDay) + print(io, uppercasefirst(string(m.light)), " from ", Date(m.start), " to ", Date(m.stop), + " at UTC", @sprintf("%+d", m.utc)) +end + +@doc raw""" + hours_from_UTC(lon::T) where {T <: Real} + +Return the naive hour difference between longitude `lon` [rad] and UTC. +""" +hours_from_UTC(lon::T) where {T <: Real} = ceil(Int, 12*lon/π - 0.5) +function hours_from_UTC(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + lon, _ = lonlat(observatory) + return hours_from_UTC(lon) +end + +@doc raw""" + lonlat(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + +Return longitude and latitude (both in rad) of an observatory. +""" +function lonlat(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + # ECEF [km] + p_ECEF = obsposECEF(observatory) + # ECEF [m] -> Geodetic [m] + lat_geodetic, lon, altitude = ecef_to_geodetic(1_000 * p_ECEF) + # Geodetic [m] -> Geocentric [m] + lat_geocentric, _ = geodetic_to_geocentric(lat_geodetic, altitude) + + return lon, lat_geocentric +end + +@doc raw""" + sunriseset(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + sunriseset(radec::RadecMPC{T}) where {T <: AbstractFloat} + +Return `DateTime` of sunrise and sunset at a particular date and location. + +!!! reference + See "General Solar Position Calculations" by NOAA at + https://gml.noaa.gov/grad/solcalc/solareqns.PDF. +""" +function sunriseset(date::DateTime, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} + # Fractional year [rad] + γ = 2π * (dayofyear(date) - 1 + (hour(date)-12)/24) / daysinyear(date) + # Equation of time [min] + eqtime = 229.18 * (0.000075 + 0.001868*cos(γ) - 0.032077*sin(γ) - 0.014615*cos(2γ) + - 0.040849*sin(2γ) ) + # Solar declination angle [rad] + δ = 0.006918 - 0.399912*cos(γ) + 0.070257*sin(γ) - 0.006758*cos(2γ) + 0.000907*sin(2γ) + - 0.002697*cos(3γ) + 0.00148*sin(3γ) + # Longitude and latitude [rad] + lon, lat = lonlat(observatory) + # Solar hour angle [deg] + ha_sunrise = acosd(cosd(90.833)/cos(lat)/cos(δ) - tan(lat)*tan(δ)) + ha_sunset = -ha_sunrise + # Day [DateTime] + day = DateTime(Date(date)) + # UTC time of sunrise [min] + sunrise_min = 720 - 4*(rad2deg(lon) + ha_sunrise) - eqtime + # UTC time of sunrise [DateTime] + sunrise = day + Microsecond(round(Int, sunrise_min*6e7)) + # UTC time of sunset [min] + sunset_min = 720 - 4*(rad2deg(lon) + ha_sunset) - eqtime + # UTC time of sunset [DateTime] + sunset = day + Microsecond(round(Int, sunset_min*6e7)) + + return sunrise, sunset +end + +sunriseset(radec::RadecMPC{T}) where {T <: AbstractFloat} = sunriseset(date(radec), observatory(radec)) + +@doc raw""" + obsposECEF(observatory::ObservatoryMPC{T}; kwarg) where {T <: AbstractFloat} + obsposECEF(x::RadecMPC{T}; kwarg) where {T <: AbstractFloat} + obsposECEF(x::RadarJPL{T}; kwarg) where {T <: AbstractFloat} + +Return the observer's geocentric `[x, y, z]` position vector in Earth-Centered Earth-Fixed +(ECEF) reference frame. + +# Keyword argument +- `eop::Union{EopIau1980, EopIau2000A}`: Earth Orientation Parameters (eop). +""" +function obsposECEF(observatory::ObservatoryMPC{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} + + # Make sure observatory has coordinates + @assert hascoord(observatory) "Cannot compute position for observatory [$(observatory.code)] without coordinates" + + if issatellite(observatory) || isoccultation(observatory) + # Ephemeris seconds since J2000 + et = datetime2et(observatory.date) + # Earth-Centered Inertial position position of observer + posvel_ECI = obsposvelECI(observatory, et; eop) + # UTC seconds + utc_secs = et - tdb_utc(et) + # Julian days UTC + jd_utc = JD_J2000 + utc_secs/daysec + # State vector + pv_ECI = OrbitStateVector(jd_utc, posvel_ECI[1:3], posvel_ECI[4:6], zeros(3)) + + # Transform position/velocity from Earth-Centered Inertial (ECI) frame to Earth-Centered Earth-fixed (ECEF) frame + # ITRF: International Terrestrial Reference Frame + # GCRF: Geocentric Celestial Reference Frame + pv_ECEF = sv_eci_to_ecef(pv_ECI, Val(:GCRF), Val(:ITRF), jd_utc, eop) + + # ECEF position + pos_ECEF = convert(Vector{eltype(pv_ECEF.r)}, pv_ECEF.r) + + return pos_ECEF + else + # λ_deg: longitude [degrees east of Greenwich] + # u: distance from spin axis [km], u = ρ*cos(ϕ') + # v: height above equatorial plane [km], v = ρ*sin(ϕ'), + # where ϕ' is the geocentric latitude and ρ is the geocentric distance in km + + # Cilindrical components of Earth-Centered Earth-Fixed position of observer + λ_deg = observatory.long # deg + u = observatory.cos * RE # km + v = observatory.sin * RE # km + + # Cartesian components of Earth-Centered Earth-Fixed position of observer + λ_rad = deg2rad(λ_deg) # rad + x_gc = u * cos(λ_rad) # km + y_gc = u * sin(λ_rad) # km + z_gc = v # km + + # Earth-Centered Earth-Fixed position position of observer + pos_ECEF = [x_gc, y_gc, z_gc] # km + + return pos_ECEF + end +end + +obsposECEF(x::RadecMPC{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} = obsposECEF(x.observatory; eop) +obsposECEF(x::RadarJPL{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} = obsposECEF(x.rcvr; eop) + +# TODO: avoid sv_ecef_to_ecef overload by defining proper product between DCMs and Taylor1/TaylorN +# method below has been adapted from SatelliteToolboxTransformations.jl, MIT-licensed +# https://github.com/JuliaSpace/SatelliteToolboxTransformations.jl +function sv_ecef_to_ecef( + sv::OrbitStateVector, + T_ECEF1::Val{:ITRF}, + T_ECEF2::Val{:TIRS}, + jd_utc::Taylor1{TaylorN{Float64}}, + eop_data::Union{Nothing, EopIau1980, EopIau2000A} = nothing +) + D = r_ecef_to_ecef(DCM, T_ECEF1, T_ECEF2, jd_utc, eop_data) + + # Since both frames does not have a significant angular velocity between + # them, then we just need to convert the representations. + r_ecef::Vector{Taylor1{TaylorN{Float64}}} = D * sv.r + v_ecef::Vector{Taylor1{TaylorN{Float64}}} = D * sv.v + a_ecef::Vector{Taylor1{TaylorN{Float64}}} = D * sv.a + return OrbitStateVector(sv.t, r_ecef, v_ecef, a_ecef) +end + +# TODO: avoid sv_ecef_to_eci overload by defining proper product between DCMs and Taylor1/TaylorN +# method below has been adapted from SatelliteToolboxTransformations.jl, MIT-licensed +# https://github.com/JuliaSpace/SatelliteToolboxTransformations.jl +function sv_ecef_to_eci( + sv::OrbitStateVector, + T_ECEF::Union{Val{:PEF}, Val{:TIRS}}, + T_ECI::Union{T_ECIs, T_ECIs_IAU_2006}, + jd_utc::Taylor1{TaylorN{Float64}}, + eop_data::Union{Nothing, EopIau1980, EopIau2000A} = nothing +) + # Get the matrix that converts the ECEF to the ECI. + if eop_data === nothing + D = r_ecef_to_eci(DCM, T_ECEF, T_ECI, jd_utc) + else + D = r_ecef_to_eci(DCM, T_ECEF, T_ECI, jd_utc, eop_data) + end + + # Since the ECI and ECEF frames have a relative velocity between them, then + # we must account from it when converting the velocity and acceleration. The + # angular velocity between those frames is computed using `we` and corrected + # by the length of day (LOD) parameter of the EOP data, if available. + ω = EARTH_ANGULAR_SPEED * (1 - (eop_data !== nothing ? eop_data.lod(jd_utc) / 86400000 : 0)) + vω = [0, 0, ω] + + # Compute the position in the ECI frame. + r_eci::Vector{Taylor1{TaylorN{Float64}}} = D * sv.r + + # Compute the velocity in the ECI frame. + vω_x_r = vω × sv.r + v_eci::Vector{Taylor1{TaylorN{Float64}}} = D * (sv.v + vω_x_r ) + + # Compute the acceleration in the ECI frame. + a_eci::Vector{Taylor1{TaylorN{Float64}}} = D * (sv.a + vω × vω_x_r + 2vω × sv.v) + + return OrbitStateVector(sv.t, r_eci, v_eci, a_eci) +end + +@doc raw""" + obsposvelECI(observatory::ObservatoryMPC{T}, et::U; kwarg) where {T <: AbstractFloat, U <: Number} + obsposvelECI(x::RadecMPC{T}; kwarg) where {T <: AbstractFloat} + obsposvelECI(x::RadarJPL{T}; kwarg) where {T <: AbstractFloat} + +Return the observer's geocentric `[x, y, z, v_x, v_y, v_z]` "state" vector in Earth-Centered +Inertial (ECI) reference frame. By default, the IAU200A Earth orientation model is used to +transform from Earth-centered, Earth-fixed (ECEF) frame to ECI frame. Other Earth orientation +models, such as the IAU1976/80 model, can be used by importing the +`SatelliteToolboxTransformations.EopIau1980` type and passing it to the `eop` keyword +argument in the function call. + +See also [`SatelliteToolboxBase.OrbitStateVector`](@ref) and +[`SatelliteToolboxTransformations.sv_ecef_to_eci`](@ref). + +# Arguments + +- `observatory::ObservatoryMPC{T}`: observation site. +- `et::U`: ephemeris time (TDB seconds since J2000.0 epoch). +- `x::RadecMPC{T}/RadarJPL{T}`: astrometric observation. + +# Keyword argument + +- `eop::Union{EopIau1980, EopIau2000A}`: Earth Orientation Parameters (eop). +""" +function obsposvelECI(observatory::ObservatoryMPC{T}, et::U; + eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat, U <: Number} + + # Make sure observatory has coordinates + @assert hascoord(observatory) "Cannot compute position for observatory [$(observatory.code)] without coordinates" + # One with correct type + oneU = one(et) + + if issatellite(observatory) || isoccultation(observatory) + # @assert datetime2et(observatory.date) == cte(et) + return [observatory.long * oneU, observatory.cos * oneU, observatory.sin * oneU, + zero(et), zero(et), zero(et)] + else + # Earth-Centered Earth-Fixed position position of observer + pos_ECEF = obsposECEF(observatory) + + # UTC seconds + utc_secs = et - tdb_utc(et) + # Julian days UTC + jd_utc = JD_J2000 + utc_secs/daysec + # State vector + pv_ECEF = OrbitStateVector(jd_utc, pos_ECEF, zeros(3), zeros(3)) + + # Transform position/velocity from Earth-Centered Earth-fixed (ECEF) frame to Earth-Centered Inertial (ECI) frame + # ITRF: International Terrestrial Reference Frame + # GCRF: Geocentric Celestial Reference Frame + pv_ECI = sv_ecef_to_eci(pv_ECEF, Val(:ITRF), Val(:GCRF), jd_utc, eop) + + # ECI state vector (of correct type) + r_ECI = Vector{U}(undef, 6) + # Inertial position + for i in eachindex(pv_ECI.r) + r_ECI[i] = pv_ECI.r[i] * oneU + end + # Inertial velocity + for i in eachindex(pv_ECI.v) + r_ECI[i+3] = pv_ECI.v[i] * oneU + end + + return r_ECI + end +end + +function obsposvelECI(x::RadecMPC{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} + return obsposvelECI(x.observatory, datetime2et(x.date); eop) +end +function obsposvelECI(x::RadarJPL{T}; eop::Union{EopIau1980, EopIau2000A} = eop_IAU2000A) where {T <: AbstractFloat} + return obsposvelECI(x.rcvr, datetime2et(x.date); eop) +end + +# Special method of SatelliteToolboxTransformations.ecef_to_geocentric for Vector{TaylorN{T}} +# See https://github.com/JuliaSpace/SatelliteToolboxTransformations.jl/blob/b7790389407a207499d343aa6d546ef54990baa2/src/reference_frames/geodetic_geocentric.jl#L31-L60 +function ecef_to_geocentric(r_e::Vector{TaylorN{T}}) where {T<:AbstractFloat} + + # Auxiliary variables. + x = r_e[1] + y = r_e[2] + z = r_e[3] + x² = x^2 + y² = y^2 + z² = z^2 + + lat = atan(z, √(x² + y²)) + lon = atan(y, x) + r = √(x² + y² + z²) + + return lat, lon, r end \ No newline at end of file diff --git a/src/observations/tracklet.jl b/src/observations/tracklet.jl index d88dbd25..60746af4 100644 --- a/src/observations/tracklet.jl +++ b/src/observations/tracklet.jl @@ -113,7 +113,7 @@ function Tracklet(radec::Vector{RadecMPC{T}}, df::AbstractDataFrame) where {T <: mag = df.mag[1] return Tracklet{T}(radec, observatory, night, date, α, δ, v_α, v_δ, mag, nobs, indices) - end + end # Make sure there are no repeated dates gdf = groupby(df, :date) @@ -141,7 +141,7 @@ function Tracklet(radec::Vector{RadecMPC{T}}, df::AbstractDataFrame) where {T <: α_coef = polyfit(df.t_rel, df.α) δ_coef = polyfit(df.t_rel, df.δ) - # Evaluate polynomials at mean date + # Evaluate polynomials at mean date α = mod2pi(polymodel(t_mean, α_coef)) δ = polymodel(t_mean, δ_coef) v_α = polymodel(t_mean, diffcoeffs(α_coef)) @@ -152,21 +152,21 @@ function Tracklet(radec::Vector{RadecMPC{T}}, df::AbstractDataFrame) where {T <: return Tracklet{T}(radec, observatory, night, date, α, δ, v_α, v_δ, mag, nobs, indices) -end +end @doc raw""" reduce_tracklets(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} Return a `Vector{Tracklet{T}}` where each element corresponds to a batch of observations taken by the same observatory on the same night. The reduction -is performed via polynomial regression. +is performed via polynomial regression. """ function reduce_tracklets(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - # Convert to DataFrame + # Convert to DataFrame df = DataFrame(radec) # Compute TimeOfDay df.TimeOfDay = TimeOfDay.(radec) - # Group by observatory and TimeOfDay + # Group by observatory and TimeOfDay gdf = groupby(df, [:observatory, :TimeOfDay]) # Allocate memmory for tracklets vector tracklets = Vector{Tracklet{T}}(undef, gdf.ngroups) @@ -177,6 +177,6 @@ function reduce_tracklets(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} end # Sort by date sort!(tracklets) - + return tracklets end \ No newline at end of file diff --git a/src/observations/units.jl b/src/observations/units.jl old mode 100755 new mode 100644 index 5d8931dd..2ad37651 --- a/src/observations/units.jl +++ b/src/observations/units.jl @@ -1,181 +1,181 @@ -@doc raw""" - julian2etsecs(jd::T) where {T <: Number} - -Convert the Julian date `jd` to ephemeris seconds since J2000. - -See also [`etsecs2julian`](@ref). -""" -function julian2etsecs(jd::T) where {T <: Number} - return (jd - JD_J2000) * daysec -end - -@doc raw""" - etsecs2julian(et::T) where {T <: Number} - -Convert `et` ephemeris seconds since J2000 to Julian date. - -See also [`julian2etsecs`](@ref). -""" -function etsecs2julian(et::T) where {T <: Number} - return JD_J2000 + et / daysec -end - -@doc raw""" - datetime2et(x::DateTime) - datetime2et(x::T) where {T <: AbstractAstrometry} - -Convert a UTC `DateTime` to TDB seconds past the J2000 epoch. -""" -function datetime2et(x::DateTime) - # UTC seconds since J2000.0 epoch - utc_seconds = Millisecond(x - DateTime(2000,1,1,12)).value/1000 - # TAI - UTC - tai_utc = get_Δat(datetime2julian(x)) - # TT - TAI - tt_tai = 32.184 - # TT - UTC = (TT-TAI) + (TAI-UTC) - tt_utc = tt_tai +tai_utc - # TT seconds = UTC seconds + (TT-UTC) - tt_seconds = utc_seconds + tt_utc - # TDB seconds = TT seconds + (TDB-TT) - return tt_seconds - ttmtdb_tt(tt_seconds) -end - -datetime2et(x::T) where {T <: AbstractAstrometry} = datetime2et(x.date) - -@doc raw""" - et_to_200X(et::T) where {T <: Number} - -Convert `et` ephemeris seconds since J2000 to years `200X`. -""" -et_to_200X(et::T) where {T <: Number} = 2000 + et/daysec/yr - -@doc raw""" - days_to_200X(d::T) where {T <: Number} - -Convert `d` days since J2000 to years `200X`. -""" -days_to_200X(d::T) where {T <: Number} = 2000 + d/yr - -@doc raw""" - datetime_to_200X(x::DateTime) - -Convert `DateTime` `x` to years `200X`. -""" -datetime_to_200X(x::DateTime) = et_to_200X(datetime2et(x)) - -@doc raw""" - datetime2days(x::DateTime) - -Convert `DateTime` `x` to days since J2000. -""" -datetime2days(x::DateTime) = datetime2julian(x) - JD_J2000 - -@doc raw""" - days2datetime(d::T) where {T <: Number} - -Convert `d` days since J2000 to `DateTime`. -""" -days2datetime(d::T) where {T <: Number} = julian2datetime(d + JD_J2000) - -@doc raw""" - tdb_utc(et::T) where {T <: Number} - -Given `et`, a number of TDB seconds past J2000.0 epoch, compute -the difference (TDB-UTC) -```math -\begin{align*} -TDB-UTC & = (TDB-TAI) + (TAI-UTC) \\ - & = (TDB-TT) + (TT-TAI) + (TAI-UTC) \\ - & = (TDB-TT) + 32.184 s + ΔAT, -\end{align*} -``` -where TDB is the Barycentric Dynamical Time (Temps Dynamique Barycentrique), -TT is the Terrestrial Time, TAI is the International Atomic Time, and UTC is -the Coordinated Universal Time. - -# Arguments - -- `et::Number`: TDB seconds since J2000.0. - -!!! reference - This function is useful to convert TDB to UTC via UTC + (TDB-UTC) and viceversa. - It does not include the correction due to the position of the measurement station - ``v_E.(r_S-r_E)/c^2`` (Folkner et al. 2014; Moyer, 2003). -""" -function tdb_utc(et::T) where {T <: Number} - # TT-TDB - tt_tdb_et = ttmtdb(et/daysec) - # TT-TAI - tt_tai = 32.184 - # TDB - TAI = (TT-TAI) + (TDB-TT) = (TDB-TT) + 32.184 s - tdb_tai = tt_tai - tt_tdb_et - - # TAI seconds since J2000.0; used to determine ΔAT = TAI - UTC - tai_secs = cte(cte(et)) - cte(cte(tdb_tai)) - # Julian date corresponding to tai_secs - jd_tai = JD_J2000 + tai_secs/daysec - # ΔAT = TAI - UTC - tai_utc = get_Δat(jd_tai) - # TDB-UTC = (TDB-TAI) + (TAI-UTC) = (TDB-TT) + 32.184 s + ΔAT - return tdb_tai + tai_utc -end - -@doc raw""" - ttmtdb_tt(tt::T; niter::Int = 5) where {T <: Real} - -Given `tt`, a number of TT seconds past J2000.0 epoch, compute -the difference (TT-TDB), where TDB is the Barycentric Dynamical Time (Temps Dynamique -Barycentrique) and TT is the Terrestrial Time. - -# Arguments - -- `tt::T`: tt seconds since J2000.0. - -!!! reference - This function is useful during the reduction of observations, when the TDB instant - is computed from a known UTC instant. The computed value does not include the - correction due to the position of the measurement station ``v_E.(r_S-r_E)/c^2`` - (Folkner et al. 2014; Moyer, 2003). -""" -function ttmtdb_tt(tt::T; niter::Int = 5) where {T <: Real} - # Ansatz: TDB - TT = 0 - ttmtdb_order = ttmtdb.x[1].order - tdb = Taylor1([tt,one(tt)], ttmtdb_order) - for _ in 1:niter - ttmtdb_tdb = ttmtdb(tdb/daysec) - # we look for TDB* such that TT-TDB* = (TT-TDB)(TDB*) - y = tt - tdb - ttmtdb_tdb - dy = - 1 - TaylorSeries.differentiate(ttmtdb_tdb) - # perform Newton iteration - tdb[0] -= cte(y/dy) - end - return ttmtdb(tdb[0]/daysec) -end - -@doc raw""" - rad2arcsec(x::T) where {T <: Number} - -Convert radians to arcseconds. - -See also [`arcsec2rad`](@ref) and [`mas2rad`](@ref). -""" -rad2arcsec(x::T) where {T <: Number} = 3600 * rad2deg(x) # rad2deg(rad) -> deg; 3600 * deg -> arcsec - -@doc raw""" - arcsec2rad(x::T) where {T <: Number} - -Convert arcseconds to radians. - -See also [`rad2arcsec`](@ref) and [`mas2rad`](@ref). -""" -arcsec2rad(x::T) where {T <: Number} = deg2rad(x / 3600) # arcsec/3600 -> deg; deg2rad(deg) -> rad - -@doc raw""" - mas2rad(x::T) where {T <: Number} - -Convert milli-arcseconds to radians. - -See also [`rad2arcsec`](@ref) and [`arcsec2rad`](@ref). -""" +@doc raw""" + julian2etsecs(jd::T) where {T <: Number} + +Convert the Julian date `jd` to ephemeris seconds since J2000. + +See also [`etsecs2julian`](@ref). +""" +function julian2etsecs(jd::T) where {T <: Number} + return (jd - JD_J2000) * daysec +end + +@doc raw""" + etsecs2julian(et::T) where {T <: Number} + +Convert `et` ephemeris seconds since J2000 to Julian date. + +See also [`julian2etsecs`](@ref). +""" +function etsecs2julian(et::T) where {T <: Number} + return JD_J2000 + et / daysec +end + +@doc raw""" + datetime2et(x::DateTime) + datetime2et(x::T) where {T <: AbstractAstrometry} + +Convert a UTC `DateTime` to TDB seconds past the J2000 epoch. +""" +function datetime2et(x::DateTime) + # UTC seconds since J2000.0 epoch + utc_seconds = Millisecond(x - DateTime(2000,1,1,12)).value/1000 + # TAI - UTC + tai_utc = get_Δat(datetime2julian(x)) + # TT - TAI + tt_tai = 32.184 + # TT - UTC = (TT-TAI) + (TAI-UTC) + tt_utc = tt_tai +tai_utc + # TT seconds = UTC seconds + (TT-UTC) + tt_seconds = utc_seconds + tt_utc + # TDB seconds = TT seconds + (TDB-TT) + return tt_seconds - ttmtdb_tt(tt_seconds) +end + +datetime2et(x::T) where {T <: AbstractAstrometry} = datetime2et(x.date) + +@doc raw""" + et_to_200X(et::T) where {T <: Number} + +Convert `et` ephemeris seconds since J2000 to years `200X`. +""" +et_to_200X(et::T) where {T <: Number} = 2000 + et/daysec/yr + +@doc raw""" + days_to_200X(d::T) where {T <: Number} + +Convert `d` days since J2000 to years `200X`. +""" +days_to_200X(d::T) where {T <: Number} = 2000 + d/yr + +@doc raw""" + datetime_to_200X(x::DateTime) + +Convert `DateTime` `x` to years `200X`. +""" +datetime_to_200X(x::DateTime) = et_to_200X(datetime2et(x)) + +@doc raw""" + datetime2days(x::DateTime) + +Convert `DateTime` `x` to days since J2000. +""" +datetime2days(x::DateTime) = datetime2julian(x) - JD_J2000 + +@doc raw""" + days2datetime(d::T) where {T <: Number} + +Convert `d` days since J2000 to `DateTime`. +""" +days2datetime(d::T) where {T <: Number} = julian2datetime(d + JD_J2000) + +@doc raw""" + tdb_utc(et::T) where {T <: Number} + +Given `et`, a number of TDB seconds past J2000.0 epoch, compute +the difference (TDB-UTC) +```math +\begin{align*} +TDB-UTC & = (TDB-TAI) + (TAI-UTC) \\ + & = (TDB-TT) + (TT-TAI) + (TAI-UTC) \\ + & = (TDB-TT) + 32.184 s + ΔAT, +\end{align*} +``` +where TDB is the Barycentric Dynamical Time (Temps Dynamique Barycentrique), +TT is the Terrestrial Time, TAI is the International Atomic Time, and UTC is +the Coordinated Universal Time. + +# Arguments + +- `et::Number`: TDB seconds since J2000.0. + +!!! reference + This function is useful to convert TDB to UTC via UTC + (TDB-UTC) and viceversa. + It does not include the correction due to the position of the measurement station + ``v_E.(r_S-r_E)/c^2`` (Folkner et al. 2014; Moyer, 2003). +""" +function tdb_utc(et::T) where {T <: Number} + # TT-TDB + tt_tdb_et = ttmtdb(et/daysec) + # TT-TAI + tt_tai = 32.184 + # TDB - TAI = (TT-TAI) + (TDB-TT) = (TDB-TT) + 32.184 s + tdb_tai = tt_tai - tt_tdb_et + + # TAI seconds since J2000.0; used to determine ΔAT = TAI - UTC + tai_secs = cte(cte(et)) - cte(cte(tdb_tai)) + # Julian date corresponding to tai_secs + jd_tai = JD_J2000 + tai_secs/daysec + # ΔAT = TAI - UTC + tai_utc = get_Δat(jd_tai) + # TDB-UTC = (TDB-TAI) + (TAI-UTC) = (TDB-TT) + 32.184 s + ΔAT + return tdb_tai + tai_utc +end + +@doc raw""" + ttmtdb_tt(tt::T; niter::Int = 5) where {T <: Real} + +Given `tt`, a number of TT seconds past J2000.0 epoch, compute +the difference (TT-TDB), where TDB is the Barycentric Dynamical Time (Temps Dynamique +Barycentrique) and TT is the Terrestrial Time. + +# Arguments + +- `tt::T`: tt seconds since J2000.0. + +!!! reference + This function is useful during the reduction of observations, when the TDB instant + is computed from a known UTC instant. The computed value does not include the + correction due to the position of the measurement station ``v_E.(r_S-r_E)/c^2`` + (Folkner et al. 2014; Moyer, 2003). +""" +function ttmtdb_tt(tt::T; niter::Int = 5) where {T <: Real} + # Ansatz: TDB - TT = 0 + ttmtdb_order = ttmtdb.x[1].order + tdb = Taylor1([tt,one(tt)], ttmtdb_order) + for _ in 1:niter + ttmtdb_tdb = ttmtdb(tdb/daysec) + # we look for TDB* such that TT-TDB* = (TT-TDB)(TDB*) + y = tt - tdb - ttmtdb_tdb + dy = - 1 - TaylorSeries.differentiate(ttmtdb_tdb) + # perform Newton iteration + tdb[0] -= cte(y/dy) + end + return ttmtdb(tdb[0]/daysec) +end + +@doc raw""" + rad2arcsec(x::T) where {T <: Number} + +Convert radians to arcseconds. + +See also [`arcsec2rad`](@ref) and [`mas2rad`](@ref). +""" +rad2arcsec(x::T) where {T <: Number} = 3600 * rad2deg(x) # rad2deg(rad) -> deg; 3600 * deg -> arcsec + +@doc raw""" + arcsec2rad(x::T) where {T <: Number} + +Convert arcseconds to radians. + +See also [`rad2arcsec`](@ref) and [`mas2rad`](@ref). +""" +arcsec2rad(x::T) where {T <: Number} = deg2rad(x / 3600) # arcsec/3600 -> deg; deg2rad(deg) -> rad + +@doc raw""" + mas2rad(x::T) where {T <: Number} + +Convert milli-arcseconds to radians. + +See also [`rad2arcsec`](@ref) and [`arcsec2rad`](@ref). +""" mas2rad(x::T) where {T <: Number} = arcsec2rad(x / 1000) # mas/1000 -> arcsec; arcsec2rad(arcsec) -> rad \ No newline at end of file diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl old mode 100755 new mode 100644 index 1324b95a..095d51e1 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -1,548 +1,548 @@ -@doc raw""" - GaussSolution{T <: Real, U <: Number} - -A preliminary orbit obtained from Gauss method of orbit determination. - -See also [`gauss_method`](@ref). - -# Fields - -- `statevect::Vector{U}`: state vector at middle observation. -- `ρ::Vector{U}`: topocentric ranges. -- `D::Matrix{U}`: D matrix. -- `R_vec::Matrix{T}`: observer's heliocentric positions. -- `ρ_vec::Matrix{U}`: line of sight unit vectors. -- `τ_1::T`: time between first and second observations. -- `τ_3::T`: time between third and second observations. -- `f_1, g_1, f_3, g_3::U`: Lagrange coefficients. - -!!! reference - See Algorithm 5.5 in page 274 of https://doi.org/10.1016/C2016-0-02107-1. -""" -@auto_hash_equals struct GaussSolution{T <: Real, U <: Number} - statevect::Vector{U} - ρ::Vector{U} - D::Matrix{U} - R_vec::Matrix{T} - ρ_vec::Matrix{U} - τ_1::T - τ_3::T - f_1::U - g_1::U - f_3::U - g_3::U - # Inner constructor - function GaussSolution{T, U}( - statevect::Vector{U}, ρ::Vector{U}, D::Matrix{U}, R_vec::Matrix{T}, - ρ_vec::Matrix{U}, τ_1::T, τ_3::T, f_1::U, g_1::U, f_3::U, g_3::U) where {T <: Real, U <: Number} - return new{T, U}(statevect, ρ, D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3) - end -end - -# Outer constructor -function GaussSolution( - statevect::Vector{U}, ρ::Vector{U}, D::Matrix{U}, R_vec::Matrix{T}, - ρ_vec::Matrix{U}, τ_1::T, τ_3::T, f_1::U, g_1::U, f_3::U, g_3::U) where {T <: Real, U <: Number} - return GaussSolution{T, U}(statevect, ρ, D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3) -end - -# Print method for GaussSolution -# Examples: -# Gauss solution (r = 1.0800950907383229 AU) -function show(io::IO, g::GaussSolution{T, U}) where {T <: Real, U <: Number} - print(io, "Gauss solution (r = ", norm(cte.(g.statevect[1:3])), " AU)") -end - -@doc raw""" - topounit(α::T, δ::T) where {T <: Number} - topounit(obs::RadecMPC{T}) where {T <: AbstractFloat} - -Return the topocentric unit vector. -""" -function topounit(α::T, δ::T) where {T <: Number} - - sin_α, cos_α = sincos(α) - sin_δ, cos_δ = sincos(δ) - - pos = [cos_δ * cos_α, cos_δ * sin_α, sin_δ] - - return pos -end - -topounit(obs::RadecMPC{T}) where {T <: AbstractFloat} = topounit(obs.α, obs.δ) - -# TO DO: Should we allow to use other μ? - -@doc raw""" - f_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} - -Return the 1st order approximation to Lagrange's f function. -""" -function f_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} - r3 = r * r * r - return 1 - μ_S * (τ^2) / 2 / r3 -end - -@doc raw""" - g_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} - -Return the 1st order approximation to Lagrange's g function. -""" -function g_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} - r3 = r * r * r - return τ - μ_S * (τ^3) / 6 / r3 -end - -@doc raw""" - vectors2matrix(x::T) where {T <: AbstractVector} - -Convert a vector of vectors `x` to a matrix. -""" -vectors2matrix(x::T) where {T <: AbstractVector} = permutedims(reduce(hcat, x)) - -@doc raw""" - _format_Lagrange_equation(a::T, b::T, c::T) where {T <: AbstractFloat} - -Format Lagrange equation as `r⁸ + a r⁶ + b r³ + c = 0`. -""" -function _format_Lagrange_equation(a::T, b::T, c::T) where {T <: AbstractFloat} - a_sgn = a ≥ 0 ? "+" : "-" - b_sgn = b ≥ 0 ? "+" : "-" - c_sgn = c ≥ 0 ? "+" : "-" - - return join(["r⁸ ", a_sgn, " ", abs(a), " r⁶ ", b_sgn, " ", abs(b), " r³ ", c_sgn, " ", abs(c), " = 0"]) -end - -@doc raw""" - lagrange(x::T, a::U, b::U, c::U) where {T, U <: Number} - -Lagrange polynomial to be solved during Gauss method. -""" -function lagrange(x::T, a::U, b::U, c::U) where {T, U <: Number} - # Evaluate via Horner's method - x2 = x * x - x3 = x2 * x - return c + x3 * (b + x3 * (a + x2)) -end - -@doc raw""" - lagrange_derivative(x::T, a::T, b::T) where {T <: Number} - -Derivative of Lagrange polynomial to be solved during Gauss method. -""" -function lagrange_derivative(x::T, a::U, b::U) where {T, U <: Number} - # Evaluate via Horner's method - x2 = x * x - x3 = x2 * x - return x2 * (3*b + x3 * (6*a + 8*x2)) -end - -# TO DO: Allow to control interval over which to look for solutions -# Currently we look between the radius of the Sun (∼0.00465047 AU) and -# the radius of the Solar System (∼40 AU) - -@doc raw""" - solve_lagrange(a::T, b::T, c::T; niter::Int = 5) where {T <: Real} - solve_lagrange(a::TaylorN{T}, b::TaylorN{T}, c::TaylorN{T}; niter::Int = 5) where {T <: Real} - -Solve Lagrange polynomial. - -See also [`lagrange`](@ref). -""" -function solve_lagrange(a::T, b::T, c::T; niter::Int = 5) where {T <: Real} - return find_zeros(x -> lagrange(x, a, b, c), 0.00465047, 40.0) -end - -function solve_lagrange(a::TaylorN{T}, b::TaylorN{T}, c::TaylorN{T}; niter::Int = 5) where {T <: Real} - # 0-th order solution - sol_0 = solve_lagrange(cte(a), cte(b), cte(c)) - # Vector of solutions - sol = Vector{TaylorN{T}}(undef, length(sol_0)) - # Conversion factor to TaylorN - oneN = one(a) - # Iterate solutions - for i in eachindex(sol) - # Newton's method - r_0::TaylorN{T} = sol_0[i] * oneN - r_2::TaylorN{T} = sol_0[i] * oneN - for j in 1:niter - r_2 = r_0 - lagrange(r_0, a, b, c) / lagrange_derivative(r_0, a, b) - r_0 = r_2 - end - sol[i] = r_2 - end - - return sol -end - -@doc raw""" - heliocentric_energy(r::Vector{T}) where {T <: Number} - -Return the heliocentric energy per unit mass for heliocentric state vector `r` [au, au/day]. -""" -function heliocentric_energy(r::Vector{T}) where {T <: Number} - @assert length(r) == 6 "r must have length 6" - kinetic = 0.5 * (r[4]^2 + r[5]^2 + r[6]^2) - potential = k_gauss^2 / sqrt(r[1]^2 + r[2]^2 + r[3]^2) - return kinetic - potential -end - -@doc raw""" - gauss_method(obs::Vector{RadecMPC{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} - gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{DateTime}, - α::Vector{U}, δ::Vector{U}, params::NEOParameters{T}) where {T <: Real, U <: Number} - -Core Gauss method of Initial Orbit determination (IOD). - -# Arguments - -- `obs::Vector{RadecMPC{T}}`: three observations. -- `observatories::Vector{ObservatoryMPC{T}}`: sites of observation. -- `dates::Vector{DateTime}`: times of observation. -- `α::Vector{U}`: right ascension [rad]. -- `δ::Vector{U}`: declination [rad]. -- `params::NEOParameters{T}`: see `Gauss Method Parameters` of [`NEOParameters`](@ref). - -!!! reference - See Algorithm 5.5 in page 274 https://doi.org/10.1016/C2016-0-02107-1. -""" -function gauss_method(obs::Vector{RadecMPC{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} - - # Make sure observations are in temporal order - sort!(obs) - # Sites of observation - observatories = observatory.(obs) - # Dates of observation - dates = date.(obs) - # Right ascension - α = ra.(obs) - # Declination - δ = dec.(obs) - - return gauss_method(observatories, dates, α, δ, params) -end - -function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{DateTime}, - α::Vector{U}, δ::Vector{U}, params::NEOParameters{T}) where {T <: Real, U <: Number} - - # Check we have exactly three observations - @assert length(observatories) == length(dates) == length(α) == length(δ) == 3 "Gauss method requires exactly three observations" - # Check observations are in temporal order - @assert issorted(dates) "Observations must be in temporal order" - - # Times of observation [et] - t_et = datetime2et.(dates) - # Times of observation [days since J2000] - t_days = t_et ./ daysec - - # Time intervals - τ_1 = t_days[1] - t_days[2] - τ_3 = t_days[3] - t_days[2] - τ = τ_3 - τ_1 - - # NEO's topocentric position unit vectors - ρ_vec = vectors2matrix(topounit.(α, δ)) - # Geocentric state vector of the observer [au, au/day] - g_vec = kmsec2auday.(obsposvelECI.(observatories, t_et)) - # Heliocentric state vector of the Earth [au, au/day] - G_vec = params.eph_ea.(t_days) - params.eph_su.(t_days) - # Observer's heliocentric positions [au, au/day] - R_vec = vectors2matrix(G_vec .+ g_vec)[:, 1:3] - - # Cross products - p_vec = zeros(U, 3, 3) - p_vec[1, :] = @views cross(ρ_vec[2, :], ρ_vec[3, :]) - p_vec[2, :] = @views cross(ρ_vec[1, :], ρ_vec[3, :]) - p_vec[3, :] = @views cross(ρ_vec[1, :], ρ_vec[2, :]) - - # Gauss scalar - D_0 = dot(ρ_vec[1, :], p_vec[1, :]) - - # Matrix of triple products - D = zeros(U, 3, 3) - for i in 1:3 - for j in 1:3 - D[i, j] = @views dot(R_vec[i, :], p_vec[j, :]) - end - end - - # A and B scalars - A = (-D[1, 2]*τ_3/τ + D[2, 2] + D[3, 2]*τ_1/τ) / D_0 - B = (D[1, 2]*(τ_3^2 - τ^2)*τ_3/τ + D[3, 2]*(τ^2 - τ_1^2)*τ_1/τ) / 6 / D_0 - - # E and F scalars - E = @views dot(R_vec[2, :], ρ_vec[2, :]) - F = @views dot(R_vec[2, :], R_vec[2, :]) - - # Lagrange equation coefficients - a = -(A*A + 2*A*E + F) - b = -2*μ_S*B*(A + E) - c = -(μ_S^2)*(B*B) - - # Solve Lagrange equation - sol = solve_lagrange(a, b, c; niter = params.niter) - - # Number of solutions - n_sol = length(sol) - - if iszero(n_sol) - - @warn("""No solutions found for Lagrange equation $(_format_Lagrange_equation(cte(a), cte(b), cte(c)))""") - - return Vector{GaussSolution{T, U}}(undef, 0) - - else - - sol_gauss = Vector{GaussSolution{T, U}}(undef, n_sol) - - for i in eachindex(sol_gauss) - # Heliocentric range - r_2 = sol[i] - # Range cubed - r_23 = r_2 * r_2 * r_2 - # Slant ranges - ρ = zeros(U, 3) - - num_1 = 6*(D[3, 1]*τ_1/τ_3 + D[2, 1]*τ/τ_3)*r_23 + μ_S*D[3, 1]*(τ^2 - τ_1^2)*τ_1/τ_3 - den_1 = 6*r_23 + μ_S*(τ^2 - τ_3^2) - ρ[1] = (num_1 / den_1 - D[1, 1]) / D_0 - - ρ[2] = A + μ_S*B/r_23 - - num_3 = 6*(D[1, 3]*τ_3/τ_1 - D[2, 3]*τ/τ_1)*r_23 + μ_S*D[1, 3]*(τ^2 - τ_3^2)*τ_3/τ_1 - den_3 = 6*r_23 + μ_S*(τ^2 - τ_1^2) - ρ[3] = (num_3 / den_3 - D[3, 3]) / D_0 - - # Heliocentric position of the NEO - r_vec = R_vec .+ ρ .* ρ_vec - - # f, g Lagrange coefficients - f_1 = f_Lagrange(τ_1, r_2) - f_3 = f_Lagrange(τ_3, r_2) - - g_1 = g_Lagrange(τ_1, r_2) - g_3 = g_Lagrange(τ_3, r_2) - - # Heliocentric velocity of the NEO - v_2_vec = @views (- f_3 * r_vec[1, :] + f_1 * r_vec[3, :]) / (f_1*g_3 - f_3*g_1) - - sol_gauss[i] = GaussSolution{T, U}( - vcat(r_vec[2, :], v_2_vec), ρ, D, R_vec, - ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3 - ) - end - # Sort solutions by heliocentric range - return sort!(sol_gauss, by = x -> norm(cte.(x.statevect[1:3]))) - - end - -end - -@doc raw""" - numberofdays(dates::Vector{DateTime}) - numberofdays(dates::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - numberofdays(dates::Vector{Tracklet{T}}) where {T <: AbstractFloat} - -Return the time span of `dates` in days. The function assumes `dates` is sorted. -""" -numberofdays(dates::Vector{DateTime}) = (dates[end] - dates[1]).value / 86_400_000 - -function numberofdays(dates::Vector{RadecMPC{T}}) where {T <: AbstractFloat} - return (dates[end].date - dates[1].date).value / 86_400_000 -end - -function numberofdays(dates::Vector{Tracklet{T}}) where {T <: AbstractFloat} - return (dates[end].radec[end].date - dates[1].radec[1].date).value / 86_400_000 -end - -@doc raw""" - gauss_norm(dates::Vector{DateTime}) - -Return a measure of how evenly distributed in time a triplet is; -used within [`gauss_triplets`](@ref) to sort triplets for Gauss method. -The function assumes `dates` is sorted. -""" -gauss_norm(dates::Vector{DateTime}) = abs( (dates[2] - dates[1]).value - (dates[3] - dates[2]).value ) / 86_400_000 - -@doc raw""" - gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_iter::Int = 100) - -Return a vector of `max_triplets` triplets to be used within [`gaussinitcond`](@ref) -to select the best observations for Gauss method. The triplets are sorted by [`gauss_norm`](@ref). -""" -function gauss_triplets(dates::Vector{DateTime}, Δ_min::Period, Δ_max::Period, - avoid::Vector{Vector{Int}}, max_triplets::Int) - - triplets = Vector{Vector{Int}}(undef, 0) - L = length(dates) - for i_1 in 1:L-2 - for i_2 in i_1+1:L-1 - for i_3 in i_2+1:L - tmp = [i_1, i_2, i_3] - if (Δ_min <= dates[i_3] - dates[i_1] <= Δ_max) && !(tmp in avoid) - push!(triplets, tmp) - end - end - end - end - - sort!(triplets, by = x -> gauss_norm(dates[x])) - - n = min(length(triplets), max_triplets) - - return triplets[1:n] -end - -function gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_iter::Int = 100) - Δ_min = Hour(20) - Δ_max = Day(7) - - triplets = Vector{Vector{Int}}(undef, 0) - - niter = 0 - - while length(triplets) < max_triplets && niter < max_iter - triplets = vcat(triplets, gauss_triplets(dates, Δ_min, Δ_max, triplets, max_triplets)) - if Δ_min >= Hour(1) - Δ_min -= Hour(1) - end - Δ_max += Day(1) - niter += 1 - end - - n = min(length(triplets), max_triplets) - - return triplets[1:n] -end - -@doc raw""" - gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, - params::NEOParameters{T}; dynamics::D = newtonian!) where {T <: AbstractFloat, D} - -Return initial conditions via Gauss Method. - -See also [`gauss_method`](@ref). - -# Arguments - -- `radec::Vector{RadecMPC{T}}`: vector of observations. -- `tracklets::Vector{Tracklet{T}},`: vector of tracklets. -- `params::NEOParameters{T}`: see `Gauss Method Parameters` of [`NEOParameters`](@ref). -- `dynamics::D`: dynamical model. - -!!! warning - This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. -""" -function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, - params::NEOParameters{T}; dynamics::D = newtonian!) where {T <: AbstractFloat, D} - - # Allocate memory for initial conditions - best_sol = zero(NEOSolution{T, T}) - # Unfold - observatories, dates, α, δ = observatory.(tracklets), date.(tracklets), ra.(tracklets), dec.(tracklets) - # Observations triplets - triplets = gauss_triplets(dates, params.max_triplets) - # Start point of LS fits - x0 = zeros(T, 6) - # Jet transport scaling factors - scalings = fill(1e-6, 6) - # Jet transport perturbation (ra/dec) - dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃", scalings, - order = params.varorder) - # Normalized root mean square error (NRMS) - best_Q = T(Inf) - # Break flag - flag = false - - # Iterate over triplets - for j in eachindex(triplets) - - # Current triplet - triplet = triplets[j] - # Julian day of middle observation - _jd0_ = datetime2julian(dates[triplet[2]]) - # Gauss method solution - sol = gauss_method(observatories[triplet], dates[triplet], α[triplet] .+ dq[1:3], - δ[triplet] .+ dq[4:6], params) - # Filter Gauss solutions by heliocentric energy - filter!(x -> heliocentric_energy(x.statevect) <= 0, sol) - - # Iterate over Gauss solutions - for i in eachindex(sol) - - # Light-time correction - jd0 = _jd0_ - cte(sol[i].ρ[2]) / c_au_per_day - # Initial conditions (jet transport) - q0 = sol[i].statevect .+ params.eph_su(jd0 - PE.J2000) - - # Propagation and residuals - bwd, fwd, res = propres(radec, jd0, q0, params; dynamics) - iszero(length(res)) && continue - - # Subset of radec for orbit fit - g_0 = triplet[1] - g_f = triplet[3] - idxs = reduce(vcat, indices.(tracklets[g_0:g_f])) - sort!(idxs) - # Orbit fit - fit = tryls(res[idxs], x0, params.niter) - !fit.success && continue - - # Right iteration - for k in g_f+1:length(tracklets) - extra = indices(tracklets[k]) - fit_new = tryls(res[idxs ∪ extra], x0, params.niter) - if fit_new.success - fit = fit_new - idxs = vcat(idxs, extra) - sort!(idxs) - g_f = k - else - break - end - end - - # Left iteration - for k in g_0-1:-1:1 - extra = indices(tracklets[k]) - fit_new = tryls(res[idxs ∪ extra], x0, params.niter) - if fit_new.success - fit = fit_new - idxs = vcat(idxs, extra) - sort!(idxs) - g_0 = k - else - break - end - end - - # NRMS - Q = nrms(res, fit) - - # TO DO: check cases where newton converges but diffcorr no - # Update NRMS and initial conditions - if Q < best_Q - best_Q = Q - best_sol = evalfit(NEOSolution(tracklets[g_0:g_f], bwd, fwd, - res[idxs], fit, scalings)) - end - # Break condition - if Q <= params.gaussQmax - flag = true - break - end - end - if flag - break - end - end - - # Case: all solutions were unsuccesful - if isinf(best_Q) - return zero(NEOSolution{T, T}) - # Case: at least one solution was succesful - else - return best_sol - end - +@doc raw""" + GaussSolution{T <: Real, U <: Number} + +A preliminary orbit obtained from Gauss method of orbit determination. + +See also [`gauss_method`](@ref). + +# Fields + +- `statevect::Vector{U}`: state vector at middle observation. +- `ρ::Vector{U}`: topocentric ranges. +- `D::Matrix{U}`: D matrix. +- `R_vec::Matrix{T}`: observer's heliocentric positions. +- `ρ_vec::Matrix{U}`: line of sight unit vectors. +- `τ_1::T`: time between first and second observations. +- `τ_3::T`: time between third and second observations. +- `f_1, g_1, f_3, g_3::U`: Lagrange coefficients. + +!!! reference + See Algorithm 5.5 in page 274 of https://doi.org/10.1016/C2016-0-02107-1. +""" +@auto_hash_equals struct GaussSolution{T <: Real, U <: Number} + statevect::Vector{U} + ρ::Vector{U} + D::Matrix{U} + R_vec::Matrix{T} + ρ_vec::Matrix{U} + τ_1::T + τ_3::T + f_1::U + g_1::U + f_3::U + g_3::U + # Inner constructor + function GaussSolution{T, U}( + statevect::Vector{U}, ρ::Vector{U}, D::Matrix{U}, R_vec::Matrix{T}, + ρ_vec::Matrix{U}, τ_1::T, τ_3::T, f_1::U, g_1::U, f_3::U, g_3::U) where {T <: Real, U <: Number} + return new{T, U}(statevect, ρ, D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3) + end +end + +# Outer constructor +function GaussSolution( + statevect::Vector{U}, ρ::Vector{U}, D::Matrix{U}, R_vec::Matrix{T}, + ρ_vec::Matrix{U}, τ_1::T, τ_3::T, f_1::U, g_1::U, f_3::U, g_3::U) where {T <: Real, U <: Number} + return GaussSolution{T, U}(statevect, ρ, D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3) +end + +# Print method for GaussSolution +# Examples: +# Gauss solution (r = 1.0800950907383229 AU) +function show(io::IO, g::GaussSolution{T, U}) where {T <: Real, U <: Number} + print(io, "Gauss solution (r = ", norm(cte.(g.statevect[1:3])), " AU)") +end + +@doc raw""" + topounit(α::T, δ::T) where {T <: Number} + topounit(obs::RadecMPC{T}) where {T <: AbstractFloat} + +Return the topocentric unit vector. +""" +function topounit(α::T, δ::T) where {T <: Number} + + sin_α, cos_α = sincos(α) + sin_δ, cos_δ = sincos(δ) + + pos = [cos_δ * cos_α, cos_δ * sin_α, sin_δ] + + return pos +end + +topounit(obs::RadecMPC{T}) where {T <: AbstractFloat} = topounit(obs.α, obs.δ) + +# TO DO: Should we allow to use other μ? + +@doc raw""" + f_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} + +Return the 1st order approximation to Lagrange's f function. +""" +function f_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} + r3 = r * r * r + return 1 - μ_S * (τ^2) / 2 / r3 +end + +@doc raw""" + g_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} + +Return the 1st order approximation to Lagrange's g function. +""" +function g_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} + r3 = r * r * r + return τ - μ_S * (τ^3) / 6 / r3 +end + +@doc raw""" + vectors2matrix(x::T) where {T <: AbstractVector} + +Convert a vector of vectors `x` to a matrix. +""" +vectors2matrix(x::T) where {T <: AbstractVector} = permutedims(reduce(hcat, x)) + +@doc raw""" + _format_Lagrange_equation(a::T, b::T, c::T) where {T <: AbstractFloat} + +Format Lagrange equation as `r⁸ + a r⁶ + b r³ + c = 0`. +""" +function _format_Lagrange_equation(a::T, b::T, c::T) where {T <: AbstractFloat} + a_sgn = a ≥ 0 ? "+" : "-" + b_sgn = b ≥ 0 ? "+" : "-" + c_sgn = c ≥ 0 ? "+" : "-" + + return join(["r⁸ ", a_sgn, " ", abs(a), " r⁶ ", b_sgn, " ", abs(b), " r³ ", c_sgn, " ", abs(c), " = 0"]) +end + +@doc raw""" + lagrange(x::T, a::U, b::U, c::U) where {T, U <: Number} + +Lagrange polynomial to be solved during Gauss method. +""" +function lagrange(x::T, a::U, b::U, c::U) where {T, U <: Number} + # Evaluate via Horner's method + x2 = x * x + x3 = x2 * x + return c + x3 * (b + x3 * (a + x2)) +end + +@doc raw""" + lagrange_derivative(x::T, a::T, b::T) where {T <: Number} + +Derivative of Lagrange polynomial to be solved during Gauss method. +""" +function lagrange_derivative(x::T, a::U, b::U) where {T, U <: Number} + # Evaluate via Horner's method + x2 = x * x + x3 = x2 * x + return x2 * (3*b + x3 * (6*a + 8*x2)) +end + +# TO DO: Allow to control interval over which to look for solutions +# Currently we look between the radius of the Sun (∼0.00465047 AU) and +# the radius of the Solar System (∼40 AU) + +@doc raw""" + solve_lagrange(a::T, b::T, c::T; niter::Int = 5) where {T <: Real} + solve_lagrange(a::TaylorN{T}, b::TaylorN{T}, c::TaylorN{T}; niter::Int = 5) where {T <: Real} + +Solve Lagrange polynomial. + +See also [`lagrange`](@ref). +""" +function solve_lagrange(a::T, b::T, c::T; niter::Int = 5) where {T <: Real} + return find_zeros(x -> lagrange(x, a, b, c), 0.00465047, 40.0) +end + +function solve_lagrange(a::TaylorN{T}, b::TaylorN{T}, c::TaylorN{T}; niter::Int = 5) where {T <: Real} + # 0-th order solution + sol_0 = solve_lagrange(cte(a), cte(b), cte(c)) + # Vector of solutions + sol = Vector{TaylorN{T}}(undef, length(sol_0)) + # Conversion factor to TaylorN + oneN = one(a) + # Iterate solutions + for i in eachindex(sol) + # Newton's method + r_0::TaylorN{T} = sol_0[i] * oneN + r_2::TaylorN{T} = sol_0[i] * oneN + for j in 1:niter + r_2 = r_0 - lagrange(r_0, a, b, c) / lagrange_derivative(r_0, a, b) + r_0 = r_2 + end + sol[i] = r_2 + end + + return sol +end + +@doc raw""" + heliocentric_energy(r::Vector{T}) where {T <: Number} + +Return the heliocentric energy per unit mass for heliocentric state vector `r` [au, au/day]. +""" +function heliocentric_energy(r::Vector{T}) where {T <: Number} + @assert length(r) == 6 "r must have length 6" + kinetic = 0.5 * (r[4]^2 + r[5]^2 + r[6]^2) + potential = k_gauss^2 / sqrt(r[1]^2 + r[2]^2 + r[3]^2) + return kinetic - potential +end + +@doc raw""" + gauss_method(obs::Vector{RadecMPC{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} + gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{DateTime}, + α::Vector{U}, δ::Vector{U}, params::NEOParameters{T}) where {T <: Real, U <: Number} + +Core Gauss method of Initial Orbit determination (IOD). + +# Arguments + +- `obs::Vector{RadecMPC{T}}`: three observations. +- `observatories::Vector{ObservatoryMPC{T}}`: sites of observation. +- `dates::Vector{DateTime}`: times of observation. +- `α::Vector{U}`: right ascension [rad]. +- `δ::Vector{U}`: declination [rad]. +- `params::NEOParameters{T}`: see `Gauss Method Parameters` of [`NEOParameters`](@ref). + +!!! reference + See Algorithm 5.5 in page 274 https://doi.org/10.1016/C2016-0-02107-1. +""" +function gauss_method(obs::Vector{RadecMPC{T}}, params::NEOParameters{T}) where {T <: AbstractFloat} + + # Make sure observations are in temporal order + sort!(obs) + # Sites of observation + observatories = observatory.(obs) + # Dates of observation + dates = date.(obs) + # Right ascension + α = ra.(obs) + # Declination + δ = dec.(obs) + + return gauss_method(observatories, dates, α, δ, params) +end + +function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{DateTime}, + α::Vector{U}, δ::Vector{U}, params::NEOParameters{T}) where {T <: Real, U <: Number} + + # Check we have exactly three observations + @assert length(observatories) == length(dates) == length(α) == length(δ) == 3 "Gauss method requires exactly three observations" + # Check observations are in temporal order + @assert issorted(dates) "Observations must be in temporal order" + + # Times of observation [et] + t_et = datetime2et.(dates) + # Times of observation [days since J2000] + t_days = t_et ./ daysec + + # Time intervals + τ_1 = t_days[1] - t_days[2] + τ_3 = t_days[3] - t_days[2] + τ = τ_3 - τ_1 + + # NEO's topocentric position unit vectors + ρ_vec = vectors2matrix(topounit.(α, δ)) + # Geocentric state vector of the observer [au, au/day] + g_vec = kmsec2auday.(obsposvelECI.(observatories, t_et)) + # Heliocentric state vector of the Earth [au, au/day] + G_vec = params.eph_ea.(t_days) - params.eph_su.(t_days) + # Observer's heliocentric positions [au, au/day] + R_vec = vectors2matrix(G_vec .+ g_vec)[:, 1:3] + + # Cross products + p_vec = zeros(U, 3, 3) + p_vec[1, :] = @views cross(ρ_vec[2, :], ρ_vec[3, :]) + p_vec[2, :] = @views cross(ρ_vec[1, :], ρ_vec[3, :]) + p_vec[3, :] = @views cross(ρ_vec[1, :], ρ_vec[2, :]) + + # Gauss scalar + D_0 = dot(ρ_vec[1, :], p_vec[1, :]) + + # Matrix of triple products + D = zeros(U, 3, 3) + for i in 1:3 + for j in 1:3 + D[i, j] = @views dot(R_vec[i, :], p_vec[j, :]) + end + end + + # A and B scalars + A = (-D[1, 2]*τ_3/τ + D[2, 2] + D[3, 2]*τ_1/τ) / D_0 + B = (D[1, 2]*(τ_3^2 - τ^2)*τ_3/τ + D[3, 2]*(τ^2 - τ_1^2)*τ_1/τ) / 6 / D_0 + + # E and F scalars + E = @views dot(R_vec[2, :], ρ_vec[2, :]) + F = @views dot(R_vec[2, :], R_vec[2, :]) + + # Lagrange equation coefficients + a = -(A*A + 2*A*E + F) + b = -2*μ_S*B*(A + E) + c = -(μ_S^2)*(B*B) + + # Solve Lagrange equation + sol = solve_lagrange(a, b, c; niter = params.niter) + + # Number of solutions + n_sol = length(sol) + + if iszero(n_sol) + + @warn("""No solutions found for Lagrange equation $(_format_Lagrange_equation(cte(a), cte(b), cte(c)))""") + + return Vector{GaussSolution{T, U}}(undef, 0) + + else + + sol_gauss = Vector{GaussSolution{T, U}}(undef, n_sol) + + for i in eachindex(sol_gauss) + # Heliocentric range + r_2 = sol[i] + # Range cubed + r_23 = r_2 * r_2 * r_2 + # Slant ranges + ρ = zeros(U, 3) + + num_1 = 6*(D[3, 1]*τ_1/τ_3 + D[2, 1]*τ/τ_3)*r_23 + μ_S*D[3, 1]*(τ^2 - τ_1^2)*τ_1/τ_3 + den_1 = 6*r_23 + μ_S*(τ^2 - τ_3^2) + ρ[1] = (num_1 / den_1 - D[1, 1]) / D_0 + + ρ[2] = A + μ_S*B/r_23 + + num_3 = 6*(D[1, 3]*τ_3/τ_1 - D[2, 3]*τ/τ_1)*r_23 + μ_S*D[1, 3]*(τ^2 - τ_3^2)*τ_3/τ_1 + den_3 = 6*r_23 + μ_S*(τ^2 - τ_1^2) + ρ[3] = (num_3 / den_3 - D[3, 3]) / D_0 + + # Heliocentric position of the NEO + r_vec = R_vec .+ ρ .* ρ_vec + + # f, g Lagrange coefficients + f_1 = f_Lagrange(τ_1, r_2) + f_3 = f_Lagrange(τ_3, r_2) + + g_1 = g_Lagrange(τ_1, r_2) + g_3 = g_Lagrange(τ_3, r_2) + + # Heliocentric velocity of the NEO + v_2_vec = @views (- f_3 * r_vec[1, :] + f_1 * r_vec[3, :]) / (f_1*g_3 - f_3*g_1) + + sol_gauss[i] = GaussSolution{T, U}( + vcat(r_vec[2, :], v_2_vec), ρ, D, R_vec, + ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3 + ) + end + # Sort solutions by heliocentric range + return sort!(sol_gauss, by = x -> norm(cte.(x.statevect[1:3]))) + + end + +end + +@doc raw""" + numberofdays(dates::Vector{DateTime}) + numberofdays(dates::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + numberofdays(dates::Vector{Tracklet{T}}) where {T <: AbstractFloat} + +Return the time span of `dates` in days. The function assumes `dates` is sorted. +""" +numberofdays(dates::Vector{DateTime}) = (dates[end] - dates[1]).value / 86_400_000 + +function numberofdays(dates::Vector{RadecMPC{T}}) where {T <: AbstractFloat} + return (dates[end].date - dates[1].date).value / 86_400_000 +end + +function numberofdays(dates::Vector{Tracklet{T}}) where {T <: AbstractFloat} + return (dates[end].radec[end].date - dates[1].radec[1].date).value / 86_400_000 +end + +@doc raw""" + gauss_norm(dates::Vector{DateTime}) + +Return a measure of how evenly distributed in time a triplet is; +used within [`gauss_triplets`](@ref) to sort triplets for Gauss method. +The function assumes `dates` is sorted. +""" +gauss_norm(dates::Vector{DateTime}) = abs( (dates[2] - dates[1]).value - (dates[3] - dates[2]).value ) / 86_400_000 + +@doc raw""" + gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_iter::Int = 100) + +Return a vector of `max_triplets` triplets to be used within [`gaussinitcond`](@ref) +to select the best observations for Gauss method. The triplets are sorted by [`gauss_norm`](@ref). +""" +function gauss_triplets(dates::Vector{DateTime}, Δ_min::Period, Δ_max::Period, + avoid::Vector{Vector{Int}}, max_triplets::Int) + + triplets = Vector{Vector{Int}}(undef, 0) + L = length(dates) + for i_1 in 1:L-2 + for i_2 in i_1+1:L-1 + for i_3 in i_2+1:L + tmp = [i_1, i_2, i_3] + if (Δ_min <= dates[i_3] - dates[i_1] <= Δ_max) && !(tmp in avoid) + push!(triplets, tmp) + end + end + end + end + + sort!(triplets, by = x -> gauss_norm(dates[x])) + + n = min(length(triplets), max_triplets) + + return triplets[1:n] +end + +function gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_iter::Int = 100) + Δ_min = Hour(20) + Δ_max = Day(7) + + triplets = Vector{Vector{Int}}(undef, 0) + + niter = 0 + + while length(triplets) < max_triplets && niter < max_iter + triplets = vcat(triplets, gauss_triplets(dates, Δ_min, Δ_max, triplets, max_triplets)) + if Δ_min >= Hour(1) + Δ_min -= Hour(1) + end + Δ_max += Day(1) + niter += 1 + end + + n = min(length(triplets), max_triplets) + + return triplets[1:n] +end + +@doc raw""" + gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, + params::NEOParameters{T}; dynamics::D = newtonian!) where {T <: AbstractFloat, D} + +Return initial conditions via Gauss Method. + +See also [`gauss_method`](@ref). + +# Arguments + +- `radec::Vector{RadecMPC{T}}`: vector of observations. +- `tracklets::Vector{Tracklet{T}},`: vector of tracklets. +- `params::NEOParameters{T}`: see `Gauss Method Parameters` of [`NEOParameters`](@ref). +- `dynamics::D`: dynamical model. + +!!! warning + This function will set the (global) `TaylorSeries` variables to `δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃`. +""" +function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, + params::NEOParameters{T}; dynamics::D = newtonian!) where {T <: AbstractFloat, D} + + # Allocate memory for initial conditions + best_sol = zero(NEOSolution{T, T}) + # Unfold + observatories, dates, α, δ = observatory.(tracklets), date.(tracklets), ra.(tracklets), dec.(tracklets) + # Observations triplets + triplets = gauss_triplets(dates, params.max_triplets) + # Start point of LS fits + x0 = zeros(T, 6) + # Jet transport scaling factors + scalings = fill(1e-6, 6) + # Jet transport perturbation (ra/dec) + dq = scaled_variables("δα₁ δα₂ δα₃ δδ₁ δδ₂ δδ₃", scalings, + order = params.varorder) + # Normalized root mean square error (NRMS) + best_Q = T(Inf) + # Break flag + flag = false + + # Iterate over triplets + for j in eachindex(triplets) + + # Current triplet + triplet = triplets[j] + # Julian day of middle observation + _jd0_ = datetime2julian(dates[triplet[2]]) + # Gauss method solution + sol = gauss_method(observatories[triplet], dates[triplet], α[triplet] .+ dq[1:3], + δ[triplet] .+ dq[4:6], params) + # Filter Gauss solutions by heliocentric energy + filter!(x -> heliocentric_energy(x.statevect) <= 0, sol) + + # Iterate over Gauss solutions + for i in eachindex(sol) + + # Light-time correction + jd0 = _jd0_ - cte(sol[i].ρ[2]) / c_au_per_day + # Initial conditions (jet transport) + q0 = sol[i].statevect .+ params.eph_su(jd0 - PE.J2000) + + # Propagation and residuals + bwd, fwd, res = propres(radec, jd0, q0, params; dynamics) + iszero(length(res)) && continue + + # Subset of radec for orbit fit + g_0 = triplet[1] + g_f = triplet[3] + idxs = reduce(vcat, indices.(tracklets[g_0:g_f])) + sort!(idxs) + # Orbit fit + fit = tryls(res[idxs], x0, params.niter) + !fit.success && continue + + # Right iteration + for k in g_f+1:length(tracklets) + extra = indices(tracklets[k]) + fit_new = tryls(res[idxs ∪ extra], x0, params.niter) + if fit_new.success + fit = fit_new + idxs = vcat(idxs, extra) + sort!(idxs) + g_f = k + else + break + end + end + + # Left iteration + for k in g_0-1:-1:1 + extra = indices(tracklets[k]) + fit_new = tryls(res[idxs ∪ extra], x0, params.niter) + if fit_new.success + fit = fit_new + idxs = vcat(idxs, extra) + sort!(idxs) + g_0 = k + else + break + end + end + + # NRMS + Q = nrms(res, fit) + + # TO DO: check cases where newton converges but diffcorr no + # Update NRMS and initial conditions + if Q < best_Q + best_Q = Q + best_sol = evalfit(NEOSolution(tracklets[g_0:g_f], bwd, fwd, + res[idxs], fit, scalings)) + end + # Break condition + if Q <= params.gaussQmax + flag = true + break + end + end + if flag + break + end + end + + # Case: all solutions were unsuccesful + if isinf(best_Q) + return zero(NEOSolution{T, T}) + # Case: at least one solution was succesful + else + return best_sol + end + end \ No newline at end of file diff --git a/src/orbit_determination/least_squares.jl b/src/orbit_determination/least_squares.jl old mode 100755 new mode 100644 index d862c4b2..83d686f1 --- a/src/orbit_determination/least_squares.jl +++ b/src/orbit_determination/least_squares.jl @@ -1,815 +1,815 @@ -@doc raw""" - LeastSquaresFit{T <: Real} - -A least squares fit. - -# Fields -- `success::Bool`: whether the routine converged or not. -- `x::Vector{T}`: deltas that minimize the objective function. -- `Γ::Matrix{T}`: covariance matrix. -- `routine::Symbol`: minimization routine (`:newton` or `:diffcorr`). -""" -@auto_hash_equals struct LeastSquaresFit{T <: Real} - success::Bool - x::Vector{T} - Γ::Matrix{T} - routine::Symbol - # Inner constructor - function LeastSquaresFit{T}(success::Bool, x::Vector{T}, Γ::Matrix{T}, - routine::Symbol) where {T <: Real} - return new{T}(success, x, Γ, routine) - end -end -# Outer constructor -function LeastSquaresFit(success::Bool, x::Vector{T}, Γ::Matrix{T}, - routine::Symbol) where {T <: Real} - return LeastSquaresFit{T}(success, x, Γ, routine) -end - -# Definition of zero LeastSquaresFit{T} -function zero(::Type{LeastSquaresFit{T}}) where {T <: Real} - return LeastSquaresFit{T}(false, Vector{T}(undef, 0), Matrix{T}(undef, 0, 0), :zero) -end - -# Print method for LeastSquaresFit -# Examples: -# Succesful Newton -# Succesful differential corrections -function show(io::IO, fit::LeastSquaresFit{T}) where {T <: Real} - success_s = fit.success ? "Succesful" : "Unsuccesful" - if fit.routine == :newton - routine_s = "Newton" - elseif fit.routine == :diffcorr - routine_s = "Differential Corrections" - elseif fit.routine == :lm - routine_s = "Levenberg-Marquardt" - else - routine_s = "Least Squares" - end - print(io, success_s, " ", routine_s) -end - -@doc raw""" - carpino_smoothing(n::T) where {T <: Real} - -Fudge term for rejection condition in [`outlier_rejection`](@ref). - -!!! reference - See page 253 of https://doi.org/10.1016/S0019-1035(03)00051-4. -""" -carpino_smoothing(n::T) where {T <: Real} = 400*(1.2)^(-n) - -@doc raw""" - outlier_rejection(ξs::Vector{OpticalResidual{T, TaylorN{T}}}, fit::LeastSquaresFit{T}; - χ2_rec::T = 7.0, χ2_rej::T = 8.0, α::T = 0.25, max_per::T = 10.) where {T <: Real} - -Outlier rejection algorithm. - -# Arguments - -- `ξs::Vector{OpticalResidual{T}}`: vector of residuals. -- `fit::LeastSquaresFit{T}`: least squares fit. -- `χ2_rec::T`: recovery condition. -- `χ2_rej::T`: rejection condition. -- `α::T`: scaling factor for maximum chi. -- `max_per::T`: maximum allowed drop percentage. - -!!! reference - See https://doi.org/10.1016/S0019-1035(03)00051-4. -""" -function outlier_rejection(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::LeastSquaresFit{T}; - χ2_rec::T = 7., χ2_rej::T = 8., α::T = 0.25, max_per::T = 10.) where {T <: Real} - - # Number of residuals - L = length(res) - # Evaluate residuals - eval_res = res(fit.x) - # Vector of χ2 - χ2s = Vector{T}(undef, L) - # Maximum χ2 (over non outliers) - χ2_max = zero(T) - # Number of non outliers - N_sel = 0 - - # Compute χ2s - for i in eachindex(χ2s) - # Weights of current residual - w_α, w_δ = res[i].w_α / res[i].relax_factor, res[i].w_δ / res[i].relax_factor - # Current observation covariance matrix - γ = [w_α zero(T); zero(T) w_δ] - # Current model matrix - A = hcat(TS.gradient(res[i].ξ_α)(fit.x), TS.gradient(res[i].ξ_δ)(fit.x)) - # Outlier sign - outlier_sign = res[i].outlier*2-1 - # Current residual covariance matrix - γ_ξ = γ + outlier_sign*(A')*fit.Γ*A - # Current residual - ξ = [eval_res[i].ξ_α, eval_res[i].ξ_δ] - # Current chi2 - χ2s[i] = ξ' * inv(γ_ξ) * ξ - # Update N_sel - if !res[i].outlier - N_sel += 1 - # Update maximum χ2 - if χ2s[i] > χ2_max - χ2_max = χ2s[i] - end - end - end - - # Maximum allowed drops - max_drop = ceil(Int, max_per * L / 100) - # Number of dropped residuals - N_drop = 0 - # New outliers - new_outliers = outlier.(res) - # Sort χ2s - idxs = sortperm(χ2s, rev = true) - # Rejection threshold - χ2_rej = max(χ2_rej + carpino_smoothing(N_sel), α*χ2_max) - - for i in idxs - if χ2s[i] > χ2_rej && N_drop < max_drop - new_outliers[i] = true - N_drop += 1 - elseif χ2s[i] < χ2_rec - new_outliers[i] = false - end - end - - return OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), - relax_factor.(res), new_outliers) -end - -@doc raw""" - project(y::Vector{TaylorN{T}}, fit::LeastSquaresFit{T}) where {T <: Real} - -Project `fit`'s covariance matrix into `y`. -""" -function project(y::Vector{TaylorN{T}}, fit::LeastSquaresFit{T}) where {T <: Real} - J = Matrix{T}(undef, get_numvars(), length(y)) - for i in eachindex(y) - J[:, i] = TS.gradient(y[i])(fit.x) - end - return (J') * fit.Γ * J -end - -@doc raw""" - chi2(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} - chi2(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} - -Returns the chi square -```math -\chi^2 = \sum_{i=1}^m \frac{ \xi_i^2}{\sigma_i^2}, -``` -where ``\mathbf{w} = (1/\sigma_1^2,\ldots,1/\sigma_m^2)^T`` and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` -are the vectors of weights and residuals respectively. - -# Arguments - -- `res::Vector{U}/Vector{OpticalResidual{T, U}}`: vector of residuals. -- `w::Vector{T}`: vector of weights. -""" -function chi2(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} - # Have as many residuals as weights - @assert length(res) == length(w) - # Chi square - return sum(w .* (res.^2)) -end -function chi2(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} - _res_, _w_ = unfold(res) - return chi2(_res_, _w_) -end - -@doc raw""" - nms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} - nms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} - nms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::LeastSquaresFit{T}) where {T <: Real} - -Return the normalized chi square. See [`chi2`](@ref). -""" -nms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} = chi2(res, w) / length(res) - -function nms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} - _res_, _w_ = unfold(res) - return nms(_res_, _w_) -end - -function nms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::LeastSquaresFit{T}) where {T <: Real} - _res_, _w_ = unfold(res) - return nms(_res_(fit.x), _w_) -end - -@doc raw""" - nrms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} - nrms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} - nrms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::LeastSquaresFit{T}) where {T <: Real} - -Returns the normalized root mean square error -```math -\texttt{NRMS} = \sqrt{\frac{\chi^2}{m}}, -``` -where ``\chi^2`` is the chi square and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` is the vector -of residuals. - -See also [`chi2`](@ref). - -# Arguments - -- `res::Vector{U}/Vector{OpticalResidual{T, U}}`: Vector of residuals. -- `w::Vector{T}`: Vector of weights. -- `fit::LeastSquaresFit{T}`: least squares fit. - -""" -function nrms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} - # Have as many residuals as weights - @assert length(res) == length(w) - # Normalized root mean square error - return sqrt( chi2(res, w)/length(res) ) -end - -function nrms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} - _res_, _w_ = unfold(res) - return nrms(_res_, _w_) -end - -function nrms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::LeastSquaresFit{T}) where {T <: Real} - _res_, _w_ = unfold(res) - return nrms(_res_(fit.x), _w_) -end - -@doc raw""" - BHC(res::Vector{TaylorN{T}}, w::Vector{T}, npar::Int) where {T <: Real} - -Returns the ``\mathbf{B}``, ``\mathbf{H}`` and ``\mathbf{C}`` arrays -```math -\mathbf{B} = \frac{\partial\mathbf{\xi}}{\partial\mathbf{x}_0}(\mathbf{x}_0), \quad -\mathbf{H} = \frac{\partial^2\mathbf{\xi}}{\partial\mathbf{x}_0^2}(\mathbf{x}_0) \quad \text{and} \quad -\mathbf{C} = \mathbf{B}^T\mathbf{W}\mathbf{B}, -``` -where ``\mathbf{x}_0 = (x_1,\ldots,x_n)^T`` and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` -are the vectors of initial conditions and residuals respectively; and -``\mathbf{W} = \text{diag}(1/\sigma_1^2,\ldots,1/\sigma_m^2)`` is the weights matrix. - -``\mathbf{B}`` is called the design matrix and is of size ``m\times n``, ``\mathbf{H}`` is a three index -array of size ``m\times n\times n`` and ``\mathbf{C}`` is called the normal matrix and is of size ``n\times n``. - -# Arguments - -- `res::Vector{TaylorN{T}}`: vector of residuals. -- `w::Vector{T}`: vector of weights. -- `npar::Int`: degrees of freedom ``n``. - -!!! reference - See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. -""" -function BHC(res::Vector{TaylorN{T}}, w::Vector{T}, npar::Int) where {T <: Real} - # Number of observations - nobs = length(res) - - # Allocate memory for the three arrays - B_mat = Matrix{TaylorN{T}}(undef, nobs, npar) - H_mat = Array{TaylorN{T}}(undef, nobs, npar, npar) - C_mat = Array{TaylorN{T}}(undef, npar, npar) - - # Design matrix B - for i in 1:nobs - # Gradient of the i-th residual with respect to the initial conditions x_0 - B_mat[i,:] .= TaylorSeries.gradient(res[i]) - end - # H matrix - for i in 1:nobs - for j in 1:npar - # Gradient of the (i, j)-th element of B with respect to to the initial - # conditions x_0 - H_mat[i,j,:] .= TaylorSeries.gradient(B_mat[i,j]) - end - end - # Normal matrix C - sqrtw_B = sqrt.(w) .* B_mat - C_mat .= (sqrtw_B') * sqrtw_B - - return B_mat, H_mat, C_mat -end - -@doc raw""" - ξTH(w, res, H_mat, npar) - -Returns ``\mathbf{\xi}^T\mathbf{W}\mathbf{H}``, where ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` -is the vector of residuals, ``\mathbf{W} = \text{diag}(1/\sigma_1^2,\ldots,1/\sigma_m^2)`` is -the weights matrix and ``\mathbf{H}`` is the matrix of second derivatives of ``\mathbf{\xi}`` -with respect to the initial conditions. - -See also [`BHC`](@ref). - -# Arguments - -- `w`: Vector of weights. -- `res`: Vector or residuals. -- `H_mat`: matrix of second derivatives of ``\mathbf{\xi}`` with respect to the initial conditions. -- `npar`: Degrees of freedom ``n``. -""" -function ξTH(w, res, H_mat, npar) - # Allocate memory for output - ξTHv = Array{Float64}(undef, npar, npar) - - for j in 1:npar - for i in 1:npar - # transpose(ξ) * W * H matrix - ξTHv[i,j] = (w .* res)' * (H_mat[:,i,j]) - end - end - - return ξTHv -end - -@doc raw""" - diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, - niters::Int = 5) where {T <: Real} - diffcorr(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, - niters::Int = 5) where {T <: Real} - -Differential corrections subroutine for least-squares fitting. Returns an -`LeastSquaresFit` with the `niters`-th -correction -```math -\mathbf{x}_{k+1} = \mathbf{x}_k - \mathbf{C}^{-1}\mathbf{D}, -``` -and the covariance matrix -```math -\mathbf{\Gamma} = \mathbf{C}^{-1}, -``` -where ``\mathbf{C} = \mathbf{B}^T\mathbf{W}\mathbf{B}`` is the normal matrix and -``\mathbf{D} = \mathbf{B}^T\mathbf{W}\mathbf{\xi}``, with ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` -the vector of residuals, ``\mathbf{B}`` the design matrix and ``\mathbf{W} = \text{diag}(1/\sigma_1^2,\ldots,1/\sigma_m^2)`` -the weights matrix. - -See also [`BHC`](@ref). - -# Arguments - -- `res::Vector{TaylorN{T}/Vector{OpticalResidual{T, TaylorN{T}}}`: vector of residuals. -- `w::Vector{T}`: vector of weights. -- `x_0::Vector{T}`: first guess. -- `niters::Int`: number of iterations. - -!!! reference - See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. -""" -function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, - niters::Int = 5) where {T <: Real} - # TO DO: Adapt diffcorr for idxs - # Degrees of freedom - npar = length(x0) - # Design matrix B, H array and normal matrix C - B_mat, H_mat, C_mat = BHC(res, w, npar) - # D matrix: transpose(B) * W * ξ - D_mat = B_mat' * (w .* res) - # ξTH_mat = ξTH(w, res, H_mat, npar) - # Vector of x - x = Matrix{T}(undef, npar, niters + 1) - # First guess - x[:, 1] = x0 - # Vector of errors - error = Vector{T}(undef, niters + 1) - # Error of first guess - error[1] = T(Inf) - # Iteration - for i in 1:niters - # Current x - xi = x[:, i] - # D matrix evaluated in xi - D = D_mat(xi) - # C matrix evaluated in xi - C = C_mat(xi) #.+ ξTH_mat(xi) - # Update rule - Δx = - inv(C)*D - # New x - x[:, i+1] = xi + Δx - # Error - error2 = ( (Δx') * (C*Δx) ) / npar - if error2 ≥ 0 - error[i+1] = sqrt(error2) - # The method do not converge - else - return LeastSquaresFit(false, x[:, i+1], inv(C), :diffcorr) - end - end - # Index with the lowest error - i = argmin(error) - # x with the lowest error - x_new = x[:, i] - # Normal C matrix evaluated in x_new - C = C_mat(x_new) - # Covariance matrix - Γ = inv(C) - - if any(diag(Γ) .< 0) - return LeastSquaresFit(false, x_new, Γ, :diffcorr) - else - return LeastSquaresFit(true, x_new, Γ, :diffcorr) - end -end - -function diffcorr(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, - niters::Int = 5) where {T <: Real} - # Unfold residuals and weights - _res_, _w_ = unfold(res) - - return diffcorr(_res_, _w_, x0, niters) -end - -@doc raw""" - newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, - niters::Int = 5) where {T <: Real} - newtonls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, - niters::Int = 5) where {T <: Real} - -Newton method subroutine for least-squares fitting. Returns an `LeastSquaresFit` -with the `niters`-th iteration -```math -\mathbf{x}_{k+1} = \mathbf{x}_k - -\left(\frac{\partial^2 Q}{\partial\mathbf{x}_0^2}\right)^{-1} -\frac{\partial Q}{\partial\mathbf{x}_0}, -``` -and the covariance matrix -```math -\mathbf{\Gamma} = \mathbf{C}^{-1}, -``` -where ``\mathbf{C} = \frac{m}{2}\frac{\partial^2 Q}{\partial\mathbf{x}_0^2}`` is the normal -matrix, ``Q = \frac{\chi^2}{m}`` is the mean square residual, ``m`` is the number of -observations and ``\mathbf{x}_0 = (x_1,\ldots,x_n)`` is the vector of initial conditions. - -See also [`chi2`](@ref). - -# Arguments - -- `res::Vector{TaylorN{T}/Vector{OpticalResidual{T, TaylorN{T}}}`: vector of residuals. -- `w::Vector{T}`: vector of weights. -- `x_0::Vector{T}`: first guess. -- `niters::Int`: number of iterations. - -!!! reference - See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. -""" -function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, - niters::Int = 5, idxs::AbstractVector{Int} = eachindex(x0)) where {T <: Real} - # Number of observations - nobs = length(res) - # Degrees of freedom - npar = length(x0) - # Mean square residual - Q = chi2(res, w)/nobs - # Vector of x - x = zeros(T, npar, niters + 1) - # First guess - x[:, 1] = x0 - # Vector of errors - error = Vector{T}(undef, niters + 1) - # Error of first guess - error[1] = T(Inf) - # Iteration - for i in 1:niters - # Current x - xi = x[:, i] - # Gradient of Q with respect to x - dQ = TaylorSeries.gradient(Q)(xi)[idxs] - # Hessian of Q with respect to x - d2Q = TaylorSeries.hessian(Q, xi)[idxs, idxs] - # Newton update rule - Δx = - inv(d2Q)*dQ - # New x - x[idxs, i+1] = xi[idxs] + Δx - # Normal matrix - C = d2Q/(2/nobs) # C = d2Q/(2/m) - # Error - error2 = ( (Δx') * (C*Δx) ) / npar - if error2 ≥ 0 - error[i+1] = sqrt(error2) - # The method do not converge - else - return LeastSquaresFit(false, x[:, i+1], inv(C), :newton) - end - end - # TO DO: study Gauss method solution dependence on jt order - # TO DO: try even varorder - # TO DO: study optimal number of iterations - - # Index with the lowest error - i = argmin(error) - # x with the lowest error - x_new = x[:, i] - # Normal matrix - C = TaylorSeries.hessian(Q, x_new)/(2/nobs) # C = d2Q/(2/m) - # Covariance matrix - Γ = inv(C[idxs, idxs]) - - if any(diag(Γ) .< 0) - return LeastSquaresFit(false, x_new, Γ, :newton) - else - return LeastSquaresFit(true, x_new, Γ, :newton) - end -end - -function newtonls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, - niters::Int = 5, idxs::AbstractVector{Int} = eachindex(x0)) where {T <: Real} - # Unfold residuals and weights - _res_, _w_ = unfold(res) - - return newtonls(_res_, _w_, x0, niters, idxs) -end - -# In-place Levenberg-Marquardt hessian -function lmhessian!(_d2Q_::AbstractMatrix{T}, d2Q::AbstractMatrix{T}, λ::T) where {T <: AbstractFloat} - k = 1 + λ - for j in axes(d2Q, 2) - for i in axes(d2Q, 1) - if i == j - _d2Q_[i, j] = k * d2Q[i, j] - else - _d2Q_[i, j] = d2Q[i, j] - end - end - end - return nothing -end - -@doc raw""" - levenbergmarquardt(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, - niters::Int = 500) where {T <: Real} - levenbergmarquardt(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, - niters::Int = 500) where {T <: Real} - -Levenberg-Marquardt method subroutine for least-squares fitting. Returns an `LeastSquaresFit` -with the best iteration of `niters` iterations. - -See also [`chi2`](@ref). - -# Arguments - -- `res::Vector{TaylorN{T}/Vector{OpticalResidual{T, TaylorN{T}}}`: vector of residuals. -- `w::Vector{T}`: vector of weights. -- `x_0::Vector{T}`: first guess. -- `niters::Int`: number of iterations. - -!!! reference - See section 15.5.2 of https://books.google.com.mx/books?id=1aAOdzK3FegC&lpg=PP1&pg=PP1#v=onepage&q&f=false. -""" -function levenbergmarquardt(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, - niters::Int = 500, idxs::AbstractVector{Int} = eachindex(x0), - λ::T = 0.001) where {T <: Real} - # Number of observations - nobs = length(res) - # Degrees of freedom - npar = length(x0) - # Normalized mean square residual - Q = chi2(res, w)/nobs - # Vector of Qs - Qs = fill(T(Inf), niters + 1) - # Gradient of Q with respect to x - dQ = TaylorSeries.gradient(Q) - # Pre-allocate memory - _dQ_ = zeros(T, npar) - _d2Q_ = zeros(T, npar, npar) - x = zeros(T, npar, niters + 1) - # First guess - x[:, 1] = x0 - # Iteration - for i in 1:niters - # Current x - xi = x[:, i] - # Current Q - Qs[i] = Q(xi) - # Convergence condition - i > 1 && abs(Qs[i] - Qs[i-1]) / Qs[i-1] < 0.001 && break - # Gradient of Q with respect to x - _dQ_ .= dQ(xi) - # Hessian of Q with respect to x - d2Q = TaylorSeries.hessian(Q, xi) - # Choose λ - for _ in 1:niters - # Modified Hessian - lmhessian!(_d2Q_, d2Q, λ) - # Levenberg-Marquardt step - Δx = - inv(_d2Q_[idxs, idxs]) * _dQ_[idxs] - # Update point - x[idxs, i+1] = xi[idxs] + Δx - # Choose λ - if 0 < Q(x[:, i+1]) < Qs[i] && isposdef(_d2Q_[idxs, idxs]) - λ /= 10 - x[idxs, i+1] = xi[idxs] + Δx - break - else - λ *= 10 - end - end - end - # Index with the lowest error - i = argmin(Qs) - # x with the lowest error - x_new = x[:, i] - # Hessian of Q with respect to x - d2Q = TaylorSeries.hessian(Q, x_new) - # Normal matrix - if isposdef(d2Q) - C = d2Q/(2/nobs) - else - lmhessian!(_d2Q_, d2Q, λ) - C = _d2Q_/(2/nobs) # C = d2Q/(2/m) - end - # Covariance matrix - Γ = inv(C[idxs, idxs]) - - if any(diag(Γ) .< 0) - return LeastSquaresFit(false, x_new, Γ, :lm) - else - return LeastSquaresFit(true, x_new, Γ, :lm) - end -end - -function levenbergmarquardt(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, - niters::Int = 500, idxs::AbstractVector{Int} = eachindex(x0), - λ::T = 0.001) where {T <: Real} - # Unfold residuals and weights - _res_, _w_ = unfold(res) - - return levenbergmarquardt(_res_, _w_, x0, niters, idxs, λ) -end - -@doc raw""" - tryls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, - niters::Int = 5) where {T <: Real} - -Return the best least squares fit between two routines: [`newtonls`](@ref) and -[`diffcorr`](@ref). - -# Arguments - -- `res::Vector{OpticalResidual{T, TaylorN{T}}}`: vector of residuals. -- `x_0::Vector{T}`: first guess. -- `niters::Int`: number of iterations. -""" -function tryls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, - niters::Int = 5, idxs::AbstractVector{Int} = eachindex(x0), - order::Vector{Symbol} = [:newton, :lm]) where {T <: Real} - # Allocate memory - fit = zero(LeastSquaresFit{T}) - # Least squares methods in order - for i in eachindex(order) - if order[i] == :newton - fit = newtonls(res, x0, niters, idxs) - elseif order[i] == :lm - fit = levenbergmarquardt(res, x0, niters, idxs) - elseif order[i] == :diffcorr - fit = diffcorr(res, x0, niters, idxs) - end - fit.success && break - end - - return fit -end - -# TO DO: update / deprecate the following three functions - -@doc raw""" - newtonls_Q(Q, nobs, x0, niters=5) - -Does the same as `newtonls`, but recives ``Q`` as an argument, instead of computing it. -Returns the `niters`-th iteration and the covariance matrix ``\Gamma``. - -See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. - -See also [`newtonls`](@ref). - -# Arguments - -- `Q`: Mean square residual. -- `nobs`: Number of observations. -- `x_0`: First guess for the initial conditions. -- `niters`: Number of iterations. -""" -function newtonls_Q(Q, nobs, x0, niters=5) - # Number of observations - npar = length(x0) - # First guess - x_new = x0 - # Iteration - for i in 1:niters - # Gradient of Q with respect to x_0 - dQ = TaylorSeries.gradient(Q)(x_new) - # Hessian of Q with respect to x_0 - d2Q = TaylorSeries.hessian(Q, x_new) - # Newton update rule - Δx = - inv(d2Q)*dQ - x_new = x_new + Δx - # Normal matrix - C = d2Q/(2/nobs) # C = d2Q/(2/m) - @show sqrt(((Δx')*(C*Δx))/npar) - end - # Normal matrix - C = TaylorSeries.hessian(Q, x_new)/(2/nobs) # C = d2Q/(2/m) - # Covariance matrix - Γ = inv(C) - - return x_new, Γ -end - -@doc raw""" - newtonls_6v(res, w, x0, niters=5) - -Specialized version of `newtonls` on 6 variables for parametrized orbit determination -with respect to ``A_2`` Yarkovsky non-gravitational coefficient. Returns the `niters`-th -iteration and the covariance matrix ``\Gamma``. - -See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. - -See also [`newtonls`](@ref). - -# Arguments - -- `res`: Vector of residuals. -- `w`: Vector of weights. -- `x_0`: First guess for the initial conditions. -- `niters`: Number of iterations. -""" -function newtonls_6v(res, w, x0, niters=5) - # Have as many residuals as weights - @assert length(res) == length(w) - # Number of observations - nobs = length(res) - # Degrees of freedom - npar = 6 # length(x0) - # Mean square residual - Q = chi2(res, w)/nobs - # First guess - x_new = x0 - # Iteration - for i in 1:niters - # Gradient of Q with respect to x_0 - dQ = TaylorSeries.gradient(Q)(x_new)[1:6] - # Hessian of Q with respect to x_0 - d2Q = TaylorSeries.hessian(Q, x_new)[1:6,1:6] - # Newton update rule - Δx = - inv(d2Q)*dQ - x_new[1:6] = x_new[1:6] + Δx - # Normal matrix - C = d2Q/(2/nobs) # C = d2Q/(2/m) - @show sqrt(((Δx')*(C*Δx))/npar) - end - # Normal matrix - C = TaylorSeries.hessian(Q, x_new)/(2/nobs) # C = d2Q/(2/m) - # Covariance matrix - Γ = inv(C[1:6,1:6]) - - return x_new, Γ -end - -@doc raw""" - newtonls_A2(res, w, x0, niters=5) - -Specialized version of `newtonls` with the Newton method only over the seventh degree of -freedom, i.e., with respect to ``A_2`` Yarkovsky non-gravitational coefficient. Returns the -`niters`-th iteration, the covariance matrix ``\Gamma`` and the normal matrix ``C``. - -See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. - -See also [`newtonls`](@ref). - -# Arguments - -- `res`: Vector of residuals. -- `w`: Vector of weights. -- `x_0`: First guess for the initial conditions. -- `niters`: Number of iterations. -""" -function newtonls_A2(res, w, x0, niters=5) - # Have as many residuals as weights - @assert length(res) == length(w) - # Number of observations - nobs = length(res) - # Degrees of freedom - npar = length(x0) - # Mean square residual - Q = chi2(res, w)/nobs - # First guess - x_new = x0 - # Iteration - for i in 1:niters - # Gradient of Q with respect to x_0 - dQ = TaylorSeries.gradient(Q)(x_new) - # Hessian of Q with respect to x_0 - d2Q = TaylorSeries.hessian(Q, x_new) - # Newton update rule - Δx = - inv(d2Q)*dQ - x_new[7] = x_new[7] + Δx[7] - # Normal matrix - C = d2Q/(2/nobs) # C = d2Q/(2/m) - @show sqrt(((Δx')*(C*Δx))/npar) - end - # Normal matrix - C = TaylorSeries.hessian(Q, x_new)/(2/nobs) # C = d2Q/(2/m) - # Covariance matrix - Γ = inv(C) - - return x_new, Γ, C -end +@doc raw""" + LeastSquaresFit{T <: Real} + +A least squares fit. + +# Fields +- `success::Bool`: whether the routine converged or not. +- `x::Vector{T}`: deltas that minimize the objective function. +- `Γ::Matrix{T}`: covariance matrix. +- `routine::Symbol`: minimization routine (`:newton` or `:diffcorr`). +""" +@auto_hash_equals struct LeastSquaresFit{T <: Real} + success::Bool + x::Vector{T} + Γ::Matrix{T} + routine::Symbol + # Inner constructor + function LeastSquaresFit{T}(success::Bool, x::Vector{T}, Γ::Matrix{T}, + routine::Symbol) where {T <: Real} + return new{T}(success, x, Γ, routine) + end +end +# Outer constructor +function LeastSquaresFit(success::Bool, x::Vector{T}, Γ::Matrix{T}, + routine::Symbol) where {T <: Real} + return LeastSquaresFit{T}(success, x, Γ, routine) +end + +# Definition of zero LeastSquaresFit{T} +function zero(::Type{LeastSquaresFit{T}}) where {T <: Real} + return LeastSquaresFit{T}(false, Vector{T}(undef, 0), Matrix{T}(undef, 0, 0), :zero) +end + +# Print method for LeastSquaresFit +# Examples: +# Succesful Newton +# Succesful differential corrections +function show(io::IO, fit::LeastSquaresFit{T}) where {T <: Real} + success_s = fit.success ? "Succesful" : "Unsuccesful" + if fit.routine == :newton + routine_s = "Newton" + elseif fit.routine == :diffcorr + routine_s = "Differential Corrections" + elseif fit.routine == :lm + routine_s = "Levenberg-Marquardt" + else + routine_s = "Least Squares" + end + print(io, success_s, " ", routine_s) +end + +@doc raw""" + carpino_smoothing(n::T) where {T <: Real} + +Fudge term for rejection condition in [`outlier_rejection`](@ref). + +!!! reference + See page 253 of https://doi.org/10.1016/S0019-1035(03)00051-4. +""" +carpino_smoothing(n::T) where {T <: Real} = 400*(1.2)^(-n) + +@doc raw""" + outlier_rejection(ξs::Vector{OpticalResidual{T, TaylorN{T}}}, fit::LeastSquaresFit{T}; + χ2_rec::T = 7.0, χ2_rej::T = 8.0, α::T = 0.25, max_per::T = 10.) where {T <: Real} + +Outlier rejection algorithm. + +# Arguments + +- `ξs::Vector{OpticalResidual{T}}`: vector of residuals. +- `fit::LeastSquaresFit{T}`: least squares fit. +- `χ2_rec::T`: recovery condition. +- `χ2_rej::T`: rejection condition. +- `α::T`: scaling factor for maximum chi. +- `max_per::T`: maximum allowed drop percentage. + +!!! reference + See https://doi.org/10.1016/S0019-1035(03)00051-4. +""" +function outlier_rejection(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::LeastSquaresFit{T}; + χ2_rec::T = 7., χ2_rej::T = 8., α::T = 0.25, max_per::T = 10.) where {T <: Real} + + # Number of residuals + L = length(res) + # Evaluate residuals + eval_res = res(fit.x) + # Vector of χ2 + χ2s = Vector{T}(undef, L) + # Maximum χ2 (over non outliers) + χ2_max = zero(T) + # Number of non outliers + N_sel = 0 + + # Compute χ2s + for i in eachindex(χ2s) + # Weights of current residual + w_α, w_δ = res[i].w_α / res[i].relax_factor, res[i].w_δ / res[i].relax_factor + # Current observation covariance matrix + γ = [w_α zero(T); zero(T) w_δ] + # Current model matrix + A = hcat(TS.gradient(res[i].ξ_α)(fit.x), TS.gradient(res[i].ξ_δ)(fit.x)) + # Outlier sign + outlier_sign = res[i].outlier*2-1 + # Current residual covariance matrix + γ_ξ = γ + outlier_sign*(A')*fit.Γ*A + # Current residual + ξ = [eval_res[i].ξ_α, eval_res[i].ξ_δ] + # Current chi2 + χ2s[i] = ξ' * inv(γ_ξ) * ξ + # Update N_sel + if !res[i].outlier + N_sel += 1 + # Update maximum χ2 + if χ2s[i] > χ2_max + χ2_max = χ2s[i] + end + end + end + + # Maximum allowed drops + max_drop = ceil(Int, max_per * L / 100) + # Number of dropped residuals + N_drop = 0 + # New outliers + new_outliers = outlier.(res) + # Sort χ2s + idxs = sortperm(χ2s, rev = true) + # Rejection threshold + χ2_rej = max(χ2_rej + carpino_smoothing(N_sel), α*χ2_max) + + for i in idxs + if χ2s[i] > χ2_rej && N_drop < max_drop + new_outliers[i] = true + N_drop += 1 + elseif χ2s[i] < χ2_rec + new_outliers[i] = false + end + end + + return OpticalResidual.(ra.(res), dec.(res), weight_ra.(res), weight_dec.(res), + relax_factor.(res), new_outliers) +end + +@doc raw""" + project(y::Vector{TaylorN{T}}, fit::LeastSquaresFit{T}) where {T <: Real} + +Project `fit`'s covariance matrix into `y`. +""" +function project(y::Vector{TaylorN{T}}, fit::LeastSquaresFit{T}) where {T <: Real} + J = Matrix{T}(undef, get_numvars(), length(y)) + for i in eachindex(y) + J[:, i] = TS.gradient(y[i])(fit.x) + end + return (J') * fit.Γ * J +end + +@doc raw""" + chi2(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} + chi2(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + +Returns the chi square +```math +\chi^2 = \sum_{i=1}^m \frac{ \xi_i^2}{\sigma_i^2}, +``` +where ``\mathbf{w} = (1/\sigma_1^2,\ldots,1/\sigma_m^2)^T`` and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` +are the vectors of weights and residuals respectively. + +# Arguments + +- `res::Vector{U}/Vector{OpticalResidual{T, U}}`: vector of residuals. +- `w::Vector{T}`: vector of weights. +""" +function chi2(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} + # Have as many residuals as weights + @assert length(res) == length(w) + # Chi square + return sum(w .* (res.^2)) +end +function chi2(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + _res_, _w_ = unfold(res) + return chi2(_res_, _w_) +end + +@doc raw""" + nms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} + nms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + nms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::LeastSquaresFit{T}) where {T <: Real} + +Return the normalized chi square. See [`chi2`](@ref). +""" +nms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} = chi2(res, w) / length(res) + +function nms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + _res_, _w_ = unfold(res) + return nms(_res_, _w_) +end + +function nms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::LeastSquaresFit{T}) where {T <: Real} + _res_, _w_ = unfold(res) + return nms(_res_(fit.x), _w_) +end + +@doc raw""" + nrms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} + nrms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + nrms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::LeastSquaresFit{T}) where {T <: Real} + +Returns the normalized root mean square error +```math +\texttt{NRMS} = \sqrt{\frac{\chi^2}{m}}, +``` +where ``\chi^2`` is the chi square and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` is the vector +of residuals. + +See also [`chi2`](@ref). + +# Arguments + +- `res::Vector{U}/Vector{OpticalResidual{T, U}}`: Vector of residuals. +- `w::Vector{T}`: Vector of weights. +- `fit::LeastSquaresFit{T}`: least squares fit. + +""" +function nrms(res::Vector{U}, w::Vector{T}) where {T <: Real, U <: Number} + # Have as many residuals as weights + @assert length(res) == length(w) + # Normalized root mean square error + return sqrt( chi2(res, w)/length(res) ) +end + +function nrms(res::Vector{OpticalResidual{T, U}}) where {T <: Real, U <: Number} + _res_, _w_ = unfold(res) + return nrms(_res_, _w_) +end + +function nrms(res::Vector{OpticalResidual{T, TaylorN{T}}}, fit::LeastSquaresFit{T}) where {T <: Real} + _res_, _w_ = unfold(res) + return nrms(_res_(fit.x), _w_) +end + +@doc raw""" + BHC(res::Vector{TaylorN{T}}, w::Vector{T}, npar::Int) where {T <: Real} + +Returns the ``\mathbf{B}``, ``\mathbf{H}`` and ``\mathbf{C}`` arrays +```math +\mathbf{B} = \frac{\partial\mathbf{\xi}}{\partial\mathbf{x}_0}(\mathbf{x}_0), \quad +\mathbf{H} = \frac{\partial^2\mathbf{\xi}}{\partial\mathbf{x}_0^2}(\mathbf{x}_0) \quad \text{and} \quad +\mathbf{C} = \mathbf{B}^T\mathbf{W}\mathbf{B}, +``` +where ``\mathbf{x}_0 = (x_1,\ldots,x_n)^T`` and ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` +are the vectors of initial conditions and residuals respectively; and +``\mathbf{W} = \text{diag}(1/\sigma_1^2,\ldots,1/\sigma_m^2)`` is the weights matrix. + +``\mathbf{B}`` is called the design matrix and is of size ``m\times n``, ``\mathbf{H}`` is a three index +array of size ``m\times n\times n`` and ``\mathbf{C}`` is called the normal matrix and is of size ``n\times n``. + +# Arguments + +- `res::Vector{TaylorN{T}}`: vector of residuals. +- `w::Vector{T}`: vector of weights. +- `npar::Int`: degrees of freedom ``n``. + +!!! reference + See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. +""" +function BHC(res::Vector{TaylorN{T}}, w::Vector{T}, npar::Int) where {T <: Real} + # Number of observations + nobs = length(res) + + # Allocate memory for the three arrays + B_mat = Matrix{TaylorN{T}}(undef, nobs, npar) + H_mat = Array{TaylorN{T}}(undef, nobs, npar, npar) + C_mat = Array{TaylorN{T}}(undef, npar, npar) + + # Design matrix B + for i in 1:nobs + # Gradient of the i-th residual with respect to the initial conditions x_0 + B_mat[i,:] .= TaylorSeries.gradient(res[i]) + end + # H matrix + for i in 1:nobs + for j in 1:npar + # Gradient of the (i, j)-th element of B with respect to to the initial + # conditions x_0 + H_mat[i,j,:] .= TaylorSeries.gradient(B_mat[i,j]) + end + end + # Normal matrix C + sqrtw_B = sqrt.(w) .* B_mat + C_mat .= (sqrtw_B') * sqrtw_B + + return B_mat, H_mat, C_mat +end + +@doc raw""" + ξTH(w, res, H_mat, npar) + +Returns ``\mathbf{\xi}^T\mathbf{W}\mathbf{H}``, where ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` +is the vector of residuals, ``\mathbf{W} = \text{diag}(1/\sigma_1^2,\ldots,1/\sigma_m^2)`` is +the weights matrix and ``\mathbf{H}`` is the matrix of second derivatives of ``\mathbf{\xi}`` +with respect to the initial conditions. + +See also [`BHC`](@ref). + +# Arguments + +- `w`: Vector of weights. +- `res`: Vector or residuals. +- `H_mat`: matrix of second derivatives of ``\mathbf{\xi}`` with respect to the initial conditions. +- `npar`: Degrees of freedom ``n``. +""" +function ξTH(w, res, H_mat, npar) + # Allocate memory for output + ξTHv = Array{Float64}(undef, npar, npar) + + for j in 1:npar + for i in 1:npar + # transpose(ξ) * W * H matrix + ξTHv[i,j] = (w .* res)' * (H_mat[:,i,j]) + end + end + + return ξTHv +end + +@doc raw""" + diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, + niters::Int = 5) where {T <: Real} + diffcorr(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, + niters::Int = 5) where {T <: Real} + +Differential corrections subroutine for least-squares fitting. Returns an +`LeastSquaresFit` with the `niters`-th +correction +```math +\mathbf{x}_{k+1} = \mathbf{x}_k - \mathbf{C}^{-1}\mathbf{D}, +``` +and the covariance matrix +```math +\mathbf{\Gamma} = \mathbf{C}^{-1}, +``` +where ``\mathbf{C} = \mathbf{B}^T\mathbf{W}\mathbf{B}`` is the normal matrix and +``\mathbf{D} = \mathbf{B}^T\mathbf{W}\mathbf{\xi}``, with ``\mathbf{\xi} = (\xi_1,\ldots,\xi_m)^T`` +the vector of residuals, ``\mathbf{B}`` the design matrix and ``\mathbf{W} = \text{diag}(1/\sigma_1^2,\ldots,1/\sigma_m^2)`` +the weights matrix. + +See also [`BHC`](@ref). + +# Arguments + +- `res::Vector{TaylorN{T}/Vector{OpticalResidual{T, TaylorN{T}}}`: vector of residuals. +- `w::Vector{T}`: vector of weights. +- `x_0::Vector{T}`: first guess. +- `niters::Int`: number of iterations. + +!!! reference + See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. +""" +function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, + niters::Int = 5) where {T <: Real} + # TO DO: Adapt diffcorr for idxs + # Degrees of freedom + npar = length(x0) + # Design matrix B, H array and normal matrix C + B_mat, H_mat, C_mat = BHC(res, w, npar) + # D matrix: transpose(B) * W * ξ + D_mat = B_mat' * (w .* res) + # ξTH_mat = ξTH(w, res, H_mat, npar) + # Vector of x + x = Matrix{T}(undef, npar, niters + 1) + # First guess + x[:, 1] = x0 + # Vector of errors + error = Vector{T}(undef, niters + 1) + # Error of first guess + error[1] = T(Inf) + # Iteration + for i in 1:niters + # Current x + xi = x[:, i] + # D matrix evaluated in xi + D = D_mat(xi) + # C matrix evaluated in xi + C = C_mat(xi) #.+ ξTH_mat(xi) + # Update rule + Δx = - inv(C)*D + # New x + x[:, i+1] = xi + Δx + # Error + error2 = ( (Δx') * (C*Δx) ) / npar + if error2 ≥ 0 + error[i+1] = sqrt(error2) + # The method do not converge + else + return LeastSquaresFit(false, x[:, i+1], inv(C), :diffcorr) + end + end + # Index with the lowest error + i = argmin(error) + # x with the lowest error + x_new = x[:, i] + # Normal C matrix evaluated in x_new + C = C_mat(x_new) + # Covariance matrix + Γ = inv(C) + + if any(diag(Γ) .< 0) + return LeastSquaresFit(false, x_new, Γ, :diffcorr) + else + return LeastSquaresFit(true, x_new, Γ, :diffcorr) + end +end + +function diffcorr(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, + niters::Int = 5) where {T <: Real} + # Unfold residuals and weights + _res_, _w_ = unfold(res) + + return diffcorr(_res_, _w_, x0, niters) +end + +@doc raw""" + newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, + niters::Int = 5) where {T <: Real} + newtonls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, + niters::Int = 5) where {T <: Real} + +Newton method subroutine for least-squares fitting. Returns an `LeastSquaresFit` +with the `niters`-th iteration +```math +\mathbf{x}_{k+1} = \mathbf{x}_k - +\left(\frac{\partial^2 Q}{\partial\mathbf{x}_0^2}\right)^{-1} +\frac{\partial Q}{\partial\mathbf{x}_0}, +``` +and the covariance matrix +```math +\mathbf{\Gamma} = \mathbf{C}^{-1}, +``` +where ``\mathbf{C} = \frac{m}{2}\frac{\partial^2 Q}{\partial\mathbf{x}_0^2}`` is the normal +matrix, ``Q = \frac{\chi^2}{m}`` is the mean square residual, ``m`` is the number of +observations and ``\mathbf{x}_0 = (x_1,\ldots,x_n)`` is the vector of initial conditions. + +See also [`chi2`](@ref). + +# Arguments + +- `res::Vector{TaylorN{T}/Vector{OpticalResidual{T, TaylorN{T}}}`: vector of residuals. +- `w::Vector{T}`: vector of weights. +- `x_0::Vector{T}`: first guess. +- `niters::Int`: number of iterations. + +!!! reference + See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. +""" +function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, + niters::Int = 5, idxs::AbstractVector{Int} = eachindex(x0)) where {T <: Real} + # Number of observations + nobs = length(res) + # Degrees of freedom + npar = length(x0) + # Mean square residual + Q = chi2(res, w)/nobs + # Vector of x + x = zeros(T, npar, niters + 1) + # First guess + x[:, 1] = x0 + # Vector of errors + error = Vector{T}(undef, niters + 1) + # Error of first guess + error[1] = T(Inf) + # Iteration + for i in 1:niters + # Current x + xi = x[:, i] + # Gradient of Q with respect to x + dQ = TaylorSeries.gradient(Q)(xi)[idxs] + # Hessian of Q with respect to x + d2Q = TaylorSeries.hessian(Q, xi)[idxs, idxs] + # Newton update rule + Δx = - inv(d2Q)*dQ + # New x + x[idxs, i+1] = xi[idxs] + Δx + # Normal matrix + C = d2Q/(2/nobs) # C = d2Q/(2/m) + # Error + error2 = ( (Δx') * (C*Δx) ) / npar + if error2 ≥ 0 + error[i+1] = sqrt(error2) + # The method do not converge + else + return LeastSquaresFit(false, x[:, i+1], inv(C), :newton) + end + end + # TO DO: study Gauss method solution dependence on jt order + # TO DO: try even varorder + # TO DO: study optimal number of iterations + + # Index with the lowest error + i = argmin(error) + # x with the lowest error + x_new = x[:, i] + # Normal matrix + C = TaylorSeries.hessian(Q, x_new)/(2/nobs) # C = d2Q/(2/m) + # Covariance matrix + Γ = inv(C[idxs, idxs]) + + if any(diag(Γ) .< 0) + return LeastSquaresFit(false, x_new, Γ, :newton) + else + return LeastSquaresFit(true, x_new, Γ, :newton) + end +end + +function newtonls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, + niters::Int = 5, idxs::AbstractVector{Int} = eachindex(x0)) where {T <: Real} + # Unfold residuals and weights + _res_, _w_ = unfold(res) + + return newtonls(_res_, _w_, x0, niters, idxs) +end + +# In-place Levenberg-Marquardt hessian +function lmhessian!(_d2Q_::AbstractMatrix{T}, d2Q::AbstractMatrix{T}, λ::T) where {T <: AbstractFloat} + k = 1 + λ + for j in axes(d2Q, 2) + for i in axes(d2Q, 1) + if i == j + _d2Q_[i, j] = k * d2Q[i, j] + else + _d2Q_[i, j] = d2Q[i, j] + end + end + end + return nothing +end + +@doc raw""" + levenbergmarquardt(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, + niters::Int = 500) where {T <: Real} + levenbergmarquardt(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, + niters::Int = 500) where {T <: Real} + +Levenberg-Marquardt method subroutine for least-squares fitting. Returns an `LeastSquaresFit` +with the best iteration of `niters` iterations. + +See also [`chi2`](@ref). + +# Arguments + +- `res::Vector{TaylorN{T}/Vector{OpticalResidual{T, TaylorN{T}}}`: vector of residuals. +- `w::Vector{T}`: vector of weights. +- `x_0::Vector{T}`: first guess. +- `niters::Int`: number of iterations. + +!!! reference + See section 15.5.2 of https://books.google.com.mx/books?id=1aAOdzK3FegC&lpg=PP1&pg=PP1#v=onepage&q&f=false. +""" +function levenbergmarquardt(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, + niters::Int = 500, idxs::AbstractVector{Int} = eachindex(x0), + λ::T = 0.001) where {T <: Real} + # Number of observations + nobs = length(res) + # Degrees of freedom + npar = length(x0) + # Normalized mean square residual + Q = chi2(res, w)/nobs + # Vector of Qs + Qs = fill(T(Inf), niters + 1) + # Gradient of Q with respect to x + dQ = TaylorSeries.gradient(Q) + # Pre-allocate memory + _dQ_ = zeros(T, npar) + _d2Q_ = zeros(T, npar, npar) + x = zeros(T, npar, niters + 1) + # First guess + x[:, 1] = x0 + # Iteration + for i in 1:niters + # Current x + xi = x[:, i] + # Current Q + Qs[i] = Q(xi) + # Convergence condition + i > 1 && abs(Qs[i] - Qs[i-1]) / Qs[i-1] < 0.001 && break + # Gradient of Q with respect to x + _dQ_ .= dQ(xi) + # Hessian of Q with respect to x + d2Q = TaylorSeries.hessian(Q, xi) + # Choose λ + for _ in 1:niters + # Modified Hessian + lmhessian!(_d2Q_, d2Q, λ) + # Levenberg-Marquardt step + Δx = - inv(_d2Q_[idxs, idxs]) * _dQ_[idxs] + # Update point + x[idxs, i+1] = xi[idxs] + Δx + # Choose λ + if 0 < Q(x[:, i+1]) < Qs[i] && isposdef(_d2Q_[idxs, idxs]) + λ /= 10 + x[idxs, i+1] = xi[idxs] + Δx + break + else + λ *= 10 + end + end + end + # Index with the lowest error + i = argmin(Qs) + # x with the lowest error + x_new = x[:, i] + # Hessian of Q with respect to x + d2Q = TaylorSeries.hessian(Q, x_new) + # Normal matrix + if isposdef(d2Q) + C = d2Q/(2/nobs) + else + lmhessian!(_d2Q_, d2Q, λ) + C = _d2Q_/(2/nobs) # C = d2Q/(2/m) + end + # Covariance matrix + Γ = inv(C[idxs, idxs]) + + if any(diag(Γ) .< 0) + return LeastSquaresFit(false, x_new, Γ, :lm) + else + return LeastSquaresFit(true, x_new, Γ, :lm) + end +end + +function levenbergmarquardt(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, + niters::Int = 500, idxs::AbstractVector{Int} = eachindex(x0), + λ::T = 0.001) where {T <: Real} + # Unfold residuals and weights + _res_, _w_ = unfold(res) + + return levenbergmarquardt(_res_, _w_, x0, niters, idxs, λ) +end + +@doc raw""" + tryls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, + niters::Int = 5) where {T <: Real} + +Return the best least squares fit between two routines: [`newtonls`](@ref) and +[`diffcorr`](@ref). + +# Arguments + +- `res::Vector{OpticalResidual{T, TaylorN{T}}}`: vector of residuals. +- `x_0::Vector{T}`: first guess. +- `niters::Int`: number of iterations. +""" +function tryls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, + niters::Int = 5, idxs::AbstractVector{Int} = eachindex(x0), + order::Vector{Symbol} = [:newton, :lm]) where {T <: Real} + # Allocate memory + fit = zero(LeastSquaresFit{T}) + # Least squares methods in order + for i in eachindex(order) + if order[i] == :newton + fit = newtonls(res, x0, niters, idxs) + elseif order[i] == :lm + fit = levenbergmarquardt(res, x0, niters, idxs) + elseif order[i] == :diffcorr + fit = diffcorr(res, x0, niters, idxs) + end + fit.success && break + end + + return fit +end + +# TO DO: update / deprecate the following three functions + +@doc raw""" + newtonls_Q(Q, nobs, x0, niters=5) + +Does the same as `newtonls`, but recives ``Q`` as an argument, instead of computing it. +Returns the `niters`-th iteration and the covariance matrix ``\Gamma``. + +See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. + +See also [`newtonls`](@ref). + +# Arguments + +- `Q`: Mean square residual. +- `nobs`: Number of observations. +- `x_0`: First guess for the initial conditions. +- `niters`: Number of iterations. +""" +function newtonls_Q(Q, nobs, x0, niters=5) + # Number of observations + npar = length(x0) + # First guess + x_new = x0 + # Iteration + for i in 1:niters + # Gradient of Q with respect to x_0 + dQ = TaylorSeries.gradient(Q)(x_new) + # Hessian of Q with respect to x_0 + d2Q = TaylorSeries.hessian(Q, x_new) + # Newton update rule + Δx = - inv(d2Q)*dQ + x_new = x_new + Δx + # Normal matrix + C = d2Q/(2/nobs) # C = d2Q/(2/m) + @show sqrt(((Δx')*(C*Δx))/npar) + end + # Normal matrix + C = TaylorSeries.hessian(Q, x_new)/(2/nobs) # C = d2Q/(2/m) + # Covariance matrix + Γ = inv(C) + + return x_new, Γ +end + +@doc raw""" + newtonls_6v(res, w, x0, niters=5) + +Specialized version of `newtonls` on 6 variables for parametrized orbit determination +with respect to ``A_2`` Yarkovsky non-gravitational coefficient. Returns the `niters`-th +iteration and the covariance matrix ``\Gamma``. + +See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. + +See also [`newtonls`](@ref). + +# Arguments + +- `res`: Vector of residuals. +- `w`: Vector of weights. +- `x_0`: First guess for the initial conditions. +- `niters`: Number of iterations. +""" +function newtonls_6v(res, w, x0, niters=5) + # Have as many residuals as weights + @assert length(res) == length(w) + # Number of observations + nobs = length(res) + # Degrees of freedom + npar = 6 # length(x0) + # Mean square residual + Q = chi2(res, w)/nobs + # First guess + x_new = x0 + # Iteration + for i in 1:niters + # Gradient of Q with respect to x_0 + dQ = TaylorSeries.gradient(Q)(x_new)[1:6] + # Hessian of Q with respect to x_0 + d2Q = TaylorSeries.hessian(Q, x_new)[1:6,1:6] + # Newton update rule + Δx = - inv(d2Q)*dQ + x_new[1:6] = x_new[1:6] + Δx + # Normal matrix + C = d2Q/(2/nobs) # C = d2Q/(2/m) + @show sqrt(((Δx')*(C*Δx))/npar) + end + # Normal matrix + C = TaylorSeries.hessian(Q, x_new)/(2/nobs) # C = d2Q/(2/m) + # Covariance matrix + Γ = inv(C[1:6,1:6]) + + return x_new, Γ +end + +@doc raw""" + newtonls_A2(res, w, x0, niters=5) + +Specialized version of `newtonls` with the Newton method only over the seventh degree of +freedom, i.e., with respect to ``A_2`` Yarkovsky non-gravitational coefficient. Returns the +`niters`-th iteration, the covariance matrix ``\Gamma`` and the normal matrix ``C``. + +See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. + +See also [`newtonls`](@ref). + +# Arguments + +- `res`: Vector of residuals. +- `w`: Vector of weights. +- `x_0`: First guess for the initial conditions. +- `niters`: Number of iterations. +""" +function newtonls_A2(res, w, x0, niters=5) + # Have as many residuals as weights + @assert length(res) == length(w) + # Number of observations + nobs = length(res) + # Degrees of freedom + npar = length(x0) + # Mean square residual + Q = chi2(res, w)/nobs + # First guess + x_new = x0 + # Iteration + for i in 1:niters + # Gradient of Q with respect to x_0 + dQ = TaylorSeries.gradient(Q)(x_new) + # Hessian of Q with respect to x_0 + d2Q = TaylorSeries.hessian(Q, x_new) + # Newton update rule + Δx = - inv(d2Q)*dQ + x_new[7] = x_new[7] + Δx[7] + # Normal matrix + C = d2Q/(2/nobs) # C = d2Q/(2/m) + @show sqrt(((Δx')*(C*Δx))/npar) + end + # Normal matrix + C = TaylorSeries.hessian(Q, x_new)/(2/nobs) # C = d2Q/(2/m) + # Covariance matrix + Γ = inv(C) + + return x_new, Γ, C +end diff --git a/src/orbit_determination/neosolution.jl b/src/orbit_determination/neosolution.jl old mode 100755 new mode 100644 index 80498ccc..f6b7cf2a --- a/src/orbit_determination/neosolution.jl +++ b/src/orbit_determination/neosolution.jl @@ -1,172 +1,172 @@ -@doc raw""" - NEOSolution{T <: Real, U <: Number} - -The outcome of the orbit determination process for a NEO. - -# Fields - -- `tracklets::Vector{Tracklet{T}}`: vector of tracklets. -- `bwd/fwd::TaylorInterpolant{T, U, 2, Vector{T}, Matrix{Taylor1{U}}}`: backward (forward) integration. -- `t_bwd/t_fwd::Vector{U}`: time of Earth close approach. -- `x_bwd/x_fwd::Vector{U}`: state vector at Earth close approach. -- `g_bwd/g_fwd::Vector{U}`: geocentric distance at close approach. -- `res::Vector{OpticalResidual{T, U}}`: vector of optical residuals. -- `fit::LeastSquaresFit{T}`: least squares fit. -- `scalings::Vector{T}`: jet transport scaling factors. -""" -@auto_hash_equals struct NEOSolution{T <: Real, U <: Number} - tracklets::Vector{Tracklet{T}} - bwd::TaylorInterpolant{T, U, 2, Vector{T}, Matrix{Taylor1{U}}} - t_bwd::Vector{U} - x_bwd::Matrix{U} - g_bwd::Vector{U} - fwd::TaylorInterpolant{T, U, 2, Vector{T}, Matrix{Taylor1{U}}} - t_fwd::Vector{U} - x_fwd::Matrix{U} - g_fwd::Vector{U} - res::Vector{OpticalResidual{T, U}} - fit::LeastSquaresFit{T} - scalings::Vector{T} - # Inner constructor - function NEOSolution{T, U}( - tracklets::Vector{Tracklet{T}}, - bwd::TaylorInterpolant{T, U, 2, VT, X}, t_bwd::Vector{U}, x_bwd::Matrix{U}, g_bwd::Vector{U}, - fwd::TaylorInterpolant{T, U, 2, VT, X}, t_fwd::Vector{U}, x_fwd::Matrix{U}, g_fwd::Vector{U}, - res::Vector{OpticalResidual{T, U}}, fit::LeastSquaresFit{T}, scalings::Vector{T} - ) where {T <: Real, U <: Number, VT <: AbstractVector{T}, X <: AbstractMatrix{Taylor1{U}}} - @assert bwd.t0 == fwd.t0 "Backward and forward propagation initial times must match" - _bwd_ = TaylorInterpolant(bwd.t0, bwd.t, collect(bwd.x)) - _fwd_ = TaylorInterpolant(fwd.t0, fwd.t, collect(fwd.x)) - new{T, U}( - tracklets, - _bwd_, t_bwd, x_bwd, g_bwd, - _fwd_, t_fwd, x_fwd, g_fwd, - res, fit, scalings - ) - end -end -# Outer constructors -function NEOSolution( - tracklets::Vector{Tracklet{T}}, - bwd::TaylorInterpolant{T, U, 2, VT, X}, t_bwd::Vector{U}, x_bwd::Matrix{U}, g_bwd::Vector{U}, - fwd::TaylorInterpolant{T, U, 2, VT, X}, t_fwd::Vector{U}, x_fwd::Matrix{U}, g_fwd::Vector{U}, - res::Vector{OpticalResidual{T, U}}, fit::LeastSquaresFit{T}, scalings::Vector{T} -) where {T <: Real, U <: Number, VT <: AbstractVector{T}, X <: AbstractMatrix{Taylor1{U}}} - NEOSolution{T, U}( - tracklets, - bwd, t_bwd, x_bwd, g_bwd, - fwd, t_fwd, x_fwd, g_fwd, - res, fit, scalings - ) -end - -function NEOSolution( - tracklets::Vector{Tracklet{T}}, - bwd::TaylorInterpolant{T, U, 2, VT, X}, fwd::TaylorInterpolant{T, U, 2, VT, X}, - res::Vector{OpticalResidual{T, U}}, fit::LeastSquaresFit{T}, scalings::Vector{T} -) where {T <: Real, U <: Number, VT <: AbstractVector{T}, X <: AbstractMatrix{Taylor1{U}}} - # Backward roots - t_bwd = Vector{U}(undef, 0) - x_bwd = Matrix{U}(undef, 0, 0) - g_bwd = Vector{U}(undef, 0) - # Forward roots - t_fwd = Vector{U}(undef, 0) - x_fwd = Matrix{U}(undef, 0, 0) - g_fwd = Vector{U}(undef, 0) - - NEOSolution{T, U}( - tracklets, - bwd, t_bwd, x_bwd, g_bwd, - fwd, t_fwd, x_fwd, g_fwd, - res, fit, scalings - ) -end - -# Print method for NEOSolution -# Examples: -# NEO solution with 123 residuals -function show(io::IO, x::NEOSolution{T, U}) where {T <: Real, U <: Number} - print(io, "NEO solution with ", length(x.res), " residuals") -end - -# Evaluation in time method -function (sol::NEOSolution{T, U})(t::V = sol.bwd.t0) where {T <: Real, U <: Number, V <: Number} - if t <= sol.bwd.t0 - return sol.bwd(t) - else - return sol.fwd(t) - end -end - -# Evaluation in fit δs method -function evalfit(sol::NEOSolution{T, TaylorN{T}}) where {T <: Real} - # Fit δs - δs = sol.fit.x - # Evaluate backward integration - new_bwd_x = map(x -> Taylor1(x.coeffs(δs)), sol.bwd.x); - new_bwd = TaylorInterpolant(sol.bwd.t0, sol.bwd.t, new_bwd_x) - # Evaluate backward roots - new_t_bwd = sol.t_bwd(δs) - new_x_bwd = sol.x_bwd(δs) - new_g_bwd = sol.g_bwd(δs) - # Evaluate forward integration - new_fwd_x = map(x -> Taylor1(x.coeffs(δs)), sol.fwd.x); - new_fwd = TaylorInterpolant(sol.fwd.t0, sol.fwd.t, new_fwd_x) - # Evaluate forward roots - new_t_fwd = sol.t_fwd(δs) - new_x_fwd = sol.x_fwd(δs) - new_g_fwd = sol.g_fwd(δs) - # Evaluate residuals - new_res = sol.res(δs) - - NEOSolution{T, T}( - sol.tracklets, - new_bwd, new_t_bwd, new_x_bwd, new_g_bwd, - new_fwd, new_t_fwd, new_x_fwd, new_g_fwd, - new_res, sol.fit, sol.scalings - ) -end - -# Definition of zero NEOSolution -function zero(::Type{NEOSolution{T, U}}) where {T <: Real, U <: Number} - tracklets = Vector{Tracklet{T}}(undef, 0) - bwd = zero(TaylorInterpolant{T, U, 2, Vector{T}, Matrix{Taylor1{U}}}) - t_bwd = Vector{U}(undef, 0) - x_bwd = Matrix{U}(undef, 0, 0) - g_bwd = Vector{U}(undef, 0) - fwd = zero(TaylorInterpolant{T, U, 2, Vector{T}, Matrix{Taylor1{U}}}) - t_fwd = Vector{U}(undef, 0) - x_fwd = Matrix{U}(undef, 0, 0) - g_fwd = Vector{U}(undef, 0) - res = Vector{OpticalResidual{T, U}}(undef, 0) - fit = LeastSquaresFit{T}(false, Vector{T}(undef, 0), Matrix{T}(undef, 0, 0), :newton) - scalings = Vector{T}(undef, 0) - - NEOSolution{T, U}( - tracklets, - bwd, t_bwd, x_bwd, g_bwd, - fwd, t_fwd, x_fwd, g_fwd, - res, fit, scalings - ) -end - -iszero(x::NEOSolution{T, U}) where {T <: Real, U <: Number} = x == zero(NEOSolution{T, U}) - -# Normalized Root Mean Square Error -function nrms(sol::NEOSolution{T, T}) where {T <: Real} - if iszero(sol) - return T(Inf) - else - return nrms(sol.res) - end -end -# Normalized Mean Square Error -function nms(sol::NEOSolution{T, T}) where {T <: Real} - if iszero(sol) - return T(Inf) - else - return nms(sol.res) - end -end - +@doc raw""" + NEOSolution{T <: Real, U <: Number} + +The outcome of the orbit determination process for a NEO. + +# Fields + +- `tracklets::Vector{Tracklet{T}}`: vector of tracklets. +- `bwd/fwd::TaylorInterpolant{T, U, 2, Vector{T}, Matrix{Taylor1{U}}}`: backward (forward) integration. +- `t_bwd/t_fwd::Vector{U}`: time of Earth close approach. +- `x_bwd/x_fwd::Vector{U}`: state vector at Earth close approach. +- `g_bwd/g_fwd::Vector{U}`: geocentric distance at close approach. +- `res::Vector{OpticalResidual{T, U}}`: vector of optical residuals. +- `fit::LeastSquaresFit{T}`: least squares fit. +- `scalings::Vector{T}`: jet transport scaling factors. +""" +@auto_hash_equals struct NEOSolution{T <: Real, U <: Number} + tracklets::Vector{Tracklet{T}} + bwd::TaylorInterpolant{T, U, 2, Vector{T}, Matrix{Taylor1{U}}} + t_bwd::Vector{U} + x_bwd::Matrix{U} + g_bwd::Vector{U} + fwd::TaylorInterpolant{T, U, 2, Vector{T}, Matrix{Taylor1{U}}} + t_fwd::Vector{U} + x_fwd::Matrix{U} + g_fwd::Vector{U} + res::Vector{OpticalResidual{T, U}} + fit::LeastSquaresFit{T} + scalings::Vector{T} + # Inner constructor + function NEOSolution{T, U}( + tracklets::Vector{Tracklet{T}}, + bwd::TaylorInterpolant{T, U, 2, VT, X}, t_bwd::Vector{U}, x_bwd::Matrix{U}, g_bwd::Vector{U}, + fwd::TaylorInterpolant{T, U, 2, VT, X}, t_fwd::Vector{U}, x_fwd::Matrix{U}, g_fwd::Vector{U}, + res::Vector{OpticalResidual{T, U}}, fit::LeastSquaresFit{T}, scalings::Vector{T} + ) where {T <: Real, U <: Number, VT <: AbstractVector{T}, X <: AbstractMatrix{Taylor1{U}}} + @assert bwd.t0 == fwd.t0 "Backward and forward propagation initial times must match" + _bwd_ = TaylorInterpolant(bwd.t0, bwd.t, collect(bwd.x)) + _fwd_ = TaylorInterpolant(fwd.t0, fwd.t, collect(fwd.x)) + new{T, U}( + tracklets, + _bwd_, t_bwd, x_bwd, g_bwd, + _fwd_, t_fwd, x_fwd, g_fwd, + res, fit, scalings + ) + end +end +# Outer constructors +function NEOSolution( + tracklets::Vector{Tracklet{T}}, + bwd::TaylorInterpolant{T, U, 2, VT, X}, t_bwd::Vector{U}, x_bwd::Matrix{U}, g_bwd::Vector{U}, + fwd::TaylorInterpolant{T, U, 2, VT, X}, t_fwd::Vector{U}, x_fwd::Matrix{U}, g_fwd::Vector{U}, + res::Vector{OpticalResidual{T, U}}, fit::LeastSquaresFit{T}, scalings::Vector{T} +) where {T <: Real, U <: Number, VT <: AbstractVector{T}, X <: AbstractMatrix{Taylor1{U}}} + NEOSolution{T, U}( + tracklets, + bwd, t_bwd, x_bwd, g_bwd, + fwd, t_fwd, x_fwd, g_fwd, + res, fit, scalings + ) +end + +function NEOSolution( + tracklets::Vector{Tracklet{T}}, + bwd::TaylorInterpolant{T, U, 2, VT, X}, fwd::TaylorInterpolant{T, U, 2, VT, X}, + res::Vector{OpticalResidual{T, U}}, fit::LeastSquaresFit{T}, scalings::Vector{T} +) where {T <: Real, U <: Number, VT <: AbstractVector{T}, X <: AbstractMatrix{Taylor1{U}}} + # Backward roots + t_bwd = Vector{U}(undef, 0) + x_bwd = Matrix{U}(undef, 0, 0) + g_bwd = Vector{U}(undef, 0) + # Forward roots + t_fwd = Vector{U}(undef, 0) + x_fwd = Matrix{U}(undef, 0, 0) + g_fwd = Vector{U}(undef, 0) + + NEOSolution{T, U}( + tracklets, + bwd, t_bwd, x_bwd, g_bwd, + fwd, t_fwd, x_fwd, g_fwd, + res, fit, scalings + ) +end + +# Print method for NEOSolution +# Examples: +# NEO solution with 123 residuals +function show(io::IO, x::NEOSolution{T, U}) where {T <: Real, U <: Number} + print(io, "NEO solution with ", length(x.res), " residuals") +end + +# Evaluation in time method +function (sol::NEOSolution{T, U})(t::V = sol.bwd.t0) where {T <: Real, U <: Number, V <: Number} + if t <= sol.bwd.t0 + return sol.bwd(t) + else + return sol.fwd(t) + end +end + +# Evaluation in fit δs method +function evalfit(sol::NEOSolution{T, TaylorN{T}}) where {T <: Real} + # Fit δs + δs = sol.fit.x + # Evaluate backward integration + new_bwd_x = map(x -> Taylor1(x.coeffs(δs)), sol.bwd.x); + new_bwd = TaylorInterpolant(sol.bwd.t0, sol.bwd.t, new_bwd_x) + # Evaluate backward roots + new_t_bwd = sol.t_bwd(δs) + new_x_bwd = sol.x_bwd(δs) + new_g_bwd = sol.g_bwd(δs) + # Evaluate forward integration + new_fwd_x = map(x -> Taylor1(x.coeffs(δs)), sol.fwd.x); + new_fwd = TaylorInterpolant(sol.fwd.t0, sol.fwd.t, new_fwd_x) + # Evaluate forward roots + new_t_fwd = sol.t_fwd(δs) + new_x_fwd = sol.x_fwd(δs) + new_g_fwd = sol.g_fwd(δs) + # Evaluate residuals + new_res = sol.res(δs) + + NEOSolution{T, T}( + sol.tracklets, + new_bwd, new_t_bwd, new_x_bwd, new_g_bwd, + new_fwd, new_t_fwd, new_x_fwd, new_g_fwd, + new_res, sol.fit, sol.scalings + ) +end + +# Definition of zero NEOSolution +function zero(::Type{NEOSolution{T, U}}) where {T <: Real, U <: Number} + tracklets = Vector{Tracklet{T}}(undef, 0) + bwd = zero(TaylorInterpolant{T, U, 2, Vector{T}, Matrix{Taylor1{U}}}) + t_bwd = Vector{U}(undef, 0) + x_bwd = Matrix{U}(undef, 0, 0) + g_bwd = Vector{U}(undef, 0) + fwd = zero(TaylorInterpolant{T, U, 2, Vector{T}, Matrix{Taylor1{U}}}) + t_fwd = Vector{U}(undef, 0) + x_fwd = Matrix{U}(undef, 0, 0) + g_fwd = Vector{U}(undef, 0) + res = Vector{OpticalResidual{T, U}}(undef, 0) + fit = LeastSquaresFit{T}(false, Vector{T}(undef, 0), Matrix{T}(undef, 0, 0), :newton) + scalings = Vector{T}(undef, 0) + + NEOSolution{T, U}( + tracklets, + bwd, t_bwd, x_bwd, g_bwd, + fwd, t_fwd, x_fwd, g_fwd, + res, fit, scalings + ) +end + +iszero(x::NEOSolution{T, U}) where {T <: Real, U <: Number} = x == zero(NEOSolution{T, U}) + +# Normalized Root Mean Square Error +function nrms(sol::NEOSolution{T, T}) where {T <: Real} + if iszero(sol) + return T(Inf) + else + return nrms(sol.res) + end +end +# Normalized Mean Square Error +function nms(sol::NEOSolution{T, T}) where {T <: Real} + if iszero(sol) + return T(Inf) + else + return nms(sol.res) + end +end + sigmas(sol::NEOSolution{T, T}) where {T <: Real} = sqrt.(diag(sol.fit.Γ)) .* sol.scalings \ No newline at end of file diff --git a/src/orbit_determination/osculating.jl b/src/orbit_determination/osculating.jl old mode 100755 new mode 100644 index 683988bd..cf290738 --- a/src/orbit_determination/osculating.jl +++ b/src/orbit_determination/osculating.jl @@ -1,186 +1,186 @@ -@doc raw""" - OsculatingElements{T <: Number} - -Osculating orbital elements of a NEO. - -# Fields - -- `e::T`: eccentricity. -- `q::T`: perihelion distance [au]. -- `tp::T`: time of pericenter passage [jd]. -- `M::T`: mean anomaly [deg]. -- `Ω::T`: longitude of ascending node [deg]. -- `ω::T`: argument of pericentre [deg]. -- `i::T`: inclination [deg]. -- `a::T`: semimajor axis [au]. -""" -@auto_hash_equals struct OsculatingElements{T <: Number} - e::T - q::T - tp::T - Ω::T - ω::T - i::T - M::T - a::T - # Inner constructor - function OsculatingElements{T}(e::T, q::T, tp::T, Ω::T, ω::T, i::T, M::T, a::T) where {T <: Number} - return new{T}(e, q, tp, Ω, ω, i, M, a) - end -end - -# Outer constructors -function OsculatingElements(e::T, q::T, tp::T, Ω::T, ω::T, i::T, M::T, a::T) where {T <: Number} - return OsculatingElements{T}(e, q, tp, Ω, ω, i, M, a) -end - -function OsculatingElements() - return OsculatingElements(NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN) -end - -# A OsculatingElements is NaN if all its fields are NaN -function isnan(osc::OsculatingElements{T}) where {T <: Number} - return isnan(osc.e) && isnan(osc.q) && isnan(osc.tp) && isnan(osc.Ω) && isnan(osc.ω) && - isnan(osc.i) && isnan(osc.M) && isnan(osc.a) -end - -# Print method for OsculatingElements -# Example: -# Eccentricity (e): 0.4231715487782969 -# Pericenter distance (q): 0.5028397744678126 au -# Time of pericenter passage (tp): 2021-03-19T03:45:01.293 JDTDB -# Longitude of Ascending Node (Ω): 17.855086873010706 deg -# Argument of pericenter (ω): 194.74654283451 deg -# Inclination (i): 34.81327005431841 deg -# Mean anomaly (M): 118.87965684315387 deg -# Semimajor axis (a): 0.8717319220347314 au -function show(io::IO, m::OsculatingElements{T}) where {T <: Number} - - print(io, rpad("Eccentricity (e): ", 36), @sprintf("%.5f", cte(m.e)), "\n") - print(io, rpad("Pericenter distance (q): ", 36), @sprintf("%.5f", cte(m.q)), " au\n") - if isnan(m.tp) - print(io, rpad("Time of pericenter passage (tp): ", 36), "NaN JDTDB\n") - else - print(io, rpad("Time of pericenter passage (tp): ", 36), julian2datetime(cte(m.tp)), " JDTDB\n") - end - print(io, rpad("Longitude of Ascending Node (Ω): ", 36), @sprintf("%.5f", cte(m.Ω)), " deg\n") - print(io, rpad("Argument of pericenter (ω): ", 36), @sprintf("%.5f", cte(m.ω)), " deg\n") - print(io, rpad("Inclination (i): ", 36), @sprintf("%.5f", cte(m.i)), " deg\n") - print(io, rpad("Mean anomaly (M): ", 36), @sprintf("%.5f", cte(m.M)), " deg\n") - print(io, rpad("Semimajor axis (a): ", 36), @sprintf("%.5f", cte(m.a)), " au\n") - -end - -@doc raw""" - equatorial2ecliptic(xas::Vector{T}) where {T <: Number} - -Rotate state vector `xas` from equatorial plane to the ecliptic. -""" -function equatorial2ecliptic(xas::Vector{T}) where {T <: Number} - # Rotation matrix (only positions) - m_eq2ecl = Rx(deg2rad(ϵ0_deg)) - # Rotational matrix (positions + velocities) - m_xv_eq2ecl = hcat(vcat(m_eq2ecl, zeros(3,3)), vcat(zeros(3,3), m_eq2ecl)) - # Rotated state vector - return m_xv_eq2ecl*xas -end - -@doc raw""" - pv2kep(xas::Vector{U}; μ::T = μ_S, jd::T = JD_J2000, - frame::Symbol = :equatorial) where {T <: Real, U <: Number} - -Compute the orbital elements of the NEO with state vector `xas`. -Return an `OsculatingElements` object. - -See also [`equatorial2ecliptic`](@ref), [`eccentricity`](@ref), [`semimajoraxis`](@ref), -[`timeperipass`](@ref), [`longascnode`](@ref), [`argperi`](@ref) and [`inclination`](@ref). - -# Arguments - -- `xas::Vector{U}`: state vector of the asteroid `[x, y, z, v_x, v_y, v_z]`. -- `μ_S::T`: mass parameter of the central body (Sun). -- `jd::T`: orbit epoch of reference in julian days. -- `frame::Symbol`: plane of reference (`:equatorial` or `:ecliptic`). -""" -function pv2kep(xas::Vector{U}; μ::T = μ_S, jd::T = JD_J2000, - frame::Symbol = :equatorial) where {T <: Real, U <: Number} - if frame == :ecliptic - xas = equatorial2ecliptic(xas) - end - e = eccentricity(xas..., μ, 0.0) - a = semimajoraxis(xas..., μ, 0.0) - q = a * (1 - e) - tp = timeperipass(jd, xas..., μ, 0.0) - n = meanmotion(μ,a) - M = rad2deg(meananomaly(n, jd, tp)) - Ω = rad2deg(longascnode(xas...)) - ω = rad2deg(argperi(xas..., μ, 0.0)) - i = rad2deg(inclination(xas...)) - return OsculatingElements(e, q, tp, Ω, ω, i, M, a) -end - -@doc raw""" - (osc::OsculatingElements{T})(t::T) where {T <: Number} - -Return cartesian state vector of orbit `osc` at time `t` (Julian day). -""" -function (osc::OsculatingElements{T})(t::U) where {T,U <: Number} - - # Mean motion - n = PE.meanmotion(μ_S, osc.a) - # Mean anomaly - M = PE.meananomaly(n, t, osc.tp) - # Eccentric anomaly - E = PE.eccentricanomaly(osc.e, M) - # True anomaly - f = PE.trueanomaly(osc.e, E) - - # Distance to the central body - r = osc.a * (1 - osc.e^2) / (1 + osc.e * cos(f)) - - # Obtain position and velocity in the orbital frame - r_o = r .* [cos(f), sin(f), 0.0] - v_o = (sqrt(μ_S*osc.a)/r) .* [-sin(E), sqrt(1 - osc.e^2) * cos(E), 0.0] - - # Transform r_o and v_o to the inertial frame - ω = deg2rad(osc.ω) - i = deg2rad(osc.i) - Ω = deg2rad(osc.Ω) - # Rotation from orbital to inertial frame - A = Rz(-Ω) * Rx(-i) * Rz(-ω) - r_i = A * r_o - v_i = A * v_o - - # State vector - pv_i = vcat(r_i, v_i) - - return pv_i -end - -@doc raw""" - yarkp2adot(A2, a, e, μ_S) - -Return the average semimajor axis drift due to the Yarkovsky effect -```math -\begin{align*} - \left\langle\dot{a}\right\rangle & = \frac{2A_2(1-e^2)}{n}\left(\frac{1 \ \text{AU}}{p}\right)^2 \\ - & = \frac{2A_2}{(1-e^2)\sqrt{a\mu_\odot}}(1 \ \text{AU})^2, -\end{align*} -``` -where ``A_2`` is the Yarkovsky parameter, ``\mu_\odot = GM_\odot`` is the Sun's gravitational parameter, -``e`` is the eccentricity, ``n = \sqrt{\mu/a^3}`` is the mean motion, ``p = a(1-e^2)`` is the -semilatus rectum, and ``a`` is the semimajor axis. - -# Arguments - -- `A2`: Yarkovsky parameter. -- `a`: semimajor axis. -- `e`: eccentricity. -- `μ_S`: mass parameter of the Sun. - -!!! reference - See https://doi.org/10.1016/j.icarus.2013.02.004. -""" -function yarkp2adot(A2, a, e; μ = μ_S) - return 2A2/(sqrt(a)*(1-e^2)*sqrt(μ)) -end +@doc raw""" + OsculatingElements{T <: Number} + +Osculating orbital elements of a NEO. + +# Fields + +- `e::T`: eccentricity. +- `q::T`: perihelion distance [au]. +- `tp::T`: time of pericenter passage [jd]. +- `M::T`: mean anomaly [deg]. +- `Ω::T`: longitude of ascending node [deg]. +- `ω::T`: argument of pericentre [deg]. +- `i::T`: inclination [deg]. +- `a::T`: semimajor axis [au]. +""" +@auto_hash_equals struct OsculatingElements{T <: Number} + e::T + q::T + tp::T + Ω::T + ω::T + i::T + M::T + a::T + # Inner constructor + function OsculatingElements{T}(e::T, q::T, tp::T, Ω::T, ω::T, i::T, M::T, a::T) where {T <: Number} + return new{T}(e, q, tp, Ω, ω, i, M, a) + end +end + +# Outer constructors +function OsculatingElements(e::T, q::T, tp::T, Ω::T, ω::T, i::T, M::T, a::T) where {T <: Number} + return OsculatingElements{T}(e, q, tp, Ω, ω, i, M, a) +end + +function OsculatingElements() + return OsculatingElements(NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN) +end + +# A OsculatingElements is NaN if all its fields are NaN +function isnan(osc::OsculatingElements{T}) where {T <: Number} + return isnan(osc.e) && isnan(osc.q) && isnan(osc.tp) && isnan(osc.Ω) && isnan(osc.ω) && + isnan(osc.i) && isnan(osc.M) && isnan(osc.a) +end + +# Print method for OsculatingElements +# Example: +# Eccentricity (e): 0.4231715487782969 +# Pericenter distance (q): 0.5028397744678126 au +# Time of pericenter passage (tp): 2021-03-19T03:45:01.293 JDTDB +# Longitude of Ascending Node (Ω): 17.855086873010706 deg +# Argument of pericenter (ω): 194.74654283451 deg +# Inclination (i): 34.81327005431841 deg +# Mean anomaly (M): 118.87965684315387 deg +# Semimajor axis (a): 0.8717319220347314 au +function show(io::IO, m::OsculatingElements{T}) where {T <: Number} + + print(io, rpad("Eccentricity (e): ", 36), @sprintf("%.5f", cte(m.e)), "\n") + print(io, rpad("Pericenter distance (q): ", 36), @sprintf("%.5f", cte(m.q)), " au\n") + if isnan(m.tp) + print(io, rpad("Time of pericenter passage (tp): ", 36), "NaN JDTDB\n") + else + print(io, rpad("Time of pericenter passage (tp): ", 36), julian2datetime(cte(m.tp)), " JDTDB\n") + end + print(io, rpad("Longitude of Ascending Node (Ω): ", 36), @sprintf("%.5f", cte(m.Ω)), " deg\n") + print(io, rpad("Argument of pericenter (ω): ", 36), @sprintf("%.5f", cte(m.ω)), " deg\n") + print(io, rpad("Inclination (i): ", 36), @sprintf("%.5f", cte(m.i)), " deg\n") + print(io, rpad("Mean anomaly (M): ", 36), @sprintf("%.5f", cte(m.M)), " deg\n") + print(io, rpad("Semimajor axis (a): ", 36), @sprintf("%.5f", cte(m.a)), " au\n") + +end + +@doc raw""" + equatorial2ecliptic(xas::Vector{T}) where {T <: Number} + +Rotate state vector `xas` from equatorial plane to the ecliptic. +""" +function equatorial2ecliptic(xas::Vector{T}) where {T <: Number} + # Rotation matrix (only positions) + m_eq2ecl = Rx(deg2rad(ϵ0_deg)) + # Rotational matrix (positions + velocities) + m_xv_eq2ecl = hcat(vcat(m_eq2ecl, zeros(3,3)), vcat(zeros(3,3), m_eq2ecl)) + # Rotated state vector + return m_xv_eq2ecl*xas +end + +@doc raw""" + pv2kep(xas::Vector{U}; μ::T = μ_S, jd::T = JD_J2000, + frame::Symbol = :equatorial) where {T <: Real, U <: Number} + +Compute the orbital elements of the NEO with state vector `xas`. +Return an `OsculatingElements` object. + +See also [`equatorial2ecliptic`](@ref), [`eccentricity`](@ref), [`semimajoraxis`](@ref), +[`timeperipass`](@ref), [`longascnode`](@ref), [`argperi`](@ref) and [`inclination`](@ref). + +# Arguments + +- `xas::Vector{U}`: state vector of the asteroid `[x, y, z, v_x, v_y, v_z]`. +- `μ_S::T`: mass parameter of the central body (Sun). +- `jd::T`: orbit epoch of reference in julian days. +- `frame::Symbol`: plane of reference (`:equatorial` or `:ecliptic`). +""" +function pv2kep(xas::Vector{U}; μ::T = μ_S, jd::T = JD_J2000, + frame::Symbol = :equatorial) where {T <: Real, U <: Number} + if frame == :ecliptic + xas = equatorial2ecliptic(xas) + end + e = eccentricity(xas..., μ, 0.0) + a = semimajoraxis(xas..., μ, 0.0) + q = a * (1 - e) + tp = timeperipass(jd, xas..., μ, 0.0) + n = meanmotion(μ,a) + M = rad2deg(meananomaly(n, jd, tp)) + Ω = rad2deg(longascnode(xas...)) + ω = rad2deg(argperi(xas..., μ, 0.0)) + i = rad2deg(inclination(xas...)) + return OsculatingElements(e, q, tp, Ω, ω, i, M, a) +end + +@doc raw""" + (osc::OsculatingElements{T})(t::T) where {T <: Number} + +Return cartesian state vector of orbit `osc` at time `t` (Julian day). +""" +function (osc::OsculatingElements{T})(t::U) where {T,U <: Number} + + # Mean motion + n = PE.meanmotion(μ_S, osc.a) + # Mean anomaly + M = PE.meananomaly(n, t, osc.tp) + # Eccentric anomaly + E = PE.eccentricanomaly(osc.e, M) + # True anomaly + f = PE.trueanomaly(osc.e, E) + + # Distance to the central body + r = osc.a * (1 - osc.e^2) / (1 + osc.e * cos(f)) + + # Obtain position and velocity in the orbital frame + r_o = r .* [cos(f), sin(f), 0.0] + v_o = (sqrt(μ_S*osc.a)/r) .* [-sin(E), sqrt(1 - osc.e^2) * cos(E), 0.0] + + # Transform r_o and v_o to the inertial frame + ω = deg2rad(osc.ω) + i = deg2rad(osc.i) + Ω = deg2rad(osc.Ω) + # Rotation from orbital to inertial frame + A = Rz(-Ω) * Rx(-i) * Rz(-ω) + r_i = A * r_o + v_i = A * v_o + + # State vector + pv_i = vcat(r_i, v_i) + + return pv_i +end + +@doc raw""" + yarkp2adot(A2, a, e, μ_S) + +Return the average semimajor axis drift due to the Yarkovsky effect +```math +\begin{align*} + \left\langle\dot{a}\right\rangle & = \frac{2A_2(1-e^2)}{n}\left(\frac{1 \ \text{AU}}{p}\right)^2 \\ + & = \frac{2A_2}{(1-e^2)\sqrt{a\mu_\odot}}(1 \ \text{AU})^2, +\end{align*} +``` +where ``A_2`` is the Yarkovsky parameter, ``\mu_\odot = GM_\odot`` is the Sun's gravitational parameter, +``e`` is the eccentricity, ``n = \sqrt{\mu/a^3}`` is the mean motion, ``p = a(1-e^2)`` is the +semilatus rectum, and ``a`` is the semimajor axis. + +# Arguments + +- `A2`: Yarkovsky parameter. +- `a`: semimajor axis. +- `e`: eccentricity. +- `μ_S`: mass parameter of the Sun. + +!!! reference + See https://doi.org/10.1016/j.icarus.2013.02.004. +""" +function yarkp2adot(A2, a, e; μ = μ_S) + return 2A2/(sqrt(a)*(1-e^2)*sqrt(μ)) +end diff --git a/src/postprocessing/b_plane.jl b/src/postprocessing/b_plane.jl old mode 100755 new mode 100644 index ab0e55a6..76436030 --- a/src/postprocessing/b_plane.jl +++ b/src/postprocessing/b_plane.jl @@ -1,209 +1,209 @@ -@doc raw""" - crosssection(μ_P, R_P, vinf) - -Returns the "critical" ``B``, derived from conservation of energy and angular momentum -```math -B = \sqrt{1 + \frac{2\mu_P}{R_P v_\infty^2}}, -``` -i.e., what impact parameter ``B`` corresponds to a grazing impact in hyperbolic close -encounter. ``\mu_P`` is the planet's gravitational parameter, ``R_P`` is the planet's -radius and ``v_\infty`` is the asymptotic inbound velocity. If actual ``B`` is equal or -less to this, then impact happens. Output is in planet radii. - -# Arguments - -- `μ_P`: planetary gravitational parameter (au^3/day^2). -- `R_P`: planetary radius (au). -- `vinf`: asymptotic inbound velocity (au/day). - -!!! reference - See equations (13)-(14) in pages 4-5 of https://doi.org/10.1007/s10569-019-9914-4. -""" -function crosssection(μ_P, R_P, vinf) - return sqrt( 1 + (2μ_P)/(R_P*(vinf)^2) ) -end - -@doc raw""" - bopik(xae, xes) - -Computes Öpik's coordinates of impact parameter vector ``\mathbf{B}`` in hyperbolic planetary -close encounter. Returns a named tuple with the following fields: - -- `ξ` = ``\mathbf{B}\cdot\hat{\mathbf{\xi}}/R_E`` and `ζ` = ``\mathbf{B}\cdot\hat{\mathbf{\zeta}}/R_E``, where ``\mathbf{B}`` is the impact parameter vector, ``(\hat{\mathbf{\xi}}, \hat{\mathbf{\zeta}})`` is Öpik's frame and ``R_E`` is the Earth's radius in au. - -- `U` is another named tuple with the following fields: - - `y` = ``U_y``. - - `norm` = ``||\mathbf{U}||`` where ``\mathbf{U}`` is the planetocentric velocity vector in km/s. - -- `b` = ``b_E``, where ``b_E`` is the Earth impact cross section ("critical B"). See [`crosssection`](@ref). - -# Arguments - -- `xae`: asteroid's geocentric position/velocity vector at closest approach in au, au/day. -- `xes`: planet's heliocentric position/velocity vector at asteroid's closest approach in au, au/day. - -!!! reference - See equations (37)-(38) in page 14 of https://doi.org/10.1007/s10569-019-9914-4. -""" -function bopik(xae, xes) - - # Computation of Öpik's frame (\mathbf{ξ}, \mathbf{ζ}) - # See equations (37)-(38) in page 14 of https://doi.org/10.1007/s10569-019-9914-4 - - # Earth's gravitational parameter - μ_E = PE.μ[ea] - # Asteroid geocentric range at closest approach [au] - rae = sqrt(xae[1]^2 + xae[2]^2 + xae[3]^2) - # Osculating semimajor axis at closest approach (negative since hyperbolic) - a = semimajoraxis(xae..., μ_E, 0.0) - # Asymptotic inbound velocity v_\infty (au/day) - # See equation (1) in page 2 of https://doi.org/10.1007/s10569-019-9914-4 - v_infty = sqrt(μ_E/(-a)) - # Angular momentum per unit mass h = r × v - hvec = cross(xae[1:3], xae[4:6]) - # Magntude of h - h = sqrt(hvec[1]^2 + hvec[2]^2 + hvec[3]^2) - # Laplace-Runge-Lenz (eccentricity) vector - # \vec{e} = (\vec{v} × \vec{h})/μ - \vec{r}/r - evec = cross(xae[4:6], hvec)/μ_E - xae[1:3]/rae - # Osculating eccentricity - e = eccentricity(xae..., μ_E, 0.0) - # Osculating inclination - i = inclination(xae...) - # Periapsis position (unit vector) and periapsis velocity (unit vector) - # See first sentence below equation (3) in page 2 of https://doi.org/10.1007/s10569-019-9914-4 - P_v = evec./e - Q_v = cross(hvec, P_v)./h - # Inbound asymptote direction - # See equation (2) in page 2 of https://doi.org/10.1007/s10569-019-9914-4 - S_v = (P_v + (sqrt(e^2 - 1))Q_v)/e - # Earth's heliocentric velocity at closest approach (CA) - v_pl = xes[4:6] - # ξ-axis is essentially the MOID (Valsecchi et al, 2003) - # See equation (37) in page 14 of https://doi.org/10.1007/s10569-019-9914-4 - ξ_v_unnormalized = cross(v_pl, S_v) - ξ_v_norm = sqrt(ξ_v_unnormalized[1]^2 + ξ_v_unnormalized[2]^2 + ξ_v_unnormalized[3]^2) - ξ_v = ξ_v_unnormalized./ξ_v_norm - # ζ-axis: delay/advance in CA time (Valsecchi et al, 2003) - # See equation (37) in page 14 of https://doi.org/10.1007/s10569-019-9914-4 - ζ_v = -cross(S_v, ξ_v) - - # Computation of Öpik's coordinates of impact parameter vector \mathbf{B} - - # B-vector: "vector from the planet center to the intersection between the B-plane - # and the asymptote". - # See equation (4) in page 3 of https://doi.org/10.1007/s10569-019-9914-4 - Bvec = cross(S_v, hvec)./v_infty - # Impact parameter vector Öpik's coordinates - B_dot_ξ = dot(Bvec, ξ_v) - B_dot_ζ = dot(Bvec, ζ_v) - - # Computation of planetocentric velocity (U) vector - ves = v_pl # Earth's velocity, au/day - ves_norm = sqrt(ves[1]^2 + ves[2]^2 + ves[3]^2) # Earth's speed, au/day - ves_unit = ves/ves_norm # Earth's velocity unit vector - # angle between Y-axis and \vec{U} - cosθ = dot(S_v, ves_unit) - v_infty_kms = v_infty*au/daysec # Asteroid unperturbed speed, km/sec - # @show v_infty_kms() - # The norm of \vec{U} in appropriate units - U_unit = ves_norm # 1 U = v_ast/v_pl - U_norm = v_infty/U_unit - # U_y - U_y = U_norm*cosθ - # @show U_y U_norm - - # Earth impact cross section ("critical B") - b_E = crosssection(μ_E, RE/au, v_infty) - # @show b_E - - return (ξ=B_dot_ξ*au/RE, ζ=B_dot_ζ*au/RE, U=(y=U_y, norm=U_norm), b=b_E) -end - -@doc raw""" - valsecchi_circle(a, e, i, k, h; m_pl=3.003489614915764e-6) - -Computes Valsecchi circle associated to a mean motion resonance. Returns radius ``R`` (au) and -``\zeta``-axis coordinate ``D`` (au). This function first computes the Y-component and norm -of the planetocentric velocity vector ``\mathbf{U}`` -```math -U_y = \sqrt{a(1-e^2)}\cos i - 1 \quad \text{and} \quad -U = ||\mathbf{U}|| = \sqrt{3 - \frac{1}{a} - 2\sqrt{a(1-e^2)}\cos i}, -``` -and then substitutes into `valsecchi_circle(U_y, U_norm, k, h; m_pl=3.003489614915764e-6, a_pl=1.0)`. -`a `, `e` and `i` are the asteroid heliocentric semimajor axis (au), eccentricity and -inclination (rad) respectively. - -# Arguments - -- `a`: asteroid heliocentric semimajor axis (au). -- `e`: asteroid heliocentric eccentricity. -- `i`: asteroid heliocentric inclination, ecliptic (rad). -- `k/h`: `h` heliocentric revolutions of asteroid per `k` heliocentric revolutions of Earth. -- `m_pl`: planet mass normalized to Sun's mass, equal to Earth mass in solar masses by default. - -!!! reference - See section 2.1 in page 1181 of https://doi.org/10.1051/0004-6361:20031039. -""" -function valsecchi_circle(a, e, i, k, h; m_pl=3.003489614915764e-6) - # Components and norm of the planetocentric velocity vector - # See section 2.1 in page 1181 of https://doi.org/10.1051/0004-6361:20031039 - # U_x = sqrt( 2 - (1/a) - a*(1-(e^2)) ) # TODO: CHECK SIGN - U_y = sqrt( a*(1-(e^2)) )*cos(i) - 1 - # U_z = sqrt( a*(1-(e^2)) )*sin(i) # TODO: CHECK SIGN - U_norm = sqrt( 3 - (1/a) - 2*sqrt(a*(1-(e^2)))*cos(i) ) - # Expression below should be equal to asteroid heliocentric elliptic semimamajor axis - # in au units - # @show 1/(1-U_^2-2U_y) - return valsecchi_circle(U_y, U_norm, k, h, m_pl=m_pl) -end - -@doc raw""" - valsecchi_circle(U_y, U_norm, k, h; m_pl=3.003489614915764e-6, a_pl=1.0) - -Computes Valsecchi circle associated to a mean motion resonance. Returns radius ``R`` (au) and -``\zeta``-axis coordinate ``D`` (au) -```math -R = \left|\frac{c\sin\theta_0'}{\cos\theta_0' - \cos\theta}\right| \quad \text{and} \quad -D = \frac{c\sin\theta}{\cos\theta_0' - \cos\theta}, -``` -where ``c = m/U^2`` with ``m`` the mass of the planet and ``U = ||\mathbf{U}||`` the norm of -the planetocentric velocity vector; and ``\theta``, ``\theta_0'`` are the angles between Y-axis -and ``\mathbf{U}`` pre and post encounter respectively. - -# Arguments -- `U_y`: Y-component of unperturbed planetocentric velocity (Y-axis coincides with the direction of motion of the planet). -- `U_norm`: Euclidean norm of unperturbed planetocentric velocity. Both `U_y`, `U_norm` are in units such that the heliocentric velocity of the planet is 1. -- `k/h`: `h` heliocentric revolutions of asteroid per `k` heliocentric revolutions of Earth. -- `m_pl`: planet mass normalized to Sun's mass, equal to Earth mass in solar masses by default. -- `a_pl`: planetary heliocentric semimajor axis in au; default value is 1. - -!!! reference - See pages 1181, 1182 and 1187 of https://doi.org/10.1051/0004-6361:20031039. -""" -function valsecchi_circle(U_y, U_norm, k, h; m_pl=3.003489614915764e-6, a_pl=1.0) - # Post-encounter semimajor axis - # See page 1187 of https://doi.org/10.1051/0004-6361:20031039 - a0p = a_pl*(k/h)^(2/3) - - # θ: angle between Y-axis and planetocentric velocity vector \vec{U} - - # Trigonometric functions of pre encounter θ - # See page 1181 of https://doi.org/10.1051/0004-6361:20031039 - cosθ = U_y/U_norm - sinθ = sin(acos(cosθ)) # sqrt(1-cosθ^2) # TODO: CHECK SIGN - # Trigonometric functions of post-encounter θ - # See page 1187 of https://doi.org/10.1051/0004-6361:20031039 - cosθ0p = (1-(U_norm^2)-(1/a0p))/(2U_norm) - sinθ0p = sin(acos(cosθ0p)) - # c = m/U^2 - # See first sentence below equation (3) in section 2.3, page 1182 of - # https://doi.org/10.1051/0004-6361:20031039 - c = m_pl/(U_norm^2) - # Radius of the Valsecchi circle R and its ζ-axis component D - # See page 1187 of https://doi.org/10.1051/0004-6361:20031039 - R0 = abs( c*sinθ0p/(cosθ0p-cosθ) ) - D0 = c*sinθ/(cosθ0p-cosθ) - - return R0, D0 +@doc raw""" + crosssection(μ_P, R_P, vinf) + +Returns the "critical" ``B``, derived from conservation of energy and angular momentum +```math +B = \sqrt{1 + \frac{2\mu_P}{R_P v_\infty^2}}, +``` +i.e., what impact parameter ``B`` corresponds to a grazing impact in hyperbolic close +encounter. ``\mu_P`` is the planet's gravitational parameter, ``R_P`` is the planet's +radius and ``v_\infty`` is the asymptotic inbound velocity. If actual ``B`` is equal or +less to this, then impact happens. Output is in planet radii. + +# Arguments + +- `μ_P`: planetary gravitational parameter (au^3/day^2). +- `R_P`: planetary radius (au). +- `vinf`: asymptotic inbound velocity (au/day). + +!!! reference + See equations (13)-(14) in pages 4-5 of https://doi.org/10.1007/s10569-019-9914-4. +""" +function crosssection(μ_P, R_P, vinf) + return sqrt( 1 + (2μ_P)/(R_P*(vinf)^2) ) +end + +@doc raw""" + bopik(xae, xes) + +Computes Öpik's coordinates of impact parameter vector ``\mathbf{B}`` in hyperbolic planetary +close encounter. Returns a named tuple with the following fields: + +- `ξ` = ``\mathbf{B}\cdot\hat{\mathbf{\xi}}/R_E`` and `ζ` = ``\mathbf{B}\cdot\hat{\mathbf{\zeta}}/R_E``, where ``\mathbf{B}`` is the impact parameter vector, ``(\hat{\mathbf{\xi}}, \hat{\mathbf{\zeta}})`` is Öpik's frame and ``R_E`` is the Earth's radius in au. + +- `U` is another named tuple with the following fields: + - `y` = ``U_y``. + - `norm` = ``||\mathbf{U}||`` where ``\mathbf{U}`` is the planetocentric velocity vector in km/s. + +- `b` = ``b_E``, where ``b_E`` is the Earth impact cross section ("critical B"). See [`crosssection`](@ref). + +# Arguments + +- `xae`: asteroid's geocentric position/velocity vector at closest approach in au, au/day. +- `xes`: planet's heliocentric position/velocity vector at asteroid's closest approach in au, au/day. + +!!! reference + See equations (37)-(38) in page 14 of https://doi.org/10.1007/s10569-019-9914-4. +""" +function bopik(xae, xes) + + # Computation of Öpik's frame (\mathbf{ξ}, \mathbf{ζ}) + # See equations (37)-(38) in page 14 of https://doi.org/10.1007/s10569-019-9914-4 + + # Earth's gravitational parameter + μ_E = PE.μ[ea] + # Asteroid geocentric range at closest approach [au] + rae = sqrt(xae[1]^2 + xae[2]^2 + xae[3]^2) + # Osculating semimajor axis at closest approach (negative since hyperbolic) + a = semimajoraxis(xae..., μ_E, 0.0) + # Asymptotic inbound velocity v_\infty (au/day) + # See equation (1) in page 2 of https://doi.org/10.1007/s10569-019-9914-4 + v_infty = sqrt(μ_E/(-a)) + # Angular momentum per unit mass h = r × v + hvec = cross(xae[1:3], xae[4:6]) + # Magntude of h + h = sqrt(hvec[1]^2 + hvec[2]^2 + hvec[3]^2) + # Laplace-Runge-Lenz (eccentricity) vector + # \vec{e} = (\vec{v} × \vec{h})/μ - \vec{r}/r + evec = cross(xae[4:6], hvec)/μ_E - xae[1:3]/rae + # Osculating eccentricity + e = eccentricity(xae..., μ_E, 0.0) + # Osculating inclination + i = inclination(xae...) + # Periapsis position (unit vector) and periapsis velocity (unit vector) + # See first sentence below equation (3) in page 2 of https://doi.org/10.1007/s10569-019-9914-4 + P_v = evec./e + Q_v = cross(hvec, P_v)./h + # Inbound asymptote direction + # See equation (2) in page 2 of https://doi.org/10.1007/s10569-019-9914-4 + S_v = (P_v + (sqrt(e^2 - 1))Q_v)/e + # Earth's heliocentric velocity at closest approach (CA) + v_pl = xes[4:6] + # ξ-axis is essentially the MOID (Valsecchi et al, 2003) + # See equation (37) in page 14 of https://doi.org/10.1007/s10569-019-9914-4 + ξ_v_unnormalized = cross(v_pl, S_v) + ξ_v_norm = sqrt(ξ_v_unnormalized[1]^2 + ξ_v_unnormalized[2]^2 + ξ_v_unnormalized[3]^2) + ξ_v = ξ_v_unnormalized./ξ_v_norm + # ζ-axis: delay/advance in CA time (Valsecchi et al, 2003) + # See equation (37) in page 14 of https://doi.org/10.1007/s10569-019-9914-4 + ζ_v = -cross(S_v, ξ_v) + + # Computation of Öpik's coordinates of impact parameter vector \mathbf{B} + + # B-vector: "vector from the planet center to the intersection between the B-plane + # and the asymptote". + # See equation (4) in page 3 of https://doi.org/10.1007/s10569-019-9914-4 + Bvec = cross(S_v, hvec)./v_infty + # Impact parameter vector Öpik's coordinates + B_dot_ξ = dot(Bvec, ξ_v) + B_dot_ζ = dot(Bvec, ζ_v) + + # Computation of planetocentric velocity (U) vector + ves = v_pl # Earth's velocity, au/day + ves_norm = sqrt(ves[1]^2 + ves[2]^2 + ves[3]^2) # Earth's speed, au/day + ves_unit = ves/ves_norm # Earth's velocity unit vector + # angle between Y-axis and \vec{U} + cosθ = dot(S_v, ves_unit) + v_infty_kms = v_infty*au/daysec # Asteroid unperturbed speed, km/sec + # @show v_infty_kms() + # The norm of \vec{U} in appropriate units + U_unit = ves_norm # 1 U = v_ast/v_pl + U_norm = v_infty/U_unit + # U_y + U_y = U_norm*cosθ + # @show U_y U_norm + + # Earth impact cross section ("critical B") + b_E = crosssection(μ_E, RE/au, v_infty) + # @show b_E + + return (ξ=B_dot_ξ*au/RE, ζ=B_dot_ζ*au/RE, U=(y=U_y, norm=U_norm), b=b_E) +end + +@doc raw""" + valsecchi_circle(a, e, i, k, h; m_pl=3.003489614915764e-6) + +Computes Valsecchi circle associated to a mean motion resonance. Returns radius ``R`` (au) and +``\zeta``-axis coordinate ``D`` (au). This function first computes the Y-component and norm +of the planetocentric velocity vector ``\mathbf{U}`` +```math +U_y = \sqrt{a(1-e^2)}\cos i - 1 \quad \text{and} \quad +U = ||\mathbf{U}|| = \sqrt{3 - \frac{1}{a} - 2\sqrt{a(1-e^2)}\cos i}, +``` +and then substitutes into `valsecchi_circle(U_y, U_norm, k, h; m_pl=3.003489614915764e-6, a_pl=1.0)`. +`a `, `e` and `i` are the asteroid heliocentric semimajor axis (au), eccentricity and +inclination (rad) respectively. + +# Arguments + +- `a`: asteroid heliocentric semimajor axis (au). +- `e`: asteroid heliocentric eccentricity. +- `i`: asteroid heliocentric inclination, ecliptic (rad). +- `k/h`: `h` heliocentric revolutions of asteroid per `k` heliocentric revolutions of Earth. +- `m_pl`: planet mass normalized to Sun's mass, equal to Earth mass in solar masses by default. + +!!! reference + See section 2.1 in page 1181 of https://doi.org/10.1051/0004-6361:20031039. +""" +function valsecchi_circle(a, e, i, k, h; m_pl=3.003489614915764e-6) + # Components and norm of the planetocentric velocity vector + # See section 2.1 in page 1181 of https://doi.org/10.1051/0004-6361:20031039 + # U_x = sqrt( 2 - (1/a) - a*(1-(e^2)) ) # TODO: CHECK SIGN + U_y = sqrt( a*(1-(e^2)) )*cos(i) - 1 + # U_z = sqrt( a*(1-(e^2)) )*sin(i) # TODO: CHECK SIGN + U_norm = sqrt( 3 - (1/a) - 2*sqrt(a*(1-(e^2)))*cos(i) ) + # Expression below should be equal to asteroid heliocentric elliptic semimamajor axis + # in au units + # @show 1/(1-U_^2-2U_y) + return valsecchi_circle(U_y, U_norm, k, h, m_pl=m_pl) +end + +@doc raw""" + valsecchi_circle(U_y, U_norm, k, h; m_pl=3.003489614915764e-6, a_pl=1.0) + +Computes Valsecchi circle associated to a mean motion resonance. Returns radius ``R`` (au) and +``\zeta``-axis coordinate ``D`` (au) +```math +R = \left|\frac{c\sin\theta_0'}{\cos\theta_0' - \cos\theta}\right| \quad \text{and} \quad +D = \frac{c\sin\theta}{\cos\theta_0' - \cos\theta}, +``` +where ``c = m/U^2`` with ``m`` the mass of the planet and ``U = ||\mathbf{U}||`` the norm of +the planetocentric velocity vector; and ``\theta``, ``\theta_0'`` are the angles between Y-axis +and ``\mathbf{U}`` pre and post encounter respectively. + +# Arguments +- `U_y`: Y-component of unperturbed planetocentric velocity (Y-axis coincides with the direction of motion of the planet). +- `U_norm`: Euclidean norm of unperturbed planetocentric velocity. Both `U_y`, `U_norm` are in units such that the heliocentric velocity of the planet is 1. +- `k/h`: `h` heliocentric revolutions of asteroid per `k` heliocentric revolutions of Earth. +- `m_pl`: planet mass normalized to Sun's mass, equal to Earth mass in solar masses by default. +- `a_pl`: planetary heliocentric semimajor axis in au; default value is 1. + +!!! reference + See pages 1181, 1182 and 1187 of https://doi.org/10.1051/0004-6361:20031039. +""" +function valsecchi_circle(U_y, U_norm, k, h; m_pl=3.003489614915764e-6, a_pl=1.0) + # Post-encounter semimajor axis + # See page 1187 of https://doi.org/10.1051/0004-6361:20031039 + a0p = a_pl*(k/h)^(2/3) + + # θ: angle between Y-axis and planetocentric velocity vector \vec{U} + + # Trigonometric functions of pre encounter θ + # See page 1181 of https://doi.org/10.1051/0004-6361:20031039 + cosθ = U_y/U_norm + sinθ = sin(acos(cosθ)) # sqrt(1-cosθ^2) # TODO: CHECK SIGN + # Trigonometric functions of post-encounter θ + # See page 1187 of https://doi.org/10.1051/0004-6361:20031039 + cosθ0p = (1-(U_norm^2)-(1/a0p))/(2U_norm) + sinθ0p = sin(acos(cosθ0p)) + # c = m/U^2 + # See first sentence below equation (3) in section 2.3, page 1182 of + # https://doi.org/10.1051/0004-6361:20031039 + c = m_pl/(U_norm^2) + # Radius of the Valsecchi circle R and its ζ-axis component D + # See page 1187 of https://doi.org/10.1051/0004-6361:20031039 + R0 = abs( c*sinθ0p/(cosθ0p-cosθ) ) + D0 = c*sinθ/(cosθ0p-cosθ) + + return R0, D0 end \ No newline at end of file diff --git a/src/propagation/asteroid_dynamical_models.jl b/src/propagation/asteroid_dynamical_models.jl old mode 100755 new mode 100644 index 942d8ca0..3fc9957c --- a/src/propagation/asteroid_dynamical_models.jl +++ b/src/propagation/asteroid_dynamical_models.jl @@ -1,1278 +1,1278 @@ -@doc raw""" - evaleph(eph::TaylorInterpolant, t::Taylor1, q::Taylor1{U}) where {U} - evaleph(eph::TaylorInterpolant, t::Taylor1, q::TaylorN{Taylor1{T}}) where {T<:Real} - -Evaluate planetary ephemeris with type given by `q`. -""" -function evaleph(eph::TaylorInterpolant, t::Taylor1, q::Taylor1{U}) where {U} - return map(x -> Taylor1( x.coeffs*one(q[0]) ), eph(t)) -end - -function evaleph(eph::TaylorInterpolant, t::Taylor1, q::TaylorN{Taylor1{T}}) where {T<:Real} - return one(q)*eph(t) -end - -@doc raw""" - auxzero(a::AbstractSeries) - -Return a zero of the same type as `a`. -""" -function auxzero(a::AbstractSeries) - return zero(a) -end - -@doc raw""" - auxzero(a::TaylorN{Taylor1{T}}) where {T<:Number} - -Return a `TaylorN` with zero coefficients of the same type as `a.coeffs`. -""" -function auxzero(a::TaylorN{Taylor1{T}}) where {T<:Number} - return TaylorN(zero.(a.coeffs)) -end - -# Nearth-Earth asteroid dynamical model (d=2.0) -# Bodies considered in the model are: the Sun, the eight planets, the Moon and Ceres, -# as well as the asteroid of interest as a test particle with null mass. Dynamical -# effects considered are: -# - post-Newtonian point-mass accelerations between all bodies, -# - figure-effects (oblateness) of the Earth (J2 and J3) -# - J2 effect of the Sun -# - J2 and J3 effect of the Moon -# - Kinematic model for the precession and nutation of the Earth's orientation (IAU 1976/1980 Earth orientation model) -# - Kinematic model for the Moons's orientation (Seidelmann et al., 2006) -# - Non-gravitational accelerations acting upon the asteroid -# are included (Yarkovsky effect) a_nongrav = A2*t_vec*(au/r)^d, where t_vec is the -# unit heliocentric transverse vector, au is 1 astronomical unit, r is the -# asteroid's heliocentric range, A2 is a coefficient (with units of au/day^2), -# and d = 2.0 - -@doc raw""" - RNp1BP_pN_A_J23E_J2S_ng_eph_threads!(dq, q, params, t) - -Near-Earth asteroid dynamical model (``d = 2``). Bodies considered in the model are: the Sun, -the eight planets, the Moon and Ceres, as well as the asteroid of interest as a test particle -with null mass. Dynamical effects considered are: - -- Post-Newtonian point-mass accelerations between all bodies: see equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract. - -- Figure-effects (oblateness) of the Earth (``J_2`` and ``J_3``), - -- ``J_2`` effect of the Sun and - -- ``J_2`` and ``J_3`` effect of the Moon: see equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract. - -- Kinematic model for the precession and nutation of the Earth's orientation (IAU 1976/1980 Earth orientation model): see [`PlanetaryEphemeris.c2t_jpl_de430`](@ref). - -- Kinematic model for the Moon's orientation (Seidelmann et al., 2006): see equations (14)-(15) in page 9 and equations (34)-(35) in page 16 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract. - -- Non-gravitational accelerations acting upon the asteroid: are included (Yarkovsky effect) -```math -\mathbf{a}_\text{nongrav} = A_2\left(\frac{1 \ \text{au}}{r}\right)^d*\hat{\mathbf{t}}, -``` -where ``\hat{\mathbf{t}}`` is the unit heliocentric transverse vector, ``r`` is the -asteroid's heliocentric range, ``A_2`` is a coefficient (with units of au/day^2), -and ``d = 2``. - -To improve performance, some internal loops are multi-threaded via `Threads.threads for` - -See also [`PlanetaryEphemeris.NBP_pN_A_J23E_J23M_J2S!`](@ref). -""" RNp1BP_pN_A_J23E_J2S_ng_eph_threads! - -function RNp1BP_pN_A_J23E_J2S_ng_eph_threads!(dq, q, params, t) - # Julian date of start time - local jd0 = params[4] - # Days since J2000.0 = 2.451545e6 - local dsj2k = t + (jd0 - JD_J2000) - # Solar system ephemeris at dsj2k - local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) - # Accelerations at dsj2k - local acceph_t = evaleph(params[2], dsj2k, q[1]) - # Newtonian potentials at dsj2k - local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) - # Type of position / velocity components - local S = eltype(q) - # Interaction matrix with flattened bodies - local UJ_interaction = params[5] - # Number of bodies, including NEA - local N = params[6] - # Number of bodies, except the asteroid - local Nm1 = N-1 - # Vector of mass parameters GM's - local μ = params[7] - - # zero(q[1]) - local zero_q_1 = auxzero(q[1]) - - #= - Point-mass accelerations - See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - - # Position of the i-th body - position of the asteroid - X = Array{S}(undef, N) # X-axis component - Y = Array{S}(undef, N) # Y-axis component - Z = Array{S}(undef, N) # Z-axis component - - # Distance between the i-th body and the asteroid - r_p2 = Array{S}(undef, N) # r_{i,asteroid}^2 - r_p1d2 = Array{S}(undef, N) # sqrt(r_p2) <-> r_{i, asteroid} - r_p3d2 = Array{S}(undef, N) # r_p2^1.5 <-> r_{i, asteroid}^3 - r_p7d2 = Array{S}(undef, N) # r_p2^3.5 <-> r_{i, asteroid}^7 - - # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 - newtonianCoeff = Array{S}(undef, N) - - # Velocity of the i-th body - ui = Array{S}(undef, N-1) # X-axis component - vi = Array{S}(undef, N-1) # Y-axis component - wi = Array{S}(undef, N-1) # Z-axis component - - # Post-Newtonian stuff - - # Velocity of the i-th body - velocity of the asteroid - U = Array{S}(undef, N) # X-axis component - V = Array{S}(undef, N) # Y-axis component - W = Array{S}(undef, N) # Z-axis component - - # 4 * Velocity of the asteroid - 3 * velocity of the i-th body - _4U_m_3X = Array{S}(undef, N) # X-axis component - _4V_m_3Y = Array{S}(undef, N) # Y-axis component - _4W_m_3Z = Array{S}(undef, N) # Z-axis component - - # v_{i,j}v_{asteroid,j} j = x, y, z - UU = Array{S}(undef, N) # v_{i,x}v_{asteroid,x} - VV = Array{S}(undef, N) # v_{i,y}v_{asteroid,y} - WW = Array{S}(undef, N) # v_{i,z}v_{asteroid,z} - - # Newtonian potential of 1 body \mu_i / r_{i, asteroid} - newtonian1b_Potential = Array{S}(undef, N) - # Newtonian potential of N bodies - # \sum_{i\neq l} \frac{\mu_i}{r_{il}} or - # \sum_{j\neq k} \frac{\mu_j}{r_{jk}} - newtonianNb_Potential = Array{S}(undef, N) - - # Newtonian coefficient * difference between two positions, i.e., - # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 - newton_acc_X = Array{S}(undef, N) # X-axis component - newton_acc_Y = Array{S}(undef, N) # Y-axis component - newton_acc_Z = Array{S}(undef, N) # Z-axis component - - # Combinations of velocities - v2 = Array{S}(undef, N) # Velocity magnitude squared ||\mathbf{v}_i||^2 - vi_dot_vj = Array{S}(undef, N) # - - # Second term without (\mathbf{v}_i - \mathbf{v}_j) - pn2 = Array{S}(undef, N) - # Full second term - U_t_pn2 = Array{S}(undef, N) # X-axis component - V_t_pn2 = Array{S}(undef, N) # Y-axis component - W_t_pn2 = Array{S}(undef, N) # Z-axis component - - # Third term without newtonian accelerations \mathbf{a}_i - pn3 = Array{S}(undef, N) - # Full third term of equation (35) - pNX_t_pn3 = Array{S}(undef, N) # X-axis component - pNY_t_pn3 = Array{S}(undef, N) # Y-axis component - pNZ_t_pn3 = Array{S}(undef, N) # Z-axis component - - # First term - _4ϕj = Array{S}(undef, N) # 4*\sum term inside {} - ϕi_plus_4ϕj = Array{S}(undef, N) # 4*\sum + \sum terms inside {} - sj2_plus_2si2_minus_4vivj = Array{S}(undef, N) # \dot{s}_j^2 + 2\dot{s}_i^2 - 4 <, > terms inside {} - ϕs_and_vs = Array{S}(undef, N) # -4\sum - \sum + \dot{s}_j^2 + 2\dot{s}_i^2 - 4<, > terms inside {} - pn1t1_7 = Array{S}(undef, N) # Everything inside the {} in the first term except for the term with accelerations (last) - # Last term inside the {} - pNX_t_X = Array{S}(undef, N) # X-axis component - pNY_t_Y = Array{S}(undef, N) # Y-axis component - pNZ_t_Z = Array{S}(undef, N) # Z-axis component - # Everything inside the {} in the first term - pn1 = Array{S}(undef, N) - # Full first term - X_t_pn1 = Array{S}(undef, N) # X-axis component - Y_t_pn1 = Array{S}(undef, N) # Y-axis component - Z_t_pn1 = Array{S}(undef, N) # Z-axis component - - # Temporary post-Newtonian accelerations - pntempX = zero_q_1 # X-axis component - pntempY = zero_q_1 # Y-axis component - pntempZ = zero_q_1 # Z-axis component - - #= - Extended body accelerations - See equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract - and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - - # J_2 acceleration auxiliaries - - # Auxiliaries to compute body-fixed frame coordinates - t31 = Array{S}(undef, N) - t32 = Array{S}(undef, N) - t33 = Array{S}(undef, N) - # z-coordinate in body-fixed frame - r_sin_ϕ = Array{S}(undef, N) - - # Trigonometric functions of latitude ϕ and longitude λ in the body-fixed coordinate system - # See equations (165)-(168) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - sin_ϕ = Array{S}(undef, N) # sin(latitude ϕ) - ϕ = Array{S}(undef, N) # Latitude ϕ - cos_ϕ = Array{S}(undef, N) # cos(latitude ϕ) - sin2_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^2 - sin3_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^3 - sin4_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^4 - - # Acceleration due to zonal harmonics in inertial frame - F_J2_x = Array{S}(undef, N) - F_J2_y = Array{S}(undef, N) - F_J2_z = Array{S}(undef, N) - # Auxiliaries to compute F_J2_i, i = x, y, z - F_J2_x1 = Array{S}(undef, N) - F_J2_y1 = Array{S}(undef, N) - F_J2_z1 = Array{S}(undef, N) - F_J2_x2 = Array{S}(undef, N) - F_J2_y2 = Array{S}(undef, N) - F_J2_z2 = Array{S}(undef, N) - - # Temporary arrays for the sum of full extended body accelerations - temp_accX_i = Array{S}(undef, N) - temp_accY_i = Array{S}(undef, N) - temp_accZ_i = Array{S}(undef, N) - - # Legendre polynomials - # See equations (176) and (177) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - P_2_sin_ϕ = Array{S}(undef, N) # Second Legendre polynomial P_2(sin ϕ) - ∂P_2_sin_ϕ = Array{S}(undef, N) # dP_2(sin ϕ)/d(sin ϕ) - P_3_sin_ϕ = Array{S}(undef, N) # Third Legendre polynomial P_3(sin ϕ) - ∂P_3_sin_ϕ = Array{S}(undef, N) # dP_3(sin ϕ)/d(sin ϕ) - # -cos ϕ P_n' - m_c_ϕ_∂P_2 = Array{S}(undef, N) # -cos ϕ P_2' - m_c_ϕ_∂P_3 = Array{S}(undef, N) # -cos ϕ P_3' - - # -J_n * R^n / r^m - # J_n: n-th zonal harmonic coefficient - # R: radius of the body - # r: distance between the body and the asteroid - Λ2j_div_r4 = Array{S}(undef, N) # J_2 * R^2 / r^4 - Λ3j_div_r5 = Array{S}(undef, N) # J_3 * R^3 / r^5 - - # Accelerations due to zonal harmonics in body frame - - # Acceleration due to zonal harmonics J_n, n = 2, 3 - F_J_ξ = Array{S}(undef, N) # ξ-axis component - F_J_η = Array{S}(undef, N) # η-axis component - F_J_ζ = Array{S}(undef, N) # ζ-axis component - # Acceleration due to second zonal harmonic J_2 - F_J2_ξ = Array{S}(undef, N) # ξ-axis component - F_J2_η = Array{S}(undef, N) # η-axis component - F_J2_ζ = Array{S}(undef, N) # ζ-axis component - # Acceleration due to third zonal harmonic J_3 - F_J3_ξ = Array{S}(undef, N) # ξ-axis component - F_J3_η = Array{S}(undef, N) # η-axis component - F_J3_ζ = Array{S}(undef, N) # ζ-axis component - - # Unit vectors (ξ, η, ζ) in inertial frame - - # ξ vector - ξx = Array{S}(undef, N) - ξy = Array{S}(undef, N) - ξz = Array{S}(undef, N) - # η vector - ηx = Array{S}(undef, N) - ηy = Array{S}(undef, N) - ηz = Array{S}(undef, N) - # Auxiliaries to compute η vector - ηx1 = Array{S}(undef, N) - ηy1 = Array{S}(undef, N) - ηz1 = Array{S}(undef, N) - ηx2 = Array{S}(undef, N) - ηy2 = Array{S}(undef, N) - ηz2 = Array{S}(undef, N) - # ζ vector - ζx = Array{S}(undef, N) - ζy = Array{S}(undef, N) - ζz = Array{S}(undef, N) - # Auxiliaries to compute ζ vector - ζx1 = Array{S}(undef, N) - ζy1 = Array{S}(undef, N) - ζz1 = Array{S}(undef, N) - ζx2 = Array{S}(undef, N) - ζy2 = Array{S}(undef, N) - ζz2 = Array{S}(undef, N) - - # Full extended-body accelerations - accX = zero_q_1 - accY = zero_q_1 - accZ = zero_q_1 - - # Rotations to and from Earth, Sun and Moon pole-oriented frames - local M_ = Array{S}(undef, 3, 3, N) - local M_ .= zero_q_1 - local M_[:, :, ea] .= t2c_jpl_de430(dsj2k)[:, :] .+ zero_q_1 - - # Fill first 3 elements of dq with velocities - dq[1] = q[4] - dq[2] = q[5] - dq[3] = q[6] - - # Newtonian potential of N bodies - newtonianNb_Potential[N] = zero_q_1 - - #= - Compute point-mass Newtonian accelerations, all bodies - See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - Threads.@threads for i in 1:Nm1 - # Velocity of the i-th body - ui[i] = ss16asteph_t[3(N-1+i)-2] # X-axis component - vi[i] = ss16asteph_t[3(N-1+i)-1] # Y-axis component - wi[i] = ss16asteph_t[3(N-1+i) ] # Z-axis component - - # Position of the i-th body - position of the asteroid - X[i] = ss16asteph_t[3i-2]-q[1] # X-axis component - Y[i] = ss16asteph_t[3i-1]-q[2] # Y-axis component - Z[i] = ss16asteph_t[3i ]-q[3] # Z-axis component - - # Velocity of the i-th body - velocity of the asteroid - U[i] = ui[i]-dq[1] # X-axis component - V[i] = vi[i]-dq[2] # Y-axis component - W[i] = wi[i]-dq[3] # Z-axis component - - # 4 * Velocity of the asteroid - 3 * velocity of the i-th body - _4U_m_3X[i] = (4dq[1]) - (3ui[i]) # X-axis component - _4V_m_3Y[i] = (4dq[2]) - (3vi[i]) # Y-axis component - _4W_m_3Z[i] = (4dq[3]) - (3wi[i]) # Z-axis component - - # Dot product inside the [] in the second term - pn2x = X[i]*_4U_m_3X[i] - pn2y = Y[i]*_4V_m_3Y[i] - pn2z = Z[i]*_4W_m_3Z[i] - - # v_{ij}v_{asteroid} j = x, y, z - UU[i] = ui[i]*dq[1] - VV[i] = vi[i]*dq[2] - WW[i] = wi[i]*dq[3] - - # - vi_dot_vj[i] = ( UU[i]+VV[i] ) + WW[i] - - # Distance between the i-th body and the asteroid - r_p2[i] = ( (X[i]^2)+(Y[i]^2) ) + (Z[i]^2) # r_{i,asteroid}^2 - r_p1d2[i] = sqrt(r_p2[i]) # sqrt(r_p2) <-> r_{i,asteroid} - r_p3d2[i] = r_p2[i]^1.5 # r_p2^1.5 <-> r_{i, asteroid}^3 - r_p7d2[i] = r_p2[i]^3.5 # r_p2^3.5 <-> r_{i, asteroid}^7 - - # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 - newtonianCoeff[i] = μ[i]/r_p3d2[i] - - # Second term without (\mathbf{v}_i - \mathbf{v}_asteroid) - pn2[i] = newtonianCoeff[i]*(( pn2x+pn2y ) + pn2z) - - # Newtonian coefficient * difference between two positions, i.e., - # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 - newton_acc_X[i] = X[i]*newtonianCoeff[i] - newton_acc_Y[i] = Y[i]*newtonianCoeff[i] - newton_acc_Z[i] = Z[i]*newtonianCoeff[i] - - # Newtonian potential of 1 body \mu_i / r_{i, asteroid} - newtonian1b_Potential[i] = μ[i]/r_p1d2[i] - # Third term without newtonian accelerations \mathbf{a}_i - pn3[i] = 3.5newtonian1b_Potential[i] - # Full second term - U_t_pn2[i] = pn2[i]*U[i] # X-axis component - V_t_pn2[i] = pn2[i]*V[i] # Y-axis component - W_t_pn2[i] = pn2[i]*W[i] # Z-axis component - - #= - Extended body accelerations - See equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract - and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - - # J_2 accelerations, if i-th body is flattened - if UJ_interaction[i] - # Rotate from inertial frame to extended-body frame - # Here we are rotating only the Z-coordinate - t31[i] = -X[i]*M_[1,3,i] - t32[i] = -Y[i]*M_[2,3,i] - t33[i] = -Z[i]*M_[3,3,i] - r_sin_ϕ[i] = (t31[i]+t32[i])+t33[i] # z-coordinate in body-fixed frame - - # Trigonometric functions of latitude ϕ and longitude λ in the body-fixed coordinate system - # See equations (165)-(168) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - - sin_ϕ[i] = r_sin_ϕ[i]/r_p1d2[i] # sin(latitude ϕ) - ϕ[i] = asin(sin_ϕ[i]) # Latitude ϕ - cos_ϕ[i] = cos(ϕ[i]) # cos(latitude ϕ) - sin2_ϕ[i] = sin_ϕ[i]^2 # sin(latitude ϕ)^2 - sin3_ϕ[i] = sin_ϕ[i]^3 # sin(latitude ϕ)^3 - - # Legendre polynomials - - # See equations (176) and (177) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - P_2_sin_ϕ[i] = 1.5sin2_ϕ[i] - 0.5 # Second Legendre polynomial P_2(sin ϕ) - ∂P_2_sin_ϕ[i] = 3sin_ϕ[i] # dP_2(sin ϕ)/d(sin ϕ) - P_3_sin_ϕ[i] = (-1.5sin_ϕ[i]) + (2.5sin3_ϕ[i]) # Third Legendre polynomial P_3(sin ϕ) - ∂P_3_sin_ϕ[i] = -1.5 + 7.5sin2_ϕ[i] # dP_3(sin ϕ)/d(sin ϕ) - - # Compute cartesian coordinates of acceleration due to body figure in body frame - - # -J_n * R^n / r^m - # J_n: n-th zonal harmonic coefficient - # R: radius of the body - # r: distance between the body and the asteroid - Λ2j_div_r4[i] = -(Λ2[i]/(r_p2[i]^2)) # J_2 * R^2 / r^4 - Λ3j_div_r5[i] = -(Λ3[i]/(r_p1d2[i]^5)) # J_3 * R^3 / r^5 - - # -cos ϕ P_n' - m_c_ϕ_∂P_2[i] = (-cos_ϕ[i])*∂P_2_sin_ϕ[i] # -cos ϕ P_2' - m_c_ϕ_∂P_3[i] = (-cos_ϕ[i])*∂P_3_sin_ϕ[i] # -cos ϕ P_3' - - # Acceleration due to second zonal harmonic J_2 in body frame - F_J2_ξ[i] = ( Λ2j_div_r4[i]*(3P_2_sin_ϕ[i]) ) # ξ-axis component - # F_J2_η[i] = zero_q_1 # η-axis component - F_J2_ζ[i] = Λ2j_div_r4[i]*m_c_ϕ_∂P_2[i] # ζ-axis component - - # Acceleration due to third zonal harmonic J_3 in body frame - F_J3_ξ[i] = ( Λ3j_div_r5[i]*(4P_3_sin_ϕ[i]) ) # ξ-axis component - #F_J3_η[i] = zero_q_1 # η-axis component - F_J3_ζ[i] = Λ3j_div_r5[i]*m_c_ϕ_∂P_3[i] # ζ-axis component - - # Compute accelerations due to zonal harmonics J_n, n = 2, 3 in body frame - F_J_ξ[i] = F_J2_ξ[i] # + F_J3_ξ[i] # ξ-axis component - # F_J_η[i] = zero_q_1 # η-axis component - F_J_ζ[i] = F_J2_ζ[i] # + F_J3_ζ[i] # ζ-axis component - - # Compute unit vectors (ξ, η, ζ) in inertial frame - - # ξ components in inertial frame - ξx[i] = -X[i]/r_p1d2[i] - ξy[i] = -Y[i]/r_p1d2[i] - ξz[i] = -Z[i]/r_p1d2[i] - - # Compute η = p x ξ - # Auxiliaries - ηx1[i] = M_[2,3,i]*ξz[i] - ηy1[i] = M_[3,3,i]*ξx[i] - ηz1[i] = M_[1,3,i]*ξy[i] - ηx2[i] = M_[3,3,i]*ξy[i] - ηy2[i] = M_[1,3,i]*ξz[i] - ηz2[i] = M_[2,3,i]*ξx[i] - # η components in inertial frame - ηx[i] = ηx1[i] - ηx2[i] - ηy[i] = ηy1[i] - ηy2[i] - ηz[i] = ηz1[i] - ηz2[i] - - # Compute ζ = ξ x η - ζx1[i] = ξy[i]*ηz[i] - ζy1[i] = ξz[i]*ηx[i] - ζz1[i] = ξx[i]*ηy[i] - ζx2[i] = ξz[i]*ηy[i] - ζy2[i] = ξx[i]*ηz[i] - ζz2[i] = ξy[i]*ηx[i] - # ζ components in inertial frame - ζx[i] = ζx1[i] - ζx2[i] - ζy[i] = ζy1[i] - ζy2[i] - ζz[i] = ζz1[i] - ζz2[i] - - # Compute cartesian coordinates of acceleration due to body figure in inertial frame - # Auxiliaries - F_J2_x1[i] = F_J_ξ[i]*ξx[i] - F_J2_y1[i] = F_J_ξ[i]*ξy[i] - F_J2_z1[i] = F_J_ξ[i]*ξz[i] - F_J2_x2[i] = F_J_ζ[i]*ζx[i] - F_J2_y2[i] = F_J_ζ[i]*ζy[i] - F_J2_z2[i] = F_J_ζ[i]*ζz[i] - # Acceleration due to zonal harmonics in inertial frame - F_J2_x[i] = F_J2_x1[i] + F_J2_x2[i] - F_J2_y[i] = F_J2_y1[i] + F_J2_y2[i] - F_J2_z[i] = F_J2_z1[i] + F_J2_z2[i] - end - # Velocity magnitude of the i-th body - v2[i] = ( (ui[i]^2)+(vi[i]^2) ) + (wi[i]^2) - end - # Asteroid velocity magnitude - v2[N] = ( (q[4]^2)+(q[5]^2) ) + (q[6]^2) - - for i in 1:Nm1 - # Newtonian potential of N bodies - # \sum_{i\neq l} \frac{\mu_i}{r_{il}} or - # \sum_{j\neq k} \frac{\mu_j}{r_{jk}} - temp_004 = newtonian1b_Potential[i] + newtonianNb_Potential[N] - newtonianNb_Potential[N] = temp_004 - - # Extended body accelerations - # J_n accelerations, if i-th body is flattened - if UJ_interaction[i] - # Reaction force on i-th body - temp_accX_i[i] = accX - (μ[i]*F_J2_x[i]) - accX = temp_accX_i[i] - temp_accY_i[i] = accY - (μ[i]*F_J2_y[i]) - accY = temp_accY_i[i] - temp_accZ_i[i] = accZ - (μ[i]*F_J2_z[i]) - accZ = temp_accZ_i[i] - end - end - - #= - Post-Newtonian accelerations due to Sun, Moon and planets (Mercury through Neptune) - Post-Newtonian iterative procedure setup and initialization - See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - - # First term - - # 4*\sum term inside {} - _4ϕj[N] = 4newtonianNb_Potential[N] - Threads.@threads for i in 1:10 - # 4*\sum + \sum terms inside {} - ϕi_plus_4ϕj[i] = newtonianNb_Potential_t[i] + _4ϕj[N] - # \dot{s}_j^2 + 2\dot{s}_i^2 - 4 <, > terms inside {} - sj2_plus_2si2_minus_4vivj[i] = ( (2v2[i]) - (4vi_dot_vj[i]) ) + v2[N] - # -4\sum - \sum + \dot{s}_j^2 + 2\dot{s}_i^2 - 4<, > terms inside {} - ϕs_and_vs[i] = sj2_plus_2si2_minus_4vivj[i] - ϕi_plus_4ϕj[i] - # (\mathbf{r}_i - \mathbf{r}_asteroid)\cdot\mathbf{v_i} - Xij_t_Ui = X[i]*ui[i] - Yij_t_Vi = Y[i]*vi[i] - Zij_t_Wi = Z[i]*wi[i] - Rij_dot_Vi = ( Xij_t_Ui+Yij_t_Vi ) + Zij_t_Wi - # The expression below inside the (...)^2 should have a minus sign in front of the - # numerator, but upon squaring it is eliminated, so at the end of the day, it is - # irrelevant ;) - # (\mathbf{r}_i - \mathbf{r}_asteroid)\cdot\mathbf{v_i} / r_{i, asteroid} - pn1t7 = (Rij_dot_Vi^2)/r_p2[i] - # Everything inside the {} except for the first and last terms - pn1t2_7 = ϕs_and_vs[i] - (1.5pn1t7) - # Everything inside the {} except for the last term - pn1t1_7[i] = c_p2 + pn1t2_7 - - # Last term inside the {} - pNX_t_X[i] = acceph_t[3i-2]*X[i] # X-axis component - pNY_t_Y[i] = acceph_t[3i-1]*Y[i] # Y-axis component - pNZ_t_Z[i] = acceph_t[3i ]*Z[i] # Z-axis component - - # Everything inside the {} in the first term - pn1[i] = ( pn1t1_7[i] + (0.5*( (pNX_t_X[i]+pNY_t_Y[i]) + pNZ_t_Z[i] )) ) - - # Full first term - X_t_pn1[i] = newton_acc_X[i]*pn1[i] # X-axis component - Y_t_pn1[i] = newton_acc_Y[i]*pn1[i] # Y-axis component - Z_t_pn1[i] = newton_acc_Z[i]*pn1[i] # Z-axis component - - # Full third term - pNX_t_pn3[i] = acceph_t[3i-2]*pn3[i] # X-axis component - pNY_t_pn3[i] = acceph_t[3i-1]*pn3[i] # Y-axis component - pNZ_t_pn3[i] = acceph_t[3i ]*pn3[i] # Z-axis component - end - # Temporary post-Newtonian accelerations (planets) - for i in 1:10 - termpnx = ( X_t_pn1[i] + (U_t_pn2[i]+pNX_t_pn3[i]) ) # X-axis component - sumpnx = pntempX + termpnx - pntempX = sumpnx - termpny = ( Y_t_pn1[i] + (V_t_pn2[i]+pNY_t_pn3[i]) ) # Y-axis component - sumpny = pntempY + termpny - pntempY = sumpny - termpnz = ( Z_t_pn1[i] + (W_t_pn2[i]+pNZ_t_pn3[i]) ) # Z-axis component - sumpnz = pntempZ + termpnz - pntempZ = sumpnz - end - # Compute Newtonian accelerations due to Pluto and 16 asteroid perturbers - Threads.@threads for i in 11:Nm1 - # Full first term - X_t_pn1[i] = c_p2*newton_acc_X[i] - Y_t_pn1[i] = c_p2*newton_acc_Y[i] - Z_t_pn1[i] = c_p2*newton_acc_Z[i] - end - # Temporary post-Newtonian accelerations (Pluto + 16 asteroid perturbers) - for i in 11:Nm1 - termpnx = X_t_pn1[i] # X-axis component - sumpnx = pntempX + termpnx - pntempX = sumpnx - termpny = Y_t_pn1[i] # Y-axis component - sumpny = pntempY + termpny - pntempY = sumpny - termpnz = Z_t_pn1[i] # Z-axis component - sumpnz = pntempZ + termpnz - pntempZ = sumpnz - end - # Post-Newtonian acelerations - postNewtonX = pntempX*c_m2 # X-axis component - postNewtonY = pntempY*c_m2 # Y-axis component - postNewtonZ = pntempZ*c_m2 # Z-axis component - - #= - Compute non-gravitational acceleration - =# - - # Angular momentum per unit mass - hx = (Y[1]*W[1])-(Z[1]*V[1]) # X-axis component - hy = (Z[1]*U[1])-(X[1]*W[1]) # Y-axis component - hz = (X[1]*V[1])-(Y[1]*U[1]) # Z-axis component - - # Cartesian components of transversal vector t = h × (\mathbf{r}_Sun - \mathbf{r}_asteroid) - t_x = (hz*Y[1]) - (hy*Z[1]) # Note: Y[1] = y_Sun - y_asteroid, etc. - t_y = (hx*Z[1]) - (hz*X[1]) - t_z = (hy*X[1]) - (hx*Y[1]) - # Norm of transversal vector - t_norm = sqrt( ((t_x^2)+(t_y^2))+(t_z^2) ) - # Cartesian components of transversal unit vector - t_x_unit = t_x/t_norm - t_y_unit = t_y/t_norm - t_z_unit = t_z/t_norm - - # Cartesian components of radial unit vector - r_x_unit = -(X[1]/r_p1d2[1]) - r_y_unit = -(Y[1]/r_p1d2[1]) - r_z_unit = -(Z[1]/r_p1d2[1]) - - # Evaluate non-grav acceleration (solar radiation pressure, Yarkovsky) - g_r = r_p2[1] # Distance Sun-asteroid - A2_t_g_r = q[7]/g_r # Yarkovsky effect - A1_t_g_r = q[8]/g_r # Radiation pressure - - # Non gravitational acceleration: Yarkovsky + radiation pressure - NGAx = (A2_t_g_r*t_x_unit) + (A1_t_g_r*r_x_unit) - NGAy = (A2_t_g_r*t_y_unit) + (A1_t_g_r*r_y_unit) - NGAz = (A2_t_g_r*t_z_unit) + (A1_t_g_r*r_z_unit) - - # Fill dq[4:6] with accelerations - # Post-Newton point mass + Extended body + Non-gravitational - dq[4] = ( postNewtonX + accX ) + NGAx - dq[5] = ( postNewtonY + accY ) + NGAy - dq[6] = ( postNewtonZ + accZ ) + NGAz - # Yarkovsky coefficient does not change in time - dq[7] = zero_q_1 - - nothing -end - -function RNp1BP_pN_A_J23E_J2S_eph_threads!(dq, q, params, t) - # Julian date of start time - local jd0 = params[4] - # Days since J2000.0 = 2.451545e6 - local dsj2k = t + (jd0 - JD_J2000) - # Solar system ephemeris at dsj2k - local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) - # Accelerations at dsj2k - local acceph_t = evaleph(params[2], dsj2k, q[1]) - # Newtonian potentials at dsj2k - local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) - # Type of position / velocity components - local S = eltype(q) - # Interaction matrix with flattened bodies - local UJ_interaction = params[5] - # Number of bodies, including NEA - local N = params[6] - # Number of bodies, except the asteroid - local Nm1 = N-1 - # Vector of mass parameters GM's - local μ = params[7] - - # zero(q[1]) - local zero_q_1 = auxzero(q[1]) - - #= - Point-mass accelerations - See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - - # Position of the i-th body - position of the asteroid - X = Array{S}(undef, N) # X-axis component - Y = Array{S}(undef, N) # Y-axis component - Z = Array{S}(undef, N) # Z-axis component - - # Distance between the i-th body and the asteroid - r_p2 = Array{S}(undef, N) # r_{i,asteroid}^2 - r_p1d2 = Array{S}(undef, N) # sqrt(r_p2) <-> r_{i, asteroid} - r_p3d2 = Array{S}(undef, N) # r_p2^1.5 <-> r_{i, asteroid}^3 - r_p7d2 = Array{S}(undef, N) # r_p2^3.5 <-> r_{i, asteroid}^7 - - # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 - newtonianCoeff = Array{S}(undef, N) - - # Velocity of the i-th body - ui = Array{S}(undef, N-1) # X-axis component - vi = Array{S}(undef, N-1) # Y-axis component - wi = Array{S}(undef, N-1) # Z-axis component - - # Post-Newtonian stuff - - # Velocity of the i-th body - velocity of the asteroid - U = Array{S}(undef, N) # X-axis component - V = Array{S}(undef, N) # Y-axis component - W = Array{S}(undef, N) # Z-axis component - - # 4 * Velocity of the asteroid - 3 * velocity of the i-th body - _4U_m_3X = Array{S}(undef, N) # X-axis component - _4V_m_3Y = Array{S}(undef, N) # Y-axis component - _4W_m_3Z = Array{S}(undef, N) # Z-axis component - - # v_{i,j}v_{asteroid,j} j = x, y, z - UU = Array{S}(undef, N) # v_{i,x}v_{asteroid,x} - VV = Array{S}(undef, N) # v_{i,y}v_{asteroid,y} - WW = Array{S}(undef, N) # v_{i,z}v_{asteroid,z} - - # Newtonian potential of 1 body \mu_i / r_{i, asteroid} - newtonian1b_Potential = Array{S}(undef, N) - # Newtonian potential of N bodies - # \sum_{i\neq l} \frac{\mu_i}{r_{il}} or - # \sum_{j\neq k} \frac{\mu_j}{r_{jk}} - newtonianNb_Potential = Array{S}(undef, N) - - # Newtonian coefficient * difference between two positions, i.e., - # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 - newton_acc_X = Array{S}(undef, N) # X-axis component - newton_acc_Y = Array{S}(undef, N) # Y-axis component - newton_acc_Z = Array{S}(undef, N) # Z-axis component - - # Combinations of velocities - v2 = Array{S}(undef, N) # Velocity magnitude squared ||\mathbf{v}_i||^2 - vi_dot_vj = Array{S}(undef, N) # - - # Second term without (\mathbf{v}_i - \mathbf{v}_j) - pn2 = Array{S}(undef, N) - # Full second term - U_t_pn2 = Array{S}(undef, N) # X-axis component - V_t_pn2 = Array{S}(undef, N) # Y-axis component - W_t_pn2 = Array{S}(undef, N) # Z-axis component - - # Third term without newtonian accelerations \mathbf{a}_i - pn3 = Array{S}(undef, N) - # Full third term of equation (35) - pNX_t_pn3 = Array{S}(undef, N) # X-axis component - pNY_t_pn3 = Array{S}(undef, N) # Y-axis component - pNZ_t_pn3 = Array{S}(undef, N) # Z-axis component - - # First term - _4ϕj = Array{S}(undef, N) # 4*\sum term inside {} - ϕi_plus_4ϕj = Array{S}(undef, N) # 4*\sum + \sum terms inside {} - sj2_plus_2si2_minus_4vivj = Array{S}(undef, N) # \dot{s}_j^2 + 2\dot{s}_i^2 - 4 <, > terms inside {} - ϕs_and_vs = Array{S}(undef, N) # -4\sum - \sum + \dot{s}_j^2 + 2\dot{s}_i^2 - 4<, > terms inside {} - pn1t1_7 = Array{S}(undef, N) # Everything inside the {} in the first term except for the term with accelerations (last) - # Last term inside the {} - pNX_t_X = Array{S}(undef, N) # X-axis component - pNY_t_Y = Array{S}(undef, N) # Y-axis component - pNZ_t_Z = Array{S}(undef, N) # Z-axis component - # Everything inside the {} in the first term - pn1 = Array{S}(undef, N) - # Full first term - X_t_pn1 = Array{S}(undef, N) # X-axis component - Y_t_pn1 = Array{S}(undef, N) # Y-axis component - Z_t_pn1 = Array{S}(undef, N) # Z-axis component - - # Temporary post-Newtonian accelerations - pntempX = zero_q_1 # X-axis component - pntempY = zero_q_1 # Y-axis component - pntempZ = zero_q_1 # Z-axis component - - #= - Extended body accelerations - See equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract - and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - - # J_2 acceleration auxiliaries - - # Auxiliaries to compute body-fixed frame coordinates - t31 = Array{S}(undef, N) - t32 = Array{S}(undef, N) - t33 = Array{S}(undef, N) - # z-coordinate in body-fixed frame - r_sin_ϕ = Array{S}(undef, N) - - # Trigonometric functions of latitude ϕ and longitude λ in the body-fixed coordinate system - # See equations (165)-(168) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - sin_ϕ = Array{S}(undef, N) # sin(latitude ϕ) - ϕ = Array{S}(undef, N) # Latitude ϕ - cos_ϕ = Array{S}(undef, N) # cos(latitude ϕ) - sin2_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^2 - sin3_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^3 - sin4_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^4 - - # Acceleration due to zonal harmonics in inertial frame - F_J2_x = Array{S}(undef, N) - F_J2_y = Array{S}(undef, N) - F_J2_z = Array{S}(undef, N) - # Auxiliaries to compute F_J2_i, i = x, y, z - F_J2_x1 = Array{S}(undef, N) - F_J2_y1 = Array{S}(undef, N) - F_J2_z1 = Array{S}(undef, N) - F_J2_x2 = Array{S}(undef, N) - F_J2_y2 = Array{S}(undef, N) - F_J2_z2 = Array{S}(undef, N) - - # Temporary arrays for the sum of full extended body accelerations - temp_accX_i = Array{S}(undef, N) - temp_accY_i = Array{S}(undef, N) - temp_accZ_i = Array{S}(undef, N) - - # Legendre polynomials - # See equations (176) and (177) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - P_2_sin_ϕ = Array{S}(undef, N) # Second Legendre polynomial P_2(sin ϕ) - ∂P_2_sin_ϕ = Array{S}(undef, N) # dP_2(sin ϕ)/d(sin ϕ) - P_3_sin_ϕ = Array{S}(undef, N) # Third Legendre polynomial P_3(sin ϕ) - ∂P_3_sin_ϕ = Array{S}(undef, N) # dP_3(sin ϕ)/d(sin ϕ) - # -cos ϕ P_n' - m_c_ϕ_∂P_2 = Array{S}(undef, N) # -cos ϕ P_2' - m_c_ϕ_∂P_3 = Array{S}(undef, N) # -cos ϕ P_3' - - # -J_n * R^n / r^m - # J_n: n-th zonal harmonic coefficient - # R: radius of the body - # r: distance between the body and the asteroid - Λ2j_div_r4 = Array{S}(undef, N) # J_2 * R^2 / r^4 - Λ3j_div_r5 = Array{S}(undef, N) # J_3 * R^3 / r^5 - - # Accelerations due to zonal harmonics in body frame - - # Acceleration due to zonal harmonics J_n, n = 2, 3 - F_J_ξ = Array{S}(undef, N) # ξ-axis component - F_J_η = Array{S}(undef, N) # η-axis component - F_J_ζ = Array{S}(undef, N) # ζ-axis component - # Acceleration due to second zonal harmonic J_2 - F_J2_ξ = Array{S}(undef, N) # ξ-axis component - F_J2_η = Array{S}(undef, N) # η-axis component - F_J2_ζ = Array{S}(undef, N) # ζ-axis component - # Acceleration due to third zonal harmonic J_3 - F_J3_ξ = Array{S}(undef, N) # ξ-axis component - F_J3_η = Array{S}(undef, N) # η-axis component - F_J3_ζ = Array{S}(undef, N) # ζ-axis component - - # Unit vectors (ξ, η, ζ) in inertial frame - - # ξ vector - ξx = Array{S}(undef, N) - ξy = Array{S}(undef, N) - ξz = Array{S}(undef, N) - # η vector - ηx = Array{S}(undef, N) - ηy = Array{S}(undef, N) - ηz = Array{S}(undef, N) - # Auxiliaries to compute η vector - ηx1 = Array{S}(undef, N) - ηy1 = Array{S}(undef, N) - ηz1 = Array{S}(undef, N) - ηx2 = Array{S}(undef, N) - ηy2 = Array{S}(undef, N) - ηz2 = Array{S}(undef, N) - # ζ vector - ζx = Array{S}(undef, N) - ζy = Array{S}(undef, N) - ζz = Array{S}(undef, N) - # Auxiliaries to compute ζ vector - ζx1 = Array{S}(undef, N) - ζy1 = Array{S}(undef, N) - ζz1 = Array{S}(undef, N) - ζx2 = Array{S}(undef, N) - ζy2 = Array{S}(undef, N) - ζz2 = Array{S}(undef, N) - - # Full extended-body accelerations - accX = zero_q_1 - accY = zero_q_1 - accZ = zero_q_1 - - # Rotations to and from Earth, Sun and Moon pole-oriented frames - local M_ = Array{S}(undef, 3, 3, N) - local M_ .= zero_q_1 - local M_[:, :, ea] .= t2c_jpl_de430(dsj2k)[:, :] .+ zero_q_1 - - # Fill first 3 elements of dq with velocities - dq[1] = q[4] - dq[2] = q[5] - dq[3] = q[6] - - # Newtonian potential of N bodies - newtonianNb_Potential[N] = zero_q_1 - - #= - Compute point-mass Newtonian accelerations, all bodies - See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - Threads.@threads for i in 1:Nm1 - # Velocity of the i-th body - ui[i] = ss16asteph_t[3(N-1+i)-2] # X-axis component - vi[i] = ss16asteph_t[3(N-1+i)-1] # Y-axis component - wi[i] = ss16asteph_t[3(N-1+i) ] # Z-axis component - - # Position of the i-th body - position of the asteroid - X[i] = ss16asteph_t[3i-2]-q[1] # X-axis component - Y[i] = ss16asteph_t[3i-1]-q[2] # Y-axis component - Z[i] = ss16asteph_t[3i ]-q[3] # Z-axis component - - # Velocity of the i-th body - velocity of the asteroid - U[i] = ui[i]-dq[1] # X-axis component - V[i] = vi[i]-dq[2] # Y-axis component - W[i] = wi[i]-dq[3] # Z-axis component - - # 4 * Velocity of the asteroid - 3 * velocity of the i-th body - _4U_m_3X[i] = (4dq[1]) - (3ui[i]) # X-axis component - _4V_m_3Y[i] = (4dq[2]) - (3vi[i]) # Y-axis component - _4W_m_3Z[i] = (4dq[3]) - (3wi[i]) # Z-axis component - - # Dot product inside the [] in the second term - pn2x = X[i]*_4U_m_3X[i] - pn2y = Y[i]*_4V_m_3Y[i] - pn2z = Z[i]*_4W_m_3Z[i] - - # v_{ij}v_{asteroid} j = x, y, z - UU[i] = ui[i]*dq[1] - VV[i] = vi[i]*dq[2] - WW[i] = wi[i]*dq[3] - - # - vi_dot_vj[i] = ( UU[i]+VV[i] ) + WW[i] - - # Distance between the i-th body and the asteroid - r_p2[i] = ( (X[i]^2)+(Y[i]^2) ) + (Z[i]^2) # r_{i,asteroid}^2 - r_p1d2[i] = sqrt(r_p2[i]) # sqrt(r_p2) <-> r_{i,asteroid} - r_p3d2[i] = r_p2[i]^1.5 # r_p2^1.5 <-> r_{i, asteroid}^3 - r_p7d2[i] = r_p2[i]^3.5 # r_p2^3.5 <-> r_{i, asteroid}^7 - - # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 - newtonianCoeff[i] = μ[i]/r_p3d2[i] - - # Second term without (\mathbf{v}_i - \mathbf{v}_asteroid) - pn2[i] = newtonianCoeff[i]*(( pn2x+pn2y ) + pn2z) - - # Newtonian coefficient * difference between two positions, i.e., - # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 - newton_acc_X[i] = X[i]*newtonianCoeff[i] - newton_acc_Y[i] = Y[i]*newtonianCoeff[i] - newton_acc_Z[i] = Z[i]*newtonianCoeff[i] - - # Newtonian potential of 1 body \mu_i / r_{i, asteroid} - newtonian1b_Potential[i] = μ[i]/r_p1d2[i] - # Third term without newtonian accelerations \mathbf{a}_i - pn3[i] = 3.5newtonian1b_Potential[i] - # Full second term - U_t_pn2[i] = pn2[i]*U[i] # X-axis component - V_t_pn2[i] = pn2[i]*V[i] # Y-axis component - W_t_pn2[i] = pn2[i]*W[i] # Z-axis component - - #= - Extended body accelerations - See equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract - and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - - # J_2 accelerations, if i-th body is flattened - if UJ_interaction[i] - # Rotate from inertial frame to extended-body frame - # Here we are rotating only the Z-coordinate - t31[i] = -X[i]*M_[1,3,i] - t32[i] = -Y[i]*M_[2,3,i] - t33[i] = -Z[i]*M_[3,3,i] - r_sin_ϕ[i] = (t31[i]+t32[i])+t33[i] # z-coordinate in body-fixed frame - - # Trigonometric functions of latitude ϕ and longitude λ in the body-fixed coordinate system - # See equations (165)-(168) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - - sin_ϕ[i] = r_sin_ϕ[i]/r_p1d2[i] # sin(latitude ϕ) - ϕ[i] = asin(sin_ϕ[i]) # Latitude ϕ - cos_ϕ[i] = cos(ϕ[i]) # cos(latitude ϕ) - sin2_ϕ[i] = sin_ϕ[i]^2 # sin(latitude ϕ)^2 - sin3_ϕ[i] = sin_ϕ[i]^3 # sin(latitude ϕ)^3 - - # Legendre polynomials - - # See equations (176) and (177) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - P_2_sin_ϕ[i] = 1.5sin2_ϕ[i] - 0.5 # Second Legendre polynomial P_2(sin ϕ) - ∂P_2_sin_ϕ[i] = 3sin_ϕ[i] # dP_2(sin ϕ)/d(sin ϕ) - P_3_sin_ϕ[i] = (-1.5sin_ϕ[i]) + (2.5sin3_ϕ[i]) # Third Legendre polynomial P_3(sin ϕ) - ∂P_3_sin_ϕ[i] = -1.5 + 7.5sin2_ϕ[i] # dP_3(sin ϕ)/d(sin ϕ) - - # Compute cartesian coordinates of acceleration due to body figure in body frame - - # -J_n * R^n / r^m - # J_n: n-th zonal harmonic coefficient - # R: radius of the body - # r: distance between the body and the asteroid - Λ2j_div_r4[i] = -(Λ2[i]/(r_p2[i]^2)) # J_2 * R^2 / r^4 - Λ3j_div_r5[i] = -(Λ3[i]/(r_p1d2[i]^5)) # J_3 * R^3 / r^5 - - # -cos ϕ P_n' - m_c_ϕ_∂P_2[i] = (-cos_ϕ[i])*∂P_2_sin_ϕ[i] # -cos ϕ P_2' - m_c_ϕ_∂P_3[i] = (-cos_ϕ[i])*∂P_3_sin_ϕ[i] # -cos ϕ P_3' - - # Acceleration due to second zonal harmonic J_2 in body frame - F_J2_ξ[i] = ( Λ2j_div_r4[i]*(3P_2_sin_ϕ[i]) ) # ξ-axis component - # F_J2_η[i] = zero_q_1 # η-axis component - F_J2_ζ[i] = Λ2j_div_r4[i]*m_c_ϕ_∂P_2[i] # ζ-axis component - - # Acceleration due to third zonal harmonic J_3 in body frame - F_J3_ξ[i] = ( Λ3j_div_r5[i]*(4P_3_sin_ϕ[i]) ) # ξ-axis component - #F_J3_η[i] = zero_q_1 # η-axis component - F_J3_ζ[i] = Λ3j_div_r5[i]*m_c_ϕ_∂P_3[i] # ζ-axis component - - # Compute accelerations due to zonal harmonics J_n, n = 2, 3 in body frame - F_J_ξ[i] = F_J2_ξ[i] # + F_J3_ξ[i] # ξ-axis component - # F_J_η[i] = zero_q_1 # η-axis component - F_J_ζ[i] = F_J2_ζ[i] # + F_J3_ζ[i] # ζ-axis component - - # Compute unit vectors (ξ, η, ζ) in inertial frame - - # ξ components in inertial frame - ξx[i] = -X[i]/r_p1d2[i] - ξy[i] = -Y[i]/r_p1d2[i] - ξz[i] = -Z[i]/r_p1d2[i] - - # Compute η = p x ξ - # Auxiliaries - ηx1[i] = M_[2,3,i]*ξz[i] - ηy1[i] = M_[3,3,i]*ξx[i] - ηz1[i] = M_[1,3,i]*ξy[i] - ηx2[i] = M_[3,3,i]*ξy[i] - ηy2[i] = M_[1,3,i]*ξz[i] - ηz2[i] = M_[2,3,i]*ξx[i] - # η components in inertial frame - ηx[i] = ηx1[i] - ηx2[i] - ηy[i] = ηy1[i] - ηy2[i] - ηz[i] = ηz1[i] - ηz2[i] - - # Compute ζ = ξ x η - ζx1[i] = ξy[i]*ηz[i] - ζy1[i] = ξz[i]*ηx[i] - ζz1[i] = ξx[i]*ηy[i] - ζx2[i] = ξz[i]*ηy[i] - ζy2[i] = ξx[i]*ηz[i] - ζz2[i] = ξy[i]*ηx[i] - # ζ components in inertial frame - ζx[i] = ζx1[i] - ζx2[i] - ζy[i] = ζy1[i] - ζy2[i] - ζz[i] = ζz1[i] - ζz2[i] - - # Compute cartesian coordinates of acceleration due to body figure in inertial frame - # Auxiliaries - F_J2_x1[i] = F_J_ξ[i]*ξx[i] - F_J2_y1[i] = F_J_ξ[i]*ξy[i] - F_J2_z1[i] = F_J_ξ[i]*ξz[i] - F_J2_x2[i] = F_J_ζ[i]*ζx[i] - F_J2_y2[i] = F_J_ζ[i]*ζy[i] - F_J2_z2[i] = F_J_ζ[i]*ζz[i] - # Acceleration due to zonal harmonics in inertial frame - F_J2_x[i] = F_J2_x1[i] + F_J2_x2[i] - F_J2_y[i] = F_J2_y1[i] + F_J2_y2[i] - F_J2_z[i] = F_J2_z1[i] + F_J2_z2[i] - end - # Velocity magnitude of the i-th body - v2[i] = ( (ui[i]^2)+(vi[i]^2) ) + (wi[i]^2) - end - # Asteroid velocity magnitude - v2[N] = ( (q[4]^2)+(q[5]^2) ) + (q[6]^2) - - for i in 1:Nm1 - # Newtonian potential of N bodies - # \sum_{i\neq l} \frac{\mu_i}{r_{il}} or - # \sum_{j\neq k} \frac{\mu_j}{r_{jk}} - temp_004 = newtonian1b_Potential[i] + newtonianNb_Potential[N] - newtonianNb_Potential[N] = temp_004 - - # Extended body accelerations - # J_n accelerations, if i-th body is flattened - if UJ_interaction[i] - # Reaction force on i-th body - temp_accX_i[i] = accX - (μ[i]*F_J2_x[i]) - accX = temp_accX_i[i] - temp_accY_i[i] = accY - (μ[i]*F_J2_y[i]) - accY = temp_accY_i[i] - temp_accZ_i[i] = accZ - (μ[i]*F_J2_z[i]) - accZ = temp_accZ_i[i] - end - end - - #= - Post-Newtonian accelerations due to Sun, Moon and planets (Mercury through Neptune) - Post-Newtonian iterative procedure setup and initialization - See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - - # First term - - # 4*\sum term inside {} - _4ϕj[N] = 4newtonianNb_Potential[N] - Threads.@threads for i in 1:10 - # 4*\sum + \sum terms inside {} - ϕi_plus_4ϕj[i] = newtonianNb_Potential_t[i] + _4ϕj[N] - # \dot{s}_j^2 + 2\dot{s}_i^2 - 4 <, > terms inside {} - sj2_plus_2si2_minus_4vivj[i] = ( (2v2[i]) - (4vi_dot_vj[i]) ) + v2[N] - # -4\sum - \sum + \dot{s}_j^2 + 2\dot{s}_i^2 - 4<, > terms inside {} - ϕs_and_vs[i] = sj2_plus_2si2_minus_4vivj[i] - ϕi_plus_4ϕj[i] - # (\mathbf{r}_i - \mathbf{r}_asteroid)\cdot\mathbf{v_i} - Xij_t_Ui = X[i]*ui[i] - Yij_t_Vi = Y[i]*vi[i] - Zij_t_Wi = Z[i]*wi[i] - Rij_dot_Vi = ( Xij_t_Ui+Yij_t_Vi ) + Zij_t_Wi - # The expression below inside the (...)^2 should have a minus sign in front of the - # numerator, but upon squaring it is eliminated, so at the end of the day, it is - # irrelevant ;) - # (\mathbf{r}_i - \mathbf{r}_asteroid)\cdot\mathbf{v_i} / r_{i, asteroid} - pn1t7 = (Rij_dot_Vi^2)/r_p2[i] - # Everything inside the {} except for the first and last terms - pn1t2_7 = ϕs_and_vs[i] - (1.5pn1t7) - # Everything inside the {} except for the last term - pn1t1_7[i] = c_p2 + pn1t2_7 - - # Last term inside the {} - pNX_t_X[i] = acceph_t[3i-2]*X[i] # X-axis component - pNY_t_Y[i] = acceph_t[3i-1]*Y[i] # Y-axis component - pNZ_t_Z[i] = acceph_t[3i ]*Z[i] # Z-axis component - - # Everything inside the {} in the first term - pn1[i] = ( pn1t1_7[i] + (0.5*( (pNX_t_X[i]+pNY_t_Y[i]) + pNZ_t_Z[i] )) ) - - # Full first term - X_t_pn1[i] = newton_acc_X[i]*pn1[i] # X-axis component - Y_t_pn1[i] = newton_acc_Y[i]*pn1[i] # Y-axis component - Z_t_pn1[i] = newton_acc_Z[i]*pn1[i] # Z-axis component - - # Full third term - pNX_t_pn3[i] = acceph_t[3i-2]*pn3[i] # X-axis component - pNY_t_pn3[i] = acceph_t[3i-1]*pn3[i] # Y-axis component - pNZ_t_pn3[i] = acceph_t[3i ]*pn3[i] # Z-axis component - end - # Temporary post-Newtonian accelerations (planets) - for i in 1:10 - termpnx = ( X_t_pn1[i] + (U_t_pn2[i]+pNX_t_pn3[i]) ) # X-axis component - sumpnx = pntempX + termpnx - pntempX = sumpnx - termpny = ( Y_t_pn1[i] + (V_t_pn2[i]+pNY_t_pn3[i]) ) # Y-axis component - sumpny = pntempY + termpny - pntempY = sumpny - termpnz = ( Z_t_pn1[i] + (W_t_pn2[i]+pNZ_t_pn3[i]) ) # Z-axis component - sumpnz = pntempZ + termpnz - pntempZ = sumpnz - end - # Compute Newtonian accelerations due to Pluto and 16 asteroid perturbers - Threads.@threads for i in 11:Nm1 - # Full first term - X_t_pn1[i] = c_p2*newton_acc_X[i] - Y_t_pn1[i] = c_p2*newton_acc_Y[i] - Z_t_pn1[i] = c_p2*newton_acc_Z[i] - end - # Temporary post-Newtonian accelerations (Pluto + 16 asteroid perturbers) - for i in 11:Nm1 - termpnx = X_t_pn1[i] # X-axis component - sumpnx = pntempX + termpnx - pntempX = sumpnx - termpny = Y_t_pn1[i] # Y-axis component - sumpny = pntempY + termpny - pntempY = sumpny - termpnz = Z_t_pn1[i] # Z-axis component - sumpnz = pntempZ + termpnz - pntempZ = sumpnz - end - # Post-Newtonian acelerations - postNewtonX = pntempX*c_m2 # X-axis component - postNewtonY = pntempY*c_m2 # Y-axis component - postNewtonZ = pntempZ*c_m2 # Z-axis component - - # Fill dq[4:6] with accelerations - # Post-Newton point mass + Extended body - dq[4] = postNewtonX + accX - dq[5] = postNewtonY + accY - dq[6] = postNewtonZ + accZ - - nothing -end - -@taylorize function newtonian!(dq, q, params, t) - # Julian date of start time - local jd0 = params[4] - # Days since J2000.0 = 2.451545e6 - local dsj2k = t + (jd0 - JD_J2000) - # Solar system ephemeris at dsj2k - local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) - # Type of position / velocity components - local S = eltype(q) - # Interaction matrix with flattened bodies - local UJ_interaction = params[5] - # Number of bodies, including NEA - local N = 10 # Sun, Moon and planets # params[6] - # Number of bodies, except the asteroid - local Nm1 = N-1 - # Vector of mass parameters GM's - local μ = params[7][1:10] - - # zero(q[1]) - local zero_q_1 = auxzero(q[1]) - - #= - Point-mass accelerations - See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - - # Position of the i-th body - position of the asteroid - X = Array{S}(undef, N) # X-axis component - Y = Array{S}(undef, N) # Y-axis component - Z = Array{S}(undef, N) # Z-axis component - - # Distance between the i-th body and the asteroid - r_p2 = Array{S}(undef, N) # r_{i,asteroid}^2 - r_p3d2 = Array{S}(undef, N) # r_p2^1.5 <-> r_{i, asteroid}^3 - - # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 - newtonianCoeff = Array{S}(undef, N) - - # Newtonian coefficient * difference between two positions, i.e., - # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 - newton_acc_X = Array{S}(undef, N) # X-axis component - newton_acc_Y = Array{S}(undef, N) # Y-axis component - newton_acc_Z = Array{S}(undef, N) # Z-axis component - - # Temporary arrays for the sum of full extended body accelerations - temp_accX_i = Array{S}(undef, N) - temp_accY_i = Array{S}(undef, N) - temp_accZ_i = Array{S}(undef, N) - - # Full extended-body accelerations - accX = zero_q_1 - accY = zero_q_1 - accZ = zero_q_1 - - # Fill first 3 elements of dq with velocities - dq[1] = q[4] - dq[2] = q[5] - dq[3] = q[6] - - #= - Compute point-mass Newtonian accelerations, all bodies - See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract - =# - Threads.@threads for i in 1:Nm1 - # Position of the i-th body - position of the asteroid - X[i] = ss16asteph_t[3i-2]-q[1] # X-axis component - Y[i] = ss16asteph_t[3i-1]-q[2] # Y-axis component - Z[i] = ss16asteph_t[3i ]-q[3] # Z-axis component - - # Distance between the i-th body and the asteroid - r_p2[i] = ( (X[i]^2)+(Y[i]^2) ) + (Z[i]^2) # r_{i,asteroid}^2 - r_p3d2[i] = r_p2[i]^1.5 # r_p2^1.5 <-> r_{i, asteroid}^3 - - # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 - newtonianCoeff[i] = μ[i]/r_p3d2[i] - - # Newtonian coefficient * difference between two positions, i.e., - # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 - newton_acc_X[i] = X[i]*newtonianCoeff[i] - newton_acc_Y[i] = Y[i]*newtonianCoeff[i] - newton_acc_Z[i] = Z[i]*newtonianCoeff[i] - end - - for i in 1:Nm1 - # Newtonian point-mass accelerations - temp_accX_i[i] = accX + newton_acc_X[i] - accX = temp_accX_i[i] - temp_accY_i[i] = accY + newton_acc_Y[i] - accY = temp_accY_i[i] - temp_accZ_i[i] = accZ + newton_acc_Z[i] - accZ = temp_accZ_i[i] - end - - # Fill dq[4:6] with accelerations - # Newtonian point-mass accelerations - dq[4] = accX - dq[5] = accY - dq[6] = accZ - - nothing +@doc raw""" + evaleph(eph::TaylorInterpolant, t::Taylor1, q::Taylor1{U}) where {U} + evaleph(eph::TaylorInterpolant, t::Taylor1, q::TaylorN{Taylor1{T}}) where {T<:Real} + +Evaluate planetary ephemeris with type given by `q`. +""" +function evaleph(eph::TaylorInterpolant, t::Taylor1, q::Taylor1{U}) where {U} + return map(x -> Taylor1( x.coeffs*one(q[0]) ), eph(t)) +end + +function evaleph(eph::TaylorInterpolant, t::Taylor1, q::TaylorN{Taylor1{T}}) where {T<:Real} + return one(q)*eph(t) +end + +@doc raw""" + auxzero(a::AbstractSeries) + +Return a zero of the same type as `a`. +""" +function auxzero(a::AbstractSeries) + return zero(a) +end + +@doc raw""" + auxzero(a::TaylorN{Taylor1{T}}) where {T<:Number} + +Return a `TaylorN` with zero coefficients of the same type as `a.coeffs`. +""" +function auxzero(a::TaylorN{Taylor1{T}}) where {T<:Number} + return TaylorN(zero.(a.coeffs)) +end + +# Nearth-Earth asteroid dynamical model (d=2.0) +# Bodies considered in the model are: the Sun, the eight planets, the Moon and Ceres, +# as well as the asteroid of interest as a test particle with null mass. Dynamical +# effects considered are: +# - post-Newtonian point-mass accelerations between all bodies, +# - figure-effects (oblateness) of the Earth (J2 and J3) +# - J2 effect of the Sun +# - J2 and J3 effect of the Moon +# - Kinematic model for the precession and nutation of the Earth's orientation (IAU 1976/1980 Earth orientation model) +# - Kinematic model for the Moons's orientation (Seidelmann et al., 2006) +# - Non-gravitational accelerations acting upon the asteroid +# are included (Yarkovsky effect) a_nongrav = A2*t_vec*(au/r)^d, where t_vec is the +# unit heliocentric transverse vector, au is 1 astronomical unit, r is the +# asteroid's heliocentric range, A2 is a coefficient (with units of au/day^2), +# and d = 2.0 + +@doc raw""" + RNp1BP_pN_A_J23E_J2S_ng_eph_threads!(dq, q, params, t) + +Near-Earth asteroid dynamical model (``d = 2``). Bodies considered in the model are: the Sun, +the eight planets, the Moon and Ceres, as well as the asteroid of interest as a test particle +with null mass. Dynamical effects considered are: + +- Post-Newtonian point-mass accelerations between all bodies: see equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract. + +- Figure-effects (oblateness) of the Earth (``J_2`` and ``J_3``), + +- ``J_2`` effect of the Sun and + +- ``J_2`` and ``J_3`` effect of the Moon: see equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract. + +- Kinematic model for the precession and nutation of the Earth's orientation (IAU 1976/1980 Earth orientation model): see [`PlanetaryEphemeris.c2t_jpl_de430`](@ref). + +- Kinematic model for the Moon's orientation (Seidelmann et al., 2006): see equations (14)-(15) in page 9 and equations (34)-(35) in page 16 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract. + +- Non-gravitational accelerations acting upon the asteroid: are included (Yarkovsky effect) +```math +\mathbf{a}_\text{nongrav} = A_2\left(\frac{1 \ \text{au}}{r}\right)^d*\hat{\mathbf{t}}, +``` +where ``\hat{\mathbf{t}}`` is the unit heliocentric transverse vector, ``r`` is the +asteroid's heliocentric range, ``A_2`` is a coefficient (with units of au/day^2), +and ``d = 2``. + +To improve performance, some internal loops are multi-threaded via `Threads.threads for` + +See also [`PlanetaryEphemeris.NBP_pN_A_J23E_J23M_J2S!`](@ref). +""" RNp1BP_pN_A_J23E_J2S_ng_eph_threads! + +function RNp1BP_pN_A_J23E_J2S_ng_eph_threads!(dq, q, params, t) + # Julian date of start time + local jd0 = params[4] + # Days since J2000.0 = 2.451545e6 + local dsj2k = t + (jd0 - JD_J2000) + # Solar system ephemeris at dsj2k + local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) + # Accelerations at dsj2k + local acceph_t = evaleph(params[2], dsj2k, q[1]) + # Newtonian potentials at dsj2k + local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) + # Type of position / velocity components + local S = eltype(q) + # Interaction matrix with flattened bodies + local UJ_interaction = params[5] + # Number of bodies, including NEA + local N = params[6] + # Number of bodies, except the asteroid + local Nm1 = N-1 + # Vector of mass parameters GM's + local μ = params[7] + + # zero(q[1]) + local zero_q_1 = auxzero(q[1]) + + #= + Point-mass accelerations + See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + + # Position of the i-th body - position of the asteroid + X = Array{S}(undef, N) # X-axis component + Y = Array{S}(undef, N) # Y-axis component + Z = Array{S}(undef, N) # Z-axis component + + # Distance between the i-th body and the asteroid + r_p2 = Array{S}(undef, N) # r_{i,asteroid}^2 + r_p1d2 = Array{S}(undef, N) # sqrt(r_p2) <-> r_{i, asteroid} + r_p3d2 = Array{S}(undef, N) # r_p2^1.5 <-> r_{i, asteroid}^3 + r_p7d2 = Array{S}(undef, N) # r_p2^3.5 <-> r_{i, asteroid}^7 + + # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 + newtonianCoeff = Array{S}(undef, N) + + # Velocity of the i-th body + ui = Array{S}(undef, N-1) # X-axis component + vi = Array{S}(undef, N-1) # Y-axis component + wi = Array{S}(undef, N-1) # Z-axis component + + # Post-Newtonian stuff + + # Velocity of the i-th body - velocity of the asteroid + U = Array{S}(undef, N) # X-axis component + V = Array{S}(undef, N) # Y-axis component + W = Array{S}(undef, N) # Z-axis component + + # 4 * Velocity of the asteroid - 3 * velocity of the i-th body + _4U_m_3X = Array{S}(undef, N) # X-axis component + _4V_m_3Y = Array{S}(undef, N) # Y-axis component + _4W_m_3Z = Array{S}(undef, N) # Z-axis component + + # v_{i,j}v_{asteroid,j} j = x, y, z + UU = Array{S}(undef, N) # v_{i,x}v_{asteroid,x} + VV = Array{S}(undef, N) # v_{i,y}v_{asteroid,y} + WW = Array{S}(undef, N) # v_{i,z}v_{asteroid,z} + + # Newtonian potential of 1 body \mu_i / r_{i, asteroid} + newtonian1b_Potential = Array{S}(undef, N) + # Newtonian potential of N bodies + # \sum_{i\neq l} \frac{\mu_i}{r_{il}} or + # \sum_{j\neq k} \frac{\mu_j}{r_{jk}} + newtonianNb_Potential = Array{S}(undef, N) + + # Newtonian coefficient * difference between two positions, i.e., + # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 + newton_acc_X = Array{S}(undef, N) # X-axis component + newton_acc_Y = Array{S}(undef, N) # Y-axis component + newton_acc_Z = Array{S}(undef, N) # Z-axis component + + # Combinations of velocities + v2 = Array{S}(undef, N) # Velocity magnitude squared ||\mathbf{v}_i||^2 + vi_dot_vj = Array{S}(undef, N) # + + # Second term without (\mathbf{v}_i - \mathbf{v}_j) + pn2 = Array{S}(undef, N) + # Full second term + U_t_pn2 = Array{S}(undef, N) # X-axis component + V_t_pn2 = Array{S}(undef, N) # Y-axis component + W_t_pn2 = Array{S}(undef, N) # Z-axis component + + # Third term without newtonian accelerations \mathbf{a}_i + pn3 = Array{S}(undef, N) + # Full third term of equation (35) + pNX_t_pn3 = Array{S}(undef, N) # X-axis component + pNY_t_pn3 = Array{S}(undef, N) # Y-axis component + pNZ_t_pn3 = Array{S}(undef, N) # Z-axis component + + # First term + _4ϕj = Array{S}(undef, N) # 4*\sum term inside {} + ϕi_plus_4ϕj = Array{S}(undef, N) # 4*\sum + \sum terms inside {} + sj2_plus_2si2_minus_4vivj = Array{S}(undef, N) # \dot{s}_j^2 + 2\dot{s}_i^2 - 4 <, > terms inside {} + ϕs_and_vs = Array{S}(undef, N) # -4\sum - \sum + \dot{s}_j^2 + 2\dot{s}_i^2 - 4<, > terms inside {} + pn1t1_7 = Array{S}(undef, N) # Everything inside the {} in the first term except for the term with accelerations (last) + # Last term inside the {} + pNX_t_X = Array{S}(undef, N) # X-axis component + pNY_t_Y = Array{S}(undef, N) # Y-axis component + pNZ_t_Z = Array{S}(undef, N) # Z-axis component + # Everything inside the {} in the first term + pn1 = Array{S}(undef, N) + # Full first term + X_t_pn1 = Array{S}(undef, N) # X-axis component + Y_t_pn1 = Array{S}(undef, N) # Y-axis component + Z_t_pn1 = Array{S}(undef, N) # Z-axis component + + # Temporary post-Newtonian accelerations + pntempX = zero_q_1 # X-axis component + pntempY = zero_q_1 # Y-axis component + pntempZ = zero_q_1 # Z-axis component + + #= + Extended body accelerations + See equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract + and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + + # J_2 acceleration auxiliaries + + # Auxiliaries to compute body-fixed frame coordinates + t31 = Array{S}(undef, N) + t32 = Array{S}(undef, N) + t33 = Array{S}(undef, N) + # z-coordinate in body-fixed frame + r_sin_ϕ = Array{S}(undef, N) + + # Trigonometric functions of latitude ϕ and longitude λ in the body-fixed coordinate system + # See equations (165)-(168) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + sin_ϕ = Array{S}(undef, N) # sin(latitude ϕ) + ϕ = Array{S}(undef, N) # Latitude ϕ + cos_ϕ = Array{S}(undef, N) # cos(latitude ϕ) + sin2_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^2 + sin3_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^3 + sin4_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^4 + + # Acceleration due to zonal harmonics in inertial frame + F_J2_x = Array{S}(undef, N) + F_J2_y = Array{S}(undef, N) + F_J2_z = Array{S}(undef, N) + # Auxiliaries to compute F_J2_i, i = x, y, z + F_J2_x1 = Array{S}(undef, N) + F_J2_y1 = Array{S}(undef, N) + F_J2_z1 = Array{S}(undef, N) + F_J2_x2 = Array{S}(undef, N) + F_J2_y2 = Array{S}(undef, N) + F_J2_z2 = Array{S}(undef, N) + + # Temporary arrays for the sum of full extended body accelerations + temp_accX_i = Array{S}(undef, N) + temp_accY_i = Array{S}(undef, N) + temp_accZ_i = Array{S}(undef, N) + + # Legendre polynomials + # See equations (176) and (177) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + P_2_sin_ϕ = Array{S}(undef, N) # Second Legendre polynomial P_2(sin ϕ) + ∂P_2_sin_ϕ = Array{S}(undef, N) # dP_2(sin ϕ)/d(sin ϕ) + P_3_sin_ϕ = Array{S}(undef, N) # Third Legendre polynomial P_3(sin ϕ) + ∂P_3_sin_ϕ = Array{S}(undef, N) # dP_3(sin ϕ)/d(sin ϕ) + # -cos ϕ P_n' + m_c_ϕ_∂P_2 = Array{S}(undef, N) # -cos ϕ P_2' + m_c_ϕ_∂P_3 = Array{S}(undef, N) # -cos ϕ P_3' + + # -J_n * R^n / r^m + # J_n: n-th zonal harmonic coefficient + # R: radius of the body + # r: distance between the body and the asteroid + Λ2j_div_r4 = Array{S}(undef, N) # J_2 * R^2 / r^4 + Λ3j_div_r5 = Array{S}(undef, N) # J_3 * R^3 / r^5 + + # Accelerations due to zonal harmonics in body frame + + # Acceleration due to zonal harmonics J_n, n = 2, 3 + F_J_ξ = Array{S}(undef, N) # ξ-axis component + F_J_η = Array{S}(undef, N) # η-axis component + F_J_ζ = Array{S}(undef, N) # ζ-axis component + # Acceleration due to second zonal harmonic J_2 + F_J2_ξ = Array{S}(undef, N) # ξ-axis component + F_J2_η = Array{S}(undef, N) # η-axis component + F_J2_ζ = Array{S}(undef, N) # ζ-axis component + # Acceleration due to third zonal harmonic J_3 + F_J3_ξ = Array{S}(undef, N) # ξ-axis component + F_J3_η = Array{S}(undef, N) # η-axis component + F_J3_ζ = Array{S}(undef, N) # ζ-axis component + + # Unit vectors (ξ, η, ζ) in inertial frame + + # ξ vector + ξx = Array{S}(undef, N) + ξy = Array{S}(undef, N) + ξz = Array{S}(undef, N) + # η vector + ηx = Array{S}(undef, N) + ηy = Array{S}(undef, N) + ηz = Array{S}(undef, N) + # Auxiliaries to compute η vector + ηx1 = Array{S}(undef, N) + ηy1 = Array{S}(undef, N) + ηz1 = Array{S}(undef, N) + ηx2 = Array{S}(undef, N) + ηy2 = Array{S}(undef, N) + ηz2 = Array{S}(undef, N) + # ζ vector + ζx = Array{S}(undef, N) + ζy = Array{S}(undef, N) + ζz = Array{S}(undef, N) + # Auxiliaries to compute ζ vector + ζx1 = Array{S}(undef, N) + ζy1 = Array{S}(undef, N) + ζz1 = Array{S}(undef, N) + ζx2 = Array{S}(undef, N) + ζy2 = Array{S}(undef, N) + ζz2 = Array{S}(undef, N) + + # Full extended-body accelerations + accX = zero_q_1 + accY = zero_q_1 + accZ = zero_q_1 + + # Rotations to and from Earth, Sun and Moon pole-oriented frames + local M_ = Array{S}(undef, 3, 3, N) + local M_ .= zero_q_1 + local M_[:, :, ea] .= t2c_jpl_de430(dsj2k)[:, :] .+ zero_q_1 + + # Fill first 3 elements of dq with velocities + dq[1] = q[4] + dq[2] = q[5] + dq[3] = q[6] + + # Newtonian potential of N bodies + newtonianNb_Potential[N] = zero_q_1 + + #= + Compute point-mass Newtonian accelerations, all bodies + See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + Threads.@threads for i in 1:Nm1 + # Velocity of the i-th body + ui[i] = ss16asteph_t[3(N-1+i)-2] # X-axis component + vi[i] = ss16asteph_t[3(N-1+i)-1] # Y-axis component + wi[i] = ss16asteph_t[3(N-1+i) ] # Z-axis component + + # Position of the i-th body - position of the asteroid + X[i] = ss16asteph_t[3i-2]-q[1] # X-axis component + Y[i] = ss16asteph_t[3i-1]-q[2] # Y-axis component + Z[i] = ss16asteph_t[3i ]-q[3] # Z-axis component + + # Velocity of the i-th body - velocity of the asteroid + U[i] = ui[i]-dq[1] # X-axis component + V[i] = vi[i]-dq[2] # Y-axis component + W[i] = wi[i]-dq[3] # Z-axis component + + # 4 * Velocity of the asteroid - 3 * velocity of the i-th body + _4U_m_3X[i] = (4dq[1]) - (3ui[i]) # X-axis component + _4V_m_3Y[i] = (4dq[2]) - (3vi[i]) # Y-axis component + _4W_m_3Z[i] = (4dq[3]) - (3wi[i]) # Z-axis component + + # Dot product inside the [] in the second term + pn2x = X[i]*_4U_m_3X[i] + pn2y = Y[i]*_4V_m_3Y[i] + pn2z = Z[i]*_4W_m_3Z[i] + + # v_{ij}v_{asteroid} j = x, y, z + UU[i] = ui[i]*dq[1] + VV[i] = vi[i]*dq[2] + WW[i] = wi[i]*dq[3] + + # + vi_dot_vj[i] = ( UU[i]+VV[i] ) + WW[i] + + # Distance between the i-th body and the asteroid + r_p2[i] = ( (X[i]^2)+(Y[i]^2) ) + (Z[i]^2) # r_{i,asteroid}^2 + r_p1d2[i] = sqrt(r_p2[i]) # sqrt(r_p2) <-> r_{i,asteroid} + r_p3d2[i] = r_p2[i]^1.5 # r_p2^1.5 <-> r_{i, asteroid}^3 + r_p7d2[i] = r_p2[i]^3.5 # r_p2^3.5 <-> r_{i, asteroid}^7 + + # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 + newtonianCoeff[i] = μ[i]/r_p3d2[i] + + # Second term without (\mathbf{v}_i - \mathbf{v}_asteroid) + pn2[i] = newtonianCoeff[i]*(( pn2x+pn2y ) + pn2z) + + # Newtonian coefficient * difference between two positions, i.e., + # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 + newton_acc_X[i] = X[i]*newtonianCoeff[i] + newton_acc_Y[i] = Y[i]*newtonianCoeff[i] + newton_acc_Z[i] = Z[i]*newtonianCoeff[i] + + # Newtonian potential of 1 body \mu_i / r_{i, asteroid} + newtonian1b_Potential[i] = μ[i]/r_p1d2[i] + # Third term without newtonian accelerations \mathbf{a}_i + pn3[i] = 3.5newtonian1b_Potential[i] + # Full second term + U_t_pn2[i] = pn2[i]*U[i] # X-axis component + V_t_pn2[i] = pn2[i]*V[i] # Y-axis component + W_t_pn2[i] = pn2[i]*W[i] # Z-axis component + + #= + Extended body accelerations + See equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract + and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + + # J_2 accelerations, if i-th body is flattened + if UJ_interaction[i] + # Rotate from inertial frame to extended-body frame + # Here we are rotating only the Z-coordinate + t31[i] = -X[i]*M_[1,3,i] + t32[i] = -Y[i]*M_[2,3,i] + t33[i] = -Z[i]*M_[3,3,i] + r_sin_ϕ[i] = (t31[i]+t32[i])+t33[i] # z-coordinate in body-fixed frame + + # Trigonometric functions of latitude ϕ and longitude λ in the body-fixed coordinate system + # See equations (165)-(168) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + + sin_ϕ[i] = r_sin_ϕ[i]/r_p1d2[i] # sin(latitude ϕ) + ϕ[i] = asin(sin_ϕ[i]) # Latitude ϕ + cos_ϕ[i] = cos(ϕ[i]) # cos(latitude ϕ) + sin2_ϕ[i] = sin_ϕ[i]^2 # sin(latitude ϕ)^2 + sin3_ϕ[i] = sin_ϕ[i]^3 # sin(latitude ϕ)^3 + + # Legendre polynomials + + # See equations (176) and (177) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + P_2_sin_ϕ[i] = 1.5sin2_ϕ[i] - 0.5 # Second Legendre polynomial P_2(sin ϕ) + ∂P_2_sin_ϕ[i] = 3sin_ϕ[i] # dP_2(sin ϕ)/d(sin ϕ) + P_3_sin_ϕ[i] = (-1.5sin_ϕ[i]) + (2.5sin3_ϕ[i]) # Third Legendre polynomial P_3(sin ϕ) + ∂P_3_sin_ϕ[i] = -1.5 + 7.5sin2_ϕ[i] # dP_3(sin ϕ)/d(sin ϕ) + + # Compute cartesian coordinates of acceleration due to body figure in body frame + + # -J_n * R^n / r^m + # J_n: n-th zonal harmonic coefficient + # R: radius of the body + # r: distance between the body and the asteroid + Λ2j_div_r4[i] = -(Λ2[i]/(r_p2[i]^2)) # J_2 * R^2 / r^4 + Λ3j_div_r5[i] = -(Λ3[i]/(r_p1d2[i]^5)) # J_3 * R^3 / r^5 + + # -cos ϕ P_n' + m_c_ϕ_∂P_2[i] = (-cos_ϕ[i])*∂P_2_sin_ϕ[i] # -cos ϕ P_2' + m_c_ϕ_∂P_3[i] = (-cos_ϕ[i])*∂P_3_sin_ϕ[i] # -cos ϕ P_3' + + # Acceleration due to second zonal harmonic J_2 in body frame + F_J2_ξ[i] = ( Λ2j_div_r4[i]*(3P_2_sin_ϕ[i]) ) # ξ-axis component + # F_J2_η[i] = zero_q_1 # η-axis component + F_J2_ζ[i] = Λ2j_div_r4[i]*m_c_ϕ_∂P_2[i] # ζ-axis component + + # Acceleration due to third zonal harmonic J_3 in body frame + F_J3_ξ[i] = ( Λ3j_div_r5[i]*(4P_3_sin_ϕ[i]) ) # ξ-axis component + #F_J3_η[i] = zero_q_1 # η-axis component + F_J3_ζ[i] = Λ3j_div_r5[i]*m_c_ϕ_∂P_3[i] # ζ-axis component + + # Compute accelerations due to zonal harmonics J_n, n = 2, 3 in body frame + F_J_ξ[i] = F_J2_ξ[i] # + F_J3_ξ[i] # ξ-axis component + # F_J_η[i] = zero_q_1 # η-axis component + F_J_ζ[i] = F_J2_ζ[i] # + F_J3_ζ[i] # ζ-axis component + + # Compute unit vectors (ξ, η, ζ) in inertial frame + + # ξ components in inertial frame + ξx[i] = -X[i]/r_p1d2[i] + ξy[i] = -Y[i]/r_p1d2[i] + ξz[i] = -Z[i]/r_p1d2[i] + + # Compute η = p x ξ + # Auxiliaries + ηx1[i] = M_[2,3,i]*ξz[i] + ηy1[i] = M_[3,3,i]*ξx[i] + ηz1[i] = M_[1,3,i]*ξy[i] + ηx2[i] = M_[3,3,i]*ξy[i] + ηy2[i] = M_[1,3,i]*ξz[i] + ηz2[i] = M_[2,3,i]*ξx[i] + # η components in inertial frame + ηx[i] = ηx1[i] - ηx2[i] + ηy[i] = ηy1[i] - ηy2[i] + ηz[i] = ηz1[i] - ηz2[i] + + # Compute ζ = ξ x η + ζx1[i] = ξy[i]*ηz[i] + ζy1[i] = ξz[i]*ηx[i] + ζz1[i] = ξx[i]*ηy[i] + ζx2[i] = ξz[i]*ηy[i] + ζy2[i] = ξx[i]*ηz[i] + ζz2[i] = ξy[i]*ηx[i] + # ζ components in inertial frame + ζx[i] = ζx1[i] - ζx2[i] + ζy[i] = ζy1[i] - ζy2[i] + ζz[i] = ζz1[i] - ζz2[i] + + # Compute cartesian coordinates of acceleration due to body figure in inertial frame + # Auxiliaries + F_J2_x1[i] = F_J_ξ[i]*ξx[i] + F_J2_y1[i] = F_J_ξ[i]*ξy[i] + F_J2_z1[i] = F_J_ξ[i]*ξz[i] + F_J2_x2[i] = F_J_ζ[i]*ζx[i] + F_J2_y2[i] = F_J_ζ[i]*ζy[i] + F_J2_z2[i] = F_J_ζ[i]*ζz[i] + # Acceleration due to zonal harmonics in inertial frame + F_J2_x[i] = F_J2_x1[i] + F_J2_x2[i] + F_J2_y[i] = F_J2_y1[i] + F_J2_y2[i] + F_J2_z[i] = F_J2_z1[i] + F_J2_z2[i] + end + # Velocity magnitude of the i-th body + v2[i] = ( (ui[i]^2)+(vi[i]^2) ) + (wi[i]^2) + end + # Asteroid velocity magnitude + v2[N] = ( (q[4]^2)+(q[5]^2) ) + (q[6]^2) + + for i in 1:Nm1 + # Newtonian potential of N bodies + # \sum_{i\neq l} \frac{\mu_i}{r_{il}} or + # \sum_{j\neq k} \frac{\mu_j}{r_{jk}} + temp_004 = newtonian1b_Potential[i] + newtonianNb_Potential[N] + newtonianNb_Potential[N] = temp_004 + + # Extended body accelerations + # J_n accelerations, if i-th body is flattened + if UJ_interaction[i] + # Reaction force on i-th body + temp_accX_i[i] = accX - (μ[i]*F_J2_x[i]) + accX = temp_accX_i[i] + temp_accY_i[i] = accY - (μ[i]*F_J2_y[i]) + accY = temp_accY_i[i] + temp_accZ_i[i] = accZ - (μ[i]*F_J2_z[i]) + accZ = temp_accZ_i[i] + end + end + + #= + Post-Newtonian accelerations due to Sun, Moon and planets (Mercury through Neptune) + Post-Newtonian iterative procedure setup and initialization + See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + + # First term + + # 4*\sum term inside {} + _4ϕj[N] = 4newtonianNb_Potential[N] + Threads.@threads for i in 1:10 + # 4*\sum + \sum terms inside {} + ϕi_plus_4ϕj[i] = newtonianNb_Potential_t[i] + _4ϕj[N] + # \dot{s}_j^2 + 2\dot{s}_i^2 - 4 <, > terms inside {} + sj2_plus_2si2_minus_4vivj[i] = ( (2v2[i]) - (4vi_dot_vj[i]) ) + v2[N] + # -4\sum - \sum + \dot{s}_j^2 + 2\dot{s}_i^2 - 4<, > terms inside {} + ϕs_and_vs[i] = sj2_plus_2si2_minus_4vivj[i] - ϕi_plus_4ϕj[i] + # (\mathbf{r}_i - \mathbf{r}_asteroid)\cdot\mathbf{v_i} + Xij_t_Ui = X[i]*ui[i] + Yij_t_Vi = Y[i]*vi[i] + Zij_t_Wi = Z[i]*wi[i] + Rij_dot_Vi = ( Xij_t_Ui+Yij_t_Vi ) + Zij_t_Wi + # The expression below inside the (...)^2 should have a minus sign in front of the + # numerator, but upon squaring it is eliminated, so at the end of the day, it is + # irrelevant ;) + # (\mathbf{r}_i - \mathbf{r}_asteroid)\cdot\mathbf{v_i} / r_{i, asteroid} + pn1t7 = (Rij_dot_Vi^2)/r_p2[i] + # Everything inside the {} except for the first and last terms + pn1t2_7 = ϕs_and_vs[i] - (1.5pn1t7) + # Everything inside the {} except for the last term + pn1t1_7[i] = c_p2 + pn1t2_7 + + # Last term inside the {} + pNX_t_X[i] = acceph_t[3i-2]*X[i] # X-axis component + pNY_t_Y[i] = acceph_t[3i-1]*Y[i] # Y-axis component + pNZ_t_Z[i] = acceph_t[3i ]*Z[i] # Z-axis component + + # Everything inside the {} in the first term + pn1[i] = ( pn1t1_7[i] + (0.5*( (pNX_t_X[i]+pNY_t_Y[i]) + pNZ_t_Z[i] )) ) + + # Full first term + X_t_pn1[i] = newton_acc_X[i]*pn1[i] # X-axis component + Y_t_pn1[i] = newton_acc_Y[i]*pn1[i] # Y-axis component + Z_t_pn1[i] = newton_acc_Z[i]*pn1[i] # Z-axis component + + # Full third term + pNX_t_pn3[i] = acceph_t[3i-2]*pn3[i] # X-axis component + pNY_t_pn3[i] = acceph_t[3i-1]*pn3[i] # Y-axis component + pNZ_t_pn3[i] = acceph_t[3i ]*pn3[i] # Z-axis component + end + # Temporary post-Newtonian accelerations (planets) + for i in 1:10 + termpnx = ( X_t_pn1[i] + (U_t_pn2[i]+pNX_t_pn3[i]) ) # X-axis component + sumpnx = pntempX + termpnx + pntempX = sumpnx + termpny = ( Y_t_pn1[i] + (V_t_pn2[i]+pNY_t_pn3[i]) ) # Y-axis component + sumpny = pntempY + termpny + pntempY = sumpny + termpnz = ( Z_t_pn1[i] + (W_t_pn2[i]+pNZ_t_pn3[i]) ) # Z-axis component + sumpnz = pntempZ + termpnz + pntempZ = sumpnz + end + # Compute Newtonian accelerations due to Pluto and 16 asteroid perturbers + Threads.@threads for i in 11:Nm1 + # Full first term + X_t_pn1[i] = c_p2*newton_acc_X[i] + Y_t_pn1[i] = c_p2*newton_acc_Y[i] + Z_t_pn1[i] = c_p2*newton_acc_Z[i] + end + # Temporary post-Newtonian accelerations (Pluto + 16 asteroid perturbers) + for i in 11:Nm1 + termpnx = X_t_pn1[i] # X-axis component + sumpnx = pntempX + termpnx + pntempX = sumpnx + termpny = Y_t_pn1[i] # Y-axis component + sumpny = pntempY + termpny + pntempY = sumpny + termpnz = Z_t_pn1[i] # Z-axis component + sumpnz = pntempZ + termpnz + pntempZ = sumpnz + end + # Post-Newtonian acelerations + postNewtonX = pntempX*c_m2 # X-axis component + postNewtonY = pntempY*c_m2 # Y-axis component + postNewtonZ = pntempZ*c_m2 # Z-axis component + + #= + Compute non-gravitational acceleration + =# + + # Angular momentum per unit mass + hx = (Y[1]*W[1])-(Z[1]*V[1]) # X-axis component + hy = (Z[1]*U[1])-(X[1]*W[1]) # Y-axis component + hz = (X[1]*V[1])-(Y[1]*U[1]) # Z-axis component + + # Cartesian components of transversal vector t = h × (\mathbf{r}_Sun - \mathbf{r}_asteroid) + t_x = (hz*Y[1]) - (hy*Z[1]) # Note: Y[1] = y_Sun - y_asteroid, etc. + t_y = (hx*Z[1]) - (hz*X[1]) + t_z = (hy*X[1]) - (hx*Y[1]) + # Norm of transversal vector + t_norm = sqrt( ((t_x^2)+(t_y^2))+(t_z^2) ) + # Cartesian components of transversal unit vector + t_x_unit = t_x/t_norm + t_y_unit = t_y/t_norm + t_z_unit = t_z/t_norm + + # Cartesian components of radial unit vector + r_x_unit = -(X[1]/r_p1d2[1]) + r_y_unit = -(Y[1]/r_p1d2[1]) + r_z_unit = -(Z[1]/r_p1d2[1]) + + # Evaluate non-grav acceleration (solar radiation pressure, Yarkovsky) + g_r = r_p2[1] # Distance Sun-asteroid + A2_t_g_r = q[7]/g_r # Yarkovsky effect + A1_t_g_r = q[8]/g_r # Radiation pressure + + # Non gravitational acceleration: Yarkovsky + radiation pressure + NGAx = (A2_t_g_r*t_x_unit) + (A1_t_g_r*r_x_unit) + NGAy = (A2_t_g_r*t_y_unit) + (A1_t_g_r*r_y_unit) + NGAz = (A2_t_g_r*t_z_unit) + (A1_t_g_r*r_z_unit) + + # Fill dq[4:6] with accelerations + # Post-Newton point mass + Extended body + Non-gravitational + dq[4] = ( postNewtonX + accX ) + NGAx + dq[5] = ( postNewtonY + accY ) + NGAy + dq[6] = ( postNewtonZ + accZ ) + NGAz + # Yarkovsky coefficient does not change in time + dq[7] = zero_q_1 + + nothing +end + +function RNp1BP_pN_A_J23E_J2S_eph_threads!(dq, q, params, t) + # Julian date of start time + local jd0 = params[4] + # Days since J2000.0 = 2.451545e6 + local dsj2k = t + (jd0 - JD_J2000) + # Solar system ephemeris at dsj2k + local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) + # Accelerations at dsj2k + local acceph_t = evaleph(params[2], dsj2k, q[1]) + # Newtonian potentials at dsj2k + local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) + # Type of position / velocity components + local S = eltype(q) + # Interaction matrix with flattened bodies + local UJ_interaction = params[5] + # Number of bodies, including NEA + local N = params[6] + # Number of bodies, except the asteroid + local Nm1 = N-1 + # Vector of mass parameters GM's + local μ = params[7] + + # zero(q[1]) + local zero_q_1 = auxzero(q[1]) + + #= + Point-mass accelerations + See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + + # Position of the i-th body - position of the asteroid + X = Array{S}(undef, N) # X-axis component + Y = Array{S}(undef, N) # Y-axis component + Z = Array{S}(undef, N) # Z-axis component + + # Distance between the i-th body and the asteroid + r_p2 = Array{S}(undef, N) # r_{i,asteroid}^2 + r_p1d2 = Array{S}(undef, N) # sqrt(r_p2) <-> r_{i, asteroid} + r_p3d2 = Array{S}(undef, N) # r_p2^1.5 <-> r_{i, asteroid}^3 + r_p7d2 = Array{S}(undef, N) # r_p2^3.5 <-> r_{i, asteroid}^7 + + # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 + newtonianCoeff = Array{S}(undef, N) + + # Velocity of the i-th body + ui = Array{S}(undef, N-1) # X-axis component + vi = Array{S}(undef, N-1) # Y-axis component + wi = Array{S}(undef, N-1) # Z-axis component + + # Post-Newtonian stuff + + # Velocity of the i-th body - velocity of the asteroid + U = Array{S}(undef, N) # X-axis component + V = Array{S}(undef, N) # Y-axis component + W = Array{S}(undef, N) # Z-axis component + + # 4 * Velocity of the asteroid - 3 * velocity of the i-th body + _4U_m_3X = Array{S}(undef, N) # X-axis component + _4V_m_3Y = Array{S}(undef, N) # Y-axis component + _4W_m_3Z = Array{S}(undef, N) # Z-axis component + + # v_{i,j}v_{asteroid,j} j = x, y, z + UU = Array{S}(undef, N) # v_{i,x}v_{asteroid,x} + VV = Array{S}(undef, N) # v_{i,y}v_{asteroid,y} + WW = Array{S}(undef, N) # v_{i,z}v_{asteroid,z} + + # Newtonian potential of 1 body \mu_i / r_{i, asteroid} + newtonian1b_Potential = Array{S}(undef, N) + # Newtonian potential of N bodies + # \sum_{i\neq l} \frac{\mu_i}{r_{il}} or + # \sum_{j\neq k} \frac{\mu_j}{r_{jk}} + newtonianNb_Potential = Array{S}(undef, N) + + # Newtonian coefficient * difference between two positions, i.e., + # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 + newton_acc_X = Array{S}(undef, N) # X-axis component + newton_acc_Y = Array{S}(undef, N) # Y-axis component + newton_acc_Z = Array{S}(undef, N) # Z-axis component + + # Combinations of velocities + v2 = Array{S}(undef, N) # Velocity magnitude squared ||\mathbf{v}_i||^2 + vi_dot_vj = Array{S}(undef, N) # + + # Second term without (\mathbf{v}_i - \mathbf{v}_j) + pn2 = Array{S}(undef, N) + # Full second term + U_t_pn2 = Array{S}(undef, N) # X-axis component + V_t_pn2 = Array{S}(undef, N) # Y-axis component + W_t_pn2 = Array{S}(undef, N) # Z-axis component + + # Third term without newtonian accelerations \mathbf{a}_i + pn3 = Array{S}(undef, N) + # Full third term of equation (35) + pNX_t_pn3 = Array{S}(undef, N) # X-axis component + pNY_t_pn3 = Array{S}(undef, N) # Y-axis component + pNZ_t_pn3 = Array{S}(undef, N) # Z-axis component + + # First term + _4ϕj = Array{S}(undef, N) # 4*\sum term inside {} + ϕi_plus_4ϕj = Array{S}(undef, N) # 4*\sum + \sum terms inside {} + sj2_plus_2si2_minus_4vivj = Array{S}(undef, N) # \dot{s}_j^2 + 2\dot{s}_i^2 - 4 <, > terms inside {} + ϕs_and_vs = Array{S}(undef, N) # -4\sum - \sum + \dot{s}_j^2 + 2\dot{s}_i^2 - 4<, > terms inside {} + pn1t1_7 = Array{S}(undef, N) # Everything inside the {} in the first term except for the term with accelerations (last) + # Last term inside the {} + pNX_t_X = Array{S}(undef, N) # X-axis component + pNY_t_Y = Array{S}(undef, N) # Y-axis component + pNZ_t_Z = Array{S}(undef, N) # Z-axis component + # Everything inside the {} in the first term + pn1 = Array{S}(undef, N) + # Full first term + X_t_pn1 = Array{S}(undef, N) # X-axis component + Y_t_pn1 = Array{S}(undef, N) # Y-axis component + Z_t_pn1 = Array{S}(undef, N) # Z-axis component + + # Temporary post-Newtonian accelerations + pntempX = zero_q_1 # X-axis component + pntempY = zero_q_1 # Y-axis component + pntempZ = zero_q_1 # Z-axis component + + #= + Extended body accelerations + See equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract + and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + + # J_2 acceleration auxiliaries + + # Auxiliaries to compute body-fixed frame coordinates + t31 = Array{S}(undef, N) + t32 = Array{S}(undef, N) + t33 = Array{S}(undef, N) + # z-coordinate in body-fixed frame + r_sin_ϕ = Array{S}(undef, N) + + # Trigonometric functions of latitude ϕ and longitude λ in the body-fixed coordinate system + # See equations (165)-(168) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + sin_ϕ = Array{S}(undef, N) # sin(latitude ϕ) + ϕ = Array{S}(undef, N) # Latitude ϕ + cos_ϕ = Array{S}(undef, N) # cos(latitude ϕ) + sin2_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^2 + sin3_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^3 + sin4_ϕ = Array{S}(undef, N) # sin(latitude ϕ)^4 + + # Acceleration due to zonal harmonics in inertial frame + F_J2_x = Array{S}(undef, N) + F_J2_y = Array{S}(undef, N) + F_J2_z = Array{S}(undef, N) + # Auxiliaries to compute F_J2_i, i = x, y, z + F_J2_x1 = Array{S}(undef, N) + F_J2_y1 = Array{S}(undef, N) + F_J2_z1 = Array{S}(undef, N) + F_J2_x2 = Array{S}(undef, N) + F_J2_y2 = Array{S}(undef, N) + F_J2_z2 = Array{S}(undef, N) + + # Temporary arrays for the sum of full extended body accelerations + temp_accX_i = Array{S}(undef, N) + temp_accY_i = Array{S}(undef, N) + temp_accZ_i = Array{S}(undef, N) + + # Legendre polynomials + # See equations (176) and (177) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + P_2_sin_ϕ = Array{S}(undef, N) # Second Legendre polynomial P_2(sin ϕ) + ∂P_2_sin_ϕ = Array{S}(undef, N) # dP_2(sin ϕ)/d(sin ϕ) + P_3_sin_ϕ = Array{S}(undef, N) # Third Legendre polynomial P_3(sin ϕ) + ∂P_3_sin_ϕ = Array{S}(undef, N) # dP_3(sin ϕ)/d(sin ϕ) + # -cos ϕ P_n' + m_c_ϕ_∂P_2 = Array{S}(undef, N) # -cos ϕ P_2' + m_c_ϕ_∂P_3 = Array{S}(undef, N) # -cos ϕ P_3' + + # -J_n * R^n / r^m + # J_n: n-th zonal harmonic coefficient + # R: radius of the body + # r: distance between the body and the asteroid + Λ2j_div_r4 = Array{S}(undef, N) # J_2 * R^2 / r^4 + Λ3j_div_r5 = Array{S}(undef, N) # J_3 * R^3 / r^5 + + # Accelerations due to zonal harmonics in body frame + + # Acceleration due to zonal harmonics J_n, n = 2, 3 + F_J_ξ = Array{S}(undef, N) # ξ-axis component + F_J_η = Array{S}(undef, N) # η-axis component + F_J_ζ = Array{S}(undef, N) # ζ-axis component + # Acceleration due to second zonal harmonic J_2 + F_J2_ξ = Array{S}(undef, N) # ξ-axis component + F_J2_η = Array{S}(undef, N) # η-axis component + F_J2_ζ = Array{S}(undef, N) # ζ-axis component + # Acceleration due to third zonal harmonic J_3 + F_J3_ξ = Array{S}(undef, N) # ξ-axis component + F_J3_η = Array{S}(undef, N) # η-axis component + F_J3_ζ = Array{S}(undef, N) # ζ-axis component + + # Unit vectors (ξ, η, ζ) in inertial frame + + # ξ vector + ξx = Array{S}(undef, N) + ξy = Array{S}(undef, N) + ξz = Array{S}(undef, N) + # η vector + ηx = Array{S}(undef, N) + ηy = Array{S}(undef, N) + ηz = Array{S}(undef, N) + # Auxiliaries to compute η vector + ηx1 = Array{S}(undef, N) + ηy1 = Array{S}(undef, N) + ηz1 = Array{S}(undef, N) + ηx2 = Array{S}(undef, N) + ηy2 = Array{S}(undef, N) + ηz2 = Array{S}(undef, N) + # ζ vector + ζx = Array{S}(undef, N) + ζy = Array{S}(undef, N) + ζz = Array{S}(undef, N) + # Auxiliaries to compute ζ vector + ζx1 = Array{S}(undef, N) + ζy1 = Array{S}(undef, N) + ζz1 = Array{S}(undef, N) + ζx2 = Array{S}(undef, N) + ζy2 = Array{S}(undef, N) + ζz2 = Array{S}(undef, N) + + # Full extended-body accelerations + accX = zero_q_1 + accY = zero_q_1 + accZ = zero_q_1 + + # Rotations to and from Earth, Sun and Moon pole-oriented frames + local M_ = Array{S}(undef, 3, 3, N) + local M_ .= zero_q_1 + local M_[:, :, ea] .= t2c_jpl_de430(dsj2k)[:, :] .+ zero_q_1 + + # Fill first 3 elements of dq with velocities + dq[1] = q[4] + dq[2] = q[5] + dq[3] = q[6] + + # Newtonian potential of N bodies + newtonianNb_Potential[N] = zero_q_1 + + #= + Compute point-mass Newtonian accelerations, all bodies + See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + Threads.@threads for i in 1:Nm1 + # Velocity of the i-th body + ui[i] = ss16asteph_t[3(N-1+i)-2] # X-axis component + vi[i] = ss16asteph_t[3(N-1+i)-1] # Y-axis component + wi[i] = ss16asteph_t[3(N-1+i) ] # Z-axis component + + # Position of the i-th body - position of the asteroid + X[i] = ss16asteph_t[3i-2]-q[1] # X-axis component + Y[i] = ss16asteph_t[3i-1]-q[2] # Y-axis component + Z[i] = ss16asteph_t[3i ]-q[3] # Z-axis component + + # Velocity of the i-th body - velocity of the asteroid + U[i] = ui[i]-dq[1] # X-axis component + V[i] = vi[i]-dq[2] # Y-axis component + W[i] = wi[i]-dq[3] # Z-axis component + + # 4 * Velocity of the asteroid - 3 * velocity of the i-th body + _4U_m_3X[i] = (4dq[1]) - (3ui[i]) # X-axis component + _4V_m_3Y[i] = (4dq[2]) - (3vi[i]) # Y-axis component + _4W_m_3Z[i] = (4dq[3]) - (3wi[i]) # Z-axis component + + # Dot product inside the [] in the second term + pn2x = X[i]*_4U_m_3X[i] + pn2y = Y[i]*_4V_m_3Y[i] + pn2z = Z[i]*_4W_m_3Z[i] + + # v_{ij}v_{asteroid} j = x, y, z + UU[i] = ui[i]*dq[1] + VV[i] = vi[i]*dq[2] + WW[i] = wi[i]*dq[3] + + # + vi_dot_vj[i] = ( UU[i]+VV[i] ) + WW[i] + + # Distance between the i-th body and the asteroid + r_p2[i] = ( (X[i]^2)+(Y[i]^2) ) + (Z[i]^2) # r_{i,asteroid}^2 + r_p1d2[i] = sqrt(r_p2[i]) # sqrt(r_p2) <-> r_{i,asteroid} + r_p3d2[i] = r_p2[i]^1.5 # r_p2^1.5 <-> r_{i, asteroid}^3 + r_p7d2[i] = r_p2[i]^3.5 # r_p2^3.5 <-> r_{i, asteroid}^7 + + # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 + newtonianCoeff[i] = μ[i]/r_p3d2[i] + + # Second term without (\mathbf{v}_i - \mathbf{v}_asteroid) + pn2[i] = newtonianCoeff[i]*(( pn2x+pn2y ) + pn2z) + + # Newtonian coefficient * difference between two positions, i.e., + # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 + newton_acc_X[i] = X[i]*newtonianCoeff[i] + newton_acc_Y[i] = Y[i]*newtonianCoeff[i] + newton_acc_Z[i] = Z[i]*newtonianCoeff[i] + + # Newtonian potential of 1 body \mu_i / r_{i, asteroid} + newtonian1b_Potential[i] = μ[i]/r_p1d2[i] + # Third term without newtonian accelerations \mathbf{a}_i + pn3[i] = 3.5newtonian1b_Potential[i] + # Full second term + U_t_pn2[i] = pn2[i]*U[i] # X-axis component + V_t_pn2[i] = pn2[i]*V[i] # Y-axis component + W_t_pn2[i] = pn2[i]*W[i] # Z-axis component + + #= + Extended body accelerations + See equation (28) in page 13 of https://ui.adsabs.harvard.edu/abs/2014IPNPR.196C...1F%2F/abstract + and equations (173) and (174) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + + # J_2 accelerations, if i-th body is flattened + if UJ_interaction[i] + # Rotate from inertial frame to extended-body frame + # Here we are rotating only the Z-coordinate + t31[i] = -X[i]*M_[1,3,i] + t32[i] = -Y[i]*M_[2,3,i] + t33[i] = -Z[i]*M_[3,3,i] + r_sin_ϕ[i] = (t31[i]+t32[i])+t33[i] # z-coordinate in body-fixed frame + + # Trigonometric functions of latitude ϕ and longitude λ in the body-fixed coordinate system + # See equations (165)-(168) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + + sin_ϕ[i] = r_sin_ϕ[i]/r_p1d2[i] # sin(latitude ϕ) + ϕ[i] = asin(sin_ϕ[i]) # Latitude ϕ + cos_ϕ[i] = cos(ϕ[i]) # cos(latitude ϕ) + sin2_ϕ[i] = sin_ϕ[i]^2 # sin(latitude ϕ)^2 + sin3_ϕ[i] = sin_ϕ[i]^3 # sin(latitude ϕ)^3 + + # Legendre polynomials + + # See equations (176) and (177) in page 33 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + P_2_sin_ϕ[i] = 1.5sin2_ϕ[i] - 0.5 # Second Legendre polynomial P_2(sin ϕ) + ∂P_2_sin_ϕ[i] = 3sin_ϕ[i] # dP_2(sin ϕ)/d(sin ϕ) + P_3_sin_ϕ[i] = (-1.5sin_ϕ[i]) + (2.5sin3_ϕ[i]) # Third Legendre polynomial P_3(sin ϕ) + ∂P_3_sin_ϕ[i] = -1.5 + 7.5sin2_ϕ[i] # dP_3(sin ϕ)/d(sin ϕ) + + # Compute cartesian coordinates of acceleration due to body figure in body frame + + # -J_n * R^n / r^m + # J_n: n-th zonal harmonic coefficient + # R: radius of the body + # r: distance between the body and the asteroid + Λ2j_div_r4[i] = -(Λ2[i]/(r_p2[i]^2)) # J_2 * R^2 / r^4 + Λ3j_div_r5[i] = -(Λ3[i]/(r_p1d2[i]^5)) # J_3 * R^3 / r^5 + + # -cos ϕ P_n' + m_c_ϕ_∂P_2[i] = (-cos_ϕ[i])*∂P_2_sin_ϕ[i] # -cos ϕ P_2' + m_c_ϕ_∂P_3[i] = (-cos_ϕ[i])*∂P_3_sin_ϕ[i] # -cos ϕ P_3' + + # Acceleration due to second zonal harmonic J_2 in body frame + F_J2_ξ[i] = ( Λ2j_div_r4[i]*(3P_2_sin_ϕ[i]) ) # ξ-axis component + # F_J2_η[i] = zero_q_1 # η-axis component + F_J2_ζ[i] = Λ2j_div_r4[i]*m_c_ϕ_∂P_2[i] # ζ-axis component + + # Acceleration due to third zonal harmonic J_3 in body frame + F_J3_ξ[i] = ( Λ3j_div_r5[i]*(4P_3_sin_ϕ[i]) ) # ξ-axis component + #F_J3_η[i] = zero_q_1 # η-axis component + F_J3_ζ[i] = Λ3j_div_r5[i]*m_c_ϕ_∂P_3[i] # ζ-axis component + + # Compute accelerations due to zonal harmonics J_n, n = 2, 3 in body frame + F_J_ξ[i] = F_J2_ξ[i] # + F_J3_ξ[i] # ξ-axis component + # F_J_η[i] = zero_q_1 # η-axis component + F_J_ζ[i] = F_J2_ζ[i] # + F_J3_ζ[i] # ζ-axis component + + # Compute unit vectors (ξ, η, ζ) in inertial frame + + # ξ components in inertial frame + ξx[i] = -X[i]/r_p1d2[i] + ξy[i] = -Y[i]/r_p1d2[i] + ξz[i] = -Z[i]/r_p1d2[i] + + # Compute η = p x ξ + # Auxiliaries + ηx1[i] = M_[2,3,i]*ξz[i] + ηy1[i] = M_[3,3,i]*ξx[i] + ηz1[i] = M_[1,3,i]*ξy[i] + ηx2[i] = M_[3,3,i]*ξy[i] + ηy2[i] = M_[1,3,i]*ξz[i] + ηz2[i] = M_[2,3,i]*ξx[i] + # η components in inertial frame + ηx[i] = ηx1[i] - ηx2[i] + ηy[i] = ηy1[i] - ηy2[i] + ηz[i] = ηz1[i] - ηz2[i] + + # Compute ζ = ξ x η + ζx1[i] = ξy[i]*ηz[i] + ζy1[i] = ξz[i]*ηx[i] + ζz1[i] = ξx[i]*ηy[i] + ζx2[i] = ξz[i]*ηy[i] + ζy2[i] = ξx[i]*ηz[i] + ζz2[i] = ξy[i]*ηx[i] + # ζ components in inertial frame + ζx[i] = ζx1[i] - ζx2[i] + ζy[i] = ζy1[i] - ζy2[i] + ζz[i] = ζz1[i] - ζz2[i] + + # Compute cartesian coordinates of acceleration due to body figure in inertial frame + # Auxiliaries + F_J2_x1[i] = F_J_ξ[i]*ξx[i] + F_J2_y1[i] = F_J_ξ[i]*ξy[i] + F_J2_z1[i] = F_J_ξ[i]*ξz[i] + F_J2_x2[i] = F_J_ζ[i]*ζx[i] + F_J2_y2[i] = F_J_ζ[i]*ζy[i] + F_J2_z2[i] = F_J_ζ[i]*ζz[i] + # Acceleration due to zonal harmonics in inertial frame + F_J2_x[i] = F_J2_x1[i] + F_J2_x2[i] + F_J2_y[i] = F_J2_y1[i] + F_J2_y2[i] + F_J2_z[i] = F_J2_z1[i] + F_J2_z2[i] + end + # Velocity magnitude of the i-th body + v2[i] = ( (ui[i]^2)+(vi[i]^2) ) + (wi[i]^2) + end + # Asteroid velocity magnitude + v2[N] = ( (q[4]^2)+(q[5]^2) ) + (q[6]^2) + + for i in 1:Nm1 + # Newtonian potential of N bodies + # \sum_{i\neq l} \frac{\mu_i}{r_{il}} or + # \sum_{j\neq k} \frac{\mu_j}{r_{jk}} + temp_004 = newtonian1b_Potential[i] + newtonianNb_Potential[N] + newtonianNb_Potential[N] = temp_004 + + # Extended body accelerations + # J_n accelerations, if i-th body is flattened + if UJ_interaction[i] + # Reaction force on i-th body + temp_accX_i[i] = accX - (μ[i]*F_J2_x[i]) + accX = temp_accX_i[i] + temp_accY_i[i] = accY - (μ[i]*F_J2_y[i]) + accY = temp_accY_i[i] + temp_accZ_i[i] = accZ - (μ[i]*F_J2_z[i]) + accZ = temp_accZ_i[i] + end + end + + #= + Post-Newtonian accelerations due to Sun, Moon and planets (Mercury through Neptune) + Post-Newtonian iterative procedure setup and initialization + See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + + # First term + + # 4*\sum term inside {} + _4ϕj[N] = 4newtonianNb_Potential[N] + Threads.@threads for i in 1:10 + # 4*\sum + \sum terms inside {} + ϕi_plus_4ϕj[i] = newtonianNb_Potential_t[i] + _4ϕj[N] + # \dot{s}_j^2 + 2\dot{s}_i^2 - 4 <, > terms inside {} + sj2_plus_2si2_minus_4vivj[i] = ( (2v2[i]) - (4vi_dot_vj[i]) ) + v2[N] + # -4\sum - \sum + \dot{s}_j^2 + 2\dot{s}_i^2 - 4<, > terms inside {} + ϕs_and_vs[i] = sj2_plus_2si2_minus_4vivj[i] - ϕi_plus_4ϕj[i] + # (\mathbf{r}_i - \mathbf{r}_asteroid)\cdot\mathbf{v_i} + Xij_t_Ui = X[i]*ui[i] + Yij_t_Vi = Y[i]*vi[i] + Zij_t_Wi = Z[i]*wi[i] + Rij_dot_Vi = ( Xij_t_Ui+Yij_t_Vi ) + Zij_t_Wi + # The expression below inside the (...)^2 should have a minus sign in front of the + # numerator, but upon squaring it is eliminated, so at the end of the day, it is + # irrelevant ;) + # (\mathbf{r}_i - \mathbf{r}_asteroid)\cdot\mathbf{v_i} / r_{i, asteroid} + pn1t7 = (Rij_dot_Vi^2)/r_p2[i] + # Everything inside the {} except for the first and last terms + pn1t2_7 = ϕs_and_vs[i] - (1.5pn1t7) + # Everything inside the {} except for the last term + pn1t1_7[i] = c_p2 + pn1t2_7 + + # Last term inside the {} + pNX_t_X[i] = acceph_t[3i-2]*X[i] # X-axis component + pNY_t_Y[i] = acceph_t[3i-1]*Y[i] # Y-axis component + pNZ_t_Z[i] = acceph_t[3i ]*Z[i] # Z-axis component + + # Everything inside the {} in the first term + pn1[i] = ( pn1t1_7[i] + (0.5*( (pNX_t_X[i]+pNY_t_Y[i]) + pNZ_t_Z[i] )) ) + + # Full first term + X_t_pn1[i] = newton_acc_X[i]*pn1[i] # X-axis component + Y_t_pn1[i] = newton_acc_Y[i]*pn1[i] # Y-axis component + Z_t_pn1[i] = newton_acc_Z[i]*pn1[i] # Z-axis component + + # Full third term + pNX_t_pn3[i] = acceph_t[3i-2]*pn3[i] # X-axis component + pNY_t_pn3[i] = acceph_t[3i-1]*pn3[i] # Y-axis component + pNZ_t_pn3[i] = acceph_t[3i ]*pn3[i] # Z-axis component + end + # Temporary post-Newtonian accelerations (planets) + for i in 1:10 + termpnx = ( X_t_pn1[i] + (U_t_pn2[i]+pNX_t_pn3[i]) ) # X-axis component + sumpnx = pntempX + termpnx + pntempX = sumpnx + termpny = ( Y_t_pn1[i] + (V_t_pn2[i]+pNY_t_pn3[i]) ) # Y-axis component + sumpny = pntempY + termpny + pntempY = sumpny + termpnz = ( Z_t_pn1[i] + (W_t_pn2[i]+pNZ_t_pn3[i]) ) # Z-axis component + sumpnz = pntempZ + termpnz + pntempZ = sumpnz + end + # Compute Newtonian accelerations due to Pluto and 16 asteroid perturbers + Threads.@threads for i in 11:Nm1 + # Full first term + X_t_pn1[i] = c_p2*newton_acc_X[i] + Y_t_pn1[i] = c_p2*newton_acc_Y[i] + Z_t_pn1[i] = c_p2*newton_acc_Z[i] + end + # Temporary post-Newtonian accelerations (Pluto + 16 asteroid perturbers) + for i in 11:Nm1 + termpnx = X_t_pn1[i] # X-axis component + sumpnx = pntempX + termpnx + pntempX = sumpnx + termpny = Y_t_pn1[i] # Y-axis component + sumpny = pntempY + termpny + pntempY = sumpny + termpnz = Z_t_pn1[i] # Z-axis component + sumpnz = pntempZ + termpnz + pntempZ = sumpnz + end + # Post-Newtonian acelerations + postNewtonX = pntempX*c_m2 # X-axis component + postNewtonY = pntempY*c_m2 # Y-axis component + postNewtonZ = pntempZ*c_m2 # Z-axis component + + # Fill dq[4:6] with accelerations + # Post-Newton point mass + Extended body + dq[4] = postNewtonX + accX + dq[5] = postNewtonY + accY + dq[6] = postNewtonZ + accZ + + nothing +end + +@taylorize function newtonian!(dq, q, params, t) + # Julian date of start time + local jd0 = params[4] + # Days since J2000.0 = 2.451545e6 + local dsj2k = t + (jd0 - JD_J2000) + # Solar system ephemeris at dsj2k + local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) + # Type of position / velocity components + local S = eltype(q) + # Interaction matrix with flattened bodies + local UJ_interaction = params[5] + # Number of bodies, including NEA + local N = 10 # Sun, Moon and planets # params[6] + # Number of bodies, except the asteroid + local Nm1 = N-1 + # Vector of mass parameters GM's + local μ = params[7][1:10] + + # zero(q[1]) + local zero_q_1 = auxzero(q[1]) + + #= + Point-mass accelerations + See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + + # Position of the i-th body - position of the asteroid + X = Array{S}(undef, N) # X-axis component + Y = Array{S}(undef, N) # Y-axis component + Z = Array{S}(undef, N) # Z-axis component + + # Distance between the i-th body and the asteroid + r_p2 = Array{S}(undef, N) # r_{i,asteroid}^2 + r_p3d2 = Array{S}(undef, N) # r_p2^1.5 <-> r_{i, asteroid}^3 + + # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 + newtonianCoeff = Array{S}(undef, N) + + # Newtonian coefficient * difference between two positions, i.e., + # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 + newton_acc_X = Array{S}(undef, N) # X-axis component + newton_acc_Y = Array{S}(undef, N) # Y-axis component + newton_acc_Z = Array{S}(undef, N) # Z-axis component + + # Temporary arrays for the sum of full extended body accelerations + temp_accX_i = Array{S}(undef, N) + temp_accY_i = Array{S}(undef, N) + temp_accZ_i = Array{S}(undef, N) + + # Full extended-body accelerations + accX = zero_q_1 + accY = zero_q_1 + accZ = zero_q_1 + + # Fill first 3 elements of dq with velocities + dq[1] = q[4] + dq[2] = q[5] + dq[3] = q[6] + + #= + Compute point-mass Newtonian accelerations, all bodies + See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract + =# + Threads.@threads for i in 1:Nm1 + # Position of the i-th body - position of the asteroid + X[i] = ss16asteph_t[3i-2]-q[1] # X-axis component + Y[i] = ss16asteph_t[3i-1]-q[2] # Y-axis component + Z[i] = ss16asteph_t[3i ]-q[3] # Z-axis component + + # Distance between the i-th body and the asteroid + r_p2[i] = ( (X[i]^2)+(Y[i]^2) ) + (Z[i]^2) # r_{i,asteroid}^2 + r_p3d2[i] = r_p2[i]^1.5 # r_p2^1.5 <-> r_{i, asteroid}^3 + + # Newtonian coefficient, i.e., mass parameter / distance^3 -> \mu_i / r_{i, asteroid}^3 + newtonianCoeff[i] = μ[i]/r_p3d2[i] + + # Newtonian coefficient * difference between two positions, i.e., + # \mu_i * (\mathbf{r_i} - \mathbf{r_asteroid}) / r_{ij}^3 + newton_acc_X[i] = X[i]*newtonianCoeff[i] + newton_acc_Y[i] = Y[i]*newtonianCoeff[i] + newton_acc_Z[i] = Z[i]*newtonianCoeff[i] + end + + for i in 1:Nm1 + # Newtonian point-mass accelerations + temp_accX_i[i] = accX + newton_acc_X[i] + accX = temp_accX_i[i] + temp_accY_i[i] = accY + newton_acc_Y[i] + accY = temp_accY_i[i] + temp_accZ_i[i] = accZ + newton_acc_Z[i] + accZ = temp_accZ_i[i] + end + + # Fill dq[4:6] with accelerations + # Newtonian point-mass accelerations + dq[4] = accX + dq[5] = accY + dq[6] = accZ + + nothing end \ No newline at end of file diff --git a/src/propagation/jetcoeffs.jl b/src/propagation/jetcoeffs.jl old mode 100755 new mode 100644 index 1d9ad5dc..f4990048 --- a/src/propagation/jetcoeffs.jl +++ b/src/propagation/jetcoeffs.jl @@ -1,2993 +1,2993 @@ -# DO NOT MODIFY THIS FILE BY HAND - -# Methods of `TaylorIntegration._allocate_jetcoeffs!` and `TaylorIntegration.jetcoeffs!` generated by @taylorize for the functions -# in src/propagation/asteroid_dynamical_models.jl - -# To update the functions do the following: -# 1.- Update the corresponding function in src/propagation/asteroid_dynamical_models.jl -# 2.- using TaylorIntegration -# 2.- ex = :(paste here the modified function) -# 3.- x, y = TaylorIntegration._make_parsed_coeffs(ex) -# 4.- Paste x and y in this file - -# TaylorIntegration._allocate_jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_ng_eph_threads! -function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params) where {_T <: Real, _S <: Number, _N} - order = t.order - local jd0 = params[4] - local dsj2k = t + (jd0 - JD_J2000) - local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) - local acceph_t = evaleph(params[2], dsj2k, q[1]) - local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) - local S = eltype(q) - local UJ_interaction = params[5] - local N = params[6] - local Nm1 = N - 1 - local μ = params[7] - local zero_q_1 = auxzero(q[1]) - X = Array{S}(undef, N) - Y = Array{S}(undef, N) - Z = Array{S}(undef, N) - r_p2 = Array{S}(undef, N) - r_p1d2 = Array{S}(undef, N) - r_p3d2 = Array{S}(undef, N) - r_p7d2 = Array{S}(undef, N) - newtonianCoeff = Array{S}(undef, N) - ui = Array{S}(undef, N - 1) - vi = Array{S}(undef, N - 1) - wi = Array{S}(undef, N - 1) - U = Array{S}(undef, N) - V = Array{S}(undef, N) - W = Array{S}(undef, N) - _4U_m_3X = Array{S}(undef, N) - _4V_m_3Y = Array{S}(undef, N) - _4W_m_3Z = Array{S}(undef, N) - UU = Array{S}(undef, N) - VV = Array{S}(undef, N) - WW = Array{S}(undef, N) - newtonian1b_Potential = Array{S}(undef, N) - newtonianNb_Potential = Array{S}(undef, N) - newton_acc_X = Array{S}(undef, N) - newton_acc_Y = Array{S}(undef, N) - newton_acc_Z = Array{S}(undef, N) - v2 = Array{S}(undef, N) - vi_dot_vj = Array{S}(undef, N) - pn2 = Array{S}(undef, N) - U_t_pn2 = Array{S}(undef, N) - V_t_pn2 = Array{S}(undef, N) - W_t_pn2 = Array{S}(undef, N) - pn3 = Array{S}(undef, N) - pNX_t_pn3 = Array{S}(undef, N) - pNY_t_pn3 = Array{S}(undef, N) - pNZ_t_pn3 = Array{S}(undef, N) - _4ϕj = Array{S}(undef, N) - ϕi_plus_4ϕj = Array{S}(undef, N) - sj2_plus_2si2_minus_4vivj = Array{S}(undef, N) - ϕs_and_vs = Array{S}(undef, N) - pn1t1_7 = Array{S}(undef, N) - pNX_t_X = Array{S}(undef, N) - pNY_t_Y = Array{S}(undef, N) - pNZ_t_Z = Array{S}(undef, N) - pn1 = Array{S}(undef, N) - X_t_pn1 = Array{S}(undef, N) - Y_t_pn1 = Array{S}(undef, N) - Z_t_pn1 = Array{S}(undef, N) - pntempX = Taylor1(identity(constant_term(zero_q_1)), order) - pntempY = Taylor1(identity(constant_term(zero_q_1)), order) - pntempZ = Taylor1(identity(constant_term(zero_q_1)), order) - t31 = Array{S}(undef, N) - t32 = Array{S}(undef, N) - t33 = Array{S}(undef, N) - r_sin_ϕ = Array{S}(undef, N) - sin_ϕ = Array{S}(undef, N) - ϕ = Array{S}(undef, N) - cos_ϕ = Array{S}(undef, N) - sin2_ϕ = Array{S}(undef, N) - sin3_ϕ = Array{S}(undef, N) - sin4_ϕ = Array{S}(undef, N) - F_J2_x = Array{S}(undef, N) - F_J2_y = Array{S}(undef, N) - F_J2_z = Array{S}(undef, N) - F_J2_x1 = Array{S}(undef, N) - F_J2_y1 = Array{S}(undef, N) - F_J2_z1 = Array{S}(undef, N) - F_J2_x2 = Array{S}(undef, N) - F_J2_y2 = Array{S}(undef, N) - F_J2_z2 = Array{S}(undef, N) - temp_accX_i = Array{S}(undef, N) - temp_accY_i = Array{S}(undef, N) - temp_accZ_i = Array{S}(undef, N) - P_2_sin_ϕ = Array{S}(undef, N) - ∂P_2_sin_ϕ = Array{S}(undef, N) - P_3_sin_ϕ = Array{S}(undef, N) - ∂P_3_sin_ϕ = Array{S}(undef, N) - m_c_ϕ_∂P_2 = Array{S}(undef, N) - m_c_ϕ_∂P_3 = Array{S}(undef, N) - Λ2j_div_r4 = Array{S}(undef, N) - Λ3j_div_r5 = Array{S}(undef, N) - F_J_ξ = Array{S}(undef, N) - F_J_η = Array{S}(undef, N) - F_J_ζ = Array{S}(undef, N) - F_J2_ξ = Array{S}(undef, N) - F_J2_η = Array{S}(undef, N) - F_J2_ζ = Array{S}(undef, N) - F_J3_ξ = Array{S}(undef, N) - F_J3_η = Array{S}(undef, N) - F_J3_ζ = Array{S}(undef, N) - ξx = Array{S}(undef, N) - ξy = Array{S}(undef, N) - ξz = Array{S}(undef, N) - ηx = Array{S}(undef, N) - ηy = Array{S}(undef, N) - ηz = Array{S}(undef, N) - ηx1 = Array{S}(undef, N) - ηy1 = Array{S}(undef, N) - ηz1 = Array{S}(undef, N) - ηx2 = Array{S}(undef, N) - ηy2 = Array{S}(undef, N) - ηz2 = Array{S}(undef, N) - ζx = Array{S}(undef, N) - ζy = Array{S}(undef, N) - ζz = Array{S}(undef, N) - ζx1 = Array{S}(undef, N) - ζy1 = Array{S}(undef, N) - ζz1 = Array{S}(undef, N) - ζx2 = Array{S}(undef, N) - ζy2 = Array{S}(undef, N) - ζz2 = Array{S}(undef, N) - accX = Taylor1(identity(constant_term(zero_q_1)), order) - accY = Taylor1(identity(constant_term(zero_q_1)), order) - accZ = Taylor1(identity(constant_term(zero_q_1)), order) - local M_ = Array{S}(undef, 3, 3, N) - local M_ .= zero_q_1 - local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 - dq[1] = Taylor1(identity(constant_term(q[4])), order) - dq[2] = Taylor1(identity(constant_term(q[5])), order) - dq[3] = Taylor1(identity(constant_term(q[6])), order) - newtonianNb_Potential[N] = Taylor1(identity(constant_term(zero_q_1)), order) - tmp687 = Array{Taylor1{_S}}(undef, size(dq)) - tmp687 .= Taylor1(zero(constant_term(q[1])), order) - tmp689 = Array{Taylor1{_S}}(undef, size(ui)) - tmp689 .= Taylor1(zero(constant_term(q[1])), order) - tmp692 = Array{Taylor1{_S}}(undef, size(dq)) - tmp692 .= Taylor1(zero(constant_term(q[1])), order) - tmp694 = Array{Taylor1{_S}}(undef, size(vi)) - tmp694 .= Taylor1(zero(constant_term(q[1])), order) - tmp697 = Array{Taylor1{_S}}(undef, size(dq)) - tmp697 .= Taylor1(zero(constant_term(q[1])), order) - tmp699 = Array{Taylor1{_S}}(undef, size(wi)) - tmp699 .= Taylor1(zero(constant_term(q[1])), order) - pn2x = Array{Taylor1{_S}}(undef, size(X)) - pn2x .= Taylor1(zero(constant_term(q[1])), order) - pn2y = Array{Taylor1{_S}}(undef, size(Y)) - pn2y .= Taylor1(zero(constant_term(q[1])), order) - pn2z = Array{Taylor1{_S}}(undef, size(Z)) - pn2z .= Taylor1(zero(constant_term(q[1])), order) - tmp707 = Array{Taylor1{_S}}(undef, size(UU)) - tmp707 .= Taylor1(zero(constant_term(q[1])), order) - tmp710 = Array{Taylor1{_S}}(undef, size(X)) - tmp710 .= Taylor1(zero(constant_term(q[1])), order) - tmp712 = Array{Taylor1{_S}}(undef, size(Y)) - tmp712 .= Taylor1(zero(constant_term(q[1])), order) - tmp713 = Array{Taylor1{_S}}(undef, size(tmp710)) - tmp713 .= Taylor1(zero(constant_term(q[1])), order) - tmp715 = Array{Taylor1{_S}}(undef, size(Z)) - tmp715 .= Taylor1(zero(constant_term(q[1])), order) - tmp723 = Array{Taylor1{_S}}(undef, size(pn2x)) - tmp723 .= Taylor1(zero(constant_term(q[1])), order) - tmp724 = Array{Taylor1{_S}}(undef, size(tmp723)) - tmp724 .= Taylor1(zero(constant_term(q[1])), order) - tmp819 = Array{Taylor1{_S}}(undef, size(ui)) - tmp819 .= Taylor1(zero(constant_term(q[1])), order) - tmp821 = Array{Taylor1{_S}}(undef, size(vi)) - tmp821 .= Taylor1(zero(constant_term(q[1])), order) - tmp822 = Array{Taylor1{_S}}(undef, size(tmp819)) - tmp822 .= Taylor1(zero(constant_term(q[1])), order) - tmp824 = Array{Taylor1{_S}}(undef, size(wi)) - tmp824 .= Taylor1(zero(constant_term(q[1])), order) - tmp735 = Array{Taylor1{_S}}(undef, size(X)) - tmp735 .= Taylor1(zero(constant_term(q[1])), order) - tmp737 = Array{Taylor1{_S}}(undef, size(Y)) - tmp737 .= Taylor1(zero(constant_term(q[1])), order) - tmp739 = Array{Taylor1{_S}}(undef, size(Z)) - tmp739 .= Taylor1(zero(constant_term(q[1])), order) - tmp741 = Array{Taylor1{_S}}(undef, size(t31)) - tmp741 .= Taylor1(zero(constant_term(q[1])), order) - tmp948 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp948 .= Taylor1(zero(constant_term(q[1])), order) - tmp949 = Array{Taylor1{_S}}(undef, size(ϕ)) - tmp949 .= Taylor1(zero(constant_term(q[1])), order) - tmp751 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp751 .= Taylor1(zero(constant_term(q[1])), order) - tmp757 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp757 .= Taylor1(zero(constant_term(q[1])), order) - tmp759 = Array{Taylor1{_S}}(undef, size(sin3_ϕ)) - tmp759 .= Taylor1(zero(constant_term(q[1])), order) - tmp763 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp763 .= Taylor1(zero(constant_term(q[1])), order) - tmp766 = Array{Taylor1{_S}}(undef, size(r_p2)) - tmp766 .= Taylor1(zero(constant_term(q[1])), order) - tmp767 = Array{Taylor1{_S}}(undef, size(Λ2)) - tmp767 .= Taylor1(zero(constant_term(q[1])), order) - tmp770 = Array{Taylor1{_S}}(undef, size(r_p1d2)) - tmp770 .= Taylor1(zero(constant_term(q[1])), order) - tmp771 = Array{Taylor1{_S}}(undef, size(Λ3)) - tmp771 .= Taylor1(zero(constant_term(q[1])), order) - tmp773 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp773 .= Taylor1(zero(constant_term(q[1])), order) - tmp775 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp775 .= Taylor1(zero(constant_term(q[1])), order) - tmp778 = Array{Taylor1{_S}}(undef, size(Λ2j_div_r4)) - tmp778 .= Taylor1(zero(constant_term(q[1])), order) - tmp782 = Array{Taylor1{_S}}(undef, size(Λ3j_div_r5)) - tmp782 .= Taylor1(zero(constant_term(q[1])), order) - tmp785 = Array{Taylor1{_S}}(undef, size(X)) - tmp785 .= Taylor1(zero(constant_term(q[1])), order) - tmp787 = Array{Taylor1{_S}}(undef, size(Y)) - tmp787 .= Taylor1(zero(constant_term(q[1])), order) - tmp789 = Array{Taylor1{_S}}(undef, size(Z)) - tmp789 .= Taylor1(zero(constant_term(q[1])), order) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 - ui[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])), order) - vi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])), order) - wi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])), order) - X[i] = Taylor1(constant_term(ss16asteph_t[3i - 2]) - constant_term(q[1]), order) - Y[i] = Taylor1(constant_term(ss16asteph_t[3i - 1]) - constant_term(q[2]), order) - Z[i] = Taylor1(constant_term(ss16asteph_t[3i]) - constant_term(q[3]), order) - U[i] = Taylor1(constant_term(ui[i]) - constant_term(dq[1]), order) - V[i] = Taylor1(constant_term(vi[i]) - constant_term(dq[2]), order) - W[i] = Taylor1(constant_term(wi[i]) - constant_term(dq[3]), order) - tmp687[1] = Taylor1(constant_term(4) * constant_term(dq[1]), order) - tmp689[i] = Taylor1(constant_term(3) * constant_term(ui[i]), order) - _4U_m_3X[i] = Taylor1(constant_term(tmp687[1]) - constant_term(tmp689[i]), order) - tmp692[2] = Taylor1(constant_term(4) * constant_term(dq[2]), order) - tmp694[i] = Taylor1(constant_term(3) * constant_term(vi[i]), order) - _4V_m_3Y[i] = Taylor1(constant_term(tmp692[2]) - constant_term(tmp694[i]), order) - tmp697[3] = Taylor1(constant_term(4) * constant_term(dq[3]), order) - tmp699[i] = Taylor1(constant_term(3) * constant_term(wi[i]), order) - _4W_m_3Z[i] = Taylor1(constant_term(tmp697[3]) - constant_term(tmp699[i]), order) - pn2x[i] = Taylor1(constant_term(X[i]) * constant_term(_4U_m_3X[i]), order) - pn2y[i] = Taylor1(constant_term(Y[i]) * constant_term(_4V_m_3Y[i]), order) - pn2z[i] = Taylor1(constant_term(Z[i]) * constant_term(_4W_m_3Z[i]), order) - UU[i] = Taylor1(constant_term(ui[i]) * constant_term(dq[1]), order) - VV[i] = Taylor1(constant_term(vi[i]) * constant_term(dq[2]), order) - WW[i] = Taylor1(constant_term(wi[i]) * constant_term(dq[3]), order) - tmp707[i] = Taylor1(constant_term(UU[i]) + constant_term(VV[i]), order) - vi_dot_vj[i] = Taylor1(constant_term(tmp707[i]) + constant_term(WW[i]), order) - tmp710[i] = Taylor1(constant_term(X[i]) ^ float(constant_term(2)), order) - tmp712[i] = Taylor1(constant_term(Y[i]) ^ float(constant_term(2)), order) - tmp713[i] = Taylor1(constant_term(tmp710[i]) + constant_term(tmp712[i]), order) - tmp715[i] = Taylor1(constant_term(Z[i]) ^ float(constant_term(2)), order) - r_p2[i] = Taylor1(constant_term(tmp713[i]) + constant_term(tmp715[i]), order) - r_p1d2[i] = Taylor1(sqrt(constant_term(r_p2[i])), order) - r_p3d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(1.5)), order) - r_p7d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(3.5)), order) - newtonianCoeff[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p3d2[i]), order) - tmp723[i] = Taylor1(constant_term(pn2x[i]) + constant_term(pn2y[i]), order) - tmp724[i] = Taylor1(constant_term(tmp723[i]) + constant_term(pn2z[i]), order) - pn2[i] = Taylor1(constant_term(newtonianCoeff[i]) * constant_term(tmp724[i]), order) - newton_acc_X[i] = Taylor1(constant_term(X[i]) * constant_term(newtonianCoeff[i]), order) - newton_acc_Y[i] = Taylor1(constant_term(Y[i]) * constant_term(newtonianCoeff[i]), order) - newton_acc_Z[i] = Taylor1(constant_term(Z[i]) * constant_term(newtonianCoeff[i]), order) - newtonian1b_Potential[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p1d2[i]), order) - pn3[i] = Taylor1(constant_term(3.5) * constant_term(newtonian1b_Potential[i]), order) - U_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(U[i]), order) - V_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(V[i]), order) - W_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(W[i]), order) - if UJ_interaction[i] - tmp735[i] = Taylor1(-(constant_term(X[i])), order) - t31[i] = Taylor1(constant_term(tmp735[i]) * constant_term(M_[1, 3, i]), order) - tmp737[i] = Taylor1(-(constant_term(Y[i])), order) - t32[i] = Taylor1(constant_term(tmp737[i]) * constant_term(M_[2, 3, i]), order) - tmp739[i] = Taylor1(-(constant_term(Z[i])), order) - t33[i] = Taylor1(constant_term(tmp739[i]) * constant_term(M_[3, 3, i]), order) - tmp741[i] = Taylor1(constant_term(t31[i]) + constant_term(t32[i]), order) - r_sin_ϕ[i] = Taylor1(constant_term(tmp741[i]) + constant_term(t33[i]), order) - sin_ϕ[i] = Taylor1(constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]), order) - ϕ[i] = Taylor1(asin(constant_term(sin_ϕ[i])), order) - tmp948[i] = Taylor1(sqrt(1 - constant_term(sin_ϕ[i]) ^ 2), order) - cos_ϕ[i] = Taylor1(cos(constant_term(ϕ[i])), order) - tmp949[i] = Taylor1(sin(constant_term(ϕ[i])), order) - sin2_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(2)), order) - sin3_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(3)), order) - tmp751[i] = Taylor1(constant_term(1.5) * constant_term(sin2_ϕ[i]), order) - P_2_sin_ϕ[i] = Taylor1(constant_term(tmp751[i]) - constant_term(0.5), order) - ∂P_2_sin_ϕ[i] = Taylor1(constant_term(3) * constant_term(sin_ϕ[i]), order) - tmp757[i] = Taylor1(constant_term(-1.5) * constant_term(sin_ϕ[i]), order) - tmp759[i] = Taylor1(constant_term(2.5) * constant_term(sin3_ϕ[i]), order) - P_3_sin_ϕ[i] = Taylor1(constant_term(tmp757[i]) + constant_term(tmp759[i]), order) - tmp763[i] = Taylor1(constant_term(7.5) * constant_term(sin2_ϕ[i]), order) - ∂P_3_sin_ϕ[i] = Taylor1(constant_term(-1.5) + constant_term(tmp763[i]), order) - tmp766[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(2)), order) - tmp767[i] = Taylor1(constant_term(Λ2[i]) / constant_term(tmp766[i]), order) - Λ2j_div_r4[i] = Taylor1(-(constant_term(tmp767[i])), order) - tmp770[i] = Taylor1(constant_term(r_p1d2[i]) ^ float(constant_term(5)), order) - tmp771[i] = Taylor1(constant_term(Λ3[i]) / constant_term(tmp770[i]), order) - Λ3j_div_r5[i] = Taylor1(-(constant_term(tmp771[i])), order) - tmp773[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) - m_c_ϕ_∂P_2[i] = Taylor1(constant_term(tmp773[i]) * constant_term(∂P_2_sin_ϕ[i]), order) - tmp775[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) - m_c_ϕ_∂P_3[i] = Taylor1(constant_term(tmp775[i]) * constant_term(∂P_3_sin_ϕ[i]), order) - tmp778[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(3), order) - F_J2_ξ[i] = Taylor1(constant_term(tmp778[i]) * constant_term(P_2_sin_ϕ[i]), order) - F_J2_ζ[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]), order) - tmp782[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(4), order) - F_J3_ξ[i] = Taylor1(constant_term(tmp782[i]) * constant_term(P_3_sin_ϕ[i]), order) - F_J3_ζ[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]), order) - F_J_ξ[i] = Taylor1(identity(constant_term(F_J2_ξ[i])), order) - F_J_ζ[i] = Taylor1(identity(constant_term(F_J2_ζ[i])), order) - tmp785[i] = Taylor1(-(constant_term(X[i])), order) - ξx[i] = Taylor1(constant_term(tmp785[i]) / constant_term(r_p1d2[i]), order) - tmp787[i] = Taylor1(-(constant_term(Y[i])), order) - ξy[i] = Taylor1(constant_term(tmp787[i]) / constant_term(r_p1d2[i]), order) - tmp789[i] = Taylor1(-(constant_term(Z[i])), order) - ξz[i] = Taylor1(constant_term(tmp789[i]) / constant_term(r_p1d2[i]), order) - ηx1[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξz[i]), order) - ηy1[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξx[i]), order) - ηz1[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξy[i]), order) - ηx2[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξy[i]), order) - ηy2[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξz[i]), order) - ηz2[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξx[i]), order) - ηx[i] = Taylor1(constant_term(ηx1[i]) - constant_term(ηx2[i]), order) - ηy[i] = Taylor1(constant_term(ηy1[i]) - constant_term(ηy2[i]), order) - ηz[i] = Taylor1(constant_term(ηz1[i]) - constant_term(ηz2[i]), order) - ζx1[i] = Taylor1(constant_term(ξy[i]) * constant_term(ηz[i]), order) - ζy1[i] = Taylor1(constant_term(ξz[i]) * constant_term(ηx[i]), order) - ζz1[i] = Taylor1(constant_term(ξx[i]) * constant_term(ηy[i]), order) - ζx2[i] = Taylor1(constant_term(ξz[i]) * constant_term(ηy[i]), order) - ζy2[i] = Taylor1(constant_term(ξx[i]) * constant_term(ηz[i]), order) - ζz2[i] = Taylor1(constant_term(ξy[i]) * constant_term(ηx[i]), order) - ζx[i] = Taylor1(constant_term(ζx1[i]) - constant_term(ζx2[i]), order) - ζy[i] = Taylor1(constant_term(ζy1[i]) - constant_term(ζy2[i]), order) - ζz[i] = Taylor1(constant_term(ζz1[i]) - constant_term(ζz2[i]), order) - F_J2_x1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξx[i]), order) - F_J2_y1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξy[i]), order) - F_J2_z1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξz[i]), order) - F_J2_x2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζx[i]), order) - F_J2_y2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζy[i]), order) - F_J2_z2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζz[i]), order) - F_J2_x[i] = Taylor1(constant_term(F_J2_x1[i]) + constant_term(F_J2_x2[i]), order) - F_J2_y[i] = Taylor1(constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]), order) - F_J2_z[i] = Taylor1(constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]), order) - end - tmp819[i] = Taylor1(constant_term(ui[i]) ^ float(constant_term(2)), order) - tmp821[i] = Taylor1(constant_term(vi[i]) ^ float(constant_term(2)), order) - tmp822[i] = Taylor1(constant_term(tmp819[i]) + constant_term(tmp821[i]), order) - tmp824[i] = Taylor1(constant_term(wi[i]) ^ float(constant_term(2)), order) - v2[i] = Taylor1(constant_term(tmp822[i]) + constant_term(tmp824[i]), order) - end - tmp827 = Taylor1(constant_term(q[4]) ^ float(constant_term(2)), order) - tmp829 = Taylor1(constant_term(q[5]) ^ float(constant_term(2)), order) - tmp830 = Taylor1(constant_term(tmp827) + constant_term(tmp829), order) - tmp832 = Taylor1(constant_term(q[6]) ^ float(constant_term(2)), order) - v2[N] = Taylor1(constant_term(tmp830) + constant_term(tmp832), order) - temp_004 = Array{Taylor1{_S}}(undef, size(newtonian1b_Potential)) - temp_004 .= Taylor1(zero(constant_term(q[1])), order) - tmp835 = Array{Taylor1{_S}}(undef, size(μ)) - tmp835 .= Taylor1(zero(constant_term(q[1])), order) - tmp837 = Array{Taylor1{_S}}(undef, size(μ)) - tmp837 .= Taylor1(zero(constant_term(q[1])), order) - tmp839 = Array{Taylor1{_S}}(undef, size(μ)) - tmp839 .= Taylor1(zero(constant_term(q[1])), order) - for i = 1:Nm1 - temp_004[i] = Taylor1(constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]), order) - newtonianNb_Potential[N] = Taylor1(identity(constant_term(temp_004[i])), order) - if UJ_interaction[i] - tmp835[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_x[i]), order) - temp_accX_i[i] = Taylor1(constant_term(accX) - constant_term(tmp835[i]), order) - accX = Taylor1(identity(constant_term(temp_accX_i[i])), order) - tmp837[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_y[i]), order) - temp_accY_i[i] = Taylor1(constant_term(accY) - constant_term(tmp837[i]), order) - accY = Taylor1(identity(constant_term(temp_accY_i[i])), order) - tmp839[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_z[i]), order) - temp_accZ_i[i] = Taylor1(constant_term(accZ) - constant_term(tmp839[i]), order) - accZ = Taylor1(identity(constant_term(temp_accZ_i[i])), order) - end - end - _4ϕj[N] = Taylor1(constant_term(4) * constant_term(newtonianNb_Potential[N]), order) - tmp845 = Array{Taylor1{_S}}(undef, size(v2)) - tmp845 .= Taylor1(zero(constant_term(q[1])), order) - tmp847 = Array{Taylor1{_S}}(undef, size(vi_dot_vj)) - tmp847 .= Taylor1(zero(constant_term(q[1])), order) - tmp848 = Array{Taylor1{_S}}(undef, size(tmp845)) - tmp848 .= Taylor1(zero(constant_term(q[1])), order) - Xij_t_Ui = Array{Taylor1{_S}}(undef, size(X)) - Xij_t_Ui .= Taylor1(zero(constant_term(q[1])), order) - Yij_t_Vi = Array{Taylor1{_S}}(undef, size(Y)) - Yij_t_Vi .= Taylor1(zero(constant_term(q[1])), order) - Zij_t_Wi = Array{Taylor1{_S}}(undef, size(Z)) - Zij_t_Wi .= Taylor1(zero(constant_term(q[1])), order) - tmp854 = Array{Taylor1{_S}}(undef, size(Xij_t_Ui)) - tmp854 .= Taylor1(zero(constant_term(q[1])), order) - Rij_dot_Vi = Array{Taylor1{_S}}(undef, size(tmp854)) - Rij_dot_Vi .= Taylor1(zero(constant_term(q[1])), order) - tmp857 = Array{Taylor1{_S}}(undef, size(Rij_dot_Vi)) - tmp857 .= Taylor1(zero(constant_term(q[1])), order) - pn1t7 = Array{Taylor1{_S}}(undef, size(tmp857)) - pn1t7 .= Taylor1(zero(constant_term(q[1])), order) - tmp860 = Array{Taylor1{_S}}(undef, size(pn1t7)) - tmp860 .= Taylor1(zero(constant_term(q[1])), order) - pn1t2_7 = Array{Taylor1{_S}}(undef, size(ϕs_and_vs)) - pn1t2_7 .= Taylor1(zero(constant_term(q[1])), order) - tmp867 = Array{Taylor1{_S}}(undef, size(pNX_t_X)) - tmp867 .= Taylor1(zero(constant_term(q[1])), order) - tmp868 = Array{Taylor1{_S}}(undef, size(tmp867)) - tmp868 .= Taylor1(zero(constant_term(q[1])), order) - tmp869 = Array{Taylor1{_S}}(undef, size(tmp868)) - tmp869 .= Taylor1(zero(constant_term(q[1])), order) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 - ϕi_plus_4ϕj[i] = Taylor1(constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]), order) - tmp845[i] = Taylor1(constant_term(2) * constant_term(v2[i]), order) - tmp847[i] = Taylor1(constant_term(4) * constant_term(vi_dot_vj[i]), order) - tmp848[i] = Taylor1(constant_term(tmp845[i]) - constant_term(tmp847[i]), order) - sj2_plus_2si2_minus_4vivj[i] = Taylor1(constant_term(tmp848[i]) + constant_term(v2[N]), order) - ϕs_and_vs[i] = Taylor1(constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]), order) - Xij_t_Ui[i] = Taylor1(constant_term(X[i]) * constant_term(ui[i]), order) - Yij_t_Vi[i] = Taylor1(constant_term(Y[i]) * constant_term(vi[i]), order) - Zij_t_Wi[i] = Taylor1(constant_term(Z[i]) * constant_term(wi[i]), order) - tmp854[i] = Taylor1(constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]), order) - Rij_dot_Vi[i] = Taylor1(constant_term(tmp854[i]) + constant_term(Zij_t_Wi[i]), order) - tmp857[i] = Taylor1(constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)), order) - pn1t7[i] = Taylor1(constant_term(tmp857[i]) / constant_term(r_p2[i]), order) - tmp860[i] = Taylor1(constant_term(1.5) * constant_term(pn1t7[i]), order) - pn1t2_7[i] = Taylor1(constant_term(ϕs_and_vs[i]) - constant_term(tmp860[i]), order) - pn1t1_7[i] = Taylor1(constant_term(c_p2) + constant_term(pn1t2_7[i]), order) - pNX_t_X[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(X[i]), order) - pNY_t_Y[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(Y[i]), order) - pNZ_t_Z[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(Z[i]), order) - tmp867[i] = Taylor1(constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]), order) - tmp868[i] = Taylor1(constant_term(tmp867[i]) + constant_term(pNZ_t_Z[i]), order) - tmp869[i] = Taylor1(constant_term(0.5) * constant_term(tmp868[i]), order) - pn1[i] = Taylor1(constant_term(pn1t1_7[i]) + constant_term(tmp869[i]), order) - X_t_pn1[i] = Taylor1(constant_term(newton_acc_X[i]) * constant_term(pn1[i]), order) - Y_t_pn1[i] = Taylor1(constant_term(newton_acc_Y[i]) * constant_term(pn1[i]), order) - Z_t_pn1[i] = Taylor1(constant_term(newton_acc_Z[i]) * constant_term(pn1[i]), order) - pNX_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(pn3[i]), order) - pNY_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]), order) - pNZ_t_pn3[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(pn3[i]), order) - end - tmp877 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) - tmp877 .= Taylor1(zero(constant_term(q[1])), order) - termpnx = Array{Taylor1{_S}}(undef, size(X_t_pn1)) - termpnx .= Taylor1(zero(constant_term(q[1])), order) - sumpnx = Array{Taylor1{_S}}(undef, size(termpnx)) - sumpnx .= Taylor1(zero(constant_term(q[1])), order) - tmp880 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) - tmp880 .= Taylor1(zero(constant_term(q[1])), order) - termpny = Array{Taylor1{_S}}(undef, size(Y_t_pn1)) - termpny .= Taylor1(zero(constant_term(q[1])), order) - sumpny = Array{Taylor1{_S}}(undef, size(termpny)) - sumpny .= Taylor1(zero(constant_term(q[1])), order) - tmp883 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) - tmp883 .= Taylor1(zero(constant_term(q[1])), order) - termpnz = Array{Taylor1{_S}}(undef, size(Z_t_pn1)) - termpnz .= Taylor1(zero(constant_term(q[1])), order) - sumpnz = Array{Taylor1{_S}}(undef, size(termpnz)) - sumpnz .= Taylor1(zero(constant_term(q[1])), order) - for i = 1:10 - tmp877[i] = Taylor1(constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]), order) - termpnx[i] = Taylor1(constant_term(X_t_pn1[i]) + constant_term(tmp877[i]), order) - sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) - pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) - tmp880[i] = Taylor1(constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]), order) - termpny[i] = Taylor1(constant_term(Y_t_pn1[i]) + constant_term(tmp880[i]), order) - sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) - pntempY = Taylor1(identity(constant_term(sumpny[i])), order) - tmp883[i] = Taylor1(constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]), order) - termpnz[i] = Taylor1(constant_term(Z_t_pn1[i]) + constant_term(tmp883[i]), order) - sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) - pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) - end - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 - X_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_X[i]), order) - Y_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Y[i]), order) - Z_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Z[i]), order) - end - for i = 11:Nm1 - termpnx[i] = Taylor1(identity(constant_term(X_t_pn1[i])), order) - sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) - pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) - termpny[i] = Taylor1(identity(constant_term(Y_t_pn1[i])), order) - sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) - pntempY = Taylor1(identity(constant_term(sumpny[i])), order) - termpnz[i] = Taylor1(identity(constant_term(Z_t_pn1[i])), order) - sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) - pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) - end - postNewtonX = Taylor1(constant_term(pntempX) * constant_term(c_m2), order) - postNewtonY = Taylor1(constant_term(pntempY) * constant_term(c_m2), order) - postNewtonZ = Taylor1(constant_term(pntempZ) * constant_term(c_m2), order) - tmp895 = Taylor1(constant_term(Y[1]) * constant_term(W[1]), order) - tmp896 = Taylor1(constant_term(Z[1]) * constant_term(V[1]), order) - hx = Taylor1(constant_term(tmp895) - constant_term(tmp896), order) - tmp898 = Taylor1(constant_term(Z[1]) * constant_term(U[1]), order) - tmp899 = Taylor1(constant_term(X[1]) * constant_term(W[1]), order) - hy = Taylor1(constant_term(tmp898) - constant_term(tmp899), order) - tmp901 = Taylor1(constant_term(X[1]) * constant_term(V[1]), order) - tmp902 = Taylor1(constant_term(Y[1]) * constant_term(U[1]), order) - hz = Taylor1(constant_term(tmp901) - constant_term(tmp902), order) - tmp904 = Taylor1(constant_term(hz) * constant_term(Y[1]), order) - tmp905 = Taylor1(constant_term(hy) * constant_term(Z[1]), order) - t_x = Taylor1(constant_term(tmp904) - constant_term(tmp905), order) - tmp907 = Taylor1(constant_term(hx) * constant_term(Z[1]), order) - tmp908 = Taylor1(constant_term(hz) * constant_term(X[1]), order) - t_y = Taylor1(constant_term(tmp907) - constant_term(tmp908), order) - tmp910 = Taylor1(constant_term(hy) * constant_term(X[1]), order) - tmp911 = Taylor1(constant_term(hx) * constant_term(Y[1]), order) - t_z = Taylor1(constant_term(tmp910) - constant_term(tmp911), order) - tmp914 = Taylor1(constant_term(t_x) ^ float(constant_term(2)), order) - tmp916 = Taylor1(constant_term(t_y) ^ float(constant_term(2)), order) - tmp917 = Taylor1(constant_term(tmp914) + constant_term(tmp916), order) - tmp919 = Taylor1(constant_term(t_z) ^ float(constant_term(2)), order) - tmp920 = Taylor1(constant_term(tmp917) + constant_term(tmp919), order) - t_norm = Taylor1(sqrt(constant_term(tmp920)), order) - t_x_unit = Taylor1(constant_term(t_x) / constant_term(t_norm), order) - t_y_unit = Taylor1(constant_term(t_y) / constant_term(t_norm), order) - t_z_unit = Taylor1(constant_term(t_z) / constant_term(t_norm), order) - tmp925 = Taylor1(constant_term(X[1]) / constant_term(r_p1d2[1]), order) - r_x_unit = Taylor1(-(constant_term(tmp925)), order) - tmp927 = Taylor1(constant_term(Y[1]) / constant_term(r_p1d2[1]), order) - r_y_unit = Taylor1(-(constant_term(tmp927)), order) - tmp929 = Taylor1(constant_term(Z[1]) / constant_term(r_p1d2[1]), order) - r_z_unit = Taylor1(-(constant_term(tmp929)), order) - g_r = Taylor1(identity(constant_term(r_p2[1])), order) - A2_t_g_r = Taylor1(constant_term(q[7]) / constant_term(g_r), order) - A1_t_g_r = Taylor1(constant_term(q[8]) / constant_term(g_r), order) - tmp933 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_x_unit), order) - tmp934 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_x_unit), order) - NGAx = Taylor1(constant_term(tmp933) + constant_term(tmp934), order) - tmp936 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_y_unit), order) - tmp937 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_y_unit), order) - NGAy = Taylor1(constant_term(tmp936) + constant_term(tmp937), order) - tmp939 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_z_unit), order) - tmp940 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_z_unit), order) - NGAz = Taylor1(constant_term(tmp939) + constant_term(tmp940), order) - tmp942 = Taylor1(constant_term(postNewtonX) + constant_term(accX), order) - dq[4] = Taylor1(constant_term(tmp942) + constant_term(NGAx), order) - tmp944 = Taylor1(constant_term(postNewtonY) + constant_term(accY), order) - dq[5] = Taylor1(constant_term(tmp944) + constant_term(NGAy), order) - tmp946 = Taylor1(constant_term(postNewtonZ) + constant_term(accZ), order) - dq[6] = Taylor1(constant_term(tmp946) + constant_term(NGAz), order) - dq[7] = Taylor1(identity(constant_term(zero_q_1)), order) - return TaylorIntegration.RetAlloc{Taylor1{_S}}([tmp827, tmp829, tmp830, tmp832, tmp895, tmp896, tmp898, tmp899, tmp901, tmp902, tmp904, tmp905, tmp907, tmp908, tmp910, tmp911, tmp914, tmp916, tmp917, tmp919, tmp920, tmp925, tmp927, tmp929, tmp933, tmp934, tmp936, tmp937, tmp939, tmp940, tmp942, tmp944, tmp946, pntempX, pntempY, pntempZ, accX, accY, accZ, postNewtonX, postNewtonY, postNewtonZ, hx, hy, hz, t_x, t_y, t_z, t_norm, t_x_unit, t_y_unit, t_z_unit, r_x_unit, r_y_unit, r_z_unit, g_r, A2_t_g_r, A1_t_g_r, NGAx, NGAy, NGAz], [X, Y, Z, r_p2, r_p1d2, r_p3d2, r_p7d2, newtonianCoeff, ui, vi, wi, U, V, W, _4U_m_3X, _4V_m_3Y, _4W_m_3Z, UU, VV, WW, newtonian1b_Potential, newtonianNb_Potential, newton_acc_X, newton_acc_Y, newton_acc_Z, v2, vi_dot_vj, pn2, U_t_pn2, V_t_pn2, W_t_pn2, pn3, pNX_t_pn3, pNY_t_pn3, pNZ_t_pn3, _4ϕj, ϕi_plus_4ϕj, sj2_plus_2si2_minus_4vivj, ϕs_and_vs, pn1t1_7, pNX_t_X, pNY_t_Y, pNZ_t_Z, pn1, X_t_pn1, Y_t_pn1, Z_t_pn1, t31, t32, t33, r_sin_ϕ, sin_ϕ, ϕ, cos_ϕ, sin2_ϕ, sin3_ϕ, F_J2_x, F_J2_y, F_J2_z, F_J2_x1, F_J2_y1, F_J2_z1, F_J2_x2, F_J2_y2, F_J2_z2, temp_accX_i, temp_accY_i, temp_accZ_i, P_2_sin_ϕ, ∂P_2_sin_ϕ, P_3_sin_ϕ, ∂P_3_sin_ϕ, m_c_ϕ_∂P_2, m_c_ϕ_∂P_3, Λ2j_div_r4, Λ3j_div_r5, F_J_ξ, F_J_ζ, F_J2_ξ, F_J2_ζ, F_J3_ξ, F_J3_ζ, ξx, ξy, ξz, ηx, ηy, ηz, ηx1, ηy1, ηz1, ηx2, ηy2, ηz2, ζx, ζy, ζz, ζx1, ζy1, ζz1, ζx2, ζy2, ζz2, tmp687, tmp689, tmp692, tmp694, tmp697, tmp699, pn2x, pn2y, pn2z, tmp707, tmp710, tmp712, tmp713, tmp715, tmp723, tmp724, tmp735, tmp737, tmp739, tmp741, tmp948, tmp949, tmp751, tmp757, tmp759, tmp763, tmp766, tmp767, tmp770, tmp771, tmp773, tmp775, tmp778, tmp782, tmp785, tmp787, tmp789, tmp819, tmp821, tmp822, tmp824, temp_004, tmp835, tmp837, tmp839, tmp845, tmp847, tmp848, Xij_t_Ui, Yij_t_Vi, Zij_t_Wi, tmp854, Rij_dot_Vi, tmp857, pn1t7, tmp860, pn1t2_7, tmp867, tmp868, tmp869, tmp877, termpnx, sumpnx, tmp880, termpny, sumpny, tmp883, termpnz, sumpnz], [Array{Taylor1{_S}, 2}(undef, 0, 0)], [Array{Taylor1{_S}, 3}(undef, 0, 0, 0)], [Array{Taylor1{_S}, 4}(undef, 0, 0, 0, 0)]) -end - -# TaylorIntegration.jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_ng_eph_threads! -function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params, __ralloc::TaylorIntegration.RetAlloc{Taylor1{_S}}) where {_T <: Real, _S <: Number, _N} - order = t.order - tmp827 = __ralloc.v0[1] - tmp829 = __ralloc.v0[2] - tmp830 = __ralloc.v0[3] - tmp832 = __ralloc.v0[4] - tmp895 = __ralloc.v0[5] - tmp896 = __ralloc.v0[6] - tmp898 = __ralloc.v0[7] - tmp899 = __ralloc.v0[8] - tmp901 = __ralloc.v0[9] - tmp902 = __ralloc.v0[10] - tmp904 = __ralloc.v0[11] - tmp905 = __ralloc.v0[12] - tmp907 = __ralloc.v0[13] - tmp908 = __ralloc.v0[14] - tmp910 = __ralloc.v0[15] - tmp911 = __ralloc.v0[16] - tmp914 = __ralloc.v0[17] - tmp916 = __ralloc.v0[18] - tmp917 = __ralloc.v0[19] - tmp919 = __ralloc.v0[20] - tmp920 = __ralloc.v0[21] - tmp925 = __ralloc.v0[22] - tmp927 = __ralloc.v0[23] - tmp929 = __ralloc.v0[24] - tmp933 = __ralloc.v0[25] - tmp934 = __ralloc.v0[26] - tmp936 = __ralloc.v0[27] - tmp937 = __ralloc.v0[28] - tmp939 = __ralloc.v0[29] - tmp940 = __ralloc.v0[30] - tmp942 = __ralloc.v0[31] - tmp944 = __ralloc.v0[32] - tmp946 = __ralloc.v0[33] - pntempX = __ralloc.v0[34] - pntempY = __ralloc.v0[35] - pntempZ = __ralloc.v0[36] - accX = __ralloc.v0[37] - accY = __ralloc.v0[38] - accZ = __ralloc.v0[39] - postNewtonX = __ralloc.v0[40] - postNewtonY = __ralloc.v0[41] - postNewtonZ = __ralloc.v0[42] - hx = __ralloc.v0[43] - hy = __ralloc.v0[44] - hz = __ralloc.v0[45] - t_x = __ralloc.v0[46] - t_y = __ralloc.v0[47] - t_z = __ralloc.v0[48] - t_norm = __ralloc.v0[49] - t_x_unit = __ralloc.v0[50] - t_y_unit = __ralloc.v0[51] - t_z_unit = __ralloc.v0[52] - r_x_unit = __ralloc.v0[53] - r_y_unit = __ralloc.v0[54] - r_z_unit = __ralloc.v0[55] - g_r = __ralloc.v0[56] - A2_t_g_r = __ralloc.v0[57] - A1_t_g_r = __ralloc.v0[58] - NGAx = __ralloc.v0[59] - NGAy = __ralloc.v0[60] - NGAz = __ralloc.v0[61] - X = __ralloc.v1[1] - Y = __ralloc.v1[2] - Z = __ralloc.v1[3] - r_p2 = __ralloc.v1[4] - r_p1d2 = __ralloc.v1[5] - r_p3d2 = __ralloc.v1[6] - r_p7d2 = __ralloc.v1[7] - newtonianCoeff = __ralloc.v1[8] - ui = __ralloc.v1[9] - vi = __ralloc.v1[10] - wi = __ralloc.v1[11] - U = __ralloc.v1[12] - V = __ralloc.v1[13] - W = __ralloc.v1[14] - _4U_m_3X = __ralloc.v1[15] - _4V_m_3Y = __ralloc.v1[16] - _4W_m_3Z = __ralloc.v1[17] - UU = __ralloc.v1[18] - VV = __ralloc.v1[19] - WW = __ralloc.v1[20] - newtonian1b_Potential = __ralloc.v1[21] - newtonianNb_Potential = __ralloc.v1[22] - newton_acc_X = __ralloc.v1[23] - newton_acc_Y = __ralloc.v1[24] - newton_acc_Z = __ralloc.v1[25] - v2 = __ralloc.v1[26] - vi_dot_vj = __ralloc.v1[27] - pn2 = __ralloc.v1[28] - U_t_pn2 = __ralloc.v1[29] - V_t_pn2 = __ralloc.v1[30] - W_t_pn2 = __ralloc.v1[31] - pn3 = __ralloc.v1[32] - pNX_t_pn3 = __ralloc.v1[33] - pNY_t_pn3 = __ralloc.v1[34] - pNZ_t_pn3 = __ralloc.v1[35] - _4ϕj = __ralloc.v1[36] - ϕi_plus_4ϕj = __ralloc.v1[37] - sj2_plus_2si2_minus_4vivj = __ralloc.v1[38] - ϕs_and_vs = __ralloc.v1[39] - pn1t1_7 = __ralloc.v1[40] - pNX_t_X = __ralloc.v1[41] - pNY_t_Y = __ralloc.v1[42] - pNZ_t_Z = __ralloc.v1[43] - pn1 = __ralloc.v1[44] - X_t_pn1 = __ralloc.v1[45] - Y_t_pn1 = __ralloc.v1[46] - Z_t_pn1 = __ralloc.v1[47] - t31 = __ralloc.v1[48] - t32 = __ralloc.v1[49] - t33 = __ralloc.v1[50] - r_sin_ϕ = __ralloc.v1[51] - sin_ϕ = __ralloc.v1[52] - ϕ = __ralloc.v1[53] - cos_ϕ = __ralloc.v1[54] - sin2_ϕ = __ralloc.v1[55] - sin3_ϕ = __ralloc.v1[56] - F_J2_x = __ralloc.v1[57] - F_J2_y = __ralloc.v1[58] - F_J2_z = __ralloc.v1[59] - F_J2_x1 = __ralloc.v1[60] - F_J2_y1 = __ralloc.v1[61] - F_J2_z1 = __ralloc.v1[62] - F_J2_x2 = __ralloc.v1[63] - F_J2_y2 = __ralloc.v1[64] - F_J2_z2 = __ralloc.v1[65] - temp_accX_i = __ralloc.v1[66] - temp_accY_i = __ralloc.v1[67] - temp_accZ_i = __ralloc.v1[68] - P_2_sin_ϕ = __ralloc.v1[69] - ∂P_2_sin_ϕ = __ralloc.v1[70] - P_3_sin_ϕ = __ralloc.v1[71] - ∂P_3_sin_ϕ = __ralloc.v1[72] - m_c_ϕ_∂P_2 = __ralloc.v1[73] - m_c_ϕ_∂P_3 = __ralloc.v1[74] - Λ2j_div_r4 = __ralloc.v1[75] - Λ3j_div_r5 = __ralloc.v1[76] - F_J_ξ = __ralloc.v1[77] - F_J_ζ = __ralloc.v1[78] - F_J2_ξ = __ralloc.v1[79] - F_J2_ζ = __ralloc.v1[80] - F_J3_ξ = __ralloc.v1[81] - F_J3_ζ = __ralloc.v1[82] - ξx = __ralloc.v1[83] - ξy = __ralloc.v1[84] - ξz = __ralloc.v1[85] - ηx = __ralloc.v1[86] - ηy = __ralloc.v1[87] - ηz = __ralloc.v1[88] - ηx1 = __ralloc.v1[89] - ηy1 = __ralloc.v1[90] - ηz1 = __ralloc.v1[91] - ηx2 = __ralloc.v1[92] - ηy2 = __ralloc.v1[93] - ηz2 = __ralloc.v1[94] - ζx = __ralloc.v1[95] - ζy = __ralloc.v1[96] - ζz = __ralloc.v1[97] - ζx1 = __ralloc.v1[98] - ζy1 = __ralloc.v1[99] - ζz1 = __ralloc.v1[100] - ζx2 = __ralloc.v1[101] - ζy2 = __ralloc.v1[102] - ζz2 = __ralloc.v1[103] - tmp687 = __ralloc.v1[104] - tmp689 = __ralloc.v1[105] - tmp692 = __ralloc.v1[106] - tmp694 = __ralloc.v1[107] - tmp697 = __ralloc.v1[108] - tmp699 = __ralloc.v1[109] - pn2x = __ralloc.v1[110] - pn2y = __ralloc.v1[111] - pn2z = __ralloc.v1[112] - tmp707 = __ralloc.v1[113] - tmp710 = __ralloc.v1[114] - tmp712 = __ralloc.v1[115] - tmp713 = __ralloc.v1[116] - tmp715 = __ralloc.v1[117] - tmp723 = __ralloc.v1[118] - tmp724 = __ralloc.v1[119] - tmp735 = __ralloc.v1[120] - tmp737 = __ralloc.v1[121] - tmp739 = __ralloc.v1[122] - tmp741 = __ralloc.v1[123] - tmp948 = __ralloc.v1[124] - tmp949 = __ralloc.v1[125] - tmp751 = __ralloc.v1[126] - tmp757 = __ralloc.v1[127] - tmp759 = __ralloc.v1[128] - tmp763 = __ralloc.v1[129] - tmp766 = __ralloc.v1[130] - tmp767 = __ralloc.v1[131] - tmp770 = __ralloc.v1[132] - tmp771 = __ralloc.v1[133] - tmp773 = __ralloc.v1[134] - tmp775 = __ralloc.v1[135] - tmp778 = __ralloc.v1[136] - tmp782 = __ralloc.v1[137] - tmp785 = __ralloc.v1[138] - tmp787 = __ralloc.v1[139] - tmp789 = __ralloc.v1[140] - tmp819 = __ralloc.v1[141] - tmp821 = __ralloc.v1[142] - tmp822 = __ralloc.v1[143] - tmp824 = __ralloc.v1[144] - temp_004 = __ralloc.v1[145] - tmp835 = __ralloc.v1[146] - tmp837 = __ralloc.v1[147] - tmp839 = __ralloc.v1[148] - tmp845 = __ralloc.v1[149] - tmp847 = __ralloc.v1[150] - tmp848 = __ralloc.v1[151] - Xij_t_Ui = __ralloc.v1[152] - Yij_t_Vi = __ralloc.v1[153] - Zij_t_Wi = __ralloc.v1[154] - tmp854 = __ralloc.v1[155] - Rij_dot_Vi = __ralloc.v1[156] - tmp857 = __ralloc.v1[157] - pn1t7 = __ralloc.v1[158] - tmp860 = __ralloc.v1[159] - pn1t2_7 = __ralloc.v1[160] - tmp867 = __ralloc.v1[161] - tmp868 = __ralloc.v1[162] - tmp869 = __ralloc.v1[163] - tmp877 = __ralloc.v1[164] - termpnx = __ralloc.v1[165] - sumpnx = __ralloc.v1[166] - tmp880 = __ralloc.v1[167] - termpny = __ralloc.v1[168] - sumpny = __ralloc.v1[169] - tmp883 = __ralloc.v1[170] - termpnz = __ralloc.v1[171] - sumpnz = __ralloc.v1[172] - local jd0 = params[4] - local dsj2k = t + (jd0 - JD_J2000) - local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) - local acceph_t = evaleph(params[2], dsj2k, q[1]) - local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) - local S = eltype(q) - local UJ_interaction = params[5] - local N = params[6] - local Nm1 = N - 1 - local μ = params[7] - local zero_q_1 = auxzero(q[1]) - pntempX.coeffs[1] = identity(constant_term(zero_q_1)) - pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) - pntempY.coeffs[1] = identity(constant_term(zero_q_1)) - pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) - pntempZ.coeffs[1] = identity(constant_term(zero_q_1)) - pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) - accX.coeffs[1] = identity(constant_term(zero_q_1)) - accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) - accY.coeffs[1] = identity(constant_term(zero_q_1)) - accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) - accZ.coeffs[1] = identity(constant_term(zero_q_1)) - accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) - local M_ = Array{S}(undef, 3, 3, N) - local M_ .= zero_q_1 - local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 - (dq[1]).coeffs[1] = identity(constant_term(q[4])) - (dq[1]).coeffs[2:order + 1] .= zero((dq[1]).coeffs[1]) - (dq[2]).coeffs[1] = identity(constant_term(q[5])) - (dq[2]).coeffs[2:order + 1] .= zero((dq[2]).coeffs[1]) - (dq[3]).coeffs[1] = identity(constant_term(q[6])) - (dq[3]).coeffs[2:order + 1] .= zero((dq[3]).coeffs[1]) - (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(zero_q_1)) - (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 - (ui[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])) - (ui[i]).coeffs[2:order + 1] .= zero((ui[i]).coeffs[1]) - (vi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])) - (vi[i]).coeffs[2:order + 1] .= zero((vi[i]).coeffs[1]) - (wi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])) - (wi[i]).coeffs[2:order + 1] .= zero((wi[i]).coeffs[1]) - (X[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 2]) - constant_term(q[1]) - (X[i]).coeffs[2:order + 1] .= zero((X[i]).coeffs[1]) - (Y[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 1]) - constant_term(q[2]) - (Y[i]).coeffs[2:order + 1] .= zero((Y[i]).coeffs[1]) - (Z[i]).coeffs[1] = constant_term(ss16asteph_t[3i]) - constant_term(q[3]) - (Z[i]).coeffs[2:order + 1] .= zero((Z[i]).coeffs[1]) - (U[i]).coeffs[1] = constant_term(ui[i]) - constant_term(dq[1]) - (U[i]).coeffs[2:order + 1] .= zero((U[i]).coeffs[1]) - (V[i]).coeffs[1] = constant_term(vi[i]) - constant_term(dq[2]) - (V[i]).coeffs[2:order + 1] .= zero((V[i]).coeffs[1]) - (W[i]).coeffs[1] = constant_term(wi[i]) - constant_term(dq[3]) - (W[i]).coeffs[2:order + 1] .= zero((W[i]).coeffs[1]) - (tmp687[1]).coeffs[1] = constant_term(4) * constant_term(dq[1]) - (tmp687[1]).coeffs[2:order + 1] .= zero((tmp687[1]).coeffs[1]) - (tmp689[i]).coeffs[1] = constant_term(3) * constant_term(ui[i]) - (tmp689[i]).coeffs[2:order + 1] .= zero((tmp689[i]).coeffs[1]) - (_4U_m_3X[i]).coeffs[1] = constant_term(tmp687[1]) - constant_term(tmp689[i]) - (_4U_m_3X[i]).coeffs[2:order + 1] .= zero((_4U_m_3X[i]).coeffs[1]) - (tmp692[2]).coeffs[1] = constant_term(4) * constant_term(dq[2]) - (tmp692[2]).coeffs[2:order + 1] .= zero((tmp692[2]).coeffs[1]) - (tmp694[i]).coeffs[1] = constant_term(3) * constant_term(vi[i]) - (tmp694[i]).coeffs[2:order + 1] .= zero((tmp694[i]).coeffs[1]) - (_4V_m_3Y[i]).coeffs[1] = constant_term(tmp692[2]) - constant_term(tmp694[i]) - (_4V_m_3Y[i]).coeffs[2:order + 1] .= zero((_4V_m_3Y[i]).coeffs[1]) - (tmp697[3]).coeffs[1] = constant_term(4) * constant_term(dq[3]) - (tmp697[3]).coeffs[2:order + 1] .= zero((tmp697[3]).coeffs[1]) - (tmp699[i]).coeffs[1] = constant_term(3) * constant_term(wi[i]) - (tmp699[i]).coeffs[2:order + 1] .= zero((tmp699[i]).coeffs[1]) - (_4W_m_3Z[i]).coeffs[1] = constant_term(tmp697[3]) - constant_term(tmp699[i]) - (_4W_m_3Z[i]).coeffs[2:order + 1] .= zero((_4W_m_3Z[i]).coeffs[1]) - (pn2x[i]).coeffs[1] = constant_term(X[i]) * constant_term(_4U_m_3X[i]) - (pn2x[i]).coeffs[2:order + 1] .= zero((pn2x[i]).coeffs[1]) - (pn2y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(_4V_m_3Y[i]) - (pn2y[i]).coeffs[2:order + 1] .= zero((pn2y[i]).coeffs[1]) - (pn2z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(_4W_m_3Z[i]) - (pn2z[i]).coeffs[2:order + 1] .= zero((pn2z[i]).coeffs[1]) - (UU[i]).coeffs[1] = constant_term(ui[i]) * constant_term(dq[1]) - (UU[i]).coeffs[2:order + 1] .= zero((UU[i]).coeffs[1]) - (VV[i]).coeffs[1] = constant_term(vi[i]) * constant_term(dq[2]) - (VV[i]).coeffs[2:order + 1] .= zero((VV[i]).coeffs[1]) - (WW[i]).coeffs[1] = constant_term(wi[i]) * constant_term(dq[3]) - (WW[i]).coeffs[2:order + 1] .= zero((WW[i]).coeffs[1]) - (tmp707[i]).coeffs[1] = constant_term(UU[i]) + constant_term(VV[i]) - (tmp707[i]).coeffs[2:order + 1] .= zero((tmp707[i]).coeffs[1]) - (vi_dot_vj[i]).coeffs[1] = constant_term(tmp707[i]) + constant_term(WW[i]) - (vi_dot_vj[i]).coeffs[2:order + 1] .= zero((vi_dot_vj[i]).coeffs[1]) - (tmp710[i]).coeffs[1] = constant_term(X[i]) ^ float(constant_term(2)) - (tmp710[i]).coeffs[2:order + 1] .= zero((tmp710[i]).coeffs[1]) - (tmp712[i]).coeffs[1] = constant_term(Y[i]) ^ float(constant_term(2)) - (tmp712[i]).coeffs[2:order + 1] .= zero((tmp712[i]).coeffs[1]) - (tmp713[i]).coeffs[1] = constant_term(tmp710[i]) + constant_term(tmp712[i]) - (tmp713[i]).coeffs[2:order + 1] .= zero((tmp713[i]).coeffs[1]) - (tmp715[i]).coeffs[1] = constant_term(Z[i]) ^ float(constant_term(2)) - (tmp715[i]).coeffs[2:order + 1] .= zero((tmp715[i]).coeffs[1]) - (r_p2[i]).coeffs[1] = constant_term(tmp713[i]) + constant_term(tmp715[i]) - (r_p2[i]).coeffs[2:order + 1] .= zero((r_p2[i]).coeffs[1]) - (r_p1d2[i]).coeffs[1] = sqrt(constant_term(r_p2[i])) - (r_p1d2[i]).coeffs[2:order + 1] .= zero((r_p1d2[i]).coeffs[1]) - (r_p3d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(1.5)) - (r_p3d2[i]).coeffs[2:order + 1] .= zero((r_p3d2[i]).coeffs[1]) - (r_p7d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(3.5)) - (r_p7d2[i]).coeffs[2:order + 1] .= zero((r_p7d2[i]).coeffs[1]) - (newtonianCoeff[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p3d2[i]) - (newtonianCoeff[i]).coeffs[2:order + 1] .= zero((newtonianCoeff[i]).coeffs[1]) - (tmp723[i]).coeffs[1] = constant_term(pn2x[i]) + constant_term(pn2y[i]) - (tmp723[i]).coeffs[2:order + 1] .= zero((tmp723[i]).coeffs[1]) - (tmp724[i]).coeffs[1] = constant_term(tmp723[i]) + constant_term(pn2z[i]) - (tmp724[i]).coeffs[2:order + 1] .= zero((tmp724[i]).coeffs[1]) - (pn2[i]).coeffs[1] = constant_term(newtonianCoeff[i]) * constant_term(tmp724[i]) - (pn2[i]).coeffs[2:order + 1] .= zero((pn2[i]).coeffs[1]) - (newton_acc_X[i]).coeffs[1] = constant_term(X[i]) * constant_term(newtonianCoeff[i]) - (newton_acc_X[i]).coeffs[2:order + 1] .= zero((newton_acc_X[i]).coeffs[1]) - (newton_acc_Y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(newtonianCoeff[i]) - (newton_acc_Y[i]).coeffs[2:order + 1] .= zero((newton_acc_Y[i]).coeffs[1]) - (newton_acc_Z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(newtonianCoeff[i]) - (newton_acc_Z[i]).coeffs[2:order + 1] .= zero((newton_acc_Z[i]).coeffs[1]) - (newtonian1b_Potential[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p1d2[i]) - (newtonian1b_Potential[i]).coeffs[2:order + 1] .= zero((newtonian1b_Potential[i]).coeffs[1]) - (pn3[i]).coeffs[1] = constant_term(3.5) * constant_term(newtonian1b_Potential[i]) - (pn3[i]).coeffs[2:order + 1] .= zero((pn3[i]).coeffs[1]) - (U_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(U[i]) - (U_t_pn2[i]).coeffs[2:order + 1] .= zero((U_t_pn2[i]).coeffs[1]) - (V_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(V[i]) - (V_t_pn2[i]).coeffs[2:order + 1] .= zero((V_t_pn2[i]).coeffs[1]) - (W_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(W[i]) - (W_t_pn2[i]).coeffs[2:order + 1] .= zero((W_t_pn2[i]).coeffs[1]) - if UJ_interaction[i] - (tmp735[i]).coeffs[1] = -(constant_term(X[i])) - (tmp735[i]).coeffs[2:order + 1] .= zero((tmp735[i]).coeffs[1]) - (t31[i]).coeffs[1] = constant_term(tmp735[i]) * constant_term(M_[1, 3, i]) - (t31[i]).coeffs[2:order + 1] .= zero((t31[i]).coeffs[1]) - (tmp737[i]).coeffs[1] = -(constant_term(Y[i])) - (tmp737[i]).coeffs[2:order + 1] .= zero((tmp737[i]).coeffs[1]) - (t32[i]).coeffs[1] = constant_term(tmp737[i]) * constant_term(M_[2, 3, i]) - (t32[i]).coeffs[2:order + 1] .= zero((t32[i]).coeffs[1]) - (tmp739[i]).coeffs[1] = -(constant_term(Z[i])) - (tmp739[i]).coeffs[2:order + 1] .= zero((tmp739[i]).coeffs[1]) - (t33[i]).coeffs[1] = constant_term(tmp739[i]) * constant_term(M_[3, 3, i]) - (t33[i]).coeffs[2:order + 1] .= zero((t33[i]).coeffs[1]) - (tmp741[i]).coeffs[1] = constant_term(t31[i]) + constant_term(t32[i]) - (tmp741[i]).coeffs[2:order + 1] .= zero((tmp741[i]).coeffs[1]) - (r_sin_ϕ[i]).coeffs[1] = constant_term(tmp741[i]) + constant_term(t33[i]) - (r_sin_ϕ[i]).coeffs[2:order + 1] .= zero((r_sin_ϕ[i]).coeffs[1]) - (sin_ϕ[i]).coeffs[1] = constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]) - (sin_ϕ[i]).coeffs[2:order + 1] .= zero((sin_ϕ[i]).coeffs[1]) - (ϕ[i]).coeffs[1] = asin(constant_term(sin_ϕ[i])) - (ϕ[i]).coeffs[2:order + 1] .= zero((ϕ[i]).coeffs[1]) - (tmp948[i]).coeffs[1] = sqrt(1 - constant_term(sin_ϕ[i]) ^ 2) - (tmp948[i]).coeffs[2:order + 1] .= zero((tmp948[i]).coeffs[1]) - (cos_ϕ[i]).coeffs[1] = cos(constant_term(ϕ[i])) - (cos_ϕ[i]).coeffs[2:order + 1] .= zero((cos_ϕ[i]).coeffs[1]) - (tmp949[i]).coeffs[1] = sin(constant_term(ϕ[i])) - (tmp949[i]).coeffs[2:order + 1] .= zero((tmp949[i]).coeffs[1]) - (sin2_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(2)) - (sin2_ϕ[i]).coeffs[2:order + 1] .= zero((sin2_ϕ[i]).coeffs[1]) - (sin3_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(3)) - (sin3_ϕ[i]).coeffs[2:order + 1] .= zero((sin3_ϕ[i]).coeffs[1]) - (tmp751[i]).coeffs[1] = constant_term(1.5) * constant_term(sin2_ϕ[i]) - (tmp751[i]).coeffs[2:order + 1] .= zero((tmp751[i]).coeffs[1]) - (P_2_sin_ϕ[i]).coeffs[1] = constant_term(tmp751[i]) - constant_term(0.5) - (P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_2_sin_ϕ[i]).coeffs[1]) - (∂P_2_sin_ϕ[i]).coeffs[1] = constant_term(3) * constant_term(sin_ϕ[i]) - (∂P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_2_sin_ϕ[i]).coeffs[1]) - (tmp757[i]).coeffs[1] = constant_term(-1.5) * constant_term(sin_ϕ[i]) - (tmp757[i]).coeffs[2:order + 1] .= zero((tmp757[i]).coeffs[1]) - (tmp759[i]).coeffs[1] = constant_term(2.5) * constant_term(sin3_ϕ[i]) - (tmp759[i]).coeffs[2:order + 1] .= zero((tmp759[i]).coeffs[1]) - (P_3_sin_ϕ[i]).coeffs[1] = constant_term(tmp757[i]) + constant_term(tmp759[i]) - (P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_3_sin_ϕ[i]).coeffs[1]) - (tmp763[i]).coeffs[1] = constant_term(7.5) * constant_term(sin2_ϕ[i]) - (tmp763[i]).coeffs[2:order + 1] .= zero((tmp763[i]).coeffs[1]) - (∂P_3_sin_ϕ[i]).coeffs[1] = constant_term(-1.5) + constant_term(tmp763[i]) - (∂P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_3_sin_ϕ[i]).coeffs[1]) - (tmp766[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(2)) - (tmp766[i]).coeffs[2:order + 1] .= zero((tmp766[i]).coeffs[1]) - (tmp767[i]).coeffs[1] = constant_term(Λ2[i]) / constant_term(tmp766[i]) - (tmp767[i]).coeffs[2:order + 1] .= zero((tmp767[i]).coeffs[1]) - (Λ2j_div_r4[i]).coeffs[1] = -(constant_term(tmp767[i])) - (Λ2j_div_r4[i]).coeffs[2:order + 1] .= zero((Λ2j_div_r4[i]).coeffs[1]) - (tmp770[i]).coeffs[1] = constant_term(r_p1d2[i]) ^ float(constant_term(5)) - (tmp770[i]).coeffs[2:order + 1] .= zero((tmp770[i]).coeffs[1]) - (tmp771[i]).coeffs[1] = constant_term(Λ3[i]) / constant_term(tmp770[i]) - (tmp771[i]).coeffs[2:order + 1] .= zero((tmp771[i]).coeffs[1]) - (Λ3j_div_r5[i]).coeffs[1] = -(constant_term(tmp771[i])) - (Λ3j_div_r5[i]).coeffs[2:order + 1] .= zero((Λ3j_div_r5[i]).coeffs[1]) - (tmp773[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) - (tmp773[i]).coeffs[2:order + 1] .= zero((tmp773[i]).coeffs[1]) - (m_c_ϕ_∂P_2[i]).coeffs[1] = constant_term(tmp773[i]) * constant_term(∂P_2_sin_ϕ[i]) - (m_c_ϕ_∂P_2[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_2[i]).coeffs[1]) - (tmp775[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) - (tmp775[i]).coeffs[2:order + 1] .= zero((tmp775[i]).coeffs[1]) - (m_c_ϕ_∂P_3[i]).coeffs[1] = constant_term(tmp775[i]) * constant_term(∂P_3_sin_ϕ[i]) - (m_c_ϕ_∂P_3[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_3[i]).coeffs[1]) - (tmp778[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(3) - (tmp778[i]).coeffs[2:order + 1] .= zero((tmp778[i]).coeffs[1]) - (F_J2_ξ[i]).coeffs[1] = constant_term(tmp778[i]) * constant_term(P_2_sin_ϕ[i]) - (F_J2_ξ[i]).coeffs[2:order + 1] .= zero((F_J2_ξ[i]).coeffs[1]) - (F_J2_ζ[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]) - (F_J2_ζ[i]).coeffs[2:order + 1] .= zero((F_J2_ζ[i]).coeffs[1]) - (tmp782[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(4) - (tmp782[i]).coeffs[2:order + 1] .= zero((tmp782[i]).coeffs[1]) - (F_J3_ξ[i]).coeffs[1] = constant_term(tmp782[i]) * constant_term(P_3_sin_ϕ[i]) - (F_J3_ξ[i]).coeffs[2:order + 1] .= zero((F_J3_ξ[i]).coeffs[1]) - (F_J3_ζ[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]) - (F_J3_ζ[i]).coeffs[2:order + 1] .= zero((F_J3_ζ[i]).coeffs[1]) - (F_J_ξ[i]).coeffs[1] = identity(constant_term(F_J2_ξ[i])) - (F_J_ξ[i]).coeffs[2:order + 1] .= zero((F_J_ξ[i]).coeffs[1]) - (F_J_ζ[i]).coeffs[1] = identity(constant_term(F_J2_ζ[i])) - (F_J_ζ[i]).coeffs[2:order + 1] .= zero((F_J_ζ[i]).coeffs[1]) - (tmp785[i]).coeffs[1] = -(constant_term(X[i])) - (tmp785[i]).coeffs[2:order + 1] .= zero((tmp785[i]).coeffs[1]) - (ξx[i]).coeffs[1] = constant_term(tmp785[i]) / constant_term(r_p1d2[i]) - (ξx[i]).coeffs[2:order + 1] .= zero((ξx[i]).coeffs[1]) - (tmp787[i]).coeffs[1] = -(constant_term(Y[i])) - (tmp787[i]).coeffs[2:order + 1] .= zero((tmp787[i]).coeffs[1]) - (ξy[i]).coeffs[1] = constant_term(tmp787[i]) / constant_term(r_p1d2[i]) - (ξy[i]).coeffs[2:order + 1] .= zero((ξy[i]).coeffs[1]) - (tmp789[i]).coeffs[1] = -(constant_term(Z[i])) - (tmp789[i]).coeffs[2:order + 1] .= zero((tmp789[i]).coeffs[1]) - (ξz[i]).coeffs[1] = constant_term(tmp789[i]) / constant_term(r_p1d2[i]) - (ξz[i]).coeffs[2:order + 1] .= zero((ξz[i]).coeffs[1]) - (ηx1[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξz[i]) - (ηx1[i]).coeffs[2:order + 1] .= zero((ηx1[i]).coeffs[1]) - (ηy1[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξx[i]) - (ηy1[i]).coeffs[2:order + 1] .= zero((ηy1[i]).coeffs[1]) - (ηz1[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξy[i]) - (ηz1[i]).coeffs[2:order + 1] .= zero((ηz1[i]).coeffs[1]) - (ηx2[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξy[i]) - (ηx2[i]).coeffs[2:order + 1] .= zero((ηx2[i]).coeffs[1]) - (ηy2[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξz[i]) - (ηy2[i]).coeffs[2:order + 1] .= zero((ηy2[i]).coeffs[1]) - (ηz2[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξx[i]) - (ηz2[i]).coeffs[2:order + 1] .= zero((ηz2[i]).coeffs[1]) - (ηx[i]).coeffs[1] = constant_term(ηx1[i]) - constant_term(ηx2[i]) - (ηx[i]).coeffs[2:order + 1] .= zero((ηx[i]).coeffs[1]) - (ηy[i]).coeffs[1] = constant_term(ηy1[i]) - constant_term(ηy2[i]) - (ηy[i]).coeffs[2:order + 1] .= zero((ηy[i]).coeffs[1]) - (ηz[i]).coeffs[1] = constant_term(ηz1[i]) - constant_term(ηz2[i]) - (ηz[i]).coeffs[2:order + 1] .= zero((ηz[i]).coeffs[1]) - (ζx1[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηz[i]) - (ζx1[i]).coeffs[2:order + 1] .= zero((ζx1[i]).coeffs[1]) - (ζy1[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηx[i]) - (ζy1[i]).coeffs[2:order + 1] .= zero((ζy1[i]).coeffs[1]) - (ζz1[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηy[i]) - (ζz1[i]).coeffs[2:order + 1] .= zero((ζz1[i]).coeffs[1]) - (ζx2[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηy[i]) - (ζx2[i]).coeffs[2:order + 1] .= zero((ζx2[i]).coeffs[1]) - (ζy2[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηz[i]) - (ζy2[i]).coeffs[2:order + 1] .= zero((ζy2[i]).coeffs[1]) - (ζz2[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηx[i]) - (ζz2[i]).coeffs[2:order + 1] .= zero((ζz2[i]).coeffs[1]) - (ζx[i]).coeffs[1] = constant_term(ζx1[i]) - constant_term(ζx2[i]) - (ζx[i]).coeffs[2:order + 1] .= zero((ζx[i]).coeffs[1]) - (ζy[i]).coeffs[1] = constant_term(ζy1[i]) - constant_term(ζy2[i]) - (ζy[i]).coeffs[2:order + 1] .= zero((ζy[i]).coeffs[1]) - (ζz[i]).coeffs[1] = constant_term(ζz1[i]) - constant_term(ζz2[i]) - (ζz[i]).coeffs[2:order + 1] .= zero((ζz[i]).coeffs[1]) - (F_J2_x1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξx[i]) - (F_J2_x1[i]).coeffs[2:order + 1] .= zero((F_J2_x1[i]).coeffs[1]) - (F_J2_y1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξy[i]) - (F_J2_y1[i]).coeffs[2:order + 1] .= zero((F_J2_y1[i]).coeffs[1]) - (F_J2_z1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξz[i]) - (F_J2_z1[i]).coeffs[2:order + 1] .= zero((F_J2_z1[i]).coeffs[1]) - (F_J2_x2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζx[i]) - (F_J2_x2[i]).coeffs[2:order + 1] .= zero((F_J2_x2[i]).coeffs[1]) - (F_J2_y2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζy[i]) - (F_J2_y2[i]).coeffs[2:order + 1] .= zero((F_J2_y2[i]).coeffs[1]) - (F_J2_z2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζz[i]) - (F_J2_z2[i]).coeffs[2:order + 1] .= zero((F_J2_z2[i]).coeffs[1]) - (F_J2_x[i]).coeffs[1] = constant_term(F_J2_x1[i]) + constant_term(F_J2_x2[i]) - (F_J2_x[i]).coeffs[2:order + 1] .= zero((F_J2_x[i]).coeffs[1]) - (F_J2_y[i]).coeffs[1] = constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]) - (F_J2_y[i]).coeffs[2:order + 1] .= zero((F_J2_y[i]).coeffs[1]) - (F_J2_z[i]).coeffs[1] = constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]) - (F_J2_z[i]).coeffs[2:order + 1] .= zero((F_J2_z[i]).coeffs[1]) - end - (tmp819[i]).coeffs[1] = constant_term(ui[i]) ^ float(constant_term(2)) - (tmp819[i]).coeffs[2:order + 1] .= zero((tmp819[i]).coeffs[1]) - (tmp821[i]).coeffs[1] = constant_term(vi[i]) ^ float(constant_term(2)) - (tmp821[i]).coeffs[2:order + 1] .= zero((tmp821[i]).coeffs[1]) - (tmp822[i]).coeffs[1] = constant_term(tmp819[i]) + constant_term(tmp821[i]) - (tmp822[i]).coeffs[2:order + 1] .= zero((tmp822[i]).coeffs[1]) - (tmp824[i]).coeffs[1] = constant_term(wi[i]) ^ float(constant_term(2)) - (tmp824[i]).coeffs[2:order + 1] .= zero((tmp824[i]).coeffs[1]) - (v2[i]).coeffs[1] = constant_term(tmp822[i]) + constant_term(tmp824[i]) - (v2[i]).coeffs[2:order + 1] .= zero((v2[i]).coeffs[1]) - end - tmp827.coeffs[1] = constant_term(q[4]) ^ float(constant_term(2)) - tmp827.coeffs[2:order + 1] .= zero(tmp827.coeffs[1]) - tmp829.coeffs[1] = constant_term(q[5]) ^ float(constant_term(2)) - tmp829.coeffs[2:order + 1] .= zero(tmp829.coeffs[1]) - tmp830.coeffs[1] = constant_term(tmp827) + constant_term(tmp829) - tmp830.coeffs[2:order + 1] .= zero(tmp830.coeffs[1]) - tmp832.coeffs[1] = constant_term(q[6]) ^ float(constant_term(2)) - tmp832.coeffs[2:order + 1] .= zero(tmp832.coeffs[1]) - (v2[N]).coeffs[1] = constant_term(tmp830) + constant_term(tmp832) - (v2[N]).coeffs[2:order + 1] .= zero((v2[N]).coeffs[1]) - for i = 1:Nm1 - (temp_004[i]).coeffs[1] = constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]) - (temp_004[i]).coeffs[2:order + 1] .= zero((temp_004[i]).coeffs[1]) - (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(temp_004[i])) - (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) - if UJ_interaction[i] - (tmp835[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_x[i]) - (tmp835[i]).coeffs[2:order + 1] .= zero((tmp835[i]).coeffs[1]) - (temp_accX_i[i]).coeffs[1] = constant_term(accX) - constant_term(tmp835[i]) - (temp_accX_i[i]).coeffs[2:order + 1] .= zero((temp_accX_i[i]).coeffs[1]) - accX.coeffs[1] = identity(constant_term(temp_accX_i[i])) - accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) - (tmp837[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_y[i]) - (tmp837[i]).coeffs[2:order + 1] .= zero((tmp837[i]).coeffs[1]) - (temp_accY_i[i]).coeffs[1] = constant_term(accY) - constant_term(tmp837[i]) - (temp_accY_i[i]).coeffs[2:order + 1] .= zero((temp_accY_i[i]).coeffs[1]) - accY.coeffs[1] = identity(constant_term(temp_accY_i[i])) - accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) - (tmp839[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_z[i]) - (tmp839[i]).coeffs[2:order + 1] .= zero((tmp839[i]).coeffs[1]) - (temp_accZ_i[i]).coeffs[1] = constant_term(accZ) - constant_term(tmp839[i]) - (temp_accZ_i[i]).coeffs[2:order + 1] .= zero((temp_accZ_i[i]).coeffs[1]) - accZ.coeffs[1] = identity(constant_term(temp_accZ_i[i])) - accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) - end - end - (_4ϕj[N]).coeffs[1] = constant_term(4) * constant_term(newtonianNb_Potential[N]) - (_4ϕj[N]).coeffs[2:order + 1] .= zero((_4ϕj[N]).coeffs[1]) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 - (ϕi_plus_4ϕj[i]).coeffs[1] = constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]) - (ϕi_plus_4ϕj[i]).coeffs[2:order + 1] .= zero((ϕi_plus_4ϕj[i]).coeffs[1]) - (tmp845[i]).coeffs[1] = constant_term(2) * constant_term(v2[i]) - (tmp845[i]).coeffs[2:order + 1] .= zero((tmp845[i]).coeffs[1]) - (tmp847[i]).coeffs[1] = constant_term(4) * constant_term(vi_dot_vj[i]) - (tmp847[i]).coeffs[2:order + 1] .= zero((tmp847[i]).coeffs[1]) - (tmp848[i]).coeffs[1] = constant_term(tmp845[i]) - constant_term(tmp847[i]) - (tmp848[i]).coeffs[2:order + 1] .= zero((tmp848[i]).coeffs[1]) - (sj2_plus_2si2_minus_4vivj[i]).coeffs[1] = constant_term(tmp848[i]) + constant_term(v2[N]) - (sj2_plus_2si2_minus_4vivj[i]).coeffs[2:order + 1] .= zero((sj2_plus_2si2_minus_4vivj[i]).coeffs[1]) - (ϕs_and_vs[i]).coeffs[1] = constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]) - (ϕs_and_vs[i]).coeffs[2:order + 1] .= zero((ϕs_and_vs[i]).coeffs[1]) - (Xij_t_Ui[i]).coeffs[1] = constant_term(X[i]) * constant_term(ui[i]) - (Xij_t_Ui[i]).coeffs[2:order + 1] .= zero((Xij_t_Ui[i]).coeffs[1]) - (Yij_t_Vi[i]).coeffs[1] = constant_term(Y[i]) * constant_term(vi[i]) - (Yij_t_Vi[i]).coeffs[2:order + 1] .= zero((Yij_t_Vi[i]).coeffs[1]) - (Zij_t_Wi[i]).coeffs[1] = constant_term(Z[i]) * constant_term(wi[i]) - (Zij_t_Wi[i]).coeffs[2:order + 1] .= zero((Zij_t_Wi[i]).coeffs[1]) - (tmp854[i]).coeffs[1] = constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]) - (tmp854[i]).coeffs[2:order + 1] .= zero((tmp854[i]).coeffs[1]) - (Rij_dot_Vi[i]).coeffs[1] = constant_term(tmp854[i]) + constant_term(Zij_t_Wi[i]) - (Rij_dot_Vi[i]).coeffs[2:order + 1] .= zero((Rij_dot_Vi[i]).coeffs[1]) - (tmp857[i]).coeffs[1] = constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)) - (tmp857[i]).coeffs[2:order + 1] .= zero((tmp857[i]).coeffs[1]) - (pn1t7[i]).coeffs[1] = constant_term(tmp857[i]) / constant_term(r_p2[i]) - (pn1t7[i]).coeffs[2:order + 1] .= zero((pn1t7[i]).coeffs[1]) - (tmp860[i]).coeffs[1] = constant_term(1.5) * constant_term(pn1t7[i]) - (tmp860[i]).coeffs[2:order + 1] .= zero((tmp860[i]).coeffs[1]) - (pn1t2_7[i]).coeffs[1] = constant_term(ϕs_and_vs[i]) - constant_term(tmp860[i]) - (pn1t2_7[i]).coeffs[2:order + 1] .= zero((pn1t2_7[i]).coeffs[1]) - (pn1t1_7[i]).coeffs[1] = constant_term(c_p2) + constant_term(pn1t2_7[i]) - (pn1t1_7[i]).coeffs[2:order + 1] .= zero((pn1t1_7[i]).coeffs[1]) - (pNX_t_X[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(X[i]) - (pNX_t_X[i]).coeffs[2:order + 1] .= zero((pNX_t_X[i]).coeffs[1]) - (pNY_t_Y[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(Y[i]) - (pNY_t_Y[i]).coeffs[2:order + 1] .= zero((pNY_t_Y[i]).coeffs[1]) - (pNZ_t_Z[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(Z[i]) - (pNZ_t_Z[i]).coeffs[2:order + 1] .= zero((pNZ_t_Z[i]).coeffs[1]) - (tmp867[i]).coeffs[1] = constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]) - (tmp867[i]).coeffs[2:order + 1] .= zero((tmp867[i]).coeffs[1]) - (tmp868[i]).coeffs[1] = constant_term(tmp867[i]) + constant_term(pNZ_t_Z[i]) - (tmp868[i]).coeffs[2:order + 1] .= zero((tmp868[i]).coeffs[1]) - (tmp869[i]).coeffs[1] = constant_term(0.5) * constant_term(tmp868[i]) - (tmp869[i]).coeffs[2:order + 1] .= zero((tmp869[i]).coeffs[1]) - (pn1[i]).coeffs[1] = constant_term(pn1t1_7[i]) + constant_term(tmp869[i]) - (pn1[i]).coeffs[2:order + 1] .= zero((pn1[i]).coeffs[1]) - (X_t_pn1[i]).coeffs[1] = constant_term(newton_acc_X[i]) * constant_term(pn1[i]) - (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) - (Y_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Y[i]) * constant_term(pn1[i]) - (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) - (Z_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Z[i]) * constant_term(pn1[i]) - (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) - (pNX_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(pn3[i]) - (pNX_t_pn3[i]).coeffs[2:order + 1] .= zero((pNX_t_pn3[i]).coeffs[1]) - (pNY_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]) - (pNY_t_pn3[i]).coeffs[2:order + 1] .= zero((pNY_t_pn3[i]).coeffs[1]) - (pNZ_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(pn3[i]) - (pNZ_t_pn3[i]).coeffs[2:order + 1] .= zero((pNZ_t_pn3[i]).coeffs[1]) - end - for i = 1:10 - (tmp877[i]).coeffs[1] = constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]) - (tmp877[i]).coeffs[2:order + 1] .= zero((tmp877[i]).coeffs[1]) - (termpnx[i]).coeffs[1] = constant_term(X_t_pn1[i]) + constant_term(tmp877[i]) - (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) - (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) - (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) - pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) - pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) - (tmp880[i]).coeffs[1] = constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]) - (tmp880[i]).coeffs[2:order + 1] .= zero((tmp880[i]).coeffs[1]) - (termpny[i]).coeffs[1] = constant_term(Y_t_pn1[i]) + constant_term(tmp880[i]) - (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) - (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) - (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) - pntempY.coeffs[1] = identity(constant_term(sumpny[i])) - pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) - (tmp883[i]).coeffs[1] = constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]) - (tmp883[i]).coeffs[2:order + 1] .= zero((tmp883[i]).coeffs[1]) - (termpnz[i]).coeffs[1] = constant_term(Z_t_pn1[i]) + constant_term(tmp883[i]) - (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) - (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) - (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) - pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) - pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) - end - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 - (X_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_X[i]) - (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) - (Y_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Y[i]) - (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) - (Z_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Z[i]) - (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) - end - for i = 11:Nm1 - (termpnx[i]).coeffs[1] = identity(constant_term(X_t_pn1[i])) - (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) - (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) - (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) - pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) - pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) - (termpny[i]).coeffs[1] = identity(constant_term(Y_t_pn1[i])) - (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) - (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) - (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) - pntempY.coeffs[1] = identity(constant_term(sumpny[i])) - pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) - (termpnz[i]).coeffs[1] = identity(constant_term(Z_t_pn1[i])) - (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) - (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) - (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) - pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) - pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) - end - postNewtonX.coeffs[1] = constant_term(pntempX) * constant_term(c_m2) - postNewtonX.coeffs[2:order + 1] .= zero(postNewtonX.coeffs[1]) - postNewtonY.coeffs[1] = constant_term(pntempY) * constant_term(c_m2) - postNewtonY.coeffs[2:order + 1] .= zero(postNewtonY.coeffs[1]) - postNewtonZ.coeffs[1] = constant_term(pntempZ) * constant_term(c_m2) - postNewtonZ.coeffs[2:order + 1] .= zero(postNewtonZ.coeffs[1]) - tmp895.coeffs[1] = constant_term(Y[1]) * constant_term(W[1]) - tmp895.coeffs[2:order + 1] .= zero(tmp895.coeffs[1]) - tmp896.coeffs[1] = constant_term(Z[1]) * constant_term(V[1]) - tmp896.coeffs[2:order + 1] .= zero(tmp896.coeffs[1]) - hx.coeffs[1] = constant_term(tmp895) - constant_term(tmp896) - hx.coeffs[2:order + 1] .= zero(hx.coeffs[1]) - tmp898.coeffs[1] = constant_term(Z[1]) * constant_term(U[1]) - tmp898.coeffs[2:order + 1] .= zero(tmp898.coeffs[1]) - tmp899.coeffs[1] = constant_term(X[1]) * constant_term(W[1]) - tmp899.coeffs[2:order + 1] .= zero(tmp899.coeffs[1]) - hy.coeffs[1] = constant_term(tmp898) - constant_term(tmp899) - hy.coeffs[2:order + 1] .= zero(hy.coeffs[1]) - tmp901.coeffs[1] = constant_term(X[1]) * constant_term(V[1]) - tmp901.coeffs[2:order + 1] .= zero(tmp901.coeffs[1]) - tmp902.coeffs[1] = constant_term(Y[1]) * constant_term(U[1]) - tmp902.coeffs[2:order + 1] .= zero(tmp902.coeffs[1]) - hz.coeffs[1] = constant_term(tmp901) - constant_term(tmp902) - hz.coeffs[2:order + 1] .= zero(hz.coeffs[1]) - tmp904.coeffs[1] = constant_term(hz) * constant_term(Y[1]) - tmp904.coeffs[2:order + 1] .= zero(tmp904.coeffs[1]) - tmp905.coeffs[1] = constant_term(hy) * constant_term(Z[1]) - tmp905.coeffs[2:order + 1] .= zero(tmp905.coeffs[1]) - t_x.coeffs[1] = constant_term(tmp904) - constant_term(tmp905) - t_x.coeffs[2:order + 1] .= zero(t_x.coeffs[1]) - tmp907.coeffs[1] = constant_term(hx) * constant_term(Z[1]) - tmp907.coeffs[2:order + 1] .= zero(tmp907.coeffs[1]) - tmp908.coeffs[1] = constant_term(hz) * constant_term(X[1]) - tmp908.coeffs[2:order + 1] .= zero(tmp908.coeffs[1]) - t_y.coeffs[1] = constant_term(tmp907) - constant_term(tmp908) - t_y.coeffs[2:order + 1] .= zero(t_y.coeffs[1]) - tmp910.coeffs[1] = constant_term(hy) * constant_term(X[1]) - tmp910.coeffs[2:order + 1] .= zero(tmp910.coeffs[1]) - tmp911.coeffs[1] = constant_term(hx) * constant_term(Y[1]) - tmp911.coeffs[2:order + 1] .= zero(tmp911.coeffs[1]) - t_z.coeffs[1] = constant_term(tmp910) - constant_term(tmp911) - t_z.coeffs[2:order + 1] .= zero(t_z.coeffs[1]) - tmp914.coeffs[1] = constant_term(t_x) ^ float(constant_term(2)) - tmp914.coeffs[2:order + 1] .= zero(tmp914.coeffs[1]) - tmp916.coeffs[1] = constant_term(t_y) ^ float(constant_term(2)) - tmp916.coeffs[2:order + 1] .= zero(tmp916.coeffs[1]) - tmp917.coeffs[1] = constant_term(tmp914) + constant_term(tmp916) - tmp917.coeffs[2:order + 1] .= zero(tmp917.coeffs[1]) - tmp919.coeffs[1] = constant_term(t_z) ^ float(constant_term(2)) - tmp919.coeffs[2:order + 1] .= zero(tmp919.coeffs[1]) - tmp920.coeffs[1] = constant_term(tmp917) + constant_term(tmp919) - tmp920.coeffs[2:order + 1] .= zero(tmp920.coeffs[1]) - t_norm.coeffs[1] = sqrt(constant_term(tmp920)) - t_norm.coeffs[2:order + 1] .= zero(t_norm.coeffs[1]) - t_x_unit.coeffs[1] = constant_term(t_x) / constant_term(t_norm) - t_x_unit.coeffs[2:order + 1] .= zero(t_x_unit.coeffs[1]) - t_y_unit.coeffs[1] = constant_term(t_y) / constant_term(t_norm) - t_y_unit.coeffs[2:order + 1] .= zero(t_y_unit.coeffs[1]) - t_z_unit.coeffs[1] = constant_term(t_z) / constant_term(t_norm) - t_z_unit.coeffs[2:order + 1] .= zero(t_z_unit.coeffs[1]) - tmp925.coeffs[1] = constant_term(X[1]) / constant_term(r_p1d2[1]) - tmp925.coeffs[2:order + 1] .= zero(tmp925.coeffs[1]) - r_x_unit.coeffs[1] = -(constant_term(tmp925)) - r_x_unit.coeffs[2:order + 1] .= zero(r_x_unit.coeffs[1]) - tmp927.coeffs[1] = constant_term(Y[1]) / constant_term(r_p1d2[1]) - tmp927.coeffs[2:order + 1] .= zero(tmp927.coeffs[1]) - r_y_unit.coeffs[1] = -(constant_term(tmp927)) - r_y_unit.coeffs[2:order + 1] .= zero(r_y_unit.coeffs[1]) - tmp929.coeffs[1] = constant_term(Z[1]) / constant_term(r_p1d2[1]) - tmp929.coeffs[2:order + 1] .= zero(tmp929.coeffs[1]) - r_z_unit.coeffs[1] = -(constant_term(tmp929)) - r_z_unit.coeffs[2:order + 1] .= zero(r_z_unit.coeffs[1]) - g_r.coeffs[1] = identity(constant_term(r_p2[1])) - g_r.coeffs[2:order + 1] .= zero(g_r.coeffs[1]) - A2_t_g_r.coeffs[1] = constant_term(q[7]) / constant_term(g_r) - A2_t_g_r.coeffs[2:order + 1] .= zero(A2_t_g_r.coeffs[1]) - A1_t_g_r.coeffs[1] = constant_term(q[8]) / constant_term(g_r) - A1_t_g_r.coeffs[2:order + 1] .= zero(A1_t_g_r.coeffs[1]) - tmp933.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_x_unit) - tmp933.coeffs[2:order + 1] .= zero(tmp933.coeffs[1]) - tmp934.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_x_unit) - tmp934.coeffs[2:order + 1] .= zero(tmp934.coeffs[1]) - NGAx.coeffs[1] = constant_term(tmp933) + constant_term(tmp934) - NGAx.coeffs[2:order + 1] .= zero(NGAx.coeffs[1]) - tmp936.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_y_unit) - tmp936.coeffs[2:order + 1] .= zero(tmp936.coeffs[1]) - tmp937.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_y_unit) - tmp937.coeffs[2:order + 1] .= zero(tmp937.coeffs[1]) - NGAy.coeffs[1] = constant_term(tmp936) + constant_term(tmp937) - NGAy.coeffs[2:order + 1] .= zero(NGAy.coeffs[1]) - tmp939.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_z_unit) - tmp939.coeffs[2:order + 1] .= zero(tmp939.coeffs[1]) - tmp940.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_z_unit) - tmp940.coeffs[2:order + 1] .= zero(tmp940.coeffs[1]) - NGAz.coeffs[1] = constant_term(tmp939) + constant_term(tmp940) - NGAz.coeffs[2:order + 1] .= zero(NGAz.coeffs[1]) - tmp942.coeffs[1] = constant_term(postNewtonX) + constant_term(accX) - tmp942.coeffs[2:order + 1] .= zero(tmp942.coeffs[1]) - (dq[4]).coeffs[1] = constant_term(tmp942) + constant_term(NGAx) - (dq[4]).coeffs[2:order + 1] .= zero((dq[4]).coeffs[1]) - tmp944.coeffs[1] = constant_term(postNewtonY) + constant_term(accY) - tmp944.coeffs[2:order + 1] .= zero(tmp944.coeffs[1]) - (dq[5]).coeffs[1] = constant_term(tmp944) + constant_term(NGAy) - (dq[5]).coeffs[2:order + 1] .= zero((dq[5]).coeffs[1]) - tmp946.coeffs[1] = constant_term(postNewtonZ) + constant_term(accZ) - tmp946.coeffs[2:order + 1] .= zero(tmp946.coeffs[1]) - (dq[6]).coeffs[1] = constant_term(tmp946) + constant_term(NGAz) - (dq[6]).coeffs[2:order + 1] .= zero((dq[6]).coeffs[1]) - (dq[7]).coeffs[1] = identity(constant_term(zero_q_1)) - (dq[7]).coeffs[2:order + 1] .= zero((dq[7]).coeffs[1]) - for __idx = eachindex(q) - (q[__idx]).coeffs[2] = (dq[__idx]).coeffs[1] - end - for ord = 1:order - 1 - ordnext = ord + 1 - TaylorSeries.identity!(pntempX, zero_q_1, ord) - TaylorSeries.identity!(pntempY, zero_q_1, ord) - TaylorSeries.identity!(pntempZ, zero_q_1, ord) - TaylorSeries.identity!(accX, zero_q_1, ord) - TaylorSeries.identity!(accY, zero_q_1, ord) - TaylorSeries.identity!(accZ, zero_q_1, ord) - TaylorSeries.identity!(dq[1], q[4], ord) - TaylorSeries.identity!(dq[2], q[5], ord) - TaylorSeries.identity!(dq[3], q[6], ord) - TaylorSeries.identity!(newtonianNb_Potential[N], zero_q_1, ord) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 - TaylorSeries.identity!(ui[i], ss16asteph_t[3 * ((N - 1) + i) - 2], ord) - TaylorSeries.identity!(vi[i], ss16asteph_t[3 * ((N - 1) + i) - 1], ord) - TaylorSeries.identity!(wi[i], ss16asteph_t[3 * ((N - 1) + i)], ord) - TaylorSeries.subst!(X[i], ss16asteph_t[3i - 2], q[1], ord) - TaylorSeries.subst!(Y[i], ss16asteph_t[3i - 1], q[2], ord) - TaylorSeries.subst!(Z[i], ss16asteph_t[3i], q[3], ord) - TaylorSeries.subst!(U[i], ui[i], dq[1], ord) - TaylorSeries.subst!(V[i], vi[i], dq[2], ord) - TaylorSeries.subst!(W[i], wi[i], dq[3], ord) - TaylorSeries.mul!(tmp687[1], 4, dq[1], ord) - TaylorSeries.mul!(tmp689[i], 3, ui[i], ord) - TaylorSeries.subst!(_4U_m_3X[i], tmp687[1], tmp689[i], ord) - TaylorSeries.mul!(tmp692[2], 4, dq[2], ord) - TaylorSeries.mul!(tmp694[i], 3, vi[i], ord) - TaylorSeries.subst!(_4V_m_3Y[i], tmp692[2], tmp694[i], ord) - TaylorSeries.mul!(tmp697[3], 4, dq[3], ord) - TaylorSeries.mul!(tmp699[i], 3, wi[i], ord) - TaylorSeries.subst!(_4W_m_3Z[i], tmp697[3], tmp699[i], ord) - TaylorSeries.mul!(pn2x[i], X[i], _4U_m_3X[i], ord) - TaylorSeries.mul!(pn2y[i], Y[i], _4V_m_3Y[i], ord) - TaylorSeries.mul!(pn2z[i], Z[i], _4W_m_3Z[i], ord) - TaylorSeries.mul!(UU[i], ui[i], dq[1], ord) - TaylorSeries.mul!(VV[i], vi[i], dq[2], ord) - TaylorSeries.mul!(WW[i], wi[i], dq[3], ord) - TaylorSeries.add!(tmp707[i], UU[i], VV[i], ord) - TaylorSeries.add!(vi_dot_vj[i], tmp707[i], WW[i], ord) - TaylorSeries.pow!(tmp710[i], X[i], 2, ord) - TaylorSeries.pow!(tmp712[i], Y[i], 2, ord) - TaylorSeries.add!(tmp713[i], tmp710[i], tmp712[i], ord) - TaylorSeries.pow!(tmp715[i], Z[i], 2, ord) - TaylorSeries.add!(r_p2[i], tmp713[i], tmp715[i], ord) - TaylorSeries.sqrt!(r_p1d2[i], r_p2[i], ord) - TaylorSeries.pow!(r_p3d2[i], r_p2[i], 1.5, ord) - TaylorSeries.pow!(r_p7d2[i], r_p2[i], 3.5, ord) - TaylorSeries.div!(newtonianCoeff[i], μ[i], r_p3d2[i], ord) - TaylorSeries.add!(tmp723[i], pn2x[i], pn2y[i], ord) - TaylorSeries.add!(tmp724[i], tmp723[i], pn2z[i], ord) - TaylorSeries.mul!(pn2[i], newtonianCoeff[i], tmp724[i], ord) - TaylorSeries.mul!(newton_acc_X[i], X[i], newtonianCoeff[i], ord) - TaylorSeries.mul!(newton_acc_Y[i], Y[i], newtonianCoeff[i], ord) - TaylorSeries.mul!(newton_acc_Z[i], Z[i], newtonianCoeff[i], ord) - TaylorSeries.div!(newtonian1b_Potential[i], μ[i], r_p1d2[i], ord) - TaylorSeries.mul!(pn3[i], 3.5, newtonian1b_Potential[i], ord) - TaylorSeries.mul!(U_t_pn2[i], pn2[i], U[i], ord) - TaylorSeries.mul!(V_t_pn2[i], pn2[i], V[i], ord) - TaylorSeries.mul!(W_t_pn2[i], pn2[i], W[i], ord) - if UJ_interaction[i] - TaylorSeries.subst!(tmp735[i], X[i], ord) - TaylorSeries.mul!(t31[i], tmp735[i], M_[1, 3, i], ord) - TaylorSeries.subst!(tmp737[i], Y[i], ord) - TaylorSeries.mul!(t32[i], tmp737[i], M_[2, 3, i], ord) - TaylorSeries.subst!(tmp739[i], Z[i], ord) - TaylorSeries.mul!(t33[i], tmp739[i], M_[3, 3, i], ord) - TaylorSeries.add!(tmp741[i], t31[i], t32[i], ord) - TaylorSeries.add!(r_sin_ϕ[i], tmp741[i], t33[i], ord) - TaylorSeries.div!(sin_ϕ[i], r_sin_ϕ[i], r_p1d2[i], ord) - TaylorSeries.asin!(ϕ[i], sin_ϕ[i], tmp948[i], ord) - TaylorSeries.sincos!(tmp949[i], cos_ϕ[i], ϕ[i], ord) - TaylorSeries.pow!(sin2_ϕ[i], sin_ϕ[i], 2, ord) - TaylorSeries.pow!(sin3_ϕ[i], sin_ϕ[i], 3, ord) - TaylorSeries.mul!(tmp751[i], 1.5, sin2_ϕ[i], ord) - TaylorSeries.subst!(P_2_sin_ϕ[i], tmp751[i], 0.5, ord) - TaylorSeries.mul!(∂P_2_sin_ϕ[i], 3, sin_ϕ[i], ord) - TaylorSeries.mul!(tmp757[i], -1.5, sin_ϕ[i], ord) - TaylorSeries.mul!(tmp759[i], 2.5, sin3_ϕ[i], ord) - TaylorSeries.add!(P_3_sin_ϕ[i], tmp757[i], tmp759[i], ord) - TaylorSeries.mul!(tmp763[i], 7.5, sin2_ϕ[i], ord) - TaylorSeries.add!(∂P_3_sin_ϕ[i], -1.5, tmp763[i], ord) - TaylorSeries.pow!(tmp766[i], r_p2[i], 2, ord) - TaylorSeries.div!(tmp767[i], Λ2[i], tmp766[i], ord) - TaylorSeries.subst!(Λ2j_div_r4[i], tmp767[i], ord) - TaylorSeries.pow!(tmp770[i], r_p1d2[i], 5, ord) - TaylorSeries.div!(tmp771[i], Λ3[i], tmp770[i], ord) - TaylorSeries.subst!(Λ3j_div_r5[i], tmp771[i], ord) - TaylorSeries.subst!(tmp773[i], cos_ϕ[i], ord) - TaylorSeries.mul!(m_c_ϕ_∂P_2[i], tmp773[i], ∂P_2_sin_ϕ[i], ord) - TaylorSeries.subst!(tmp775[i], cos_ϕ[i], ord) - TaylorSeries.mul!(m_c_ϕ_∂P_3[i], tmp775[i], ∂P_3_sin_ϕ[i], ord) - TaylorSeries.mul!(tmp778[i], Λ2j_div_r4[i], 3, ord) - TaylorSeries.mul!(F_J2_ξ[i], tmp778[i], P_2_sin_ϕ[i], ord) - TaylorSeries.mul!(F_J2_ζ[i], Λ2j_div_r4[i], m_c_ϕ_∂P_2[i], ord) - TaylorSeries.mul!(tmp782[i], Λ3j_div_r5[i], 4, ord) - TaylorSeries.mul!(F_J3_ξ[i], tmp782[i], P_3_sin_ϕ[i], ord) - TaylorSeries.mul!(F_J3_ζ[i], Λ3j_div_r5[i], m_c_ϕ_∂P_3[i], ord) - TaylorSeries.identity!(F_J_ξ[i], F_J2_ξ[i], ord) - TaylorSeries.identity!(F_J_ζ[i], F_J2_ζ[i], ord) - TaylorSeries.subst!(tmp785[i], X[i], ord) - TaylorSeries.div!(ξx[i], tmp785[i], r_p1d2[i], ord) - TaylorSeries.subst!(tmp787[i], Y[i], ord) - TaylorSeries.div!(ξy[i], tmp787[i], r_p1d2[i], ord) - TaylorSeries.subst!(tmp789[i], Z[i], ord) - TaylorSeries.div!(ξz[i], tmp789[i], r_p1d2[i], ord) - TaylorSeries.mul!(ηx1[i], M_[2, 3, i], ξz[i], ord) - TaylorSeries.mul!(ηy1[i], M_[3, 3, i], ξx[i], ord) - TaylorSeries.mul!(ηz1[i], M_[1, 3, i], ξy[i], ord) - TaylorSeries.mul!(ηx2[i], M_[3, 3, i], ξy[i], ord) - TaylorSeries.mul!(ηy2[i], M_[1, 3, i], ξz[i], ord) - TaylorSeries.mul!(ηz2[i], M_[2, 3, i], ξx[i], ord) - TaylorSeries.subst!(ηx[i], ηx1[i], ηx2[i], ord) - TaylorSeries.subst!(ηy[i], ηy1[i], ηy2[i], ord) - TaylorSeries.subst!(ηz[i], ηz1[i], ηz2[i], ord) - TaylorSeries.mul!(ζx1[i], ξy[i], ηz[i], ord) - TaylorSeries.mul!(ζy1[i], ξz[i], ηx[i], ord) - TaylorSeries.mul!(ζz1[i], ξx[i], ηy[i], ord) - TaylorSeries.mul!(ζx2[i], ξz[i], ηy[i], ord) - TaylorSeries.mul!(ζy2[i], ξx[i], ηz[i], ord) - TaylorSeries.mul!(ζz2[i], ξy[i], ηx[i], ord) - TaylorSeries.subst!(ζx[i], ζx1[i], ζx2[i], ord) - TaylorSeries.subst!(ζy[i], ζy1[i], ζy2[i], ord) - TaylorSeries.subst!(ζz[i], ζz1[i], ζz2[i], ord) - TaylorSeries.mul!(F_J2_x1[i], F_J_ξ[i], ξx[i], ord) - TaylorSeries.mul!(F_J2_y1[i], F_J_ξ[i], ξy[i], ord) - TaylorSeries.mul!(F_J2_z1[i], F_J_ξ[i], ξz[i], ord) - TaylorSeries.mul!(F_J2_x2[i], F_J_ζ[i], ζx[i], ord) - TaylorSeries.mul!(F_J2_y2[i], F_J_ζ[i], ζy[i], ord) - TaylorSeries.mul!(F_J2_z2[i], F_J_ζ[i], ζz[i], ord) - TaylorSeries.add!(F_J2_x[i], F_J2_x1[i], F_J2_x2[i], ord) - TaylorSeries.add!(F_J2_y[i], F_J2_y1[i], F_J2_y2[i], ord) - TaylorSeries.add!(F_J2_z[i], F_J2_z1[i], F_J2_z2[i], ord) - end - TaylorSeries.pow!(tmp819[i], ui[i], 2, ord) - TaylorSeries.pow!(tmp821[i], vi[i], 2, ord) - TaylorSeries.add!(tmp822[i], tmp819[i], tmp821[i], ord) - TaylorSeries.pow!(tmp824[i], wi[i], 2, ord) - TaylorSeries.add!(v2[i], tmp822[i], tmp824[i], ord) - end - TaylorSeries.pow!(tmp827, q[4], 2, ord) - TaylorSeries.pow!(tmp829, q[5], 2, ord) - TaylorSeries.add!(tmp830, tmp827, tmp829, ord) - TaylorSeries.pow!(tmp832, q[6], 2, ord) - TaylorSeries.add!(v2[N], tmp830, tmp832, ord) - for i = 1:Nm1 - TaylorSeries.add!(temp_004[i], newtonian1b_Potential[i], newtonianNb_Potential[N], ord) - TaylorSeries.identity!(newtonianNb_Potential[N], temp_004[i], ord) - if UJ_interaction[i] - TaylorSeries.mul!(tmp835[i], μ[i], F_J2_x[i], ord) - TaylorSeries.subst!(temp_accX_i[i], accX, tmp835[i], ord) - TaylorSeries.identity!(accX, temp_accX_i[i], ord) - TaylorSeries.mul!(tmp837[i], μ[i], F_J2_y[i], ord) - TaylorSeries.subst!(temp_accY_i[i], accY, tmp837[i], ord) - TaylorSeries.identity!(accY, temp_accY_i[i], ord) - TaylorSeries.mul!(tmp839[i], μ[i], F_J2_z[i], ord) - TaylorSeries.subst!(temp_accZ_i[i], accZ, tmp839[i], ord) - TaylorSeries.identity!(accZ, temp_accZ_i[i], ord) - end - end - TaylorSeries.mul!(_4ϕj[N], 4, newtonianNb_Potential[N], ord) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 - TaylorSeries.add!(ϕi_plus_4ϕj[i], newtonianNb_Potential_t[i], _4ϕj[N], ord) - TaylorSeries.mul!(tmp845[i], 2, v2[i], ord) - TaylorSeries.mul!(tmp847[i], 4, vi_dot_vj[i], ord) - TaylorSeries.subst!(tmp848[i], tmp845[i], tmp847[i], ord) - TaylorSeries.add!(sj2_plus_2si2_minus_4vivj[i], tmp848[i], v2[N], ord) - TaylorSeries.subst!(ϕs_and_vs[i], sj2_plus_2si2_minus_4vivj[i], ϕi_plus_4ϕj[i], ord) - TaylorSeries.mul!(Xij_t_Ui[i], X[i], ui[i], ord) - TaylorSeries.mul!(Yij_t_Vi[i], Y[i], vi[i], ord) - TaylorSeries.mul!(Zij_t_Wi[i], Z[i], wi[i], ord) - TaylorSeries.add!(tmp854[i], Xij_t_Ui[i], Yij_t_Vi[i], ord) - TaylorSeries.add!(Rij_dot_Vi[i], tmp854[i], Zij_t_Wi[i], ord) - TaylorSeries.pow!(tmp857[i], Rij_dot_Vi[i], 2, ord) - TaylorSeries.div!(pn1t7[i], tmp857[i], r_p2[i], ord) - TaylorSeries.mul!(tmp860[i], 1.5, pn1t7[i], ord) - TaylorSeries.subst!(pn1t2_7[i], ϕs_and_vs[i], tmp860[i], ord) - TaylorSeries.add!(pn1t1_7[i], c_p2, pn1t2_7[i], ord) - TaylorSeries.mul!(pNX_t_X[i], acceph_t[3i - 2], X[i], ord) - TaylorSeries.mul!(pNY_t_Y[i], acceph_t[3i - 1], Y[i], ord) - TaylorSeries.mul!(pNZ_t_Z[i], acceph_t[3i], Z[i], ord) - TaylorSeries.add!(tmp867[i], pNX_t_X[i], pNY_t_Y[i], ord) - TaylorSeries.add!(tmp868[i], tmp867[i], pNZ_t_Z[i], ord) - TaylorSeries.mul!(tmp869[i], 0.5, tmp868[i], ord) - TaylorSeries.add!(pn1[i], pn1t1_7[i], tmp869[i], ord) - TaylorSeries.mul!(X_t_pn1[i], newton_acc_X[i], pn1[i], ord) - TaylorSeries.mul!(Y_t_pn1[i], newton_acc_Y[i], pn1[i], ord) - TaylorSeries.mul!(Z_t_pn1[i], newton_acc_Z[i], pn1[i], ord) - TaylorSeries.mul!(pNX_t_pn3[i], acceph_t[3i - 2], pn3[i], ord) - TaylorSeries.mul!(pNY_t_pn3[i], acceph_t[3i - 1], pn3[i], ord) - TaylorSeries.mul!(pNZ_t_pn3[i], acceph_t[3i], pn3[i], ord) - end - for i = 1:10 - TaylorSeries.add!(tmp877[i], U_t_pn2[i], pNX_t_pn3[i], ord) - TaylorSeries.add!(termpnx[i], X_t_pn1[i], tmp877[i], ord) - TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) - TaylorSeries.identity!(pntempX, sumpnx[i], ord) - TaylorSeries.add!(tmp880[i], V_t_pn2[i], pNY_t_pn3[i], ord) - TaylorSeries.add!(termpny[i], Y_t_pn1[i], tmp880[i], ord) - TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) - TaylorSeries.identity!(pntempY, sumpny[i], ord) - TaylorSeries.add!(tmp883[i], W_t_pn2[i], pNZ_t_pn3[i], ord) - TaylorSeries.add!(termpnz[i], Z_t_pn1[i], tmp883[i], ord) - TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) - TaylorSeries.identity!(pntempZ, sumpnz[i], ord) - end - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 - TaylorSeries.mul!(X_t_pn1[i], c_p2, newton_acc_X[i], ord) - TaylorSeries.mul!(Y_t_pn1[i], c_p2, newton_acc_Y[i], ord) - TaylorSeries.mul!(Z_t_pn1[i], c_p2, newton_acc_Z[i], ord) - end - for i = 11:Nm1 - TaylorSeries.identity!(termpnx[i], X_t_pn1[i], ord) - TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) - TaylorSeries.identity!(pntempX, sumpnx[i], ord) - TaylorSeries.identity!(termpny[i], Y_t_pn1[i], ord) - TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) - TaylorSeries.identity!(pntempY, sumpny[i], ord) - TaylorSeries.identity!(termpnz[i], Z_t_pn1[i], ord) - TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) - TaylorSeries.identity!(pntempZ, sumpnz[i], ord) - end - TaylorSeries.mul!(postNewtonX, pntempX, c_m2, ord) - TaylorSeries.mul!(postNewtonY, pntempY, c_m2, ord) - TaylorSeries.mul!(postNewtonZ, pntempZ, c_m2, ord) - TaylorSeries.mul!(tmp895, Y[1], W[1], ord) - TaylorSeries.mul!(tmp896, Z[1], V[1], ord) - TaylorSeries.subst!(hx, tmp895, tmp896, ord) - TaylorSeries.mul!(tmp898, Z[1], U[1], ord) - TaylorSeries.mul!(tmp899, X[1], W[1], ord) - TaylorSeries.subst!(hy, tmp898, tmp899, ord) - TaylorSeries.mul!(tmp901, X[1], V[1], ord) - TaylorSeries.mul!(tmp902, Y[1], U[1], ord) - TaylorSeries.subst!(hz, tmp901, tmp902, ord) - TaylorSeries.mul!(tmp904, hz, Y[1], ord) - TaylorSeries.mul!(tmp905, hy, Z[1], ord) - TaylorSeries.subst!(t_x, tmp904, tmp905, ord) - TaylorSeries.mul!(tmp907, hx, Z[1], ord) - TaylorSeries.mul!(tmp908, hz, X[1], ord) - TaylorSeries.subst!(t_y, tmp907, tmp908, ord) - TaylorSeries.mul!(tmp910, hy, X[1], ord) - TaylorSeries.mul!(tmp911, hx, Y[1], ord) - TaylorSeries.subst!(t_z, tmp910, tmp911, ord) - TaylorSeries.pow!(tmp914, t_x, 2, ord) - TaylorSeries.pow!(tmp916, t_y, 2, ord) - TaylorSeries.add!(tmp917, tmp914, tmp916, ord) - TaylorSeries.pow!(tmp919, t_z, 2, ord) - TaylorSeries.add!(tmp920, tmp917, tmp919, ord) - TaylorSeries.sqrt!(t_norm, tmp920, ord) - TaylorSeries.div!(t_x_unit, t_x, t_norm, ord) - TaylorSeries.div!(t_y_unit, t_y, t_norm, ord) - TaylorSeries.div!(t_z_unit, t_z, t_norm, ord) - TaylorSeries.div!(tmp925, X[1], r_p1d2[1], ord) - TaylorSeries.subst!(r_x_unit, tmp925, ord) - TaylorSeries.div!(tmp927, Y[1], r_p1d2[1], ord) - TaylorSeries.subst!(r_y_unit, tmp927, ord) - TaylorSeries.div!(tmp929, Z[1], r_p1d2[1], ord) - TaylorSeries.subst!(r_z_unit, tmp929, ord) - TaylorSeries.identity!(g_r, r_p2[1], ord) - TaylorSeries.div!(A2_t_g_r, q[7], g_r, ord) - TaylorSeries.div!(A1_t_g_r, q[8], g_r, ord) - TaylorSeries.mul!(tmp933, A2_t_g_r, t_x_unit, ord) - TaylorSeries.mul!(tmp934, A1_t_g_r, r_x_unit, ord) - TaylorSeries.add!(NGAx, tmp933, tmp934, ord) - TaylorSeries.mul!(tmp936, A2_t_g_r, t_y_unit, ord) - TaylorSeries.mul!(tmp937, A1_t_g_r, r_y_unit, ord) - TaylorSeries.add!(NGAy, tmp936, tmp937, ord) - TaylorSeries.mul!(tmp939, A2_t_g_r, t_z_unit, ord) - TaylorSeries.mul!(tmp940, A1_t_g_r, r_z_unit, ord) - TaylorSeries.add!(NGAz, tmp939, tmp940, ord) - TaylorSeries.add!(tmp942, postNewtonX, accX, ord) - TaylorSeries.add!(dq[4], tmp942, NGAx, ord) - TaylorSeries.add!(tmp944, postNewtonY, accY, ord) - TaylorSeries.add!(dq[5], tmp944, NGAy, ord) - TaylorSeries.add!(tmp946, postNewtonZ, accZ, ord) - TaylorSeries.add!(dq[6], tmp946, NGAz, ord) - TaylorSeries.identity!(dq[7], zero_q_1, ord) - for __idx = eachindex(q) - (q[__idx]).coeffs[ordnext + 1] = (dq[__idx]).coeffs[ordnext] / ordnext - end - end - return nothing -end - -# TaylorIntegration._allocate_jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_eph_threads! -function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params) where {_T <: Real, _S <: Number, _N} - order = t.order - local jd0 = params[4] - local dsj2k = t + (jd0 - JD_J2000) - local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) - local acceph_t = evaleph(params[2], dsj2k, q[1]) - local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) - local S = eltype(q) - local UJ_interaction = params[5] - local N = params[6] - local Nm1 = N - 1 - local μ = params[7] - local zero_q_1 = auxzero(q[1]) - X = Array{S}(undef, N) - Y = Array{S}(undef, N) - Z = Array{S}(undef, N) - r_p2 = Array{S}(undef, N) - r_p1d2 = Array{S}(undef, N) - r_p3d2 = Array{S}(undef, N) - r_p7d2 = Array{S}(undef, N) - newtonianCoeff = Array{S}(undef, N) - ui = Array{S}(undef, N - 1) - vi = Array{S}(undef, N - 1) - wi = Array{S}(undef, N - 1) - U = Array{S}(undef, N) - V = Array{S}(undef, N) - W = Array{S}(undef, N) - _4U_m_3X = Array{S}(undef, N) - _4V_m_3Y = Array{S}(undef, N) - _4W_m_3Z = Array{S}(undef, N) - UU = Array{S}(undef, N) - VV = Array{S}(undef, N) - WW = Array{S}(undef, N) - newtonian1b_Potential = Array{S}(undef, N) - newtonianNb_Potential = Array{S}(undef, N) - newton_acc_X = Array{S}(undef, N) - newton_acc_Y = Array{S}(undef, N) - newton_acc_Z = Array{S}(undef, N) - v2 = Array{S}(undef, N) - vi_dot_vj = Array{S}(undef, N) - pn2 = Array{S}(undef, N) - U_t_pn2 = Array{S}(undef, N) - V_t_pn2 = Array{S}(undef, N) - W_t_pn2 = Array{S}(undef, N) - pn3 = Array{S}(undef, N) - pNX_t_pn3 = Array{S}(undef, N) - pNY_t_pn3 = Array{S}(undef, N) - pNZ_t_pn3 = Array{S}(undef, N) - _4ϕj = Array{S}(undef, N) - ϕi_plus_4ϕj = Array{S}(undef, N) - sj2_plus_2si2_minus_4vivj = Array{S}(undef, N) - ϕs_and_vs = Array{S}(undef, N) - pn1t1_7 = Array{S}(undef, N) - pNX_t_X = Array{S}(undef, N) - pNY_t_Y = Array{S}(undef, N) - pNZ_t_Z = Array{S}(undef, N) - pn1 = Array{S}(undef, N) - X_t_pn1 = Array{S}(undef, N) - Y_t_pn1 = Array{S}(undef, N) - Z_t_pn1 = Array{S}(undef, N) - pntempX = Taylor1(identity(constant_term(zero_q_1)), order) - pntempY = Taylor1(identity(constant_term(zero_q_1)), order) - pntempZ = Taylor1(identity(constant_term(zero_q_1)), order) - t31 = Array{S}(undef, N) - t32 = Array{S}(undef, N) - t33 = Array{S}(undef, N) - r_sin_ϕ = Array{S}(undef, N) - sin_ϕ = Array{S}(undef, N) - ϕ = Array{S}(undef, N) - cos_ϕ = Array{S}(undef, N) - sin2_ϕ = Array{S}(undef, N) - sin3_ϕ = Array{S}(undef, N) - sin4_ϕ = Array{S}(undef, N) - F_J2_x = Array{S}(undef, N) - F_J2_y = Array{S}(undef, N) - F_J2_z = Array{S}(undef, N) - F_J2_x1 = Array{S}(undef, N) - F_J2_y1 = Array{S}(undef, N) - F_J2_z1 = Array{S}(undef, N) - F_J2_x2 = Array{S}(undef, N) - F_J2_y2 = Array{S}(undef, N) - F_J2_z2 = Array{S}(undef, N) - temp_accX_i = Array{S}(undef, N) - temp_accY_i = Array{S}(undef, N) - temp_accZ_i = Array{S}(undef, N) - P_2_sin_ϕ = Array{S}(undef, N) - ∂P_2_sin_ϕ = Array{S}(undef, N) - P_3_sin_ϕ = Array{S}(undef, N) - ∂P_3_sin_ϕ = Array{S}(undef, N) - m_c_ϕ_∂P_2 = Array{S}(undef, N) - m_c_ϕ_∂P_3 = Array{S}(undef, N) - Λ2j_div_r4 = Array{S}(undef, N) - Λ3j_div_r5 = Array{S}(undef, N) - F_J_ξ = Array{S}(undef, N) - F_J_η = Array{S}(undef, N) - F_J_ζ = Array{S}(undef, N) - F_J2_ξ = Array{S}(undef, N) - F_J2_η = Array{S}(undef, N) - F_J2_ζ = Array{S}(undef, N) - F_J3_ξ = Array{S}(undef, N) - F_J3_η = Array{S}(undef, N) - F_J3_ζ = Array{S}(undef, N) - ξx = Array{S}(undef, N) - ξy = Array{S}(undef, N) - ξz = Array{S}(undef, N) - ηx = Array{S}(undef, N) - ηy = Array{S}(undef, N) - ηz = Array{S}(undef, N) - ηx1 = Array{S}(undef, N) - ηy1 = Array{S}(undef, N) - ηz1 = Array{S}(undef, N) - ηx2 = Array{S}(undef, N) - ηy2 = Array{S}(undef, N) - ηz2 = Array{S}(undef, N) - ζx = Array{S}(undef, N) - ζy = Array{S}(undef, N) - ζz = Array{S}(undef, N) - ζx1 = Array{S}(undef, N) - ζy1 = Array{S}(undef, N) - ζz1 = Array{S}(undef, N) - ζx2 = Array{S}(undef, N) - ζy2 = Array{S}(undef, N) - ζz2 = Array{S}(undef, N) - accX = Taylor1(identity(constant_term(zero_q_1)), order) - accY = Taylor1(identity(constant_term(zero_q_1)), order) - accZ = Taylor1(identity(constant_term(zero_q_1)), order) - local M_ = Array{S}(undef, 3, 3, N) - local M_ .= zero_q_1 - local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 - dq[1] = Taylor1(identity(constant_term(q[4])), order) - dq[2] = Taylor1(identity(constant_term(q[5])), order) - dq[3] = Taylor1(identity(constant_term(q[6])), order) - newtonianNb_Potential[N] = Taylor1(identity(constant_term(zero_q_1)), order) - tmp1317 = Array{Taylor1{_S}}(undef, size(dq)) - tmp1317 .= Taylor1(zero(constant_term(q[1])), order) - tmp1319 = Array{Taylor1{_S}}(undef, size(ui)) - tmp1319 .= Taylor1(zero(constant_term(q[1])), order) - tmp1322 = Array{Taylor1{_S}}(undef, size(dq)) - tmp1322 .= Taylor1(zero(constant_term(q[1])), order) - tmp1324 = Array{Taylor1{_S}}(undef, size(vi)) - tmp1324 .= Taylor1(zero(constant_term(q[1])), order) - tmp1327 = Array{Taylor1{_S}}(undef, size(dq)) - tmp1327 .= Taylor1(zero(constant_term(q[1])), order) - tmp1329 = Array{Taylor1{_S}}(undef, size(wi)) - tmp1329 .= Taylor1(zero(constant_term(q[1])), order) - pn2x = Array{Taylor1{_S}}(undef, size(X)) - pn2x .= Taylor1(zero(constant_term(q[1])), order) - pn2y = Array{Taylor1{_S}}(undef, size(Y)) - pn2y .= Taylor1(zero(constant_term(q[1])), order) - pn2z = Array{Taylor1{_S}}(undef, size(Z)) - pn2z .= Taylor1(zero(constant_term(q[1])), order) - tmp1337 = Array{Taylor1{_S}}(undef, size(UU)) - tmp1337 .= Taylor1(zero(constant_term(q[1])), order) - tmp1340 = Array{Taylor1{_S}}(undef, size(X)) - tmp1340 .= Taylor1(zero(constant_term(q[1])), order) - tmp1342 = Array{Taylor1{_S}}(undef, size(Y)) - tmp1342 .= Taylor1(zero(constant_term(q[1])), order) - tmp1343 = Array{Taylor1{_S}}(undef, size(tmp1340)) - tmp1343 .= Taylor1(zero(constant_term(q[1])), order) - tmp1345 = Array{Taylor1{_S}}(undef, size(Z)) - tmp1345 .= Taylor1(zero(constant_term(q[1])), order) - tmp1353 = Array{Taylor1{_S}}(undef, size(pn2x)) - tmp1353 .= Taylor1(zero(constant_term(q[1])), order) - tmp1354 = Array{Taylor1{_S}}(undef, size(tmp1353)) - tmp1354 .= Taylor1(zero(constant_term(q[1])), order) - tmp1449 = Array{Taylor1{_S}}(undef, size(ui)) - tmp1449 .= Taylor1(zero(constant_term(q[1])), order) - tmp1451 = Array{Taylor1{_S}}(undef, size(vi)) - tmp1451 .= Taylor1(zero(constant_term(q[1])), order) - tmp1452 = Array{Taylor1{_S}}(undef, size(tmp1449)) - tmp1452 .= Taylor1(zero(constant_term(q[1])), order) - tmp1454 = Array{Taylor1{_S}}(undef, size(wi)) - tmp1454 .= Taylor1(zero(constant_term(q[1])), order) - tmp1365 = Array{Taylor1{_S}}(undef, size(X)) - tmp1365 .= Taylor1(zero(constant_term(q[1])), order) - tmp1367 = Array{Taylor1{_S}}(undef, size(Y)) - tmp1367 .= Taylor1(zero(constant_term(q[1])), order) - tmp1369 = Array{Taylor1{_S}}(undef, size(Z)) - tmp1369 .= Taylor1(zero(constant_term(q[1])), order) - tmp1371 = Array{Taylor1{_S}}(undef, size(t31)) - tmp1371 .= Taylor1(zero(constant_term(q[1])), order) - tmp1528 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp1528 .= Taylor1(zero(constant_term(q[1])), order) - tmp1529 = Array{Taylor1{_S}}(undef, size(ϕ)) - tmp1529 .= Taylor1(zero(constant_term(q[1])), order) - tmp1381 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp1381 .= Taylor1(zero(constant_term(q[1])), order) - tmp1387 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp1387 .= Taylor1(zero(constant_term(q[1])), order) - tmp1389 = Array{Taylor1{_S}}(undef, size(sin3_ϕ)) - tmp1389 .= Taylor1(zero(constant_term(q[1])), order) - tmp1393 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp1393 .= Taylor1(zero(constant_term(q[1])), order) - tmp1396 = Array{Taylor1{_S}}(undef, size(r_p2)) - tmp1396 .= Taylor1(zero(constant_term(q[1])), order) - tmp1397 = Array{Taylor1{_S}}(undef, size(Λ2)) - tmp1397 .= Taylor1(zero(constant_term(q[1])), order) - tmp1400 = Array{Taylor1{_S}}(undef, size(r_p1d2)) - tmp1400 .= Taylor1(zero(constant_term(q[1])), order) - tmp1401 = Array{Taylor1{_S}}(undef, size(Λ3)) - tmp1401 .= Taylor1(zero(constant_term(q[1])), order) - tmp1403 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp1403 .= Taylor1(zero(constant_term(q[1])), order) - tmp1405 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp1405 .= Taylor1(zero(constant_term(q[1])), order) - tmp1408 = Array{Taylor1{_S}}(undef, size(Λ2j_div_r4)) - tmp1408 .= Taylor1(zero(constant_term(q[1])), order) - tmp1412 = Array{Taylor1{_S}}(undef, size(Λ3j_div_r5)) - tmp1412 .= Taylor1(zero(constant_term(q[1])), order) - tmp1415 = Array{Taylor1{_S}}(undef, size(X)) - tmp1415 .= Taylor1(zero(constant_term(q[1])), order) - tmp1417 = Array{Taylor1{_S}}(undef, size(Y)) - tmp1417 .= Taylor1(zero(constant_term(q[1])), order) - tmp1419 = Array{Taylor1{_S}}(undef, size(Z)) - tmp1419 .= Taylor1(zero(constant_term(q[1])), order) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 - ui[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])), order) - vi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])), order) - wi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])), order) - X[i] = Taylor1(constant_term(ss16asteph_t[3i - 2]) - constant_term(q[1]), order) - Y[i] = Taylor1(constant_term(ss16asteph_t[3i - 1]) - constant_term(q[2]), order) - Z[i] = Taylor1(constant_term(ss16asteph_t[3i]) - constant_term(q[3]), order) - U[i] = Taylor1(constant_term(ui[i]) - constant_term(dq[1]), order) - V[i] = Taylor1(constant_term(vi[i]) - constant_term(dq[2]), order) - W[i] = Taylor1(constant_term(wi[i]) - constant_term(dq[3]), order) - tmp1317[1] = Taylor1(constant_term(4) * constant_term(dq[1]), order) - tmp1319[i] = Taylor1(constant_term(3) * constant_term(ui[i]), order) - _4U_m_3X[i] = Taylor1(constant_term(tmp1317[1]) - constant_term(tmp1319[i]), order) - tmp1322[2] = Taylor1(constant_term(4) * constant_term(dq[2]), order) - tmp1324[i] = Taylor1(constant_term(3) * constant_term(vi[i]), order) - _4V_m_3Y[i] = Taylor1(constant_term(tmp1322[2]) - constant_term(tmp1324[i]), order) - tmp1327[3] = Taylor1(constant_term(4) * constant_term(dq[3]), order) - tmp1329[i] = Taylor1(constant_term(3) * constant_term(wi[i]), order) - _4W_m_3Z[i] = Taylor1(constant_term(tmp1327[3]) - constant_term(tmp1329[i]), order) - pn2x[i] = Taylor1(constant_term(X[i]) * constant_term(_4U_m_3X[i]), order) - pn2y[i] = Taylor1(constant_term(Y[i]) * constant_term(_4V_m_3Y[i]), order) - pn2z[i] = Taylor1(constant_term(Z[i]) * constant_term(_4W_m_3Z[i]), order) - UU[i] = Taylor1(constant_term(ui[i]) * constant_term(dq[1]), order) - VV[i] = Taylor1(constant_term(vi[i]) * constant_term(dq[2]), order) - WW[i] = Taylor1(constant_term(wi[i]) * constant_term(dq[3]), order) - tmp1337[i] = Taylor1(constant_term(UU[i]) + constant_term(VV[i]), order) - vi_dot_vj[i] = Taylor1(constant_term(tmp1337[i]) + constant_term(WW[i]), order) - tmp1340[i] = Taylor1(constant_term(X[i]) ^ float(constant_term(2)), order) - tmp1342[i] = Taylor1(constant_term(Y[i]) ^ float(constant_term(2)), order) - tmp1343[i] = Taylor1(constant_term(tmp1340[i]) + constant_term(tmp1342[i]), order) - tmp1345[i] = Taylor1(constant_term(Z[i]) ^ float(constant_term(2)), order) - r_p2[i] = Taylor1(constant_term(tmp1343[i]) + constant_term(tmp1345[i]), order) - r_p1d2[i] = Taylor1(sqrt(constant_term(r_p2[i])), order) - r_p3d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(1.5)), order) - r_p7d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(3.5)), order) - newtonianCoeff[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p3d2[i]), order) - tmp1353[i] = Taylor1(constant_term(pn2x[i]) + constant_term(pn2y[i]), order) - tmp1354[i] = Taylor1(constant_term(tmp1353[i]) + constant_term(pn2z[i]), order) - pn2[i] = Taylor1(constant_term(newtonianCoeff[i]) * constant_term(tmp1354[i]), order) - newton_acc_X[i] = Taylor1(constant_term(X[i]) * constant_term(newtonianCoeff[i]), order) - newton_acc_Y[i] = Taylor1(constant_term(Y[i]) * constant_term(newtonianCoeff[i]), order) - newton_acc_Z[i] = Taylor1(constant_term(Z[i]) * constant_term(newtonianCoeff[i]), order) - newtonian1b_Potential[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p1d2[i]), order) - pn3[i] = Taylor1(constant_term(3.5) * constant_term(newtonian1b_Potential[i]), order) - U_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(U[i]), order) - V_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(V[i]), order) - W_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(W[i]), order) - if UJ_interaction[i] - tmp1365[i] = Taylor1(-(constant_term(X[i])), order) - t31[i] = Taylor1(constant_term(tmp1365[i]) * constant_term(M_[1, 3, i]), order) - tmp1367[i] = Taylor1(-(constant_term(Y[i])), order) - t32[i] = Taylor1(constant_term(tmp1367[i]) * constant_term(M_[2, 3, i]), order) - tmp1369[i] = Taylor1(-(constant_term(Z[i])), order) - t33[i] = Taylor1(constant_term(tmp1369[i]) * constant_term(M_[3, 3, i]), order) - tmp1371[i] = Taylor1(constant_term(t31[i]) + constant_term(t32[i]), order) - r_sin_ϕ[i] = Taylor1(constant_term(tmp1371[i]) + constant_term(t33[i]), order) - sin_ϕ[i] = Taylor1(constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]), order) - ϕ[i] = Taylor1(asin(constant_term(sin_ϕ[i])), order) - tmp1528[i] = Taylor1(sqrt(1 - constant_term(sin_ϕ[i]) ^ 2), order) - cos_ϕ[i] = Taylor1(cos(constant_term(ϕ[i])), order) - tmp1529[i] = Taylor1(sin(constant_term(ϕ[i])), order) - sin2_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(2)), order) - sin3_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(3)), order) - tmp1381[i] = Taylor1(constant_term(1.5) * constant_term(sin2_ϕ[i]), order) - P_2_sin_ϕ[i] = Taylor1(constant_term(tmp1381[i]) - constant_term(0.5), order) - ∂P_2_sin_ϕ[i] = Taylor1(constant_term(3) * constant_term(sin_ϕ[i]), order) - tmp1387[i] = Taylor1(constant_term(-1.5) * constant_term(sin_ϕ[i]), order) - tmp1389[i] = Taylor1(constant_term(2.5) * constant_term(sin3_ϕ[i]), order) - P_3_sin_ϕ[i] = Taylor1(constant_term(tmp1387[i]) + constant_term(tmp1389[i]), order) - tmp1393[i] = Taylor1(constant_term(7.5) * constant_term(sin2_ϕ[i]), order) - ∂P_3_sin_ϕ[i] = Taylor1(constant_term(-1.5) + constant_term(tmp1393[i]), order) - tmp1396[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(2)), order) - tmp1397[i] = Taylor1(constant_term(Λ2[i]) / constant_term(tmp1396[i]), order) - Λ2j_div_r4[i] = Taylor1(-(constant_term(tmp1397[i])), order) - tmp1400[i] = Taylor1(constant_term(r_p1d2[i]) ^ float(constant_term(5)), order) - tmp1401[i] = Taylor1(constant_term(Λ3[i]) / constant_term(tmp1400[i]), order) - Λ3j_div_r5[i] = Taylor1(-(constant_term(tmp1401[i])), order) - tmp1403[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) - m_c_ϕ_∂P_2[i] = Taylor1(constant_term(tmp1403[i]) * constant_term(∂P_2_sin_ϕ[i]), order) - tmp1405[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) - m_c_ϕ_∂P_3[i] = Taylor1(constant_term(tmp1405[i]) * constant_term(∂P_3_sin_ϕ[i]), order) - tmp1408[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(3), order) - F_J2_ξ[i] = Taylor1(constant_term(tmp1408[i]) * constant_term(P_2_sin_ϕ[i]), order) - F_J2_ζ[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]), order) - tmp1412[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(4), order) - F_J3_ξ[i] = Taylor1(constant_term(tmp1412[i]) * constant_term(P_3_sin_ϕ[i]), order) - F_J3_ζ[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]), order) - F_J_ξ[i] = Taylor1(identity(constant_term(F_J2_ξ[i])), order) - F_J_ζ[i] = Taylor1(identity(constant_term(F_J2_ζ[i])), order) - tmp1415[i] = Taylor1(-(constant_term(X[i])), order) - ξx[i] = Taylor1(constant_term(tmp1415[i]) / constant_term(r_p1d2[i]), order) - tmp1417[i] = Taylor1(-(constant_term(Y[i])), order) - ξy[i] = Taylor1(constant_term(tmp1417[i]) / constant_term(r_p1d2[i]), order) - tmp1419[i] = Taylor1(-(constant_term(Z[i])), order) - ξz[i] = Taylor1(constant_term(tmp1419[i]) / constant_term(r_p1d2[i]), order) - ηx1[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξz[i]), order) - ηy1[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξx[i]), order) - ηz1[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξy[i]), order) - ηx2[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξy[i]), order) - ηy2[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξz[i]), order) - ηz2[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξx[i]), order) - ηx[i] = Taylor1(constant_term(ηx1[i]) - constant_term(ηx2[i]), order) - ηy[i] = Taylor1(constant_term(ηy1[i]) - constant_term(ηy2[i]), order) - ηz[i] = Taylor1(constant_term(ηz1[i]) - constant_term(ηz2[i]), order) - ζx1[i] = Taylor1(constant_term(ξy[i]) * constant_term(ηz[i]), order) - ζy1[i] = Taylor1(constant_term(ξz[i]) * constant_term(ηx[i]), order) - ζz1[i] = Taylor1(constant_term(ξx[i]) * constant_term(ηy[i]), order) - ζx2[i] = Taylor1(constant_term(ξz[i]) * constant_term(ηy[i]), order) - ζy2[i] = Taylor1(constant_term(ξx[i]) * constant_term(ηz[i]), order) - ζz2[i] = Taylor1(constant_term(ξy[i]) * constant_term(ηx[i]), order) - ζx[i] = Taylor1(constant_term(ζx1[i]) - constant_term(ζx2[i]), order) - ζy[i] = Taylor1(constant_term(ζy1[i]) - constant_term(ζy2[i]), order) - ζz[i] = Taylor1(constant_term(ζz1[i]) - constant_term(ζz2[i]), order) - F_J2_x1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξx[i]), order) - F_J2_y1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξy[i]), order) - F_J2_z1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξz[i]), order) - F_J2_x2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζx[i]), order) - F_J2_y2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζy[i]), order) - F_J2_z2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζz[i]), order) - F_J2_x[i] = Taylor1(constant_term(F_J2_x1[i]) + constant_term(F_J2_x2[i]), order) - F_J2_y[i] = Taylor1(constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]), order) - F_J2_z[i] = Taylor1(constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]), order) - end - tmp1449[i] = Taylor1(constant_term(ui[i]) ^ float(constant_term(2)), order) - tmp1451[i] = Taylor1(constant_term(vi[i]) ^ float(constant_term(2)), order) - tmp1452[i] = Taylor1(constant_term(tmp1449[i]) + constant_term(tmp1451[i]), order) - tmp1454[i] = Taylor1(constant_term(wi[i]) ^ float(constant_term(2)), order) - v2[i] = Taylor1(constant_term(tmp1452[i]) + constant_term(tmp1454[i]), order) - end - tmp1457 = Taylor1(constant_term(q[4]) ^ float(constant_term(2)), order) - tmp1459 = Taylor1(constant_term(q[5]) ^ float(constant_term(2)), order) - tmp1460 = Taylor1(constant_term(tmp1457) + constant_term(tmp1459), order) - tmp1462 = Taylor1(constant_term(q[6]) ^ float(constant_term(2)), order) - v2[N] = Taylor1(constant_term(tmp1460) + constant_term(tmp1462), order) - temp_004 = Array{Taylor1{_S}}(undef, size(newtonian1b_Potential)) - temp_004 .= Taylor1(zero(constant_term(q[1])), order) - tmp1465 = Array{Taylor1{_S}}(undef, size(μ)) - tmp1465 .= Taylor1(zero(constant_term(q[1])), order) - tmp1467 = Array{Taylor1{_S}}(undef, size(μ)) - tmp1467 .= Taylor1(zero(constant_term(q[1])), order) - tmp1469 = Array{Taylor1{_S}}(undef, size(μ)) - tmp1469 .= Taylor1(zero(constant_term(q[1])), order) - for i = 1:Nm1 - temp_004[i] = Taylor1(constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]), order) - newtonianNb_Potential[N] = Taylor1(identity(constant_term(temp_004[i])), order) - if UJ_interaction[i] - tmp1465[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_x[i]), order) - temp_accX_i[i] = Taylor1(constant_term(accX) - constant_term(tmp1465[i]), order) - accX = Taylor1(identity(constant_term(temp_accX_i[i])), order) - tmp1467[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_y[i]), order) - temp_accY_i[i] = Taylor1(constant_term(accY) - constant_term(tmp1467[i]), order) - accY = Taylor1(identity(constant_term(temp_accY_i[i])), order) - tmp1469[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_z[i]), order) - temp_accZ_i[i] = Taylor1(constant_term(accZ) - constant_term(tmp1469[i]), order) - accZ = Taylor1(identity(constant_term(temp_accZ_i[i])), order) - end - end - _4ϕj[N] = Taylor1(constant_term(4) * constant_term(newtonianNb_Potential[N]), order) - tmp1475 = Array{Taylor1{_S}}(undef, size(v2)) - tmp1475 .= Taylor1(zero(constant_term(q[1])), order) - tmp1477 = Array{Taylor1{_S}}(undef, size(vi_dot_vj)) - tmp1477 .= Taylor1(zero(constant_term(q[1])), order) - tmp1478 = Array{Taylor1{_S}}(undef, size(tmp1475)) - tmp1478 .= Taylor1(zero(constant_term(q[1])), order) - Xij_t_Ui = Array{Taylor1{_S}}(undef, size(X)) - Xij_t_Ui .= Taylor1(zero(constant_term(q[1])), order) - Yij_t_Vi = Array{Taylor1{_S}}(undef, size(Y)) - Yij_t_Vi .= Taylor1(zero(constant_term(q[1])), order) - Zij_t_Wi = Array{Taylor1{_S}}(undef, size(Z)) - Zij_t_Wi .= Taylor1(zero(constant_term(q[1])), order) - tmp1484 = Array{Taylor1{_S}}(undef, size(Xij_t_Ui)) - tmp1484 .= Taylor1(zero(constant_term(q[1])), order) - Rij_dot_Vi = Array{Taylor1{_S}}(undef, size(tmp1484)) - Rij_dot_Vi .= Taylor1(zero(constant_term(q[1])), order) - tmp1487 = Array{Taylor1{_S}}(undef, size(Rij_dot_Vi)) - tmp1487 .= Taylor1(zero(constant_term(q[1])), order) - pn1t7 = Array{Taylor1{_S}}(undef, size(tmp1487)) - pn1t7 .= Taylor1(zero(constant_term(q[1])), order) - tmp1490 = Array{Taylor1{_S}}(undef, size(pn1t7)) - tmp1490 .= Taylor1(zero(constant_term(q[1])), order) - pn1t2_7 = Array{Taylor1{_S}}(undef, size(ϕs_and_vs)) - pn1t2_7 .= Taylor1(zero(constant_term(q[1])), order) - tmp1497 = Array{Taylor1{_S}}(undef, size(pNX_t_X)) - tmp1497 .= Taylor1(zero(constant_term(q[1])), order) - tmp1498 = Array{Taylor1{_S}}(undef, size(tmp1497)) - tmp1498 .= Taylor1(zero(constant_term(q[1])), order) - tmp1499 = Array{Taylor1{_S}}(undef, size(tmp1498)) - tmp1499 .= Taylor1(zero(constant_term(q[1])), order) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 - ϕi_plus_4ϕj[i] = Taylor1(constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]), order) - tmp1475[i] = Taylor1(constant_term(2) * constant_term(v2[i]), order) - tmp1477[i] = Taylor1(constant_term(4) * constant_term(vi_dot_vj[i]), order) - tmp1478[i] = Taylor1(constant_term(tmp1475[i]) - constant_term(tmp1477[i]), order) - sj2_plus_2si2_minus_4vivj[i] = Taylor1(constant_term(tmp1478[i]) + constant_term(v2[N]), order) - ϕs_and_vs[i] = Taylor1(constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]), order) - Xij_t_Ui[i] = Taylor1(constant_term(X[i]) * constant_term(ui[i]), order) - Yij_t_Vi[i] = Taylor1(constant_term(Y[i]) * constant_term(vi[i]), order) - Zij_t_Wi[i] = Taylor1(constant_term(Z[i]) * constant_term(wi[i]), order) - tmp1484[i] = Taylor1(constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]), order) - Rij_dot_Vi[i] = Taylor1(constant_term(tmp1484[i]) + constant_term(Zij_t_Wi[i]), order) - tmp1487[i] = Taylor1(constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)), order) - pn1t7[i] = Taylor1(constant_term(tmp1487[i]) / constant_term(r_p2[i]), order) - tmp1490[i] = Taylor1(constant_term(1.5) * constant_term(pn1t7[i]), order) - pn1t2_7[i] = Taylor1(constant_term(ϕs_and_vs[i]) - constant_term(tmp1490[i]), order) - pn1t1_7[i] = Taylor1(constant_term(c_p2) + constant_term(pn1t2_7[i]), order) - pNX_t_X[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(X[i]), order) - pNY_t_Y[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(Y[i]), order) - pNZ_t_Z[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(Z[i]), order) - tmp1497[i] = Taylor1(constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]), order) - tmp1498[i] = Taylor1(constant_term(tmp1497[i]) + constant_term(pNZ_t_Z[i]), order) - tmp1499[i] = Taylor1(constant_term(0.5) * constant_term(tmp1498[i]), order) - pn1[i] = Taylor1(constant_term(pn1t1_7[i]) + constant_term(tmp1499[i]), order) - X_t_pn1[i] = Taylor1(constant_term(newton_acc_X[i]) * constant_term(pn1[i]), order) - Y_t_pn1[i] = Taylor1(constant_term(newton_acc_Y[i]) * constant_term(pn1[i]), order) - Z_t_pn1[i] = Taylor1(constant_term(newton_acc_Z[i]) * constant_term(pn1[i]), order) - pNX_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(pn3[i]), order) - pNY_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]), order) - pNZ_t_pn3[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(pn3[i]), order) - end - tmp1507 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) - tmp1507 .= Taylor1(zero(constant_term(q[1])), order) - termpnx = Array{Taylor1{_S}}(undef, size(X_t_pn1)) - termpnx .= Taylor1(zero(constant_term(q[1])), order) - sumpnx = Array{Taylor1{_S}}(undef, size(termpnx)) - sumpnx .= Taylor1(zero(constant_term(q[1])), order) - tmp1510 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) - tmp1510 .= Taylor1(zero(constant_term(q[1])), order) - termpny = Array{Taylor1{_S}}(undef, size(Y_t_pn1)) - termpny .= Taylor1(zero(constant_term(q[1])), order) - sumpny = Array{Taylor1{_S}}(undef, size(termpny)) - sumpny .= Taylor1(zero(constant_term(q[1])), order) - tmp1513 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) - tmp1513 .= Taylor1(zero(constant_term(q[1])), order) - termpnz = Array{Taylor1{_S}}(undef, size(Z_t_pn1)) - termpnz .= Taylor1(zero(constant_term(q[1])), order) - sumpnz = Array{Taylor1{_S}}(undef, size(termpnz)) - sumpnz .= Taylor1(zero(constant_term(q[1])), order) - for i = 1:10 - tmp1507[i] = Taylor1(constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]), order) - termpnx[i] = Taylor1(constant_term(X_t_pn1[i]) + constant_term(tmp1507[i]), order) - sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) - pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) - tmp1510[i] = Taylor1(constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]), order) - termpny[i] = Taylor1(constant_term(Y_t_pn1[i]) + constant_term(tmp1510[i]), order) - sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) - pntempY = Taylor1(identity(constant_term(sumpny[i])), order) - tmp1513[i] = Taylor1(constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]), order) - termpnz[i] = Taylor1(constant_term(Z_t_pn1[i]) + constant_term(tmp1513[i]), order) - sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) - pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) - end - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 - X_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_X[i]), order) - Y_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Y[i]), order) - Z_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Z[i]), order) - end - for i = 11:Nm1 - termpnx[i] = Taylor1(identity(constant_term(X_t_pn1[i])), order) - sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) - pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) - termpny[i] = Taylor1(identity(constant_term(Y_t_pn1[i])), order) - sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) - pntempY = Taylor1(identity(constant_term(sumpny[i])), order) - termpnz[i] = Taylor1(identity(constant_term(Z_t_pn1[i])), order) - sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) - pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) - end - postNewtonX = Taylor1(constant_term(pntempX) * constant_term(c_m2), order) - postNewtonY = Taylor1(constant_term(pntempY) * constant_term(c_m2), order) - postNewtonZ = Taylor1(constant_term(pntempZ) * constant_term(c_m2), order) - dq[4] = Taylor1(constant_term(postNewtonX) + constant_term(accX), order) - dq[5] = Taylor1(constant_term(postNewtonY) + constant_term(accY), order) - dq[6] = Taylor1(constant_term(postNewtonZ) + constant_term(accZ), order) - return TaylorIntegration.RetAlloc{Taylor1{_S}}([tmp1457, tmp1459, tmp1460, tmp1462, pntempX, pntempY, pntempZ, accX, accY, accZ, postNewtonX, postNewtonY, postNewtonZ], [X, Y, Z, r_p2, r_p1d2, r_p3d2, r_p7d2, newtonianCoeff, ui, vi, wi, U, V, W, _4U_m_3X, _4V_m_3Y, _4W_m_3Z, UU, VV, WW, newtonian1b_Potential, newtonianNb_Potential, newton_acc_X, newton_acc_Y, newton_acc_Z, v2, vi_dot_vj, pn2, U_t_pn2, V_t_pn2, W_t_pn2, pn3, pNX_t_pn3, pNY_t_pn3, pNZ_t_pn3, _4ϕj, ϕi_plus_4ϕj, sj2_plus_2si2_minus_4vivj, ϕs_and_vs, pn1t1_7, pNX_t_X, pNY_t_Y, pNZ_t_Z, pn1, X_t_pn1, Y_t_pn1, Z_t_pn1, t31, t32, t33, r_sin_ϕ, sin_ϕ, ϕ, cos_ϕ, sin2_ϕ, sin3_ϕ, F_J2_x, F_J2_y, F_J2_z, F_J2_x1, F_J2_y1, F_J2_z1, F_J2_x2, F_J2_y2, F_J2_z2, temp_accX_i, temp_accY_i, temp_accZ_i, P_2_sin_ϕ, ∂P_2_sin_ϕ, P_3_sin_ϕ, ∂P_3_sin_ϕ, m_c_ϕ_∂P_2, m_c_ϕ_∂P_3, Λ2j_div_r4, Λ3j_div_r5, F_J_ξ, F_J_ζ, F_J2_ξ, F_J2_ζ, F_J3_ξ, F_J3_ζ, ξx, ξy, ξz, ηx, ηy, ηz, ηx1, ηy1, ηz1, ηx2, ηy2, ηz2, ζx, ζy, ζz, ζx1, ζy1, ζz1, ζx2, ζy2, ζz2, tmp1317, tmp1319, tmp1322, tmp1324, tmp1327, tmp1329, pn2x, pn2y, pn2z, tmp1337, tmp1340, tmp1342, tmp1343, tmp1345, tmp1353, tmp1354, tmp1365, tmp1367, tmp1369, tmp1371, tmp1528, tmp1529, tmp1381, tmp1387, tmp1389, tmp1393, tmp1396, tmp1397, tmp1400, tmp1401, tmp1403, tmp1405, tmp1408, tmp1412, tmp1415, tmp1417, tmp1419, tmp1449, tmp1451, tmp1452, tmp1454, temp_004, tmp1465, tmp1467, tmp1469, tmp1475, tmp1477, tmp1478, Xij_t_Ui, Yij_t_Vi, Zij_t_Wi, tmp1484, Rij_dot_Vi, tmp1487, pn1t7, tmp1490, pn1t2_7, tmp1497, tmp1498, tmp1499, tmp1507, termpnx, sumpnx, tmp1510, termpny, sumpny, tmp1513, termpnz, sumpnz], [Array{Taylor1{_S}, 2}(undef, 0, 0)], [Array{Taylor1{_S}, 3}(undef, 0, 0, 0)], [Array{Taylor1{_S}, 4}(undef, 0, 0, 0, 0)]) -end - -# TaylorIntegration.jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_eph_threads! -function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params, __ralloc::TaylorIntegration.RetAlloc{Taylor1{_S}}) where {_T <: Real, _S <: Number, _N} - order = t.order - tmp1457 = __ralloc.v0[1] - tmp1459 = __ralloc.v0[2] - tmp1460 = __ralloc.v0[3] - tmp1462 = __ralloc.v0[4] - pntempX = __ralloc.v0[5] - pntempY = __ralloc.v0[6] - pntempZ = __ralloc.v0[7] - accX = __ralloc.v0[8] - accY = __ralloc.v0[9] - accZ = __ralloc.v0[10] - postNewtonX = __ralloc.v0[11] - postNewtonY = __ralloc.v0[12] - postNewtonZ = __ralloc.v0[13] - X = __ralloc.v1[1] - Y = __ralloc.v1[2] - Z = __ralloc.v1[3] - r_p2 = __ralloc.v1[4] - r_p1d2 = __ralloc.v1[5] - r_p3d2 = __ralloc.v1[6] - r_p7d2 = __ralloc.v1[7] - newtonianCoeff = __ralloc.v1[8] - ui = __ralloc.v1[9] - vi = __ralloc.v1[10] - wi = __ralloc.v1[11] - U = __ralloc.v1[12] - V = __ralloc.v1[13] - W = __ralloc.v1[14] - _4U_m_3X = __ralloc.v1[15] - _4V_m_3Y = __ralloc.v1[16] - _4W_m_3Z = __ralloc.v1[17] - UU = __ralloc.v1[18] - VV = __ralloc.v1[19] - WW = __ralloc.v1[20] - newtonian1b_Potential = __ralloc.v1[21] - newtonianNb_Potential = __ralloc.v1[22] - newton_acc_X = __ralloc.v1[23] - newton_acc_Y = __ralloc.v1[24] - newton_acc_Z = __ralloc.v1[25] - v2 = __ralloc.v1[26] - vi_dot_vj = __ralloc.v1[27] - pn2 = __ralloc.v1[28] - U_t_pn2 = __ralloc.v1[29] - V_t_pn2 = __ralloc.v1[30] - W_t_pn2 = __ralloc.v1[31] - pn3 = __ralloc.v1[32] - pNX_t_pn3 = __ralloc.v1[33] - pNY_t_pn3 = __ralloc.v1[34] - pNZ_t_pn3 = __ralloc.v1[35] - _4ϕj = __ralloc.v1[36] - ϕi_plus_4ϕj = __ralloc.v1[37] - sj2_plus_2si2_minus_4vivj = __ralloc.v1[38] - ϕs_and_vs = __ralloc.v1[39] - pn1t1_7 = __ralloc.v1[40] - pNX_t_X = __ralloc.v1[41] - pNY_t_Y = __ralloc.v1[42] - pNZ_t_Z = __ralloc.v1[43] - pn1 = __ralloc.v1[44] - X_t_pn1 = __ralloc.v1[45] - Y_t_pn1 = __ralloc.v1[46] - Z_t_pn1 = __ralloc.v1[47] - t31 = __ralloc.v1[48] - t32 = __ralloc.v1[49] - t33 = __ralloc.v1[50] - r_sin_ϕ = __ralloc.v1[51] - sin_ϕ = __ralloc.v1[52] - ϕ = __ralloc.v1[53] - cos_ϕ = __ralloc.v1[54] - sin2_ϕ = __ralloc.v1[55] - sin3_ϕ = __ralloc.v1[56] - F_J2_x = __ralloc.v1[57] - F_J2_y = __ralloc.v1[58] - F_J2_z = __ralloc.v1[59] - F_J2_x1 = __ralloc.v1[60] - F_J2_y1 = __ralloc.v1[61] - F_J2_z1 = __ralloc.v1[62] - F_J2_x2 = __ralloc.v1[63] - F_J2_y2 = __ralloc.v1[64] - F_J2_z2 = __ralloc.v1[65] - temp_accX_i = __ralloc.v1[66] - temp_accY_i = __ralloc.v1[67] - temp_accZ_i = __ralloc.v1[68] - P_2_sin_ϕ = __ralloc.v1[69] - ∂P_2_sin_ϕ = __ralloc.v1[70] - P_3_sin_ϕ = __ralloc.v1[71] - ∂P_3_sin_ϕ = __ralloc.v1[72] - m_c_ϕ_∂P_2 = __ralloc.v1[73] - m_c_ϕ_∂P_3 = __ralloc.v1[74] - Λ2j_div_r4 = __ralloc.v1[75] - Λ3j_div_r5 = __ralloc.v1[76] - F_J_ξ = __ralloc.v1[77] - F_J_ζ = __ralloc.v1[78] - F_J2_ξ = __ralloc.v1[79] - F_J2_ζ = __ralloc.v1[80] - F_J3_ξ = __ralloc.v1[81] - F_J3_ζ = __ralloc.v1[82] - ξx = __ralloc.v1[83] - ξy = __ralloc.v1[84] - ξz = __ralloc.v1[85] - ηx = __ralloc.v1[86] - ηy = __ralloc.v1[87] - ηz = __ralloc.v1[88] - ηx1 = __ralloc.v1[89] - ηy1 = __ralloc.v1[90] - ηz1 = __ralloc.v1[91] - ηx2 = __ralloc.v1[92] - ηy2 = __ralloc.v1[93] - ηz2 = __ralloc.v1[94] - ζx = __ralloc.v1[95] - ζy = __ralloc.v1[96] - ζz = __ralloc.v1[97] - ζx1 = __ralloc.v1[98] - ζy1 = __ralloc.v1[99] - ζz1 = __ralloc.v1[100] - ζx2 = __ralloc.v1[101] - ζy2 = __ralloc.v1[102] - ζz2 = __ralloc.v1[103] - tmp1317 = __ralloc.v1[104] - tmp1319 = __ralloc.v1[105] - tmp1322 = __ralloc.v1[106] - tmp1324 = __ralloc.v1[107] - tmp1327 = __ralloc.v1[108] - tmp1329 = __ralloc.v1[109] - pn2x = __ralloc.v1[110] - pn2y = __ralloc.v1[111] - pn2z = __ralloc.v1[112] - tmp1337 = __ralloc.v1[113] - tmp1340 = __ralloc.v1[114] - tmp1342 = __ralloc.v1[115] - tmp1343 = __ralloc.v1[116] - tmp1345 = __ralloc.v1[117] - tmp1353 = __ralloc.v1[118] - tmp1354 = __ralloc.v1[119] - tmp1365 = __ralloc.v1[120] - tmp1367 = __ralloc.v1[121] - tmp1369 = __ralloc.v1[122] - tmp1371 = __ralloc.v1[123] - tmp1528 = __ralloc.v1[124] - tmp1529 = __ralloc.v1[125] - tmp1381 = __ralloc.v1[126] - tmp1387 = __ralloc.v1[127] - tmp1389 = __ralloc.v1[128] - tmp1393 = __ralloc.v1[129] - tmp1396 = __ralloc.v1[130] - tmp1397 = __ralloc.v1[131] - tmp1400 = __ralloc.v1[132] - tmp1401 = __ralloc.v1[133] - tmp1403 = __ralloc.v1[134] - tmp1405 = __ralloc.v1[135] - tmp1408 = __ralloc.v1[136] - tmp1412 = __ralloc.v1[137] - tmp1415 = __ralloc.v1[138] - tmp1417 = __ralloc.v1[139] - tmp1419 = __ralloc.v1[140] - tmp1449 = __ralloc.v1[141] - tmp1451 = __ralloc.v1[142] - tmp1452 = __ralloc.v1[143] - tmp1454 = __ralloc.v1[144] - temp_004 = __ralloc.v1[145] - tmp1465 = __ralloc.v1[146] - tmp1467 = __ralloc.v1[147] - tmp1469 = __ralloc.v1[148] - tmp1475 = __ralloc.v1[149] - tmp1477 = __ralloc.v1[150] - tmp1478 = __ralloc.v1[151] - Xij_t_Ui = __ralloc.v1[152] - Yij_t_Vi = __ralloc.v1[153] - Zij_t_Wi = __ralloc.v1[154] - tmp1484 = __ralloc.v1[155] - Rij_dot_Vi = __ralloc.v1[156] - tmp1487 = __ralloc.v1[157] - pn1t7 = __ralloc.v1[158] - tmp1490 = __ralloc.v1[159] - pn1t2_7 = __ralloc.v1[160] - tmp1497 = __ralloc.v1[161] - tmp1498 = __ralloc.v1[162] - tmp1499 = __ralloc.v1[163] - tmp1507 = __ralloc.v1[164] - termpnx = __ralloc.v1[165] - sumpnx = __ralloc.v1[166] - tmp1510 = __ralloc.v1[167] - termpny = __ralloc.v1[168] - sumpny = __ralloc.v1[169] - tmp1513 = __ralloc.v1[170] - termpnz = __ralloc.v1[171] - sumpnz = __ralloc.v1[172] - local jd0 = params[4] - local dsj2k = t + (jd0 - JD_J2000) - local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) - local acceph_t = evaleph(params[2], dsj2k, q[1]) - local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) - local S = eltype(q) - local UJ_interaction = params[5] - local N = params[6] - local Nm1 = N - 1 - local μ = params[7] - local zero_q_1 = auxzero(q[1]) - pntempX.coeffs[1] = identity(constant_term(zero_q_1)) - pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) - pntempY.coeffs[1] = identity(constant_term(zero_q_1)) - pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) - pntempZ.coeffs[1] = identity(constant_term(zero_q_1)) - pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) - accX.coeffs[1] = identity(constant_term(zero_q_1)) - accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) - accY.coeffs[1] = identity(constant_term(zero_q_1)) - accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) - accZ.coeffs[1] = identity(constant_term(zero_q_1)) - accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) - local M_ = Array{S}(undef, 3, 3, N) - local M_ .= zero_q_1 - local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 - (dq[1]).coeffs[1] = identity(constant_term(q[4])) - (dq[1]).coeffs[2:order + 1] .= zero((dq[1]).coeffs[1]) - (dq[2]).coeffs[1] = identity(constant_term(q[5])) - (dq[2]).coeffs[2:order + 1] .= zero((dq[2]).coeffs[1]) - (dq[3]).coeffs[1] = identity(constant_term(q[6])) - (dq[3]).coeffs[2:order + 1] .= zero((dq[3]).coeffs[1]) - (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(zero_q_1)) - (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 - (ui[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])) - (ui[i]).coeffs[2:order + 1] .= zero((ui[i]).coeffs[1]) - (vi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])) - (vi[i]).coeffs[2:order + 1] .= zero((vi[i]).coeffs[1]) - (wi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])) - (wi[i]).coeffs[2:order + 1] .= zero((wi[i]).coeffs[1]) - (X[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 2]) - constant_term(q[1]) - (X[i]).coeffs[2:order + 1] .= zero((X[i]).coeffs[1]) - (Y[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 1]) - constant_term(q[2]) - (Y[i]).coeffs[2:order + 1] .= zero((Y[i]).coeffs[1]) - (Z[i]).coeffs[1] = constant_term(ss16asteph_t[3i]) - constant_term(q[3]) - (Z[i]).coeffs[2:order + 1] .= zero((Z[i]).coeffs[1]) - (U[i]).coeffs[1] = constant_term(ui[i]) - constant_term(dq[1]) - (U[i]).coeffs[2:order + 1] .= zero((U[i]).coeffs[1]) - (V[i]).coeffs[1] = constant_term(vi[i]) - constant_term(dq[2]) - (V[i]).coeffs[2:order + 1] .= zero((V[i]).coeffs[1]) - (W[i]).coeffs[1] = constant_term(wi[i]) - constant_term(dq[3]) - (W[i]).coeffs[2:order + 1] .= zero((W[i]).coeffs[1]) - (tmp1317[1]).coeffs[1] = constant_term(4) * constant_term(dq[1]) - (tmp1317[1]).coeffs[2:order + 1] .= zero((tmp1317[1]).coeffs[1]) - (tmp1319[i]).coeffs[1] = constant_term(3) * constant_term(ui[i]) - (tmp1319[i]).coeffs[2:order + 1] .= zero((tmp1319[i]).coeffs[1]) - (_4U_m_3X[i]).coeffs[1] = constant_term(tmp1317[1]) - constant_term(tmp1319[i]) - (_4U_m_3X[i]).coeffs[2:order + 1] .= zero((_4U_m_3X[i]).coeffs[1]) - (tmp1322[2]).coeffs[1] = constant_term(4) * constant_term(dq[2]) - (tmp1322[2]).coeffs[2:order + 1] .= zero((tmp1322[2]).coeffs[1]) - (tmp1324[i]).coeffs[1] = constant_term(3) * constant_term(vi[i]) - (tmp1324[i]).coeffs[2:order + 1] .= zero((tmp1324[i]).coeffs[1]) - (_4V_m_3Y[i]).coeffs[1] = constant_term(tmp1322[2]) - constant_term(tmp1324[i]) - (_4V_m_3Y[i]).coeffs[2:order + 1] .= zero((_4V_m_3Y[i]).coeffs[1]) - (tmp1327[3]).coeffs[1] = constant_term(4) * constant_term(dq[3]) - (tmp1327[3]).coeffs[2:order + 1] .= zero((tmp1327[3]).coeffs[1]) - (tmp1329[i]).coeffs[1] = constant_term(3) * constant_term(wi[i]) - (tmp1329[i]).coeffs[2:order + 1] .= zero((tmp1329[i]).coeffs[1]) - (_4W_m_3Z[i]).coeffs[1] = constant_term(tmp1327[3]) - constant_term(tmp1329[i]) - (_4W_m_3Z[i]).coeffs[2:order + 1] .= zero((_4W_m_3Z[i]).coeffs[1]) - (pn2x[i]).coeffs[1] = constant_term(X[i]) * constant_term(_4U_m_3X[i]) - (pn2x[i]).coeffs[2:order + 1] .= zero((pn2x[i]).coeffs[1]) - (pn2y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(_4V_m_3Y[i]) - (pn2y[i]).coeffs[2:order + 1] .= zero((pn2y[i]).coeffs[1]) - (pn2z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(_4W_m_3Z[i]) - (pn2z[i]).coeffs[2:order + 1] .= zero((pn2z[i]).coeffs[1]) - (UU[i]).coeffs[1] = constant_term(ui[i]) * constant_term(dq[1]) - (UU[i]).coeffs[2:order + 1] .= zero((UU[i]).coeffs[1]) - (VV[i]).coeffs[1] = constant_term(vi[i]) * constant_term(dq[2]) - (VV[i]).coeffs[2:order + 1] .= zero((VV[i]).coeffs[1]) - (WW[i]).coeffs[1] = constant_term(wi[i]) * constant_term(dq[3]) - (WW[i]).coeffs[2:order + 1] .= zero((WW[i]).coeffs[1]) - (tmp1337[i]).coeffs[1] = constant_term(UU[i]) + constant_term(VV[i]) - (tmp1337[i]).coeffs[2:order + 1] .= zero((tmp1337[i]).coeffs[1]) - (vi_dot_vj[i]).coeffs[1] = constant_term(tmp1337[i]) + constant_term(WW[i]) - (vi_dot_vj[i]).coeffs[2:order + 1] .= zero((vi_dot_vj[i]).coeffs[1]) - (tmp1340[i]).coeffs[1] = constant_term(X[i]) ^ float(constant_term(2)) - (tmp1340[i]).coeffs[2:order + 1] .= zero((tmp1340[i]).coeffs[1]) - (tmp1342[i]).coeffs[1] = constant_term(Y[i]) ^ float(constant_term(2)) - (tmp1342[i]).coeffs[2:order + 1] .= zero((tmp1342[i]).coeffs[1]) - (tmp1343[i]).coeffs[1] = constant_term(tmp1340[i]) + constant_term(tmp1342[i]) - (tmp1343[i]).coeffs[2:order + 1] .= zero((tmp1343[i]).coeffs[1]) - (tmp1345[i]).coeffs[1] = constant_term(Z[i]) ^ float(constant_term(2)) - (tmp1345[i]).coeffs[2:order + 1] .= zero((tmp1345[i]).coeffs[1]) - (r_p2[i]).coeffs[1] = constant_term(tmp1343[i]) + constant_term(tmp1345[i]) - (r_p2[i]).coeffs[2:order + 1] .= zero((r_p2[i]).coeffs[1]) - (r_p1d2[i]).coeffs[1] = sqrt(constant_term(r_p2[i])) - (r_p1d2[i]).coeffs[2:order + 1] .= zero((r_p1d2[i]).coeffs[1]) - (r_p3d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(1.5)) - (r_p3d2[i]).coeffs[2:order + 1] .= zero((r_p3d2[i]).coeffs[1]) - (r_p7d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(3.5)) - (r_p7d2[i]).coeffs[2:order + 1] .= zero((r_p7d2[i]).coeffs[1]) - (newtonianCoeff[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p3d2[i]) - (newtonianCoeff[i]).coeffs[2:order + 1] .= zero((newtonianCoeff[i]).coeffs[1]) - (tmp1353[i]).coeffs[1] = constant_term(pn2x[i]) + constant_term(pn2y[i]) - (tmp1353[i]).coeffs[2:order + 1] .= zero((tmp1353[i]).coeffs[1]) - (tmp1354[i]).coeffs[1] = constant_term(tmp1353[i]) + constant_term(pn2z[i]) - (tmp1354[i]).coeffs[2:order + 1] .= zero((tmp1354[i]).coeffs[1]) - (pn2[i]).coeffs[1] = constant_term(newtonianCoeff[i]) * constant_term(tmp1354[i]) - (pn2[i]).coeffs[2:order + 1] .= zero((pn2[i]).coeffs[1]) - (newton_acc_X[i]).coeffs[1] = constant_term(X[i]) * constant_term(newtonianCoeff[i]) - (newton_acc_X[i]).coeffs[2:order + 1] .= zero((newton_acc_X[i]).coeffs[1]) - (newton_acc_Y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(newtonianCoeff[i]) - (newton_acc_Y[i]).coeffs[2:order + 1] .= zero((newton_acc_Y[i]).coeffs[1]) - (newton_acc_Z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(newtonianCoeff[i]) - (newton_acc_Z[i]).coeffs[2:order + 1] .= zero((newton_acc_Z[i]).coeffs[1]) - (newtonian1b_Potential[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p1d2[i]) - (newtonian1b_Potential[i]).coeffs[2:order + 1] .= zero((newtonian1b_Potential[i]).coeffs[1]) - (pn3[i]).coeffs[1] = constant_term(3.5) * constant_term(newtonian1b_Potential[i]) - (pn3[i]).coeffs[2:order + 1] .= zero((pn3[i]).coeffs[1]) - (U_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(U[i]) - (U_t_pn2[i]).coeffs[2:order + 1] .= zero((U_t_pn2[i]).coeffs[1]) - (V_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(V[i]) - (V_t_pn2[i]).coeffs[2:order + 1] .= zero((V_t_pn2[i]).coeffs[1]) - (W_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(W[i]) - (W_t_pn2[i]).coeffs[2:order + 1] .= zero((W_t_pn2[i]).coeffs[1]) - if UJ_interaction[i] - (tmp1365[i]).coeffs[1] = -(constant_term(X[i])) - (tmp1365[i]).coeffs[2:order + 1] .= zero((tmp1365[i]).coeffs[1]) - (t31[i]).coeffs[1] = constant_term(tmp1365[i]) * constant_term(M_[1, 3, i]) - (t31[i]).coeffs[2:order + 1] .= zero((t31[i]).coeffs[1]) - (tmp1367[i]).coeffs[1] = -(constant_term(Y[i])) - (tmp1367[i]).coeffs[2:order + 1] .= zero((tmp1367[i]).coeffs[1]) - (t32[i]).coeffs[1] = constant_term(tmp1367[i]) * constant_term(M_[2, 3, i]) - (t32[i]).coeffs[2:order + 1] .= zero((t32[i]).coeffs[1]) - (tmp1369[i]).coeffs[1] = -(constant_term(Z[i])) - (tmp1369[i]).coeffs[2:order + 1] .= zero((tmp1369[i]).coeffs[1]) - (t33[i]).coeffs[1] = constant_term(tmp1369[i]) * constant_term(M_[3, 3, i]) - (t33[i]).coeffs[2:order + 1] .= zero((t33[i]).coeffs[1]) - (tmp1371[i]).coeffs[1] = constant_term(t31[i]) + constant_term(t32[i]) - (tmp1371[i]).coeffs[2:order + 1] .= zero((tmp1371[i]).coeffs[1]) - (r_sin_ϕ[i]).coeffs[1] = constant_term(tmp1371[i]) + constant_term(t33[i]) - (r_sin_ϕ[i]).coeffs[2:order + 1] .= zero((r_sin_ϕ[i]).coeffs[1]) - (sin_ϕ[i]).coeffs[1] = constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]) - (sin_ϕ[i]).coeffs[2:order + 1] .= zero((sin_ϕ[i]).coeffs[1]) - (ϕ[i]).coeffs[1] = asin(constant_term(sin_ϕ[i])) - (ϕ[i]).coeffs[2:order + 1] .= zero((ϕ[i]).coeffs[1]) - (tmp1528[i]).coeffs[1] = sqrt(1 - constant_term(sin_ϕ[i]) ^ 2) - (tmp1528[i]).coeffs[2:order + 1] .= zero((tmp1528[i]).coeffs[1]) - (cos_ϕ[i]).coeffs[1] = cos(constant_term(ϕ[i])) - (cos_ϕ[i]).coeffs[2:order + 1] .= zero((cos_ϕ[i]).coeffs[1]) - (tmp1529[i]).coeffs[1] = sin(constant_term(ϕ[i])) - (tmp1529[i]).coeffs[2:order + 1] .= zero((tmp1529[i]).coeffs[1]) - (sin2_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(2)) - (sin2_ϕ[i]).coeffs[2:order + 1] .= zero((sin2_ϕ[i]).coeffs[1]) - (sin3_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(3)) - (sin3_ϕ[i]).coeffs[2:order + 1] .= zero((sin3_ϕ[i]).coeffs[1]) - (tmp1381[i]).coeffs[1] = constant_term(1.5) * constant_term(sin2_ϕ[i]) - (tmp1381[i]).coeffs[2:order + 1] .= zero((tmp1381[i]).coeffs[1]) - (P_2_sin_ϕ[i]).coeffs[1] = constant_term(tmp1381[i]) - constant_term(0.5) - (P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_2_sin_ϕ[i]).coeffs[1]) - (∂P_2_sin_ϕ[i]).coeffs[1] = constant_term(3) * constant_term(sin_ϕ[i]) - (∂P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_2_sin_ϕ[i]).coeffs[1]) - (tmp1387[i]).coeffs[1] = constant_term(-1.5) * constant_term(sin_ϕ[i]) - (tmp1387[i]).coeffs[2:order + 1] .= zero((tmp1387[i]).coeffs[1]) - (tmp1389[i]).coeffs[1] = constant_term(2.5) * constant_term(sin3_ϕ[i]) - (tmp1389[i]).coeffs[2:order + 1] .= zero((tmp1389[i]).coeffs[1]) - (P_3_sin_ϕ[i]).coeffs[1] = constant_term(tmp1387[i]) + constant_term(tmp1389[i]) - (P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_3_sin_ϕ[i]).coeffs[1]) - (tmp1393[i]).coeffs[1] = constant_term(7.5) * constant_term(sin2_ϕ[i]) - (tmp1393[i]).coeffs[2:order + 1] .= zero((tmp1393[i]).coeffs[1]) - (∂P_3_sin_ϕ[i]).coeffs[1] = constant_term(-1.5) + constant_term(tmp1393[i]) - (∂P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_3_sin_ϕ[i]).coeffs[1]) - (tmp1396[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(2)) - (tmp1396[i]).coeffs[2:order + 1] .= zero((tmp1396[i]).coeffs[1]) - (tmp1397[i]).coeffs[1] = constant_term(Λ2[i]) / constant_term(tmp1396[i]) - (tmp1397[i]).coeffs[2:order + 1] .= zero((tmp1397[i]).coeffs[1]) - (Λ2j_div_r4[i]).coeffs[1] = -(constant_term(tmp1397[i])) - (Λ2j_div_r4[i]).coeffs[2:order + 1] .= zero((Λ2j_div_r4[i]).coeffs[1]) - (tmp1400[i]).coeffs[1] = constant_term(r_p1d2[i]) ^ float(constant_term(5)) - (tmp1400[i]).coeffs[2:order + 1] .= zero((tmp1400[i]).coeffs[1]) - (tmp1401[i]).coeffs[1] = constant_term(Λ3[i]) / constant_term(tmp1400[i]) - (tmp1401[i]).coeffs[2:order + 1] .= zero((tmp1401[i]).coeffs[1]) - (Λ3j_div_r5[i]).coeffs[1] = -(constant_term(tmp1401[i])) - (Λ3j_div_r5[i]).coeffs[2:order + 1] .= zero((Λ3j_div_r5[i]).coeffs[1]) - (tmp1403[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) - (tmp1403[i]).coeffs[2:order + 1] .= zero((tmp1403[i]).coeffs[1]) - (m_c_ϕ_∂P_2[i]).coeffs[1] = constant_term(tmp1403[i]) * constant_term(∂P_2_sin_ϕ[i]) - (m_c_ϕ_∂P_2[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_2[i]).coeffs[1]) - (tmp1405[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) - (tmp1405[i]).coeffs[2:order + 1] .= zero((tmp1405[i]).coeffs[1]) - (m_c_ϕ_∂P_3[i]).coeffs[1] = constant_term(tmp1405[i]) * constant_term(∂P_3_sin_ϕ[i]) - (m_c_ϕ_∂P_3[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_3[i]).coeffs[1]) - (tmp1408[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(3) - (tmp1408[i]).coeffs[2:order + 1] .= zero((tmp1408[i]).coeffs[1]) - (F_J2_ξ[i]).coeffs[1] = constant_term(tmp1408[i]) * constant_term(P_2_sin_ϕ[i]) - (F_J2_ξ[i]).coeffs[2:order + 1] .= zero((F_J2_ξ[i]).coeffs[1]) - (F_J2_ζ[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]) - (F_J2_ζ[i]).coeffs[2:order + 1] .= zero((F_J2_ζ[i]).coeffs[1]) - (tmp1412[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(4) - (tmp1412[i]).coeffs[2:order + 1] .= zero((tmp1412[i]).coeffs[1]) - (F_J3_ξ[i]).coeffs[1] = constant_term(tmp1412[i]) * constant_term(P_3_sin_ϕ[i]) - (F_J3_ξ[i]).coeffs[2:order + 1] .= zero((F_J3_ξ[i]).coeffs[1]) - (F_J3_ζ[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]) - (F_J3_ζ[i]).coeffs[2:order + 1] .= zero((F_J3_ζ[i]).coeffs[1]) - (F_J_ξ[i]).coeffs[1] = identity(constant_term(F_J2_ξ[i])) - (F_J_ξ[i]).coeffs[2:order + 1] .= zero((F_J_ξ[i]).coeffs[1]) - (F_J_ζ[i]).coeffs[1] = identity(constant_term(F_J2_ζ[i])) - (F_J_ζ[i]).coeffs[2:order + 1] .= zero((F_J_ζ[i]).coeffs[1]) - (tmp1415[i]).coeffs[1] = -(constant_term(X[i])) - (tmp1415[i]).coeffs[2:order + 1] .= zero((tmp1415[i]).coeffs[1]) - (ξx[i]).coeffs[1] = constant_term(tmp1415[i]) / constant_term(r_p1d2[i]) - (ξx[i]).coeffs[2:order + 1] .= zero((ξx[i]).coeffs[1]) - (tmp1417[i]).coeffs[1] = -(constant_term(Y[i])) - (tmp1417[i]).coeffs[2:order + 1] .= zero((tmp1417[i]).coeffs[1]) - (ξy[i]).coeffs[1] = constant_term(tmp1417[i]) / constant_term(r_p1d2[i]) - (ξy[i]).coeffs[2:order + 1] .= zero((ξy[i]).coeffs[1]) - (tmp1419[i]).coeffs[1] = -(constant_term(Z[i])) - (tmp1419[i]).coeffs[2:order + 1] .= zero((tmp1419[i]).coeffs[1]) - (ξz[i]).coeffs[1] = constant_term(tmp1419[i]) / constant_term(r_p1d2[i]) - (ξz[i]).coeffs[2:order + 1] .= zero((ξz[i]).coeffs[1]) - (ηx1[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξz[i]) - (ηx1[i]).coeffs[2:order + 1] .= zero((ηx1[i]).coeffs[1]) - (ηy1[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξx[i]) - (ηy1[i]).coeffs[2:order + 1] .= zero((ηy1[i]).coeffs[1]) - (ηz1[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξy[i]) - (ηz1[i]).coeffs[2:order + 1] .= zero((ηz1[i]).coeffs[1]) - (ηx2[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξy[i]) - (ηx2[i]).coeffs[2:order + 1] .= zero((ηx2[i]).coeffs[1]) - (ηy2[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξz[i]) - (ηy2[i]).coeffs[2:order + 1] .= zero((ηy2[i]).coeffs[1]) - (ηz2[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξx[i]) - (ηz2[i]).coeffs[2:order + 1] .= zero((ηz2[i]).coeffs[1]) - (ηx[i]).coeffs[1] = constant_term(ηx1[i]) - constant_term(ηx2[i]) - (ηx[i]).coeffs[2:order + 1] .= zero((ηx[i]).coeffs[1]) - (ηy[i]).coeffs[1] = constant_term(ηy1[i]) - constant_term(ηy2[i]) - (ηy[i]).coeffs[2:order + 1] .= zero((ηy[i]).coeffs[1]) - (ηz[i]).coeffs[1] = constant_term(ηz1[i]) - constant_term(ηz2[i]) - (ηz[i]).coeffs[2:order + 1] .= zero((ηz[i]).coeffs[1]) - (ζx1[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηz[i]) - (ζx1[i]).coeffs[2:order + 1] .= zero((ζx1[i]).coeffs[1]) - (ζy1[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηx[i]) - (ζy1[i]).coeffs[2:order + 1] .= zero((ζy1[i]).coeffs[1]) - (ζz1[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηy[i]) - (ζz1[i]).coeffs[2:order + 1] .= zero((ζz1[i]).coeffs[1]) - (ζx2[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηy[i]) - (ζx2[i]).coeffs[2:order + 1] .= zero((ζx2[i]).coeffs[1]) - (ζy2[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηz[i]) - (ζy2[i]).coeffs[2:order + 1] .= zero((ζy2[i]).coeffs[1]) - (ζz2[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηx[i]) - (ζz2[i]).coeffs[2:order + 1] .= zero((ζz2[i]).coeffs[1]) - (ζx[i]).coeffs[1] = constant_term(ζx1[i]) - constant_term(ζx2[i]) - (ζx[i]).coeffs[2:order + 1] .= zero((ζx[i]).coeffs[1]) - (ζy[i]).coeffs[1] = constant_term(ζy1[i]) - constant_term(ζy2[i]) - (ζy[i]).coeffs[2:order + 1] .= zero((ζy[i]).coeffs[1]) - (ζz[i]).coeffs[1] = constant_term(ζz1[i]) - constant_term(ζz2[i]) - (ζz[i]).coeffs[2:order + 1] .= zero((ζz[i]).coeffs[1]) - (F_J2_x1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξx[i]) - (F_J2_x1[i]).coeffs[2:order + 1] .= zero((F_J2_x1[i]).coeffs[1]) - (F_J2_y1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξy[i]) - (F_J2_y1[i]).coeffs[2:order + 1] .= zero((F_J2_y1[i]).coeffs[1]) - (F_J2_z1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξz[i]) - (F_J2_z1[i]).coeffs[2:order + 1] .= zero((F_J2_z1[i]).coeffs[1]) - (F_J2_x2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζx[i]) - (F_J2_x2[i]).coeffs[2:order + 1] .= zero((F_J2_x2[i]).coeffs[1]) - (F_J2_y2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζy[i]) - (F_J2_y2[i]).coeffs[2:order + 1] .= zero((F_J2_y2[i]).coeffs[1]) - (F_J2_z2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζz[i]) - (F_J2_z2[i]).coeffs[2:order + 1] .= zero((F_J2_z2[i]).coeffs[1]) - (F_J2_x[i]).coeffs[1] = constant_term(F_J2_x1[i]) + constant_term(F_J2_x2[i]) - (F_J2_x[i]).coeffs[2:order + 1] .= zero((F_J2_x[i]).coeffs[1]) - (F_J2_y[i]).coeffs[1] = constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]) - (F_J2_y[i]).coeffs[2:order + 1] .= zero((F_J2_y[i]).coeffs[1]) - (F_J2_z[i]).coeffs[1] = constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]) - (F_J2_z[i]).coeffs[2:order + 1] .= zero((F_J2_z[i]).coeffs[1]) - end - (tmp1449[i]).coeffs[1] = constant_term(ui[i]) ^ float(constant_term(2)) - (tmp1449[i]).coeffs[2:order + 1] .= zero((tmp1449[i]).coeffs[1]) - (tmp1451[i]).coeffs[1] = constant_term(vi[i]) ^ float(constant_term(2)) - (tmp1451[i]).coeffs[2:order + 1] .= zero((tmp1451[i]).coeffs[1]) - (tmp1452[i]).coeffs[1] = constant_term(tmp1449[i]) + constant_term(tmp1451[i]) - (tmp1452[i]).coeffs[2:order + 1] .= zero((tmp1452[i]).coeffs[1]) - (tmp1454[i]).coeffs[1] = constant_term(wi[i]) ^ float(constant_term(2)) - (tmp1454[i]).coeffs[2:order + 1] .= zero((tmp1454[i]).coeffs[1]) - (v2[i]).coeffs[1] = constant_term(tmp1452[i]) + constant_term(tmp1454[i]) - (v2[i]).coeffs[2:order + 1] .= zero((v2[i]).coeffs[1]) - end - tmp1457.coeffs[1] = constant_term(q[4]) ^ float(constant_term(2)) - tmp1457.coeffs[2:order + 1] .= zero(tmp1457.coeffs[1]) - tmp1459.coeffs[1] = constant_term(q[5]) ^ float(constant_term(2)) - tmp1459.coeffs[2:order + 1] .= zero(tmp1459.coeffs[1]) - tmp1460.coeffs[1] = constant_term(tmp1457) + constant_term(tmp1459) - tmp1460.coeffs[2:order + 1] .= zero(tmp1460.coeffs[1]) - tmp1462.coeffs[1] = constant_term(q[6]) ^ float(constant_term(2)) - tmp1462.coeffs[2:order + 1] .= zero(tmp1462.coeffs[1]) - (v2[N]).coeffs[1] = constant_term(tmp1460) + constant_term(tmp1462) - (v2[N]).coeffs[2:order + 1] .= zero((v2[N]).coeffs[1]) - for i = 1:Nm1 - (temp_004[i]).coeffs[1] = constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]) - (temp_004[i]).coeffs[2:order + 1] .= zero((temp_004[i]).coeffs[1]) - (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(temp_004[i])) - (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) - if UJ_interaction[i] - (tmp1465[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_x[i]) - (tmp1465[i]).coeffs[2:order + 1] .= zero((tmp1465[i]).coeffs[1]) - (temp_accX_i[i]).coeffs[1] = constant_term(accX) - constant_term(tmp1465[i]) - (temp_accX_i[i]).coeffs[2:order + 1] .= zero((temp_accX_i[i]).coeffs[1]) - accX.coeffs[1] = identity(constant_term(temp_accX_i[i])) - accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) - (tmp1467[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_y[i]) - (tmp1467[i]).coeffs[2:order + 1] .= zero((tmp1467[i]).coeffs[1]) - (temp_accY_i[i]).coeffs[1] = constant_term(accY) - constant_term(tmp1467[i]) - (temp_accY_i[i]).coeffs[2:order + 1] .= zero((temp_accY_i[i]).coeffs[1]) - accY.coeffs[1] = identity(constant_term(temp_accY_i[i])) - accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) - (tmp1469[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_z[i]) - (tmp1469[i]).coeffs[2:order + 1] .= zero((tmp1469[i]).coeffs[1]) - (temp_accZ_i[i]).coeffs[1] = constant_term(accZ) - constant_term(tmp1469[i]) - (temp_accZ_i[i]).coeffs[2:order + 1] .= zero((temp_accZ_i[i]).coeffs[1]) - accZ.coeffs[1] = identity(constant_term(temp_accZ_i[i])) - accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) - end - end - (_4ϕj[N]).coeffs[1] = constant_term(4) * constant_term(newtonianNb_Potential[N]) - (_4ϕj[N]).coeffs[2:order + 1] .= zero((_4ϕj[N]).coeffs[1]) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 - (ϕi_plus_4ϕj[i]).coeffs[1] = constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]) - (ϕi_plus_4ϕj[i]).coeffs[2:order + 1] .= zero((ϕi_plus_4ϕj[i]).coeffs[1]) - (tmp1475[i]).coeffs[1] = constant_term(2) * constant_term(v2[i]) - (tmp1475[i]).coeffs[2:order + 1] .= zero((tmp1475[i]).coeffs[1]) - (tmp1477[i]).coeffs[1] = constant_term(4) * constant_term(vi_dot_vj[i]) - (tmp1477[i]).coeffs[2:order + 1] .= zero((tmp1477[i]).coeffs[1]) - (tmp1478[i]).coeffs[1] = constant_term(tmp1475[i]) - constant_term(tmp1477[i]) - (tmp1478[i]).coeffs[2:order + 1] .= zero((tmp1478[i]).coeffs[1]) - (sj2_plus_2si2_minus_4vivj[i]).coeffs[1] = constant_term(tmp1478[i]) + constant_term(v2[N]) - (sj2_plus_2si2_minus_4vivj[i]).coeffs[2:order + 1] .= zero((sj2_plus_2si2_minus_4vivj[i]).coeffs[1]) - (ϕs_and_vs[i]).coeffs[1] = constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]) - (ϕs_and_vs[i]).coeffs[2:order + 1] .= zero((ϕs_and_vs[i]).coeffs[1]) - (Xij_t_Ui[i]).coeffs[1] = constant_term(X[i]) * constant_term(ui[i]) - (Xij_t_Ui[i]).coeffs[2:order + 1] .= zero((Xij_t_Ui[i]).coeffs[1]) - (Yij_t_Vi[i]).coeffs[1] = constant_term(Y[i]) * constant_term(vi[i]) - (Yij_t_Vi[i]).coeffs[2:order + 1] .= zero((Yij_t_Vi[i]).coeffs[1]) - (Zij_t_Wi[i]).coeffs[1] = constant_term(Z[i]) * constant_term(wi[i]) - (Zij_t_Wi[i]).coeffs[2:order + 1] .= zero((Zij_t_Wi[i]).coeffs[1]) - (tmp1484[i]).coeffs[1] = constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]) - (tmp1484[i]).coeffs[2:order + 1] .= zero((tmp1484[i]).coeffs[1]) - (Rij_dot_Vi[i]).coeffs[1] = constant_term(tmp1484[i]) + constant_term(Zij_t_Wi[i]) - (Rij_dot_Vi[i]).coeffs[2:order + 1] .= zero((Rij_dot_Vi[i]).coeffs[1]) - (tmp1487[i]).coeffs[1] = constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)) - (tmp1487[i]).coeffs[2:order + 1] .= zero((tmp1487[i]).coeffs[1]) - (pn1t7[i]).coeffs[1] = constant_term(tmp1487[i]) / constant_term(r_p2[i]) - (pn1t7[i]).coeffs[2:order + 1] .= zero((pn1t7[i]).coeffs[1]) - (tmp1490[i]).coeffs[1] = constant_term(1.5) * constant_term(pn1t7[i]) - (tmp1490[i]).coeffs[2:order + 1] .= zero((tmp1490[i]).coeffs[1]) - (pn1t2_7[i]).coeffs[1] = constant_term(ϕs_and_vs[i]) - constant_term(tmp1490[i]) - (pn1t2_7[i]).coeffs[2:order + 1] .= zero((pn1t2_7[i]).coeffs[1]) - (pn1t1_7[i]).coeffs[1] = constant_term(c_p2) + constant_term(pn1t2_7[i]) - (pn1t1_7[i]).coeffs[2:order + 1] .= zero((pn1t1_7[i]).coeffs[1]) - (pNX_t_X[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(X[i]) - (pNX_t_X[i]).coeffs[2:order + 1] .= zero((pNX_t_X[i]).coeffs[1]) - (pNY_t_Y[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(Y[i]) - (pNY_t_Y[i]).coeffs[2:order + 1] .= zero((pNY_t_Y[i]).coeffs[1]) - (pNZ_t_Z[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(Z[i]) - (pNZ_t_Z[i]).coeffs[2:order + 1] .= zero((pNZ_t_Z[i]).coeffs[1]) - (tmp1497[i]).coeffs[1] = constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]) - (tmp1497[i]).coeffs[2:order + 1] .= zero((tmp1497[i]).coeffs[1]) - (tmp1498[i]).coeffs[1] = constant_term(tmp1497[i]) + constant_term(pNZ_t_Z[i]) - (tmp1498[i]).coeffs[2:order + 1] .= zero((tmp1498[i]).coeffs[1]) - (tmp1499[i]).coeffs[1] = constant_term(0.5) * constant_term(tmp1498[i]) - (tmp1499[i]).coeffs[2:order + 1] .= zero((tmp1499[i]).coeffs[1]) - (pn1[i]).coeffs[1] = constant_term(pn1t1_7[i]) + constant_term(tmp1499[i]) - (pn1[i]).coeffs[2:order + 1] .= zero((pn1[i]).coeffs[1]) - (X_t_pn1[i]).coeffs[1] = constant_term(newton_acc_X[i]) * constant_term(pn1[i]) - (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) - (Y_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Y[i]) * constant_term(pn1[i]) - (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) - (Z_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Z[i]) * constant_term(pn1[i]) - (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) - (pNX_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(pn3[i]) - (pNX_t_pn3[i]).coeffs[2:order + 1] .= zero((pNX_t_pn3[i]).coeffs[1]) - (pNY_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]) - (pNY_t_pn3[i]).coeffs[2:order + 1] .= zero((pNY_t_pn3[i]).coeffs[1]) - (pNZ_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(pn3[i]) - (pNZ_t_pn3[i]).coeffs[2:order + 1] .= zero((pNZ_t_pn3[i]).coeffs[1]) - end - for i = 1:10 - (tmp1507[i]).coeffs[1] = constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]) - (tmp1507[i]).coeffs[2:order + 1] .= zero((tmp1507[i]).coeffs[1]) - (termpnx[i]).coeffs[1] = constant_term(X_t_pn1[i]) + constant_term(tmp1507[i]) - (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) - (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) - (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) - pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) - pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) - (tmp1510[i]).coeffs[1] = constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]) - (tmp1510[i]).coeffs[2:order + 1] .= zero((tmp1510[i]).coeffs[1]) - (termpny[i]).coeffs[1] = constant_term(Y_t_pn1[i]) + constant_term(tmp1510[i]) - (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) - (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) - (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) - pntempY.coeffs[1] = identity(constant_term(sumpny[i])) - pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) - (tmp1513[i]).coeffs[1] = constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]) - (tmp1513[i]).coeffs[2:order + 1] .= zero((tmp1513[i]).coeffs[1]) - (termpnz[i]).coeffs[1] = constant_term(Z_t_pn1[i]) + constant_term(tmp1513[i]) - (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) - (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) - (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) - pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) - pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) - end - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 - (X_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_X[i]) - (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) - (Y_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Y[i]) - (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) - (Z_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Z[i]) - (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) - end - for i = 11:Nm1 - (termpnx[i]).coeffs[1] = identity(constant_term(X_t_pn1[i])) - (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) - (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) - (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) - pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) - pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) - (termpny[i]).coeffs[1] = identity(constant_term(Y_t_pn1[i])) - (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) - (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) - (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) - pntempY.coeffs[1] = identity(constant_term(sumpny[i])) - pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) - (termpnz[i]).coeffs[1] = identity(constant_term(Z_t_pn1[i])) - (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) - (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) - (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) - pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) - pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) - end - postNewtonX.coeffs[1] = constant_term(pntempX) * constant_term(c_m2) - postNewtonX.coeffs[2:order + 1] .= zero(postNewtonX.coeffs[1]) - postNewtonY.coeffs[1] = constant_term(pntempY) * constant_term(c_m2) - postNewtonY.coeffs[2:order + 1] .= zero(postNewtonY.coeffs[1]) - postNewtonZ.coeffs[1] = constant_term(pntempZ) * constant_term(c_m2) - postNewtonZ.coeffs[2:order + 1] .= zero(postNewtonZ.coeffs[1]) - (dq[4]).coeffs[1] = constant_term(postNewtonX) + constant_term(accX) - (dq[4]).coeffs[2:order + 1] .= zero((dq[4]).coeffs[1]) - (dq[5]).coeffs[1] = constant_term(postNewtonY) + constant_term(accY) - (dq[5]).coeffs[2:order + 1] .= zero((dq[5]).coeffs[1]) - (dq[6]).coeffs[1] = constant_term(postNewtonZ) + constant_term(accZ) - (dq[6]).coeffs[2:order + 1] .= zero((dq[6]).coeffs[1]) - for __idx = eachindex(q) - (q[__idx]).coeffs[2] = (dq[__idx]).coeffs[1] - end - for ord = 1:order - 1 - ordnext = ord + 1 - TaylorSeries.identity!(pntempX, zero_q_1, ord) - TaylorSeries.identity!(pntempY, zero_q_1, ord) - TaylorSeries.identity!(pntempZ, zero_q_1, ord) - TaylorSeries.identity!(accX, zero_q_1, ord) - TaylorSeries.identity!(accY, zero_q_1, ord) - TaylorSeries.identity!(accZ, zero_q_1, ord) - TaylorSeries.identity!(dq[1], q[4], ord) - TaylorSeries.identity!(dq[2], q[5], ord) - TaylorSeries.identity!(dq[3], q[6], ord) - TaylorSeries.identity!(newtonianNb_Potential[N], zero_q_1, ord) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 - TaylorSeries.identity!(ui[i], ss16asteph_t[3 * ((N - 1) + i) - 2], ord) - TaylorSeries.identity!(vi[i], ss16asteph_t[3 * ((N - 1) + i) - 1], ord) - TaylorSeries.identity!(wi[i], ss16asteph_t[3 * ((N - 1) + i)], ord) - TaylorSeries.subst!(X[i], ss16asteph_t[3i - 2], q[1], ord) - TaylorSeries.subst!(Y[i], ss16asteph_t[3i - 1], q[2], ord) - TaylorSeries.subst!(Z[i], ss16asteph_t[3i], q[3], ord) - TaylorSeries.subst!(U[i], ui[i], dq[1], ord) - TaylorSeries.subst!(V[i], vi[i], dq[2], ord) - TaylorSeries.subst!(W[i], wi[i], dq[3], ord) - TaylorSeries.mul!(tmp1317[1], 4, dq[1], ord) - TaylorSeries.mul!(tmp1319[i], 3, ui[i], ord) - TaylorSeries.subst!(_4U_m_3X[i], tmp1317[1], tmp1319[i], ord) - TaylorSeries.mul!(tmp1322[2], 4, dq[2], ord) - TaylorSeries.mul!(tmp1324[i], 3, vi[i], ord) - TaylorSeries.subst!(_4V_m_3Y[i], tmp1322[2], tmp1324[i], ord) - TaylorSeries.mul!(tmp1327[3], 4, dq[3], ord) - TaylorSeries.mul!(tmp1329[i], 3, wi[i], ord) - TaylorSeries.subst!(_4W_m_3Z[i], tmp1327[3], tmp1329[i], ord) - TaylorSeries.mul!(pn2x[i], X[i], _4U_m_3X[i], ord) - TaylorSeries.mul!(pn2y[i], Y[i], _4V_m_3Y[i], ord) - TaylorSeries.mul!(pn2z[i], Z[i], _4W_m_3Z[i], ord) - TaylorSeries.mul!(UU[i], ui[i], dq[1], ord) - TaylorSeries.mul!(VV[i], vi[i], dq[2], ord) - TaylorSeries.mul!(WW[i], wi[i], dq[3], ord) - TaylorSeries.add!(tmp1337[i], UU[i], VV[i], ord) - TaylorSeries.add!(vi_dot_vj[i], tmp1337[i], WW[i], ord) - TaylorSeries.pow!(tmp1340[i], X[i], 2, ord) - TaylorSeries.pow!(tmp1342[i], Y[i], 2, ord) - TaylorSeries.add!(tmp1343[i], tmp1340[i], tmp1342[i], ord) - TaylorSeries.pow!(tmp1345[i], Z[i], 2, ord) - TaylorSeries.add!(r_p2[i], tmp1343[i], tmp1345[i], ord) - TaylorSeries.sqrt!(r_p1d2[i], r_p2[i], ord) - TaylorSeries.pow!(r_p3d2[i], r_p2[i], 1.5, ord) - TaylorSeries.pow!(r_p7d2[i], r_p2[i], 3.5, ord) - TaylorSeries.div!(newtonianCoeff[i], μ[i], r_p3d2[i], ord) - TaylorSeries.add!(tmp1353[i], pn2x[i], pn2y[i], ord) - TaylorSeries.add!(tmp1354[i], tmp1353[i], pn2z[i], ord) - TaylorSeries.mul!(pn2[i], newtonianCoeff[i], tmp1354[i], ord) - TaylorSeries.mul!(newton_acc_X[i], X[i], newtonianCoeff[i], ord) - TaylorSeries.mul!(newton_acc_Y[i], Y[i], newtonianCoeff[i], ord) - TaylorSeries.mul!(newton_acc_Z[i], Z[i], newtonianCoeff[i], ord) - TaylorSeries.div!(newtonian1b_Potential[i], μ[i], r_p1d2[i], ord) - TaylorSeries.mul!(pn3[i], 3.5, newtonian1b_Potential[i], ord) - TaylorSeries.mul!(U_t_pn2[i], pn2[i], U[i], ord) - TaylorSeries.mul!(V_t_pn2[i], pn2[i], V[i], ord) - TaylorSeries.mul!(W_t_pn2[i], pn2[i], W[i], ord) - if UJ_interaction[i] - TaylorSeries.subst!(tmp1365[i], X[i], ord) - TaylorSeries.mul!(t31[i], tmp1365[i], M_[1, 3, i], ord) - TaylorSeries.subst!(tmp1367[i], Y[i], ord) - TaylorSeries.mul!(t32[i], tmp1367[i], M_[2, 3, i], ord) - TaylorSeries.subst!(tmp1369[i], Z[i], ord) - TaylorSeries.mul!(t33[i], tmp1369[i], M_[3, 3, i], ord) - TaylorSeries.add!(tmp1371[i], t31[i], t32[i], ord) - TaylorSeries.add!(r_sin_ϕ[i], tmp1371[i], t33[i], ord) - TaylorSeries.div!(sin_ϕ[i], r_sin_ϕ[i], r_p1d2[i], ord) - TaylorSeries.asin!(ϕ[i], sin_ϕ[i], tmp1528[i], ord) - TaylorSeries.sincos!(tmp1529[i], cos_ϕ[i], ϕ[i], ord) - TaylorSeries.pow!(sin2_ϕ[i], sin_ϕ[i], 2, ord) - TaylorSeries.pow!(sin3_ϕ[i], sin_ϕ[i], 3, ord) - TaylorSeries.mul!(tmp1381[i], 1.5, sin2_ϕ[i], ord) - TaylorSeries.subst!(P_2_sin_ϕ[i], tmp1381[i], 0.5, ord) - TaylorSeries.mul!(∂P_2_sin_ϕ[i], 3, sin_ϕ[i], ord) - TaylorSeries.mul!(tmp1387[i], -1.5, sin_ϕ[i], ord) - TaylorSeries.mul!(tmp1389[i], 2.5, sin3_ϕ[i], ord) - TaylorSeries.add!(P_3_sin_ϕ[i], tmp1387[i], tmp1389[i], ord) - TaylorSeries.mul!(tmp1393[i], 7.5, sin2_ϕ[i], ord) - TaylorSeries.add!(∂P_3_sin_ϕ[i], -1.5, tmp1393[i], ord) - TaylorSeries.pow!(tmp1396[i], r_p2[i], 2, ord) - TaylorSeries.div!(tmp1397[i], Λ2[i], tmp1396[i], ord) - TaylorSeries.subst!(Λ2j_div_r4[i], tmp1397[i], ord) - TaylorSeries.pow!(tmp1400[i], r_p1d2[i], 5, ord) - TaylorSeries.div!(tmp1401[i], Λ3[i], tmp1400[i], ord) - TaylorSeries.subst!(Λ3j_div_r5[i], tmp1401[i], ord) - TaylorSeries.subst!(tmp1403[i], cos_ϕ[i], ord) - TaylorSeries.mul!(m_c_ϕ_∂P_2[i], tmp1403[i], ∂P_2_sin_ϕ[i], ord) - TaylorSeries.subst!(tmp1405[i], cos_ϕ[i], ord) - TaylorSeries.mul!(m_c_ϕ_∂P_3[i], tmp1405[i], ∂P_3_sin_ϕ[i], ord) - TaylorSeries.mul!(tmp1408[i], Λ2j_div_r4[i], 3, ord) - TaylorSeries.mul!(F_J2_ξ[i], tmp1408[i], P_2_sin_ϕ[i], ord) - TaylorSeries.mul!(F_J2_ζ[i], Λ2j_div_r4[i], m_c_ϕ_∂P_2[i], ord) - TaylorSeries.mul!(tmp1412[i], Λ3j_div_r5[i], 4, ord) - TaylorSeries.mul!(F_J3_ξ[i], tmp1412[i], P_3_sin_ϕ[i], ord) - TaylorSeries.mul!(F_J3_ζ[i], Λ3j_div_r5[i], m_c_ϕ_∂P_3[i], ord) - TaylorSeries.identity!(F_J_ξ[i], F_J2_ξ[i], ord) - TaylorSeries.identity!(F_J_ζ[i], F_J2_ζ[i], ord) - TaylorSeries.subst!(tmp1415[i], X[i], ord) - TaylorSeries.div!(ξx[i], tmp1415[i], r_p1d2[i], ord) - TaylorSeries.subst!(tmp1417[i], Y[i], ord) - TaylorSeries.div!(ξy[i], tmp1417[i], r_p1d2[i], ord) - TaylorSeries.subst!(tmp1419[i], Z[i], ord) - TaylorSeries.div!(ξz[i], tmp1419[i], r_p1d2[i], ord) - TaylorSeries.mul!(ηx1[i], M_[2, 3, i], ξz[i], ord) - TaylorSeries.mul!(ηy1[i], M_[3, 3, i], ξx[i], ord) - TaylorSeries.mul!(ηz1[i], M_[1, 3, i], ξy[i], ord) - TaylorSeries.mul!(ηx2[i], M_[3, 3, i], ξy[i], ord) - TaylorSeries.mul!(ηy2[i], M_[1, 3, i], ξz[i], ord) - TaylorSeries.mul!(ηz2[i], M_[2, 3, i], ξx[i], ord) - TaylorSeries.subst!(ηx[i], ηx1[i], ηx2[i], ord) - TaylorSeries.subst!(ηy[i], ηy1[i], ηy2[i], ord) - TaylorSeries.subst!(ηz[i], ηz1[i], ηz2[i], ord) - TaylorSeries.mul!(ζx1[i], ξy[i], ηz[i], ord) - TaylorSeries.mul!(ζy1[i], ξz[i], ηx[i], ord) - TaylorSeries.mul!(ζz1[i], ξx[i], ηy[i], ord) - TaylorSeries.mul!(ζx2[i], ξz[i], ηy[i], ord) - TaylorSeries.mul!(ζy2[i], ξx[i], ηz[i], ord) - TaylorSeries.mul!(ζz2[i], ξy[i], ηx[i], ord) - TaylorSeries.subst!(ζx[i], ζx1[i], ζx2[i], ord) - TaylorSeries.subst!(ζy[i], ζy1[i], ζy2[i], ord) - TaylorSeries.subst!(ζz[i], ζz1[i], ζz2[i], ord) - TaylorSeries.mul!(F_J2_x1[i], F_J_ξ[i], ξx[i], ord) - TaylorSeries.mul!(F_J2_y1[i], F_J_ξ[i], ξy[i], ord) - TaylorSeries.mul!(F_J2_z1[i], F_J_ξ[i], ξz[i], ord) - TaylorSeries.mul!(F_J2_x2[i], F_J_ζ[i], ζx[i], ord) - TaylorSeries.mul!(F_J2_y2[i], F_J_ζ[i], ζy[i], ord) - TaylorSeries.mul!(F_J2_z2[i], F_J_ζ[i], ζz[i], ord) - TaylorSeries.add!(F_J2_x[i], F_J2_x1[i], F_J2_x2[i], ord) - TaylorSeries.add!(F_J2_y[i], F_J2_y1[i], F_J2_y2[i], ord) - TaylorSeries.add!(F_J2_z[i], F_J2_z1[i], F_J2_z2[i], ord) - end - TaylorSeries.pow!(tmp1449[i], ui[i], 2, ord) - TaylorSeries.pow!(tmp1451[i], vi[i], 2, ord) - TaylorSeries.add!(tmp1452[i], tmp1449[i], tmp1451[i], ord) - TaylorSeries.pow!(tmp1454[i], wi[i], 2, ord) - TaylorSeries.add!(v2[i], tmp1452[i], tmp1454[i], ord) - end - TaylorSeries.pow!(tmp1457, q[4], 2, ord) - TaylorSeries.pow!(tmp1459, q[5], 2, ord) - TaylorSeries.add!(tmp1460, tmp1457, tmp1459, ord) - TaylorSeries.pow!(tmp1462, q[6], 2, ord) - TaylorSeries.add!(v2[N], tmp1460, tmp1462, ord) - for i = 1:Nm1 - TaylorSeries.add!(temp_004[i], newtonian1b_Potential[i], newtonianNb_Potential[N], ord) - TaylorSeries.identity!(newtonianNb_Potential[N], temp_004[i], ord) - if UJ_interaction[i] - TaylorSeries.mul!(tmp1465[i], μ[i], F_J2_x[i], ord) - TaylorSeries.subst!(temp_accX_i[i], accX, tmp1465[i], ord) - TaylorSeries.identity!(accX, temp_accX_i[i], ord) - TaylorSeries.mul!(tmp1467[i], μ[i], F_J2_y[i], ord) - TaylorSeries.subst!(temp_accY_i[i], accY, tmp1467[i], ord) - TaylorSeries.identity!(accY, temp_accY_i[i], ord) - TaylorSeries.mul!(tmp1469[i], μ[i], F_J2_z[i], ord) - TaylorSeries.subst!(temp_accZ_i[i], accZ, tmp1469[i], ord) - TaylorSeries.identity!(accZ, temp_accZ_i[i], ord) - end - end - TaylorSeries.mul!(_4ϕj[N], 4, newtonianNb_Potential[N], ord) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 - TaylorSeries.add!(ϕi_plus_4ϕj[i], newtonianNb_Potential_t[i], _4ϕj[N], ord) - TaylorSeries.mul!(tmp1475[i], 2, v2[i], ord) - TaylorSeries.mul!(tmp1477[i], 4, vi_dot_vj[i], ord) - TaylorSeries.subst!(tmp1478[i], tmp1475[i], tmp1477[i], ord) - TaylorSeries.add!(sj2_plus_2si2_minus_4vivj[i], tmp1478[i], v2[N], ord) - TaylorSeries.subst!(ϕs_and_vs[i], sj2_plus_2si2_minus_4vivj[i], ϕi_plus_4ϕj[i], ord) - TaylorSeries.mul!(Xij_t_Ui[i], X[i], ui[i], ord) - TaylorSeries.mul!(Yij_t_Vi[i], Y[i], vi[i], ord) - TaylorSeries.mul!(Zij_t_Wi[i], Z[i], wi[i], ord) - TaylorSeries.add!(tmp1484[i], Xij_t_Ui[i], Yij_t_Vi[i], ord) - TaylorSeries.add!(Rij_dot_Vi[i], tmp1484[i], Zij_t_Wi[i], ord) - TaylorSeries.pow!(tmp1487[i], Rij_dot_Vi[i], 2, ord) - TaylorSeries.div!(pn1t7[i], tmp1487[i], r_p2[i], ord) - TaylorSeries.mul!(tmp1490[i], 1.5, pn1t7[i], ord) - TaylorSeries.subst!(pn1t2_7[i], ϕs_and_vs[i], tmp1490[i], ord) - TaylorSeries.add!(pn1t1_7[i], c_p2, pn1t2_7[i], ord) - TaylorSeries.mul!(pNX_t_X[i], acceph_t[3i - 2], X[i], ord) - TaylorSeries.mul!(pNY_t_Y[i], acceph_t[3i - 1], Y[i], ord) - TaylorSeries.mul!(pNZ_t_Z[i], acceph_t[3i], Z[i], ord) - TaylorSeries.add!(tmp1497[i], pNX_t_X[i], pNY_t_Y[i], ord) - TaylorSeries.add!(tmp1498[i], tmp1497[i], pNZ_t_Z[i], ord) - TaylorSeries.mul!(tmp1499[i], 0.5, tmp1498[i], ord) - TaylorSeries.add!(pn1[i], pn1t1_7[i], tmp1499[i], ord) - TaylorSeries.mul!(X_t_pn1[i], newton_acc_X[i], pn1[i], ord) - TaylorSeries.mul!(Y_t_pn1[i], newton_acc_Y[i], pn1[i], ord) - TaylorSeries.mul!(Z_t_pn1[i], newton_acc_Z[i], pn1[i], ord) - TaylorSeries.mul!(pNX_t_pn3[i], acceph_t[3i - 2], pn3[i], ord) - TaylorSeries.mul!(pNY_t_pn3[i], acceph_t[3i - 1], pn3[i], ord) - TaylorSeries.mul!(pNZ_t_pn3[i], acceph_t[3i], pn3[i], ord) - end - for i = 1:10 - TaylorSeries.add!(tmp1507[i], U_t_pn2[i], pNX_t_pn3[i], ord) - TaylorSeries.add!(termpnx[i], X_t_pn1[i], tmp1507[i], ord) - TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) - TaylorSeries.identity!(pntempX, sumpnx[i], ord) - TaylorSeries.add!(tmp1510[i], V_t_pn2[i], pNY_t_pn3[i], ord) - TaylorSeries.add!(termpny[i], Y_t_pn1[i], tmp1510[i], ord) - TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) - TaylorSeries.identity!(pntempY, sumpny[i], ord) - TaylorSeries.add!(tmp1513[i], W_t_pn2[i], pNZ_t_pn3[i], ord) - TaylorSeries.add!(termpnz[i], Z_t_pn1[i], tmp1513[i], ord) - TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) - TaylorSeries.identity!(pntempZ, sumpnz[i], ord) - end - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 - TaylorSeries.mul!(X_t_pn1[i], c_p2, newton_acc_X[i], ord) - TaylorSeries.mul!(Y_t_pn1[i], c_p2, newton_acc_Y[i], ord) - TaylorSeries.mul!(Z_t_pn1[i], c_p2, newton_acc_Z[i], ord) - end - for i = 11:Nm1 - TaylorSeries.identity!(termpnx[i], X_t_pn1[i], ord) - TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) - TaylorSeries.identity!(pntempX, sumpnx[i], ord) - TaylorSeries.identity!(termpny[i], Y_t_pn1[i], ord) - TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) - TaylorSeries.identity!(pntempY, sumpny[i], ord) - TaylorSeries.identity!(termpnz[i], Z_t_pn1[i], ord) - TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) - TaylorSeries.identity!(pntempZ, sumpnz[i], ord) - end - TaylorSeries.mul!(postNewtonX, pntempX, c_m2, ord) - TaylorSeries.mul!(postNewtonY, pntempY, c_m2, ord) - TaylorSeries.mul!(postNewtonZ, pntempZ, c_m2, ord) - TaylorSeries.add!(dq[4], postNewtonX, accX, ord) - TaylorSeries.add!(dq[5], postNewtonY, accY, ord) - TaylorSeries.add!(dq[6], postNewtonZ, accZ, ord) - for __idx = eachindex(q) - (q[__idx]).coeffs[ordnext + 1] = (dq[__idx]).coeffs[ordnext] / ordnext - end - end - return nothing +# DO NOT MODIFY THIS FILE BY HAND + +# Methods of `TaylorIntegration._allocate_jetcoeffs!` and `TaylorIntegration.jetcoeffs!` generated by @taylorize for the functions +# in src/propagation/asteroid_dynamical_models.jl + +# To update the functions do the following: +# 1.- Update the corresponding function in src/propagation/asteroid_dynamical_models.jl +# 2.- using TaylorIntegration +# 2.- ex = :(paste here the modified function) +# 3.- x, y = TaylorIntegration._make_parsed_coeffs(ex) +# 4.- Paste x and y in this file + +# TaylorIntegration._allocate_jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_ng_eph_threads! +function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params) where {_T <: Real, _S <: Number, _N} + order = t.order + local jd0 = params[4] + local dsj2k = t + (jd0 - JD_J2000) + local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) + local acceph_t = evaleph(params[2], dsj2k, q[1]) + local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) + local S = eltype(q) + local UJ_interaction = params[5] + local N = params[6] + local Nm1 = N - 1 + local μ = params[7] + local zero_q_1 = auxzero(q[1]) + X = Array{S}(undef, N) + Y = Array{S}(undef, N) + Z = Array{S}(undef, N) + r_p2 = Array{S}(undef, N) + r_p1d2 = Array{S}(undef, N) + r_p3d2 = Array{S}(undef, N) + r_p7d2 = Array{S}(undef, N) + newtonianCoeff = Array{S}(undef, N) + ui = Array{S}(undef, N - 1) + vi = Array{S}(undef, N - 1) + wi = Array{S}(undef, N - 1) + U = Array{S}(undef, N) + V = Array{S}(undef, N) + W = Array{S}(undef, N) + _4U_m_3X = Array{S}(undef, N) + _4V_m_3Y = Array{S}(undef, N) + _4W_m_3Z = Array{S}(undef, N) + UU = Array{S}(undef, N) + VV = Array{S}(undef, N) + WW = Array{S}(undef, N) + newtonian1b_Potential = Array{S}(undef, N) + newtonianNb_Potential = Array{S}(undef, N) + newton_acc_X = Array{S}(undef, N) + newton_acc_Y = Array{S}(undef, N) + newton_acc_Z = Array{S}(undef, N) + v2 = Array{S}(undef, N) + vi_dot_vj = Array{S}(undef, N) + pn2 = Array{S}(undef, N) + U_t_pn2 = Array{S}(undef, N) + V_t_pn2 = Array{S}(undef, N) + W_t_pn2 = Array{S}(undef, N) + pn3 = Array{S}(undef, N) + pNX_t_pn3 = Array{S}(undef, N) + pNY_t_pn3 = Array{S}(undef, N) + pNZ_t_pn3 = Array{S}(undef, N) + _4ϕj = Array{S}(undef, N) + ϕi_plus_4ϕj = Array{S}(undef, N) + sj2_plus_2si2_minus_4vivj = Array{S}(undef, N) + ϕs_and_vs = Array{S}(undef, N) + pn1t1_7 = Array{S}(undef, N) + pNX_t_X = Array{S}(undef, N) + pNY_t_Y = Array{S}(undef, N) + pNZ_t_Z = Array{S}(undef, N) + pn1 = Array{S}(undef, N) + X_t_pn1 = Array{S}(undef, N) + Y_t_pn1 = Array{S}(undef, N) + Z_t_pn1 = Array{S}(undef, N) + pntempX = Taylor1(identity(constant_term(zero_q_1)), order) + pntempY = Taylor1(identity(constant_term(zero_q_1)), order) + pntempZ = Taylor1(identity(constant_term(zero_q_1)), order) + t31 = Array{S}(undef, N) + t32 = Array{S}(undef, N) + t33 = Array{S}(undef, N) + r_sin_ϕ = Array{S}(undef, N) + sin_ϕ = Array{S}(undef, N) + ϕ = Array{S}(undef, N) + cos_ϕ = Array{S}(undef, N) + sin2_ϕ = Array{S}(undef, N) + sin3_ϕ = Array{S}(undef, N) + sin4_ϕ = Array{S}(undef, N) + F_J2_x = Array{S}(undef, N) + F_J2_y = Array{S}(undef, N) + F_J2_z = Array{S}(undef, N) + F_J2_x1 = Array{S}(undef, N) + F_J2_y1 = Array{S}(undef, N) + F_J2_z1 = Array{S}(undef, N) + F_J2_x2 = Array{S}(undef, N) + F_J2_y2 = Array{S}(undef, N) + F_J2_z2 = Array{S}(undef, N) + temp_accX_i = Array{S}(undef, N) + temp_accY_i = Array{S}(undef, N) + temp_accZ_i = Array{S}(undef, N) + P_2_sin_ϕ = Array{S}(undef, N) + ∂P_2_sin_ϕ = Array{S}(undef, N) + P_3_sin_ϕ = Array{S}(undef, N) + ∂P_3_sin_ϕ = Array{S}(undef, N) + m_c_ϕ_∂P_2 = Array{S}(undef, N) + m_c_ϕ_∂P_3 = Array{S}(undef, N) + Λ2j_div_r4 = Array{S}(undef, N) + Λ3j_div_r5 = Array{S}(undef, N) + F_J_ξ = Array{S}(undef, N) + F_J_η = Array{S}(undef, N) + F_J_ζ = Array{S}(undef, N) + F_J2_ξ = Array{S}(undef, N) + F_J2_η = Array{S}(undef, N) + F_J2_ζ = Array{S}(undef, N) + F_J3_ξ = Array{S}(undef, N) + F_J3_η = Array{S}(undef, N) + F_J3_ζ = Array{S}(undef, N) + ξx = Array{S}(undef, N) + ξy = Array{S}(undef, N) + ξz = Array{S}(undef, N) + ηx = Array{S}(undef, N) + ηy = Array{S}(undef, N) + ηz = Array{S}(undef, N) + ηx1 = Array{S}(undef, N) + ηy1 = Array{S}(undef, N) + ηz1 = Array{S}(undef, N) + ηx2 = Array{S}(undef, N) + ηy2 = Array{S}(undef, N) + ηz2 = Array{S}(undef, N) + ζx = Array{S}(undef, N) + ζy = Array{S}(undef, N) + ζz = Array{S}(undef, N) + ζx1 = Array{S}(undef, N) + ζy1 = Array{S}(undef, N) + ζz1 = Array{S}(undef, N) + ζx2 = Array{S}(undef, N) + ζy2 = Array{S}(undef, N) + ζz2 = Array{S}(undef, N) + accX = Taylor1(identity(constant_term(zero_q_1)), order) + accY = Taylor1(identity(constant_term(zero_q_1)), order) + accZ = Taylor1(identity(constant_term(zero_q_1)), order) + local M_ = Array{S}(undef, 3, 3, N) + local M_ .= zero_q_1 + local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 + dq[1] = Taylor1(identity(constant_term(q[4])), order) + dq[2] = Taylor1(identity(constant_term(q[5])), order) + dq[3] = Taylor1(identity(constant_term(q[6])), order) + newtonianNb_Potential[N] = Taylor1(identity(constant_term(zero_q_1)), order) + tmp687 = Array{Taylor1{_S}}(undef, size(dq)) + tmp687 .= Taylor1(zero(constant_term(q[1])), order) + tmp689 = Array{Taylor1{_S}}(undef, size(ui)) + tmp689 .= Taylor1(zero(constant_term(q[1])), order) + tmp692 = Array{Taylor1{_S}}(undef, size(dq)) + tmp692 .= Taylor1(zero(constant_term(q[1])), order) + tmp694 = Array{Taylor1{_S}}(undef, size(vi)) + tmp694 .= Taylor1(zero(constant_term(q[1])), order) + tmp697 = Array{Taylor1{_S}}(undef, size(dq)) + tmp697 .= Taylor1(zero(constant_term(q[1])), order) + tmp699 = Array{Taylor1{_S}}(undef, size(wi)) + tmp699 .= Taylor1(zero(constant_term(q[1])), order) + pn2x = Array{Taylor1{_S}}(undef, size(X)) + pn2x .= Taylor1(zero(constant_term(q[1])), order) + pn2y = Array{Taylor1{_S}}(undef, size(Y)) + pn2y .= Taylor1(zero(constant_term(q[1])), order) + pn2z = Array{Taylor1{_S}}(undef, size(Z)) + pn2z .= Taylor1(zero(constant_term(q[1])), order) + tmp707 = Array{Taylor1{_S}}(undef, size(UU)) + tmp707 .= Taylor1(zero(constant_term(q[1])), order) + tmp710 = Array{Taylor1{_S}}(undef, size(X)) + tmp710 .= Taylor1(zero(constant_term(q[1])), order) + tmp712 = Array{Taylor1{_S}}(undef, size(Y)) + tmp712 .= Taylor1(zero(constant_term(q[1])), order) + tmp713 = Array{Taylor1{_S}}(undef, size(tmp710)) + tmp713 .= Taylor1(zero(constant_term(q[1])), order) + tmp715 = Array{Taylor1{_S}}(undef, size(Z)) + tmp715 .= Taylor1(zero(constant_term(q[1])), order) + tmp723 = Array{Taylor1{_S}}(undef, size(pn2x)) + tmp723 .= Taylor1(zero(constant_term(q[1])), order) + tmp724 = Array{Taylor1{_S}}(undef, size(tmp723)) + tmp724 .= Taylor1(zero(constant_term(q[1])), order) + tmp819 = Array{Taylor1{_S}}(undef, size(ui)) + tmp819 .= Taylor1(zero(constant_term(q[1])), order) + tmp821 = Array{Taylor1{_S}}(undef, size(vi)) + tmp821 .= Taylor1(zero(constant_term(q[1])), order) + tmp822 = Array{Taylor1{_S}}(undef, size(tmp819)) + tmp822 .= Taylor1(zero(constant_term(q[1])), order) + tmp824 = Array{Taylor1{_S}}(undef, size(wi)) + tmp824 .= Taylor1(zero(constant_term(q[1])), order) + tmp735 = Array{Taylor1{_S}}(undef, size(X)) + tmp735 .= Taylor1(zero(constant_term(q[1])), order) + tmp737 = Array{Taylor1{_S}}(undef, size(Y)) + tmp737 .= Taylor1(zero(constant_term(q[1])), order) + tmp739 = Array{Taylor1{_S}}(undef, size(Z)) + tmp739 .= Taylor1(zero(constant_term(q[1])), order) + tmp741 = Array{Taylor1{_S}}(undef, size(t31)) + tmp741 .= Taylor1(zero(constant_term(q[1])), order) + tmp948 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) + tmp948 .= Taylor1(zero(constant_term(q[1])), order) + tmp949 = Array{Taylor1{_S}}(undef, size(ϕ)) + tmp949 .= Taylor1(zero(constant_term(q[1])), order) + tmp751 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) + tmp751 .= Taylor1(zero(constant_term(q[1])), order) + tmp757 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) + tmp757 .= Taylor1(zero(constant_term(q[1])), order) + tmp759 = Array{Taylor1{_S}}(undef, size(sin3_ϕ)) + tmp759 .= Taylor1(zero(constant_term(q[1])), order) + tmp763 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) + tmp763 .= Taylor1(zero(constant_term(q[1])), order) + tmp766 = Array{Taylor1{_S}}(undef, size(r_p2)) + tmp766 .= Taylor1(zero(constant_term(q[1])), order) + tmp767 = Array{Taylor1{_S}}(undef, size(Λ2)) + tmp767 .= Taylor1(zero(constant_term(q[1])), order) + tmp770 = Array{Taylor1{_S}}(undef, size(r_p1d2)) + tmp770 .= Taylor1(zero(constant_term(q[1])), order) + tmp771 = Array{Taylor1{_S}}(undef, size(Λ3)) + tmp771 .= Taylor1(zero(constant_term(q[1])), order) + tmp773 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) + tmp773 .= Taylor1(zero(constant_term(q[1])), order) + tmp775 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) + tmp775 .= Taylor1(zero(constant_term(q[1])), order) + tmp778 = Array{Taylor1{_S}}(undef, size(Λ2j_div_r4)) + tmp778 .= Taylor1(zero(constant_term(q[1])), order) + tmp782 = Array{Taylor1{_S}}(undef, size(Λ3j_div_r5)) + tmp782 .= Taylor1(zero(constant_term(q[1])), order) + tmp785 = Array{Taylor1{_S}}(undef, size(X)) + tmp785 .= Taylor1(zero(constant_term(q[1])), order) + tmp787 = Array{Taylor1{_S}}(undef, size(Y)) + tmp787 .= Taylor1(zero(constant_term(q[1])), order) + tmp789 = Array{Taylor1{_S}}(undef, size(Z)) + tmp789 .= Taylor1(zero(constant_term(q[1])), order) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 + ui[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])), order) + vi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])), order) + wi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])), order) + X[i] = Taylor1(constant_term(ss16asteph_t[3i - 2]) - constant_term(q[1]), order) + Y[i] = Taylor1(constant_term(ss16asteph_t[3i - 1]) - constant_term(q[2]), order) + Z[i] = Taylor1(constant_term(ss16asteph_t[3i]) - constant_term(q[3]), order) + U[i] = Taylor1(constant_term(ui[i]) - constant_term(dq[1]), order) + V[i] = Taylor1(constant_term(vi[i]) - constant_term(dq[2]), order) + W[i] = Taylor1(constant_term(wi[i]) - constant_term(dq[3]), order) + tmp687[1] = Taylor1(constant_term(4) * constant_term(dq[1]), order) + tmp689[i] = Taylor1(constant_term(3) * constant_term(ui[i]), order) + _4U_m_3X[i] = Taylor1(constant_term(tmp687[1]) - constant_term(tmp689[i]), order) + tmp692[2] = Taylor1(constant_term(4) * constant_term(dq[2]), order) + tmp694[i] = Taylor1(constant_term(3) * constant_term(vi[i]), order) + _4V_m_3Y[i] = Taylor1(constant_term(tmp692[2]) - constant_term(tmp694[i]), order) + tmp697[3] = Taylor1(constant_term(4) * constant_term(dq[3]), order) + tmp699[i] = Taylor1(constant_term(3) * constant_term(wi[i]), order) + _4W_m_3Z[i] = Taylor1(constant_term(tmp697[3]) - constant_term(tmp699[i]), order) + pn2x[i] = Taylor1(constant_term(X[i]) * constant_term(_4U_m_3X[i]), order) + pn2y[i] = Taylor1(constant_term(Y[i]) * constant_term(_4V_m_3Y[i]), order) + pn2z[i] = Taylor1(constant_term(Z[i]) * constant_term(_4W_m_3Z[i]), order) + UU[i] = Taylor1(constant_term(ui[i]) * constant_term(dq[1]), order) + VV[i] = Taylor1(constant_term(vi[i]) * constant_term(dq[2]), order) + WW[i] = Taylor1(constant_term(wi[i]) * constant_term(dq[3]), order) + tmp707[i] = Taylor1(constant_term(UU[i]) + constant_term(VV[i]), order) + vi_dot_vj[i] = Taylor1(constant_term(tmp707[i]) + constant_term(WW[i]), order) + tmp710[i] = Taylor1(constant_term(X[i]) ^ float(constant_term(2)), order) + tmp712[i] = Taylor1(constant_term(Y[i]) ^ float(constant_term(2)), order) + tmp713[i] = Taylor1(constant_term(tmp710[i]) + constant_term(tmp712[i]), order) + tmp715[i] = Taylor1(constant_term(Z[i]) ^ float(constant_term(2)), order) + r_p2[i] = Taylor1(constant_term(tmp713[i]) + constant_term(tmp715[i]), order) + r_p1d2[i] = Taylor1(sqrt(constant_term(r_p2[i])), order) + r_p3d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(1.5)), order) + r_p7d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(3.5)), order) + newtonianCoeff[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p3d2[i]), order) + tmp723[i] = Taylor1(constant_term(pn2x[i]) + constant_term(pn2y[i]), order) + tmp724[i] = Taylor1(constant_term(tmp723[i]) + constant_term(pn2z[i]), order) + pn2[i] = Taylor1(constant_term(newtonianCoeff[i]) * constant_term(tmp724[i]), order) + newton_acc_X[i] = Taylor1(constant_term(X[i]) * constant_term(newtonianCoeff[i]), order) + newton_acc_Y[i] = Taylor1(constant_term(Y[i]) * constant_term(newtonianCoeff[i]), order) + newton_acc_Z[i] = Taylor1(constant_term(Z[i]) * constant_term(newtonianCoeff[i]), order) + newtonian1b_Potential[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p1d2[i]), order) + pn3[i] = Taylor1(constant_term(3.5) * constant_term(newtonian1b_Potential[i]), order) + U_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(U[i]), order) + V_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(V[i]), order) + W_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(W[i]), order) + if UJ_interaction[i] + tmp735[i] = Taylor1(-(constant_term(X[i])), order) + t31[i] = Taylor1(constant_term(tmp735[i]) * constant_term(M_[1, 3, i]), order) + tmp737[i] = Taylor1(-(constant_term(Y[i])), order) + t32[i] = Taylor1(constant_term(tmp737[i]) * constant_term(M_[2, 3, i]), order) + tmp739[i] = Taylor1(-(constant_term(Z[i])), order) + t33[i] = Taylor1(constant_term(tmp739[i]) * constant_term(M_[3, 3, i]), order) + tmp741[i] = Taylor1(constant_term(t31[i]) + constant_term(t32[i]), order) + r_sin_ϕ[i] = Taylor1(constant_term(tmp741[i]) + constant_term(t33[i]), order) + sin_ϕ[i] = Taylor1(constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]), order) + ϕ[i] = Taylor1(asin(constant_term(sin_ϕ[i])), order) + tmp948[i] = Taylor1(sqrt(1 - constant_term(sin_ϕ[i]) ^ 2), order) + cos_ϕ[i] = Taylor1(cos(constant_term(ϕ[i])), order) + tmp949[i] = Taylor1(sin(constant_term(ϕ[i])), order) + sin2_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(2)), order) + sin3_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(3)), order) + tmp751[i] = Taylor1(constant_term(1.5) * constant_term(sin2_ϕ[i]), order) + P_2_sin_ϕ[i] = Taylor1(constant_term(tmp751[i]) - constant_term(0.5), order) + ∂P_2_sin_ϕ[i] = Taylor1(constant_term(3) * constant_term(sin_ϕ[i]), order) + tmp757[i] = Taylor1(constant_term(-1.5) * constant_term(sin_ϕ[i]), order) + tmp759[i] = Taylor1(constant_term(2.5) * constant_term(sin3_ϕ[i]), order) + P_3_sin_ϕ[i] = Taylor1(constant_term(tmp757[i]) + constant_term(tmp759[i]), order) + tmp763[i] = Taylor1(constant_term(7.5) * constant_term(sin2_ϕ[i]), order) + ∂P_3_sin_ϕ[i] = Taylor1(constant_term(-1.5) + constant_term(tmp763[i]), order) + tmp766[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(2)), order) + tmp767[i] = Taylor1(constant_term(Λ2[i]) / constant_term(tmp766[i]), order) + Λ2j_div_r4[i] = Taylor1(-(constant_term(tmp767[i])), order) + tmp770[i] = Taylor1(constant_term(r_p1d2[i]) ^ float(constant_term(5)), order) + tmp771[i] = Taylor1(constant_term(Λ3[i]) / constant_term(tmp770[i]), order) + Λ3j_div_r5[i] = Taylor1(-(constant_term(tmp771[i])), order) + tmp773[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) + m_c_ϕ_∂P_2[i] = Taylor1(constant_term(tmp773[i]) * constant_term(∂P_2_sin_ϕ[i]), order) + tmp775[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) + m_c_ϕ_∂P_3[i] = Taylor1(constant_term(tmp775[i]) * constant_term(∂P_3_sin_ϕ[i]), order) + tmp778[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(3), order) + F_J2_ξ[i] = Taylor1(constant_term(tmp778[i]) * constant_term(P_2_sin_ϕ[i]), order) + F_J2_ζ[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]), order) + tmp782[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(4), order) + F_J3_ξ[i] = Taylor1(constant_term(tmp782[i]) * constant_term(P_3_sin_ϕ[i]), order) + F_J3_ζ[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]), order) + F_J_ξ[i] = Taylor1(identity(constant_term(F_J2_ξ[i])), order) + F_J_ζ[i] = Taylor1(identity(constant_term(F_J2_ζ[i])), order) + tmp785[i] = Taylor1(-(constant_term(X[i])), order) + ξx[i] = Taylor1(constant_term(tmp785[i]) / constant_term(r_p1d2[i]), order) + tmp787[i] = Taylor1(-(constant_term(Y[i])), order) + ξy[i] = Taylor1(constant_term(tmp787[i]) / constant_term(r_p1d2[i]), order) + tmp789[i] = Taylor1(-(constant_term(Z[i])), order) + ξz[i] = Taylor1(constant_term(tmp789[i]) / constant_term(r_p1d2[i]), order) + ηx1[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξz[i]), order) + ηy1[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξx[i]), order) + ηz1[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξy[i]), order) + ηx2[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξy[i]), order) + ηy2[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξz[i]), order) + ηz2[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξx[i]), order) + ηx[i] = Taylor1(constant_term(ηx1[i]) - constant_term(ηx2[i]), order) + ηy[i] = Taylor1(constant_term(ηy1[i]) - constant_term(ηy2[i]), order) + ηz[i] = Taylor1(constant_term(ηz1[i]) - constant_term(ηz2[i]), order) + ζx1[i] = Taylor1(constant_term(ξy[i]) * constant_term(ηz[i]), order) + ζy1[i] = Taylor1(constant_term(ξz[i]) * constant_term(ηx[i]), order) + ζz1[i] = Taylor1(constant_term(ξx[i]) * constant_term(ηy[i]), order) + ζx2[i] = Taylor1(constant_term(ξz[i]) * constant_term(ηy[i]), order) + ζy2[i] = Taylor1(constant_term(ξx[i]) * constant_term(ηz[i]), order) + ζz2[i] = Taylor1(constant_term(ξy[i]) * constant_term(ηx[i]), order) + ζx[i] = Taylor1(constant_term(ζx1[i]) - constant_term(ζx2[i]), order) + ζy[i] = Taylor1(constant_term(ζy1[i]) - constant_term(ζy2[i]), order) + ζz[i] = Taylor1(constant_term(ζz1[i]) - constant_term(ζz2[i]), order) + F_J2_x1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξx[i]), order) + F_J2_y1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξy[i]), order) + F_J2_z1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξz[i]), order) + F_J2_x2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζx[i]), order) + F_J2_y2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζy[i]), order) + F_J2_z2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζz[i]), order) + F_J2_x[i] = Taylor1(constant_term(F_J2_x1[i]) + constant_term(F_J2_x2[i]), order) + F_J2_y[i] = Taylor1(constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]), order) + F_J2_z[i] = Taylor1(constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]), order) + end + tmp819[i] = Taylor1(constant_term(ui[i]) ^ float(constant_term(2)), order) + tmp821[i] = Taylor1(constant_term(vi[i]) ^ float(constant_term(2)), order) + tmp822[i] = Taylor1(constant_term(tmp819[i]) + constant_term(tmp821[i]), order) + tmp824[i] = Taylor1(constant_term(wi[i]) ^ float(constant_term(2)), order) + v2[i] = Taylor1(constant_term(tmp822[i]) + constant_term(tmp824[i]), order) + end + tmp827 = Taylor1(constant_term(q[4]) ^ float(constant_term(2)), order) + tmp829 = Taylor1(constant_term(q[5]) ^ float(constant_term(2)), order) + tmp830 = Taylor1(constant_term(tmp827) + constant_term(tmp829), order) + tmp832 = Taylor1(constant_term(q[6]) ^ float(constant_term(2)), order) + v2[N] = Taylor1(constant_term(tmp830) + constant_term(tmp832), order) + temp_004 = Array{Taylor1{_S}}(undef, size(newtonian1b_Potential)) + temp_004 .= Taylor1(zero(constant_term(q[1])), order) + tmp835 = Array{Taylor1{_S}}(undef, size(μ)) + tmp835 .= Taylor1(zero(constant_term(q[1])), order) + tmp837 = Array{Taylor1{_S}}(undef, size(μ)) + tmp837 .= Taylor1(zero(constant_term(q[1])), order) + tmp839 = Array{Taylor1{_S}}(undef, size(μ)) + tmp839 .= Taylor1(zero(constant_term(q[1])), order) + for i = 1:Nm1 + temp_004[i] = Taylor1(constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]), order) + newtonianNb_Potential[N] = Taylor1(identity(constant_term(temp_004[i])), order) + if UJ_interaction[i] + tmp835[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_x[i]), order) + temp_accX_i[i] = Taylor1(constant_term(accX) - constant_term(tmp835[i]), order) + accX = Taylor1(identity(constant_term(temp_accX_i[i])), order) + tmp837[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_y[i]), order) + temp_accY_i[i] = Taylor1(constant_term(accY) - constant_term(tmp837[i]), order) + accY = Taylor1(identity(constant_term(temp_accY_i[i])), order) + tmp839[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_z[i]), order) + temp_accZ_i[i] = Taylor1(constant_term(accZ) - constant_term(tmp839[i]), order) + accZ = Taylor1(identity(constant_term(temp_accZ_i[i])), order) + end + end + _4ϕj[N] = Taylor1(constant_term(4) * constant_term(newtonianNb_Potential[N]), order) + tmp845 = Array{Taylor1{_S}}(undef, size(v2)) + tmp845 .= Taylor1(zero(constant_term(q[1])), order) + tmp847 = Array{Taylor1{_S}}(undef, size(vi_dot_vj)) + tmp847 .= Taylor1(zero(constant_term(q[1])), order) + tmp848 = Array{Taylor1{_S}}(undef, size(tmp845)) + tmp848 .= Taylor1(zero(constant_term(q[1])), order) + Xij_t_Ui = Array{Taylor1{_S}}(undef, size(X)) + Xij_t_Ui .= Taylor1(zero(constant_term(q[1])), order) + Yij_t_Vi = Array{Taylor1{_S}}(undef, size(Y)) + Yij_t_Vi .= Taylor1(zero(constant_term(q[1])), order) + Zij_t_Wi = Array{Taylor1{_S}}(undef, size(Z)) + Zij_t_Wi .= Taylor1(zero(constant_term(q[1])), order) + tmp854 = Array{Taylor1{_S}}(undef, size(Xij_t_Ui)) + tmp854 .= Taylor1(zero(constant_term(q[1])), order) + Rij_dot_Vi = Array{Taylor1{_S}}(undef, size(tmp854)) + Rij_dot_Vi .= Taylor1(zero(constant_term(q[1])), order) + tmp857 = Array{Taylor1{_S}}(undef, size(Rij_dot_Vi)) + tmp857 .= Taylor1(zero(constant_term(q[1])), order) + pn1t7 = Array{Taylor1{_S}}(undef, size(tmp857)) + pn1t7 .= Taylor1(zero(constant_term(q[1])), order) + tmp860 = Array{Taylor1{_S}}(undef, size(pn1t7)) + tmp860 .= Taylor1(zero(constant_term(q[1])), order) + pn1t2_7 = Array{Taylor1{_S}}(undef, size(ϕs_and_vs)) + pn1t2_7 .= Taylor1(zero(constant_term(q[1])), order) + tmp867 = Array{Taylor1{_S}}(undef, size(pNX_t_X)) + tmp867 .= Taylor1(zero(constant_term(q[1])), order) + tmp868 = Array{Taylor1{_S}}(undef, size(tmp867)) + tmp868 .= Taylor1(zero(constant_term(q[1])), order) + tmp869 = Array{Taylor1{_S}}(undef, size(tmp868)) + tmp869 .= Taylor1(zero(constant_term(q[1])), order) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 + ϕi_plus_4ϕj[i] = Taylor1(constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]), order) + tmp845[i] = Taylor1(constant_term(2) * constant_term(v2[i]), order) + tmp847[i] = Taylor1(constant_term(4) * constant_term(vi_dot_vj[i]), order) + tmp848[i] = Taylor1(constant_term(tmp845[i]) - constant_term(tmp847[i]), order) + sj2_plus_2si2_minus_4vivj[i] = Taylor1(constant_term(tmp848[i]) + constant_term(v2[N]), order) + ϕs_and_vs[i] = Taylor1(constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]), order) + Xij_t_Ui[i] = Taylor1(constant_term(X[i]) * constant_term(ui[i]), order) + Yij_t_Vi[i] = Taylor1(constant_term(Y[i]) * constant_term(vi[i]), order) + Zij_t_Wi[i] = Taylor1(constant_term(Z[i]) * constant_term(wi[i]), order) + tmp854[i] = Taylor1(constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]), order) + Rij_dot_Vi[i] = Taylor1(constant_term(tmp854[i]) + constant_term(Zij_t_Wi[i]), order) + tmp857[i] = Taylor1(constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)), order) + pn1t7[i] = Taylor1(constant_term(tmp857[i]) / constant_term(r_p2[i]), order) + tmp860[i] = Taylor1(constant_term(1.5) * constant_term(pn1t7[i]), order) + pn1t2_7[i] = Taylor1(constant_term(ϕs_and_vs[i]) - constant_term(tmp860[i]), order) + pn1t1_7[i] = Taylor1(constant_term(c_p2) + constant_term(pn1t2_7[i]), order) + pNX_t_X[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(X[i]), order) + pNY_t_Y[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(Y[i]), order) + pNZ_t_Z[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(Z[i]), order) + tmp867[i] = Taylor1(constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]), order) + tmp868[i] = Taylor1(constant_term(tmp867[i]) + constant_term(pNZ_t_Z[i]), order) + tmp869[i] = Taylor1(constant_term(0.5) * constant_term(tmp868[i]), order) + pn1[i] = Taylor1(constant_term(pn1t1_7[i]) + constant_term(tmp869[i]), order) + X_t_pn1[i] = Taylor1(constant_term(newton_acc_X[i]) * constant_term(pn1[i]), order) + Y_t_pn1[i] = Taylor1(constant_term(newton_acc_Y[i]) * constant_term(pn1[i]), order) + Z_t_pn1[i] = Taylor1(constant_term(newton_acc_Z[i]) * constant_term(pn1[i]), order) + pNX_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(pn3[i]), order) + pNY_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]), order) + pNZ_t_pn3[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(pn3[i]), order) + end + tmp877 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) + tmp877 .= Taylor1(zero(constant_term(q[1])), order) + termpnx = Array{Taylor1{_S}}(undef, size(X_t_pn1)) + termpnx .= Taylor1(zero(constant_term(q[1])), order) + sumpnx = Array{Taylor1{_S}}(undef, size(termpnx)) + sumpnx .= Taylor1(zero(constant_term(q[1])), order) + tmp880 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) + tmp880 .= Taylor1(zero(constant_term(q[1])), order) + termpny = Array{Taylor1{_S}}(undef, size(Y_t_pn1)) + termpny .= Taylor1(zero(constant_term(q[1])), order) + sumpny = Array{Taylor1{_S}}(undef, size(termpny)) + sumpny .= Taylor1(zero(constant_term(q[1])), order) + tmp883 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) + tmp883 .= Taylor1(zero(constant_term(q[1])), order) + termpnz = Array{Taylor1{_S}}(undef, size(Z_t_pn1)) + termpnz .= Taylor1(zero(constant_term(q[1])), order) + sumpnz = Array{Taylor1{_S}}(undef, size(termpnz)) + sumpnz .= Taylor1(zero(constant_term(q[1])), order) + for i = 1:10 + tmp877[i] = Taylor1(constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]), order) + termpnx[i] = Taylor1(constant_term(X_t_pn1[i]) + constant_term(tmp877[i]), order) + sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) + pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) + tmp880[i] = Taylor1(constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]), order) + termpny[i] = Taylor1(constant_term(Y_t_pn1[i]) + constant_term(tmp880[i]), order) + sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) + pntempY = Taylor1(identity(constant_term(sumpny[i])), order) + tmp883[i] = Taylor1(constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]), order) + termpnz[i] = Taylor1(constant_term(Z_t_pn1[i]) + constant_term(tmp883[i]), order) + sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) + pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) + end + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 + X_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_X[i]), order) + Y_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Y[i]), order) + Z_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Z[i]), order) + end + for i = 11:Nm1 + termpnx[i] = Taylor1(identity(constant_term(X_t_pn1[i])), order) + sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) + pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) + termpny[i] = Taylor1(identity(constant_term(Y_t_pn1[i])), order) + sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) + pntempY = Taylor1(identity(constant_term(sumpny[i])), order) + termpnz[i] = Taylor1(identity(constant_term(Z_t_pn1[i])), order) + sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) + pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) + end + postNewtonX = Taylor1(constant_term(pntempX) * constant_term(c_m2), order) + postNewtonY = Taylor1(constant_term(pntempY) * constant_term(c_m2), order) + postNewtonZ = Taylor1(constant_term(pntempZ) * constant_term(c_m2), order) + tmp895 = Taylor1(constant_term(Y[1]) * constant_term(W[1]), order) + tmp896 = Taylor1(constant_term(Z[1]) * constant_term(V[1]), order) + hx = Taylor1(constant_term(tmp895) - constant_term(tmp896), order) + tmp898 = Taylor1(constant_term(Z[1]) * constant_term(U[1]), order) + tmp899 = Taylor1(constant_term(X[1]) * constant_term(W[1]), order) + hy = Taylor1(constant_term(tmp898) - constant_term(tmp899), order) + tmp901 = Taylor1(constant_term(X[1]) * constant_term(V[1]), order) + tmp902 = Taylor1(constant_term(Y[1]) * constant_term(U[1]), order) + hz = Taylor1(constant_term(tmp901) - constant_term(tmp902), order) + tmp904 = Taylor1(constant_term(hz) * constant_term(Y[1]), order) + tmp905 = Taylor1(constant_term(hy) * constant_term(Z[1]), order) + t_x = Taylor1(constant_term(tmp904) - constant_term(tmp905), order) + tmp907 = Taylor1(constant_term(hx) * constant_term(Z[1]), order) + tmp908 = Taylor1(constant_term(hz) * constant_term(X[1]), order) + t_y = Taylor1(constant_term(tmp907) - constant_term(tmp908), order) + tmp910 = Taylor1(constant_term(hy) * constant_term(X[1]), order) + tmp911 = Taylor1(constant_term(hx) * constant_term(Y[1]), order) + t_z = Taylor1(constant_term(tmp910) - constant_term(tmp911), order) + tmp914 = Taylor1(constant_term(t_x) ^ float(constant_term(2)), order) + tmp916 = Taylor1(constant_term(t_y) ^ float(constant_term(2)), order) + tmp917 = Taylor1(constant_term(tmp914) + constant_term(tmp916), order) + tmp919 = Taylor1(constant_term(t_z) ^ float(constant_term(2)), order) + tmp920 = Taylor1(constant_term(tmp917) + constant_term(tmp919), order) + t_norm = Taylor1(sqrt(constant_term(tmp920)), order) + t_x_unit = Taylor1(constant_term(t_x) / constant_term(t_norm), order) + t_y_unit = Taylor1(constant_term(t_y) / constant_term(t_norm), order) + t_z_unit = Taylor1(constant_term(t_z) / constant_term(t_norm), order) + tmp925 = Taylor1(constant_term(X[1]) / constant_term(r_p1d2[1]), order) + r_x_unit = Taylor1(-(constant_term(tmp925)), order) + tmp927 = Taylor1(constant_term(Y[1]) / constant_term(r_p1d2[1]), order) + r_y_unit = Taylor1(-(constant_term(tmp927)), order) + tmp929 = Taylor1(constant_term(Z[1]) / constant_term(r_p1d2[1]), order) + r_z_unit = Taylor1(-(constant_term(tmp929)), order) + g_r = Taylor1(identity(constant_term(r_p2[1])), order) + A2_t_g_r = Taylor1(constant_term(q[7]) / constant_term(g_r), order) + A1_t_g_r = Taylor1(constant_term(q[8]) / constant_term(g_r), order) + tmp933 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_x_unit), order) + tmp934 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_x_unit), order) + NGAx = Taylor1(constant_term(tmp933) + constant_term(tmp934), order) + tmp936 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_y_unit), order) + tmp937 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_y_unit), order) + NGAy = Taylor1(constant_term(tmp936) + constant_term(tmp937), order) + tmp939 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_z_unit), order) + tmp940 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_z_unit), order) + NGAz = Taylor1(constant_term(tmp939) + constant_term(tmp940), order) + tmp942 = Taylor1(constant_term(postNewtonX) + constant_term(accX), order) + dq[4] = Taylor1(constant_term(tmp942) + constant_term(NGAx), order) + tmp944 = Taylor1(constant_term(postNewtonY) + constant_term(accY), order) + dq[5] = Taylor1(constant_term(tmp944) + constant_term(NGAy), order) + tmp946 = Taylor1(constant_term(postNewtonZ) + constant_term(accZ), order) + dq[6] = Taylor1(constant_term(tmp946) + constant_term(NGAz), order) + dq[7] = Taylor1(identity(constant_term(zero_q_1)), order) + return TaylorIntegration.RetAlloc{Taylor1{_S}}([tmp827, tmp829, tmp830, tmp832, tmp895, tmp896, tmp898, tmp899, tmp901, tmp902, tmp904, tmp905, tmp907, tmp908, tmp910, tmp911, tmp914, tmp916, tmp917, tmp919, tmp920, tmp925, tmp927, tmp929, tmp933, tmp934, tmp936, tmp937, tmp939, tmp940, tmp942, tmp944, tmp946, pntempX, pntempY, pntempZ, accX, accY, accZ, postNewtonX, postNewtonY, postNewtonZ, hx, hy, hz, t_x, t_y, t_z, t_norm, t_x_unit, t_y_unit, t_z_unit, r_x_unit, r_y_unit, r_z_unit, g_r, A2_t_g_r, A1_t_g_r, NGAx, NGAy, NGAz], [X, Y, Z, r_p2, r_p1d2, r_p3d2, r_p7d2, newtonianCoeff, ui, vi, wi, U, V, W, _4U_m_3X, _4V_m_3Y, _4W_m_3Z, UU, VV, WW, newtonian1b_Potential, newtonianNb_Potential, newton_acc_X, newton_acc_Y, newton_acc_Z, v2, vi_dot_vj, pn2, U_t_pn2, V_t_pn2, W_t_pn2, pn3, pNX_t_pn3, pNY_t_pn3, pNZ_t_pn3, _4ϕj, ϕi_plus_4ϕj, sj2_plus_2si2_minus_4vivj, ϕs_and_vs, pn1t1_7, pNX_t_X, pNY_t_Y, pNZ_t_Z, pn1, X_t_pn1, Y_t_pn1, Z_t_pn1, t31, t32, t33, r_sin_ϕ, sin_ϕ, ϕ, cos_ϕ, sin2_ϕ, sin3_ϕ, F_J2_x, F_J2_y, F_J2_z, F_J2_x1, F_J2_y1, F_J2_z1, F_J2_x2, F_J2_y2, F_J2_z2, temp_accX_i, temp_accY_i, temp_accZ_i, P_2_sin_ϕ, ∂P_2_sin_ϕ, P_3_sin_ϕ, ∂P_3_sin_ϕ, m_c_ϕ_∂P_2, m_c_ϕ_∂P_3, Λ2j_div_r4, Λ3j_div_r5, F_J_ξ, F_J_ζ, F_J2_ξ, F_J2_ζ, F_J3_ξ, F_J3_ζ, ξx, ξy, ξz, ηx, ηy, ηz, ηx1, ηy1, ηz1, ηx2, ηy2, ηz2, ζx, ζy, ζz, ζx1, ζy1, ζz1, ζx2, ζy2, ζz2, tmp687, tmp689, tmp692, tmp694, tmp697, tmp699, pn2x, pn2y, pn2z, tmp707, tmp710, tmp712, tmp713, tmp715, tmp723, tmp724, tmp735, tmp737, tmp739, tmp741, tmp948, tmp949, tmp751, tmp757, tmp759, tmp763, tmp766, tmp767, tmp770, tmp771, tmp773, tmp775, tmp778, tmp782, tmp785, tmp787, tmp789, tmp819, tmp821, tmp822, tmp824, temp_004, tmp835, tmp837, tmp839, tmp845, tmp847, tmp848, Xij_t_Ui, Yij_t_Vi, Zij_t_Wi, tmp854, Rij_dot_Vi, tmp857, pn1t7, tmp860, pn1t2_7, tmp867, tmp868, tmp869, tmp877, termpnx, sumpnx, tmp880, termpny, sumpny, tmp883, termpnz, sumpnz], [Array{Taylor1{_S}, 2}(undef, 0, 0)], [Array{Taylor1{_S}, 3}(undef, 0, 0, 0)], [Array{Taylor1{_S}, 4}(undef, 0, 0, 0, 0)]) +end + +# TaylorIntegration.jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_ng_eph_threads! +function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params, __ralloc::TaylorIntegration.RetAlloc{Taylor1{_S}}) where {_T <: Real, _S <: Number, _N} + order = t.order + tmp827 = __ralloc.v0[1] + tmp829 = __ralloc.v0[2] + tmp830 = __ralloc.v0[3] + tmp832 = __ralloc.v0[4] + tmp895 = __ralloc.v0[5] + tmp896 = __ralloc.v0[6] + tmp898 = __ralloc.v0[7] + tmp899 = __ralloc.v0[8] + tmp901 = __ralloc.v0[9] + tmp902 = __ralloc.v0[10] + tmp904 = __ralloc.v0[11] + tmp905 = __ralloc.v0[12] + tmp907 = __ralloc.v0[13] + tmp908 = __ralloc.v0[14] + tmp910 = __ralloc.v0[15] + tmp911 = __ralloc.v0[16] + tmp914 = __ralloc.v0[17] + tmp916 = __ralloc.v0[18] + tmp917 = __ralloc.v0[19] + tmp919 = __ralloc.v0[20] + tmp920 = __ralloc.v0[21] + tmp925 = __ralloc.v0[22] + tmp927 = __ralloc.v0[23] + tmp929 = __ralloc.v0[24] + tmp933 = __ralloc.v0[25] + tmp934 = __ralloc.v0[26] + tmp936 = __ralloc.v0[27] + tmp937 = __ralloc.v0[28] + tmp939 = __ralloc.v0[29] + tmp940 = __ralloc.v0[30] + tmp942 = __ralloc.v0[31] + tmp944 = __ralloc.v0[32] + tmp946 = __ralloc.v0[33] + pntempX = __ralloc.v0[34] + pntempY = __ralloc.v0[35] + pntempZ = __ralloc.v0[36] + accX = __ralloc.v0[37] + accY = __ralloc.v0[38] + accZ = __ralloc.v0[39] + postNewtonX = __ralloc.v0[40] + postNewtonY = __ralloc.v0[41] + postNewtonZ = __ralloc.v0[42] + hx = __ralloc.v0[43] + hy = __ralloc.v0[44] + hz = __ralloc.v0[45] + t_x = __ralloc.v0[46] + t_y = __ralloc.v0[47] + t_z = __ralloc.v0[48] + t_norm = __ralloc.v0[49] + t_x_unit = __ralloc.v0[50] + t_y_unit = __ralloc.v0[51] + t_z_unit = __ralloc.v0[52] + r_x_unit = __ralloc.v0[53] + r_y_unit = __ralloc.v0[54] + r_z_unit = __ralloc.v0[55] + g_r = __ralloc.v0[56] + A2_t_g_r = __ralloc.v0[57] + A1_t_g_r = __ralloc.v0[58] + NGAx = __ralloc.v0[59] + NGAy = __ralloc.v0[60] + NGAz = __ralloc.v0[61] + X = __ralloc.v1[1] + Y = __ralloc.v1[2] + Z = __ralloc.v1[3] + r_p2 = __ralloc.v1[4] + r_p1d2 = __ralloc.v1[5] + r_p3d2 = __ralloc.v1[6] + r_p7d2 = __ralloc.v1[7] + newtonianCoeff = __ralloc.v1[8] + ui = __ralloc.v1[9] + vi = __ralloc.v1[10] + wi = __ralloc.v1[11] + U = __ralloc.v1[12] + V = __ralloc.v1[13] + W = __ralloc.v1[14] + _4U_m_3X = __ralloc.v1[15] + _4V_m_3Y = __ralloc.v1[16] + _4W_m_3Z = __ralloc.v1[17] + UU = __ralloc.v1[18] + VV = __ralloc.v1[19] + WW = __ralloc.v1[20] + newtonian1b_Potential = __ralloc.v1[21] + newtonianNb_Potential = __ralloc.v1[22] + newton_acc_X = __ralloc.v1[23] + newton_acc_Y = __ralloc.v1[24] + newton_acc_Z = __ralloc.v1[25] + v2 = __ralloc.v1[26] + vi_dot_vj = __ralloc.v1[27] + pn2 = __ralloc.v1[28] + U_t_pn2 = __ralloc.v1[29] + V_t_pn2 = __ralloc.v1[30] + W_t_pn2 = __ralloc.v1[31] + pn3 = __ralloc.v1[32] + pNX_t_pn3 = __ralloc.v1[33] + pNY_t_pn3 = __ralloc.v1[34] + pNZ_t_pn3 = __ralloc.v1[35] + _4ϕj = __ralloc.v1[36] + ϕi_plus_4ϕj = __ralloc.v1[37] + sj2_plus_2si2_minus_4vivj = __ralloc.v1[38] + ϕs_and_vs = __ralloc.v1[39] + pn1t1_7 = __ralloc.v1[40] + pNX_t_X = __ralloc.v1[41] + pNY_t_Y = __ralloc.v1[42] + pNZ_t_Z = __ralloc.v1[43] + pn1 = __ralloc.v1[44] + X_t_pn1 = __ralloc.v1[45] + Y_t_pn1 = __ralloc.v1[46] + Z_t_pn1 = __ralloc.v1[47] + t31 = __ralloc.v1[48] + t32 = __ralloc.v1[49] + t33 = __ralloc.v1[50] + r_sin_ϕ = __ralloc.v1[51] + sin_ϕ = __ralloc.v1[52] + ϕ = __ralloc.v1[53] + cos_ϕ = __ralloc.v1[54] + sin2_ϕ = __ralloc.v1[55] + sin3_ϕ = __ralloc.v1[56] + F_J2_x = __ralloc.v1[57] + F_J2_y = __ralloc.v1[58] + F_J2_z = __ralloc.v1[59] + F_J2_x1 = __ralloc.v1[60] + F_J2_y1 = __ralloc.v1[61] + F_J2_z1 = __ralloc.v1[62] + F_J2_x2 = __ralloc.v1[63] + F_J2_y2 = __ralloc.v1[64] + F_J2_z2 = __ralloc.v1[65] + temp_accX_i = __ralloc.v1[66] + temp_accY_i = __ralloc.v1[67] + temp_accZ_i = __ralloc.v1[68] + P_2_sin_ϕ = __ralloc.v1[69] + ∂P_2_sin_ϕ = __ralloc.v1[70] + P_3_sin_ϕ = __ralloc.v1[71] + ∂P_3_sin_ϕ = __ralloc.v1[72] + m_c_ϕ_∂P_2 = __ralloc.v1[73] + m_c_ϕ_∂P_3 = __ralloc.v1[74] + Λ2j_div_r4 = __ralloc.v1[75] + Λ3j_div_r5 = __ralloc.v1[76] + F_J_ξ = __ralloc.v1[77] + F_J_ζ = __ralloc.v1[78] + F_J2_ξ = __ralloc.v1[79] + F_J2_ζ = __ralloc.v1[80] + F_J3_ξ = __ralloc.v1[81] + F_J3_ζ = __ralloc.v1[82] + ξx = __ralloc.v1[83] + ξy = __ralloc.v1[84] + ξz = __ralloc.v1[85] + ηx = __ralloc.v1[86] + ηy = __ralloc.v1[87] + ηz = __ralloc.v1[88] + ηx1 = __ralloc.v1[89] + ηy1 = __ralloc.v1[90] + ηz1 = __ralloc.v1[91] + ηx2 = __ralloc.v1[92] + ηy2 = __ralloc.v1[93] + ηz2 = __ralloc.v1[94] + ζx = __ralloc.v1[95] + ζy = __ralloc.v1[96] + ζz = __ralloc.v1[97] + ζx1 = __ralloc.v1[98] + ζy1 = __ralloc.v1[99] + ζz1 = __ralloc.v1[100] + ζx2 = __ralloc.v1[101] + ζy2 = __ralloc.v1[102] + ζz2 = __ralloc.v1[103] + tmp687 = __ralloc.v1[104] + tmp689 = __ralloc.v1[105] + tmp692 = __ralloc.v1[106] + tmp694 = __ralloc.v1[107] + tmp697 = __ralloc.v1[108] + tmp699 = __ralloc.v1[109] + pn2x = __ralloc.v1[110] + pn2y = __ralloc.v1[111] + pn2z = __ralloc.v1[112] + tmp707 = __ralloc.v1[113] + tmp710 = __ralloc.v1[114] + tmp712 = __ralloc.v1[115] + tmp713 = __ralloc.v1[116] + tmp715 = __ralloc.v1[117] + tmp723 = __ralloc.v1[118] + tmp724 = __ralloc.v1[119] + tmp735 = __ralloc.v1[120] + tmp737 = __ralloc.v1[121] + tmp739 = __ralloc.v1[122] + tmp741 = __ralloc.v1[123] + tmp948 = __ralloc.v1[124] + tmp949 = __ralloc.v1[125] + tmp751 = __ralloc.v1[126] + tmp757 = __ralloc.v1[127] + tmp759 = __ralloc.v1[128] + tmp763 = __ralloc.v1[129] + tmp766 = __ralloc.v1[130] + tmp767 = __ralloc.v1[131] + tmp770 = __ralloc.v1[132] + tmp771 = __ralloc.v1[133] + tmp773 = __ralloc.v1[134] + tmp775 = __ralloc.v1[135] + tmp778 = __ralloc.v1[136] + tmp782 = __ralloc.v1[137] + tmp785 = __ralloc.v1[138] + tmp787 = __ralloc.v1[139] + tmp789 = __ralloc.v1[140] + tmp819 = __ralloc.v1[141] + tmp821 = __ralloc.v1[142] + tmp822 = __ralloc.v1[143] + tmp824 = __ralloc.v1[144] + temp_004 = __ralloc.v1[145] + tmp835 = __ralloc.v1[146] + tmp837 = __ralloc.v1[147] + tmp839 = __ralloc.v1[148] + tmp845 = __ralloc.v1[149] + tmp847 = __ralloc.v1[150] + tmp848 = __ralloc.v1[151] + Xij_t_Ui = __ralloc.v1[152] + Yij_t_Vi = __ralloc.v1[153] + Zij_t_Wi = __ralloc.v1[154] + tmp854 = __ralloc.v1[155] + Rij_dot_Vi = __ralloc.v1[156] + tmp857 = __ralloc.v1[157] + pn1t7 = __ralloc.v1[158] + tmp860 = __ralloc.v1[159] + pn1t2_7 = __ralloc.v1[160] + tmp867 = __ralloc.v1[161] + tmp868 = __ralloc.v1[162] + tmp869 = __ralloc.v1[163] + tmp877 = __ralloc.v1[164] + termpnx = __ralloc.v1[165] + sumpnx = __ralloc.v1[166] + tmp880 = __ralloc.v1[167] + termpny = __ralloc.v1[168] + sumpny = __ralloc.v1[169] + tmp883 = __ralloc.v1[170] + termpnz = __ralloc.v1[171] + sumpnz = __ralloc.v1[172] + local jd0 = params[4] + local dsj2k = t + (jd0 - JD_J2000) + local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) + local acceph_t = evaleph(params[2], dsj2k, q[1]) + local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) + local S = eltype(q) + local UJ_interaction = params[5] + local N = params[6] + local Nm1 = N - 1 + local μ = params[7] + local zero_q_1 = auxzero(q[1]) + pntempX.coeffs[1] = identity(constant_term(zero_q_1)) + pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) + pntempY.coeffs[1] = identity(constant_term(zero_q_1)) + pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) + pntempZ.coeffs[1] = identity(constant_term(zero_q_1)) + pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) + accX.coeffs[1] = identity(constant_term(zero_q_1)) + accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) + accY.coeffs[1] = identity(constant_term(zero_q_1)) + accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) + accZ.coeffs[1] = identity(constant_term(zero_q_1)) + accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) + local M_ = Array{S}(undef, 3, 3, N) + local M_ .= zero_q_1 + local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 + (dq[1]).coeffs[1] = identity(constant_term(q[4])) + (dq[1]).coeffs[2:order + 1] .= zero((dq[1]).coeffs[1]) + (dq[2]).coeffs[1] = identity(constant_term(q[5])) + (dq[2]).coeffs[2:order + 1] .= zero((dq[2]).coeffs[1]) + (dq[3]).coeffs[1] = identity(constant_term(q[6])) + (dq[3]).coeffs[2:order + 1] .= zero((dq[3]).coeffs[1]) + (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(zero_q_1)) + (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 + (ui[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])) + (ui[i]).coeffs[2:order + 1] .= zero((ui[i]).coeffs[1]) + (vi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])) + (vi[i]).coeffs[2:order + 1] .= zero((vi[i]).coeffs[1]) + (wi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])) + (wi[i]).coeffs[2:order + 1] .= zero((wi[i]).coeffs[1]) + (X[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 2]) - constant_term(q[1]) + (X[i]).coeffs[2:order + 1] .= zero((X[i]).coeffs[1]) + (Y[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 1]) - constant_term(q[2]) + (Y[i]).coeffs[2:order + 1] .= zero((Y[i]).coeffs[1]) + (Z[i]).coeffs[1] = constant_term(ss16asteph_t[3i]) - constant_term(q[3]) + (Z[i]).coeffs[2:order + 1] .= zero((Z[i]).coeffs[1]) + (U[i]).coeffs[1] = constant_term(ui[i]) - constant_term(dq[1]) + (U[i]).coeffs[2:order + 1] .= zero((U[i]).coeffs[1]) + (V[i]).coeffs[1] = constant_term(vi[i]) - constant_term(dq[2]) + (V[i]).coeffs[2:order + 1] .= zero((V[i]).coeffs[1]) + (W[i]).coeffs[1] = constant_term(wi[i]) - constant_term(dq[3]) + (W[i]).coeffs[2:order + 1] .= zero((W[i]).coeffs[1]) + (tmp687[1]).coeffs[1] = constant_term(4) * constant_term(dq[1]) + (tmp687[1]).coeffs[2:order + 1] .= zero((tmp687[1]).coeffs[1]) + (tmp689[i]).coeffs[1] = constant_term(3) * constant_term(ui[i]) + (tmp689[i]).coeffs[2:order + 1] .= zero((tmp689[i]).coeffs[1]) + (_4U_m_3X[i]).coeffs[1] = constant_term(tmp687[1]) - constant_term(tmp689[i]) + (_4U_m_3X[i]).coeffs[2:order + 1] .= zero((_4U_m_3X[i]).coeffs[1]) + (tmp692[2]).coeffs[1] = constant_term(4) * constant_term(dq[2]) + (tmp692[2]).coeffs[2:order + 1] .= zero((tmp692[2]).coeffs[1]) + (tmp694[i]).coeffs[1] = constant_term(3) * constant_term(vi[i]) + (tmp694[i]).coeffs[2:order + 1] .= zero((tmp694[i]).coeffs[1]) + (_4V_m_3Y[i]).coeffs[1] = constant_term(tmp692[2]) - constant_term(tmp694[i]) + (_4V_m_3Y[i]).coeffs[2:order + 1] .= zero((_4V_m_3Y[i]).coeffs[1]) + (tmp697[3]).coeffs[1] = constant_term(4) * constant_term(dq[3]) + (tmp697[3]).coeffs[2:order + 1] .= zero((tmp697[3]).coeffs[1]) + (tmp699[i]).coeffs[1] = constant_term(3) * constant_term(wi[i]) + (tmp699[i]).coeffs[2:order + 1] .= zero((tmp699[i]).coeffs[1]) + (_4W_m_3Z[i]).coeffs[1] = constant_term(tmp697[3]) - constant_term(tmp699[i]) + (_4W_m_3Z[i]).coeffs[2:order + 1] .= zero((_4W_m_3Z[i]).coeffs[1]) + (pn2x[i]).coeffs[1] = constant_term(X[i]) * constant_term(_4U_m_3X[i]) + (pn2x[i]).coeffs[2:order + 1] .= zero((pn2x[i]).coeffs[1]) + (pn2y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(_4V_m_3Y[i]) + (pn2y[i]).coeffs[2:order + 1] .= zero((pn2y[i]).coeffs[1]) + (pn2z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(_4W_m_3Z[i]) + (pn2z[i]).coeffs[2:order + 1] .= zero((pn2z[i]).coeffs[1]) + (UU[i]).coeffs[1] = constant_term(ui[i]) * constant_term(dq[1]) + (UU[i]).coeffs[2:order + 1] .= zero((UU[i]).coeffs[1]) + (VV[i]).coeffs[1] = constant_term(vi[i]) * constant_term(dq[2]) + (VV[i]).coeffs[2:order + 1] .= zero((VV[i]).coeffs[1]) + (WW[i]).coeffs[1] = constant_term(wi[i]) * constant_term(dq[3]) + (WW[i]).coeffs[2:order + 1] .= zero((WW[i]).coeffs[1]) + (tmp707[i]).coeffs[1] = constant_term(UU[i]) + constant_term(VV[i]) + (tmp707[i]).coeffs[2:order + 1] .= zero((tmp707[i]).coeffs[1]) + (vi_dot_vj[i]).coeffs[1] = constant_term(tmp707[i]) + constant_term(WW[i]) + (vi_dot_vj[i]).coeffs[2:order + 1] .= zero((vi_dot_vj[i]).coeffs[1]) + (tmp710[i]).coeffs[1] = constant_term(X[i]) ^ float(constant_term(2)) + (tmp710[i]).coeffs[2:order + 1] .= zero((tmp710[i]).coeffs[1]) + (tmp712[i]).coeffs[1] = constant_term(Y[i]) ^ float(constant_term(2)) + (tmp712[i]).coeffs[2:order + 1] .= zero((tmp712[i]).coeffs[1]) + (tmp713[i]).coeffs[1] = constant_term(tmp710[i]) + constant_term(tmp712[i]) + (tmp713[i]).coeffs[2:order + 1] .= zero((tmp713[i]).coeffs[1]) + (tmp715[i]).coeffs[1] = constant_term(Z[i]) ^ float(constant_term(2)) + (tmp715[i]).coeffs[2:order + 1] .= zero((tmp715[i]).coeffs[1]) + (r_p2[i]).coeffs[1] = constant_term(tmp713[i]) + constant_term(tmp715[i]) + (r_p2[i]).coeffs[2:order + 1] .= zero((r_p2[i]).coeffs[1]) + (r_p1d2[i]).coeffs[1] = sqrt(constant_term(r_p2[i])) + (r_p1d2[i]).coeffs[2:order + 1] .= zero((r_p1d2[i]).coeffs[1]) + (r_p3d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(1.5)) + (r_p3d2[i]).coeffs[2:order + 1] .= zero((r_p3d2[i]).coeffs[1]) + (r_p7d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(3.5)) + (r_p7d2[i]).coeffs[2:order + 1] .= zero((r_p7d2[i]).coeffs[1]) + (newtonianCoeff[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p3d2[i]) + (newtonianCoeff[i]).coeffs[2:order + 1] .= zero((newtonianCoeff[i]).coeffs[1]) + (tmp723[i]).coeffs[1] = constant_term(pn2x[i]) + constant_term(pn2y[i]) + (tmp723[i]).coeffs[2:order + 1] .= zero((tmp723[i]).coeffs[1]) + (tmp724[i]).coeffs[1] = constant_term(tmp723[i]) + constant_term(pn2z[i]) + (tmp724[i]).coeffs[2:order + 1] .= zero((tmp724[i]).coeffs[1]) + (pn2[i]).coeffs[1] = constant_term(newtonianCoeff[i]) * constant_term(tmp724[i]) + (pn2[i]).coeffs[2:order + 1] .= zero((pn2[i]).coeffs[1]) + (newton_acc_X[i]).coeffs[1] = constant_term(X[i]) * constant_term(newtonianCoeff[i]) + (newton_acc_X[i]).coeffs[2:order + 1] .= zero((newton_acc_X[i]).coeffs[1]) + (newton_acc_Y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(newtonianCoeff[i]) + (newton_acc_Y[i]).coeffs[2:order + 1] .= zero((newton_acc_Y[i]).coeffs[1]) + (newton_acc_Z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(newtonianCoeff[i]) + (newton_acc_Z[i]).coeffs[2:order + 1] .= zero((newton_acc_Z[i]).coeffs[1]) + (newtonian1b_Potential[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p1d2[i]) + (newtonian1b_Potential[i]).coeffs[2:order + 1] .= zero((newtonian1b_Potential[i]).coeffs[1]) + (pn3[i]).coeffs[1] = constant_term(3.5) * constant_term(newtonian1b_Potential[i]) + (pn3[i]).coeffs[2:order + 1] .= zero((pn3[i]).coeffs[1]) + (U_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(U[i]) + (U_t_pn2[i]).coeffs[2:order + 1] .= zero((U_t_pn2[i]).coeffs[1]) + (V_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(V[i]) + (V_t_pn2[i]).coeffs[2:order + 1] .= zero((V_t_pn2[i]).coeffs[1]) + (W_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(W[i]) + (W_t_pn2[i]).coeffs[2:order + 1] .= zero((W_t_pn2[i]).coeffs[1]) + if UJ_interaction[i] + (tmp735[i]).coeffs[1] = -(constant_term(X[i])) + (tmp735[i]).coeffs[2:order + 1] .= zero((tmp735[i]).coeffs[1]) + (t31[i]).coeffs[1] = constant_term(tmp735[i]) * constant_term(M_[1, 3, i]) + (t31[i]).coeffs[2:order + 1] .= zero((t31[i]).coeffs[1]) + (tmp737[i]).coeffs[1] = -(constant_term(Y[i])) + (tmp737[i]).coeffs[2:order + 1] .= zero((tmp737[i]).coeffs[1]) + (t32[i]).coeffs[1] = constant_term(tmp737[i]) * constant_term(M_[2, 3, i]) + (t32[i]).coeffs[2:order + 1] .= zero((t32[i]).coeffs[1]) + (tmp739[i]).coeffs[1] = -(constant_term(Z[i])) + (tmp739[i]).coeffs[2:order + 1] .= zero((tmp739[i]).coeffs[1]) + (t33[i]).coeffs[1] = constant_term(tmp739[i]) * constant_term(M_[3, 3, i]) + (t33[i]).coeffs[2:order + 1] .= zero((t33[i]).coeffs[1]) + (tmp741[i]).coeffs[1] = constant_term(t31[i]) + constant_term(t32[i]) + (tmp741[i]).coeffs[2:order + 1] .= zero((tmp741[i]).coeffs[1]) + (r_sin_ϕ[i]).coeffs[1] = constant_term(tmp741[i]) + constant_term(t33[i]) + (r_sin_ϕ[i]).coeffs[2:order + 1] .= zero((r_sin_ϕ[i]).coeffs[1]) + (sin_ϕ[i]).coeffs[1] = constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]) + (sin_ϕ[i]).coeffs[2:order + 1] .= zero((sin_ϕ[i]).coeffs[1]) + (ϕ[i]).coeffs[1] = asin(constant_term(sin_ϕ[i])) + (ϕ[i]).coeffs[2:order + 1] .= zero((ϕ[i]).coeffs[1]) + (tmp948[i]).coeffs[1] = sqrt(1 - constant_term(sin_ϕ[i]) ^ 2) + (tmp948[i]).coeffs[2:order + 1] .= zero((tmp948[i]).coeffs[1]) + (cos_ϕ[i]).coeffs[1] = cos(constant_term(ϕ[i])) + (cos_ϕ[i]).coeffs[2:order + 1] .= zero((cos_ϕ[i]).coeffs[1]) + (tmp949[i]).coeffs[1] = sin(constant_term(ϕ[i])) + (tmp949[i]).coeffs[2:order + 1] .= zero((tmp949[i]).coeffs[1]) + (sin2_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(2)) + (sin2_ϕ[i]).coeffs[2:order + 1] .= zero((sin2_ϕ[i]).coeffs[1]) + (sin3_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(3)) + (sin3_ϕ[i]).coeffs[2:order + 1] .= zero((sin3_ϕ[i]).coeffs[1]) + (tmp751[i]).coeffs[1] = constant_term(1.5) * constant_term(sin2_ϕ[i]) + (tmp751[i]).coeffs[2:order + 1] .= zero((tmp751[i]).coeffs[1]) + (P_2_sin_ϕ[i]).coeffs[1] = constant_term(tmp751[i]) - constant_term(0.5) + (P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_2_sin_ϕ[i]).coeffs[1]) + (∂P_2_sin_ϕ[i]).coeffs[1] = constant_term(3) * constant_term(sin_ϕ[i]) + (∂P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_2_sin_ϕ[i]).coeffs[1]) + (tmp757[i]).coeffs[1] = constant_term(-1.5) * constant_term(sin_ϕ[i]) + (tmp757[i]).coeffs[2:order + 1] .= zero((tmp757[i]).coeffs[1]) + (tmp759[i]).coeffs[1] = constant_term(2.5) * constant_term(sin3_ϕ[i]) + (tmp759[i]).coeffs[2:order + 1] .= zero((tmp759[i]).coeffs[1]) + (P_3_sin_ϕ[i]).coeffs[1] = constant_term(tmp757[i]) + constant_term(tmp759[i]) + (P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_3_sin_ϕ[i]).coeffs[1]) + (tmp763[i]).coeffs[1] = constant_term(7.5) * constant_term(sin2_ϕ[i]) + (tmp763[i]).coeffs[2:order + 1] .= zero((tmp763[i]).coeffs[1]) + (∂P_3_sin_ϕ[i]).coeffs[1] = constant_term(-1.5) + constant_term(tmp763[i]) + (∂P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_3_sin_ϕ[i]).coeffs[1]) + (tmp766[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(2)) + (tmp766[i]).coeffs[2:order + 1] .= zero((tmp766[i]).coeffs[1]) + (tmp767[i]).coeffs[1] = constant_term(Λ2[i]) / constant_term(tmp766[i]) + (tmp767[i]).coeffs[2:order + 1] .= zero((tmp767[i]).coeffs[1]) + (Λ2j_div_r4[i]).coeffs[1] = -(constant_term(tmp767[i])) + (Λ2j_div_r4[i]).coeffs[2:order + 1] .= zero((Λ2j_div_r4[i]).coeffs[1]) + (tmp770[i]).coeffs[1] = constant_term(r_p1d2[i]) ^ float(constant_term(5)) + (tmp770[i]).coeffs[2:order + 1] .= zero((tmp770[i]).coeffs[1]) + (tmp771[i]).coeffs[1] = constant_term(Λ3[i]) / constant_term(tmp770[i]) + (tmp771[i]).coeffs[2:order + 1] .= zero((tmp771[i]).coeffs[1]) + (Λ3j_div_r5[i]).coeffs[1] = -(constant_term(tmp771[i])) + (Λ3j_div_r5[i]).coeffs[2:order + 1] .= zero((Λ3j_div_r5[i]).coeffs[1]) + (tmp773[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) + (tmp773[i]).coeffs[2:order + 1] .= zero((tmp773[i]).coeffs[1]) + (m_c_ϕ_∂P_2[i]).coeffs[1] = constant_term(tmp773[i]) * constant_term(∂P_2_sin_ϕ[i]) + (m_c_ϕ_∂P_2[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_2[i]).coeffs[1]) + (tmp775[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) + (tmp775[i]).coeffs[2:order + 1] .= zero((tmp775[i]).coeffs[1]) + (m_c_ϕ_∂P_3[i]).coeffs[1] = constant_term(tmp775[i]) * constant_term(∂P_3_sin_ϕ[i]) + (m_c_ϕ_∂P_3[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_3[i]).coeffs[1]) + (tmp778[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(3) + (tmp778[i]).coeffs[2:order + 1] .= zero((tmp778[i]).coeffs[1]) + (F_J2_ξ[i]).coeffs[1] = constant_term(tmp778[i]) * constant_term(P_2_sin_ϕ[i]) + (F_J2_ξ[i]).coeffs[2:order + 1] .= zero((F_J2_ξ[i]).coeffs[1]) + (F_J2_ζ[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]) + (F_J2_ζ[i]).coeffs[2:order + 1] .= zero((F_J2_ζ[i]).coeffs[1]) + (tmp782[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(4) + (tmp782[i]).coeffs[2:order + 1] .= zero((tmp782[i]).coeffs[1]) + (F_J3_ξ[i]).coeffs[1] = constant_term(tmp782[i]) * constant_term(P_3_sin_ϕ[i]) + (F_J3_ξ[i]).coeffs[2:order + 1] .= zero((F_J3_ξ[i]).coeffs[1]) + (F_J3_ζ[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]) + (F_J3_ζ[i]).coeffs[2:order + 1] .= zero((F_J3_ζ[i]).coeffs[1]) + (F_J_ξ[i]).coeffs[1] = identity(constant_term(F_J2_ξ[i])) + (F_J_ξ[i]).coeffs[2:order + 1] .= zero((F_J_ξ[i]).coeffs[1]) + (F_J_ζ[i]).coeffs[1] = identity(constant_term(F_J2_ζ[i])) + (F_J_ζ[i]).coeffs[2:order + 1] .= zero((F_J_ζ[i]).coeffs[1]) + (tmp785[i]).coeffs[1] = -(constant_term(X[i])) + (tmp785[i]).coeffs[2:order + 1] .= zero((tmp785[i]).coeffs[1]) + (ξx[i]).coeffs[1] = constant_term(tmp785[i]) / constant_term(r_p1d2[i]) + (ξx[i]).coeffs[2:order + 1] .= zero((ξx[i]).coeffs[1]) + (tmp787[i]).coeffs[1] = -(constant_term(Y[i])) + (tmp787[i]).coeffs[2:order + 1] .= zero((tmp787[i]).coeffs[1]) + (ξy[i]).coeffs[1] = constant_term(tmp787[i]) / constant_term(r_p1d2[i]) + (ξy[i]).coeffs[2:order + 1] .= zero((ξy[i]).coeffs[1]) + (tmp789[i]).coeffs[1] = -(constant_term(Z[i])) + (tmp789[i]).coeffs[2:order + 1] .= zero((tmp789[i]).coeffs[1]) + (ξz[i]).coeffs[1] = constant_term(tmp789[i]) / constant_term(r_p1d2[i]) + (ξz[i]).coeffs[2:order + 1] .= zero((ξz[i]).coeffs[1]) + (ηx1[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξz[i]) + (ηx1[i]).coeffs[2:order + 1] .= zero((ηx1[i]).coeffs[1]) + (ηy1[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξx[i]) + (ηy1[i]).coeffs[2:order + 1] .= zero((ηy1[i]).coeffs[1]) + (ηz1[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξy[i]) + (ηz1[i]).coeffs[2:order + 1] .= zero((ηz1[i]).coeffs[1]) + (ηx2[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξy[i]) + (ηx2[i]).coeffs[2:order + 1] .= zero((ηx2[i]).coeffs[1]) + (ηy2[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξz[i]) + (ηy2[i]).coeffs[2:order + 1] .= zero((ηy2[i]).coeffs[1]) + (ηz2[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξx[i]) + (ηz2[i]).coeffs[2:order + 1] .= zero((ηz2[i]).coeffs[1]) + (ηx[i]).coeffs[1] = constant_term(ηx1[i]) - constant_term(ηx2[i]) + (ηx[i]).coeffs[2:order + 1] .= zero((ηx[i]).coeffs[1]) + (ηy[i]).coeffs[1] = constant_term(ηy1[i]) - constant_term(ηy2[i]) + (ηy[i]).coeffs[2:order + 1] .= zero((ηy[i]).coeffs[1]) + (ηz[i]).coeffs[1] = constant_term(ηz1[i]) - constant_term(ηz2[i]) + (ηz[i]).coeffs[2:order + 1] .= zero((ηz[i]).coeffs[1]) + (ζx1[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηz[i]) + (ζx1[i]).coeffs[2:order + 1] .= zero((ζx1[i]).coeffs[1]) + (ζy1[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηx[i]) + (ζy1[i]).coeffs[2:order + 1] .= zero((ζy1[i]).coeffs[1]) + (ζz1[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηy[i]) + (ζz1[i]).coeffs[2:order + 1] .= zero((ζz1[i]).coeffs[1]) + (ζx2[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηy[i]) + (ζx2[i]).coeffs[2:order + 1] .= zero((ζx2[i]).coeffs[1]) + (ζy2[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηz[i]) + (ζy2[i]).coeffs[2:order + 1] .= zero((ζy2[i]).coeffs[1]) + (ζz2[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηx[i]) + (ζz2[i]).coeffs[2:order + 1] .= zero((ζz2[i]).coeffs[1]) + (ζx[i]).coeffs[1] = constant_term(ζx1[i]) - constant_term(ζx2[i]) + (ζx[i]).coeffs[2:order + 1] .= zero((ζx[i]).coeffs[1]) + (ζy[i]).coeffs[1] = constant_term(ζy1[i]) - constant_term(ζy2[i]) + (ζy[i]).coeffs[2:order + 1] .= zero((ζy[i]).coeffs[1]) + (ζz[i]).coeffs[1] = constant_term(ζz1[i]) - constant_term(ζz2[i]) + (ζz[i]).coeffs[2:order + 1] .= zero((ζz[i]).coeffs[1]) + (F_J2_x1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξx[i]) + (F_J2_x1[i]).coeffs[2:order + 1] .= zero((F_J2_x1[i]).coeffs[1]) + (F_J2_y1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξy[i]) + (F_J2_y1[i]).coeffs[2:order + 1] .= zero((F_J2_y1[i]).coeffs[1]) + (F_J2_z1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξz[i]) + (F_J2_z1[i]).coeffs[2:order + 1] .= zero((F_J2_z1[i]).coeffs[1]) + (F_J2_x2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζx[i]) + (F_J2_x2[i]).coeffs[2:order + 1] .= zero((F_J2_x2[i]).coeffs[1]) + (F_J2_y2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζy[i]) + (F_J2_y2[i]).coeffs[2:order + 1] .= zero((F_J2_y2[i]).coeffs[1]) + (F_J2_z2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζz[i]) + (F_J2_z2[i]).coeffs[2:order + 1] .= zero((F_J2_z2[i]).coeffs[1]) + (F_J2_x[i]).coeffs[1] = constant_term(F_J2_x1[i]) + constant_term(F_J2_x2[i]) + (F_J2_x[i]).coeffs[2:order + 1] .= zero((F_J2_x[i]).coeffs[1]) + (F_J2_y[i]).coeffs[1] = constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]) + (F_J2_y[i]).coeffs[2:order + 1] .= zero((F_J2_y[i]).coeffs[1]) + (F_J2_z[i]).coeffs[1] = constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]) + (F_J2_z[i]).coeffs[2:order + 1] .= zero((F_J2_z[i]).coeffs[1]) + end + (tmp819[i]).coeffs[1] = constant_term(ui[i]) ^ float(constant_term(2)) + (tmp819[i]).coeffs[2:order + 1] .= zero((tmp819[i]).coeffs[1]) + (tmp821[i]).coeffs[1] = constant_term(vi[i]) ^ float(constant_term(2)) + (tmp821[i]).coeffs[2:order + 1] .= zero((tmp821[i]).coeffs[1]) + (tmp822[i]).coeffs[1] = constant_term(tmp819[i]) + constant_term(tmp821[i]) + (tmp822[i]).coeffs[2:order + 1] .= zero((tmp822[i]).coeffs[1]) + (tmp824[i]).coeffs[1] = constant_term(wi[i]) ^ float(constant_term(2)) + (tmp824[i]).coeffs[2:order + 1] .= zero((tmp824[i]).coeffs[1]) + (v2[i]).coeffs[1] = constant_term(tmp822[i]) + constant_term(tmp824[i]) + (v2[i]).coeffs[2:order + 1] .= zero((v2[i]).coeffs[1]) + end + tmp827.coeffs[1] = constant_term(q[4]) ^ float(constant_term(2)) + tmp827.coeffs[2:order + 1] .= zero(tmp827.coeffs[1]) + tmp829.coeffs[1] = constant_term(q[5]) ^ float(constant_term(2)) + tmp829.coeffs[2:order + 1] .= zero(tmp829.coeffs[1]) + tmp830.coeffs[1] = constant_term(tmp827) + constant_term(tmp829) + tmp830.coeffs[2:order + 1] .= zero(tmp830.coeffs[1]) + tmp832.coeffs[1] = constant_term(q[6]) ^ float(constant_term(2)) + tmp832.coeffs[2:order + 1] .= zero(tmp832.coeffs[1]) + (v2[N]).coeffs[1] = constant_term(tmp830) + constant_term(tmp832) + (v2[N]).coeffs[2:order + 1] .= zero((v2[N]).coeffs[1]) + for i = 1:Nm1 + (temp_004[i]).coeffs[1] = constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]) + (temp_004[i]).coeffs[2:order + 1] .= zero((temp_004[i]).coeffs[1]) + (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(temp_004[i])) + (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) + if UJ_interaction[i] + (tmp835[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_x[i]) + (tmp835[i]).coeffs[2:order + 1] .= zero((tmp835[i]).coeffs[1]) + (temp_accX_i[i]).coeffs[1] = constant_term(accX) - constant_term(tmp835[i]) + (temp_accX_i[i]).coeffs[2:order + 1] .= zero((temp_accX_i[i]).coeffs[1]) + accX.coeffs[1] = identity(constant_term(temp_accX_i[i])) + accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) + (tmp837[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_y[i]) + (tmp837[i]).coeffs[2:order + 1] .= zero((tmp837[i]).coeffs[1]) + (temp_accY_i[i]).coeffs[1] = constant_term(accY) - constant_term(tmp837[i]) + (temp_accY_i[i]).coeffs[2:order + 1] .= zero((temp_accY_i[i]).coeffs[1]) + accY.coeffs[1] = identity(constant_term(temp_accY_i[i])) + accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) + (tmp839[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_z[i]) + (tmp839[i]).coeffs[2:order + 1] .= zero((tmp839[i]).coeffs[1]) + (temp_accZ_i[i]).coeffs[1] = constant_term(accZ) - constant_term(tmp839[i]) + (temp_accZ_i[i]).coeffs[2:order + 1] .= zero((temp_accZ_i[i]).coeffs[1]) + accZ.coeffs[1] = identity(constant_term(temp_accZ_i[i])) + accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) + end + end + (_4ϕj[N]).coeffs[1] = constant_term(4) * constant_term(newtonianNb_Potential[N]) + (_4ϕj[N]).coeffs[2:order + 1] .= zero((_4ϕj[N]).coeffs[1]) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 + (ϕi_plus_4ϕj[i]).coeffs[1] = constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]) + (ϕi_plus_4ϕj[i]).coeffs[2:order + 1] .= zero((ϕi_plus_4ϕj[i]).coeffs[1]) + (tmp845[i]).coeffs[1] = constant_term(2) * constant_term(v2[i]) + (tmp845[i]).coeffs[2:order + 1] .= zero((tmp845[i]).coeffs[1]) + (tmp847[i]).coeffs[1] = constant_term(4) * constant_term(vi_dot_vj[i]) + (tmp847[i]).coeffs[2:order + 1] .= zero((tmp847[i]).coeffs[1]) + (tmp848[i]).coeffs[1] = constant_term(tmp845[i]) - constant_term(tmp847[i]) + (tmp848[i]).coeffs[2:order + 1] .= zero((tmp848[i]).coeffs[1]) + (sj2_plus_2si2_minus_4vivj[i]).coeffs[1] = constant_term(tmp848[i]) + constant_term(v2[N]) + (sj2_plus_2si2_minus_4vivj[i]).coeffs[2:order + 1] .= zero((sj2_plus_2si2_minus_4vivj[i]).coeffs[1]) + (ϕs_and_vs[i]).coeffs[1] = constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]) + (ϕs_and_vs[i]).coeffs[2:order + 1] .= zero((ϕs_and_vs[i]).coeffs[1]) + (Xij_t_Ui[i]).coeffs[1] = constant_term(X[i]) * constant_term(ui[i]) + (Xij_t_Ui[i]).coeffs[2:order + 1] .= zero((Xij_t_Ui[i]).coeffs[1]) + (Yij_t_Vi[i]).coeffs[1] = constant_term(Y[i]) * constant_term(vi[i]) + (Yij_t_Vi[i]).coeffs[2:order + 1] .= zero((Yij_t_Vi[i]).coeffs[1]) + (Zij_t_Wi[i]).coeffs[1] = constant_term(Z[i]) * constant_term(wi[i]) + (Zij_t_Wi[i]).coeffs[2:order + 1] .= zero((Zij_t_Wi[i]).coeffs[1]) + (tmp854[i]).coeffs[1] = constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]) + (tmp854[i]).coeffs[2:order + 1] .= zero((tmp854[i]).coeffs[1]) + (Rij_dot_Vi[i]).coeffs[1] = constant_term(tmp854[i]) + constant_term(Zij_t_Wi[i]) + (Rij_dot_Vi[i]).coeffs[2:order + 1] .= zero((Rij_dot_Vi[i]).coeffs[1]) + (tmp857[i]).coeffs[1] = constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)) + (tmp857[i]).coeffs[2:order + 1] .= zero((tmp857[i]).coeffs[1]) + (pn1t7[i]).coeffs[1] = constant_term(tmp857[i]) / constant_term(r_p2[i]) + (pn1t7[i]).coeffs[2:order + 1] .= zero((pn1t7[i]).coeffs[1]) + (tmp860[i]).coeffs[1] = constant_term(1.5) * constant_term(pn1t7[i]) + (tmp860[i]).coeffs[2:order + 1] .= zero((tmp860[i]).coeffs[1]) + (pn1t2_7[i]).coeffs[1] = constant_term(ϕs_and_vs[i]) - constant_term(tmp860[i]) + (pn1t2_7[i]).coeffs[2:order + 1] .= zero((pn1t2_7[i]).coeffs[1]) + (pn1t1_7[i]).coeffs[1] = constant_term(c_p2) + constant_term(pn1t2_7[i]) + (pn1t1_7[i]).coeffs[2:order + 1] .= zero((pn1t1_7[i]).coeffs[1]) + (pNX_t_X[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(X[i]) + (pNX_t_X[i]).coeffs[2:order + 1] .= zero((pNX_t_X[i]).coeffs[1]) + (pNY_t_Y[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(Y[i]) + (pNY_t_Y[i]).coeffs[2:order + 1] .= zero((pNY_t_Y[i]).coeffs[1]) + (pNZ_t_Z[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(Z[i]) + (pNZ_t_Z[i]).coeffs[2:order + 1] .= zero((pNZ_t_Z[i]).coeffs[1]) + (tmp867[i]).coeffs[1] = constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]) + (tmp867[i]).coeffs[2:order + 1] .= zero((tmp867[i]).coeffs[1]) + (tmp868[i]).coeffs[1] = constant_term(tmp867[i]) + constant_term(pNZ_t_Z[i]) + (tmp868[i]).coeffs[2:order + 1] .= zero((tmp868[i]).coeffs[1]) + (tmp869[i]).coeffs[1] = constant_term(0.5) * constant_term(tmp868[i]) + (tmp869[i]).coeffs[2:order + 1] .= zero((tmp869[i]).coeffs[1]) + (pn1[i]).coeffs[1] = constant_term(pn1t1_7[i]) + constant_term(tmp869[i]) + (pn1[i]).coeffs[2:order + 1] .= zero((pn1[i]).coeffs[1]) + (X_t_pn1[i]).coeffs[1] = constant_term(newton_acc_X[i]) * constant_term(pn1[i]) + (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) + (Y_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Y[i]) * constant_term(pn1[i]) + (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) + (Z_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Z[i]) * constant_term(pn1[i]) + (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) + (pNX_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(pn3[i]) + (pNX_t_pn3[i]).coeffs[2:order + 1] .= zero((pNX_t_pn3[i]).coeffs[1]) + (pNY_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]) + (pNY_t_pn3[i]).coeffs[2:order + 1] .= zero((pNY_t_pn3[i]).coeffs[1]) + (pNZ_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(pn3[i]) + (pNZ_t_pn3[i]).coeffs[2:order + 1] .= zero((pNZ_t_pn3[i]).coeffs[1]) + end + for i = 1:10 + (tmp877[i]).coeffs[1] = constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]) + (tmp877[i]).coeffs[2:order + 1] .= zero((tmp877[i]).coeffs[1]) + (termpnx[i]).coeffs[1] = constant_term(X_t_pn1[i]) + constant_term(tmp877[i]) + (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) + (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) + (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) + pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) + pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) + (tmp880[i]).coeffs[1] = constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]) + (tmp880[i]).coeffs[2:order + 1] .= zero((tmp880[i]).coeffs[1]) + (termpny[i]).coeffs[1] = constant_term(Y_t_pn1[i]) + constant_term(tmp880[i]) + (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) + (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) + (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) + pntempY.coeffs[1] = identity(constant_term(sumpny[i])) + pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) + (tmp883[i]).coeffs[1] = constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]) + (tmp883[i]).coeffs[2:order + 1] .= zero((tmp883[i]).coeffs[1]) + (termpnz[i]).coeffs[1] = constant_term(Z_t_pn1[i]) + constant_term(tmp883[i]) + (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) + (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) + (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) + pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) + pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) + end + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 + (X_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_X[i]) + (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) + (Y_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Y[i]) + (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) + (Z_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Z[i]) + (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) + end + for i = 11:Nm1 + (termpnx[i]).coeffs[1] = identity(constant_term(X_t_pn1[i])) + (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) + (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) + (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) + pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) + pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) + (termpny[i]).coeffs[1] = identity(constant_term(Y_t_pn1[i])) + (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) + (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) + (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) + pntempY.coeffs[1] = identity(constant_term(sumpny[i])) + pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) + (termpnz[i]).coeffs[1] = identity(constant_term(Z_t_pn1[i])) + (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) + (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) + (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) + pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) + pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) + end + postNewtonX.coeffs[1] = constant_term(pntempX) * constant_term(c_m2) + postNewtonX.coeffs[2:order + 1] .= zero(postNewtonX.coeffs[1]) + postNewtonY.coeffs[1] = constant_term(pntempY) * constant_term(c_m2) + postNewtonY.coeffs[2:order + 1] .= zero(postNewtonY.coeffs[1]) + postNewtonZ.coeffs[1] = constant_term(pntempZ) * constant_term(c_m2) + postNewtonZ.coeffs[2:order + 1] .= zero(postNewtonZ.coeffs[1]) + tmp895.coeffs[1] = constant_term(Y[1]) * constant_term(W[1]) + tmp895.coeffs[2:order + 1] .= zero(tmp895.coeffs[1]) + tmp896.coeffs[1] = constant_term(Z[1]) * constant_term(V[1]) + tmp896.coeffs[2:order + 1] .= zero(tmp896.coeffs[1]) + hx.coeffs[1] = constant_term(tmp895) - constant_term(tmp896) + hx.coeffs[2:order + 1] .= zero(hx.coeffs[1]) + tmp898.coeffs[1] = constant_term(Z[1]) * constant_term(U[1]) + tmp898.coeffs[2:order + 1] .= zero(tmp898.coeffs[1]) + tmp899.coeffs[1] = constant_term(X[1]) * constant_term(W[1]) + tmp899.coeffs[2:order + 1] .= zero(tmp899.coeffs[1]) + hy.coeffs[1] = constant_term(tmp898) - constant_term(tmp899) + hy.coeffs[2:order + 1] .= zero(hy.coeffs[1]) + tmp901.coeffs[1] = constant_term(X[1]) * constant_term(V[1]) + tmp901.coeffs[2:order + 1] .= zero(tmp901.coeffs[1]) + tmp902.coeffs[1] = constant_term(Y[1]) * constant_term(U[1]) + tmp902.coeffs[2:order + 1] .= zero(tmp902.coeffs[1]) + hz.coeffs[1] = constant_term(tmp901) - constant_term(tmp902) + hz.coeffs[2:order + 1] .= zero(hz.coeffs[1]) + tmp904.coeffs[1] = constant_term(hz) * constant_term(Y[1]) + tmp904.coeffs[2:order + 1] .= zero(tmp904.coeffs[1]) + tmp905.coeffs[1] = constant_term(hy) * constant_term(Z[1]) + tmp905.coeffs[2:order + 1] .= zero(tmp905.coeffs[1]) + t_x.coeffs[1] = constant_term(tmp904) - constant_term(tmp905) + t_x.coeffs[2:order + 1] .= zero(t_x.coeffs[1]) + tmp907.coeffs[1] = constant_term(hx) * constant_term(Z[1]) + tmp907.coeffs[2:order + 1] .= zero(tmp907.coeffs[1]) + tmp908.coeffs[1] = constant_term(hz) * constant_term(X[1]) + tmp908.coeffs[2:order + 1] .= zero(tmp908.coeffs[1]) + t_y.coeffs[1] = constant_term(tmp907) - constant_term(tmp908) + t_y.coeffs[2:order + 1] .= zero(t_y.coeffs[1]) + tmp910.coeffs[1] = constant_term(hy) * constant_term(X[1]) + tmp910.coeffs[2:order + 1] .= zero(tmp910.coeffs[1]) + tmp911.coeffs[1] = constant_term(hx) * constant_term(Y[1]) + tmp911.coeffs[2:order + 1] .= zero(tmp911.coeffs[1]) + t_z.coeffs[1] = constant_term(tmp910) - constant_term(tmp911) + t_z.coeffs[2:order + 1] .= zero(t_z.coeffs[1]) + tmp914.coeffs[1] = constant_term(t_x) ^ float(constant_term(2)) + tmp914.coeffs[2:order + 1] .= zero(tmp914.coeffs[1]) + tmp916.coeffs[1] = constant_term(t_y) ^ float(constant_term(2)) + tmp916.coeffs[2:order + 1] .= zero(tmp916.coeffs[1]) + tmp917.coeffs[1] = constant_term(tmp914) + constant_term(tmp916) + tmp917.coeffs[2:order + 1] .= zero(tmp917.coeffs[1]) + tmp919.coeffs[1] = constant_term(t_z) ^ float(constant_term(2)) + tmp919.coeffs[2:order + 1] .= zero(tmp919.coeffs[1]) + tmp920.coeffs[1] = constant_term(tmp917) + constant_term(tmp919) + tmp920.coeffs[2:order + 1] .= zero(tmp920.coeffs[1]) + t_norm.coeffs[1] = sqrt(constant_term(tmp920)) + t_norm.coeffs[2:order + 1] .= zero(t_norm.coeffs[1]) + t_x_unit.coeffs[1] = constant_term(t_x) / constant_term(t_norm) + t_x_unit.coeffs[2:order + 1] .= zero(t_x_unit.coeffs[1]) + t_y_unit.coeffs[1] = constant_term(t_y) / constant_term(t_norm) + t_y_unit.coeffs[2:order + 1] .= zero(t_y_unit.coeffs[1]) + t_z_unit.coeffs[1] = constant_term(t_z) / constant_term(t_norm) + t_z_unit.coeffs[2:order + 1] .= zero(t_z_unit.coeffs[1]) + tmp925.coeffs[1] = constant_term(X[1]) / constant_term(r_p1d2[1]) + tmp925.coeffs[2:order + 1] .= zero(tmp925.coeffs[1]) + r_x_unit.coeffs[1] = -(constant_term(tmp925)) + r_x_unit.coeffs[2:order + 1] .= zero(r_x_unit.coeffs[1]) + tmp927.coeffs[1] = constant_term(Y[1]) / constant_term(r_p1d2[1]) + tmp927.coeffs[2:order + 1] .= zero(tmp927.coeffs[1]) + r_y_unit.coeffs[1] = -(constant_term(tmp927)) + r_y_unit.coeffs[2:order + 1] .= zero(r_y_unit.coeffs[1]) + tmp929.coeffs[1] = constant_term(Z[1]) / constant_term(r_p1d2[1]) + tmp929.coeffs[2:order + 1] .= zero(tmp929.coeffs[1]) + r_z_unit.coeffs[1] = -(constant_term(tmp929)) + r_z_unit.coeffs[2:order + 1] .= zero(r_z_unit.coeffs[1]) + g_r.coeffs[1] = identity(constant_term(r_p2[1])) + g_r.coeffs[2:order + 1] .= zero(g_r.coeffs[1]) + A2_t_g_r.coeffs[1] = constant_term(q[7]) / constant_term(g_r) + A2_t_g_r.coeffs[2:order + 1] .= zero(A2_t_g_r.coeffs[1]) + A1_t_g_r.coeffs[1] = constant_term(q[8]) / constant_term(g_r) + A1_t_g_r.coeffs[2:order + 1] .= zero(A1_t_g_r.coeffs[1]) + tmp933.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_x_unit) + tmp933.coeffs[2:order + 1] .= zero(tmp933.coeffs[1]) + tmp934.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_x_unit) + tmp934.coeffs[2:order + 1] .= zero(tmp934.coeffs[1]) + NGAx.coeffs[1] = constant_term(tmp933) + constant_term(tmp934) + NGAx.coeffs[2:order + 1] .= zero(NGAx.coeffs[1]) + tmp936.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_y_unit) + tmp936.coeffs[2:order + 1] .= zero(tmp936.coeffs[1]) + tmp937.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_y_unit) + tmp937.coeffs[2:order + 1] .= zero(tmp937.coeffs[1]) + NGAy.coeffs[1] = constant_term(tmp936) + constant_term(tmp937) + NGAy.coeffs[2:order + 1] .= zero(NGAy.coeffs[1]) + tmp939.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_z_unit) + tmp939.coeffs[2:order + 1] .= zero(tmp939.coeffs[1]) + tmp940.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_z_unit) + tmp940.coeffs[2:order + 1] .= zero(tmp940.coeffs[1]) + NGAz.coeffs[1] = constant_term(tmp939) + constant_term(tmp940) + NGAz.coeffs[2:order + 1] .= zero(NGAz.coeffs[1]) + tmp942.coeffs[1] = constant_term(postNewtonX) + constant_term(accX) + tmp942.coeffs[2:order + 1] .= zero(tmp942.coeffs[1]) + (dq[4]).coeffs[1] = constant_term(tmp942) + constant_term(NGAx) + (dq[4]).coeffs[2:order + 1] .= zero((dq[4]).coeffs[1]) + tmp944.coeffs[1] = constant_term(postNewtonY) + constant_term(accY) + tmp944.coeffs[2:order + 1] .= zero(tmp944.coeffs[1]) + (dq[5]).coeffs[1] = constant_term(tmp944) + constant_term(NGAy) + (dq[5]).coeffs[2:order + 1] .= zero((dq[5]).coeffs[1]) + tmp946.coeffs[1] = constant_term(postNewtonZ) + constant_term(accZ) + tmp946.coeffs[2:order + 1] .= zero(tmp946.coeffs[1]) + (dq[6]).coeffs[1] = constant_term(tmp946) + constant_term(NGAz) + (dq[6]).coeffs[2:order + 1] .= zero((dq[6]).coeffs[1]) + (dq[7]).coeffs[1] = identity(constant_term(zero_q_1)) + (dq[7]).coeffs[2:order + 1] .= zero((dq[7]).coeffs[1]) + for __idx = eachindex(q) + (q[__idx]).coeffs[2] = (dq[__idx]).coeffs[1] + end + for ord = 1:order - 1 + ordnext = ord + 1 + TaylorSeries.identity!(pntempX, zero_q_1, ord) + TaylorSeries.identity!(pntempY, zero_q_1, ord) + TaylorSeries.identity!(pntempZ, zero_q_1, ord) + TaylorSeries.identity!(accX, zero_q_1, ord) + TaylorSeries.identity!(accY, zero_q_1, ord) + TaylorSeries.identity!(accZ, zero_q_1, ord) + TaylorSeries.identity!(dq[1], q[4], ord) + TaylorSeries.identity!(dq[2], q[5], ord) + TaylorSeries.identity!(dq[3], q[6], ord) + TaylorSeries.identity!(newtonianNb_Potential[N], zero_q_1, ord) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 + TaylorSeries.identity!(ui[i], ss16asteph_t[3 * ((N - 1) + i) - 2], ord) + TaylorSeries.identity!(vi[i], ss16asteph_t[3 * ((N - 1) + i) - 1], ord) + TaylorSeries.identity!(wi[i], ss16asteph_t[3 * ((N - 1) + i)], ord) + TaylorSeries.subst!(X[i], ss16asteph_t[3i - 2], q[1], ord) + TaylorSeries.subst!(Y[i], ss16asteph_t[3i - 1], q[2], ord) + TaylorSeries.subst!(Z[i], ss16asteph_t[3i], q[3], ord) + TaylorSeries.subst!(U[i], ui[i], dq[1], ord) + TaylorSeries.subst!(V[i], vi[i], dq[2], ord) + TaylorSeries.subst!(W[i], wi[i], dq[3], ord) + TaylorSeries.mul!(tmp687[1], 4, dq[1], ord) + TaylorSeries.mul!(tmp689[i], 3, ui[i], ord) + TaylorSeries.subst!(_4U_m_3X[i], tmp687[1], tmp689[i], ord) + TaylorSeries.mul!(tmp692[2], 4, dq[2], ord) + TaylorSeries.mul!(tmp694[i], 3, vi[i], ord) + TaylorSeries.subst!(_4V_m_3Y[i], tmp692[2], tmp694[i], ord) + TaylorSeries.mul!(tmp697[3], 4, dq[3], ord) + TaylorSeries.mul!(tmp699[i], 3, wi[i], ord) + TaylorSeries.subst!(_4W_m_3Z[i], tmp697[3], tmp699[i], ord) + TaylorSeries.mul!(pn2x[i], X[i], _4U_m_3X[i], ord) + TaylorSeries.mul!(pn2y[i], Y[i], _4V_m_3Y[i], ord) + TaylorSeries.mul!(pn2z[i], Z[i], _4W_m_3Z[i], ord) + TaylorSeries.mul!(UU[i], ui[i], dq[1], ord) + TaylorSeries.mul!(VV[i], vi[i], dq[2], ord) + TaylorSeries.mul!(WW[i], wi[i], dq[3], ord) + TaylorSeries.add!(tmp707[i], UU[i], VV[i], ord) + TaylorSeries.add!(vi_dot_vj[i], tmp707[i], WW[i], ord) + TaylorSeries.pow!(tmp710[i], X[i], 2, ord) + TaylorSeries.pow!(tmp712[i], Y[i], 2, ord) + TaylorSeries.add!(tmp713[i], tmp710[i], tmp712[i], ord) + TaylorSeries.pow!(tmp715[i], Z[i], 2, ord) + TaylorSeries.add!(r_p2[i], tmp713[i], tmp715[i], ord) + TaylorSeries.sqrt!(r_p1d2[i], r_p2[i], ord) + TaylorSeries.pow!(r_p3d2[i], r_p2[i], 1.5, ord) + TaylorSeries.pow!(r_p7d2[i], r_p2[i], 3.5, ord) + TaylorSeries.div!(newtonianCoeff[i], μ[i], r_p3d2[i], ord) + TaylorSeries.add!(tmp723[i], pn2x[i], pn2y[i], ord) + TaylorSeries.add!(tmp724[i], tmp723[i], pn2z[i], ord) + TaylorSeries.mul!(pn2[i], newtonianCoeff[i], tmp724[i], ord) + TaylorSeries.mul!(newton_acc_X[i], X[i], newtonianCoeff[i], ord) + TaylorSeries.mul!(newton_acc_Y[i], Y[i], newtonianCoeff[i], ord) + TaylorSeries.mul!(newton_acc_Z[i], Z[i], newtonianCoeff[i], ord) + TaylorSeries.div!(newtonian1b_Potential[i], μ[i], r_p1d2[i], ord) + TaylorSeries.mul!(pn3[i], 3.5, newtonian1b_Potential[i], ord) + TaylorSeries.mul!(U_t_pn2[i], pn2[i], U[i], ord) + TaylorSeries.mul!(V_t_pn2[i], pn2[i], V[i], ord) + TaylorSeries.mul!(W_t_pn2[i], pn2[i], W[i], ord) + if UJ_interaction[i] + TaylorSeries.subst!(tmp735[i], X[i], ord) + TaylorSeries.mul!(t31[i], tmp735[i], M_[1, 3, i], ord) + TaylorSeries.subst!(tmp737[i], Y[i], ord) + TaylorSeries.mul!(t32[i], tmp737[i], M_[2, 3, i], ord) + TaylorSeries.subst!(tmp739[i], Z[i], ord) + TaylorSeries.mul!(t33[i], tmp739[i], M_[3, 3, i], ord) + TaylorSeries.add!(tmp741[i], t31[i], t32[i], ord) + TaylorSeries.add!(r_sin_ϕ[i], tmp741[i], t33[i], ord) + TaylorSeries.div!(sin_ϕ[i], r_sin_ϕ[i], r_p1d2[i], ord) + TaylorSeries.asin!(ϕ[i], sin_ϕ[i], tmp948[i], ord) + TaylorSeries.sincos!(tmp949[i], cos_ϕ[i], ϕ[i], ord) + TaylorSeries.pow!(sin2_ϕ[i], sin_ϕ[i], 2, ord) + TaylorSeries.pow!(sin3_ϕ[i], sin_ϕ[i], 3, ord) + TaylorSeries.mul!(tmp751[i], 1.5, sin2_ϕ[i], ord) + TaylorSeries.subst!(P_2_sin_ϕ[i], tmp751[i], 0.5, ord) + TaylorSeries.mul!(∂P_2_sin_ϕ[i], 3, sin_ϕ[i], ord) + TaylorSeries.mul!(tmp757[i], -1.5, sin_ϕ[i], ord) + TaylorSeries.mul!(tmp759[i], 2.5, sin3_ϕ[i], ord) + TaylorSeries.add!(P_3_sin_ϕ[i], tmp757[i], tmp759[i], ord) + TaylorSeries.mul!(tmp763[i], 7.5, sin2_ϕ[i], ord) + TaylorSeries.add!(∂P_3_sin_ϕ[i], -1.5, tmp763[i], ord) + TaylorSeries.pow!(tmp766[i], r_p2[i], 2, ord) + TaylorSeries.div!(tmp767[i], Λ2[i], tmp766[i], ord) + TaylorSeries.subst!(Λ2j_div_r4[i], tmp767[i], ord) + TaylorSeries.pow!(tmp770[i], r_p1d2[i], 5, ord) + TaylorSeries.div!(tmp771[i], Λ3[i], tmp770[i], ord) + TaylorSeries.subst!(Λ3j_div_r5[i], tmp771[i], ord) + TaylorSeries.subst!(tmp773[i], cos_ϕ[i], ord) + TaylorSeries.mul!(m_c_ϕ_∂P_2[i], tmp773[i], ∂P_2_sin_ϕ[i], ord) + TaylorSeries.subst!(tmp775[i], cos_ϕ[i], ord) + TaylorSeries.mul!(m_c_ϕ_∂P_3[i], tmp775[i], ∂P_3_sin_ϕ[i], ord) + TaylorSeries.mul!(tmp778[i], Λ2j_div_r4[i], 3, ord) + TaylorSeries.mul!(F_J2_ξ[i], tmp778[i], P_2_sin_ϕ[i], ord) + TaylorSeries.mul!(F_J2_ζ[i], Λ2j_div_r4[i], m_c_ϕ_∂P_2[i], ord) + TaylorSeries.mul!(tmp782[i], Λ3j_div_r5[i], 4, ord) + TaylorSeries.mul!(F_J3_ξ[i], tmp782[i], P_3_sin_ϕ[i], ord) + TaylorSeries.mul!(F_J3_ζ[i], Λ3j_div_r5[i], m_c_ϕ_∂P_3[i], ord) + TaylorSeries.identity!(F_J_ξ[i], F_J2_ξ[i], ord) + TaylorSeries.identity!(F_J_ζ[i], F_J2_ζ[i], ord) + TaylorSeries.subst!(tmp785[i], X[i], ord) + TaylorSeries.div!(ξx[i], tmp785[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp787[i], Y[i], ord) + TaylorSeries.div!(ξy[i], tmp787[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp789[i], Z[i], ord) + TaylorSeries.div!(ξz[i], tmp789[i], r_p1d2[i], ord) + TaylorSeries.mul!(ηx1[i], M_[2, 3, i], ξz[i], ord) + TaylorSeries.mul!(ηy1[i], M_[3, 3, i], ξx[i], ord) + TaylorSeries.mul!(ηz1[i], M_[1, 3, i], ξy[i], ord) + TaylorSeries.mul!(ηx2[i], M_[3, 3, i], ξy[i], ord) + TaylorSeries.mul!(ηy2[i], M_[1, 3, i], ξz[i], ord) + TaylorSeries.mul!(ηz2[i], M_[2, 3, i], ξx[i], ord) + TaylorSeries.subst!(ηx[i], ηx1[i], ηx2[i], ord) + TaylorSeries.subst!(ηy[i], ηy1[i], ηy2[i], ord) + TaylorSeries.subst!(ηz[i], ηz1[i], ηz2[i], ord) + TaylorSeries.mul!(ζx1[i], ξy[i], ηz[i], ord) + TaylorSeries.mul!(ζy1[i], ξz[i], ηx[i], ord) + TaylorSeries.mul!(ζz1[i], ξx[i], ηy[i], ord) + TaylorSeries.mul!(ζx2[i], ξz[i], ηy[i], ord) + TaylorSeries.mul!(ζy2[i], ξx[i], ηz[i], ord) + TaylorSeries.mul!(ζz2[i], ξy[i], ηx[i], ord) + TaylorSeries.subst!(ζx[i], ζx1[i], ζx2[i], ord) + TaylorSeries.subst!(ζy[i], ζy1[i], ζy2[i], ord) + TaylorSeries.subst!(ζz[i], ζz1[i], ζz2[i], ord) + TaylorSeries.mul!(F_J2_x1[i], F_J_ξ[i], ξx[i], ord) + TaylorSeries.mul!(F_J2_y1[i], F_J_ξ[i], ξy[i], ord) + TaylorSeries.mul!(F_J2_z1[i], F_J_ξ[i], ξz[i], ord) + TaylorSeries.mul!(F_J2_x2[i], F_J_ζ[i], ζx[i], ord) + TaylorSeries.mul!(F_J2_y2[i], F_J_ζ[i], ζy[i], ord) + TaylorSeries.mul!(F_J2_z2[i], F_J_ζ[i], ζz[i], ord) + TaylorSeries.add!(F_J2_x[i], F_J2_x1[i], F_J2_x2[i], ord) + TaylorSeries.add!(F_J2_y[i], F_J2_y1[i], F_J2_y2[i], ord) + TaylorSeries.add!(F_J2_z[i], F_J2_z1[i], F_J2_z2[i], ord) + end + TaylorSeries.pow!(tmp819[i], ui[i], 2, ord) + TaylorSeries.pow!(tmp821[i], vi[i], 2, ord) + TaylorSeries.add!(tmp822[i], tmp819[i], tmp821[i], ord) + TaylorSeries.pow!(tmp824[i], wi[i], 2, ord) + TaylorSeries.add!(v2[i], tmp822[i], tmp824[i], ord) + end + TaylorSeries.pow!(tmp827, q[4], 2, ord) + TaylorSeries.pow!(tmp829, q[5], 2, ord) + TaylorSeries.add!(tmp830, tmp827, tmp829, ord) + TaylorSeries.pow!(tmp832, q[6], 2, ord) + TaylorSeries.add!(v2[N], tmp830, tmp832, ord) + for i = 1:Nm1 + TaylorSeries.add!(temp_004[i], newtonian1b_Potential[i], newtonianNb_Potential[N], ord) + TaylorSeries.identity!(newtonianNb_Potential[N], temp_004[i], ord) + if UJ_interaction[i] + TaylorSeries.mul!(tmp835[i], μ[i], F_J2_x[i], ord) + TaylorSeries.subst!(temp_accX_i[i], accX, tmp835[i], ord) + TaylorSeries.identity!(accX, temp_accX_i[i], ord) + TaylorSeries.mul!(tmp837[i], μ[i], F_J2_y[i], ord) + TaylorSeries.subst!(temp_accY_i[i], accY, tmp837[i], ord) + TaylorSeries.identity!(accY, temp_accY_i[i], ord) + TaylorSeries.mul!(tmp839[i], μ[i], F_J2_z[i], ord) + TaylorSeries.subst!(temp_accZ_i[i], accZ, tmp839[i], ord) + TaylorSeries.identity!(accZ, temp_accZ_i[i], ord) + end + end + TaylorSeries.mul!(_4ϕj[N], 4, newtonianNb_Potential[N], ord) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 + TaylorSeries.add!(ϕi_plus_4ϕj[i], newtonianNb_Potential_t[i], _4ϕj[N], ord) + TaylorSeries.mul!(tmp845[i], 2, v2[i], ord) + TaylorSeries.mul!(tmp847[i], 4, vi_dot_vj[i], ord) + TaylorSeries.subst!(tmp848[i], tmp845[i], tmp847[i], ord) + TaylorSeries.add!(sj2_plus_2si2_minus_4vivj[i], tmp848[i], v2[N], ord) + TaylorSeries.subst!(ϕs_and_vs[i], sj2_plus_2si2_minus_4vivj[i], ϕi_plus_4ϕj[i], ord) + TaylorSeries.mul!(Xij_t_Ui[i], X[i], ui[i], ord) + TaylorSeries.mul!(Yij_t_Vi[i], Y[i], vi[i], ord) + TaylorSeries.mul!(Zij_t_Wi[i], Z[i], wi[i], ord) + TaylorSeries.add!(tmp854[i], Xij_t_Ui[i], Yij_t_Vi[i], ord) + TaylorSeries.add!(Rij_dot_Vi[i], tmp854[i], Zij_t_Wi[i], ord) + TaylorSeries.pow!(tmp857[i], Rij_dot_Vi[i], 2, ord) + TaylorSeries.div!(pn1t7[i], tmp857[i], r_p2[i], ord) + TaylorSeries.mul!(tmp860[i], 1.5, pn1t7[i], ord) + TaylorSeries.subst!(pn1t2_7[i], ϕs_and_vs[i], tmp860[i], ord) + TaylorSeries.add!(pn1t1_7[i], c_p2, pn1t2_7[i], ord) + TaylorSeries.mul!(pNX_t_X[i], acceph_t[3i - 2], X[i], ord) + TaylorSeries.mul!(pNY_t_Y[i], acceph_t[3i - 1], Y[i], ord) + TaylorSeries.mul!(pNZ_t_Z[i], acceph_t[3i], Z[i], ord) + TaylorSeries.add!(tmp867[i], pNX_t_X[i], pNY_t_Y[i], ord) + TaylorSeries.add!(tmp868[i], tmp867[i], pNZ_t_Z[i], ord) + TaylorSeries.mul!(tmp869[i], 0.5, tmp868[i], ord) + TaylorSeries.add!(pn1[i], pn1t1_7[i], tmp869[i], ord) + TaylorSeries.mul!(X_t_pn1[i], newton_acc_X[i], pn1[i], ord) + TaylorSeries.mul!(Y_t_pn1[i], newton_acc_Y[i], pn1[i], ord) + TaylorSeries.mul!(Z_t_pn1[i], newton_acc_Z[i], pn1[i], ord) + TaylorSeries.mul!(pNX_t_pn3[i], acceph_t[3i - 2], pn3[i], ord) + TaylorSeries.mul!(pNY_t_pn3[i], acceph_t[3i - 1], pn3[i], ord) + TaylorSeries.mul!(pNZ_t_pn3[i], acceph_t[3i], pn3[i], ord) + end + for i = 1:10 + TaylorSeries.add!(tmp877[i], U_t_pn2[i], pNX_t_pn3[i], ord) + TaylorSeries.add!(termpnx[i], X_t_pn1[i], tmp877[i], ord) + TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) + TaylorSeries.identity!(pntempX, sumpnx[i], ord) + TaylorSeries.add!(tmp880[i], V_t_pn2[i], pNY_t_pn3[i], ord) + TaylorSeries.add!(termpny[i], Y_t_pn1[i], tmp880[i], ord) + TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) + TaylorSeries.identity!(pntempY, sumpny[i], ord) + TaylorSeries.add!(tmp883[i], W_t_pn2[i], pNZ_t_pn3[i], ord) + TaylorSeries.add!(termpnz[i], Z_t_pn1[i], tmp883[i], ord) + TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) + TaylorSeries.identity!(pntempZ, sumpnz[i], ord) + end + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 + TaylorSeries.mul!(X_t_pn1[i], c_p2, newton_acc_X[i], ord) + TaylorSeries.mul!(Y_t_pn1[i], c_p2, newton_acc_Y[i], ord) + TaylorSeries.mul!(Z_t_pn1[i], c_p2, newton_acc_Z[i], ord) + end + for i = 11:Nm1 + TaylorSeries.identity!(termpnx[i], X_t_pn1[i], ord) + TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) + TaylorSeries.identity!(pntempX, sumpnx[i], ord) + TaylorSeries.identity!(termpny[i], Y_t_pn1[i], ord) + TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) + TaylorSeries.identity!(pntempY, sumpny[i], ord) + TaylorSeries.identity!(termpnz[i], Z_t_pn1[i], ord) + TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) + TaylorSeries.identity!(pntempZ, sumpnz[i], ord) + end + TaylorSeries.mul!(postNewtonX, pntempX, c_m2, ord) + TaylorSeries.mul!(postNewtonY, pntempY, c_m2, ord) + TaylorSeries.mul!(postNewtonZ, pntempZ, c_m2, ord) + TaylorSeries.mul!(tmp895, Y[1], W[1], ord) + TaylorSeries.mul!(tmp896, Z[1], V[1], ord) + TaylorSeries.subst!(hx, tmp895, tmp896, ord) + TaylorSeries.mul!(tmp898, Z[1], U[1], ord) + TaylorSeries.mul!(tmp899, X[1], W[1], ord) + TaylorSeries.subst!(hy, tmp898, tmp899, ord) + TaylorSeries.mul!(tmp901, X[1], V[1], ord) + TaylorSeries.mul!(tmp902, Y[1], U[1], ord) + TaylorSeries.subst!(hz, tmp901, tmp902, ord) + TaylorSeries.mul!(tmp904, hz, Y[1], ord) + TaylorSeries.mul!(tmp905, hy, Z[1], ord) + TaylorSeries.subst!(t_x, tmp904, tmp905, ord) + TaylorSeries.mul!(tmp907, hx, Z[1], ord) + TaylorSeries.mul!(tmp908, hz, X[1], ord) + TaylorSeries.subst!(t_y, tmp907, tmp908, ord) + TaylorSeries.mul!(tmp910, hy, X[1], ord) + TaylorSeries.mul!(tmp911, hx, Y[1], ord) + TaylorSeries.subst!(t_z, tmp910, tmp911, ord) + TaylorSeries.pow!(tmp914, t_x, 2, ord) + TaylorSeries.pow!(tmp916, t_y, 2, ord) + TaylorSeries.add!(tmp917, tmp914, tmp916, ord) + TaylorSeries.pow!(tmp919, t_z, 2, ord) + TaylorSeries.add!(tmp920, tmp917, tmp919, ord) + TaylorSeries.sqrt!(t_norm, tmp920, ord) + TaylorSeries.div!(t_x_unit, t_x, t_norm, ord) + TaylorSeries.div!(t_y_unit, t_y, t_norm, ord) + TaylorSeries.div!(t_z_unit, t_z, t_norm, ord) + TaylorSeries.div!(tmp925, X[1], r_p1d2[1], ord) + TaylorSeries.subst!(r_x_unit, tmp925, ord) + TaylorSeries.div!(tmp927, Y[1], r_p1d2[1], ord) + TaylorSeries.subst!(r_y_unit, tmp927, ord) + TaylorSeries.div!(tmp929, Z[1], r_p1d2[1], ord) + TaylorSeries.subst!(r_z_unit, tmp929, ord) + TaylorSeries.identity!(g_r, r_p2[1], ord) + TaylorSeries.div!(A2_t_g_r, q[7], g_r, ord) + TaylorSeries.div!(A1_t_g_r, q[8], g_r, ord) + TaylorSeries.mul!(tmp933, A2_t_g_r, t_x_unit, ord) + TaylorSeries.mul!(tmp934, A1_t_g_r, r_x_unit, ord) + TaylorSeries.add!(NGAx, tmp933, tmp934, ord) + TaylorSeries.mul!(tmp936, A2_t_g_r, t_y_unit, ord) + TaylorSeries.mul!(tmp937, A1_t_g_r, r_y_unit, ord) + TaylorSeries.add!(NGAy, tmp936, tmp937, ord) + TaylorSeries.mul!(tmp939, A2_t_g_r, t_z_unit, ord) + TaylorSeries.mul!(tmp940, A1_t_g_r, r_z_unit, ord) + TaylorSeries.add!(NGAz, tmp939, tmp940, ord) + TaylorSeries.add!(tmp942, postNewtonX, accX, ord) + TaylorSeries.add!(dq[4], tmp942, NGAx, ord) + TaylorSeries.add!(tmp944, postNewtonY, accY, ord) + TaylorSeries.add!(dq[5], tmp944, NGAy, ord) + TaylorSeries.add!(tmp946, postNewtonZ, accZ, ord) + TaylorSeries.add!(dq[6], tmp946, NGAz, ord) + TaylorSeries.identity!(dq[7], zero_q_1, ord) + for __idx = eachindex(q) + (q[__idx]).coeffs[ordnext + 1] = (dq[__idx]).coeffs[ordnext] / ordnext + end + end + return nothing +end + +# TaylorIntegration._allocate_jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_eph_threads! +function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params) where {_T <: Real, _S <: Number, _N} + order = t.order + local jd0 = params[4] + local dsj2k = t + (jd0 - JD_J2000) + local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) + local acceph_t = evaleph(params[2], dsj2k, q[1]) + local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) + local S = eltype(q) + local UJ_interaction = params[5] + local N = params[6] + local Nm1 = N - 1 + local μ = params[7] + local zero_q_1 = auxzero(q[1]) + X = Array{S}(undef, N) + Y = Array{S}(undef, N) + Z = Array{S}(undef, N) + r_p2 = Array{S}(undef, N) + r_p1d2 = Array{S}(undef, N) + r_p3d2 = Array{S}(undef, N) + r_p7d2 = Array{S}(undef, N) + newtonianCoeff = Array{S}(undef, N) + ui = Array{S}(undef, N - 1) + vi = Array{S}(undef, N - 1) + wi = Array{S}(undef, N - 1) + U = Array{S}(undef, N) + V = Array{S}(undef, N) + W = Array{S}(undef, N) + _4U_m_3X = Array{S}(undef, N) + _4V_m_3Y = Array{S}(undef, N) + _4W_m_3Z = Array{S}(undef, N) + UU = Array{S}(undef, N) + VV = Array{S}(undef, N) + WW = Array{S}(undef, N) + newtonian1b_Potential = Array{S}(undef, N) + newtonianNb_Potential = Array{S}(undef, N) + newton_acc_X = Array{S}(undef, N) + newton_acc_Y = Array{S}(undef, N) + newton_acc_Z = Array{S}(undef, N) + v2 = Array{S}(undef, N) + vi_dot_vj = Array{S}(undef, N) + pn2 = Array{S}(undef, N) + U_t_pn2 = Array{S}(undef, N) + V_t_pn2 = Array{S}(undef, N) + W_t_pn2 = Array{S}(undef, N) + pn3 = Array{S}(undef, N) + pNX_t_pn3 = Array{S}(undef, N) + pNY_t_pn3 = Array{S}(undef, N) + pNZ_t_pn3 = Array{S}(undef, N) + _4ϕj = Array{S}(undef, N) + ϕi_plus_4ϕj = Array{S}(undef, N) + sj2_plus_2si2_minus_4vivj = Array{S}(undef, N) + ϕs_and_vs = Array{S}(undef, N) + pn1t1_7 = Array{S}(undef, N) + pNX_t_X = Array{S}(undef, N) + pNY_t_Y = Array{S}(undef, N) + pNZ_t_Z = Array{S}(undef, N) + pn1 = Array{S}(undef, N) + X_t_pn1 = Array{S}(undef, N) + Y_t_pn1 = Array{S}(undef, N) + Z_t_pn1 = Array{S}(undef, N) + pntempX = Taylor1(identity(constant_term(zero_q_1)), order) + pntempY = Taylor1(identity(constant_term(zero_q_1)), order) + pntempZ = Taylor1(identity(constant_term(zero_q_1)), order) + t31 = Array{S}(undef, N) + t32 = Array{S}(undef, N) + t33 = Array{S}(undef, N) + r_sin_ϕ = Array{S}(undef, N) + sin_ϕ = Array{S}(undef, N) + ϕ = Array{S}(undef, N) + cos_ϕ = Array{S}(undef, N) + sin2_ϕ = Array{S}(undef, N) + sin3_ϕ = Array{S}(undef, N) + sin4_ϕ = Array{S}(undef, N) + F_J2_x = Array{S}(undef, N) + F_J2_y = Array{S}(undef, N) + F_J2_z = Array{S}(undef, N) + F_J2_x1 = Array{S}(undef, N) + F_J2_y1 = Array{S}(undef, N) + F_J2_z1 = Array{S}(undef, N) + F_J2_x2 = Array{S}(undef, N) + F_J2_y2 = Array{S}(undef, N) + F_J2_z2 = Array{S}(undef, N) + temp_accX_i = Array{S}(undef, N) + temp_accY_i = Array{S}(undef, N) + temp_accZ_i = Array{S}(undef, N) + P_2_sin_ϕ = Array{S}(undef, N) + ∂P_2_sin_ϕ = Array{S}(undef, N) + P_3_sin_ϕ = Array{S}(undef, N) + ∂P_3_sin_ϕ = Array{S}(undef, N) + m_c_ϕ_∂P_2 = Array{S}(undef, N) + m_c_ϕ_∂P_3 = Array{S}(undef, N) + Λ2j_div_r4 = Array{S}(undef, N) + Λ3j_div_r5 = Array{S}(undef, N) + F_J_ξ = Array{S}(undef, N) + F_J_η = Array{S}(undef, N) + F_J_ζ = Array{S}(undef, N) + F_J2_ξ = Array{S}(undef, N) + F_J2_η = Array{S}(undef, N) + F_J2_ζ = Array{S}(undef, N) + F_J3_ξ = Array{S}(undef, N) + F_J3_η = Array{S}(undef, N) + F_J3_ζ = Array{S}(undef, N) + ξx = Array{S}(undef, N) + ξy = Array{S}(undef, N) + ξz = Array{S}(undef, N) + ηx = Array{S}(undef, N) + ηy = Array{S}(undef, N) + ηz = Array{S}(undef, N) + ηx1 = Array{S}(undef, N) + ηy1 = Array{S}(undef, N) + ηz1 = Array{S}(undef, N) + ηx2 = Array{S}(undef, N) + ηy2 = Array{S}(undef, N) + ηz2 = Array{S}(undef, N) + ζx = Array{S}(undef, N) + ζy = Array{S}(undef, N) + ζz = Array{S}(undef, N) + ζx1 = Array{S}(undef, N) + ζy1 = Array{S}(undef, N) + ζz1 = Array{S}(undef, N) + ζx2 = Array{S}(undef, N) + ζy2 = Array{S}(undef, N) + ζz2 = Array{S}(undef, N) + accX = Taylor1(identity(constant_term(zero_q_1)), order) + accY = Taylor1(identity(constant_term(zero_q_1)), order) + accZ = Taylor1(identity(constant_term(zero_q_1)), order) + local M_ = Array{S}(undef, 3, 3, N) + local M_ .= zero_q_1 + local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 + dq[1] = Taylor1(identity(constant_term(q[4])), order) + dq[2] = Taylor1(identity(constant_term(q[5])), order) + dq[3] = Taylor1(identity(constant_term(q[6])), order) + newtonianNb_Potential[N] = Taylor1(identity(constant_term(zero_q_1)), order) + tmp1317 = Array{Taylor1{_S}}(undef, size(dq)) + tmp1317 .= Taylor1(zero(constant_term(q[1])), order) + tmp1319 = Array{Taylor1{_S}}(undef, size(ui)) + tmp1319 .= Taylor1(zero(constant_term(q[1])), order) + tmp1322 = Array{Taylor1{_S}}(undef, size(dq)) + tmp1322 .= Taylor1(zero(constant_term(q[1])), order) + tmp1324 = Array{Taylor1{_S}}(undef, size(vi)) + tmp1324 .= Taylor1(zero(constant_term(q[1])), order) + tmp1327 = Array{Taylor1{_S}}(undef, size(dq)) + tmp1327 .= Taylor1(zero(constant_term(q[1])), order) + tmp1329 = Array{Taylor1{_S}}(undef, size(wi)) + tmp1329 .= Taylor1(zero(constant_term(q[1])), order) + pn2x = Array{Taylor1{_S}}(undef, size(X)) + pn2x .= Taylor1(zero(constant_term(q[1])), order) + pn2y = Array{Taylor1{_S}}(undef, size(Y)) + pn2y .= Taylor1(zero(constant_term(q[1])), order) + pn2z = Array{Taylor1{_S}}(undef, size(Z)) + pn2z .= Taylor1(zero(constant_term(q[1])), order) + tmp1337 = Array{Taylor1{_S}}(undef, size(UU)) + tmp1337 .= Taylor1(zero(constant_term(q[1])), order) + tmp1340 = Array{Taylor1{_S}}(undef, size(X)) + tmp1340 .= Taylor1(zero(constant_term(q[1])), order) + tmp1342 = Array{Taylor1{_S}}(undef, size(Y)) + tmp1342 .= Taylor1(zero(constant_term(q[1])), order) + tmp1343 = Array{Taylor1{_S}}(undef, size(tmp1340)) + tmp1343 .= Taylor1(zero(constant_term(q[1])), order) + tmp1345 = Array{Taylor1{_S}}(undef, size(Z)) + tmp1345 .= Taylor1(zero(constant_term(q[1])), order) + tmp1353 = Array{Taylor1{_S}}(undef, size(pn2x)) + tmp1353 .= Taylor1(zero(constant_term(q[1])), order) + tmp1354 = Array{Taylor1{_S}}(undef, size(tmp1353)) + tmp1354 .= Taylor1(zero(constant_term(q[1])), order) + tmp1449 = Array{Taylor1{_S}}(undef, size(ui)) + tmp1449 .= Taylor1(zero(constant_term(q[1])), order) + tmp1451 = Array{Taylor1{_S}}(undef, size(vi)) + tmp1451 .= Taylor1(zero(constant_term(q[1])), order) + tmp1452 = Array{Taylor1{_S}}(undef, size(tmp1449)) + tmp1452 .= Taylor1(zero(constant_term(q[1])), order) + tmp1454 = Array{Taylor1{_S}}(undef, size(wi)) + tmp1454 .= Taylor1(zero(constant_term(q[1])), order) + tmp1365 = Array{Taylor1{_S}}(undef, size(X)) + tmp1365 .= Taylor1(zero(constant_term(q[1])), order) + tmp1367 = Array{Taylor1{_S}}(undef, size(Y)) + tmp1367 .= Taylor1(zero(constant_term(q[1])), order) + tmp1369 = Array{Taylor1{_S}}(undef, size(Z)) + tmp1369 .= Taylor1(zero(constant_term(q[1])), order) + tmp1371 = Array{Taylor1{_S}}(undef, size(t31)) + tmp1371 .= Taylor1(zero(constant_term(q[1])), order) + tmp1528 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) + tmp1528 .= Taylor1(zero(constant_term(q[1])), order) + tmp1529 = Array{Taylor1{_S}}(undef, size(ϕ)) + tmp1529 .= Taylor1(zero(constant_term(q[1])), order) + tmp1381 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) + tmp1381 .= Taylor1(zero(constant_term(q[1])), order) + tmp1387 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) + tmp1387 .= Taylor1(zero(constant_term(q[1])), order) + tmp1389 = Array{Taylor1{_S}}(undef, size(sin3_ϕ)) + tmp1389 .= Taylor1(zero(constant_term(q[1])), order) + tmp1393 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) + tmp1393 .= Taylor1(zero(constant_term(q[1])), order) + tmp1396 = Array{Taylor1{_S}}(undef, size(r_p2)) + tmp1396 .= Taylor1(zero(constant_term(q[1])), order) + tmp1397 = Array{Taylor1{_S}}(undef, size(Λ2)) + tmp1397 .= Taylor1(zero(constant_term(q[1])), order) + tmp1400 = Array{Taylor1{_S}}(undef, size(r_p1d2)) + tmp1400 .= Taylor1(zero(constant_term(q[1])), order) + tmp1401 = Array{Taylor1{_S}}(undef, size(Λ3)) + tmp1401 .= Taylor1(zero(constant_term(q[1])), order) + tmp1403 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) + tmp1403 .= Taylor1(zero(constant_term(q[1])), order) + tmp1405 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) + tmp1405 .= Taylor1(zero(constant_term(q[1])), order) + tmp1408 = Array{Taylor1{_S}}(undef, size(Λ2j_div_r4)) + tmp1408 .= Taylor1(zero(constant_term(q[1])), order) + tmp1412 = Array{Taylor1{_S}}(undef, size(Λ3j_div_r5)) + tmp1412 .= Taylor1(zero(constant_term(q[1])), order) + tmp1415 = Array{Taylor1{_S}}(undef, size(X)) + tmp1415 .= Taylor1(zero(constant_term(q[1])), order) + tmp1417 = Array{Taylor1{_S}}(undef, size(Y)) + tmp1417 .= Taylor1(zero(constant_term(q[1])), order) + tmp1419 = Array{Taylor1{_S}}(undef, size(Z)) + tmp1419 .= Taylor1(zero(constant_term(q[1])), order) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 + ui[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])), order) + vi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])), order) + wi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])), order) + X[i] = Taylor1(constant_term(ss16asteph_t[3i - 2]) - constant_term(q[1]), order) + Y[i] = Taylor1(constant_term(ss16asteph_t[3i - 1]) - constant_term(q[2]), order) + Z[i] = Taylor1(constant_term(ss16asteph_t[3i]) - constant_term(q[3]), order) + U[i] = Taylor1(constant_term(ui[i]) - constant_term(dq[1]), order) + V[i] = Taylor1(constant_term(vi[i]) - constant_term(dq[2]), order) + W[i] = Taylor1(constant_term(wi[i]) - constant_term(dq[3]), order) + tmp1317[1] = Taylor1(constant_term(4) * constant_term(dq[1]), order) + tmp1319[i] = Taylor1(constant_term(3) * constant_term(ui[i]), order) + _4U_m_3X[i] = Taylor1(constant_term(tmp1317[1]) - constant_term(tmp1319[i]), order) + tmp1322[2] = Taylor1(constant_term(4) * constant_term(dq[2]), order) + tmp1324[i] = Taylor1(constant_term(3) * constant_term(vi[i]), order) + _4V_m_3Y[i] = Taylor1(constant_term(tmp1322[2]) - constant_term(tmp1324[i]), order) + tmp1327[3] = Taylor1(constant_term(4) * constant_term(dq[3]), order) + tmp1329[i] = Taylor1(constant_term(3) * constant_term(wi[i]), order) + _4W_m_3Z[i] = Taylor1(constant_term(tmp1327[3]) - constant_term(tmp1329[i]), order) + pn2x[i] = Taylor1(constant_term(X[i]) * constant_term(_4U_m_3X[i]), order) + pn2y[i] = Taylor1(constant_term(Y[i]) * constant_term(_4V_m_3Y[i]), order) + pn2z[i] = Taylor1(constant_term(Z[i]) * constant_term(_4W_m_3Z[i]), order) + UU[i] = Taylor1(constant_term(ui[i]) * constant_term(dq[1]), order) + VV[i] = Taylor1(constant_term(vi[i]) * constant_term(dq[2]), order) + WW[i] = Taylor1(constant_term(wi[i]) * constant_term(dq[3]), order) + tmp1337[i] = Taylor1(constant_term(UU[i]) + constant_term(VV[i]), order) + vi_dot_vj[i] = Taylor1(constant_term(tmp1337[i]) + constant_term(WW[i]), order) + tmp1340[i] = Taylor1(constant_term(X[i]) ^ float(constant_term(2)), order) + tmp1342[i] = Taylor1(constant_term(Y[i]) ^ float(constant_term(2)), order) + tmp1343[i] = Taylor1(constant_term(tmp1340[i]) + constant_term(tmp1342[i]), order) + tmp1345[i] = Taylor1(constant_term(Z[i]) ^ float(constant_term(2)), order) + r_p2[i] = Taylor1(constant_term(tmp1343[i]) + constant_term(tmp1345[i]), order) + r_p1d2[i] = Taylor1(sqrt(constant_term(r_p2[i])), order) + r_p3d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(1.5)), order) + r_p7d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(3.5)), order) + newtonianCoeff[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p3d2[i]), order) + tmp1353[i] = Taylor1(constant_term(pn2x[i]) + constant_term(pn2y[i]), order) + tmp1354[i] = Taylor1(constant_term(tmp1353[i]) + constant_term(pn2z[i]), order) + pn2[i] = Taylor1(constant_term(newtonianCoeff[i]) * constant_term(tmp1354[i]), order) + newton_acc_X[i] = Taylor1(constant_term(X[i]) * constant_term(newtonianCoeff[i]), order) + newton_acc_Y[i] = Taylor1(constant_term(Y[i]) * constant_term(newtonianCoeff[i]), order) + newton_acc_Z[i] = Taylor1(constant_term(Z[i]) * constant_term(newtonianCoeff[i]), order) + newtonian1b_Potential[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p1d2[i]), order) + pn3[i] = Taylor1(constant_term(3.5) * constant_term(newtonian1b_Potential[i]), order) + U_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(U[i]), order) + V_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(V[i]), order) + W_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(W[i]), order) + if UJ_interaction[i] + tmp1365[i] = Taylor1(-(constant_term(X[i])), order) + t31[i] = Taylor1(constant_term(tmp1365[i]) * constant_term(M_[1, 3, i]), order) + tmp1367[i] = Taylor1(-(constant_term(Y[i])), order) + t32[i] = Taylor1(constant_term(tmp1367[i]) * constant_term(M_[2, 3, i]), order) + tmp1369[i] = Taylor1(-(constant_term(Z[i])), order) + t33[i] = Taylor1(constant_term(tmp1369[i]) * constant_term(M_[3, 3, i]), order) + tmp1371[i] = Taylor1(constant_term(t31[i]) + constant_term(t32[i]), order) + r_sin_ϕ[i] = Taylor1(constant_term(tmp1371[i]) + constant_term(t33[i]), order) + sin_ϕ[i] = Taylor1(constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]), order) + ϕ[i] = Taylor1(asin(constant_term(sin_ϕ[i])), order) + tmp1528[i] = Taylor1(sqrt(1 - constant_term(sin_ϕ[i]) ^ 2), order) + cos_ϕ[i] = Taylor1(cos(constant_term(ϕ[i])), order) + tmp1529[i] = Taylor1(sin(constant_term(ϕ[i])), order) + sin2_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(2)), order) + sin3_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(3)), order) + tmp1381[i] = Taylor1(constant_term(1.5) * constant_term(sin2_ϕ[i]), order) + P_2_sin_ϕ[i] = Taylor1(constant_term(tmp1381[i]) - constant_term(0.5), order) + ∂P_2_sin_ϕ[i] = Taylor1(constant_term(3) * constant_term(sin_ϕ[i]), order) + tmp1387[i] = Taylor1(constant_term(-1.5) * constant_term(sin_ϕ[i]), order) + tmp1389[i] = Taylor1(constant_term(2.5) * constant_term(sin3_ϕ[i]), order) + P_3_sin_ϕ[i] = Taylor1(constant_term(tmp1387[i]) + constant_term(tmp1389[i]), order) + tmp1393[i] = Taylor1(constant_term(7.5) * constant_term(sin2_ϕ[i]), order) + ∂P_3_sin_ϕ[i] = Taylor1(constant_term(-1.5) + constant_term(tmp1393[i]), order) + tmp1396[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(2)), order) + tmp1397[i] = Taylor1(constant_term(Λ2[i]) / constant_term(tmp1396[i]), order) + Λ2j_div_r4[i] = Taylor1(-(constant_term(tmp1397[i])), order) + tmp1400[i] = Taylor1(constant_term(r_p1d2[i]) ^ float(constant_term(5)), order) + tmp1401[i] = Taylor1(constant_term(Λ3[i]) / constant_term(tmp1400[i]), order) + Λ3j_div_r5[i] = Taylor1(-(constant_term(tmp1401[i])), order) + tmp1403[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) + m_c_ϕ_∂P_2[i] = Taylor1(constant_term(tmp1403[i]) * constant_term(∂P_2_sin_ϕ[i]), order) + tmp1405[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) + m_c_ϕ_∂P_3[i] = Taylor1(constant_term(tmp1405[i]) * constant_term(∂P_3_sin_ϕ[i]), order) + tmp1408[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(3), order) + F_J2_ξ[i] = Taylor1(constant_term(tmp1408[i]) * constant_term(P_2_sin_ϕ[i]), order) + F_J2_ζ[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]), order) + tmp1412[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(4), order) + F_J3_ξ[i] = Taylor1(constant_term(tmp1412[i]) * constant_term(P_3_sin_ϕ[i]), order) + F_J3_ζ[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]), order) + F_J_ξ[i] = Taylor1(identity(constant_term(F_J2_ξ[i])), order) + F_J_ζ[i] = Taylor1(identity(constant_term(F_J2_ζ[i])), order) + tmp1415[i] = Taylor1(-(constant_term(X[i])), order) + ξx[i] = Taylor1(constant_term(tmp1415[i]) / constant_term(r_p1d2[i]), order) + tmp1417[i] = Taylor1(-(constant_term(Y[i])), order) + ξy[i] = Taylor1(constant_term(tmp1417[i]) / constant_term(r_p1d2[i]), order) + tmp1419[i] = Taylor1(-(constant_term(Z[i])), order) + ξz[i] = Taylor1(constant_term(tmp1419[i]) / constant_term(r_p1d2[i]), order) + ηx1[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξz[i]), order) + ηy1[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξx[i]), order) + ηz1[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξy[i]), order) + ηx2[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξy[i]), order) + ηy2[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξz[i]), order) + ηz2[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξx[i]), order) + ηx[i] = Taylor1(constant_term(ηx1[i]) - constant_term(ηx2[i]), order) + ηy[i] = Taylor1(constant_term(ηy1[i]) - constant_term(ηy2[i]), order) + ηz[i] = Taylor1(constant_term(ηz1[i]) - constant_term(ηz2[i]), order) + ζx1[i] = Taylor1(constant_term(ξy[i]) * constant_term(ηz[i]), order) + ζy1[i] = Taylor1(constant_term(ξz[i]) * constant_term(ηx[i]), order) + ζz1[i] = Taylor1(constant_term(ξx[i]) * constant_term(ηy[i]), order) + ζx2[i] = Taylor1(constant_term(ξz[i]) * constant_term(ηy[i]), order) + ζy2[i] = Taylor1(constant_term(ξx[i]) * constant_term(ηz[i]), order) + ζz2[i] = Taylor1(constant_term(ξy[i]) * constant_term(ηx[i]), order) + ζx[i] = Taylor1(constant_term(ζx1[i]) - constant_term(ζx2[i]), order) + ζy[i] = Taylor1(constant_term(ζy1[i]) - constant_term(ζy2[i]), order) + ζz[i] = Taylor1(constant_term(ζz1[i]) - constant_term(ζz2[i]), order) + F_J2_x1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξx[i]), order) + F_J2_y1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξy[i]), order) + F_J2_z1[i] = Taylor1(constant_term(F_J_ξ[i]) * constant_term(ξz[i]), order) + F_J2_x2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζx[i]), order) + F_J2_y2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζy[i]), order) + F_J2_z2[i] = Taylor1(constant_term(F_J_ζ[i]) * constant_term(ζz[i]), order) + F_J2_x[i] = Taylor1(constant_term(F_J2_x1[i]) + constant_term(F_J2_x2[i]), order) + F_J2_y[i] = Taylor1(constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]), order) + F_J2_z[i] = Taylor1(constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]), order) + end + tmp1449[i] = Taylor1(constant_term(ui[i]) ^ float(constant_term(2)), order) + tmp1451[i] = Taylor1(constant_term(vi[i]) ^ float(constant_term(2)), order) + tmp1452[i] = Taylor1(constant_term(tmp1449[i]) + constant_term(tmp1451[i]), order) + tmp1454[i] = Taylor1(constant_term(wi[i]) ^ float(constant_term(2)), order) + v2[i] = Taylor1(constant_term(tmp1452[i]) + constant_term(tmp1454[i]), order) + end + tmp1457 = Taylor1(constant_term(q[4]) ^ float(constant_term(2)), order) + tmp1459 = Taylor1(constant_term(q[5]) ^ float(constant_term(2)), order) + tmp1460 = Taylor1(constant_term(tmp1457) + constant_term(tmp1459), order) + tmp1462 = Taylor1(constant_term(q[6]) ^ float(constant_term(2)), order) + v2[N] = Taylor1(constant_term(tmp1460) + constant_term(tmp1462), order) + temp_004 = Array{Taylor1{_S}}(undef, size(newtonian1b_Potential)) + temp_004 .= Taylor1(zero(constant_term(q[1])), order) + tmp1465 = Array{Taylor1{_S}}(undef, size(μ)) + tmp1465 .= Taylor1(zero(constant_term(q[1])), order) + tmp1467 = Array{Taylor1{_S}}(undef, size(μ)) + tmp1467 .= Taylor1(zero(constant_term(q[1])), order) + tmp1469 = Array{Taylor1{_S}}(undef, size(μ)) + tmp1469 .= Taylor1(zero(constant_term(q[1])), order) + for i = 1:Nm1 + temp_004[i] = Taylor1(constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]), order) + newtonianNb_Potential[N] = Taylor1(identity(constant_term(temp_004[i])), order) + if UJ_interaction[i] + tmp1465[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_x[i]), order) + temp_accX_i[i] = Taylor1(constant_term(accX) - constant_term(tmp1465[i]), order) + accX = Taylor1(identity(constant_term(temp_accX_i[i])), order) + tmp1467[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_y[i]), order) + temp_accY_i[i] = Taylor1(constant_term(accY) - constant_term(tmp1467[i]), order) + accY = Taylor1(identity(constant_term(temp_accY_i[i])), order) + tmp1469[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_z[i]), order) + temp_accZ_i[i] = Taylor1(constant_term(accZ) - constant_term(tmp1469[i]), order) + accZ = Taylor1(identity(constant_term(temp_accZ_i[i])), order) + end + end + _4ϕj[N] = Taylor1(constant_term(4) * constant_term(newtonianNb_Potential[N]), order) + tmp1475 = Array{Taylor1{_S}}(undef, size(v2)) + tmp1475 .= Taylor1(zero(constant_term(q[1])), order) + tmp1477 = Array{Taylor1{_S}}(undef, size(vi_dot_vj)) + tmp1477 .= Taylor1(zero(constant_term(q[1])), order) + tmp1478 = Array{Taylor1{_S}}(undef, size(tmp1475)) + tmp1478 .= Taylor1(zero(constant_term(q[1])), order) + Xij_t_Ui = Array{Taylor1{_S}}(undef, size(X)) + Xij_t_Ui .= Taylor1(zero(constant_term(q[1])), order) + Yij_t_Vi = Array{Taylor1{_S}}(undef, size(Y)) + Yij_t_Vi .= Taylor1(zero(constant_term(q[1])), order) + Zij_t_Wi = Array{Taylor1{_S}}(undef, size(Z)) + Zij_t_Wi .= Taylor1(zero(constant_term(q[1])), order) + tmp1484 = Array{Taylor1{_S}}(undef, size(Xij_t_Ui)) + tmp1484 .= Taylor1(zero(constant_term(q[1])), order) + Rij_dot_Vi = Array{Taylor1{_S}}(undef, size(tmp1484)) + Rij_dot_Vi .= Taylor1(zero(constant_term(q[1])), order) + tmp1487 = Array{Taylor1{_S}}(undef, size(Rij_dot_Vi)) + tmp1487 .= Taylor1(zero(constant_term(q[1])), order) + pn1t7 = Array{Taylor1{_S}}(undef, size(tmp1487)) + pn1t7 .= Taylor1(zero(constant_term(q[1])), order) + tmp1490 = Array{Taylor1{_S}}(undef, size(pn1t7)) + tmp1490 .= Taylor1(zero(constant_term(q[1])), order) + pn1t2_7 = Array{Taylor1{_S}}(undef, size(ϕs_and_vs)) + pn1t2_7 .= Taylor1(zero(constant_term(q[1])), order) + tmp1497 = Array{Taylor1{_S}}(undef, size(pNX_t_X)) + tmp1497 .= Taylor1(zero(constant_term(q[1])), order) + tmp1498 = Array{Taylor1{_S}}(undef, size(tmp1497)) + tmp1498 .= Taylor1(zero(constant_term(q[1])), order) + tmp1499 = Array{Taylor1{_S}}(undef, size(tmp1498)) + tmp1499 .= Taylor1(zero(constant_term(q[1])), order) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 + ϕi_plus_4ϕj[i] = Taylor1(constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]), order) + tmp1475[i] = Taylor1(constant_term(2) * constant_term(v2[i]), order) + tmp1477[i] = Taylor1(constant_term(4) * constant_term(vi_dot_vj[i]), order) + tmp1478[i] = Taylor1(constant_term(tmp1475[i]) - constant_term(tmp1477[i]), order) + sj2_plus_2si2_minus_4vivj[i] = Taylor1(constant_term(tmp1478[i]) + constant_term(v2[N]), order) + ϕs_and_vs[i] = Taylor1(constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]), order) + Xij_t_Ui[i] = Taylor1(constant_term(X[i]) * constant_term(ui[i]), order) + Yij_t_Vi[i] = Taylor1(constant_term(Y[i]) * constant_term(vi[i]), order) + Zij_t_Wi[i] = Taylor1(constant_term(Z[i]) * constant_term(wi[i]), order) + tmp1484[i] = Taylor1(constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]), order) + Rij_dot_Vi[i] = Taylor1(constant_term(tmp1484[i]) + constant_term(Zij_t_Wi[i]), order) + tmp1487[i] = Taylor1(constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)), order) + pn1t7[i] = Taylor1(constant_term(tmp1487[i]) / constant_term(r_p2[i]), order) + tmp1490[i] = Taylor1(constant_term(1.5) * constant_term(pn1t7[i]), order) + pn1t2_7[i] = Taylor1(constant_term(ϕs_and_vs[i]) - constant_term(tmp1490[i]), order) + pn1t1_7[i] = Taylor1(constant_term(c_p2) + constant_term(pn1t2_7[i]), order) + pNX_t_X[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(X[i]), order) + pNY_t_Y[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(Y[i]), order) + pNZ_t_Z[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(Z[i]), order) + tmp1497[i] = Taylor1(constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]), order) + tmp1498[i] = Taylor1(constant_term(tmp1497[i]) + constant_term(pNZ_t_Z[i]), order) + tmp1499[i] = Taylor1(constant_term(0.5) * constant_term(tmp1498[i]), order) + pn1[i] = Taylor1(constant_term(pn1t1_7[i]) + constant_term(tmp1499[i]), order) + X_t_pn1[i] = Taylor1(constant_term(newton_acc_X[i]) * constant_term(pn1[i]), order) + Y_t_pn1[i] = Taylor1(constant_term(newton_acc_Y[i]) * constant_term(pn1[i]), order) + Z_t_pn1[i] = Taylor1(constant_term(newton_acc_Z[i]) * constant_term(pn1[i]), order) + pNX_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(pn3[i]), order) + pNY_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]), order) + pNZ_t_pn3[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(pn3[i]), order) + end + tmp1507 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) + tmp1507 .= Taylor1(zero(constant_term(q[1])), order) + termpnx = Array{Taylor1{_S}}(undef, size(X_t_pn1)) + termpnx .= Taylor1(zero(constant_term(q[1])), order) + sumpnx = Array{Taylor1{_S}}(undef, size(termpnx)) + sumpnx .= Taylor1(zero(constant_term(q[1])), order) + tmp1510 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) + tmp1510 .= Taylor1(zero(constant_term(q[1])), order) + termpny = Array{Taylor1{_S}}(undef, size(Y_t_pn1)) + termpny .= Taylor1(zero(constant_term(q[1])), order) + sumpny = Array{Taylor1{_S}}(undef, size(termpny)) + sumpny .= Taylor1(zero(constant_term(q[1])), order) + tmp1513 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) + tmp1513 .= Taylor1(zero(constant_term(q[1])), order) + termpnz = Array{Taylor1{_S}}(undef, size(Z_t_pn1)) + termpnz .= Taylor1(zero(constant_term(q[1])), order) + sumpnz = Array{Taylor1{_S}}(undef, size(termpnz)) + sumpnz .= Taylor1(zero(constant_term(q[1])), order) + for i = 1:10 + tmp1507[i] = Taylor1(constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]), order) + termpnx[i] = Taylor1(constant_term(X_t_pn1[i]) + constant_term(tmp1507[i]), order) + sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) + pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) + tmp1510[i] = Taylor1(constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]), order) + termpny[i] = Taylor1(constant_term(Y_t_pn1[i]) + constant_term(tmp1510[i]), order) + sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) + pntempY = Taylor1(identity(constant_term(sumpny[i])), order) + tmp1513[i] = Taylor1(constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]), order) + termpnz[i] = Taylor1(constant_term(Z_t_pn1[i]) + constant_term(tmp1513[i]), order) + sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) + pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) + end + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 + X_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_X[i]), order) + Y_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Y[i]), order) + Z_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Z[i]), order) + end + for i = 11:Nm1 + termpnx[i] = Taylor1(identity(constant_term(X_t_pn1[i])), order) + sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) + pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) + termpny[i] = Taylor1(identity(constant_term(Y_t_pn1[i])), order) + sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) + pntempY = Taylor1(identity(constant_term(sumpny[i])), order) + termpnz[i] = Taylor1(identity(constant_term(Z_t_pn1[i])), order) + sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) + pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) + end + postNewtonX = Taylor1(constant_term(pntempX) * constant_term(c_m2), order) + postNewtonY = Taylor1(constant_term(pntempY) * constant_term(c_m2), order) + postNewtonZ = Taylor1(constant_term(pntempZ) * constant_term(c_m2), order) + dq[4] = Taylor1(constant_term(postNewtonX) + constant_term(accX), order) + dq[5] = Taylor1(constant_term(postNewtonY) + constant_term(accY), order) + dq[6] = Taylor1(constant_term(postNewtonZ) + constant_term(accZ), order) + return TaylorIntegration.RetAlloc{Taylor1{_S}}([tmp1457, tmp1459, tmp1460, tmp1462, pntempX, pntempY, pntempZ, accX, accY, accZ, postNewtonX, postNewtonY, postNewtonZ], [X, Y, Z, r_p2, r_p1d2, r_p3d2, r_p7d2, newtonianCoeff, ui, vi, wi, U, V, W, _4U_m_3X, _4V_m_3Y, _4W_m_3Z, UU, VV, WW, newtonian1b_Potential, newtonianNb_Potential, newton_acc_X, newton_acc_Y, newton_acc_Z, v2, vi_dot_vj, pn2, U_t_pn2, V_t_pn2, W_t_pn2, pn3, pNX_t_pn3, pNY_t_pn3, pNZ_t_pn3, _4ϕj, ϕi_plus_4ϕj, sj2_plus_2si2_minus_4vivj, ϕs_and_vs, pn1t1_7, pNX_t_X, pNY_t_Y, pNZ_t_Z, pn1, X_t_pn1, Y_t_pn1, Z_t_pn1, t31, t32, t33, r_sin_ϕ, sin_ϕ, ϕ, cos_ϕ, sin2_ϕ, sin3_ϕ, F_J2_x, F_J2_y, F_J2_z, F_J2_x1, F_J2_y1, F_J2_z1, F_J2_x2, F_J2_y2, F_J2_z2, temp_accX_i, temp_accY_i, temp_accZ_i, P_2_sin_ϕ, ∂P_2_sin_ϕ, P_3_sin_ϕ, ∂P_3_sin_ϕ, m_c_ϕ_∂P_2, m_c_ϕ_∂P_3, Λ2j_div_r4, Λ3j_div_r5, F_J_ξ, F_J_ζ, F_J2_ξ, F_J2_ζ, F_J3_ξ, F_J3_ζ, ξx, ξy, ξz, ηx, ηy, ηz, ηx1, ηy1, ηz1, ηx2, ηy2, ηz2, ζx, ζy, ζz, ζx1, ζy1, ζz1, ζx2, ζy2, ζz2, tmp1317, tmp1319, tmp1322, tmp1324, tmp1327, tmp1329, pn2x, pn2y, pn2z, tmp1337, tmp1340, tmp1342, tmp1343, tmp1345, tmp1353, tmp1354, tmp1365, tmp1367, tmp1369, tmp1371, tmp1528, tmp1529, tmp1381, tmp1387, tmp1389, tmp1393, tmp1396, tmp1397, tmp1400, tmp1401, tmp1403, tmp1405, tmp1408, tmp1412, tmp1415, tmp1417, tmp1419, tmp1449, tmp1451, tmp1452, tmp1454, temp_004, tmp1465, tmp1467, tmp1469, tmp1475, tmp1477, tmp1478, Xij_t_Ui, Yij_t_Vi, Zij_t_Wi, tmp1484, Rij_dot_Vi, tmp1487, pn1t7, tmp1490, pn1t2_7, tmp1497, tmp1498, tmp1499, tmp1507, termpnx, sumpnx, tmp1510, termpny, sumpny, tmp1513, termpnz, sumpnz], [Array{Taylor1{_S}, 2}(undef, 0, 0)], [Array{Taylor1{_S}, 3}(undef, 0, 0, 0)], [Array{Taylor1{_S}, 4}(undef, 0, 0, 0, 0)]) +end + +# TaylorIntegration.jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_eph_threads! +function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params, __ralloc::TaylorIntegration.RetAlloc{Taylor1{_S}}) where {_T <: Real, _S <: Number, _N} + order = t.order + tmp1457 = __ralloc.v0[1] + tmp1459 = __ralloc.v0[2] + tmp1460 = __ralloc.v0[3] + tmp1462 = __ralloc.v0[4] + pntempX = __ralloc.v0[5] + pntempY = __ralloc.v0[6] + pntempZ = __ralloc.v0[7] + accX = __ralloc.v0[8] + accY = __ralloc.v0[9] + accZ = __ralloc.v0[10] + postNewtonX = __ralloc.v0[11] + postNewtonY = __ralloc.v0[12] + postNewtonZ = __ralloc.v0[13] + X = __ralloc.v1[1] + Y = __ralloc.v1[2] + Z = __ralloc.v1[3] + r_p2 = __ralloc.v1[4] + r_p1d2 = __ralloc.v1[5] + r_p3d2 = __ralloc.v1[6] + r_p7d2 = __ralloc.v1[7] + newtonianCoeff = __ralloc.v1[8] + ui = __ralloc.v1[9] + vi = __ralloc.v1[10] + wi = __ralloc.v1[11] + U = __ralloc.v1[12] + V = __ralloc.v1[13] + W = __ralloc.v1[14] + _4U_m_3X = __ralloc.v1[15] + _4V_m_3Y = __ralloc.v1[16] + _4W_m_3Z = __ralloc.v1[17] + UU = __ralloc.v1[18] + VV = __ralloc.v1[19] + WW = __ralloc.v1[20] + newtonian1b_Potential = __ralloc.v1[21] + newtonianNb_Potential = __ralloc.v1[22] + newton_acc_X = __ralloc.v1[23] + newton_acc_Y = __ralloc.v1[24] + newton_acc_Z = __ralloc.v1[25] + v2 = __ralloc.v1[26] + vi_dot_vj = __ralloc.v1[27] + pn2 = __ralloc.v1[28] + U_t_pn2 = __ralloc.v1[29] + V_t_pn2 = __ralloc.v1[30] + W_t_pn2 = __ralloc.v1[31] + pn3 = __ralloc.v1[32] + pNX_t_pn3 = __ralloc.v1[33] + pNY_t_pn3 = __ralloc.v1[34] + pNZ_t_pn3 = __ralloc.v1[35] + _4ϕj = __ralloc.v1[36] + ϕi_plus_4ϕj = __ralloc.v1[37] + sj2_plus_2si2_minus_4vivj = __ralloc.v1[38] + ϕs_and_vs = __ralloc.v1[39] + pn1t1_7 = __ralloc.v1[40] + pNX_t_X = __ralloc.v1[41] + pNY_t_Y = __ralloc.v1[42] + pNZ_t_Z = __ralloc.v1[43] + pn1 = __ralloc.v1[44] + X_t_pn1 = __ralloc.v1[45] + Y_t_pn1 = __ralloc.v1[46] + Z_t_pn1 = __ralloc.v1[47] + t31 = __ralloc.v1[48] + t32 = __ralloc.v1[49] + t33 = __ralloc.v1[50] + r_sin_ϕ = __ralloc.v1[51] + sin_ϕ = __ralloc.v1[52] + ϕ = __ralloc.v1[53] + cos_ϕ = __ralloc.v1[54] + sin2_ϕ = __ralloc.v1[55] + sin3_ϕ = __ralloc.v1[56] + F_J2_x = __ralloc.v1[57] + F_J2_y = __ralloc.v1[58] + F_J2_z = __ralloc.v1[59] + F_J2_x1 = __ralloc.v1[60] + F_J2_y1 = __ralloc.v1[61] + F_J2_z1 = __ralloc.v1[62] + F_J2_x2 = __ralloc.v1[63] + F_J2_y2 = __ralloc.v1[64] + F_J2_z2 = __ralloc.v1[65] + temp_accX_i = __ralloc.v1[66] + temp_accY_i = __ralloc.v1[67] + temp_accZ_i = __ralloc.v1[68] + P_2_sin_ϕ = __ralloc.v1[69] + ∂P_2_sin_ϕ = __ralloc.v1[70] + P_3_sin_ϕ = __ralloc.v1[71] + ∂P_3_sin_ϕ = __ralloc.v1[72] + m_c_ϕ_∂P_2 = __ralloc.v1[73] + m_c_ϕ_∂P_3 = __ralloc.v1[74] + Λ2j_div_r4 = __ralloc.v1[75] + Λ3j_div_r5 = __ralloc.v1[76] + F_J_ξ = __ralloc.v1[77] + F_J_ζ = __ralloc.v1[78] + F_J2_ξ = __ralloc.v1[79] + F_J2_ζ = __ralloc.v1[80] + F_J3_ξ = __ralloc.v1[81] + F_J3_ζ = __ralloc.v1[82] + ξx = __ralloc.v1[83] + ξy = __ralloc.v1[84] + ξz = __ralloc.v1[85] + ηx = __ralloc.v1[86] + ηy = __ralloc.v1[87] + ηz = __ralloc.v1[88] + ηx1 = __ralloc.v1[89] + ηy1 = __ralloc.v1[90] + ηz1 = __ralloc.v1[91] + ηx2 = __ralloc.v1[92] + ηy2 = __ralloc.v1[93] + ηz2 = __ralloc.v1[94] + ζx = __ralloc.v1[95] + ζy = __ralloc.v1[96] + ζz = __ralloc.v1[97] + ζx1 = __ralloc.v1[98] + ζy1 = __ralloc.v1[99] + ζz1 = __ralloc.v1[100] + ζx2 = __ralloc.v1[101] + ζy2 = __ralloc.v1[102] + ζz2 = __ralloc.v1[103] + tmp1317 = __ralloc.v1[104] + tmp1319 = __ralloc.v1[105] + tmp1322 = __ralloc.v1[106] + tmp1324 = __ralloc.v1[107] + tmp1327 = __ralloc.v1[108] + tmp1329 = __ralloc.v1[109] + pn2x = __ralloc.v1[110] + pn2y = __ralloc.v1[111] + pn2z = __ralloc.v1[112] + tmp1337 = __ralloc.v1[113] + tmp1340 = __ralloc.v1[114] + tmp1342 = __ralloc.v1[115] + tmp1343 = __ralloc.v1[116] + tmp1345 = __ralloc.v1[117] + tmp1353 = __ralloc.v1[118] + tmp1354 = __ralloc.v1[119] + tmp1365 = __ralloc.v1[120] + tmp1367 = __ralloc.v1[121] + tmp1369 = __ralloc.v1[122] + tmp1371 = __ralloc.v1[123] + tmp1528 = __ralloc.v1[124] + tmp1529 = __ralloc.v1[125] + tmp1381 = __ralloc.v1[126] + tmp1387 = __ralloc.v1[127] + tmp1389 = __ralloc.v1[128] + tmp1393 = __ralloc.v1[129] + tmp1396 = __ralloc.v1[130] + tmp1397 = __ralloc.v1[131] + tmp1400 = __ralloc.v1[132] + tmp1401 = __ralloc.v1[133] + tmp1403 = __ralloc.v1[134] + tmp1405 = __ralloc.v1[135] + tmp1408 = __ralloc.v1[136] + tmp1412 = __ralloc.v1[137] + tmp1415 = __ralloc.v1[138] + tmp1417 = __ralloc.v1[139] + tmp1419 = __ralloc.v1[140] + tmp1449 = __ralloc.v1[141] + tmp1451 = __ralloc.v1[142] + tmp1452 = __ralloc.v1[143] + tmp1454 = __ralloc.v1[144] + temp_004 = __ralloc.v1[145] + tmp1465 = __ralloc.v1[146] + tmp1467 = __ralloc.v1[147] + tmp1469 = __ralloc.v1[148] + tmp1475 = __ralloc.v1[149] + tmp1477 = __ralloc.v1[150] + tmp1478 = __ralloc.v1[151] + Xij_t_Ui = __ralloc.v1[152] + Yij_t_Vi = __ralloc.v1[153] + Zij_t_Wi = __ralloc.v1[154] + tmp1484 = __ralloc.v1[155] + Rij_dot_Vi = __ralloc.v1[156] + tmp1487 = __ralloc.v1[157] + pn1t7 = __ralloc.v1[158] + tmp1490 = __ralloc.v1[159] + pn1t2_7 = __ralloc.v1[160] + tmp1497 = __ralloc.v1[161] + tmp1498 = __ralloc.v1[162] + tmp1499 = __ralloc.v1[163] + tmp1507 = __ralloc.v1[164] + termpnx = __ralloc.v1[165] + sumpnx = __ralloc.v1[166] + tmp1510 = __ralloc.v1[167] + termpny = __ralloc.v1[168] + sumpny = __ralloc.v1[169] + tmp1513 = __ralloc.v1[170] + termpnz = __ralloc.v1[171] + sumpnz = __ralloc.v1[172] + local jd0 = params[4] + local dsj2k = t + (jd0 - JD_J2000) + local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) + local acceph_t = evaleph(params[2], dsj2k, q[1]) + local newtonianNb_Potential_t = evaleph(params[3], dsj2k, q[1]) + local S = eltype(q) + local UJ_interaction = params[5] + local N = params[6] + local Nm1 = N - 1 + local μ = params[7] + local zero_q_1 = auxzero(q[1]) + pntempX.coeffs[1] = identity(constant_term(zero_q_1)) + pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) + pntempY.coeffs[1] = identity(constant_term(zero_q_1)) + pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) + pntempZ.coeffs[1] = identity(constant_term(zero_q_1)) + pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) + accX.coeffs[1] = identity(constant_term(zero_q_1)) + accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) + accY.coeffs[1] = identity(constant_term(zero_q_1)) + accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) + accZ.coeffs[1] = identity(constant_term(zero_q_1)) + accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) + local M_ = Array{S}(undef, 3, 3, N) + local M_ .= zero_q_1 + local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 + (dq[1]).coeffs[1] = identity(constant_term(q[4])) + (dq[1]).coeffs[2:order + 1] .= zero((dq[1]).coeffs[1]) + (dq[2]).coeffs[1] = identity(constant_term(q[5])) + (dq[2]).coeffs[2:order + 1] .= zero((dq[2]).coeffs[1]) + (dq[3]).coeffs[1] = identity(constant_term(q[6])) + (dq[3]).coeffs[2:order + 1] .= zero((dq[3]).coeffs[1]) + (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(zero_q_1)) + (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 + (ui[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])) + (ui[i]).coeffs[2:order + 1] .= zero((ui[i]).coeffs[1]) + (vi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])) + (vi[i]).coeffs[2:order + 1] .= zero((vi[i]).coeffs[1]) + (wi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])) + (wi[i]).coeffs[2:order + 1] .= zero((wi[i]).coeffs[1]) + (X[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 2]) - constant_term(q[1]) + (X[i]).coeffs[2:order + 1] .= zero((X[i]).coeffs[1]) + (Y[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 1]) - constant_term(q[2]) + (Y[i]).coeffs[2:order + 1] .= zero((Y[i]).coeffs[1]) + (Z[i]).coeffs[1] = constant_term(ss16asteph_t[3i]) - constant_term(q[3]) + (Z[i]).coeffs[2:order + 1] .= zero((Z[i]).coeffs[1]) + (U[i]).coeffs[1] = constant_term(ui[i]) - constant_term(dq[1]) + (U[i]).coeffs[2:order + 1] .= zero((U[i]).coeffs[1]) + (V[i]).coeffs[1] = constant_term(vi[i]) - constant_term(dq[2]) + (V[i]).coeffs[2:order + 1] .= zero((V[i]).coeffs[1]) + (W[i]).coeffs[1] = constant_term(wi[i]) - constant_term(dq[3]) + (W[i]).coeffs[2:order + 1] .= zero((W[i]).coeffs[1]) + (tmp1317[1]).coeffs[1] = constant_term(4) * constant_term(dq[1]) + (tmp1317[1]).coeffs[2:order + 1] .= zero((tmp1317[1]).coeffs[1]) + (tmp1319[i]).coeffs[1] = constant_term(3) * constant_term(ui[i]) + (tmp1319[i]).coeffs[2:order + 1] .= zero((tmp1319[i]).coeffs[1]) + (_4U_m_3X[i]).coeffs[1] = constant_term(tmp1317[1]) - constant_term(tmp1319[i]) + (_4U_m_3X[i]).coeffs[2:order + 1] .= zero((_4U_m_3X[i]).coeffs[1]) + (tmp1322[2]).coeffs[1] = constant_term(4) * constant_term(dq[2]) + (tmp1322[2]).coeffs[2:order + 1] .= zero((tmp1322[2]).coeffs[1]) + (tmp1324[i]).coeffs[1] = constant_term(3) * constant_term(vi[i]) + (tmp1324[i]).coeffs[2:order + 1] .= zero((tmp1324[i]).coeffs[1]) + (_4V_m_3Y[i]).coeffs[1] = constant_term(tmp1322[2]) - constant_term(tmp1324[i]) + (_4V_m_3Y[i]).coeffs[2:order + 1] .= zero((_4V_m_3Y[i]).coeffs[1]) + (tmp1327[3]).coeffs[1] = constant_term(4) * constant_term(dq[3]) + (tmp1327[3]).coeffs[2:order + 1] .= zero((tmp1327[3]).coeffs[1]) + (tmp1329[i]).coeffs[1] = constant_term(3) * constant_term(wi[i]) + (tmp1329[i]).coeffs[2:order + 1] .= zero((tmp1329[i]).coeffs[1]) + (_4W_m_3Z[i]).coeffs[1] = constant_term(tmp1327[3]) - constant_term(tmp1329[i]) + (_4W_m_3Z[i]).coeffs[2:order + 1] .= zero((_4W_m_3Z[i]).coeffs[1]) + (pn2x[i]).coeffs[1] = constant_term(X[i]) * constant_term(_4U_m_3X[i]) + (pn2x[i]).coeffs[2:order + 1] .= zero((pn2x[i]).coeffs[1]) + (pn2y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(_4V_m_3Y[i]) + (pn2y[i]).coeffs[2:order + 1] .= zero((pn2y[i]).coeffs[1]) + (pn2z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(_4W_m_3Z[i]) + (pn2z[i]).coeffs[2:order + 1] .= zero((pn2z[i]).coeffs[1]) + (UU[i]).coeffs[1] = constant_term(ui[i]) * constant_term(dq[1]) + (UU[i]).coeffs[2:order + 1] .= zero((UU[i]).coeffs[1]) + (VV[i]).coeffs[1] = constant_term(vi[i]) * constant_term(dq[2]) + (VV[i]).coeffs[2:order + 1] .= zero((VV[i]).coeffs[1]) + (WW[i]).coeffs[1] = constant_term(wi[i]) * constant_term(dq[3]) + (WW[i]).coeffs[2:order + 1] .= zero((WW[i]).coeffs[1]) + (tmp1337[i]).coeffs[1] = constant_term(UU[i]) + constant_term(VV[i]) + (tmp1337[i]).coeffs[2:order + 1] .= zero((tmp1337[i]).coeffs[1]) + (vi_dot_vj[i]).coeffs[1] = constant_term(tmp1337[i]) + constant_term(WW[i]) + (vi_dot_vj[i]).coeffs[2:order + 1] .= zero((vi_dot_vj[i]).coeffs[1]) + (tmp1340[i]).coeffs[1] = constant_term(X[i]) ^ float(constant_term(2)) + (tmp1340[i]).coeffs[2:order + 1] .= zero((tmp1340[i]).coeffs[1]) + (tmp1342[i]).coeffs[1] = constant_term(Y[i]) ^ float(constant_term(2)) + (tmp1342[i]).coeffs[2:order + 1] .= zero((tmp1342[i]).coeffs[1]) + (tmp1343[i]).coeffs[1] = constant_term(tmp1340[i]) + constant_term(tmp1342[i]) + (tmp1343[i]).coeffs[2:order + 1] .= zero((tmp1343[i]).coeffs[1]) + (tmp1345[i]).coeffs[1] = constant_term(Z[i]) ^ float(constant_term(2)) + (tmp1345[i]).coeffs[2:order + 1] .= zero((tmp1345[i]).coeffs[1]) + (r_p2[i]).coeffs[1] = constant_term(tmp1343[i]) + constant_term(tmp1345[i]) + (r_p2[i]).coeffs[2:order + 1] .= zero((r_p2[i]).coeffs[1]) + (r_p1d2[i]).coeffs[1] = sqrt(constant_term(r_p2[i])) + (r_p1d2[i]).coeffs[2:order + 1] .= zero((r_p1d2[i]).coeffs[1]) + (r_p3d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(1.5)) + (r_p3d2[i]).coeffs[2:order + 1] .= zero((r_p3d2[i]).coeffs[1]) + (r_p7d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(3.5)) + (r_p7d2[i]).coeffs[2:order + 1] .= zero((r_p7d2[i]).coeffs[1]) + (newtonianCoeff[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p3d2[i]) + (newtonianCoeff[i]).coeffs[2:order + 1] .= zero((newtonianCoeff[i]).coeffs[1]) + (tmp1353[i]).coeffs[1] = constant_term(pn2x[i]) + constant_term(pn2y[i]) + (tmp1353[i]).coeffs[2:order + 1] .= zero((tmp1353[i]).coeffs[1]) + (tmp1354[i]).coeffs[1] = constant_term(tmp1353[i]) + constant_term(pn2z[i]) + (tmp1354[i]).coeffs[2:order + 1] .= zero((tmp1354[i]).coeffs[1]) + (pn2[i]).coeffs[1] = constant_term(newtonianCoeff[i]) * constant_term(tmp1354[i]) + (pn2[i]).coeffs[2:order + 1] .= zero((pn2[i]).coeffs[1]) + (newton_acc_X[i]).coeffs[1] = constant_term(X[i]) * constant_term(newtonianCoeff[i]) + (newton_acc_X[i]).coeffs[2:order + 1] .= zero((newton_acc_X[i]).coeffs[1]) + (newton_acc_Y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(newtonianCoeff[i]) + (newton_acc_Y[i]).coeffs[2:order + 1] .= zero((newton_acc_Y[i]).coeffs[1]) + (newton_acc_Z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(newtonianCoeff[i]) + (newton_acc_Z[i]).coeffs[2:order + 1] .= zero((newton_acc_Z[i]).coeffs[1]) + (newtonian1b_Potential[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p1d2[i]) + (newtonian1b_Potential[i]).coeffs[2:order + 1] .= zero((newtonian1b_Potential[i]).coeffs[1]) + (pn3[i]).coeffs[1] = constant_term(3.5) * constant_term(newtonian1b_Potential[i]) + (pn3[i]).coeffs[2:order + 1] .= zero((pn3[i]).coeffs[1]) + (U_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(U[i]) + (U_t_pn2[i]).coeffs[2:order + 1] .= zero((U_t_pn2[i]).coeffs[1]) + (V_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(V[i]) + (V_t_pn2[i]).coeffs[2:order + 1] .= zero((V_t_pn2[i]).coeffs[1]) + (W_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(W[i]) + (W_t_pn2[i]).coeffs[2:order + 1] .= zero((W_t_pn2[i]).coeffs[1]) + if UJ_interaction[i] + (tmp1365[i]).coeffs[1] = -(constant_term(X[i])) + (tmp1365[i]).coeffs[2:order + 1] .= zero((tmp1365[i]).coeffs[1]) + (t31[i]).coeffs[1] = constant_term(tmp1365[i]) * constant_term(M_[1, 3, i]) + (t31[i]).coeffs[2:order + 1] .= zero((t31[i]).coeffs[1]) + (tmp1367[i]).coeffs[1] = -(constant_term(Y[i])) + (tmp1367[i]).coeffs[2:order + 1] .= zero((tmp1367[i]).coeffs[1]) + (t32[i]).coeffs[1] = constant_term(tmp1367[i]) * constant_term(M_[2, 3, i]) + (t32[i]).coeffs[2:order + 1] .= zero((t32[i]).coeffs[1]) + (tmp1369[i]).coeffs[1] = -(constant_term(Z[i])) + (tmp1369[i]).coeffs[2:order + 1] .= zero((tmp1369[i]).coeffs[1]) + (t33[i]).coeffs[1] = constant_term(tmp1369[i]) * constant_term(M_[3, 3, i]) + (t33[i]).coeffs[2:order + 1] .= zero((t33[i]).coeffs[1]) + (tmp1371[i]).coeffs[1] = constant_term(t31[i]) + constant_term(t32[i]) + (tmp1371[i]).coeffs[2:order + 1] .= zero((tmp1371[i]).coeffs[1]) + (r_sin_ϕ[i]).coeffs[1] = constant_term(tmp1371[i]) + constant_term(t33[i]) + (r_sin_ϕ[i]).coeffs[2:order + 1] .= zero((r_sin_ϕ[i]).coeffs[1]) + (sin_ϕ[i]).coeffs[1] = constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]) + (sin_ϕ[i]).coeffs[2:order + 1] .= zero((sin_ϕ[i]).coeffs[1]) + (ϕ[i]).coeffs[1] = asin(constant_term(sin_ϕ[i])) + (ϕ[i]).coeffs[2:order + 1] .= zero((ϕ[i]).coeffs[1]) + (tmp1528[i]).coeffs[1] = sqrt(1 - constant_term(sin_ϕ[i]) ^ 2) + (tmp1528[i]).coeffs[2:order + 1] .= zero((tmp1528[i]).coeffs[1]) + (cos_ϕ[i]).coeffs[1] = cos(constant_term(ϕ[i])) + (cos_ϕ[i]).coeffs[2:order + 1] .= zero((cos_ϕ[i]).coeffs[1]) + (tmp1529[i]).coeffs[1] = sin(constant_term(ϕ[i])) + (tmp1529[i]).coeffs[2:order + 1] .= zero((tmp1529[i]).coeffs[1]) + (sin2_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(2)) + (sin2_ϕ[i]).coeffs[2:order + 1] .= zero((sin2_ϕ[i]).coeffs[1]) + (sin3_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(3)) + (sin3_ϕ[i]).coeffs[2:order + 1] .= zero((sin3_ϕ[i]).coeffs[1]) + (tmp1381[i]).coeffs[1] = constant_term(1.5) * constant_term(sin2_ϕ[i]) + (tmp1381[i]).coeffs[2:order + 1] .= zero((tmp1381[i]).coeffs[1]) + (P_2_sin_ϕ[i]).coeffs[1] = constant_term(tmp1381[i]) - constant_term(0.5) + (P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_2_sin_ϕ[i]).coeffs[1]) + (∂P_2_sin_ϕ[i]).coeffs[1] = constant_term(3) * constant_term(sin_ϕ[i]) + (∂P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_2_sin_ϕ[i]).coeffs[1]) + (tmp1387[i]).coeffs[1] = constant_term(-1.5) * constant_term(sin_ϕ[i]) + (tmp1387[i]).coeffs[2:order + 1] .= zero((tmp1387[i]).coeffs[1]) + (tmp1389[i]).coeffs[1] = constant_term(2.5) * constant_term(sin3_ϕ[i]) + (tmp1389[i]).coeffs[2:order + 1] .= zero((tmp1389[i]).coeffs[1]) + (P_3_sin_ϕ[i]).coeffs[1] = constant_term(tmp1387[i]) + constant_term(tmp1389[i]) + (P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_3_sin_ϕ[i]).coeffs[1]) + (tmp1393[i]).coeffs[1] = constant_term(7.5) * constant_term(sin2_ϕ[i]) + (tmp1393[i]).coeffs[2:order + 1] .= zero((tmp1393[i]).coeffs[1]) + (∂P_3_sin_ϕ[i]).coeffs[1] = constant_term(-1.5) + constant_term(tmp1393[i]) + (∂P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_3_sin_ϕ[i]).coeffs[1]) + (tmp1396[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(2)) + (tmp1396[i]).coeffs[2:order + 1] .= zero((tmp1396[i]).coeffs[1]) + (tmp1397[i]).coeffs[1] = constant_term(Λ2[i]) / constant_term(tmp1396[i]) + (tmp1397[i]).coeffs[2:order + 1] .= zero((tmp1397[i]).coeffs[1]) + (Λ2j_div_r4[i]).coeffs[1] = -(constant_term(tmp1397[i])) + (Λ2j_div_r4[i]).coeffs[2:order + 1] .= zero((Λ2j_div_r4[i]).coeffs[1]) + (tmp1400[i]).coeffs[1] = constant_term(r_p1d2[i]) ^ float(constant_term(5)) + (tmp1400[i]).coeffs[2:order + 1] .= zero((tmp1400[i]).coeffs[1]) + (tmp1401[i]).coeffs[1] = constant_term(Λ3[i]) / constant_term(tmp1400[i]) + (tmp1401[i]).coeffs[2:order + 1] .= zero((tmp1401[i]).coeffs[1]) + (Λ3j_div_r5[i]).coeffs[1] = -(constant_term(tmp1401[i])) + (Λ3j_div_r5[i]).coeffs[2:order + 1] .= zero((Λ3j_div_r5[i]).coeffs[1]) + (tmp1403[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) + (tmp1403[i]).coeffs[2:order + 1] .= zero((tmp1403[i]).coeffs[1]) + (m_c_ϕ_∂P_2[i]).coeffs[1] = constant_term(tmp1403[i]) * constant_term(∂P_2_sin_ϕ[i]) + (m_c_ϕ_∂P_2[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_2[i]).coeffs[1]) + (tmp1405[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) + (tmp1405[i]).coeffs[2:order + 1] .= zero((tmp1405[i]).coeffs[1]) + (m_c_ϕ_∂P_3[i]).coeffs[1] = constant_term(tmp1405[i]) * constant_term(∂P_3_sin_ϕ[i]) + (m_c_ϕ_∂P_3[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_3[i]).coeffs[1]) + (tmp1408[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(3) + (tmp1408[i]).coeffs[2:order + 1] .= zero((tmp1408[i]).coeffs[1]) + (F_J2_ξ[i]).coeffs[1] = constant_term(tmp1408[i]) * constant_term(P_2_sin_ϕ[i]) + (F_J2_ξ[i]).coeffs[2:order + 1] .= zero((F_J2_ξ[i]).coeffs[1]) + (F_J2_ζ[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]) + (F_J2_ζ[i]).coeffs[2:order + 1] .= zero((F_J2_ζ[i]).coeffs[1]) + (tmp1412[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(4) + (tmp1412[i]).coeffs[2:order + 1] .= zero((tmp1412[i]).coeffs[1]) + (F_J3_ξ[i]).coeffs[1] = constant_term(tmp1412[i]) * constant_term(P_3_sin_ϕ[i]) + (F_J3_ξ[i]).coeffs[2:order + 1] .= zero((F_J3_ξ[i]).coeffs[1]) + (F_J3_ζ[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]) + (F_J3_ζ[i]).coeffs[2:order + 1] .= zero((F_J3_ζ[i]).coeffs[1]) + (F_J_ξ[i]).coeffs[1] = identity(constant_term(F_J2_ξ[i])) + (F_J_ξ[i]).coeffs[2:order + 1] .= zero((F_J_ξ[i]).coeffs[1]) + (F_J_ζ[i]).coeffs[1] = identity(constant_term(F_J2_ζ[i])) + (F_J_ζ[i]).coeffs[2:order + 1] .= zero((F_J_ζ[i]).coeffs[1]) + (tmp1415[i]).coeffs[1] = -(constant_term(X[i])) + (tmp1415[i]).coeffs[2:order + 1] .= zero((tmp1415[i]).coeffs[1]) + (ξx[i]).coeffs[1] = constant_term(tmp1415[i]) / constant_term(r_p1d2[i]) + (ξx[i]).coeffs[2:order + 1] .= zero((ξx[i]).coeffs[1]) + (tmp1417[i]).coeffs[1] = -(constant_term(Y[i])) + (tmp1417[i]).coeffs[2:order + 1] .= zero((tmp1417[i]).coeffs[1]) + (ξy[i]).coeffs[1] = constant_term(tmp1417[i]) / constant_term(r_p1d2[i]) + (ξy[i]).coeffs[2:order + 1] .= zero((ξy[i]).coeffs[1]) + (tmp1419[i]).coeffs[1] = -(constant_term(Z[i])) + (tmp1419[i]).coeffs[2:order + 1] .= zero((tmp1419[i]).coeffs[1]) + (ξz[i]).coeffs[1] = constant_term(tmp1419[i]) / constant_term(r_p1d2[i]) + (ξz[i]).coeffs[2:order + 1] .= zero((ξz[i]).coeffs[1]) + (ηx1[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξz[i]) + (ηx1[i]).coeffs[2:order + 1] .= zero((ηx1[i]).coeffs[1]) + (ηy1[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξx[i]) + (ηy1[i]).coeffs[2:order + 1] .= zero((ηy1[i]).coeffs[1]) + (ηz1[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξy[i]) + (ηz1[i]).coeffs[2:order + 1] .= zero((ηz1[i]).coeffs[1]) + (ηx2[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξy[i]) + (ηx2[i]).coeffs[2:order + 1] .= zero((ηx2[i]).coeffs[1]) + (ηy2[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξz[i]) + (ηy2[i]).coeffs[2:order + 1] .= zero((ηy2[i]).coeffs[1]) + (ηz2[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξx[i]) + (ηz2[i]).coeffs[2:order + 1] .= zero((ηz2[i]).coeffs[1]) + (ηx[i]).coeffs[1] = constant_term(ηx1[i]) - constant_term(ηx2[i]) + (ηx[i]).coeffs[2:order + 1] .= zero((ηx[i]).coeffs[1]) + (ηy[i]).coeffs[1] = constant_term(ηy1[i]) - constant_term(ηy2[i]) + (ηy[i]).coeffs[2:order + 1] .= zero((ηy[i]).coeffs[1]) + (ηz[i]).coeffs[1] = constant_term(ηz1[i]) - constant_term(ηz2[i]) + (ηz[i]).coeffs[2:order + 1] .= zero((ηz[i]).coeffs[1]) + (ζx1[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηz[i]) + (ζx1[i]).coeffs[2:order + 1] .= zero((ζx1[i]).coeffs[1]) + (ζy1[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηx[i]) + (ζy1[i]).coeffs[2:order + 1] .= zero((ζy1[i]).coeffs[1]) + (ζz1[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηy[i]) + (ζz1[i]).coeffs[2:order + 1] .= zero((ζz1[i]).coeffs[1]) + (ζx2[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηy[i]) + (ζx2[i]).coeffs[2:order + 1] .= zero((ζx2[i]).coeffs[1]) + (ζy2[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηz[i]) + (ζy2[i]).coeffs[2:order + 1] .= zero((ζy2[i]).coeffs[1]) + (ζz2[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηx[i]) + (ζz2[i]).coeffs[2:order + 1] .= zero((ζz2[i]).coeffs[1]) + (ζx[i]).coeffs[1] = constant_term(ζx1[i]) - constant_term(ζx2[i]) + (ζx[i]).coeffs[2:order + 1] .= zero((ζx[i]).coeffs[1]) + (ζy[i]).coeffs[1] = constant_term(ζy1[i]) - constant_term(ζy2[i]) + (ζy[i]).coeffs[2:order + 1] .= zero((ζy[i]).coeffs[1]) + (ζz[i]).coeffs[1] = constant_term(ζz1[i]) - constant_term(ζz2[i]) + (ζz[i]).coeffs[2:order + 1] .= zero((ζz[i]).coeffs[1]) + (F_J2_x1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξx[i]) + (F_J2_x1[i]).coeffs[2:order + 1] .= zero((F_J2_x1[i]).coeffs[1]) + (F_J2_y1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξy[i]) + (F_J2_y1[i]).coeffs[2:order + 1] .= zero((F_J2_y1[i]).coeffs[1]) + (F_J2_z1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξz[i]) + (F_J2_z1[i]).coeffs[2:order + 1] .= zero((F_J2_z1[i]).coeffs[1]) + (F_J2_x2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζx[i]) + (F_J2_x2[i]).coeffs[2:order + 1] .= zero((F_J2_x2[i]).coeffs[1]) + (F_J2_y2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζy[i]) + (F_J2_y2[i]).coeffs[2:order + 1] .= zero((F_J2_y2[i]).coeffs[1]) + (F_J2_z2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζz[i]) + (F_J2_z2[i]).coeffs[2:order + 1] .= zero((F_J2_z2[i]).coeffs[1]) + (F_J2_x[i]).coeffs[1] = constant_term(F_J2_x1[i]) + constant_term(F_J2_x2[i]) + (F_J2_x[i]).coeffs[2:order + 1] .= zero((F_J2_x[i]).coeffs[1]) + (F_J2_y[i]).coeffs[1] = constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]) + (F_J2_y[i]).coeffs[2:order + 1] .= zero((F_J2_y[i]).coeffs[1]) + (F_J2_z[i]).coeffs[1] = constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]) + (F_J2_z[i]).coeffs[2:order + 1] .= zero((F_J2_z[i]).coeffs[1]) + end + (tmp1449[i]).coeffs[1] = constant_term(ui[i]) ^ float(constant_term(2)) + (tmp1449[i]).coeffs[2:order + 1] .= zero((tmp1449[i]).coeffs[1]) + (tmp1451[i]).coeffs[1] = constant_term(vi[i]) ^ float(constant_term(2)) + (tmp1451[i]).coeffs[2:order + 1] .= zero((tmp1451[i]).coeffs[1]) + (tmp1452[i]).coeffs[1] = constant_term(tmp1449[i]) + constant_term(tmp1451[i]) + (tmp1452[i]).coeffs[2:order + 1] .= zero((tmp1452[i]).coeffs[1]) + (tmp1454[i]).coeffs[1] = constant_term(wi[i]) ^ float(constant_term(2)) + (tmp1454[i]).coeffs[2:order + 1] .= zero((tmp1454[i]).coeffs[1]) + (v2[i]).coeffs[1] = constant_term(tmp1452[i]) + constant_term(tmp1454[i]) + (v2[i]).coeffs[2:order + 1] .= zero((v2[i]).coeffs[1]) + end + tmp1457.coeffs[1] = constant_term(q[4]) ^ float(constant_term(2)) + tmp1457.coeffs[2:order + 1] .= zero(tmp1457.coeffs[1]) + tmp1459.coeffs[1] = constant_term(q[5]) ^ float(constant_term(2)) + tmp1459.coeffs[2:order + 1] .= zero(tmp1459.coeffs[1]) + tmp1460.coeffs[1] = constant_term(tmp1457) + constant_term(tmp1459) + tmp1460.coeffs[2:order + 1] .= zero(tmp1460.coeffs[1]) + tmp1462.coeffs[1] = constant_term(q[6]) ^ float(constant_term(2)) + tmp1462.coeffs[2:order + 1] .= zero(tmp1462.coeffs[1]) + (v2[N]).coeffs[1] = constant_term(tmp1460) + constant_term(tmp1462) + (v2[N]).coeffs[2:order + 1] .= zero((v2[N]).coeffs[1]) + for i = 1:Nm1 + (temp_004[i]).coeffs[1] = constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]) + (temp_004[i]).coeffs[2:order + 1] .= zero((temp_004[i]).coeffs[1]) + (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(temp_004[i])) + (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) + if UJ_interaction[i] + (tmp1465[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_x[i]) + (tmp1465[i]).coeffs[2:order + 1] .= zero((tmp1465[i]).coeffs[1]) + (temp_accX_i[i]).coeffs[1] = constant_term(accX) - constant_term(tmp1465[i]) + (temp_accX_i[i]).coeffs[2:order + 1] .= zero((temp_accX_i[i]).coeffs[1]) + accX.coeffs[1] = identity(constant_term(temp_accX_i[i])) + accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) + (tmp1467[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_y[i]) + (tmp1467[i]).coeffs[2:order + 1] .= zero((tmp1467[i]).coeffs[1]) + (temp_accY_i[i]).coeffs[1] = constant_term(accY) - constant_term(tmp1467[i]) + (temp_accY_i[i]).coeffs[2:order + 1] .= zero((temp_accY_i[i]).coeffs[1]) + accY.coeffs[1] = identity(constant_term(temp_accY_i[i])) + accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) + (tmp1469[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_z[i]) + (tmp1469[i]).coeffs[2:order + 1] .= zero((tmp1469[i]).coeffs[1]) + (temp_accZ_i[i]).coeffs[1] = constant_term(accZ) - constant_term(tmp1469[i]) + (temp_accZ_i[i]).coeffs[2:order + 1] .= zero((temp_accZ_i[i]).coeffs[1]) + accZ.coeffs[1] = identity(constant_term(temp_accZ_i[i])) + accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) + end + end + (_4ϕj[N]).coeffs[1] = constant_term(4) * constant_term(newtonianNb_Potential[N]) + (_4ϕj[N]).coeffs[2:order + 1] .= zero((_4ϕj[N]).coeffs[1]) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 + (ϕi_plus_4ϕj[i]).coeffs[1] = constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]) + (ϕi_plus_4ϕj[i]).coeffs[2:order + 1] .= zero((ϕi_plus_4ϕj[i]).coeffs[1]) + (tmp1475[i]).coeffs[1] = constant_term(2) * constant_term(v2[i]) + (tmp1475[i]).coeffs[2:order + 1] .= zero((tmp1475[i]).coeffs[1]) + (tmp1477[i]).coeffs[1] = constant_term(4) * constant_term(vi_dot_vj[i]) + (tmp1477[i]).coeffs[2:order + 1] .= zero((tmp1477[i]).coeffs[1]) + (tmp1478[i]).coeffs[1] = constant_term(tmp1475[i]) - constant_term(tmp1477[i]) + (tmp1478[i]).coeffs[2:order + 1] .= zero((tmp1478[i]).coeffs[1]) + (sj2_plus_2si2_minus_4vivj[i]).coeffs[1] = constant_term(tmp1478[i]) + constant_term(v2[N]) + (sj2_plus_2si2_minus_4vivj[i]).coeffs[2:order + 1] .= zero((sj2_plus_2si2_minus_4vivj[i]).coeffs[1]) + (ϕs_and_vs[i]).coeffs[1] = constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]) + (ϕs_and_vs[i]).coeffs[2:order + 1] .= zero((ϕs_and_vs[i]).coeffs[1]) + (Xij_t_Ui[i]).coeffs[1] = constant_term(X[i]) * constant_term(ui[i]) + (Xij_t_Ui[i]).coeffs[2:order + 1] .= zero((Xij_t_Ui[i]).coeffs[1]) + (Yij_t_Vi[i]).coeffs[1] = constant_term(Y[i]) * constant_term(vi[i]) + (Yij_t_Vi[i]).coeffs[2:order + 1] .= zero((Yij_t_Vi[i]).coeffs[1]) + (Zij_t_Wi[i]).coeffs[1] = constant_term(Z[i]) * constant_term(wi[i]) + (Zij_t_Wi[i]).coeffs[2:order + 1] .= zero((Zij_t_Wi[i]).coeffs[1]) + (tmp1484[i]).coeffs[1] = constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]) + (tmp1484[i]).coeffs[2:order + 1] .= zero((tmp1484[i]).coeffs[1]) + (Rij_dot_Vi[i]).coeffs[1] = constant_term(tmp1484[i]) + constant_term(Zij_t_Wi[i]) + (Rij_dot_Vi[i]).coeffs[2:order + 1] .= zero((Rij_dot_Vi[i]).coeffs[1]) + (tmp1487[i]).coeffs[1] = constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)) + (tmp1487[i]).coeffs[2:order + 1] .= zero((tmp1487[i]).coeffs[1]) + (pn1t7[i]).coeffs[1] = constant_term(tmp1487[i]) / constant_term(r_p2[i]) + (pn1t7[i]).coeffs[2:order + 1] .= zero((pn1t7[i]).coeffs[1]) + (tmp1490[i]).coeffs[1] = constant_term(1.5) * constant_term(pn1t7[i]) + (tmp1490[i]).coeffs[2:order + 1] .= zero((tmp1490[i]).coeffs[1]) + (pn1t2_7[i]).coeffs[1] = constant_term(ϕs_and_vs[i]) - constant_term(tmp1490[i]) + (pn1t2_7[i]).coeffs[2:order + 1] .= zero((pn1t2_7[i]).coeffs[1]) + (pn1t1_7[i]).coeffs[1] = constant_term(c_p2) + constant_term(pn1t2_7[i]) + (pn1t1_7[i]).coeffs[2:order + 1] .= zero((pn1t1_7[i]).coeffs[1]) + (pNX_t_X[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(X[i]) + (pNX_t_X[i]).coeffs[2:order + 1] .= zero((pNX_t_X[i]).coeffs[1]) + (pNY_t_Y[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(Y[i]) + (pNY_t_Y[i]).coeffs[2:order + 1] .= zero((pNY_t_Y[i]).coeffs[1]) + (pNZ_t_Z[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(Z[i]) + (pNZ_t_Z[i]).coeffs[2:order + 1] .= zero((pNZ_t_Z[i]).coeffs[1]) + (tmp1497[i]).coeffs[1] = constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]) + (tmp1497[i]).coeffs[2:order + 1] .= zero((tmp1497[i]).coeffs[1]) + (tmp1498[i]).coeffs[1] = constant_term(tmp1497[i]) + constant_term(pNZ_t_Z[i]) + (tmp1498[i]).coeffs[2:order + 1] .= zero((tmp1498[i]).coeffs[1]) + (tmp1499[i]).coeffs[1] = constant_term(0.5) * constant_term(tmp1498[i]) + (tmp1499[i]).coeffs[2:order + 1] .= zero((tmp1499[i]).coeffs[1]) + (pn1[i]).coeffs[1] = constant_term(pn1t1_7[i]) + constant_term(tmp1499[i]) + (pn1[i]).coeffs[2:order + 1] .= zero((pn1[i]).coeffs[1]) + (X_t_pn1[i]).coeffs[1] = constant_term(newton_acc_X[i]) * constant_term(pn1[i]) + (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) + (Y_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Y[i]) * constant_term(pn1[i]) + (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) + (Z_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Z[i]) * constant_term(pn1[i]) + (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) + (pNX_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(pn3[i]) + (pNX_t_pn3[i]).coeffs[2:order + 1] .= zero((pNX_t_pn3[i]).coeffs[1]) + (pNY_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]) + (pNY_t_pn3[i]).coeffs[2:order + 1] .= zero((pNY_t_pn3[i]).coeffs[1]) + (pNZ_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(pn3[i]) + (pNZ_t_pn3[i]).coeffs[2:order + 1] .= zero((pNZ_t_pn3[i]).coeffs[1]) + end + for i = 1:10 + (tmp1507[i]).coeffs[1] = constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]) + (tmp1507[i]).coeffs[2:order + 1] .= zero((tmp1507[i]).coeffs[1]) + (termpnx[i]).coeffs[1] = constant_term(X_t_pn1[i]) + constant_term(tmp1507[i]) + (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) + (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) + (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) + pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) + pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) + (tmp1510[i]).coeffs[1] = constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]) + (tmp1510[i]).coeffs[2:order + 1] .= zero((tmp1510[i]).coeffs[1]) + (termpny[i]).coeffs[1] = constant_term(Y_t_pn1[i]) + constant_term(tmp1510[i]) + (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) + (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) + (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) + pntempY.coeffs[1] = identity(constant_term(sumpny[i])) + pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) + (tmp1513[i]).coeffs[1] = constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]) + (tmp1513[i]).coeffs[2:order + 1] .= zero((tmp1513[i]).coeffs[1]) + (termpnz[i]).coeffs[1] = constant_term(Z_t_pn1[i]) + constant_term(tmp1513[i]) + (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) + (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) + (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) + pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) + pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) + end + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 + (X_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_X[i]) + (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) + (Y_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Y[i]) + (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) + (Z_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Z[i]) + (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) + end + for i = 11:Nm1 + (termpnx[i]).coeffs[1] = identity(constant_term(X_t_pn1[i])) + (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) + (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) + (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) + pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) + pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) + (termpny[i]).coeffs[1] = identity(constant_term(Y_t_pn1[i])) + (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) + (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) + (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) + pntempY.coeffs[1] = identity(constant_term(sumpny[i])) + pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) + (termpnz[i]).coeffs[1] = identity(constant_term(Z_t_pn1[i])) + (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) + (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) + (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) + pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) + pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) + end + postNewtonX.coeffs[1] = constant_term(pntempX) * constant_term(c_m2) + postNewtonX.coeffs[2:order + 1] .= zero(postNewtonX.coeffs[1]) + postNewtonY.coeffs[1] = constant_term(pntempY) * constant_term(c_m2) + postNewtonY.coeffs[2:order + 1] .= zero(postNewtonY.coeffs[1]) + postNewtonZ.coeffs[1] = constant_term(pntempZ) * constant_term(c_m2) + postNewtonZ.coeffs[2:order + 1] .= zero(postNewtonZ.coeffs[1]) + (dq[4]).coeffs[1] = constant_term(postNewtonX) + constant_term(accX) + (dq[4]).coeffs[2:order + 1] .= zero((dq[4]).coeffs[1]) + (dq[5]).coeffs[1] = constant_term(postNewtonY) + constant_term(accY) + (dq[5]).coeffs[2:order + 1] .= zero((dq[5]).coeffs[1]) + (dq[6]).coeffs[1] = constant_term(postNewtonZ) + constant_term(accZ) + (dq[6]).coeffs[2:order + 1] .= zero((dq[6]).coeffs[1]) + for __idx = eachindex(q) + (q[__idx]).coeffs[2] = (dq[__idx]).coeffs[1] + end + for ord = 1:order - 1 + ordnext = ord + 1 + TaylorSeries.identity!(pntempX, zero_q_1, ord) + TaylorSeries.identity!(pntempY, zero_q_1, ord) + TaylorSeries.identity!(pntempZ, zero_q_1, ord) + TaylorSeries.identity!(accX, zero_q_1, ord) + TaylorSeries.identity!(accY, zero_q_1, ord) + TaylorSeries.identity!(accZ, zero_q_1, ord) + TaylorSeries.identity!(dq[1], q[4], ord) + TaylorSeries.identity!(dq[2], q[5], ord) + TaylorSeries.identity!(dq[3], q[6], ord) + TaylorSeries.identity!(newtonianNb_Potential[N], zero_q_1, ord) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 + TaylorSeries.identity!(ui[i], ss16asteph_t[3 * ((N - 1) + i) - 2], ord) + TaylorSeries.identity!(vi[i], ss16asteph_t[3 * ((N - 1) + i) - 1], ord) + TaylorSeries.identity!(wi[i], ss16asteph_t[3 * ((N - 1) + i)], ord) + TaylorSeries.subst!(X[i], ss16asteph_t[3i - 2], q[1], ord) + TaylorSeries.subst!(Y[i], ss16asteph_t[3i - 1], q[2], ord) + TaylorSeries.subst!(Z[i], ss16asteph_t[3i], q[3], ord) + TaylorSeries.subst!(U[i], ui[i], dq[1], ord) + TaylorSeries.subst!(V[i], vi[i], dq[2], ord) + TaylorSeries.subst!(W[i], wi[i], dq[3], ord) + TaylorSeries.mul!(tmp1317[1], 4, dq[1], ord) + TaylorSeries.mul!(tmp1319[i], 3, ui[i], ord) + TaylorSeries.subst!(_4U_m_3X[i], tmp1317[1], tmp1319[i], ord) + TaylorSeries.mul!(tmp1322[2], 4, dq[2], ord) + TaylorSeries.mul!(tmp1324[i], 3, vi[i], ord) + TaylorSeries.subst!(_4V_m_3Y[i], tmp1322[2], tmp1324[i], ord) + TaylorSeries.mul!(tmp1327[3], 4, dq[3], ord) + TaylorSeries.mul!(tmp1329[i], 3, wi[i], ord) + TaylorSeries.subst!(_4W_m_3Z[i], tmp1327[3], tmp1329[i], ord) + TaylorSeries.mul!(pn2x[i], X[i], _4U_m_3X[i], ord) + TaylorSeries.mul!(pn2y[i], Y[i], _4V_m_3Y[i], ord) + TaylorSeries.mul!(pn2z[i], Z[i], _4W_m_3Z[i], ord) + TaylorSeries.mul!(UU[i], ui[i], dq[1], ord) + TaylorSeries.mul!(VV[i], vi[i], dq[2], ord) + TaylorSeries.mul!(WW[i], wi[i], dq[3], ord) + TaylorSeries.add!(tmp1337[i], UU[i], VV[i], ord) + TaylorSeries.add!(vi_dot_vj[i], tmp1337[i], WW[i], ord) + TaylorSeries.pow!(tmp1340[i], X[i], 2, ord) + TaylorSeries.pow!(tmp1342[i], Y[i], 2, ord) + TaylorSeries.add!(tmp1343[i], tmp1340[i], tmp1342[i], ord) + TaylorSeries.pow!(tmp1345[i], Z[i], 2, ord) + TaylorSeries.add!(r_p2[i], tmp1343[i], tmp1345[i], ord) + TaylorSeries.sqrt!(r_p1d2[i], r_p2[i], ord) + TaylorSeries.pow!(r_p3d2[i], r_p2[i], 1.5, ord) + TaylorSeries.pow!(r_p7d2[i], r_p2[i], 3.5, ord) + TaylorSeries.div!(newtonianCoeff[i], μ[i], r_p3d2[i], ord) + TaylorSeries.add!(tmp1353[i], pn2x[i], pn2y[i], ord) + TaylorSeries.add!(tmp1354[i], tmp1353[i], pn2z[i], ord) + TaylorSeries.mul!(pn2[i], newtonianCoeff[i], tmp1354[i], ord) + TaylorSeries.mul!(newton_acc_X[i], X[i], newtonianCoeff[i], ord) + TaylorSeries.mul!(newton_acc_Y[i], Y[i], newtonianCoeff[i], ord) + TaylorSeries.mul!(newton_acc_Z[i], Z[i], newtonianCoeff[i], ord) + TaylorSeries.div!(newtonian1b_Potential[i], μ[i], r_p1d2[i], ord) + TaylorSeries.mul!(pn3[i], 3.5, newtonian1b_Potential[i], ord) + TaylorSeries.mul!(U_t_pn2[i], pn2[i], U[i], ord) + TaylorSeries.mul!(V_t_pn2[i], pn2[i], V[i], ord) + TaylorSeries.mul!(W_t_pn2[i], pn2[i], W[i], ord) + if UJ_interaction[i] + TaylorSeries.subst!(tmp1365[i], X[i], ord) + TaylorSeries.mul!(t31[i], tmp1365[i], M_[1, 3, i], ord) + TaylorSeries.subst!(tmp1367[i], Y[i], ord) + TaylorSeries.mul!(t32[i], tmp1367[i], M_[2, 3, i], ord) + TaylorSeries.subst!(tmp1369[i], Z[i], ord) + TaylorSeries.mul!(t33[i], tmp1369[i], M_[3, 3, i], ord) + TaylorSeries.add!(tmp1371[i], t31[i], t32[i], ord) + TaylorSeries.add!(r_sin_ϕ[i], tmp1371[i], t33[i], ord) + TaylorSeries.div!(sin_ϕ[i], r_sin_ϕ[i], r_p1d2[i], ord) + TaylorSeries.asin!(ϕ[i], sin_ϕ[i], tmp1528[i], ord) + TaylorSeries.sincos!(tmp1529[i], cos_ϕ[i], ϕ[i], ord) + TaylorSeries.pow!(sin2_ϕ[i], sin_ϕ[i], 2, ord) + TaylorSeries.pow!(sin3_ϕ[i], sin_ϕ[i], 3, ord) + TaylorSeries.mul!(tmp1381[i], 1.5, sin2_ϕ[i], ord) + TaylorSeries.subst!(P_2_sin_ϕ[i], tmp1381[i], 0.5, ord) + TaylorSeries.mul!(∂P_2_sin_ϕ[i], 3, sin_ϕ[i], ord) + TaylorSeries.mul!(tmp1387[i], -1.5, sin_ϕ[i], ord) + TaylorSeries.mul!(tmp1389[i], 2.5, sin3_ϕ[i], ord) + TaylorSeries.add!(P_3_sin_ϕ[i], tmp1387[i], tmp1389[i], ord) + TaylorSeries.mul!(tmp1393[i], 7.5, sin2_ϕ[i], ord) + TaylorSeries.add!(∂P_3_sin_ϕ[i], -1.5, tmp1393[i], ord) + TaylorSeries.pow!(tmp1396[i], r_p2[i], 2, ord) + TaylorSeries.div!(tmp1397[i], Λ2[i], tmp1396[i], ord) + TaylorSeries.subst!(Λ2j_div_r4[i], tmp1397[i], ord) + TaylorSeries.pow!(tmp1400[i], r_p1d2[i], 5, ord) + TaylorSeries.div!(tmp1401[i], Λ3[i], tmp1400[i], ord) + TaylorSeries.subst!(Λ3j_div_r5[i], tmp1401[i], ord) + TaylorSeries.subst!(tmp1403[i], cos_ϕ[i], ord) + TaylorSeries.mul!(m_c_ϕ_∂P_2[i], tmp1403[i], ∂P_2_sin_ϕ[i], ord) + TaylorSeries.subst!(tmp1405[i], cos_ϕ[i], ord) + TaylorSeries.mul!(m_c_ϕ_∂P_3[i], tmp1405[i], ∂P_3_sin_ϕ[i], ord) + TaylorSeries.mul!(tmp1408[i], Λ2j_div_r4[i], 3, ord) + TaylorSeries.mul!(F_J2_ξ[i], tmp1408[i], P_2_sin_ϕ[i], ord) + TaylorSeries.mul!(F_J2_ζ[i], Λ2j_div_r4[i], m_c_ϕ_∂P_2[i], ord) + TaylorSeries.mul!(tmp1412[i], Λ3j_div_r5[i], 4, ord) + TaylorSeries.mul!(F_J3_ξ[i], tmp1412[i], P_3_sin_ϕ[i], ord) + TaylorSeries.mul!(F_J3_ζ[i], Λ3j_div_r5[i], m_c_ϕ_∂P_3[i], ord) + TaylorSeries.identity!(F_J_ξ[i], F_J2_ξ[i], ord) + TaylorSeries.identity!(F_J_ζ[i], F_J2_ζ[i], ord) + TaylorSeries.subst!(tmp1415[i], X[i], ord) + TaylorSeries.div!(ξx[i], tmp1415[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp1417[i], Y[i], ord) + TaylorSeries.div!(ξy[i], tmp1417[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp1419[i], Z[i], ord) + TaylorSeries.div!(ξz[i], tmp1419[i], r_p1d2[i], ord) + TaylorSeries.mul!(ηx1[i], M_[2, 3, i], ξz[i], ord) + TaylorSeries.mul!(ηy1[i], M_[3, 3, i], ξx[i], ord) + TaylorSeries.mul!(ηz1[i], M_[1, 3, i], ξy[i], ord) + TaylorSeries.mul!(ηx2[i], M_[3, 3, i], ξy[i], ord) + TaylorSeries.mul!(ηy2[i], M_[1, 3, i], ξz[i], ord) + TaylorSeries.mul!(ηz2[i], M_[2, 3, i], ξx[i], ord) + TaylorSeries.subst!(ηx[i], ηx1[i], ηx2[i], ord) + TaylorSeries.subst!(ηy[i], ηy1[i], ηy2[i], ord) + TaylorSeries.subst!(ηz[i], ηz1[i], ηz2[i], ord) + TaylorSeries.mul!(ζx1[i], ξy[i], ηz[i], ord) + TaylorSeries.mul!(ζy1[i], ξz[i], ηx[i], ord) + TaylorSeries.mul!(ζz1[i], ξx[i], ηy[i], ord) + TaylorSeries.mul!(ζx2[i], ξz[i], ηy[i], ord) + TaylorSeries.mul!(ζy2[i], ξx[i], ηz[i], ord) + TaylorSeries.mul!(ζz2[i], ξy[i], ηx[i], ord) + TaylorSeries.subst!(ζx[i], ζx1[i], ζx2[i], ord) + TaylorSeries.subst!(ζy[i], ζy1[i], ζy2[i], ord) + TaylorSeries.subst!(ζz[i], ζz1[i], ζz2[i], ord) + TaylorSeries.mul!(F_J2_x1[i], F_J_ξ[i], ξx[i], ord) + TaylorSeries.mul!(F_J2_y1[i], F_J_ξ[i], ξy[i], ord) + TaylorSeries.mul!(F_J2_z1[i], F_J_ξ[i], ξz[i], ord) + TaylorSeries.mul!(F_J2_x2[i], F_J_ζ[i], ζx[i], ord) + TaylorSeries.mul!(F_J2_y2[i], F_J_ζ[i], ζy[i], ord) + TaylorSeries.mul!(F_J2_z2[i], F_J_ζ[i], ζz[i], ord) + TaylorSeries.add!(F_J2_x[i], F_J2_x1[i], F_J2_x2[i], ord) + TaylorSeries.add!(F_J2_y[i], F_J2_y1[i], F_J2_y2[i], ord) + TaylorSeries.add!(F_J2_z[i], F_J2_z1[i], F_J2_z2[i], ord) + end + TaylorSeries.pow!(tmp1449[i], ui[i], 2, ord) + TaylorSeries.pow!(tmp1451[i], vi[i], 2, ord) + TaylorSeries.add!(tmp1452[i], tmp1449[i], tmp1451[i], ord) + TaylorSeries.pow!(tmp1454[i], wi[i], 2, ord) + TaylorSeries.add!(v2[i], tmp1452[i], tmp1454[i], ord) + end + TaylorSeries.pow!(tmp1457, q[4], 2, ord) + TaylorSeries.pow!(tmp1459, q[5], 2, ord) + TaylorSeries.add!(tmp1460, tmp1457, tmp1459, ord) + TaylorSeries.pow!(tmp1462, q[6], 2, ord) + TaylorSeries.add!(v2[N], tmp1460, tmp1462, ord) + for i = 1:Nm1 + TaylorSeries.add!(temp_004[i], newtonian1b_Potential[i], newtonianNb_Potential[N], ord) + TaylorSeries.identity!(newtonianNb_Potential[N], temp_004[i], ord) + if UJ_interaction[i] + TaylorSeries.mul!(tmp1465[i], μ[i], F_J2_x[i], ord) + TaylorSeries.subst!(temp_accX_i[i], accX, tmp1465[i], ord) + TaylorSeries.identity!(accX, temp_accX_i[i], ord) + TaylorSeries.mul!(tmp1467[i], μ[i], F_J2_y[i], ord) + TaylorSeries.subst!(temp_accY_i[i], accY, tmp1467[i], ord) + TaylorSeries.identity!(accY, temp_accY_i[i], ord) + TaylorSeries.mul!(tmp1469[i], μ[i], F_J2_z[i], ord) + TaylorSeries.subst!(temp_accZ_i[i], accZ, tmp1469[i], ord) + TaylorSeries.identity!(accZ, temp_accZ_i[i], ord) + end + end + TaylorSeries.mul!(_4ϕj[N], 4, newtonianNb_Potential[N], ord) + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 + TaylorSeries.add!(ϕi_plus_4ϕj[i], newtonianNb_Potential_t[i], _4ϕj[N], ord) + TaylorSeries.mul!(tmp1475[i], 2, v2[i], ord) + TaylorSeries.mul!(tmp1477[i], 4, vi_dot_vj[i], ord) + TaylorSeries.subst!(tmp1478[i], tmp1475[i], tmp1477[i], ord) + TaylorSeries.add!(sj2_plus_2si2_minus_4vivj[i], tmp1478[i], v2[N], ord) + TaylorSeries.subst!(ϕs_and_vs[i], sj2_plus_2si2_minus_4vivj[i], ϕi_plus_4ϕj[i], ord) + TaylorSeries.mul!(Xij_t_Ui[i], X[i], ui[i], ord) + TaylorSeries.mul!(Yij_t_Vi[i], Y[i], vi[i], ord) + TaylorSeries.mul!(Zij_t_Wi[i], Z[i], wi[i], ord) + TaylorSeries.add!(tmp1484[i], Xij_t_Ui[i], Yij_t_Vi[i], ord) + TaylorSeries.add!(Rij_dot_Vi[i], tmp1484[i], Zij_t_Wi[i], ord) + TaylorSeries.pow!(tmp1487[i], Rij_dot_Vi[i], 2, ord) + TaylorSeries.div!(pn1t7[i], tmp1487[i], r_p2[i], ord) + TaylorSeries.mul!(tmp1490[i], 1.5, pn1t7[i], ord) + TaylorSeries.subst!(pn1t2_7[i], ϕs_and_vs[i], tmp1490[i], ord) + TaylorSeries.add!(pn1t1_7[i], c_p2, pn1t2_7[i], ord) + TaylorSeries.mul!(pNX_t_X[i], acceph_t[3i - 2], X[i], ord) + TaylorSeries.mul!(pNY_t_Y[i], acceph_t[3i - 1], Y[i], ord) + TaylorSeries.mul!(pNZ_t_Z[i], acceph_t[3i], Z[i], ord) + TaylorSeries.add!(tmp1497[i], pNX_t_X[i], pNY_t_Y[i], ord) + TaylorSeries.add!(tmp1498[i], tmp1497[i], pNZ_t_Z[i], ord) + TaylorSeries.mul!(tmp1499[i], 0.5, tmp1498[i], ord) + TaylorSeries.add!(pn1[i], pn1t1_7[i], tmp1499[i], ord) + TaylorSeries.mul!(X_t_pn1[i], newton_acc_X[i], pn1[i], ord) + TaylorSeries.mul!(Y_t_pn1[i], newton_acc_Y[i], pn1[i], ord) + TaylorSeries.mul!(Z_t_pn1[i], newton_acc_Z[i], pn1[i], ord) + TaylorSeries.mul!(pNX_t_pn3[i], acceph_t[3i - 2], pn3[i], ord) + TaylorSeries.mul!(pNY_t_pn3[i], acceph_t[3i - 1], pn3[i], ord) + TaylorSeries.mul!(pNZ_t_pn3[i], acceph_t[3i], pn3[i], ord) + end + for i = 1:10 + TaylorSeries.add!(tmp1507[i], U_t_pn2[i], pNX_t_pn3[i], ord) + TaylorSeries.add!(termpnx[i], X_t_pn1[i], tmp1507[i], ord) + TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) + TaylorSeries.identity!(pntempX, sumpnx[i], ord) + TaylorSeries.add!(tmp1510[i], V_t_pn2[i], pNY_t_pn3[i], ord) + TaylorSeries.add!(termpny[i], Y_t_pn1[i], tmp1510[i], ord) + TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) + TaylorSeries.identity!(pntempY, sumpny[i], ord) + TaylorSeries.add!(tmp1513[i], W_t_pn2[i], pNZ_t_pn3[i], ord) + TaylorSeries.add!(termpnz[i], Z_t_pn1[i], tmp1513[i], ord) + TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) + TaylorSeries.identity!(pntempZ, sumpnz[i], ord) + end + #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 + TaylorSeries.mul!(X_t_pn1[i], c_p2, newton_acc_X[i], ord) + TaylorSeries.mul!(Y_t_pn1[i], c_p2, newton_acc_Y[i], ord) + TaylorSeries.mul!(Z_t_pn1[i], c_p2, newton_acc_Z[i], ord) + end + for i = 11:Nm1 + TaylorSeries.identity!(termpnx[i], X_t_pn1[i], ord) + TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) + TaylorSeries.identity!(pntempX, sumpnx[i], ord) + TaylorSeries.identity!(termpny[i], Y_t_pn1[i], ord) + TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) + TaylorSeries.identity!(pntempY, sumpny[i], ord) + TaylorSeries.identity!(termpnz[i], Z_t_pn1[i], ord) + TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) + TaylorSeries.identity!(pntempZ, sumpnz[i], ord) + end + TaylorSeries.mul!(postNewtonX, pntempX, c_m2, ord) + TaylorSeries.mul!(postNewtonY, pntempY, c_m2, ord) + TaylorSeries.mul!(postNewtonZ, pntempZ, c_m2, ord) + TaylorSeries.add!(dq[4], postNewtonX, accX, ord) + TaylorSeries.add!(dq[5], postNewtonY, accY, ord) + TaylorSeries.add!(dq[6], postNewtonZ, accZ, ord) + for __idx = eachindex(q) + (q[__idx]).coeffs[ordnext + 1] = (dq[__idx]).coeffs[ordnext] / ordnext + end + end + return nothing end \ No newline at end of file diff --git a/src/propagation/parameters.jl b/src/propagation/parameters.jl index 67504441..4136429a 100644 --- a/src/propagation/parameters.jl +++ b/src/propagation/parameters.jl @@ -104,7 +104,7 @@ function NEOParameters(params::NEOParameters{T}; kwargs...) where {T <: Abstract vals = Vector{Any}(undef, length(fields)) for i in eachindex(vals) if fields[i] in keys(kwargs) - vals[i] = kwargs[i] + vals[i] = kwargs[fields[i]] else vals[i] = getfield(params, i) end diff --git a/src/propagation/propagation.jl b/src/propagation/propagation.jl old mode 100755 new mode 100644 diff --git a/test/observations.jl b/test/observations.jl old mode 100755 new mode 100644 index 066004f4..166467d8 --- a/test/observations.jl +++ b/test/observations.jl @@ -1,304 +1,304 @@ -# This file is part of the NEOs.jl package; MIT licensed - -using NEOs -using Dates -using Test - -using NEOs: src_path - -@testset "Observations" begin - - @testset "CatalogueMPC" begin - - using NEOs: CATALOGUE_MPC_REGEX, CatalogueMPC, isunknown - - # Check global variable NEOs.CATALOGUES_MPC[] - @test allunique(NEOs.CATALOGUES_MPC[]) - @test isa(NEOs.CATALOGUES_MPC[], Vector{CatalogueMPC}) - - # Parse CatalogueMPC - gaia_s = " 6 Gaia2016" - gaia_m = match(CATALOGUE_MPC_REGEX, gaia_s) - gaia = CatalogueMPC(gaia_m) - @test gaia.code == "6" - @test gaia.name == "Gaia2016" - - # Unknown catalogue - unkcat = unknowncat() - @test isunknown(unkcat) - @test !isunknown(gaia) - - # Catalogue equality - @test unkcat == unkcat - @test gaia == gaia - @test gaia != unkcat - - # Read/write catalogues file - check_file = joinpath(dirname(src_path), "test", "data", "CatalogueCodes.txt") - write_catalogues_mpc(NEOs.CATALOGUES_MPC[], check_file) - check_cat = read_catalogues_mpc(check_file) - rm(check_file) - @test NEOs.CATALOGUES_MPC[] == check_cat - - # Update catalogues file - update_catalogues_mpc() - @test allunique(NEOs.CATALOGUES_MPC[]) - @test isa(NEOs.CATALOGUES_MPC[], Vector{CatalogueMPC}) - - # Search catalogue code - cat = search_cat_code("6") - @test cat == gaia - end - - @testset "ObservatoryMPC" begin - - using NEOs: OBSERVATORY_MPC_REGEX, ObservatoryMPC, isunknown - - # Check global variable NEOs.OBSERVATORIES_MPC[] - @test allunique(NEOs.OBSERVATORIES_MPC[]) - @test isa(NEOs.OBSERVATORIES_MPC[], Vector{ObservatoryMPC{Float64}}) - - # Parse ObservatoryMPC - arecibo_s = "251 293.246920.949577+0.312734Arecibo" - arecibo_m = match(OBSERVATORY_MPC_REGEX, arecibo_s) - arecibo = ObservatoryMPC(arecibo_m) - @test arecibo.code == "251" - @test arecibo.long == 293.24692 - @test arecibo.cos == 0.949577 - @test arecibo.sin == +0.312734 - @test arecibo.name == "Arecibo" - - hubble_s = "250 Hubble Space Telescope" - hubble_m = match(OBSERVATORY_MPC_REGEX, hubble_s) - hubble = ObservatoryMPC(hubble_m) - @test hubble.code == "250" - @test isnan(hubble.long) - @test isnan(hubble.cos) - @test isnan(hubble.sin) - @test hubble.name == "Hubble Space Telescope" - - # Unknown observatory - unkobs = unknownobs() - @test isunknown(unkobs) - @test !isunknown(arecibo) - @test !isunknown(hubble) - - # hascoord - @test hascoord(arecibo) - @test !hascoord(hubble) - @test !hascoord(unkobs) - - # Catalogue equality - @test unkobs == unkobs - @test arecibo == arecibo - @test hubble == hubble - @test arecibo != unkobs - @test hubble != unkobs - @test arecibo != hubble - - # Read/write observatories file - check_file = joinpath(dirname(src_path), "test", "data", "ObsCodes.txt") - write_observatories_mpc(NEOs.OBSERVATORIES_MPC[], check_file) - check_obs = read_observatories_mpc(check_file) - rm(check_file) - @test NEOs.OBSERVATORIES_MPC[] == check_obs - - # Update observatories file - update_observatories_mpc() - @test allunique(NEOs.OBSERVATORIES_MPC[]) - @test isa(NEOs.OBSERVATORIES_MPC[], Vector{ObservatoryMPC{Float64}}) - - # Search observatory code - obs = search_obs_code("250") - @test obs == hubble - obs = search_obs_code("251") - @test obs == arecibo - end - - @testset "RadecMPC" begin - - using NEOs: RADEC_MPC_REGEX, RadecMPC - using Dates - - # Parse RadecMPC - apophis_s = "99942K04M04N C2004 03 15.10789 04 06 08.08 +16 55 04.6 om6394691" - apophis_m = match(RADEC_MPC_REGEX, apophis_s) - apophis = RadecMPC(apophis_m) - @test apophis.num == "99942" - @test apophis.tmpdesig == "K04M04N" - @test apophis.discovery == "" - @test apophis.publishnote == "" - @test apophis.obstech == "C" - @test apophis.date == DateTime("2004-03-15T02:35:21.696") - @test apophis.α == 1.0739650841580173 - @test apophis.δ == 0.2952738332250385 - @test apophis.info1 == "" - @test isnan(apophis.mag) - @test apophis.band == "" - @test apophis.catalogue == search_cat_code("o") - @test apophis.info2 == "m6394" - @test apophis.observatory == search_obs_code("691") - - # RadecMPC equality - @test apophis == apophis - - # Read/write radec file - source_file = joinpath("data", "RADEC_2023_DW.dat") - source_radec = read_radec_mpc(source_file) - - @test isa(source_radec, Vector{RadecMPC{Float64}}) - @test issorted(source_radec) - @test allunique(source_radec) - @test all( length.(string.(source_radec)) .== 80) - - check_file = joinpath("data", "RADEC_2023_DW_.dat") - write_radec_mpc(source_radec, check_file) - check_radec = read_radec_mpc(check_file) - rm(check_file) - - @test source_radec == check_radec - - # Get RadecMPC - source_file = joinpath("data", "99942.txt") - get_radec_mpc("number" => "99942", source_file) - - @test isfile(source_file) - - source_radec = read_radec_mpc(source_file) - rm(source_file) - - @test isa(source_radec, Vector{RadecMPC{Float64}}) - @test issorted(source_radec) - @test allunique(source_radec) - @test all( map(x -> length(string(x)) ∈ [80, 161], source_radec)) - - check_file = joinpath("data", "99942_.txt") - write_radec_mpc(source_radec, check_file) - check_radec = read_radec_mpc(check_file) - rm(check_file) - - @test source_radec == check_radec - end - - @testset "RadarJPL" begin - - using NEOs: RADAR_JPL_REGEX, RadarJPL, RADAR_JPL_DATEFORMAT, ismonostatic - - # Parse RadarJPL - apophis_s = "99942 Apophis (2004 MN4) 2005-01-27 23:31:00 -100849.1434 0.250 Hz 2380 251 251 C" - apophis_m = match(RADAR_JPL_REGEX, apophis_s) - apophis = RadarJPL(Val(false), apophis_m) - @test apophis.id == "99942 Apophis (2004 MN4)" - @test apophis.date == DateTime("2005-01-27 23:31:00", RADAR_JPL_DATEFORMAT) - @test isnan(apophis.Δτ) - @test isnan(apophis.Δτ_σ) - @test apophis.Δτ_units == "" - @test apophis.Δν == -100849.1434 - @test apophis.Δν_σ == 0.250 - @test apophis.Δν_units == "Hz" - @test apophis.freq == 2380.0 - @test apophis.rcvr == search_obs_code("251") - @test apophis.xmit == search_obs_code("251") - @test apophis.bouncepoint == "C" - @test ismonostatic(apophis) - @test !hasdelay(apophis) - @test hasdoppler(apophis) - - # RadarJPL equality - @test apophis == apophis - - # Read/write radar file - source_file = joinpath(dirname(src_path), "data/99942_RADAR_2005_2013.dat") - source_radar = read_radar_jpl(source_file) - check_file = joinpath(dirname(src_path), "data/99942_RADAR_2005_2013_.dat") - write_radar_jpl(source_radar, check_file) - check_radar = read_radar_jpl(check_file) - rm(check_file) - - @test source_radar == check_radar - end - - @testset "Topocentric" begin - using NEOs: TimeOfDay, sunriseset, obsposECEF, obsposvelECI - - # Ground observation - radec_1 = read_radec_mpc(""" - 99942 |C2012 12 12.33230011 28 40.300-26 29 32.10 17.70Vu~0mfl807 - 99942 |C2012 12 12.33730011 28 38.970-26 29 34.80 17.60Vu~0mfl807 - 99942 |C2012 12 12.34221011 28 37.640-26 29 37.50 17.50Vu~0mfl807 - 99942 |C2012 12 12.34712011 28 36.330-26 29 40.00 17.50Vu~0mfl807 - 99942 |C2012 12 12.35054011 28 35.400-26 29 41.80 17.50Vu~0mfl807 - """) - # Sattellite observation - radec_2 = read_radec_mpc(""" - 99942 S2020 12 18.97667011 30 15.530-10 46 20.20 19.00RL~4ROFC51 - 99942 s2020 12 18.9766701 - 5634.1734 - 2466.2657 - 3038.3924 ~4ROFC51 - 99942 S2020 12 19.10732011 30 22.510-10 48 20.00 L~4ROFC51 - 99942 s2020 12 19.1073201 - 5654.1816 - 2501.9465 - 2971.1902 ~4ROFC51 - 99942 S2020 12 19.23810011 30 29.500-10 50 19.60 L~4ROFC51 - 99942 s2020 12 19.2381001 - 5645.7831 - 2512.1036 - 2978.6411 ~4ROFC51 - 99942 S2020 12 19.23822011 30 29.570-10 50 19.20 L~4ROFC51 - 99942 s2020 12 19.2382201 - 5617.3465 - 2486.4031 - 3053.2209 ~4ROFC51 - """) - - # Check parsing - @test length(radec_1) == 5 - @test all( map(x -> x.observatory.code, radec_1) .== "807") - @test length(radec_2) == 4 - @test all( map(x -> x.observatory.code, radec_2) .== "C51") - - # TimeOfDay - tod_1 = TimeOfDay.(radec_1) - tod_2 = TimeOfDay.(radec_2) - # Check - @test allequal(tod_1) - @test tod_1[1].light == :night - @test tod_1[1].start == Date(2012, 12, 11) - @test tod_1[1].stop == Date(2012, 12, 12) - @test tod_1[1].utc == -5 - @test allunique(tod_2) - @test all( getfield.(tod_2, :light) .== :space ) - @test all( date.(radec_2) .== getfield.(tod_2, :start) .== getfield.(tod_2, :start) ) - @test all( getfield.(tod_2, :utc) .== 0 ) - - # Sunrise and sunset - radec = read_radec_mpc("99942 8C2020 12 08.15001011 20 07.510-08 02 54.20 18.50GV~4ROF094") - sun = sunriseset(radec[1]) - @test datetime2julian(sun[1]) ≈ datetime2julian(DateTime("2020-12-08T05:05:59.384")) - @test datetime2julian(sun[2]) ≈ datetime2julian(DateTime("2020-12-08T14:05:49.386")) - - # obsposECEF - ecef_2 = obsposECEF.(radec_2) - @test ecef_2[1] ≈ [-3462.643557087632, 5076.197661798687, -3049.6756672719907] - @test ecef_2[2] ≈ [1351.315736765706, 6027.937408384214, -2982.5146167937583] - @test ecef_2[3] ≈ [5332.067839021762, 3112.403799578623, -2989.9547254809945] - @test ecef_2[4] ≈ [5308.786202404402, 3079.725220466387, -3064.4773721684687] - - # obsposvelECI - eci_2 = obsposvelECI.(radec_2) - @test eci_2[1] == [-5634.1734, -2466.2657, -3038.3924, 0.0, 0.0, 0.0] - @test eci_2[2] == [-5654.1816, -2501.9465, -2971.1902, 0.0, 0.0, 0.0] - @test eci_2[3] == [-5645.7831, -2512.1036, -2978.6411, 0.0, 0.0, 0.0] - @test eci_2[4] == [-5617.3465, -2486.4031, -3053.2209, 0.0, 0.0, 0.0] - - end - - @testset "Tracklet" begin - using NEOs: reduce_tracklets - - # Choose this example because of the discontinuity in α - - # Fetch optical astrometry - radec = fetch_radec_mpc("designation" => "2020 TJ6") - # Reduce tracklets - tracklets = reduce_tracklets(radec) - - # Values by December 19, 2023 - @test length(tracklets) == 5 - @test getfield.(tracklets, :nobs) == [4, 4, 3, 4, 3] - @test tracklets[3].α ≈ 6.2831 atol = 1e-4 - @test tracklets[3].observatory == search_obs_code("J04") - @test tracklets[3].night.utc == -1 - end - -end +# This file is part of the NEOs.jl package; MIT licensed + +using NEOs +using Dates +using Test + +using NEOs: src_path + +@testset "Observations" begin + + @testset "CatalogueMPC" begin + + using NEOs: CATALOGUE_MPC_REGEX, CatalogueMPC, isunknown + + # Check global variable NEOs.CATALOGUES_MPC[] + @test allunique(NEOs.CATALOGUES_MPC[]) + @test isa(NEOs.CATALOGUES_MPC[], Vector{CatalogueMPC}) + + # Parse CatalogueMPC + gaia_s = " 6 Gaia2016" + gaia_m = match(CATALOGUE_MPC_REGEX, gaia_s) + gaia = CatalogueMPC(gaia_m) + @test gaia.code == "6" + @test gaia.name == "Gaia2016" + + # Unknown catalogue + unkcat = unknowncat() + @test isunknown(unkcat) + @test !isunknown(gaia) + + # Catalogue equality + @test unkcat == unkcat + @test gaia == gaia + @test gaia != unkcat + + # Read/write catalogues file + check_file = joinpath(dirname(src_path), "test", "data", "CatalogueCodes.txt") + write_catalogues_mpc(NEOs.CATALOGUES_MPC[], check_file) + check_cat = read_catalogues_mpc(check_file) + rm(check_file) + @test NEOs.CATALOGUES_MPC[] == check_cat + + # Update catalogues file + update_catalogues_mpc() + @test allunique(NEOs.CATALOGUES_MPC[]) + @test isa(NEOs.CATALOGUES_MPC[], Vector{CatalogueMPC}) + + # Search catalogue code + cat = search_cat_code("6") + @test cat == gaia + end + + @testset "ObservatoryMPC" begin + + using NEOs: OBSERVATORY_MPC_REGEX, ObservatoryMPC, isunknown + + # Check global variable NEOs.OBSERVATORIES_MPC[] + @test allunique(NEOs.OBSERVATORIES_MPC[]) + @test isa(NEOs.OBSERVATORIES_MPC[], Vector{ObservatoryMPC{Float64}}) + + # Parse ObservatoryMPC + arecibo_s = "251 293.246920.949577+0.312734Arecibo" + arecibo_m = match(OBSERVATORY_MPC_REGEX, arecibo_s) + arecibo = ObservatoryMPC(arecibo_m) + @test arecibo.code == "251" + @test arecibo.long == 293.24692 + @test arecibo.cos == 0.949577 + @test arecibo.sin == +0.312734 + @test arecibo.name == "Arecibo" + + hubble_s = "250 Hubble Space Telescope" + hubble_m = match(OBSERVATORY_MPC_REGEX, hubble_s) + hubble = ObservatoryMPC(hubble_m) + @test hubble.code == "250" + @test isnan(hubble.long) + @test isnan(hubble.cos) + @test isnan(hubble.sin) + @test hubble.name == "Hubble Space Telescope" + + # Unknown observatory + unkobs = unknownobs() + @test isunknown(unkobs) + @test !isunknown(arecibo) + @test !isunknown(hubble) + + # hascoord + @test hascoord(arecibo) + @test !hascoord(hubble) + @test !hascoord(unkobs) + + # Catalogue equality + @test unkobs == unkobs + @test arecibo == arecibo + @test hubble == hubble + @test arecibo != unkobs + @test hubble != unkobs + @test arecibo != hubble + + # Read/write observatories file + check_file = joinpath(dirname(src_path), "test", "data", "ObsCodes.txt") + write_observatories_mpc(NEOs.OBSERVATORIES_MPC[], check_file) + check_obs = read_observatories_mpc(check_file) + rm(check_file) + @test NEOs.OBSERVATORIES_MPC[] == check_obs + + # Update observatories file + update_observatories_mpc() + @test allunique(NEOs.OBSERVATORIES_MPC[]) + @test isa(NEOs.OBSERVATORIES_MPC[], Vector{ObservatoryMPC{Float64}}) + + # Search observatory code + obs = search_obs_code("250") + @test obs == hubble + obs = search_obs_code("251") + @test obs == arecibo + end + + @testset "RadecMPC" begin + + using NEOs: RADEC_MPC_REGEX, RadecMPC + using Dates + + # Parse RadecMPC + apophis_s = "99942K04M04N C2004 03 15.10789 04 06 08.08 +16 55 04.6 om6394691" + apophis_m = match(RADEC_MPC_REGEX, apophis_s) + apophis = RadecMPC(apophis_m) + @test apophis.num == "99942" + @test apophis.tmpdesig == "K04M04N" + @test apophis.discovery == "" + @test apophis.publishnote == "" + @test apophis.obstech == "C" + @test apophis.date == DateTime("2004-03-15T02:35:21.696") + @test apophis.α == 1.0739650841580173 + @test apophis.δ == 0.2952738332250385 + @test apophis.info1 == "" + @test isnan(apophis.mag) + @test apophis.band == "" + @test apophis.catalogue == search_cat_code("o") + @test apophis.info2 == "m6394" + @test apophis.observatory == search_obs_code("691") + + # RadecMPC equality + @test apophis == apophis + + # Read/write radec file + source_file = joinpath("data", "RADEC_2023_DW.dat") + source_radec = read_radec_mpc(source_file) + + @test isa(source_radec, Vector{RadecMPC{Float64}}) + @test issorted(source_radec) + @test allunique(source_radec) + @test all( length.(string.(source_radec)) .== 80) + + check_file = joinpath("data", "RADEC_2023_DW_.dat") + write_radec_mpc(source_radec, check_file) + check_radec = read_radec_mpc(check_file) + rm(check_file) + + @test source_radec == check_radec + + # Get RadecMPC + source_file = joinpath("data", "99942.txt") + get_radec_mpc("number" => "99942", source_file) + + @test isfile(source_file) + + source_radec = read_radec_mpc(source_file) + rm(source_file) + + @test isa(source_radec, Vector{RadecMPC{Float64}}) + @test issorted(source_radec) + @test allunique(source_radec) + @test all( map(x -> length(string(x)) ∈ [80, 161], source_radec)) + + check_file = joinpath("data", "99942_.txt") + write_radec_mpc(source_radec, check_file) + check_radec = read_radec_mpc(check_file) + rm(check_file) + + @test source_radec == check_radec + end + + @testset "RadarJPL" begin + + using NEOs: RADAR_JPL_REGEX, RadarJPL, RADAR_JPL_DATEFORMAT, ismonostatic + + # Parse RadarJPL + apophis_s = "99942 Apophis (2004 MN4) 2005-01-27 23:31:00 -100849.1434 0.250 Hz 2380 251 251 C" + apophis_m = match(RADAR_JPL_REGEX, apophis_s) + apophis = RadarJPL(Val(false), apophis_m) + @test apophis.id == "99942 Apophis (2004 MN4)" + @test apophis.date == DateTime("2005-01-27 23:31:00", RADAR_JPL_DATEFORMAT) + @test isnan(apophis.Δτ) + @test isnan(apophis.Δτ_σ) + @test apophis.Δτ_units == "" + @test apophis.Δν == -100849.1434 + @test apophis.Δν_σ == 0.250 + @test apophis.Δν_units == "Hz" + @test apophis.freq == 2380.0 + @test apophis.rcvr == search_obs_code("251") + @test apophis.xmit == search_obs_code("251") + @test apophis.bouncepoint == "C" + @test ismonostatic(apophis) + @test !hasdelay(apophis) + @test hasdoppler(apophis) + + # RadarJPL equality + @test apophis == apophis + + # Read/write radar file + source_file = joinpath(dirname(src_path), "data/99942_RADAR_2005_2013.dat") + source_radar = read_radar_jpl(source_file) + check_file = joinpath(dirname(src_path), "data/99942_RADAR_2005_2013_.dat") + write_radar_jpl(source_radar, check_file) + check_radar = read_radar_jpl(check_file) + rm(check_file) + + @test source_radar == check_radar + end + + @testset "Topocentric" begin + using NEOs: TimeOfDay, sunriseset, obsposECEF, obsposvelECI + + # Ground observation + radec_1 = read_radec_mpc(""" + 99942 |C2012 12 12.33230011 28 40.300-26 29 32.10 17.70Vu~0mfl807 + 99942 |C2012 12 12.33730011 28 38.970-26 29 34.80 17.60Vu~0mfl807 + 99942 |C2012 12 12.34221011 28 37.640-26 29 37.50 17.50Vu~0mfl807 + 99942 |C2012 12 12.34712011 28 36.330-26 29 40.00 17.50Vu~0mfl807 + 99942 |C2012 12 12.35054011 28 35.400-26 29 41.80 17.50Vu~0mfl807 + """) + # Sattellite observation + radec_2 = read_radec_mpc(""" + 99942 S2020 12 18.97667011 30 15.530-10 46 20.20 19.00RL~4ROFC51 + 99942 s2020 12 18.9766701 - 5634.1734 - 2466.2657 - 3038.3924 ~4ROFC51 + 99942 S2020 12 19.10732011 30 22.510-10 48 20.00 L~4ROFC51 + 99942 s2020 12 19.1073201 - 5654.1816 - 2501.9465 - 2971.1902 ~4ROFC51 + 99942 S2020 12 19.23810011 30 29.500-10 50 19.60 L~4ROFC51 + 99942 s2020 12 19.2381001 - 5645.7831 - 2512.1036 - 2978.6411 ~4ROFC51 + 99942 S2020 12 19.23822011 30 29.570-10 50 19.20 L~4ROFC51 + 99942 s2020 12 19.2382201 - 5617.3465 - 2486.4031 - 3053.2209 ~4ROFC51 + """) + + # Check parsing + @test length(radec_1) == 5 + @test all( map(x -> x.observatory.code, radec_1) .== "807") + @test length(radec_2) == 4 + @test all( map(x -> x.observatory.code, radec_2) .== "C51") + + # TimeOfDay + tod_1 = TimeOfDay.(radec_1) + tod_2 = TimeOfDay.(radec_2) + # Check + @test allequal(tod_1) + @test tod_1[1].light == :night + @test tod_1[1].start == Date(2012, 12, 11) + @test tod_1[1].stop == Date(2012, 12, 12) + @test tod_1[1].utc == -5 + @test allunique(tod_2) + @test all( getfield.(tod_2, :light) .== :space ) + @test all( date.(radec_2) .== getfield.(tod_2, :start) .== getfield.(tod_2, :start) ) + @test all( getfield.(tod_2, :utc) .== 0 ) + + # Sunrise and sunset + radec = read_radec_mpc("99942 8C2020 12 08.15001011 20 07.510-08 02 54.20 18.50GV~4ROF094") + sun = sunriseset(radec[1]) + @test datetime2julian(sun[1]) ≈ datetime2julian(DateTime("2020-12-08T05:05:59.384")) + @test datetime2julian(sun[2]) ≈ datetime2julian(DateTime("2020-12-08T14:05:49.386")) + + # obsposECEF + ecef_2 = obsposECEF.(radec_2) + @test ecef_2[1] ≈ [-3462.643557087632, 5076.197661798687, -3049.6756672719907] + @test ecef_2[2] ≈ [1351.315736765706, 6027.937408384214, -2982.5146167937583] + @test ecef_2[3] ≈ [5332.067839021762, 3112.403799578623, -2989.9547254809945] + @test ecef_2[4] ≈ [5308.786202404402, 3079.725220466387, -3064.4773721684687] + + # obsposvelECI + eci_2 = obsposvelECI.(radec_2) + @test eci_2[1] == [-5634.1734, -2466.2657, -3038.3924, 0.0, 0.0, 0.0] + @test eci_2[2] == [-5654.1816, -2501.9465, -2971.1902, 0.0, 0.0, 0.0] + @test eci_2[3] == [-5645.7831, -2512.1036, -2978.6411, 0.0, 0.0, 0.0] + @test eci_2[4] == [-5617.3465, -2486.4031, -3053.2209, 0.0, 0.0, 0.0] + + end + + @testset "Tracklet" begin + using NEOs: reduce_tracklets + + # Choose this example because of the discontinuity in α + + # Fetch optical astrometry + radec = fetch_radec_mpc("designation" => "2020 TJ6") + # Reduce tracklets + tracklets = reduce_tracklets(radec) + + # Values by December 19, 2023 + @test length(tracklets) == 5 + @test getfield.(tracklets, :nobs) == [4, 4, 3, 4, 3] + @test tracklets[3].α ≈ 6.2831 atol = 1e-4 + @test tracklets[3].observatory == search_obs_code("J04") + @test tracklets[3].night.utc == -1 + end + +end diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl old mode 100755 new mode 100644 index 8633424b..c801e2ef --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -1,243 +1,244 @@ -# This file is part of the NEOs.jl package; MIT licensed - -using NEOs -using Dates -using PlanetaryEphemeris -using LinearAlgebra -using Test - -using NEOs: NEOSolution, numberofdays - -@testset "Orbit Determination" begin - @testset "Gauss Method" begin - # Load observations - radec = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) - # Parameters - params = NEOParameters(bwdoffset = 0.007, fwdoffset = 0.007) - - # Orbit Determination - sol = orbitdetermination(radec, params) - - # Values by February 24, 2024 - - # Vector of observations - @test length(radec) == 123 - @test numberofdays(radec) < 21.0 - # Orbit solution - @test isa(sol, NEOSolution{Float64, Float64}) - # Tracklets - @test length(sol.tracklets) == 44 - @test sol.tracklets[1].radec[1] == radec[1] - @test sol.tracklets[end].radec[end] == radec[end] - @test issorted(sol.tracklets) - # Backward integration - @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] - @test all( norm.(sol.bwd.x, Inf) .< 2 ) - @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) - # Forward integration - @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] - @test all( norm.(sol.fwd.x, Inf) .< 2 ) - @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) - # Vector of residuals - @test length(sol.res) == 123 - @test iszero(count(outlier.(sol.res))) - # Least squares fit - @test sol.fit.success - @test all( sigmas(sol) .< 1e-4 ) - @test nrms(sol) < 0.38 - # Scalig factors - @test all(sol.scalings .== 1e-6) - # Compatibility with JPL - JPL = [-1.1003339484439327, 0.20772201506095814, 0.04202338912370205, - -0.004735538686138557, -0.010626685053348663, -0.006016258344003866] - @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 6) - end - - @testset "Too Short Arc" begin - # Fetch optical astrometry - radec = fetch_radec_mpc("designation" => "2008 EK68") - - # Parameters - params = NEOParameters(bwdoffset = 0.007, fwdoffset = 0.007) - - # Orbit Determination - sol = orbitdetermination(radec, params) - - # Values by February 24, 2024 - - # Vector of observations - @test length(radec) == 10 - @test numberofdays(radec) < 0.05 - # Orbit solution - @test isa(sol, NEOSolution{Float64, Float64}) - # Tracklets - @test length(sol.tracklets) == 1 - @test sol.tracklets[1].radec[1] == radec[1] - @test sol.tracklets[end].radec[end] == radec[end] - @test issorted(sol.tracklets) - # Backward integration - @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] - @test all( norm.(sol.bwd.x, Inf) .< 2 ) - @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) - # Forward integration - @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] - @test all( norm.(sol.fwd.x, Inf) .< 2 ) - @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) - # Vector of residuals - @test length(sol.res) == 10 - @test iszero(count(outlier.(sol.res))) - # Least squares fit - @test sol.fit.success - @test all( sigmas(sol) .< 6e-3 ) - @test nrms(sol) < 0.85 - # Scalig factors - @test all(sol.scalings .< 1e-5) - # Compatibility with JPL - JPL = [-0.9698333701500199, 0.24036461256880043, 0.10288887522619743, - -0.009512521373861719, -0.015325432152904881, -0.008094623534198382] - @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 0.1) - end - - @testset "Outlier Rejection" begin - # Fetch optical astrometry - radec = fetch_radec_mpc("designation" => "2007 VV7") - - # Parameters - params = NEOParameters(bwdoffset = 0.007, fwdoffset = 0.007) - - # Orbit Determination - sol = orbitdetermination(radec, params) - # Outlier rejection - sol = outlier_rejection(radec, sol, params) - - # Values by February 24, 2024 - - # Vector of observations - @test length(radec) == 21 - @test numberofdays(radec) < 3.03 - # Orbit solution - @test isa(sol, NEOSolution{Float64, Float64}) - # Tracklets - @test length(sol.tracklets) == 4 - @test sol.tracklets[1].radec[1] == radec[1] - @test sol.tracklets[end].radec[end] == radec[end] - @test issorted(sol.tracklets) - # Backward integration - @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] - @test all( norm.(sol.bwd.x, Inf) .< 2 ) - @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) - # Forward integration - @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] - @test all( norm.(sol.fwd.x, Inf) .< 2 ) - @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) - # Vector of residuals - @test length(sol.res) == 21 - @test count(outlier.(sol.res)) == 2 - # Least squares fit - @test sol.fit.success - @test all( sigmas(sol) .< 5e-4 ) - @test nrms(sol) < 0.25 - # Scalig factors - @test all(sol.scalings .< 8e-7) - # Compatibility with JPL - JPL = [0.7673358221902306, 0.6484904294813807, 0.2932331617634889, - -0.011023358761553661, 0.015392684491034429, 0.006528836324700449] - @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 0.1) - end - - @testset "Interesting NEOs" begin - - # 2014 AA hit the Earth around January 2, 2014, 02:49 UTC - - # Fetch optical astrometry - radec = fetch_radec_mpc("designation" => "2014 AA") - - # Parameters - params = NEOParameters(coeffstol = Inf, bwdoffset = 0.007, fwdoffset = 0.007) - - # Orbit Determination - sol = orbitdetermination(radec, params) - - # Values by February 24, 2024 - - # Vector of observations - @test length(radec) == 7 - @test numberofdays(radec) < 0.05 - # Orbit solution - @test isa(sol, NEOSolution{Float64, Float64}) - # Tracklets - @test length(sol.tracklets) == 1 - @test sol.tracklets[1].radec[1] == radec[1] - @test sol.tracklets[end].radec[end] == radec[end] - @test issorted(sol.tracklets) - # Backward integration - @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] - @test all( norm.(sol.bwd.x, Inf) .< 2 ) - @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) - # Forward integration - @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] - @test all( norm.(sol.fwd.x, Inf) .< 1e9 ) - @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) - # Vector of residuals - @test length(sol.res) == 7 - @test iszero(count(outlier.(sol.res))) - # Least squares fit - @test sol.fit.success - @test all( sigmas(sol) .< 1e-3 ) - @test nrms(sol) < 0.13 - # Scalig factors - @test all(sol.scalings .< 1e-5) - # Compatibility with JPL - JPL = [-0.17932853771087842, 0.8874166708545763, 0.38414497114153867, - -0.01755788350351527, -0.005781328974619869, -0.0020073946363600814] - @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 0.3) - - # 2008 TC3 entered the Earth's atmosphere around October 7, 2008, 02:46 UTC - - # Fetch optical astrometry - radec = fetch_radec_mpc("designation" => "2008 TC3") - - # Parameters - params = NEOParameters(coeffstol = Inf, bwdoffset = 0.007, fwdoffset = 0.007) - - # Observations with <1" weight - idxs = findall(x -> x < 1, w8sveres17.(radec)) - # Restricted Orbit Determination - sol = orbitdetermination(radec[idxs], params) - - # Values by February 24, 2024 - - # Vector of observations - @test length(radec) == 883 - @test numberofdays(radec) < 0.80 - # Orbit solution - @test isa(sol, NEOSolution{Float64, Float64}) - # Tracklets - @test length(sol.tracklets) == 2 - @test sol.tracklets[1].radec[1] == radec[idxs[1]] - @test sol.tracklets[end].radec[end] == radec[idxs[end]] - @test issorted(sol.tracklets) - # Backward integration - @test datetime2days(date(radec[idxs[1]])) > sol.bwd.t0 + sol.bwd.t[end] - @test all( norm.(sol.bwd.x, Inf) .< 2 ) - @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) - # Forward integration - @test datetime2days(date(radec[idxs[end]])) < sol.fwd.t0 + sol.fwd.t[end] - @test all( norm.(sol.fwd.x, Inf) .< 1e4 ) - @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) - # Vector of residuals - @test length(sol.res) == 20 - @test iszero(count(outlier.(sol.res))) - # Least squares fit - @test sol.fit.success - @test all( sigmas(sol) .< 2e-5 ) - @test nrms(sol) < 0.30 - # Scalig factors - @test all(sol.scalings .< 1e-5) - # Compatibility with JPL - JPL = [0.9741070119227359, 0.21515061351517384, 0.09390897837680391, - -0.007890445009307178, 0.016062726197198392, 0.006136042043681892] - @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 0.3) - end - +# This file is part of the NEOs.jl package; MIT licensed + +using NEOs +using Dates +using PlanetaryEphemeris +using LinearAlgebra +using Test + +using NEOs: NEOSolution, numberofdays + +@testset "Orbit Determination" begin + @testset "Gauss Method" begin + # Load observations + radec = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) + # Parameters + params = NEOParameters(bwdoffset = 0.007, fwdoffset = 0.007, parse_eqs = false) + params = NEOParameters(params, parse_eqs=true) + + # Orbit Determination + sol = orbitdetermination(radec, params) + + # Values by February 24, 2024 + + # Vector of observations + @test length(radec) == 123 + @test numberofdays(radec) < 21.0 + # Orbit solution + @test isa(sol, NEOSolution{Float64, Float64}) + # Tracklets + @test length(sol.tracklets) == 44 + @test sol.tracklets[1].radec[1] == radec[1] + @test sol.tracklets[end].radec[end] == radec[end] + @test issorted(sol.tracklets) + # Backward integration + @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] + @test all( norm.(sol.bwd.x, Inf) .< 2 ) + @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) + # Forward integration + @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] + @test all( norm.(sol.fwd.x, Inf) .< 2 ) + @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) + # Vector of residuals + @test length(sol.res) == 123 + @test iszero(count(outlier.(sol.res))) + # Least squares fit + @test sol.fit.success + @test all( sigmas(sol) .< 1e-4 ) + @test nrms(sol) < 0.38 + # Scalig factors + @test all(sol.scalings .== 1e-6) + # Compatibility with JPL + JPL = [-1.1003339484439327, 0.20772201506095814, 0.04202338912370205, + -0.004735538686138557, -0.010626685053348663, -0.006016258344003866] + @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 6) + end + + @testset "Too Short Arc" begin + # Fetch optical astrometry + radec = fetch_radec_mpc("designation" => "2008 EK68") + + # Parameters + params = NEOParameters(bwdoffset = 0.007, fwdoffset = 0.007) + + # Orbit Determination + sol = orbitdetermination(radec, params) + + # Values by February 24, 2024 + + # Vector of observations + @test length(radec) == 10 + @test numberofdays(radec) < 0.05 + # Orbit solution + @test isa(sol, NEOSolution{Float64, Float64}) + # Tracklets + @test length(sol.tracklets) == 1 + @test sol.tracklets[1].radec[1] == radec[1] + @test sol.tracklets[end].radec[end] == radec[end] + @test issorted(sol.tracklets) + # Backward integration + @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] + @test all( norm.(sol.bwd.x, Inf) .< 2 ) + @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) + # Forward integration + @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] + @test all( norm.(sol.fwd.x, Inf) .< 2 ) + @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) + # Vector of residuals + @test length(sol.res) == 10 + @test iszero(count(outlier.(sol.res))) + # Least squares fit + @test sol.fit.success + @test all( sigmas(sol) .< 6e-3 ) + @test nrms(sol) < 0.85 + # Scalig factors + @test all(sol.scalings .< 1e-5) + # Compatibility with JPL + JPL = [-0.9698333701500199, 0.24036461256880043, 0.10288887522619743, + -0.009512521373861719, -0.015325432152904881, -0.008094623534198382] + @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 0.1) + end + + @testset "Outlier Rejection" begin + # Fetch optical astrometry + radec = fetch_radec_mpc("designation" => "2007 VV7") + + # Parameters + params = NEOParameters(bwdoffset = 0.007, fwdoffset = 0.007) + + # Orbit Determination + sol = orbitdetermination(radec, params) + # Outlier rejection + sol = outlier_rejection(radec, sol, params) + + # Values by February 24, 2024 + + # Vector of observations + @test length(radec) == 21 + @test numberofdays(radec) < 3.03 + # Orbit solution + @test isa(sol, NEOSolution{Float64, Float64}) + # Tracklets + @test length(sol.tracklets) == 4 + @test sol.tracklets[1].radec[1] == radec[1] + @test sol.tracklets[end].radec[end] == radec[end] + @test issorted(sol.tracklets) + # Backward integration + @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] + @test all( norm.(sol.bwd.x, Inf) .< 2 ) + @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) + # Forward integration + @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] + @test all( norm.(sol.fwd.x, Inf) .< 2 ) + @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) + # Vector of residuals + @test length(sol.res) == 21 + @test count(outlier.(sol.res)) == 2 + # Least squares fit + @test sol.fit.success + @test all( sigmas(sol) .< 5e-4 ) + @test nrms(sol) < 0.25 + # Scalig factors + @test all(sol.scalings .< 8e-7) + # Compatibility with JPL + JPL = [0.7673358221902306, 0.6484904294813807, 0.2932331617634889, + -0.011023358761553661, 0.015392684491034429, 0.006528836324700449] + @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 0.1) + end + + @testset "Interesting NEOs" begin + + # 2014 AA hit the Earth around January 2, 2014, 02:49 UTC + + # Fetch optical astrometry + radec = fetch_radec_mpc("designation" => "2014 AA") + + # Parameters + params = NEOParameters(coeffstol = Inf, bwdoffset = 0.007, fwdoffset = 0.007) + + # Orbit Determination + sol = orbitdetermination(radec, params) + + # Values by February 24, 2024 + + # Vector of observations + @test length(radec) == 7 + @test numberofdays(radec) < 0.05 + # Orbit solution + @test isa(sol, NEOSolution{Float64, Float64}) + # Tracklets + @test length(sol.tracklets) == 1 + @test sol.tracklets[1].radec[1] == radec[1] + @test sol.tracklets[end].radec[end] == radec[end] + @test issorted(sol.tracklets) + # Backward integration + @test datetime2days(date(radec[1])) > sol.bwd.t0 + sol.bwd.t[end] + @test all( norm.(sol.bwd.x, Inf) .< 2 ) + @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) + # Forward integration + @test datetime2days(date(radec[end])) < sol.fwd.t0 + sol.fwd.t[end] + @test all( norm.(sol.fwd.x, Inf) .< 1e9 ) + @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) + # Vector of residuals + @test length(sol.res) == 7 + @test iszero(count(outlier.(sol.res))) + # Least squares fit + @test sol.fit.success + @test all( sigmas(sol) .< 1e-3 ) + @test nrms(sol) < 0.13 + # Scalig factors + @test all(sol.scalings .< 1e-5) + # Compatibility with JPL + JPL = [-0.17932853771087842, 0.8874166708545763, 0.38414497114153867, + -0.01755788350351527, -0.005781328974619869, -0.0020073946363600814] + @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 0.3) + + # 2008 TC3 entered the Earth's atmosphere around October 7, 2008, 02:46 UTC + + # Fetch optical astrometry + radec = fetch_radec_mpc("designation" => "2008 TC3") + + # Parameters + params = NEOParameters(coeffstol = Inf, bwdoffset = 0.007, fwdoffset = 0.007) + + # Observations with <1" weight + idxs = findall(x -> x < 1, w8sveres17.(radec)) + # Restricted Orbit Determination + sol = orbitdetermination(radec[idxs], params) + + # Values by February 24, 2024 + + # Vector of observations + @test length(radec) == 883 + @test numberofdays(radec) < 0.80 + # Orbit solution + @test isa(sol, NEOSolution{Float64, Float64}) + # Tracklets + @test length(sol.tracklets) == 2 + @test sol.tracklets[1].radec[1] == radec[idxs[1]] + @test sol.tracklets[end].radec[end] == radec[idxs[end]] + @test issorted(sol.tracklets) + # Backward integration + @test datetime2days(date(radec[idxs[1]])) > sol.bwd.t0 + sol.bwd.t[end] + @test all( norm.(sol.bwd.x, Inf) .< 2 ) + @test isempty(sol.t_bwd) && isempty(sol.x_bwd) && isempty(sol.g_bwd) + # Forward integration + @test datetime2days(date(radec[idxs[end]])) < sol.fwd.t0 + sol.fwd.t[end] + @test all( norm.(sol.fwd.x, Inf) .< 1e4 ) + @test isempty(sol.t_fwd) && isempty(sol.x_fwd) && isempty(sol.g_fwd) + # Vector of residuals + @test length(sol.res) == 20 + @test iszero(count(outlier.(sol.res))) + # Least squares fit + @test sol.fit.success + @test all( sigmas(sol) .< 2e-5 ) + @test nrms(sol) < 0.30 + # Scalig factors + @test all(sol.scalings .< 1e-5) + # Compatibility with JPL + JPL = [0.9741070119227359, 0.21515061351517384, 0.09390897837680391, + -0.007890445009307178, 0.016062726197198392, 0.006136042043681892] + @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 0.3) + end + end \ No newline at end of file diff --git a/test/propagation.jl b/test/propagation.jl old mode 100755 new mode 100644 index c30f6f03..f0bcf841 --- a/test/propagation.jl +++ b/test/propagation.jl @@ -1,404 +1,404 @@ -# This file is part of the NEOs.jl package; MIT licensed - -using NEOs -using PlanetaryEphemeris -using Dates -using TaylorIntegration -using JLD2 -using Test - -using InteractiveUtils: methodswith - -@testset "Orbit propagation" begin - - @testset "Integration methods" begin - - @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, TaylorIntegration.jetcoeffs!)) - @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, TaylorIntegration._allocate_jetcoeffs!)) - - @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorIntegration.jetcoeffs!)) - @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorIntegration._allocate_jetcoeffs!)) - - end - - using PlanetaryEphemeris: selecteph, ea, su, daysec, auday2kmsec - using Statistics - - @testset "Orbit propagation without nongravs: 2023 DW" begin - - objname = "2023DW" - # Dynamical function - dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! - # Initial time [Julian date] - jd0 = datetime2julian(DateTime(2023, 2, 25, 0, 0, 0)) - # Time of integration [years] - nyears = 0.2 - # Unperturbed initial condition - q0 = [-9.759018085743707E-01, 3.896554445697074E-01, 1.478066121706831E-01, - -9.071450085084557E-03, -9.353197026254517E-03, -5.610023032269034E-03] - # Propagation parameters - params = NEOParameters(maxsteps = 1, order = 25, abstol = 1e-20, - parse_eqs = true) - - # Initial time [days since J2000] - t0 = jd0 - PE.J2000 - # Solar System ephemeris - sseph = loadpeeph(NEOs.sseph, t0 - nyears*yr, t0 + nyears*yr) - # Sun's ephemeris - eph_su = selecteph(sseph, su) - # Earth's ephemeris - eph_ea = selecteph(sseph, ea) - - # Warmup propagation (forward) - NEOs.propagate( - dynamics, - jd0, - nyears, - q0, - params - ) - # Propagate orbit - params = NEOParameters(params; maxsteps = 1_000) - sol_bwd = NEOs.propagate( - dynamics, - jd0, - -nyears, - q0, - params - ) - sol = NEOs.propagate( - dynamics, - jd0, - nyears, - q0, - params - ) - - # Check that solution saves correctly - jldsave("test.jld2"; sol_bwd, sol) - recovered_sol = JLD2.load("test.jld2", "sol") - recovered_sol_bwd = JLD2.load("test.jld2", "sol_bwd") - @test sol == recovered_sol - @test sol_bwd == recovered_sol_bwd - rm("test.jld2") - - @test sol_bwd.t0 == sol.t0 - @test (sol_bwd.t[end]-sol_bwd.t[1])/yr ≈ -nyears - @test (sol.t[end]-sol.t[1])/yr ≈ nyears - @test sol(sol.t0) == q0 - q_fwd_end = [-1.0168239304400228, -0.3800432452351079, -0.2685901784950398, - 0.007623614213394988, -0.00961901551025335, -0.004682171726467166] - @test norm(sol(sol.t0 + sol.t[end])-q_fwd_end, Inf) < 1e-12 - @test sol_bwd(sol_bwd.t0) == q0 - q_bwd_end = [0.2689956497466164, 0.4198851302334139, 0.2438053951982368, - -0.018875911266050937, 0.0167349306087375, 0.007789382070881366] - @test norm(sol_bwd(sol_bwd.t0 + sol_bwd.t[end])-q_bwd_end, Inf) < 1e-12 - - # Read optical astrometry file - - obs_radec_mpc_2023DW = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) - - # Compute residuals - _res_ = NEOs.residuals( - obs_radec_mpc_2023DW, - params, - xve = t -> auday2kmsec(eph_ea(t/daysec)), - xvs = t -> auday2kmsec(eph_su(t/daysec)), - xva = t -> auday2kmsec(sol(t/daysec)) - ) - res, w = NEOs.unfold(_res_) - - mean_radec0 = mean(res) - std_radec0 = std(res) - rms_radec0 = nrms(res, ones(length(res))) # un-normalized RMS - @test mean_radec0 ≈ -0.667 atol=1e-3 - @test std_radec0 ≈ 0.736 atol=1e-3 - @test rms_radec0 ≈ 0.992 atol=1e-3 - - # Propagate orbit with perturbed initial conditions - q1 = q0 + vcat(1e-3randn(3), 1e-5randn(3)) - sol1 = NEOs.propagate( - dynamics, - jd0, - nyears, - q1, - params - ) - - # Check that solution saves correctly - jldsave("test.jld2"; sol1 = sol1) - recovered_sol1 = JLD2.load("test.jld2", "sol1") - @test sol1 == recovered_sol1 - rm("test.jld2") - - # Compute residuals for orbit with perturbed initial conditions - _res1_ = NEOs.residuals( - obs_radec_mpc_2023DW, - params, - xve = t -> auday2kmsec(eph_ea(t/daysec)), - xvs = t -> auday2kmsec(eph_su(t/daysec)), - xva = t -> auday2kmsec(sol1(t/daysec)) - ) - res1, _ = NEOs.unfold(_res1_) - mean_radec1 = mean(res1) - std_radec1 = std(res1) - rms_radec1 = nrms(res1, ones(length(res1))) - - @test abs(mean_radec1) ≥ abs(mean_radec0) - @test std_radec1 ≥ std_radec0 - @test rms_radec1 ≥ rms_radec0 - end - - @testset "Orbit propagation with nongravs: (99942) Apophis" begin - - objname = "Apophis" - # Dynamical function - dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! - # Initial time [Julian date] - jd0 = datetime2julian(DateTime(2004, 6, 1)) - # Time of integration [years] - nyears = 9.0 - # JPL #199 solution for Apophis at June 1st, 2004 - q0 = [-1.0506628055913627, -0.06064314196134998, -0.04997102228887035, - 0.0029591421121582077, -0.01423233538611057, -0.005218412537773594, - -5.592839897872e-14, 0.0] - # Propagation parameters - params = NEOParameters(maxsteps = 1, order = 25, abstol = 1e-20, - parse_eqs = true) - - # Initial time [days since J2000] - t0 = jd0 - PE.J2000 - # Solar System ephemeris - sseph = loadpeeph(NEOs.sseph, t0, t0 + nyears*yr) - # Sun's ephemeris - eph_su = selecteph(sseph, su) - # Earth's ephemeris - eph_ea = selecteph(sseph, ea) - - # Warmup propagation - sol = NEOs.propagate( - dynamics, - jd0, - nyears, - q0, - params - ) - # Propagate orbit - params = NEOParameters(params, maxsteps = 5_000) - sol = NEOs.propagate( - dynamics, - jd0, - nyears, - q0, - params - ) - - # Check that solution saves correctly - jldsave("test.jld2"; sol = sol) - recovered_sol = JLD2.load("test.jld2", "sol") - @test sol == recovered_sol - rm("test.jld2") - - # Read optical astrometry file - obs_radec_mpc_apophis = read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) - - # Compute optical astrometry residuals - _res_radec_ = NEOs.residuals( - obs_radec_mpc_apophis, - params, - xve = t -> auday2kmsec(eph_ea(t/daysec)), - xvs = t -> auday2kmsec(eph_su(t/daysec)), - xva = t -> auday2kmsec(sol(t/daysec)) - ) - res_radec, w_radec = NEOs.unfold(_res_radec_) - nobsopt = round(Int, length(res_radec)) - - # Compute mean optical astrometric residual (right ascension and declination) - res_ra = res_radec[1:round(Int,nobsopt/2)] - res_dec = res_radec[round(Int,nobsopt/2)+1:end] - mean_ra = mean(res_ra) - mean_dec = mean(res_dec) - std_ra = std(res_ra) - std_dec = std(res_dec) - rms_ra = nrms(res_ra,ones(length(res_ra))) - rms_dec = nrms(res_dec,ones(length(res_dec))) - @test mean_ra ≈ 0.0224 atol=1e-4 - @test std_ra ≈ 0.136 atol=1e-3 - @test rms_ra ≈ std_ra atol=1e-2 - @test mean_dec ≈ -0.0124 atol=1e-2 - @test std_dec ≈ 0.0714 atol=1e-2 - @test rms_dec ≈ std_dec atol=1e-2 - - # Read radar astrometry file - deldop_2005_2013 = NEOs.read_radar_jpl(joinpath("data", "99942_RADAR_2005_2013.dat")) - - # Compute mean radar (time-delay and Doppler-shift) residuals - @time res_del, w_del, res_dop, w_dop = residuals( - deldop_2005_2013, - xve = t -> auday2kmsec(eph_ea(t/daysec)), - xvs = t -> auday2kmsec(eph_su(t/daysec)), - xva = t -> auday2kmsec(sol(t/daysec)), - niter = 4, - tord = 5 - ) - - mean_del = mean(res_del) - mean_dop = mean(res_dop) - std_del = std(res_del) - std_dop = std(res_dop) - - @test mean_del ≈ 0.281 atol=1e-2 - @test mean_dop ≈ -0.084 atol=1e-2 - @test std_del ≈ 1.246 atol=1e-2 - @test std_dop ≈ 0.286 atol=1e-2 - - res = vcat(res_radec, res_del, res_dop) - w = vcat(w_radec, w_del, w_dop) - - # Total normalized RMS - @test nrms(res, w) ≈ 0.366 atol=1e-3 - end - - @testset "Jet transport propagation and TaylorN serialization" begin - - # Test integration (Apophis) - - # Dynamical function - dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! - # Initial date of integration [julian days] - jd0 = datetime2julian(DateTime(2029, 4, 13, 20)) - # Time of integration [years] - nyears = 0.02 - # Perturbation to nominal initial condition (Taylor1 jet transport) - dq = NEOs.scaled_variables() - # Initial conditions - q0 = [-0.9170913888342959, -0.37154308794738056, -0.1610606989484252, - 0.009701519087787077, -0.012766026792868212, -0.0043488589639194275] .+ dq - # Propagation parameters - params = NEOParameters(maxsteps = 10, order = 25, abstol = 1e-20, parse_eqs = true) - - # Propagate orbit - sol = NEOs.propagate(dynamics, jd0, nyears, q0, params) - jldsave("test.jld2"; sol) - recovered_sol = JLD2.load("test.jld2", "sol") - @test sol == recovered_sol - rm("test.jld2") - - params = NEOParameters(params; maxsteps = 1) - sol, tvS, xvS, gvS = NEOs.propagate_root(dynamics, jd0, nyears, q0, params) - - jldsave("test.jld2"; sol, tvS, xvS, gvS) - recovered_sol = JLD2.load("test.jld2", "sol") - recovered_tvS = JLD2.load("test.jld2", "tvS") - recovered_xvS = JLD2.load("test.jld2", "xvS") - recovered_gvS = JLD2.load("test.jld2", "gvS") - @test sol == recovered_sol - @test tvS == recovered_tvS - @test xvS == recovered_xvS - @test gvS == recovered_gvS - rm("test.jld2") - - # It is unlikely that such a short integration generates a non-trivial tvS, xvS and gvS. - # Therefore, to test TaylorNSerialization I suggest to generate random TaylorN and check - # it saves correctly... - random_TaylorN = [cos(sum(dq .* rand(6))), sin(sum(dq .* rand(6))), tan(sum(dq .* rand(6)))] - jldsave("test.jld2"; random_TaylorN = random_TaylorN) - recovered_taylorN = JLD2.load("test.jld2", "random_TaylorN") - @test recovered_taylorN == random_TaylorN - rm("test.jld2") - - end - - @testset "Jet transport orbit propagation and astrometric observables: (99942) Apophis" begin - - objname::String = "Apophis" - # Dynamical function - dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! - # Initial date of integration [julian days] - jd0::Float64 = datetime2julian(DateTime(2004, 6, 1)) - # Time of integration [years] - nyears::Float64 = 10.0 - # JPL #199 solution for Apophis at June 1st, 2004 - q00::Vector{Float64} = [-1.0506627988664696, -0.060643124245514164, -0.0499709975200415, 0.0029591416313078838, -0.014232335581939919, -0.0052184125285361415, -2.898870403031058e-14, -0.0] - varorder::Int = 1 - dq::Vector{TaylorN{Float64}} = NEOs.scaled_variables("δx", vcat(fill(1e-8, 6), 1e-14), order = varorder) - q0::Vector{TaylorN{Float64}} = q00 .+ vcat(dq, 0dq[1]) - # Propagation parameters - params = NEOParameters(maxsteps = 2_000, order = 25, abstol = 1e-20, parse_eqs = true) - - # Propagate orbit - sol = NEOs.propagate( - dynamics, - jd0, - nyears, - q0, - params - ) - - # Solar System ephemeris - sseph_obs = loadpeeph(NEOs.sseph, sol.t0, sol.t0 + sol.t[end]) - # Sun's ephemeris - eph_su = selecteph(sseph_obs, su) - # Earth's ephemeris - eph_ea = selecteph(sseph_obs, ea) - - # Read optical astrometry file - obs_radec_mpc_apophis = read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) - - # Compute optical astrometry residuals - _res_radec_ = NEOs.residuals( - obs_radec_mpc_apophis, - params, - xve = t -> auday2kmsec(eph_ea(t/daysec)), - xvs = t -> auday2kmsec(eph_su(t/daysec)), - xva = t -> auday2kmsec(sol(t/daysec)) - ) - res_radec, w_radec = NEOs.unfold(_res_radec_) - nobsopt = round(Int, length(res_radec)) - - # Compute mean optical astrometric residual (right ascension and declination) - res_ra = res_radec[1:round(Int,nobsopt/2)]() - res_dec = res_radec[round(Int,nobsopt/2)+1:end]() - mean_ra = mean(res_ra) - mean_dec = mean(res_dec) - std_ra = std(res_ra) - std_dec = std(res_dec) - rms_ra = nrms(res_ra,ones(length(res_ra))) - rms_dec = nrms(res_dec,ones(length(res_dec))) - @test mean_ra ≈ 0.0083 atol=1e-4 - @test std_ra ≈ 0.136 atol=1e-3 - @test rms_ra ≈ std_ra atol=1e-2 - @test mean_dec ≈ -0.0124 atol=1e-2 - @test std_dec ≈ 0.0714 atol=1e-2 - @test rms_dec ≈ std_dec atol=1e-2 - - # Read radar astrometry file - deldop_2005_2013 = NEOs.read_radar_jpl(joinpath("data", "99942_RADAR_2005_2013.dat")) - - # Compute mean radar (time-delay and Doppler-shift) residuals - @time res_del, w_del, res_dop, w_dop = residuals( - deldop_2005_2013[1:4], - xve = t -> auday2kmsec(eph_ea(t/daysec)), - xvs = t -> auday2kmsec(eph_su(t/daysec)), - xva = t -> auday2kmsec(sol(t/daysec)), - niter=10, - tord=10 - ) - - @test abs(res_dop[1]()) ≤ deldop_2005_2013[1].Δν_σ - @test abs(res_del[1]()) ≤ deldop_2005_2013[2].Δτ_σ - @test abs(res_dop[2]()) ≤ deldop_2005_2013[2].Δν_σ - @test abs(res_del[2]()) ≤ deldop_2005_2013[2].Δτ_σ - @test abs(res_dop[3]()) ≤ deldop_2005_2013[3].Δν_σ - @test abs(res_dop[4]()) ≤ deldop_2005_2013[4].Δν_σ - - dq_sample = 2ones(7) - @test abs(res_dop[1](dq_sample)) ≥ deldop_2005_2013[1].Δν_σ - @test abs(res_del[1](dq_sample)) ≥ deldop_2005_2013[2].Δτ_σ - @test abs(res_dop[2](dq_sample)) ≥ deldop_2005_2013[2].Δν_σ - @test abs(res_del[2](dq_sample)) ≥ deldop_2005_2013[2].Δτ_σ - @test abs(res_dop[3](dq_sample)) ≥ deldop_2005_2013[3].Δν_σ - @test abs(res_dop[4](dq_sample)) ≥ deldop_2005_2013[4].Δν_σ - end - -end +# This file is part of the NEOs.jl package; MIT licensed + +using NEOs +using PlanetaryEphemeris +using Dates +using TaylorIntegration +using JLD2 +using Test + +using InteractiveUtils: methodswith + +@testset "Orbit propagation" begin + + @testset "Integration methods" begin + + @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, TaylorIntegration.jetcoeffs!)) + @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, TaylorIntegration._allocate_jetcoeffs!)) + + @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorIntegration.jetcoeffs!)) + @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorIntegration._allocate_jetcoeffs!)) + + end + + using PlanetaryEphemeris: selecteph, ea, su, daysec, auday2kmsec + using Statistics + + @testset "Orbit propagation without nongravs: 2023 DW" begin + + objname = "2023DW" + # Dynamical function + dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! + # Initial time [Julian date] + jd0 = datetime2julian(DateTime(2023, 2, 25, 0, 0, 0)) + # Time of integration [years] + nyears = 0.2 + # Unperturbed initial condition + q0 = [-9.759018085743707E-01, 3.896554445697074E-01, 1.478066121706831E-01, + -9.071450085084557E-03, -9.353197026254517E-03, -5.610023032269034E-03] + # Propagation parameters + params = NEOParameters(maxsteps = 1, order = 25, abstol = 1e-20, + parse_eqs = true) + + # Initial time [days since J2000] + t0 = jd0 - PE.J2000 + # Solar System ephemeris + sseph = loadpeeph(NEOs.sseph, t0 - nyears*yr, t0 + nyears*yr) + # Sun's ephemeris + eph_su = selecteph(sseph, su) + # Earth's ephemeris + eph_ea = selecteph(sseph, ea) + + # Warmup propagation (forward) + NEOs.propagate( + dynamics, + jd0, + nyears, + q0, + params + ) + # Propagate orbit + params = NEOParameters(params; maxsteps = 1_000) + sol_bwd = NEOs.propagate( + dynamics, + jd0, + -nyears, + q0, + params + ) + sol = NEOs.propagate( + dynamics, + jd0, + nyears, + q0, + params + ) + + # Check that solution saves correctly + jldsave("test.jld2"; sol_bwd, sol) + recovered_sol = JLD2.load("test.jld2", "sol") + recovered_sol_bwd = JLD2.load("test.jld2", "sol_bwd") + @test sol == recovered_sol + @test sol_bwd == recovered_sol_bwd + rm("test.jld2") + + @test sol_bwd.t0 == sol.t0 + @test (sol_bwd.t[end]-sol_bwd.t[1])/yr ≈ -nyears + @test (sol.t[end]-sol.t[1])/yr ≈ nyears + @test sol(sol.t0) == q0 + q_fwd_end = [-1.0168239304400228, -0.3800432452351079, -0.2685901784950398, + 0.007623614213394988, -0.00961901551025335, -0.004682171726467166] + @test norm(sol(sol.t0 + sol.t[end])-q_fwd_end, Inf) < 1e-12 + @test sol_bwd(sol_bwd.t0) == q0 + q_bwd_end = [0.2689956497466164, 0.4198851302334139, 0.2438053951982368, + -0.018875911266050937, 0.0167349306087375, 0.007789382070881366] + @test norm(sol_bwd(sol_bwd.t0 + sol_bwd.t[end])-q_bwd_end, Inf) < 1e-12 + + # Read optical astrometry file + + obs_radec_mpc_2023DW = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) + + # Compute residuals + _res_ = NEOs.residuals( + obs_radec_mpc_2023DW, + params, + xve = t -> auday2kmsec(eph_ea(t/daysec)), + xvs = t -> auday2kmsec(eph_su(t/daysec)), + xva = t -> auday2kmsec(sol(t/daysec)) + ) + res, w = NEOs.unfold(_res_) + + mean_radec0 = mean(res) + std_radec0 = std(res) + rms_radec0 = nrms(res, ones(length(res))) # un-normalized RMS + @test mean_radec0 ≈ -0.667 atol=1e-3 + @test std_radec0 ≈ 0.736 atol=1e-3 + @test rms_radec0 ≈ 0.992 atol=1e-3 + + # Propagate orbit with perturbed initial conditions + q1 = q0 + vcat(1e-3randn(3), 1e-5randn(3)) + sol1 = NEOs.propagate( + dynamics, + jd0, + nyears, + q1, + params + ) + + # Check that solution saves correctly + jldsave("test.jld2"; sol1 = sol1) + recovered_sol1 = JLD2.load("test.jld2", "sol1") + @test sol1 == recovered_sol1 + rm("test.jld2") + + # Compute residuals for orbit with perturbed initial conditions + _res1_ = NEOs.residuals( + obs_radec_mpc_2023DW, + params, + xve = t -> auday2kmsec(eph_ea(t/daysec)), + xvs = t -> auday2kmsec(eph_su(t/daysec)), + xva = t -> auday2kmsec(sol1(t/daysec)) + ) + res1, _ = NEOs.unfold(_res1_) + mean_radec1 = mean(res1) + std_radec1 = std(res1) + rms_radec1 = nrms(res1, ones(length(res1))) + + @test abs(mean_radec1) ≥ abs(mean_radec0) + @test std_radec1 ≥ std_radec0 + @test rms_radec1 ≥ rms_radec0 + end + + @testset "Orbit propagation with nongravs: (99942) Apophis" begin + + objname = "Apophis" + # Dynamical function + dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! + # Initial time [Julian date] + jd0 = datetime2julian(DateTime(2004, 6, 1)) + # Time of integration [years] + nyears = 9.0 + # JPL #199 solution for Apophis at June 1st, 2004 + q0 = [-1.0506628055913627, -0.06064314196134998, -0.04997102228887035, + 0.0029591421121582077, -0.01423233538611057, -0.005218412537773594, + -5.592839897872e-14, 0.0] + # Propagation parameters + params = NEOParameters(maxsteps = 1, order = 25, abstol = 1e-20, + parse_eqs = true) + + # Initial time [days since J2000] + t0 = jd0 - PE.J2000 + # Solar System ephemeris + sseph = loadpeeph(NEOs.sseph, t0, t0 + nyears*yr) + # Sun's ephemeris + eph_su = selecteph(sseph, su) + # Earth's ephemeris + eph_ea = selecteph(sseph, ea) + + # Warmup propagation + sol = NEOs.propagate( + dynamics, + jd0, + nyears, + q0, + params + ) + # Propagate orbit + params = NEOParameters(params, maxsteps = 5_000) + sol = NEOs.propagate( + dynamics, + jd0, + nyears, + q0, + params + ) + + # Check that solution saves correctly + jldsave("test.jld2"; sol = sol) + recovered_sol = JLD2.load("test.jld2", "sol") + @test sol == recovered_sol + rm("test.jld2") + + # Read optical astrometry file + obs_radec_mpc_apophis = read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) + + # Compute optical astrometry residuals + _res_radec_ = NEOs.residuals( + obs_radec_mpc_apophis, + params, + xve = t -> auday2kmsec(eph_ea(t/daysec)), + xvs = t -> auday2kmsec(eph_su(t/daysec)), + xva = t -> auday2kmsec(sol(t/daysec)) + ) + res_radec, w_radec = NEOs.unfold(_res_radec_) + nobsopt = round(Int, length(res_radec)) + + # Compute mean optical astrometric residual (right ascension and declination) + res_ra = res_radec[1:round(Int,nobsopt/2)] + res_dec = res_radec[round(Int,nobsopt/2)+1:end] + mean_ra = mean(res_ra) + mean_dec = mean(res_dec) + std_ra = std(res_ra) + std_dec = std(res_dec) + rms_ra = nrms(res_ra,ones(length(res_ra))) + rms_dec = nrms(res_dec,ones(length(res_dec))) + @test mean_ra ≈ 0.0224 atol=1e-4 + @test std_ra ≈ 0.136 atol=1e-3 + @test rms_ra ≈ std_ra atol=1e-2 + @test mean_dec ≈ -0.0124 atol=1e-2 + @test std_dec ≈ 0.0714 atol=1e-2 + @test rms_dec ≈ std_dec atol=1e-2 + + # Read radar astrometry file + deldop_2005_2013 = NEOs.read_radar_jpl(joinpath("data", "99942_RADAR_2005_2013.dat")) + + # Compute mean radar (time-delay and Doppler-shift) residuals + @time res_del, w_del, res_dop, w_dop = residuals( + deldop_2005_2013, + xve = t -> auday2kmsec(eph_ea(t/daysec)), + xvs = t -> auday2kmsec(eph_su(t/daysec)), + xva = t -> auday2kmsec(sol(t/daysec)), + niter = 4, + tord = 5 + ) + + mean_del = mean(res_del) + mean_dop = mean(res_dop) + std_del = std(res_del) + std_dop = std(res_dop) + + @test mean_del ≈ 0.281 atol=1e-2 + @test mean_dop ≈ -0.084 atol=1e-2 + @test std_del ≈ 1.246 atol=1e-2 + @test std_dop ≈ 0.286 atol=1e-2 + + res = vcat(res_radec, res_del, res_dop) + w = vcat(w_radec, w_del, w_dop) + + # Total normalized RMS + @test nrms(res, w) ≈ 0.366 atol=1e-3 + end + + @testset "Jet transport propagation and TaylorN serialization" begin + + # Test integration (Apophis) + + # Dynamical function + dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! + # Initial date of integration [julian days] + jd0 = datetime2julian(DateTime(2029, 4, 13, 20)) + # Time of integration [years] + nyears = 0.02 + # Perturbation to nominal initial condition (Taylor1 jet transport) + dq = NEOs.scaled_variables() + # Initial conditions + q0 = [-0.9170913888342959, -0.37154308794738056, -0.1610606989484252, + 0.009701519087787077, -0.012766026792868212, -0.0043488589639194275] .+ dq + # Propagation parameters + params = NEOParameters(maxsteps = 10, order = 25, abstol = 1e-20, parse_eqs = true) + + # Propagate orbit + sol = NEOs.propagate(dynamics, jd0, nyears, q0, params) + jldsave("test.jld2"; sol) + recovered_sol = JLD2.load("test.jld2", "sol") + @test sol == recovered_sol + rm("test.jld2") + + params = NEOParameters(params; maxsteps = 1) + sol, tvS, xvS, gvS = NEOs.propagate_root(dynamics, jd0, nyears, q0, params) + + jldsave("test.jld2"; sol, tvS, xvS, gvS) + recovered_sol = JLD2.load("test.jld2", "sol") + recovered_tvS = JLD2.load("test.jld2", "tvS") + recovered_xvS = JLD2.load("test.jld2", "xvS") + recovered_gvS = JLD2.load("test.jld2", "gvS") + @test sol == recovered_sol + @test tvS == recovered_tvS + @test xvS == recovered_xvS + @test gvS == recovered_gvS + rm("test.jld2") + + # It is unlikely that such a short integration generates a non-trivial tvS, xvS and gvS. + # Therefore, to test TaylorNSerialization I suggest to generate random TaylorN and check + # it saves correctly... + random_TaylorN = [cos(sum(dq .* rand(6))), sin(sum(dq .* rand(6))), tan(sum(dq .* rand(6)))] + jldsave("test.jld2"; random_TaylorN = random_TaylorN) + recovered_taylorN = JLD2.load("test.jld2", "random_TaylorN") + @test recovered_taylorN == random_TaylorN + rm("test.jld2") + + end + + @testset "Jet transport orbit propagation and astrometric observables: (99942) Apophis" begin + + objname::String = "Apophis" + # Dynamical function + dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! + # Initial date of integration [julian days] + jd0::Float64 = datetime2julian(DateTime(2004, 6, 1)) + # Time of integration [years] + nyears::Float64 = 10.0 + # JPL #199 solution for Apophis at June 1st, 2004 + q00::Vector{Float64} = [-1.0506627988664696, -0.060643124245514164, -0.0499709975200415, 0.0029591416313078838, -0.014232335581939919, -0.0052184125285361415, -2.898870403031058e-14, -0.0] + varorder::Int = 1 + dq::Vector{TaylorN{Float64}} = NEOs.scaled_variables("δx", vcat(fill(1e-8, 6), 1e-14), order = varorder) + q0::Vector{TaylorN{Float64}} = q00 .+ vcat(dq, 0dq[1]) + # Propagation parameters + params = NEOParameters(maxsteps = 2_000, order = 25, abstol = 1e-20, parse_eqs = true) + + # Propagate orbit + sol = NEOs.propagate( + dynamics, + jd0, + nyears, + q0, + params + ) + + # Solar System ephemeris + sseph_obs = loadpeeph(NEOs.sseph, sol.t0, sol.t0 + sol.t[end]) + # Sun's ephemeris + eph_su = selecteph(sseph_obs, su) + # Earth's ephemeris + eph_ea = selecteph(sseph_obs, ea) + + # Read optical astrometry file + obs_radec_mpc_apophis = read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) + + # Compute optical astrometry residuals + _res_radec_ = NEOs.residuals( + obs_radec_mpc_apophis, + params, + xve = t -> auday2kmsec(eph_ea(t/daysec)), + xvs = t -> auday2kmsec(eph_su(t/daysec)), + xva = t -> auday2kmsec(sol(t/daysec)) + ) + res_radec, w_radec = NEOs.unfold(_res_radec_) + nobsopt = round(Int, length(res_radec)) + + # Compute mean optical astrometric residual (right ascension and declination) + res_ra = res_radec[1:round(Int,nobsopt/2)]() + res_dec = res_radec[round(Int,nobsopt/2)+1:end]() + mean_ra = mean(res_ra) + mean_dec = mean(res_dec) + std_ra = std(res_ra) + std_dec = std(res_dec) + rms_ra = nrms(res_ra,ones(length(res_ra))) + rms_dec = nrms(res_dec,ones(length(res_dec))) + @test mean_ra ≈ 0.0083 atol=1e-4 + @test std_ra ≈ 0.136 atol=1e-3 + @test rms_ra ≈ std_ra atol=1e-2 + @test mean_dec ≈ -0.0124 atol=1e-2 + @test std_dec ≈ 0.0714 atol=1e-2 + @test rms_dec ≈ std_dec atol=1e-2 + + # Read radar astrometry file + deldop_2005_2013 = NEOs.read_radar_jpl(joinpath("data", "99942_RADAR_2005_2013.dat")) + + # Compute mean radar (time-delay and Doppler-shift) residuals + @time res_del, w_del, res_dop, w_dop = residuals( + deldop_2005_2013[1:4], + xve = t -> auday2kmsec(eph_ea(t/daysec)), + xvs = t -> auday2kmsec(eph_su(t/daysec)), + xva = t -> auday2kmsec(sol(t/daysec)), + niter=10, + tord=10 + ) + + @test abs(res_dop[1]()) ≤ deldop_2005_2013[1].Δν_σ + @test abs(res_del[1]()) ≤ deldop_2005_2013[2].Δτ_σ + @test abs(res_dop[2]()) ≤ deldop_2005_2013[2].Δν_σ + @test abs(res_del[2]()) ≤ deldop_2005_2013[2].Δτ_σ + @test abs(res_dop[3]()) ≤ deldop_2005_2013[3].Δν_σ + @test abs(res_dop[4]()) ≤ deldop_2005_2013[4].Δν_σ + + dq_sample = 2ones(7) + @test abs(res_dop[1](dq_sample)) ≥ deldop_2005_2013[1].Δν_σ + @test abs(res_del[1](dq_sample)) ≥ deldop_2005_2013[2].Δτ_σ + @test abs(res_dop[2](dq_sample)) ≥ deldop_2005_2013[2].Δν_σ + @test abs(res_del[2](dq_sample)) ≥ deldop_2005_2013[2].Δτ_σ + @test abs(res_dop[3](dq_sample)) ≥ deldop_2005_2013[3].Δν_σ + @test abs(res_dop[4](dq_sample)) ≥ deldop_2005_2013[4].Δν_σ + end + +end diff --git a/test/runtests.jl b/test/runtests.jl old mode 100755 new mode 100644 index 18f8f774..d1a830a8 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,13 +1,13 @@ -# This file is part of the NEOs.jl package; MIT licensed - -testfiles = ( - "osculating.jl", - "observations.jl", - "propagation.jl", - "orbit_determination.jl", - "extensions.jl" - ) - -for file in testfiles - include(file) +# This file is part of the NEOs.jl package; MIT licensed + +testfiles = ( + "osculating.jl", + "observations.jl", + "propagation.jl", + "orbit_determination.jl", + "extensions.jl" + ) + +for file in testfiles + include(file) end \ No newline at end of file From 362331da94600de6992f389a834ef97aa041f7f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez?= Date: Tue, 27 Feb 2024 14:20:01 +0100 Subject: [PATCH 148/173] Update to TaylorSeries 0.17 (#58) * Update to TaylorSeries 0.17 * Formatting --- .github/workflows/CI.yml | 10 +- Project.toml | 6 +- pha/apophis.jl | 4 +- src/propagation/asteroid_dynamical_models.jl | 37 +- src/propagation/jetcoeffs.jl | 3820 ++++++++++-------- test/propagation.jl | 110 +- 6 files changed, 2134 insertions(+), 1853 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 26e961d3..ae99539b 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -4,10 +4,6 @@ on: paths-ignore: - 'LICENSE.md' - 'README.md' - pull_request: - branches: - - main - tags: '*' concurrency: # Skip intermediate builds: always. # Cancel intermediate builds: only if it is a pull request build. @@ -27,7 +23,6 @@ jobs: - 'nightly' os: - ubuntu-latest - - macos-latest - windows-latest arch: - x64 @@ -43,9 +38,10 @@ jobs: env: JULIA_NUM_THREADS: 2 - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v4 with: - files: lcov.info + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: false - uses: coverallsapp/github-action@v2 with: path-to-lcov: lcov.info diff --git a/Project.toml b/Project.toml index 63eed1a8..fdb418a7 100644 --- a/Project.toml +++ b/Project.toml @@ -47,13 +47,13 @@ Healpix = "4" JLD2 = "0.4" JSON = "0.21" LazyArtifacts = "1" -PlanetaryEphemeris = "0.7" +PlanetaryEphemeris = "0.8" Quadmath = "0.5" SPICE = "0.2" SatelliteToolboxTransformations = "0.1" Scratch = "1.2" StatsBase = "0.33, 0.34" Tables = "1.10" -TaylorIntegration = "0.14" -TaylorSeries = "0.16" +TaylorIntegration = "0.15" +TaylorSeries = "0.17" julia = "1.9" diff --git a/pha/apophis.jl b/pha/apophis.jl index 71b8854c..7c8bdca8 100644 --- a/pha/apophis.jl +++ b/pha/apophis.jl @@ -155,10 +155,8 @@ function main(dynamics::D, maxsteps::Int, jd0_datetime::DateTime, nyears_bwd::T, eph_su::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, su) eph_ea::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, ea) - # NEO + # Apophis # Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec - xva_bwd(et) = auday2kmsec(sol_bwd(et/daysec)[1:6]) - xva_fwd(et) = auday2kmsec(sol_fwd(et/daysec)[1:6]) xva(et) = bwdfwdeph(et, sol_bwd, sol_fwd) # Earth # Change x, v units, resp., from au, au/day to km, km/sec diff --git a/src/propagation/asteroid_dynamical_models.jl b/src/propagation/asteroid_dynamical_models.jl index 3fc9957c..d3fa37bb 100644 --- a/src/propagation/asteroid_dynamical_models.jl +++ b/src/propagation/asteroid_dynamical_models.jl @@ -134,6 +134,9 @@ function RNp1BP_pN_A_J23E_J2S_ng_eph_threads!(dq, q, params, t) V = Array{S}(undef, N) # Y-axis component W = Array{S}(undef, N) # Z-axis component + # 4 * Velocity of the asteroid + _4dq = Array{S}(undef, 3) # (X,Y,Z) components + # 4 * Velocity of the asteroid - 3 * velocity of the i-th body _4U_m_3X = Array{S}(undef, N) # X-axis component _4V_m_3Y = Array{S}(undef, N) # Y-axis component @@ -306,8 +309,8 @@ function RNp1BP_pN_A_J23E_J2S_ng_eph_threads!(dq, q, params, t) # Rotations to and from Earth, Sun and Moon pole-oriented frames local M_ = Array{S}(undef, 3, 3, N) - local M_ .= zero_q_1 - local M_[:, :, ea] .= t2c_jpl_de430(dsj2k)[:, :] .+ zero_q_1 + + local M_[:, :, ea] = t2c_jpl_de430(dsj2k) .+ zero_q_1 # Fill first 3 elements of dq with velocities dq[1] = q[4] @@ -321,6 +324,9 @@ function RNp1BP_pN_A_J23E_J2S_ng_eph_threads!(dq, q, params, t) Compute point-mass Newtonian accelerations, all bodies See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract =# + _4dq[1] = 4dq[1] + _4dq[2] = 4dq[2] + _4dq[3] = 4dq[3] Threads.@threads for i in 1:Nm1 # Velocity of the i-th body ui[i] = ss16asteph_t[3(N-1+i)-2] # X-axis component @@ -338,9 +344,9 @@ function RNp1BP_pN_A_J23E_J2S_ng_eph_threads!(dq, q, params, t) W[i] = wi[i]-dq[3] # Z-axis component # 4 * Velocity of the asteroid - 3 * velocity of the i-th body - _4U_m_3X[i] = (4dq[1]) - (3ui[i]) # X-axis component - _4V_m_3Y[i] = (4dq[2]) - (3vi[i]) # Y-axis component - _4W_m_3Z[i] = (4dq[3]) - (3wi[i]) # Z-axis component + _4U_m_3X[i] = (-3ui[i]) + (_4dq[1]) # X-axis component + _4V_m_3Y[i] = (-3vi[i]) + (_4dq[2]) # Y-axis component + _4W_m_3Z[i] = (-3wi[i]) + (_4dq[3]) # Z-axis component # Dot product inside the [] in the second term pn2x = X[i]*_4U_m_3X[i] @@ -639,8 +645,9 @@ function RNp1BP_pN_A_J23E_J2S_ng_eph_threads!(dq, q, params, t) dq[4] = ( postNewtonX + accX ) + NGAx dq[5] = ( postNewtonY + accY ) + NGAy dq[6] = ( postNewtonZ + accZ ) + NGAz - # Yarkovsky coefficient does not change in time + # Nongrav acceleration coefficients do not change in time dq[7] = zero_q_1 + dq[8] = zero_q_1 nothing end @@ -701,6 +708,9 @@ function RNp1BP_pN_A_J23E_J2S_eph_threads!(dq, q, params, t) V = Array{S}(undef, N) # Y-axis component W = Array{S}(undef, N) # Z-axis component + # 4 * Velocity of the asteroid + _4dq = Array{S}(undef, 3) # (X,Y,Z) components + # 4 * Velocity of the asteroid - 3 * velocity of the i-th body _4U_m_3X = Array{S}(undef, N) # X-axis component _4V_m_3Y = Array{S}(undef, N) # Y-axis component @@ -873,8 +883,8 @@ function RNp1BP_pN_A_J23E_J2S_eph_threads!(dq, q, params, t) # Rotations to and from Earth, Sun and Moon pole-oriented frames local M_ = Array{S}(undef, 3, 3, N) - local M_ .= zero_q_1 - local M_[:, :, ea] .= t2c_jpl_de430(dsj2k)[:, :] .+ zero_q_1 + + local M_[:, :, ea] = t2c_jpl_de430(dsj2k) .+ zero_q_1 # Fill first 3 elements of dq with velocities dq[1] = q[4] @@ -888,6 +898,9 @@ function RNp1BP_pN_A_J23E_J2S_eph_threads!(dq, q, params, t) Compute point-mass Newtonian accelerations, all bodies See equation (35) in page 7 of https://ui.adsabs.harvard.edu/abs/1971mfdo.book.....M/abstract =# + _4dq[1] = 4dq[1] + _4dq[2] = 4dq[2] + _4dq[3] = 4dq[3] Threads.@threads for i in 1:Nm1 # Velocity of the i-th body ui[i] = ss16asteph_t[3(N-1+i)-2] # X-axis component @@ -905,9 +918,9 @@ function RNp1BP_pN_A_J23E_J2S_eph_threads!(dq, q, params, t) W[i] = wi[i]-dq[3] # Z-axis component # 4 * Velocity of the asteroid - 3 * velocity of the i-th body - _4U_m_3X[i] = (4dq[1]) - (3ui[i]) # X-axis component - _4V_m_3Y[i] = (4dq[2]) - (3vi[i]) # Y-axis component - _4W_m_3Z[i] = (4dq[3]) - (3wi[i]) # Z-axis component + _4U_m_3X[i] = (-3ui[i]) + (_4dq[1]) # X-axis component + _4V_m_3Y[i] = (-3vi[i]) + (_4dq[2]) # Y-axis component + _4W_m_3Z[i] = (-3wi[i]) + (_4dq[3]) # Z-axis component # Dot product inside the [] in the second term pn2x = X[i]*_4U_m_3X[i] @@ -1275,4 +1288,4 @@ end dq[6] = accZ nothing -end \ No newline at end of file +end diff --git a/src/propagation/jetcoeffs.jl b/src/propagation/jetcoeffs.jl index f4990048..76630682 100644 --- a/src/propagation/jetcoeffs.jl +++ b/src/propagation/jetcoeffs.jl @@ -38,6 +38,7 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_ep U = Array{S}(undef, N) V = Array{S}(undef, N) W = Array{S}(undef, N) + _4dq = Array{S}(undef, 3) _4U_m_3X = Array{S}(undef, N) _4V_m_3Y = Array{S}(undef, N) _4W_m_3Z = Array{S}(undef, N) @@ -144,89 +145,162 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_ep dq[2] = Taylor1(identity(constant_term(q[5])), order) dq[3] = Taylor1(identity(constant_term(q[6])), order) newtonianNb_Potential[N] = Taylor1(identity(constant_term(zero_q_1)), order) - tmp687 = Array{Taylor1{_S}}(undef, size(dq)) - tmp687 .= Taylor1(zero(constant_term(q[1])), order) - tmp689 = Array{Taylor1{_S}}(undef, size(ui)) - tmp689 .= Taylor1(zero(constant_term(q[1])), order) - tmp692 = Array{Taylor1{_S}}(undef, size(dq)) - tmp692 .= Taylor1(zero(constant_term(q[1])), order) - tmp694 = Array{Taylor1{_S}}(undef, size(vi)) - tmp694 .= Taylor1(zero(constant_term(q[1])), order) - tmp697 = Array{Taylor1{_S}}(undef, size(dq)) - tmp697 .= Taylor1(zero(constant_term(q[1])), order) - tmp699 = Array{Taylor1{_S}}(undef, size(wi)) - tmp699 .= Taylor1(zero(constant_term(q[1])), order) + _4dq[1] = Taylor1(constant_term(4) * constant_term(dq[1]), order) + _4dq[2] = Taylor1(constant_term(4) * constant_term(dq[2]), order) + _4dq[3] = Taylor1(constant_term(4) * constant_term(dq[3]), order) + tmp5559 = Array{Taylor1{_S}}(undef, size(ui)) + for i = CartesianIndices(tmp5559) + tmp5559[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5562 = Array{Taylor1{_S}}(undef, size(vi)) + for i = CartesianIndices(tmp5562) + tmp5562[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5565 = Array{Taylor1{_S}}(undef, size(wi)) + for i = CartesianIndices(tmp5565) + tmp5565[i] = Taylor1(zero(constant_term(q[1])), order) + end pn2x = Array{Taylor1{_S}}(undef, size(X)) - pn2x .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(pn2x) + pn2x[i] = Taylor1(zero(constant_term(q[1])), order) + end pn2y = Array{Taylor1{_S}}(undef, size(Y)) - pn2y .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(pn2y) + pn2y[i] = Taylor1(zero(constant_term(q[1])), order) + end pn2z = Array{Taylor1{_S}}(undef, size(Z)) - pn2z .= Taylor1(zero(constant_term(q[1])), order) - tmp707 = Array{Taylor1{_S}}(undef, size(UU)) - tmp707 .= Taylor1(zero(constant_term(q[1])), order) - tmp710 = Array{Taylor1{_S}}(undef, size(X)) - tmp710 .= Taylor1(zero(constant_term(q[1])), order) - tmp712 = Array{Taylor1{_S}}(undef, size(Y)) - tmp712 .= Taylor1(zero(constant_term(q[1])), order) - tmp713 = Array{Taylor1{_S}}(undef, size(tmp710)) - tmp713 .= Taylor1(zero(constant_term(q[1])), order) - tmp715 = Array{Taylor1{_S}}(undef, size(Z)) - tmp715 .= Taylor1(zero(constant_term(q[1])), order) - tmp723 = Array{Taylor1{_S}}(undef, size(pn2x)) - tmp723 .= Taylor1(zero(constant_term(q[1])), order) - tmp724 = Array{Taylor1{_S}}(undef, size(tmp723)) - tmp724 .= Taylor1(zero(constant_term(q[1])), order) - tmp819 = Array{Taylor1{_S}}(undef, size(ui)) - tmp819 .= Taylor1(zero(constant_term(q[1])), order) - tmp821 = Array{Taylor1{_S}}(undef, size(vi)) - tmp821 .= Taylor1(zero(constant_term(q[1])), order) - tmp822 = Array{Taylor1{_S}}(undef, size(tmp819)) - tmp822 .= Taylor1(zero(constant_term(q[1])), order) - tmp824 = Array{Taylor1{_S}}(undef, size(wi)) - tmp824 .= Taylor1(zero(constant_term(q[1])), order) - tmp735 = Array{Taylor1{_S}}(undef, size(X)) - tmp735 .= Taylor1(zero(constant_term(q[1])), order) - tmp737 = Array{Taylor1{_S}}(undef, size(Y)) - tmp737 .= Taylor1(zero(constant_term(q[1])), order) - tmp739 = Array{Taylor1{_S}}(undef, size(Z)) - tmp739 .= Taylor1(zero(constant_term(q[1])), order) - tmp741 = Array{Taylor1{_S}}(undef, size(t31)) - tmp741 .= Taylor1(zero(constant_term(q[1])), order) - tmp948 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp948 .= Taylor1(zero(constant_term(q[1])), order) - tmp949 = Array{Taylor1{_S}}(undef, size(ϕ)) - tmp949 .= Taylor1(zero(constant_term(q[1])), order) - tmp751 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp751 .= Taylor1(zero(constant_term(q[1])), order) - tmp757 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp757 .= Taylor1(zero(constant_term(q[1])), order) - tmp759 = Array{Taylor1{_S}}(undef, size(sin3_ϕ)) - tmp759 .= Taylor1(zero(constant_term(q[1])), order) - tmp763 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp763 .= Taylor1(zero(constant_term(q[1])), order) - tmp766 = Array{Taylor1{_S}}(undef, size(r_p2)) - tmp766 .= Taylor1(zero(constant_term(q[1])), order) - tmp767 = Array{Taylor1{_S}}(undef, size(Λ2)) - tmp767 .= Taylor1(zero(constant_term(q[1])), order) - tmp770 = Array{Taylor1{_S}}(undef, size(r_p1d2)) - tmp770 .= Taylor1(zero(constant_term(q[1])), order) - tmp771 = Array{Taylor1{_S}}(undef, size(Λ3)) - tmp771 .= Taylor1(zero(constant_term(q[1])), order) - tmp773 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp773 .= Taylor1(zero(constant_term(q[1])), order) - tmp775 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp775 .= Taylor1(zero(constant_term(q[1])), order) - tmp778 = Array{Taylor1{_S}}(undef, size(Λ2j_div_r4)) - tmp778 .= Taylor1(zero(constant_term(q[1])), order) - tmp782 = Array{Taylor1{_S}}(undef, size(Λ3j_div_r5)) - tmp782 .= Taylor1(zero(constant_term(q[1])), order) - tmp785 = Array{Taylor1{_S}}(undef, size(X)) - tmp785 .= Taylor1(zero(constant_term(q[1])), order) - tmp787 = Array{Taylor1{_S}}(undef, size(Y)) - tmp787 .= Taylor1(zero(constant_term(q[1])), order) - tmp789 = Array{Taylor1{_S}}(undef, size(Z)) - tmp789 .= Taylor1(zero(constant_term(q[1])), order) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 + for i = CartesianIndices(pn2z) + pn2z[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5573 = Array{Taylor1{_S}}(undef, size(UU)) + for i = CartesianIndices(tmp5573) + tmp5573[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5576 = Array{Taylor1{_S}}(undef, size(X)) + for i = CartesianIndices(tmp5576) + tmp5576[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5578 = Array{Taylor1{_S}}(undef, size(Y)) + for i = CartesianIndices(tmp5578) + tmp5578[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5579 = Array{Taylor1{_S}}(undef, size(tmp5576)) + for i = CartesianIndices(tmp5579) + tmp5579[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5581 = Array{Taylor1{_S}}(undef, size(Z)) + for i = CartesianIndices(tmp5581) + tmp5581[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5589 = Array{Taylor1{_S}}(undef, size(pn2x)) + for i = CartesianIndices(tmp5589) + tmp5589[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5590 = Array{Taylor1{_S}}(undef, size(tmp5589)) + for i = CartesianIndices(tmp5590) + tmp5590[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5685 = Array{Taylor1{_S}}(undef, size(ui)) + for i = CartesianIndices(tmp5685) + tmp5685[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5687 = Array{Taylor1{_S}}(undef, size(vi)) + for i = CartesianIndices(tmp5687) + tmp5687[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5688 = Array{Taylor1{_S}}(undef, size(tmp5685)) + for i = CartesianIndices(tmp5688) + tmp5688[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5690 = Array{Taylor1{_S}}(undef, size(wi)) + for i = CartesianIndices(tmp5690) + tmp5690[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5601 = Array{Taylor1{_S}}(undef, size(X)) + for i = CartesianIndices(tmp5601) + tmp5601[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5603 = Array{Taylor1{_S}}(undef, size(Y)) + for i = CartesianIndices(tmp5603) + tmp5603[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5605 = Array{Taylor1{_S}}(undef, size(Z)) + for i = CartesianIndices(tmp5605) + tmp5605[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5607 = Array{Taylor1{_S}}(undef, size(t31)) + for i = CartesianIndices(tmp5607) + tmp5607[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5814 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) + for i = CartesianIndices(tmp5814) + tmp5814[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5815 = Array{Taylor1{_S}}(undef, size(ϕ)) + for i = CartesianIndices(tmp5815) + tmp5815[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5617 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) + for i = CartesianIndices(tmp5617) + tmp5617[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5623 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) + for i = CartesianIndices(tmp5623) + tmp5623[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5625 = Array{Taylor1{_S}}(undef, size(sin3_ϕ)) + for i = CartesianIndices(tmp5625) + tmp5625[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5629 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) + for i = CartesianIndices(tmp5629) + tmp5629[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5632 = Array{Taylor1{_S}}(undef, size(r_p2)) + for i = CartesianIndices(tmp5632) + tmp5632[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5633 = Array{Taylor1{_S}}(undef, size(Λ2)) + for i = CartesianIndices(tmp5633) + tmp5633[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5636 = Array{Taylor1{_S}}(undef, size(r_p1d2)) + for i = CartesianIndices(tmp5636) + tmp5636[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5637 = Array{Taylor1{_S}}(undef, size(Λ3)) + for i = CartesianIndices(tmp5637) + tmp5637[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5639 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) + for i = CartesianIndices(tmp5639) + tmp5639[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5641 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) + for i = CartesianIndices(tmp5641) + tmp5641[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5644 = Array{Taylor1{_S}}(undef, size(Λ2j_div_r4)) + for i = CartesianIndices(tmp5644) + tmp5644[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5648 = Array{Taylor1{_S}}(undef, size(Λ3j_div_r5)) + for i = CartesianIndices(tmp5648) + tmp5648[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5651 = Array{Taylor1{_S}}(undef, size(X)) + for i = CartesianIndices(tmp5651) + tmp5651[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5653 = Array{Taylor1{_S}}(undef, size(Y)) + for i = CartesianIndices(tmp5653) + tmp5653[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5655 = Array{Taylor1{_S}}(undef, size(Z)) + for i = CartesianIndices(tmp5655) + tmp5655[i] = Taylor1(zero(constant_term(q[1])), order) + end + #= /Users/Jorge/projects/neos240702/neosjetcoeffs.jl:253 =# Threads.@threads for i = 1:Nm1 ui[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])), order) vi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])), order) wi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])), order) @@ -236,35 +310,32 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_ep U[i] = Taylor1(constant_term(ui[i]) - constant_term(dq[1]), order) V[i] = Taylor1(constant_term(vi[i]) - constant_term(dq[2]), order) W[i] = Taylor1(constant_term(wi[i]) - constant_term(dq[3]), order) - tmp687[1] = Taylor1(constant_term(4) * constant_term(dq[1]), order) - tmp689[i] = Taylor1(constant_term(3) * constant_term(ui[i]), order) - _4U_m_3X[i] = Taylor1(constant_term(tmp687[1]) - constant_term(tmp689[i]), order) - tmp692[2] = Taylor1(constant_term(4) * constant_term(dq[2]), order) - tmp694[i] = Taylor1(constant_term(3) * constant_term(vi[i]), order) - _4V_m_3Y[i] = Taylor1(constant_term(tmp692[2]) - constant_term(tmp694[i]), order) - tmp697[3] = Taylor1(constant_term(4) * constant_term(dq[3]), order) - tmp699[i] = Taylor1(constant_term(3) * constant_term(wi[i]), order) - _4W_m_3Z[i] = Taylor1(constant_term(tmp697[3]) - constant_term(tmp699[i]), order) + tmp5559[i] = Taylor1(constant_term(-3) * constant_term(ui[i]), order) + _4U_m_3X[i] = Taylor1(constant_term(tmp5559[i]) + constant_term(_4dq[1]), order) + tmp5562[i] = Taylor1(constant_term(-3) * constant_term(vi[i]), order) + _4V_m_3Y[i] = Taylor1(constant_term(tmp5562[i]) + constant_term(_4dq[2]), order) + tmp5565[i] = Taylor1(constant_term(-3) * constant_term(wi[i]), order) + _4W_m_3Z[i] = Taylor1(constant_term(tmp5565[i]) + constant_term(_4dq[3]), order) pn2x[i] = Taylor1(constant_term(X[i]) * constant_term(_4U_m_3X[i]), order) pn2y[i] = Taylor1(constant_term(Y[i]) * constant_term(_4V_m_3Y[i]), order) pn2z[i] = Taylor1(constant_term(Z[i]) * constant_term(_4W_m_3Z[i]), order) UU[i] = Taylor1(constant_term(ui[i]) * constant_term(dq[1]), order) VV[i] = Taylor1(constant_term(vi[i]) * constant_term(dq[2]), order) WW[i] = Taylor1(constant_term(wi[i]) * constant_term(dq[3]), order) - tmp707[i] = Taylor1(constant_term(UU[i]) + constant_term(VV[i]), order) - vi_dot_vj[i] = Taylor1(constant_term(tmp707[i]) + constant_term(WW[i]), order) - tmp710[i] = Taylor1(constant_term(X[i]) ^ float(constant_term(2)), order) - tmp712[i] = Taylor1(constant_term(Y[i]) ^ float(constant_term(2)), order) - tmp713[i] = Taylor1(constant_term(tmp710[i]) + constant_term(tmp712[i]), order) - tmp715[i] = Taylor1(constant_term(Z[i]) ^ float(constant_term(2)), order) - r_p2[i] = Taylor1(constant_term(tmp713[i]) + constant_term(tmp715[i]), order) + tmp5573[i] = Taylor1(constant_term(UU[i]) + constant_term(VV[i]), order) + vi_dot_vj[i] = Taylor1(constant_term(tmp5573[i]) + constant_term(WW[i]), order) + tmp5576[i] = Taylor1(constant_term(X[i]) ^ float(constant_term(2)), order) + tmp5578[i] = Taylor1(constant_term(Y[i]) ^ float(constant_term(2)), order) + tmp5579[i] = Taylor1(constant_term(tmp5576[i]) + constant_term(tmp5578[i]), order) + tmp5581[i] = Taylor1(constant_term(Z[i]) ^ float(constant_term(2)), order) + r_p2[i] = Taylor1(constant_term(tmp5579[i]) + constant_term(tmp5581[i]), order) r_p1d2[i] = Taylor1(sqrt(constant_term(r_p2[i])), order) r_p3d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(1.5)), order) r_p7d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(3.5)), order) newtonianCoeff[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p3d2[i]), order) - tmp723[i] = Taylor1(constant_term(pn2x[i]) + constant_term(pn2y[i]), order) - tmp724[i] = Taylor1(constant_term(tmp723[i]) + constant_term(pn2z[i]), order) - pn2[i] = Taylor1(constant_term(newtonianCoeff[i]) * constant_term(tmp724[i]), order) + tmp5589[i] = Taylor1(constant_term(pn2x[i]) + constant_term(pn2y[i]), order) + tmp5590[i] = Taylor1(constant_term(tmp5589[i]) + constant_term(pn2z[i]), order) + pn2[i] = Taylor1(constant_term(newtonianCoeff[i]) * constant_term(tmp5590[i]), order) newton_acc_X[i] = Taylor1(constant_term(X[i]) * constant_term(newtonianCoeff[i]), order) newton_acc_Y[i] = Taylor1(constant_term(Y[i]) * constant_term(newtonianCoeff[i]), order) newton_acc_Z[i] = Taylor1(constant_term(Z[i]) * constant_term(newtonianCoeff[i]), order) @@ -274,53 +345,53 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_ep V_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(V[i]), order) W_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(W[i]), order) if UJ_interaction[i] - tmp735[i] = Taylor1(-(constant_term(X[i])), order) - t31[i] = Taylor1(constant_term(tmp735[i]) * constant_term(M_[1, 3, i]), order) - tmp737[i] = Taylor1(-(constant_term(Y[i])), order) - t32[i] = Taylor1(constant_term(tmp737[i]) * constant_term(M_[2, 3, i]), order) - tmp739[i] = Taylor1(-(constant_term(Z[i])), order) - t33[i] = Taylor1(constant_term(tmp739[i]) * constant_term(M_[3, 3, i]), order) - tmp741[i] = Taylor1(constant_term(t31[i]) + constant_term(t32[i]), order) - r_sin_ϕ[i] = Taylor1(constant_term(tmp741[i]) + constant_term(t33[i]), order) + tmp5601[i] = Taylor1(-(constant_term(X[i])), order) + t31[i] = Taylor1(constant_term(tmp5601[i]) * constant_term(M_[1, 3, i]), order) + tmp5603[i] = Taylor1(-(constant_term(Y[i])), order) + t32[i] = Taylor1(constant_term(tmp5603[i]) * constant_term(M_[2, 3, i]), order) + tmp5605[i] = Taylor1(-(constant_term(Z[i])), order) + t33[i] = Taylor1(constant_term(tmp5605[i]) * constant_term(M_[3, 3, i]), order) + tmp5607[i] = Taylor1(constant_term(t31[i]) + constant_term(t32[i]), order) + r_sin_ϕ[i] = Taylor1(constant_term(tmp5607[i]) + constant_term(t33[i]), order) sin_ϕ[i] = Taylor1(constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]), order) ϕ[i] = Taylor1(asin(constant_term(sin_ϕ[i])), order) - tmp948[i] = Taylor1(sqrt(1 - constant_term(sin_ϕ[i]) ^ 2), order) + tmp5814[i] = Taylor1(sqrt(1 - constant_term(sin_ϕ[i]) ^ 2), order) cos_ϕ[i] = Taylor1(cos(constant_term(ϕ[i])), order) - tmp949[i] = Taylor1(sin(constant_term(ϕ[i])), order) + tmp5815[i] = Taylor1(sin(constant_term(ϕ[i])), order) sin2_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(2)), order) sin3_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(3)), order) - tmp751[i] = Taylor1(constant_term(1.5) * constant_term(sin2_ϕ[i]), order) - P_2_sin_ϕ[i] = Taylor1(constant_term(tmp751[i]) - constant_term(0.5), order) + tmp5617[i] = Taylor1(constant_term(1.5) * constant_term(sin2_ϕ[i]), order) + P_2_sin_ϕ[i] = Taylor1(constant_term(tmp5617[i]) - constant_term(0.5), order) ∂P_2_sin_ϕ[i] = Taylor1(constant_term(3) * constant_term(sin_ϕ[i]), order) - tmp757[i] = Taylor1(constant_term(-1.5) * constant_term(sin_ϕ[i]), order) - tmp759[i] = Taylor1(constant_term(2.5) * constant_term(sin3_ϕ[i]), order) - P_3_sin_ϕ[i] = Taylor1(constant_term(tmp757[i]) + constant_term(tmp759[i]), order) - tmp763[i] = Taylor1(constant_term(7.5) * constant_term(sin2_ϕ[i]), order) - ∂P_3_sin_ϕ[i] = Taylor1(constant_term(-1.5) + constant_term(tmp763[i]), order) - tmp766[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(2)), order) - tmp767[i] = Taylor1(constant_term(Λ2[i]) / constant_term(tmp766[i]), order) - Λ2j_div_r4[i] = Taylor1(-(constant_term(tmp767[i])), order) - tmp770[i] = Taylor1(constant_term(r_p1d2[i]) ^ float(constant_term(5)), order) - tmp771[i] = Taylor1(constant_term(Λ3[i]) / constant_term(tmp770[i]), order) - Λ3j_div_r5[i] = Taylor1(-(constant_term(tmp771[i])), order) - tmp773[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) - m_c_ϕ_∂P_2[i] = Taylor1(constant_term(tmp773[i]) * constant_term(∂P_2_sin_ϕ[i]), order) - tmp775[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) - m_c_ϕ_∂P_3[i] = Taylor1(constant_term(tmp775[i]) * constant_term(∂P_3_sin_ϕ[i]), order) - tmp778[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(3), order) - F_J2_ξ[i] = Taylor1(constant_term(tmp778[i]) * constant_term(P_2_sin_ϕ[i]), order) + tmp5623[i] = Taylor1(constant_term(-1.5) * constant_term(sin_ϕ[i]), order) + tmp5625[i] = Taylor1(constant_term(2.5) * constant_term(sin3_ϕ[i]), order) + P_3_sin_ϕ[i] = Taylor1(constant_term(tmp5623[i]) + constant_term(tmp5625[i]), order) + tmp5629[i] = Taylor1(constant_term(7.5) * constant_term(sin2_ϕ[i]), order) + ∂P_3_sin_ϕ[i] = Taylor1(constant_term(-1.5) + constant_term(tmp5629[i]), order) + tmp5632[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(2)), order) + tmp5633[i] = Taylor1(constant_term(Λ2[i]) / constant_term(tmp5632[i]), order) + Λ2j_div_r4[i] = Taylor1(-(constant_term(tmp5633[i])), order) + tmp5636[i] = Taylor1(constant_term(r_p1d2[i]) ^ float(constant_term(5)), order) + tmp5637[i] = Taylor1(constant_term(Λ3[i]) / constant_term(tmp5636[i]), order) + Λ3j_div_r5[i] = Taylor1(-(constant_term(tmp5637[i])), order) + tmp5639[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) + m_c_ϕ_∂P_2[i] = Taylor1(constant_term(tmp5639[i]) * constant_term(∂P_2_sin_ϕ[i]), order) + tmp5641[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) + m_c_ϕ_∂P_3[i] = Taylor1(constant_term(tmp5641[i]) * constant_term(∂P_3_sin_ϕ[i]), order) + tmp5644[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(3), order) + F_J2_ξ[i] = Taylor1(constant_term(tmp5644[i]) * constant_term(P_2_sin_ϕ[i]), order) F_J2_ζ[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]), order) - tmp782[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(4), order) - F_J3_ξ[i] = Taylor1(constant_term(tmp782[i]) * constant_term(P_3_sin_ϕ[i]), order) + tmp5648[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(4), order) + F_J3_ξ[i] = Taylor1(constant_term(tmp5648[i]) * constant_term(P_3_sin_ϕ[i]), order) F_J3_ζ[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]), order) F_J_ξ[i] = Taylor1(identity(constant_term(F_J2_ξ[i])), order) F_J_ζ[i] = Taylor1(identity(constant_term(F_J2_ζ[i])), order) - tmp785[i] = Taylor1(-(constant_term(X[i])), order) - ξx[i] = Taylor1(constant_term(tmp785[i]) / constant_term(r_p1d2[i]), order) - tmp787[i] = Taylor1(-(constant_term(Y[i])), order) - ξy[i] = Taylor1(constant_term(tmp787[i]) / constant_term(r_p1d2[i]), order) - tmp789[i] = Taylor1(-(constant_term(Z[i])), order) - ξz[i] = Taylor1(constant_term(tmp789[i]) / constant_term(r_p1d2[i]), order) + tmp5651[i] = Taylor1(-(constant_term(X[i])), order) + ξx[i] = Taylor1(constant_term(tmp5651[i]) / constant_term(r_p1d2[i]), order) + tmp5653[i] = Taylor1(-(constant_term(Y[i])), order) + ξy[i] = Taylor1(constant_term(tmp5653[i]) / constant_term(r_p1d2[i]), order) + tmp5655[i] = Taylor1(-(constant_term(Z[i])), order) + ξz[i] = Taylor1(constant_term(tmp5655[i]) / constant_term(r_p1d2[i]), order) ηx1[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξz[i]), order) ηy1[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξx[i]), order) ηz1[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξy[i]), order) @@ -349,95 +420,133 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_ep F_J2_y[i] = Taylor1(constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]), order) F_J2_z[i] = Taylor1(constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]), order) end - tmp819[i] = Taylor1(constant_term(ui[i]) ^ float(constant_term(2)), order) - tmp821[i] = Taylor1(constant_term(vi[i]) ^ float(constant_term(2)), order) - tmp822[i] = Taylor1(constant_term(tmp819[i]) + constant_term(tmp821[i]), order) - tmp824[i] = Taylor1(constant_term(wi[i]) ^ float(constant_term(2)), order) - v2[i] = Taylor1(constant_term(tmp822[i]) + constant_term(tmp824[i]), order) + tmp5685[i] = Taylor1(constant_term(ui[i]) ^ float(constant_term(2)), order) + tmp5687[i] = Taylor1(constant_term(vi[i]) ^ float(constant_term(2)), order) + tmp5688[i] = Taylor1(constant_term(tmp5685[i]) + constant_term(tmp5687[i]), order) + tmp5690[i] = Taylor1(constant_term(wi[i]) ^ float(constant_term(2)), order) + v2[i] = Taylor1(constant_term(tmp5688[i]) + constant_term(tmp5690[i]), order) end - tmp827 = Taylor1(constant_term(q[4]) ^ float(constant_term(2)), order) - tmp829 = Taylor1(constant_term(q[5]) ^ float(constant_term(2)), order) - tmp830 = Taylor1(constant_term(tmp827) + constant_term(tmp829), order) - tmp832 = Taylor1(constant_term(q[6]) ^ float(constant_term(2)), order) - v2[N] = Taylor1(constant_term(tmp830) + constant_term(tmp832), order) + tmp5693 = Taylor1(constant_term(q[4]) ^ float(constant_term(2)), order) + tmp5695 = Taylor1(constant_term(q[5]) ^ float(constant_term(2)), order) + tmp5696 = Taylor1(constant_term(tmp5693) + constant_term(tmp5695), order) + tmp5698 = Taylor1(constant_term(q[6]) ^ float(constant_term(2)), order) + v2[N] = Taylor1(constant_term(tmp5696) + constant_term(tmp5698), order) temp_004 = Array{Taylor1{_S}}(undef, size(newtonian1b_Potential)) - temp_004 .= Taylor1(zero(constant_term(q[1])), order) - tmp835 = Array{Taylor1{_S}}(undef, size(μ)) - tmp835 .= Taylor1(zero(constant_term(q[1])), order) - tmp837 = Array{Taylor1{_S}}(undef, size(μ)) - tmp837 .= Taylor1(zero(constant_term(q[1])), order) - tmp839 = Array{Taylor1{_S}}(undef, size(μ)) - tmp839 .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(temp_004) + temp_004[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5701 = Array{Taylor1{_S}}(undef, size(μ)) + for i = CartesianIndices(tmp5701) + tmp5701[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5703 = Array{Taylor1{_S}}(undef, size(μ)) + for i = CartesianIndices(tmp5703) + tmp5703[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5705 = Array{Taylor1{_S}}(undef, size(μ)) + for i = CartesianIndices(tmp5705) + tmp5705[i] = Taylor1(zero(constant_term(q[1])), order) + end for i = 1:Nm1 temp_004[i] = Taylor1(constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]), order) newtonianNb_Potential[N] = Taylor1(identity(constant_term(temp_004[i])), order) if UJ_interaction[i] - tmp835[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_x[i]), order) - temp_accX_i[i] = Taylor1(constant_term(accX) - constant_term(tmp835[i]), order) + tmp5701[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_x[i]), order) + temp_accX_i[i] = Taylor1(constant_term(accX) - constant_term(tmp5701[i]), order) accX = Taylor1(identity(constant_term(temp_accX_i[i])), order) - tmp837[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_y[i]), order) - temp_accY_i[i] = Taylor1(constant_term(accY) - constant_term(tmp837[i]), order) + tmp5703[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_y[i]), order) + temp_accY_i[i] = Taylor1(constant_term(accY) - constant_term(tmp5703[i]), order) accY = Taylor1(identity(constant_term(temp_accY_i[i])), order) - tmp839[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_z[i]), order) - temp_accZ_i[i] = Taylor1(constant_term(accZ) - constant_term(tmp839[i]), order) + tmp5705[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_z[i]), order) + temp_accZ_i[i] = Taylor1(constant_term(accZ) - constant_term(tmp5705[i]), order) accZ = Taylor1(identity(constant_term(temp_accZ_i[i])), order) end end _4ϕj[N] = Taylor1(constant_term(4) * constant_term(newtonianNb_Potential[N]), order) - tmp845 = Array{Taylor1{_S}}(undef, size(v2)) - tmp845 .= Taylor1(zero(constant_term(q[1])), order) - tmp847 = Array{Taylor1{_S}}(undef, size(vi_dot_vj)) - tmp847 .= Taylor1(zero(constant_term(q[1])), order) - tmp848 = Array{Taylor1{_S}}(undef, size(tmp845)) - tmp848 .= Taylor1(zero(constant_term(q[1])), order) + tmp5711 = Array{Taylor1{_S}}(undef, size(v2)) + for i = CartesianIndices(tmp5711) + tmp5711[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5713 = Array{Taylor1{_S}}(undef, size(vi_dot_vj)) + for i = CartesianIndices(tmp5713) + tmp5713[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5714 = Array{Taylor1{_S}}(undef, size(tmp5711)) + for i = CartesianIndices(tmp5714) + tmp5714[i] = Taylor1(zero(constant_term(q[1])), order) + end Xij_t_Ui = Array{Taylor1{_S}}(undef, size(X)) - Xij_t_Ui .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(Xij_t_Ui) + Xij_t_Ui[i] = Taylor1(zero(constant_term(q[1])), order) + end Yij_t_Vi = Array{Taylor1{_S}}(undef, size(Y)) - Yij_t_Vi .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(Yij_t_Vi) + Yij_t_Vi[i] = Taylor1(zero(constant_term(q[1])), order) + end Zij_t_Wi = Array{Taylor1{_S}}(undef, size(Z)) - Zij_t_Wi .= Taylor1(zero(constant_term(q[1])), order) - tmp854 = Array{Taylor1{_S}}(undef, size(Xij_t_Ui)) - tmp854 .= Taylor1(zero(constant_term(q[1])), order) - Rij_dot_Vi = Array{Taylor1{_S}}(undef, size(tmp854)) - Rij_dot_Vi .= Taylor1(zero(constant_term(q[1])), order) - tmp857 = Array{Taylor1{_S}}(undef, size(Rij_dot_Vi)) - tmp857 .= Taylor1(zero(constant_term(q[1])), order) - pn1t7 = Array{Taylor1{_S}}(undef, size(tmp857)) - pn1t7 .= Taylor1(zero(constant_term(q[1])), order) - tmp860 = Array{Taylor1{_S}}(undef, size(pn1t7)) - tmp860 .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(Zij_t_Wi) + Zij_t_Wi[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5720 = Array{Taylor1{_S}}(undef, size(Xij_t_Ui)) + for i = CartesianIndices(tmp5720) + tmp5720[i] = Taylor1(zero(constant_term(q[1])), order) + end + Rij_dot_Vi = Array{Taylor1{_S}}(undef, size(tmp5720)) + for i = CartesianIndices(Rij_dot_Vi) + Rij_dot_Vi[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5723 = Array{Taylor1{_S}}(undef, size(Rij_dot_Vi)) + for i = CartesianIndices(tmp5723) + tmp5723[i] = Taylor1(zero(constant_term(q[1])), order) + end + pn1t7 = Array{Taylor1{_S}}(undef, size(tmp5723)) + for i = CartesianIndices(pn1t7) + pn1t7[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5726 = Array{Taylor1{_S}}(undef, size(pn1t7)) + for i = CartesianIndices(tmp5726) + tmp5726[i] = Taylor1(zero(constant_term(q[1])), order) + end pn1t2_7 = Array{Taylor1{_S}}(undef, size(ϕs_and_vs)) - pn1t2_7 .= Taylor1(zero(constant_term(q[1])), order) - tmp867 = Array{Taylor1{_S}}(undef, size(pNX_t_X)) - tmp867 .= Taylor1(zero(constant_term(q[1])), order) - tmp868 = Array{Taylor1{_S}}(undef, size(tmp867)) - tmp868 .= Taylor1(zero(constant_term(q[1])), order) - tmp869 = Array{Taylor1{_S}}(undef, size(tmp868)) - tmp869 .= Taylor1(zero(constant_term(q[1])), order) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 + for i = CartesianIndices(pn1t2_7) + pn1t2_7[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5733 = Array{Taylor1{_S}}(undef, size(pNX_t_X)) + for i = CartesianIndices(tmp5733) + tmp5733[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5734 = Array{Taylor1{_S}}(undef, size(tmp5733)) + for i = CartesianIndices(tmp5734) + tmp5734[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5735 = Array{Taylor1{_S}}(undef, size(tmp5734)) + for i = CartesianIndices(tmp5735) + tmp5735[i] = Taylor1(zero(constant_term(q[1])), order) + end + #= /Users/Jorge/projects/neos240702/neosjetcoeffs.jl:455 =# Threads.@threads for i = 1:10 ϕi_plus_4ϕj[i] = Taylor1(constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]), order) - tmp845[i] = Taylor1(constant_term(2) * constant_term(v2[i]), order) - tmp847[i] = Taylor1(constant_term(4) * constant_term(vi_dot_vj[i]), order) - tmp848[i] = Taylor1(constant_term(tmp845[i]) - constant_term(tmp847[i]), order) - sj2_plus_2si2_minus_4vivj[i] = Taylor1(constant_term(tmp848[i]) + constant_term(v2[N]), order) + tmp5711[i] = Taylor1(constant_term(2) * constant_term(v2[i]), order) + tmp5713[i] = Taylor1(constant_term(4) * constant_term(vi_dot_vj[i]), order) + tmp5714[i] = Taylor1(constant_term(tmp5711[i]) - constant_term(tmp5713[i]), order) + sj2_plus_2si2_minus_4vivj[i] = Taylor1(constant_term(tmp5714[i]) + constant_term(v2[N]), order) ϕs_and_vs[i] = Taylor1(constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]), order) Xij_t_Ui[i] = Taylor1(constant_term(X[i]) * constant_term(ui[i]), order) Yij_t_Vi[i] = Taylor1(constant_term(Y[i]) * constant_term(vi[i]), order) Zij_t_Wi[i] = Taylor1(constant_term(Z[i]) * constant_term(wi[i]), order) - tmp854[i] = Taylor1(constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]), order) - Rij_dot_Vi[i] = Taylor1(constant_term(tmp854[i]) + constant_term(Zij_t_Wi[i]), order) - tmp857[i] = Taylor1(constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)), order) - pn1t7[i] = Taylor1(constant_term(tmp857[i]) / constant_term(r_p2[i]), order) - tmp860[i] = Taylor1(constant_term(1.5) * constant_term(pn1t7[i]), order) - pn1t2_7[i] = Taylor1(constant_term(ϕs_and_vs[i]) - constant_term(tmp860[i]), order) + tmp5720[i] = Taylor1(constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]), order) + Rij_dot_Vi[i] = Taylor1(constant_term(tmp5720[i]) + constant_term(Zij_t_Wi[i]), order) + tmp5723[i] = Taylor1(constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)), order) + pn1t7[i] = Taylor1(constant_term(tmp5723[i]) / constant_term(r_p2[i]), order) + tmp5726[i] = Taylor1(constant_term(1.5) * constant_term(pn1t7[i]), order) + pn1t2_7[i] = Taylor1(constant_term(ϕs_and_vs[i]) - constant_term(tmp5726[i]), order) pn1t1_7[i] = Taylor1(constant_term(c_p2) + constant_term(pn1t2_7[i]), order) pNX_t_X[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(X[i]), order) pNY_t_Y[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(Y[i]), order) pNZ_t_Z[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(Z[i]), order) - tmp867[i] = Taylor1(constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]), order) - tmp868[i] = Taylor1(constant_term(tmp867[i]) + constant_term(pNZ_t_Z[i]), order) - tmp869[i] = Taylor1(constant_term(0.5) * constant_term(tmp868[i]), order) - pn1[i] = Taylor1(constant_term(pn1t1_7[i]) + constant_term(tmp869[i]), order) + tmp5733[i] = Taylor1(constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]), order) + tmp5734[i] = Taylor1(constant_term(tmp5733[i]) + constant_term(pNZ_t_Z[i]), order) + tmp5735[i] = Taylor1(constant_term(0.5) * constant_term(tmp5734[i]), order) + pn1[i] = Taylor1(constant_term(pn1t1_7[i]) + constant_term(tmp5735[i]), order) X_t_pn1[i] = Taylor1(constant_term(newton_acc_X[i]) * constant_term(pn1[i]), order) Y_t_pn1[i] = Taylor1(constant_term(newton_acc_Y[i]) * constant_term(pn1[i]), order) Z_t_pn1[i] = Taylor1(constant_term(newton_acc_Z[i]) * constant_term(pn1[i]), order) @@ -445,39 +554,57 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_ep pNY_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]), order) pNZ_t_pn3[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(pn3[i]), order) end - tmp877 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) - tmp877 .= Taylor1(zero(constant_term(q[1])), order) + tmp5743 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) + for i = CartesianIndices(tmp5743) + tmp5743[i] = Taylor1(zero(constant_term(q[1])), order) + end termpnx = Array{Taylor1{_S}}(undef, size(X_t_pn1)) - termpnx .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(termpnx) + termpnx[i] = Taylor1(zero(constant_term(q[1])), order) + end sumpnx = Array{Taylor1{_S}}(undef, size(termpnx)) - sumpnx .= Taylor1(zero(constant_term(q[1])), order) - tmp880 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) - tmp880 .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(sumpnx) + sumpnx[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5746 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) + for i = CartesianIndices(tmp5746) + tmp5746[i] = Taylor1(zero(constant_term(q[1])), order) + end termpny = Array{Taylor1{_S}}(undef, size(Y_t_pn1)) - termpny .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(termpny) + termpny[i] = Taylor1(zero(constant_term(q[1])), order) + end sumpny = Array{Taylor1{_S}}(undef, size(termpny)) - sumpny .= Taylor1(zero(constant_term(q[1])), order) - tmp883 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) - tmp883 .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(sumpny) + sumpny[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp5749 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) + for i = CartesianIndices(tmp5749) + tmp5749[i] = Taylor1(zero(constant_term(q[1])), order) + end termpnz = Array{Taylor1{_S}}(undef, size(Z_t_pn1)) - termpnz .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(termpnz) + termpnz[i] = Taylor1(zero(constant_term(q[1])), order) + end sumpnz = Array{Taylor1{_S}}(undef, size(termpnz)) - sumpnz .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(sumpnz) + sumpnz[i] = Taylor1(zero(constant_term(q[1])), order) + end for i = 1:10 - tmp877[i] = Taylor1(constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]), order) - termpnx[i] = Taylor1(constant_term(X_t_pn1[i]) + constant_term(tmp877[i]), order) + tmp5743[i] = Taylor1(constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]), order) + termpnx[i] = Taylor1(constant_term(X_t_pn1[i]) + constant_term(tmp5743[i]), order) sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) - tmp880[i] = Taylor1(constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]), order) - termpny[i] = Taylor1(constant_term(Y_t_pn1[i]) + constant_term(tmp880[i]), order) + tmp5746[i] = Taylor1(constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]), order) + termpny[i] = Taylor1(constant_term(Y_t_pn1[i]) + constant_term(tmp5746[i]), order) sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) pntempY = Taylor1(identity(constant_term(sumpny[i])), order) - tmp883[i] = Taylor1(constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]), order) - termpnz[i] = Taylor1(constant_term(Z_t_pn1[i]) + constant_term(tmp883[i]), order) + tmp5749[i] = Taylor1(constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]), order) + termpnz[i] = Taylor1(constant_term(Z_t_pn1[i]) + constant_term(tmp5749[i]), order) sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) end - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 + #= /Users/Jorge/projects/neos240702/neosjetcoeffs.jl:508 =# Threads.@threads for i = 11:Nm1 X_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_X[i]), order) Y_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Y[i]), order) Z_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Z[i]), order) @@ -496,97 +623,98 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_ep postNewtonX = Taylor1(constant_term(pntempX) * constant_term(c_m2), order) postNewtonY = Taylor1(constant_term(pntempY) * constant_term(c_m2), order) postNewtonZ = Taylor1(constant_term(pntempZ) * constant_term(c_m2), order) - tmp895 = Taylor1(constant_term(Y[1]) * constant_term(W[1]), order) - tmp896 = Taylor1(constant_term(Z[1]) * constant_term(V[1]), order) - hx = Taylor1(constant_term(tmp895) - constant_term(tmp896), order) - tmp898 = Taylor1(constant_term(Z[1]) * constant_term(U[1]), order) - tmp899 = Taylor1(constant_term(X[1]) * constant_term(W[1]), order) - hy = Taylor1(constant_term(tmp898) - constant_term(tmp899), order) - tmp901 = Taylor1(constant_term(X[1]) * constant_term(V[1]), order) - tmp902 = Taylor1(constant_term(Y[1]) * constant_term(U[1]), order) - hz = Taylor1(constant_term(tmp901) - constant_term(tmp902), order) - tmp904 = Taylor1(constant_term(hz) * constant_term(Y[1]), order) - tmp905 = Taylor1(constant_term(hy) * constant_term(Z[1]), order) - t_x = Taylor1(constant_term(tmp904) - constant_term(tmp905), order) - tmp907 = Taylor1(constant_term(hx) * constant_term(Z[1]), order) - tmp908 = Taylor1(constant_term(hz) * constant_term(X[1]), order) - t_y = Taylor1(constant_term(tmp907) - constant_term(tmp908), order) - tmp910 = Taylor1(constant_term(hy) * constant_term(X[1]), order) - tmp911 = Taylor1(constant_term(hx) * constant_term(Y[1]), order) - t_z = Taylor1(constant_term(tmp910) - constant_term(tmp911), order) - tmp914 = Taylor1(constant_term(t_x) ^ float(constant_term(2)), order) - tmp916 = Taylor1(constant_term(t_y) ^ float(constant_term(2)), order) - tmp917 = Taylor1(constant_term(tmp914) + constant_term(tmp916), order) - tmp919 = Taylor1(constant_term(t_z) ^ float(constant_term(2)), order) - tmp920 = Taylor1(constant_term(tmp917) + constant_term(tmp919), order) - t_norm = Taylor1(sqrt(constant_term(tmp920)), order) + tmp5761 = Taylor1(constant_term(Y[1]) * constant_term(W[1]), order) + tmp5762 = Taylor1(constant_term(Z[1]) * constant_term(V[1]), order) + hx = Taylor1(constant_term(tmp5761) - constant_term(tmp5762), order) + tmp5764 = Taylor1(constant_term(Z[1]) * constant_term(U[1]), order) + tmp5765 = Taylor1(constant_term(X[1]) * constant_term(W[1]), order) + hy = Taylor1(constant_term(tmp5764) - constant_term(tmp5765), order) + tmp5767 = Taylor1(constant_term(X[1]) * constant_term(V[1]), order) + tmp5768 = Taylor1(constant_term(Y[1]) * constant_term(U[1]), order) + hz = Taylor1(constant_term(tmp5767) - constant_term(tmp5768), order) + tmp5770 = Taylor1(constant_term(hz) * constant_term(Y[1]), order) + tmp5771 = Taylor1(constant_term(hy) * constant_term(Z[1]), order) + t_x = Taylor1(constant_term(tmp5770) - constant_term(tmp5771), order) + tmp5773 = Taylor1(constant_term(hx) * constant_term(Z[1]), order) + tmp5774 = Taylor1(constant_term(hz) * constant_term(X[1]), order) + t_y = Taylor1(constant_term(tmp5773) - constant_term(tmp5774), order) + tmp5776 = Taylor1(constant_term(hy) * constant_term(X[1]), order) + tmp5777 = Taylor1(constant_term(hx) * constant_term(Y[1]), order) + t_z = Taylor1(constant_term(tmp5776) - constant_term(tmp5777), order) + tmp5780 = Taylor1(constant_term(t_x) ^ float(constant_term(2)), order) + tmp5782 = Taylor1(constant_term(t_y) ^ float(constant_term(2)), order) + tmp5783 = Taylor1(constant_term(tmp5780) + constant_term(tmp5782), order) + tmp5785 = Taylor1(constant_term(t_z) ^ float(constant_term(2)), order) + tmp5786 = Taylor1(constant_term(tmp5783) + constant_term(tmp5785), order) + t_norm = Taylor1(sqrt(constant_term(tmp5786)), order) t_x_unit = Taylor1(constant_term(t_x) / constant_term(t_norm), order) t_y_unit = Taylor1(constant_term(t_y) / constant_term(t_norm), order) t_z_unit = Taylor1(constant_term(t_z) / constant_term(t_norm), order) - tmp925 = Taylor1(constant_term(X[1]) / constant_term(r_p1d2[1]), order) - r_x_unit = Taylor1(-(constant_term(tmp925)), order) - tmp927 = Taylor1(constant_term(Y[1]) / constant_term(r_p1d2[1]), order) - r_y_unit = Taylor1(-(constant_term(tmp927)), order) - tmp929 = Taylor1(constant_term(Z[1]) / constant_term(r_p1d2[1]), order) - r_z_unit = Taylor1(-(constant_term(tmp929)), order) + tmp5791 = Taylor1(constant_term(X[1]) / constant_term(r_p1d2[1]), order) + r_x_unit = Taylor1(-(constant_term(tmp5791)), order) + tmp5793 = Taylor1(constant_term(Y[1]) / constant_term(r_p1d2[1]), order) + r_y_unit = Taylor1(-(constant_term(tmp5793)), order) + tmp5795 = Taylor1(constant_term(Z[1]) / constant_term(r_p1d2[1]), order) + r_z_unit = Taylor1(-(constant_term(tmp5795)), order) g_r = Taylor1(identity(constant_term(r_p2[1])), order) A2_t_g_r = Taylor1(constant_term(q[7]) / constant_term(g_r), order) A1_t_g_r = Taylor1(constant_term(q[8]) / constant_term(g_r), order) - tmp933 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_x_unit), order) - tmp934 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_x_unit), order) - NGAx = Taylor1(constant_term(tmp933) + constant_term(tmp934), order) - tmp936 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_y_unit), order) - tmp937 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_y_unit), order) - NGAy = Taylor1(constant_term(tmp936) + constant_term(tmp937), order) - tmp939 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_z_unit), order) - tmp940 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_z_unit), order) - NGAz = Taylor1(constant_term(tmp939) + constant_term(tmp940), order) - tmp942 = Taylor1(constant_term(postNewtonX) + constant_term(accX), order) - dq[4] = Taylor1(constant_term(tmp942) + constant_term(NGAx), order) - tmp944 = Taylor1(constant_term(postNewtonY) + constant_term(accY), order) - dq[5] = Taylor1(constant_term(tmp944) + constant_term(NGAy), order) - tmp946 = Taylor1(constant_term(postNewtonZ) + constant_term(accZ), order) - dq[6] = Taylor1(constant_term(tmp946) + constant_term(NGAz), order) + tmp5799 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_x_unit), order) + tmp5800 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_x_unit), order) + NGAx = Taylor1(constant_term(tmp5799) + constant_term(tmp5800), order) + tmp5802 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_y_unit), order) + tmp5803 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_y_unit), order) + NGAy = Taylor1(constant_term(tmp5802) + constant_term(tmp5803), order) + tmp5805 = Taylor1(constant_term(A2_t_g_r) * constant_term(t_z_unit), order) + tmp5806 = Taylor1(constant_term(A1_t_g_r) * constant_term(r_z_unit), order) + NGAz = Taylor1(constant_term(tmp5805) + constant_term(tmp5806), order) + tmp5808 = Taylor1(constant_term(postNewtonX) + constant_term(accX), order) + dq[4] = Taylor1(constant_term(tmp5808) + constant_term(NGAx), order) + tmp5810 = Taylor1(constant_term(postNewtonY) + constant_term(accY), order) + dq[5] = Taylor1(constant_term(tmp5810) + constant_term(NGAy), order) + tmp5812 = Taylor1(constant_term(postNewtonZ) + constant_term(accZ), order) + dq[6] = Taylor1(constant_term(tmp5812) + constant_term(NGAz), order) dq[7] = Taylor1(identity(constant_term(zero_q_1)), order) - return TaylorIntegration.RetAlloc{Taylor1{_S}}([tmp827, tmp829, tmp830, tmp832, tmp895, tmp896, tmp898, tmp899, tmp901, tmp902, tmp904, tmp905, tmp907, tmp908, tmp910, tmp911, tmp914, tmp916, tmp917, tmp919, tmp920, tmp925, tmp927, tmp929, tmp933, tmp934, tmp936, tmp937, tmp939, tmp940, tmp942, tmp944, tmp946, pntempX, pntempY, pntempZ, accX, accY, accZ, postNewtonX, postNewtonY, postNewtonZ, hx, hy, hz, t_x, t_y, t_z, t_norm, t_x_unit, t_y_unit, t_z_unit, r_x_unit, r_y_unit, r_z_unit, g_r, A2_t_g_r, A1_t_g_r, NGAx, NGAy, NGAz], [X, Y, Z, r_p2, r_p1d2, r_p3d2, r_p7d2, newtonianCoeff, ui, vi, wi, U, V, W, _4U_m_3X, _4V_m_3Y, _4W_m_3Z, UU, VV, WW, newtonian1b_Potential, newtonianNb_Potential, newton_acc_X, newton_acc_Y, newton_acc_Z, v2, vi_dot_vj, pn2, U_t_pn2, V_t_pn2, W_t_pn2, pn3, pNX_t_pn3, pNY_t_pn3, pNZ_t_pn3, _4ϕj, ϕi_plus_4ϕj, sj2_plus_2si2_minus_4vivj, ϕs_and_vs, pn1t1_7, pNX_t_X, pNY_t_Y, pNZ_t_Z, pn1, X_t_pn1, Y_t_pn1, Z_t_pn1, t31, t32, t33, r_sin_ϕ, sin_ϕ, ϕ, cos_ϕ, sin2_ϕ, sin3_ϕ, F_J2_x, F_J2_y, F_J2_z, F_J2_x1, F_J2_y1, F_J2_z1, F_J2_x2, F_J2_y2, F_J2_z2, temp_accX_i, temp_accY_i, temp_accZ_i, P_2_sin_ϕ, ∂P_2_sin_ϕ, P_3_sin_ϕ, ∂P_3_sin_ϕ, m_c_ϕ_∂P_2, m_c_ϕ_∂P_3, Λ2j_div_r4, Λ3j_div_r5, F_J_ξ, F_J_ζ, F_J2_ξ, F_J2_ζ, F_J3_ξ, F_J3_ζ, ξx, ξy, ξz, ηx, ηy, ηz, ηx1, ηy1, ηz1, ηx2, ηy2, ηz2, ζx, ζy, ζz, ζx1, ζy1, ζz1, ζx2, ζy2, ζz2, tmp687, tmp689, tmp692, tmp694, tmp697, tmp699, pn2x, pn2y, pn2z, tmp707, tmp710, tmp712, tmp713, tmp715, tmp723, tmp724, tmp735, tmp737, tmp739, tmp741, tmp948, tmp949, tmp751, tmp757, tmp759, tmp763, tmp766, tmp767, tmp770, tmp771, tmp773, tmp775, tmp778, tmp782, tmp785, tmp787, tmp789, tmp819, tmp821, tmp822, tmp824, temp_004, tmp835, tmp837, tmp839, tmp845, tmp847, tmp848, Xij_t_Ui, Yij_t_Vi, Zij_t_Wi, tmp854, Rij_dot_Vi, tmp857, pn1t7, tmp860, pn1t2_7, tmp867, tmp868, tmp869, tmp877, termpnx, sumpnx, tmp880, termpny, sumpny, tmp883, termpnz, sumpnz], [Array{Taylor1{_S}, 2}(undef, 0, 0)], [Array{Taylor1{_S}, 3}(undef, 0, 0, 0)], [Array{Taylor1{_S}, 4}(undef, 0, 0, 0, 0)]) + dq[8] = Taylor1(identity(constant_term(zero_q_1)), order) + return TaylorIntegration.RetAlloc{Taylor1{_S}}([tmp5693, tmp5695, tmp5696, tmp5698, tmp5761, tmp5762, tmp5764, tmp5765, tmp5767, tmp5768, tmp5770, tmp5771, tmp5773, tmp5774, tmp5776, tmp5777, tmp5780, tmp5782, tmp5783, tmp5785, tmp5786, tmp5791, tmp5793, tmp5795, tmp5799, tmp5800, tmp5802, tmp5803, tmp5805, tmp5806, tmp5808, tmp5810, tmp5812, pntempX, pntempY, pntempZ, accX, accY, accZ, postNewtonX, postNewtonY, postNewtonZ, hx, hy, hz, t_x, t_y, t_z, t_norm, t_x_unit, t_y_unit, t_z_unit, r_x_unit, r_y_unit, r_z_unit, g_r, A2_t_g_r, A1_t_g_r, NGAx, NGAy, NGAz], [X, Y, Z, r_p2, r_p1d2, r_p3d2, r_p7d2, newtonianCoeff, ui, vi, wi, U, V, W, _4dq, _4U_m_3X, _4V_m_3Y, _4W_m_3Z, UU, VV, WW, newtonian1b_Potential, newtonianNb_Potential, newton_acc_X, newton_acc_Y, newton_acc_Z, v2, vi_dot_vj, pn2, U_t_pn2, V_t_pn2, W_t_pn2, pn3, pNX_t_pn3, pNY_t_pn3, pNZ_t_pn3, _4ϕj, ϕi_plus_4ϕj, sj2_plus_2si2_minus_4vivj, ϕs_and_vs, pn1t1_7, pNX_t_X, pNY_t_Y, pNZ_t_Z, pn1, X_t_pn1, Y_t_pn1, Z_t_pn1, t31, t32, t33, r_sin_ϕ, sin_ϕ, ϕ, cos_ϕ, sin2_ϕ, sin3_ϕ, F_J2_x, F_J2_y, F_J2_z, F_J2_x1, F_J2_y1, F_J2_z1, F_J2_x2, F_J2_y2, F_J2_z2, temp_accX_i, temp_accY_i, temp_accZ_i, P_2_sin_ϕ, ∂P_2_sin_ϕ, P_3_sin_ϕ, ∂P_3_sin_ϕ, m_c_ϕ_∂P_2, m_c_ϕ_∂P_3, Λ2j_div_r4, Λ3j_div_r5, F_J_ξ, F_J_ζ, F_J2_ξ, F_J2_ζ, F_J3_ξ, F_J3_ζ, ξx, ξy, ξz, ηx, ηy, ηz, ηx1, ηy1, ηz1, ηx2, ηy2, ηz2, ζx, ζy, ζz, ζx1, ζy1, ζz1, ζx2, ζy2, ζz2, tmp5559, tmp5562, tmp5565, pn2x, pn2y, pn2z, tmp5573, tmp5576, tmp5578, tmp5579, tmp5581, tmp5589, tmp5590, tmp5601, tmp5603, tmp5605, tmp5607, tmp5814, tmp5815, tmp5617, tmp5623, tmp5625, tmp5629, tmp5632, tmp5633, tmp5636, tmp5637, tmp5639, tmp5641, tmp5644, tmp5648, tmp5651, tmp5653, tmp5655, tmp5685, tmp5687, tmp5688, tmp5690, temp_004, tmp5701, tmp5703, tmp5705, tmp5711, tmp5713, tmp5714, Xij_t_Ui, Yij_t_Vi, Zij_t_Wi, tmp5720, Rij_dot_Vi, tmp5723, pn1t7, tmp5726, pn1t2_7, tmp5733, tmp5734, tmp5735, tmp5743, termpnx, sumpnx, tmp5746, termpny, sumpny, tmp5749, termpnz, sumpnz], [Array{Taylor1{_S}, 2}(undef, 0, 0)], [Array{Taylor1{_S}, 3}(undef, 0, 0, 0)], [Array{Taylor1{_S}, 4}(undef, 0, 0, 0, 0)]) end # TaylorIntegration.jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_ng_eph_threads! function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params, __ralloc::TaylorIntegration.RetAlloc{Taylor1{_S}}) where {_T <: Real, _S <: Number, _N} order = t.order - tmp827 = __ralloc.v0[1] - tmp829 = __ralloc.v0[2] - tmp830 = __ralloc.v0[3] - tmp832 = __ralloc.v0[4] - tmp895 = __ralloc.v0[5] - tmp896 = __ralloc.v0[6] - tmp898 = __ralloc.v0[7] - tmp899 = __ralloc.v0[8] - tmp901 = __ralloc.v0[9] - tmp902 = __ralloc.v0[10] - tmp904 = __ralloc.v0[11] - tmp905 = __ralloc.v0[12] - tmp907 = __ralloc.v0[13] - tmp908 = __ralloc.v0[14] - tmp910 = __ralloc.v0[15] - tmp911 = __ralloc.v0[16] - tmp914 = __ralloc.v0[17] - tmp916 = __ralloc.v0[18] - tmp917 = __ralloc.v0[19] - tmp919 = __ralloc.v0[20] - tmp920 = __ralloc.v0[21] - tmp925 = __ralloc.v0[22] - tmp927 = __ralloc.v0[23] - tmp929 = __ralloc.v0[24] - tmp933 = __ralloc.v0[25] - tmp934 = __ralloc.v0[26] - tmp936 = __ralloc.v0[27] - tmp937 = __ralloc.v0[28] - tmp939 = __ralloc.v0[29] - tmp940 = __ralloc.v0[30] - tmp942 = __ralloc.v0[31] - tmp944 = __ralloc.v0[32] - tmp946 = __ralloc.v0[33] + tmp5693 = __ralloc.v0[1] + tmp5695 = __ralloc.v0[2] + tmp5696 = __ralloc.v0[3] + tmp5698 = __ralloc.v0[4] + tmp5761 = __ralloc.v0[5] + tmp5762 = __ralloc.v0[6] + tmp5764 = __ralloc.v0[7] + tmp5765 = __ralloc.v0[8] + tmp5767 = __ralloc.v0[9] + tmp5768 = __ralloc.v0[10] + tmp5770 = __ralloc.v0[11] + tmp5771 = __ralloc.v0[12] + tmp5773 = __ralloc.v0[13] + tmp5774 = __ralloc.v0[14] + tmp5776 = __ralloc.v0[15] + tmp5777 = __ralloc.v0[16] + tmp5780 = __ralloc.v0[17] + tmp5782 = __ralloc.v0[18] + tmp5783 = __ralloc.v0[19] + tmp5785 = __ralloc.v0[20] + tmp5786 = __ralloc.v0[21] + tmp5791 = __ralloc.v0[22] + tmp5793 = __ralloc.v0[23] + tmp5795 = __ralloc.v0[24] + tmp5799 = __ralloc.v0[25] + tmp5800 = __ralloc.v0[26] + tmp5802 = __ralloc.v0[27] + tmp5803 = __ralloc.v0[28] + tmp5805 = __ralloc.v0[29] + tmp5806 = __ralloc.v0[30] + tmp5808 = __ralloc.v0[31] + tmp5810 = __ralloc.v0[32] + tmp5812 = __ralloc.v0[33] pntempX = __ralloc.v0[34] pntempY = __ralloc.v0[35] pntempZ = __ralloc.v0[36] @@ -629,164 +757,162 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! U = __ralloc.v1[12] V = __ralloc.v1[13] W = __ralloc.v1[14] - _4U_m_3X = __ralloc.v1[15] - _4V_m_3Y = __ralloc.v1[16] - _4W_m_3Z = __ralloc.v1[17] - UU = __ralloc.v1[18] - VV = __ralloc.v1[19] - WW = __ralloc.v1[20] - newtonian1b_Potential = __ralloc.v1[21] - newtonianNb_Potential = __ralloc.v1[22] - newton_acc_X = __ralloc.v1[23] - newton_acc_Y = __ralloc.v1[24] - newton_acc_Z = __ralloc.v1[25] - v2 = __ralloc.v1[26] - vi_dot_vj = __ralloc.v1[27] - pn2 = __ralloc.v1[28] - U_t_pn2 = __ralloc.v1[29] - V_t_pn2 = __ralloc.v1[30] - W_t_pn2 = __ralloc.v1[31] - pn3 = __ralloc.v1[32] - pNX_t_pn3 = __ralloc.v1[33] - pNY_t_pn3 = __ralloc.v1[34] - pNZ_t_pn3 = __ralloc.v1[35] - _4ϕj = __ralloc.v1[36] - ϕi_plus_4ϕj = __ralloc.v1[37] - sj2_plus_2si2_minus_4vivj = __ralloc.v1[38] - ϕs_and_vs = __ralloc.v1[39] - pn1t1_7 = __ralloc.v1[40] - pNX_t_X = __ralloc.v1[41] - pNY_t_Y = __ralloc.v1[42] - pNZ_t_Z = __ralloc.v1[43] - pn1 = __ralloc.v1[44] - X_t_pn1 = __ralloc.v1[45] - Y_t_pn1 = __ralloc.v1[46] - Z_t_pn1 = __ralloc.v1[47] - t31 = __ralloc.v1[48] - t32 = __ralloc.v1[49] - t33 = __ralloc.v1[50] - r_sin_ϕ = __ralloc.v1[51] - sin_ϕ = __ralloc.v1[52] - ϕ = __ralloc.v1[53] - cos_ϕ = __ralloc.v1[54] - sin2_ϕ = __ralloc.v1[55] - sin3_ϕ = __ralloc.v1[56] - F_J2_x = __ralloc.v1[57] - F_J2_y = __ralloc.v1[58] - F_J2_z = __ralloc.v1[59] - F_J2_x1 = __ralloc.v1[60] - F_J2_y1 = __ralloc.v1[61] - F_J2_z1 = __ralloc.v1[62] - F_J2_x2 = __ralloc.v1[63] - F_J2_y2 = __ralloc.v1[64] - F_J2_z2 = __ralloc.v1[65] - temp_accX_i = __ralloc.v1[66] - temp_accY_i = __ralloc.v1[67] - temp_accZ_i = __ralloc.v1[68] - P_2_sin_ϕ = __ralloc.v1[69] - ∂P_2_sin_ϕ = __ralloc.v1[70] - P_3_sin_ϕ = __ralloc.v1[71] - ∂P_3_sin_ϕ = __ralloc.v1[72] - m_c_ϕ_∂P_2 = __ralloc.v1[73] - m_c_ϕ_∂P_3 = __ralloc.v1[74] - Λ2j_div_r4 = __ralloc.v1[75] - Λ3j_div_r5 = __ralloc.v1[76] - F_J_ξ = __ralloc.v1[77] - F_J_ζ = __ralloc.v1[78] - F_J2_ξ = __ralloc.v1[79] - F_J2_ζ = __ralloc.v1[80] - F_J3_ξ = __ralloc.v1[81] - F_J3_ζ = __ralloc.v1[82] - ξx = __ralloc.v1[83] - ξy = __ralloc.v1[84] - ξz = __ralloc.v1[85] - ηx = __ralloc.v1[86] - ηy = __ralloc.v1[87] - ηz = __ralloc.v1[88] - ηx1 = __ralloc.v1[89] - ηy1 = __ralloc.v1[90] - ηz1 = __ralloc.v1[91] - ηx2 = __ralloc.v1[92] - ηy2 = __ralloc.v1[93] - ηz2 = __ralloc.v1[94] - ζx = __ralloc.v1[95] - ζy = __ralloc.v1[96] - ζz = __ralloc.v1[97] - ζx1 = __ralloc.v1[98] - ζy1 = __ralloc.v1[99] - ζz1 = __ralloc.v1[100] - ζx2 = __ralloc.v1[101] - ζy2 = __ralloc.v1[102] - ζz2 = __ralloc.v1[103] - tmp687 = __ralloc.v1[104] - tmp689 = __ralloc.v1[105] - tmp692 = __ralloc.v1[106] - tmp694 = __ralloc.v1[107] - tmp697 = __ralloc.v1[108] - tmp699 = __ralloc.v1[109] - pn2x = __ralloc.v1[110] - pn2y = __ralloc.v1[111] - pn2z = __ralloc.v1[112] - tmp707 = __ralloc.v1[113] - tmp710 = __ralloc.v1[114] - tmp712 = __ralloc.v1[115] - tmp713 = __ralloc.v1[116] - tmp715 = __ralloc.v1[117] - tmp723 = __ralloc.v1[118] - tmp724 = __ralloc.v1[119] - tmp735 = __ralloc.v1[120] - tmp737 = __ralloc.v1[121] - tmp739 = __ralloc.v1[122] - tmp741 = __ralloc.v1[123] - tmp948 = __ralloc.v1[124] - tmp949 = __ralloc.v1[125] - tmp751 = __ralloc.v1[126] - tmp757 = __ralloc.v1[127] - tmp759 = __ralloc.v1[128] - tmp763 = __ralloc.v1[129] - tmp766 = __ralloc.v1[130] - tmp767 = __ralloc.v1[131] - tmp770 = __ralloc.v1[132] - tmp771 = __ralloc.v1[133] - tmp773 = __ralloc.v1[134] - tmp775 = __ralloc.v1[135] - tmp778 = __ralloc.v1[136] - tmp782 = __ralloc.v1[137] - tmp785 = __ralloc.v1[138] - tmp787 = __ralloc.v1[139] - tmp789 = __ralloc.v1[140] - tmp819 = __ralloc.v1[141] - tmp821 = __ralloc.v1[142] - tmp822 = __ralloc.v1[143] - tmp824 = __ralloc.v1[144] - temp_004 = __ralloc.v1[145] - tmp835 = __ralloc.v1[146] - tmp837 = __ralloc.v1[147] - tmp839 = __ralloc.v1[148] - tmp845 = __ralloc.v1[149] - tmp847 = __ralloc.v1[150] - tmp848 = __ralloc.v1[151] - Xij_t_Ui = __ralloc.v1[152] - Yij_t_Vi = __ralloc.v1[153] - Zij_t_Wi = __ralloc.v1[154] - tmp854 = __ralloc.v1[155] - Rij_dot_Vi = __ralloc.v1[156] - tmp857 = __ralloc.v1[157] - pn1t7 = __ralloc.v1[158] - tmp860 = __ralloc.v1[159] - pn1t2_7 = __ralloc.v1[160] - tmp867 = __ralloc.v1[161] - tmp868 = __ralloc.v1[162] - tmp869 = __ralloc.v1[163] - tmp877 = __ralloc.v1[164] - termpnx = __ralloc.v1[165] - sumpnx = __ralloc.v1[166] - tmp880 = __ralloc.v1[167] - termpny = __ralloc.v1[168] - sumpny = __ralloc.v1[169] - tmp883 = __ralloc.v1[170] - termpnz = __ralloc.v1[171] - sumpnz = __ralloc.v1[172] + _4dq = __ralloc.v1[15] + _4U_m_3X = __ralloc.v1[16] + _4V_m_3Y = __ralloc.v1[17] + _4W_m_3Z = __ralloc.v1[18] + UU = __ralloc.v1[19] + VV = __ralloc.v1[20] + WW = __ralloc.v1[21] + newtonian1b_Potential = __ralloc.v1[22] + newtonianNb_Potential = __ralloc.v1[23] + newton_acc_X = __ralloc.v1[24] + newton_acc_Y = __ralloc.v1[25] + newton_acc_Z = __ralloc.v1[26] + v2 = __ralloc.v1[27] + vi_dot_vj = __ralloc.v1[28] + pn2 = __ralloc.v1[29] + U_t_pn2 = __ralloc.v1[30] + V_t_pn2 = __ralloc.v1[31] + W_t_pn2 = __ralloc.v1[32] + pn3 = __ralloc.v1[33] + pNX_t_pn3 = __ralloc.v1[34] + pNY_t_pn3 = __ralloc.v1[35] + pNZ_t_pn3 = __ralloc.v1[36] + _4ϕj = __ralloc.v1[37] + ϕi_plus_4ϕj = __ralloc.v1[38] + sj2_plus_2si2_minus_4vivj = __ralloc.v1[39] + ϕs_and_vs = __ralloc.v1[40] + pn1t1_7 = __ralloc.v1[41] + pNX_t_X = __ralloc.v1[42] + pNY_t_Y = __ralloc.v1[43] + pNZ_t_Z = __ralloc.v1[44] + pn1 = __ralloc.v1[45] + X_t_pn1 = __ralloc.v1[46] + Y_t_pn1 = __ralloc.v1[47] + Z_t_pn1 = __ralloc.v1[48] + t31 = __ralloc.v1[49] + t32 = __ralloc.v1[50] + t33 = __ralloc.v1[51] + r_sin_ϕ = __ralloc.v1[52] + sin_ϕ = __ralloc.v1[53] + ϕ = __ralloc.v1[54] + cos_ϕ = __ralloc.v1[55] + sin2_ϕ = __ralloc.v1[56] + sin3_ϕ = __ralloc.v1[57] + F_J2_x = __ralloc.v1[58] + F_J2_y = __ralloc.v1[59] + F_J2_z = __ralloc.v1[60] + F_J2_x1 = __ralloc.v1[61] + F_J2_y1 = __ralloc.v1[62] + F_J2_z1 = __ralloc.v1[63] + F_J2_x2 = __ralloc.v1[64] + F_J2_y2 = __ralloc.v1[65] + F_J2_z2 = __ralloc.v1[66] + temp_accX_i = __ralloc.v1[67] + temp_accY_i = __ralloc.v1[68] + temp_accZ_i = __ralloc.v1[69] + P_2_sin_ϕ = __ralloc.v1[70] + ∂P_2_sin_ϕ = __ralloc.v1[71] + P_3_sin_ϕ = __ralloc.v1[72] + ∂P_3_sin_ϕ = __ralloc.v1[73] + m_c_ϕ_∂P_2 = __ralloc.v1[74] + m_c_ϕ_∂P_3 = __ralloc.v1[75] + Λ2j_div_r4 = __ralloc.v1[76] + Λ3j_div_r5 = __ralloc.v1[77] + F_J_ξ = __ralloc.v1[78] + F_J_ζ = __ralloc.v1[79] + F_J2_ξ = __ralloc.v1[80] + F_J2_ζ = __ralloc.v1[81] + F_J3_ξ = __ralloc.v1[82] + F_J3_ζ = __ralloc.v1[83] + ξx = __ralloc.v1[84] + ξy = __ralloc.v1[85] + ξz = __ralloc.v1[86] + ηx = __ralloc.v1[87] + ηy = __ralloc.v1[88] + ηz = __ralloc.v1[89] + ηx1 = __ralloc.v1[90] + ηy1 = __ralloc.v1[91] + ηz1 = __ralloc.v1[92] + ηx2 = __ralloc.v1[93] + ηy2 = __ralloc.v1[94] + ηz2 = __ralloc.v1[95] + ζx = __ralloc.v1[96] + ζy = __ralloc.v1[97] + ζz = __ralloc.v1[98] + ζx1 = __ralloc.v1[99] + ζy1 = __ralloc.v1[100] + ζz1 = __ralloc.v1[101] + ζx2 = __ralloc.v1[102] + ζy2 = __ralloc.v1[103] + ζz2 = __ralloc.v1[104] + tmp5559 = __ralloc.v1[105] + tmp5562 = __ralloc.v1[106] + tmp5565 = __ralloc.v1[107] + pn2x = __ralloc.v1[108] + pn2y = __ralloc.v1[109] + pn2z = __ralloc.v1[110] + tmp5573 = __ralloc.v1[111] + tmp5576 = __ralloc.v1[112] + tmp5578 = __ralloc.v1[113] + tmp5579 = __ralloc.v1[114] + tmp5581 = __ralloc.v1[115] + tmp5589 = __ralloc.v1[116] + tmp5590 = __ralloc.v1[117] + tmp5601 = __ralloc.v1[118] + tmp5603 = __ralloc.v1[119] + tmp5605 = __ralloc.v1[120] + tmp5607 = __ralloc.v1[121] + tmp5814 = __ralloc.v1[122] + tmp5815 = __ralloc.v1[123] + tmp5617 = __ralloc.v1[124] + tmp5623 = __ralloc.v1[125] + tmp5625 = __ralloc.v1[126] + tmp5629 = __ralloc.v1[127] + tmp5632 = __ralloc.v1[128] + tmp5633 = __ralloc.v1[129] + tmp5636 = __ralloc.v1[130] + tmp5637 = __ralloc.v1[131] + tmp5639 = __ralloc.v1[132] + tmp5641 = __ralloc.v1[133] + tmp5644 = __ralloc.v1[134] + tmp5648 = __ralloc.v1[135] + tmp5651 = __ralloc.v1[136] + tmp5653 = __ralloc.v1[137] + tmp5655 = __ralloc.v1[138] + tmp5685 = __ralloc.v1[139] + tmp5687 = __ralloc.v1[140] + tmp5688 = __ralloc.v1[141] + tmp5690 = __ralloc.v1[142] + temp_004 = __ralloc.v1[143] + tmp5701 = __ralloc.v1[144] + tmp5703 = __ralloc.v1[145] + tmp5705 = __ralloc.v1[146] + tmp5711 = __ralloc.v1[147] + tmp5713 = __ralloc.v1[148] + tmp5714 = __ralloc.v1[149] + Xij_t_Ui = __ralloc.v1[150] + Yij_t_Vi = __ralloc.v1[151] + Zij_t_Wi = __ralloc.v1[152] + tmp5720 = __ralloc.v1[153] + Rij_dot_Vi = __ralloc.v1[154] + tmp5723 = __ralloc.v1[155] + pn1t7 = __ralloc.v1[156] + tmp5726 = __ralloc.v1[157] + pn1t2_7 = __ralloc.v1[158] + tmp5733 = __ralloc.v1[159] + tmp5734 = __ralloc.v1[160] + tmp5735 = __ralloc.v1[161] + tmp5743 = __ralloc.v1[162] + termpnx = __ralloc.v1[163] + sumpnx = __ralloc.v1[164] + tmp5746 = __ralloc.v1[165] + termpny = __ralloc.v1[166] + sumpny = __ralloc.v1[167] + tmp5749 = __ralloc.v1[168] + termpnz = __ralloc.v1[169] + sumpnz = __ralloc.v1[170] local jd0 = params[4] local dsj2k = t + (jd0 - JD_J2000) local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) @@ -798,545 +924,546 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! local Nm1 = N - 1 local μ = params[7] local zero_q_1 = auxzero(q[1]) + TaylorSeries.zero!(pntempX) pntempX.coeffs[1] = identity(constant_term(zero_q_1)) - pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) + TaylorSeries.zero!(pntempY) pntempY.coeffs[1] = identity(constant_term(zero_q_1)) - pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) + TaylorSeries.zero!(pntempZ) pntempZ.coeffs[1] = identity(constant_term(zero_q_1)) - pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) + TaylorSeries.zero!(accX) accX.coeffs[1] = identity(constant_term(zero_q_1)) - accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) + TaylorSeries.zero!(accY) accY.coeffs[1] = identity(constant_term(zero_q_1)) - accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) + TaylorSeries.zero!(accZ) accZ.coeffs[1] = identity(constant_term(zero_q_1)) - accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) local M_ = Array{S}(undef, 3, 3, N) - local M_ .= zero_q_1 - local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 + local M_[:, :, ea] = t2c_jpl_de430(dsj2k) .+ zero_q_1 + TaylorSeries.zero!(dq[1]) (dq[1]).coeffs[1] = identity(constant_term(q[4])) - (dq[1]).coeffs[2:order + 1] .= zero((dq[1]).coeffs[1]) + TaylorSeries.zero!(dq[2]) (dq[2]).coeffs[1] = identity(constant_term(q[5])) - (dq[2]).coeffs[2:order + 1] .= zero((dq[2]).coeffs[1]) + TaylorSeries.zero!(dq[3]) (dq[3]).coeffs[1] = identity(constant_term(q[6])) - (dq[3]).coeffs[2:order + 1] .= zero((dq[3]).coeffs[1]) + TaylorSeries.zero!(newtonianNb_Potential[N]) (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(zero_q_1)) - (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 + TaylorSeries.zero!(_4dq[1]) + (_4dq[1]).coeffs[1] = constant_term(4) * constant_term(dq[1]) + TaylorSeries.zero!(_4dq[2]) + (_4dq[2]).coeffs[1] = constant_term(4) * constant_term(dq[2]) + TaylorSeries.zero!(_4dq[3]) + (_4dq[3]).coeffs[1] = constant_term(4) * constant_term(dq[3]) + #= /Users/Jorge/projects/neos240702/neosjetcoeffs.jl:253 =# Threads.@threads for i = 1:Nm1 + TaylorSeries.zero!(ui[i]) (ui[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])) - (ui[i]).coeffs[2:order + 1] .= zero((ui[i]).coeffs[1]) + TaylorSeries.zero!(vi[i]) (vi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])) - (vi[i]).coeffs[2:order + 1] .= zero((vi[i]).coeffs[1]) + TaylorSeries.zero!(wi[i]) (wi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])) - (wi[i]).coeffs[2:order + 1] .= zero((wi[i]).coeffs[1]) + TaylorSeries.zero!(X[i]) (X[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 2]) - constant_term(q[1]) - (X[i]).coeffs[2:order + 1] .= zero((X[i]).coeffs[1]) + TaylorSeries.zero!(Y[i]) (Y[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 1]) - constant_term(q[2]) - (Y[i]).coeffs[2:order + 1] .= zero((Y[i]).coeffs[1]) + TaylorSeries.zero!(Z[i]) (Z[i]).coeffs[1] = constant_term(ss16asteph_t[3i]) - constant_term(q[3]) - (Z[i]).coeffs[2:order + 1] .= zero((Z[i]).coeffs[1]) + TaylorSeries.zero!(U[i]) (U[i]).coeffs[1] = constant_term(ui[i]) - constant_term(dq[1]) - (U[i]).coeffs[2:order + 1] .= zero((U[i]).coeffs[1]) + TaylorSeries.zero!(V[i]) (V[i]).coeffs[1] = constant_term(vi[i]) - constant_term(dq[2]) - (V[i]).coeffs[2:order + 1] .= zero((V[i]).coeffs[1]) + TaylorSeries.zero!(W[i]) (W[i]).coeffs[1] = constant_term(wi[i]) - constant_term(dq[3]) - (W[i]).coeffs[2:order + 1] .= zero((W[i]).coeffs[1]) - (tmp687[1]).coeffs[1] = constant_term(4) * constant_term(dq[1]) - (tmp687[1]).coeffs[2:order + 1] .= zero((tmp687[1]).coeffs[1]) - (tmp689[i]).coeffs[1] = constant_term(3) * constant_term(ui[i]) - (tmp689[i]).coeffs[2:order + 1] .= zero((tmp689[i]).coeffs[1]) - (_4U_m_3X[i]).coeffs[1] = constant_term(tmp687[1]) - constant_term(tmp689[i]) - (_4U_m_3X[i]).coeffs[2:order + 1] .= zero((_4U_m_3X[i]).coeffs[1]) - (tmp692[2]).coeffs[1] = constant_term(4) * constant_term(dq[2]) - (tmp692[2]).coeffs[2:order + 1] .= zero((tmp692[2]).coeffs[1]) - (tmp694[i]).coeffs[1] = constant_term(3) * constant_term(vi[i]) - (tmp694[i]).coeffs[2:order + 1] .= zero((tmp694[i]).coeffs[1]) - (_4V_m_3Y[i]).coeffs[1] = constant_term(tmp692[2]) - constant_term(tmp694[i]) - (_4V_m_3Y[i]).coeffs[2:order + 1] .= zero((_4V_m_3Y[i]).coeffs[1]) - (tmp697[3]).coeffs[1] = constant_term(4) * constant_term(dq[3]) - (tmp697[3]).coeffs[2:order + 1] .= zero((tmp697[3]).coeffs[1]) - (tmp699[i]).coeffs[1] = constant_term(3) * constant_term(wi[i]) - (tmp699[i]).coeffs[2:order + 1] .= zero((tmp699[i]).coeffs[1]) - (_4W_m_3Z[i]).coeffs[1] = constant_term(tmp697[3]) - constant_term(tmp699[i]) - (_4W_m_3Z[i]).coeffs[2:order + 1] .= zero((_4W_m_3Z[i]).coeffs[1]) + TaylorSeries.zero!(tmp5559[i]) + (tmp5559[i]).coeffs[1] = constant_term(-3) * constant_term(ui[i]) + TaylorSeries.zero!(_4U_m_3X[i]) + (_4U_m_3X[i]).coeffs[1] = constant_term(tmp5559[i]) + constant_term(_4dq[1]) + TaylorSeries.zero!(tmp5562[i]) + (tmp5562[i]).coeffs[1] = constant_term(-3) * constant_term(vi[i]) + TaylorSeries.zero!(_4V_m_3Y[i]) + (_4V_m_3Y[i]).coeffs[1] = constant_term(tmp5562[i]) + constant_term(_4dq[2]) + TaylorSeries.zero!(tmp5565[i]) + (tmp5565[i]).coeffs[1] = constant_term(-3) * constant_term(wi[i]) + TaylorSeries.zero!(_4W_m_3Z[i]) + (_4W_m_3Z[i]).coeffs[1] = constant_term(tmp5565[i]) + constant_term(_4dq[3]) + TaylorSeries.zero!(pn2x[i]) (pn2x[i]).coeffs[1] = constant_term(X[i]) * constant_term(_4U_m_3X[i]) - (pn2x[i]).coeffs[2:order + 1] .= zero((pn2x[i]).coeffs[1]) + TaylorSeries.zero!(pn2y[i]) (pn2y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(_4V_m_3Y[i]) - (pn2y[i]).coeffs[2:order + 1] .= zero((pn2y[i]).coeffs[1]) + TaylorSeries.zero!(pn2z[i]) (pn2z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(_4W_m_3Z[i]) - (pn2z[i]).coeffs[2:order + 1] .= zero((pn2z[i]).coeffs[1]) + TaylorSeries.zero!(UU[i]) (UU[i]).coeffs[1] = constant_term(ui[i]) * constant_term(dq[1]) - (UU[i]).coeffs[2:order + 1] .= zero((UU[i]).coeffs[1]) + TaylorSeries.zero!(VV[i]) (VV[i]).coeffs[1] = constant_term(vi[i]) * constant_term(dq[2]) - (VV[i]).coeffs[2:order + 1] .= zero((VV[i]).coeffs[1]) + TaylorSeries.zero!(WW[i]) (WW[i]).coeffs[1] = constant_term(wi[i]) * constant_term(dq[3]) - (WW[i]).coeffs[2:order + 1] .= zero((WW[i]).coeffs[1]) - (tmp707[i]).coeffs[1] = constant_term(UU[i]) + constant_term(VV[i]) - (tmp707[i]).coeffs[2:order + 1] .= zero((tmp707[i]).coeffs[1]) - (vi_dot_vj[i]).coeffs[1] = constant_term(tmp707[i]) + constant_term(WW[i]) - (vi_dot_vj[i]).coeffs[2:order + 1] .= zero((vi_dot_vj[i]).coeffs[1]) - (tmp710[i]).coeffs[1] = constant_term(X[i]) ^ float(constant_term(2)) - (tmp710[i]).coeffs[2:order + 1] .= zero((tmp710[i]).coeffs[1]) - (tmp712[i]).coeffs[1] = constant_term(Y[i]) ^ float(constant_term(2)) - (tmp712[i]).coeffs[2:order + 1] .= zero((tmp712[i]).coeffs[1]) - (tmp713[i]).coeffs[1] = constant_term(tmp710[i]) + constant_term(tmp712[i]) - (tmp713[i]).coeffs[2:order + 1] .= zero((tmp713[i]).coeffs[1]) - (tmp715[i]).coeffs[1] = constant_term(Z[i]) ^ float(constant_term(2)) - (tmp715[i]).coeffs[2:order + 1] .= zero((tmp715[i]).coeffs[1]) - (r_p2[i]).coeffs[1] = constant_term(tmp713[i]) + constant_term(tmp715[i]) - (r_p2[i]).coeffs[2:order + 1] .= zero((r_p2[i]).coeffs[1]) + TaylorSeries.zero!(tmp5573[i]) + (tmp5573[i]).coeffs[1] = constant_term(UU[i]) + constant_term(VV[i]) + TaylorSeries.zero!(vi_dot_vj[i]) + (vi_dot_vj[i]).coeffs[1] = constant_term(tmp5573[i]) + constant_term(WW[i]) + TaylorSeries.zero!(tmp5576[i]) + (tmp5576[i]).coeffs[1] = constant_term(X[i]) ^ float(constant_term(2)) + TaylorSeries.zero!(tmp5578[i]) + (tmp5578[i]).coeffs[1] = constant_term(Y[i]) ^ float(constant_term(2)) + TaylorSeries.zero!(tmp5579[i]) + (tmp5579[i]).coeffs[1] = constant_term(tmp5576[i]) + constant_term(tmp5578[i]) + TaylorSeries.zero!(tmp5581[i]) + (tmp5581[i]).coeffs[1] = constant_term(Z[i]) ^ float(constant_term(2)) + TaylorSeries.zero!(r_p2[i]) + (r_p2[i]).coeffs[1] = constant_term(tmp5579[i]) + constant_term(tmp5581[i]) + TaylorSeries.zero!(r_p1d2[i]) (r_p1d2[i]).coeffs[1] = sqrt(constant_term(r_p2[i])) - (r_p1d2[i]).coeffs[2:order + 1] .= zero((r_p1d2[i]).coeffs[1]) + TaylorSeries.zero!(r_p3d2[i]) (r_p3d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(1.5)) - (r_p3d2[i]).coeffs[2:order + 1] .= zero((r_p3d2[i]).coeffs[1]) + TaylorSeries.zero!(r_p7d2[i]) (r_p7d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(3.5)) - (r_p7d2[i]).coeffs[2:order + 1] .= zero((r_p7d2[i]).coeffs[1]) + TaylorSeries.zero!(newtonianCoeff[i]) (newtonianCoeff[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p3d2[i]) - (newtonianCoeff[i]).coeffs[2:order + 1] .= zero((newtonianCoeff[i]).coeffs[1]) - (tmp723[i]).coeffs[1] = constant_term(pn2x[i]) + constant_term(pn2y[i]) - (tmp723[i]).coeffs[2:order + 1] .= zero((tmp723[i]).coeffs[1]) - (tmp724[i]).coeffs[1] = constant_term(tmp723[i]) + constant_term(pn2z[i]) - (tmp724[i]).coeffs[2:order + 1] .= zero((tmp724[i]).coeffs[1]) - (pn2[i]).coeffs[1] = constant_term(newtonianCoeff[i]) * constant_term(tmp724[i]) - (pn2[i]).coeffs[2:order + 1] .= zero((pn2[i]).coeffs[1]) + TaylorSeries.zero!(tmp5589[i]) + (tmp5589[i]).coeffs[1] = constant_term(pn2x[i]) + constant_term(pn2y[i]) + TaylorSeries.zero!(tmp5590[i]) + (tmp5590[i]).coeffs[1] = constant_term(tmp5589[i]) + constant_term(pn2z[i]) + TaylorSeries.zero!(pn2[i]) + (pn2[i]).coeffs[1] = constant_term(newtonianCoeff[i]) * constant_term(tmp5590[i]) + TaylorSeries.zero!(newton_acc_X[i]) (newton_acc_X[i]).coeffs[1] = constant_term(X[i]) * constant_term(newtonianCoeff[i]) - (newton_acc_X[i]).coeffs[2:order + 1] .= zero((newton_acc_X[i]).coeffs[1]) + TaylorSeries.zero!(newton_acc_Y[i]) (newton_acc_Y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(newtonianCoeff[i]) - (newton_acc_Y[i]).coeffs[2:order + 1] .= zero((newton_acc_Y[i]).coeffs[1]) + TaylorSeries.zero!(newton_acc_Z[i]) (newton_acc_Z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(newtonianCoeff[i]) - (newton_acc_Z[i]).coeffs[2:order + 1] .= zero((newton_acc_Z[i]).coeffs[1]) + TaylorSeries.zero!(newtonian1b_Potential[i]) (newtonian1b_Potential[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p1d2[i]) - (newtonian1b_Potential[i]).coeffs[2:order + 1] .= zero((newtonian1b_Potential[i]).coeffs[1]) + TaylorSeries.zero!(pn3[i]) (pn3[i]).coeffs[1] = constant_term(3.5) * constant_term(newtonian1b_Potential[i]) - (pn3[i]).coeffs[2:order + 1] .= zero((pn3[i]).coeffs[1]) + TaylorSeries.zero!(U_t_pn2[i]) (U_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(U[i]) - (U_t_pn2[i]).coeffs[2:order + 1] .= zero((U_t_pn2[i]).coeffs[1]) + TaylorSeries.zero!(V_t_pn2[i]) (V_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(V[i]) - (V_t_pn2[i]).coeffs[2:order + 1] .= zero((V_t_pn2[i]).coeffs[1]) + TaylorSeries.zero!(W_t_pn2[i]) (W_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(W[i]) - (W_t_pn2[i]).coeffs[2:order + 1] .= zero((W_t_pn2[i]).coeffs[1]) if UJ_interaction[i] - (tmp735[i]).coeffs[1] = -(constant_term(X[i])) - (tmp735[i]).coeffs[2:order + 1] .= zero((tmp735[i]).coeffs[1]) - (t31[i]).coeffs[1] = constant_term(tmp735[i]) * constant_term(M_[1, 3, i]) - (t31[i]).coeffs[2:order + 1] .= zero((t31[i]).coeffs[1]) - (tmp737[i]).coeffs[1] = -(constant_term(Y[i])) - (tmp737[i]).coeffs[2:order + 1] .= zero((tmp737[i]).coeffs[1]) - (t32[i]).coeffs[1] = constant_term(tmp737[i]) * constant_term(M_[2, 3, i]) - (t32[i]).coeffs[2:order + 1] .= zero((t32[i]).coeffs[1]) - (tmp739[i]).coeffs[1] = -(constant_term(Z[i])) - (tmp739[i]).coeffs[2:order + 1] .= zero((tmp739[i]).coeffs[1]) - (t33[i]).coeffs[1] = constant_term(tmp739[i]) * constant_term(M_[3, 3, i]) - (t33[i]).coeffs[2:order + 1] .= zero((t33[i]).coeffs[1]) - (tmp741[i]).coeffs[1] = constant_term(t31[i]) + constant_term(t32[i]) - (tmp741[i]).coeffs[2:order + 1] .= zero((tmp741[i]).coeffs[1]) - (r_sin_ϕ[i]).coeffs[1] = constant_term(tmp741[i]) + constant_term(t33[i]) - (r_sin_ϕ[i]).coeffs[2:order + 1] .= zero((r_sin_ϕ[i]).coeffs[1]) + TaylorSeries.zero!(tmp5601[i]) + (tmp5601[i]).coeffs[1] = -(constant_term(X[i])) + TaylorSeries.zero!(t31[i]) + (t31[i]).coeffs[1] = constant_term(tmp5601[i]) * constant_term(M_[1, 3, i]) + TaylorSeries.zero!(tmp5603[i]) + (tmp5603[i]).coeffs[1] = -(constant_term(Y[i])) + TaylorSeries.zero!(t32[i]) + (t32[i]).coeffs[1] = constant_term(tmp5603[i]) * constant_term(M_[2, 3, i]) + TaylorSeries.zero!(tmp5605[i]) + (tmp5605[i]).coeffs[1] = -(constant_term(Z[i])) + TaylorSeries.zero!(t33[i]) + (t33[i]).coeffs[1] = constant_term(tmp5605[i]) * constant_term(M_[3, 3, i]) + TaylorSeries.zero!(tmp5607[i]) + (tmp5607[i]).coeffs[1] = constant_term(t31[i]) + constant_term(t32[i]) + TaylorSeries.zero!(r_sin_ϕ[i]) + (r_sin_ϕ[i]).coeffs[1] = constant_term(tmp5607[i]) + constant_term(t33[i]) + TaylorSeries.zero!(sin_ϕ[i]) (sin_ϕ[i]).coeffs[1] = constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]) - (sin_ϕ[i]).coeffs[2:order + 1] .= zero((sin_ϕ[i]).coeffs[1]) + TaylorSeries.zero!(ϕ[i]) (ϕ[i]).coeffs[1] = asin(constant_term(sin_ϕ[i])) - (ϕ[i]).coeffs[2:order + 1] .= zero((ϕ[i]).coeffs[1]) - (tmp948[i]).coeffs[1] = sqrt(1 - constant_term(sin_ϕ[i]) ^ 2) - (tmp948[i]).coeffs[2:order + 1] .= zero((tmp948[i]).coeffs[1]) + TaylorSeries.zero!(tmp5814[i]) + (tmp5814[i]).coeffs[1] = sqrt(1 - constant_term(sin_ϕ[i]) ^ 2) + TaylorSeries.zero!(cos_ϕ[i]) (cos_ϕ[i]).coeffs[1] = cos(constant_term(ϕ[i])) - (cos_ϕ[i]).coeffs[2:order + 1] .= zero((cos_ϕ[i]).coeffs[1]) - (tmp949[i]).coeffs[1] = sin(constant_term(ϕ[i])) - (tmp949[i]).coeffs[2:order + 1] .= zero((tmp949[i]).coeffs[1]) + TaylorSeries.zero!(tmp5815[i]) + (tmp5815[i]).coeffs[1] = sin(constant_term(ϕ[i])) + TaylorSeries.zero!(sin2_ϕ[i]) (sin2_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(2)) - (sin2_ϕ[i]).coeffs[2:order + 1] .= zero((sin2_ϕ[i]).coeffs[1]) + TaylorSeries.zero!(sin3_ϕ[i]) (sin3_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(3)) - (sin3_ϕ[i]).coeffs[2:order + 1] .= zero((sin3_ϕ[i]).coeffs[1]) - (tmp751[i]).coeffs[1] = constant_term(1.5) * constant_term(sin2_ϕ[i]) - (tmp751[i]).coeffs[2:order + 1] .= zero((tmp751[i]).coeffs[1]) - (P_2_sin_ϕ[i]).coeffs[1] = constant_term(tmp751[i]) - constant_term(0.5) - (P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_2_sin_ϕ[i]).coeffs[1]) + TaylorSeries.zero!(tmp5617[i]) + (tmp5617[i]).coeffs[1] = constant_term(1.5) * constant_term(sin2_ϕ[i]) + TaylorSeries.zero!(P_2_sin_ϕ[i]) + (P_2_sin_ϕ[i]).coeffs[1] = constant_term(tmp5617[i]) - constant_term(0.5) + TaylorSeries.zero!(∂P_2_sin_ϕ[i]) (∂P_2_sin_ϕ[i]).coeffs[1] = constant_term(3) * constant_term(sin_ϕ[i]) - (∂P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_2_sin_ϕ[i]).coeffs[1]) - (tmp757[i]).coeffs[1] = constant_term(-1.5) * constant_term(sin_ϕ[i]) - (tmp757[i]).coeffs[2:order + 1] .= zero((tmp757[i]).coeffs[1]) - (tmp759[i]).coeffs[1] = constant_term(2.5) * constant_term(sin3_ϕ[i]) - (tmp759[i]).coeffs[2:order + 1] .= zero((tmp759[i]).coeffs[1]) - (P_3_sin_ϕ[i]).coeffs[1] = constant_term(tmp757[i]) + constant_term(tmp759[i]) - (P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_3_sin_ϕ[i]).coeffs[1]) - (tmp763[i]).coeffs[1] = constant_term(7.5) * constant_term(sin2_ϕ[i]) - (tmp763[i]).coeffs[2:order + 1] .= zero((tmp763[i]).coeffs[1]) - (∂P_3_sin_ϕ[i]).coeffs[1] = constant_term(-1.5) + constant_term(tmp763[i]) - (∂P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_3_sin_ϕ[i]).coeffs[1]) - (tmp766[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(2)) - (tmp766[i]).coeffs[2:order + 1] .= zero((tmp766[i]).coeffs[1]) - (tmp767[i]).coeffs[1] = constant_term(Λ2[i]) / constant_term(tmp766[i]) - (tmp767[i]).coeffs[2:order + 1] .= zero((tmp767[i]).coeffs[1]) - (Λ2j_div_r4[i]).coeffs[1] = -(constant_term(tmp767[i])) - (Λ2j_div_r4[i]).coeffs[2:order + 1] .= zero((Λ2j_div_r4[i]).coeffs[1]) - (tmp770[i]).coeffs[1] = constant_term(r_p1d2[i]) ^ float(constant_term(5)) - (tmp770[i]).coeffs[2:order + 1] .= zero((tmp770[i]).coeffs[1]) - (tmp771[i]).coeffs[1] = constant_term(Λ3[i]) / constant_term(tmp770[i]) - (tmp771[i]).coeffs[2:order + 1] .= zero((tmp771[i]).coeffs[1]) - (Λ3j_div_r5[i]).coeffs[1] = -(constant_term(tmp771[i])) - (Λ3j_div_r5[i]).coeffs[2:order + 1] .= zero((Λ3j_div_r5[i]).coeffs[1]) - (tmp773[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) - (tmp773[i]).coeffs[2:order + 1] .= zero((tmp773[i]).coeffs[1]) - (m_c_ϕ_∂P_2[i]).coeffs[1] = constant_term(tmp773[i]) * constant_term(∂P_2_sin_ϕ[i]) - (m_c_ϕ_∂P_2[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_2[i]).coeffs[1]) - (tmp775[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) - (tmp775[i]).coeffs[2:order + 1] .= zero((tmp775[i]).coeffs[1]) - (m_c_ϕ_∂P_3[i]).coeffs[1] = constant_term(tmp775[i]) * constant_term(∂P_3_sin_ϕ[i]) - (m_c_ϕ_∂P_3[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_3[i]).coeffs[1]) - (tmp778[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(3) - (tmp778[i]).coeffs[2:order + 1] .= zero((tmp778[i]).coeffs[1]) - (F_J2_ξ[i]).coeffs[1] = constant_term(tmp778[i]) * constant_term(P_2_sin_ϕ[i]) - (F_J2_ξ[i]).coeffs[2:order + 1] .= zero((F_J2_ξ[i]).coeffs[1]) + TaylorSeries.zero!(tmp5623[i]) + (tmp5623[i]).coeffs[1] = constant_term(-1.5) * constant_term(sin_ϕ[i]) + TaylorSeries.zero!(tmp5625[i]) + (tmp5625[i]).coeffs[1] = constant_term(2.5) * constant_term(sin3_ϕ[i]) + TaylorSeries.zero!(P_3_sin_ϕ[i]) + (P_3_sin_ϕ[i]).coeffs[1] = constant_term(tmp5623[i]) + constant_term(tmp5625[i]) + TaylorSeries.zero!(tmp5629[i]) + (tmp5629[i]).coeffs[1] = constant_term(7.5) * constant_term(sin2_ϕ[i]) + TaylorSeries.zero!(∂P_3_sin_ϕ[i]) + (∂P_3_sin_ϕ[i]).coeffs[1] = constant_term(-1.5) + constant_term(tmp5629[i]) + TaylorSeries.zero!(tmp5632[i]) + (tmp5632[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(2)) + TaylorSeries.zero!(tmp5633[i]) + (tmp5633[i]).coeffs[1] = constant_term(Λ2[i]) / constant_term(tmp5632[i]) + TaylorSeries.zero!(Λ2j_div_r4[i]) + (Λ2j_div_r4[i]).coeffs[1] = -(constant_term(tmp5633[i])) + TaylorSeries.zero!(tmp5636[i]) + (tmp5636[i]).coeffs[1] = constant_term(r_p1d2[i]) ^ float(constant_term(5)) + TaylorSeries.zero!(tmp5637[i]) + (tmp5637[i]).coeffs[1] = constant_term(Λ3[i]) / constant_term(tmp5636[i]) + TaylorSeries.zero!(Λ3j_div_r5[i]) + (Λ3j_div_r5[i]).coeffs[1] = -(constant_term(tmp5637[i])) + TaylorSeries.zero!(tmp5639[i]) + (tmp5639[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) + TaylorSeries.zero!(m_c_ϕ_∂P_2[i]) + (m_c_ϕ_∂P_2[i]).coeffs[1] = constant_term(tmp5639[i]) * constant_term(∂P_2_sin_ϕ[i]) + TaylorSeries.zero!(tmp5641[i]) + (tmp5641[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) + TaylorSeries.zero!(m_c_ϕ_∂P_3[i]) + (m_c_ϕ_∂P_3[i]).coeffs[1] = constant_term(tmp5641[i]) * constant_term(∂P_3_sin_ϕ[i]) + TaylorSeries.zero!(tmp5644[i]) + (tmp5644[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(3) + TaylorSeries.zero!(F_J2_ξ[i]) + (F_J2_ξ[i]).coeffs[1] = constant_term(tmp5644[i]) * constant_term(P_2_sin_ϕ[i]) + TaylorSeries.zero!(F_J2_ζ[i]) (F_J2_ζ[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]) - (F_J2_ζ[i]).coeffs[2:order + 1] .= zero((F_J2_ζ[i]).coeffs[1]) - (tmp782[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(4) - (tmp782[i]).coeffs[2:order + 1] .= zero((tmp782[i]).coeffs[1]) - (F_J3_ξ[i]).coeffs[1] = constant_term(tmp782[i]) * constant_term(P_3_sin_ϕ[i]) - (F_J3_ξ[i]).coeffs[2:order + 1] .= zero((F_J3_ξ[i]).coeffs[1]) + TaylorSeries.zero!(tmp5648[i]) + (tmp5648[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(4) + TaylorSeries.zero!(F_J3_ξ[i]) + (F_J3_ξ[i]).coeffs[1] = constant_term(tmp5648[i]) * constant_term(P_3_sin_ϕ[i]) + TaylorSeries.zero!(F_J3_ζ[i]) (F_J3_ζ[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]) - (F_J3_ζ[i]).coeffs[2:order + 1] .= zero((F_J3_ζ[i]).coeffs[1]) + TaylorSeries.zero!(F_J_ξ[i]) (F_J_ξ[i]).coeffs[1] = identity(constant_term(F_J2_ξ[i])) - (F_J_ξ[i]).coeffs[2:order + 1] .= zero((F_J_ξ[i]).coeffs[1]) + TaylorSeries.zero!(F_J_ζ[i]) (F_J_ζ[i]).coeffs[1] = identity(constant_term(F_J2_ζ[i])) - (F_J_ζ[i]).coeffs[2:order + 1] .= zero((F_J_ζ[i]).coeffs[1]) - (tmp785[i]).coeffs[1] = -(constant_term(X[i])) - (tmp785[i]).coeffs[2:order + 1] .= zero((tmp785[i]).coeffs[1]) - (ξx[i]).coeffs[1] = constant_term(tmp785[i]) / constant_term(r_p1d2[i]) - (ξx[i]).coeffs[2:order + 1] .= zero((ξx[i]).coeffs[1]) - (tmp787[i]).coeffs[1] = -(constant_term(Y[i])) - (tmp787[i]).coeffs[2:order + 1] .= zero((tmp787[i]).coeffs[1]) - (ξy[i]).coeffs[1] = constant_term(tmp787[i]) / constant_term(r_p1d2[i]) - (ξy[i]).coeffs[2:order + 1] .= zero((ξy[i]).coeffs[1]) - (tmp789[i]).coeffs[1] = -(constant_term(Z[i])) - (tmp789[i]).coeffs[2:order + 1] .= zero((tmp789[i]).coeffs[1]) - (ξz[i]).coeffs[1] = constant_term(tmp789[i]) / constant_term(r_p1d2[i]) - (ξz[i]).coeffs[2:order + 1] .= zero((ξz[i]).coeffs[1]) + TaylorSeries.zero!(tmp5651[i]) + (tmp5651[i]).coeffs[1] = -(constant_term(X[i])) + TaylorSeries.zero!(ξx[i]) + (ξx[i]).coeffs[1] = constant_term(tmp5651[i]) / constant_term(r_p1d2[i]) + TaylorSeries.zero!(tmp5653[i]) + (tmp5653[i]).coeffs[1] = -(constant_term(Y[i])) + TaylorSeries.zero!(ξy[i]) + (ξy[i]).coeffs[1] = constant_term(tmp5653[i]) / constant_term(r_p1d2[i]) + TaylorSeries.zero!(tmp5655[i]) + (tmp5655[i]).coeffs[1] = -(constant_term(Z[i])) + TaylorSeries.zero!(ξz[i]) + (ξz[i]).coeffs[1] = constant_term(tmp5655[i]) / constant_term(r_p1d2[i]) + TaylorSeries.zero!(ηx1[i]) (ηx1[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξz[i]) - (ηx1[i]).coeffs[2:order + 1] .= zero((ηx1[i]).coeffs[1]) + TaylorSeries.zero!(ηy1[i]) (ηy1[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξx[i]) - (ηy1[i]).coeffs[2:order + 1] .= zero((ηy1[i]).coeffs[1]) + TaylorSeries.zero!(ηz1[i]) (ηz1[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξy[i]) - (ηz1[i]).coeffs[2:order + 1] .= zero((ηz1[i]).coeffs[1]) + TaylorSeries.zero!(ηx2[i]) (ηx2[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξy[i]) - (ηx2[i]).coeffs[2:order + 1] .= zero((ηx2[i]).coeffs[1]) + TaylorSeries.zero!(ηy2[i]) (ηy2[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξz[i]) - (ηy2[i]).coeffs[2:order + 1] .= zero((ηy2[i]).coeffs[1]) + TaylorSeries.zero!(ηz2[i]) (ηz2[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξx[i]) - (ηz2[i]).coeffs[2:order + 1] .= zero((ηz2[i]).coeffs[1]) + TaylorSeries.zero!(ηx[i]) (ηx[i]).coeffs[1] = constant_term(ηx1[i]) - constant_term(ηx2[i]) - (ηx[i]).coeffs[2:order + 1] .= zero((ηx[i]).coeffs[1]) + TaylorSeries.zero!(ηy[i]) (ηy[i]).coeffs[1] = constant_term(ηy1[i]) - constant_term(ηy2[i]) - (ηy[i]).coeffs[2:order + 1] .= zero((ηy[i]).coeffs[1]) + TaylorSeries.zero!(ηz[i]) (ηz[i]).coeffs[1] = constant_term(ηz1[i]) - constant_term(ηz2[i]) - (ηz[i]).coeffs[2:order + 1] .= zero((ηz[i]).coeffs[1]) + TaylorSeries.zero!(ζx1[i]) (ζx1[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηz[i]) - (ζx1[i]).coeffs[2:order + 1] .= zero((ζx1[i]).coeffs[1]) + TaylorSeries.zero!(ζy1[i]) (ζy1[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηx[i]) - (ζy1[i]).coeffs[2:order + 1] .= zero((ζy1[i]).coeffs[1]) + TaylorSeries.zero!(ζz1[i]) (ζz1[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηy[i]) - (ζz1[i]).coeffs[2:order + 1] .= zero((ζz1[i]).coeffs[1]) + TaylorSeries.zero!(ζx2[i]) (ζx2[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηy[i]) - (ζx2[i]).coeffs[2:order + 1] .= zero((ζx2[i]).coeffs[1]) + TaylorSeries.zero!(ζy2[i]) (ζy2[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηz[i]) - (ζy2[i]).coeffs[2:order + 1] .= zero((ζy2[i]).coeffs[1]) + TaylorSeries.zero!(ζz2[i]) (ζz2[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηx[i]) - (ζz2[i]).coeffs[2:order + 1] .= zero((ζz2[i]).coeffs[1]) + TaylorSeries.zero!(ζx[i]) (ζx[i]).coeffs[1] = constant_term(ζx1[i]) - constant_term(ζx2[i]) - (ζx[i]).coeffs[2:order + 1] .= zero((ζx[i]).coeffs[1]) + TaylorSeries.zero!(ζy[i]) (ζy[i]).coeffs[1] = constant_term(ζy1[i]) - constant_term(ζy2[i]) - (ζy[i]).coeffs[2:order + 1] .= zero((ζy[i]).coeffs[1]) + TaylorSeries.zero!(ζz[i]) (ζz[i]).coeffs[1] = constant_term(ζz1[i]) - constant_term(ζz2[i]) - (ζz[i]).coeffs[2:order + 1] .= zero((ζz[i]).coeffs[1]) + TaylorSeries.zero!(F_J2_x1[i]) (F_J2_x1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξx[i]) - (F_J2_x1[i]).coeffs[2:order + 1] .= zero((F_J2_x1[i]).coeffs[1]) + TaylorSeries.zero!(F_J2_y1[i]) (F_J2_y1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξy[i]) - (F_J2_y1[i]).coeffs[2:order + 1] .= zero((F_J2_y1[i]).coeffs[1]) + TaylorSeries.zero!(F_J2_z1[i]) (F_J2_z1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξz[i]) - (F_J2_z1[i]).coeffs[2:order + 1] .= zero((F_J2_z1[i]).coeffs[1]) + TaylorSeries.zero!(F_J2_x2[i]) (F_J2_x2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζx[i]) - (F_J2_x2[i]).coeffs[2:order + 1] .= zero((F_J2_x2[i]).coeffs[1]) + TaylorSeries.zero!(F_J2_y2[i]) (F_J2_y2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζy[i]) - (F_J2_y2[i]).coeffs[2:order + 1] .= zero((F_J2_y2[i]).coeffs[1]) + TaylorSeries.zero!(F_J2_z2[i]) (F_J2_z2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζz[i]) - (F_J2_z2[i]).coeffs[2:order + 1] .= zero((F_J2_z2[i]).coeffs[1]) + TaylorSeries.zero!(F_J2_x[i]) (F_J2_x[i]).coeffs[1] = constant_term(F_J2_x1[i]) + constant_term(F_J2_x2[i]) - (F_J2_x[i]).coeffs[2:order + 1] .= zero((F_J2_x[i]).coeffs[1]) + TaylorSeries.zero!(F_J2_y[i]) (F_J2_y[i]).coeffs[1] = constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]) - (F_J2_y[i]).coeffs[2:order + 1] .= zero((F_J2_y[i]).coeffs[1]) + TaylorSeries.zero!(F_J2_z[i]) (F_J2_z[i]).coeffs[1] = constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]) - (F_J2_z[i]).coeffs[2:order + 1] .= zero((F_J2_z[i]).coeffs[1]) end - (tmp819[i]).coeffs[1] = constant_term(ui[i]) ^ float(constant_term(2)) - (tmp819[i]).coeffs[2:order + 1] .= zero((tmp819[i]).coeffs[1]) - (tmp821[i]).coeffs[1] = constant_term(vi[i]) ^ float(constant_term(2)) - (tmp821[i]).coeffs[2:order + 1] .= zero((tmp821[i]).coeffs[1]) - (tmp822[i]).coeffs[1] = constant_term(tmp819[i]) + constant_term(tmp821[i]) - (tmp822[i]).coeffs[2:order + 1] .= zero((tmp822[i]).coeffs[1]) - (tmp824[i]).coeffs[1] = constant_term(wi[i]) ^ float(constant_term(2)) - (tmp824[i]).coeffs[2:order + 1] .= zero((tmp824[i]).coeffs[1]) - (v2[i]).coeffs[1] = constant_term(tmp822[i]) + constant_term(tmp824[i]) - (v2[i]).coeffs[2:order + 1] .= zero((v2[i]).coeffs[1]) + TaylorSeries.zero!(tmp5685[i]) + (tmp5685[i]).coeffs[1] = constant_term(ui[i]) ^ float(constant_term(2)) + TaylorSeries.zero!(tmp5687[i]) + (tmp5687[i]).coeffs[1] = constant_term(vi[i]) ^ float(constant_term(2)) + TaylorSeries.zero!(tmp5688[i]) + (tmp5688[i]).coeffs[1] = constant_term(tmp5685[i]) + constant_term(tmp5687[i]) + TaylorSeries.zero!(tmp5690[i]) + (tmp5690[i]).coeffs[1] = constant_term(wi[i]) ^ float(constant_term(2)) + TaylorSeries.zero!(v2[i]) + (v2[i]).coeffs[1] = constant_term(tmp5688[i]) + constant_term(tmp5690[i]) end - tmp827.coeffs[1] = constant_term(q[4]) ^ float(constant_term(2)) - tmp827.coeffs[2:order + 1] .= zero(tmp827.coeffs[1]) - tmp829.coeffs[1] = constant_term(q[5]) ^ float(constant_term(2)) - tmp829.coeffs[2:order + 1] .= zero(tmp829.coeffs[1]) - tmp830.coeffs[1] = constant_term(tmp827) + constant_term(tmp829) - tmp830.coeffs[2:order + 1] .= zero(tmp830.coeffs[1]) - tmp832.coeffs[1] = constant_term(q[6]) ^ float(constant_term(2)) - tmp832.coeffs[2:order + 1] .= zero(tmp832.coeffs[1]) - (v2[N]).coeffs[1] = constant_term(tmp830) + constant_term(tmp832) - (v2[N]).coeffs[2:order + 1] .= zero((v2[N]).coeffs[1]) + TaylorSeries.zero!(tmp5693) + tmp5693.coeffs[1] = constant_term(q[4]) ^ float(constant_term(2)) + TaylorSeries.zero!(tmp5695) + tmp5695.coeffs[1] = constant_term(q[5]) ^ float(constant_term(2)) + TaylorSeries.zero!(tmp5696) + tmp5696.coeffs[1] = constant_term(tmp5693) + constant_term(tmp5695) + TaylorSeries.zero!(tmp5698) + tmp5698.coeffs[1] = constant_term(q[6]) ^ float(constant_term(2)) + TaylorSeries.zero!(v2[N]) + (v2[N]).coeffs[1] = constant_term(tmp5696) + constant_term(tmp5698) for i = 1:Nm1 + TaylorSeries.zero!(temp_004[i]) (temp_004[i]).coeffs[1] = constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]) - (temp_004[i]).coeffs[2:order + 1] .= zero((temp_004[i]).coeffs[1]) + TaylorSeries.zero!(newtonianNb_Potential[N]) (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(temp_004[i])) - (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) if UJ_interaction[i] - (tmp835[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_x[i]) - (tmp835[i]).coeffs[2:order + 1] .= zero((tmp835[i]).coeffs[1]) - (temp_accX_i[i]).coeffs[1] = constant_term(accX) - constant_term(tmp835[i]) - (temp_accX_i[i]).coeffs[2:order + 1] .= zero((temp_accX_i[i]).coeffs[1]) + TaylorSeries.zero!(tmp5701[i]) + (tmp5701[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_x[i]) + TaylorSeries.zero!(temp_accX_i[i]) + (temp_accX_i[i]).coeffs[1] = constant_term(accX) - constant_term(tmp5701[i]) + TaylorSeries.zero!(accX) accX.coeffs[1] = identity(constant_term(temp_accX_i[i])) - accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) - (tmp837[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_y[i]) - (tmp837[i]).coeffs[2:order + 1] .= zero((tmp837[i]).coeffs[1]) - (temp_accY_i[i]).coeffs[1] = constant_term(accY) - constant_term(tmp837[i]) - (temp_accY_i[i]).coeffs[2:order + 1] .= zero((temp_accY_i[i]).coeffs[1]) + TaylorSeries.zero!(tmp5703[i]) + (tmp5703[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_y[i]) + TaylorSeries.zero!(temp_accY_i[i]) + (temp_accY_i[i]).coeffs[1] = constant_term(accY) - constant_term(tmp5703[i]) + TaylorSeries.zero!(accY) accY.coeffs[1] = identity(constant_term(temp_accY_i[i])) - accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) - (tmp839[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_z[i]) - (tmp839[i]).coeffs[2:order + 1] .= zero((tmp839[i]).coeffs[1]) - (temp_accZ_i[i]).coeffs[1] = constant_term(accZ) - constant_term(tmp839[i]) - (temp_accZ_i[i]).coeffs[2:order + 1] .= zero((temp_accZ_i[i]).coeffs[1]) + TaylorSeries.zero!(tmp5705[i]) + (tmp5705[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_z[i]) + TaylorSeries.zero!(temp_accZ_i[i]) + (temp_accZ_i[i]).coeffs[1] = constant_term(accZ) - constant_term(tmp5705[i]) + TaylorSeries.zero!(accZ) accZ.coeffs[1] = identity(constant_term(temp_accZ_i[i])) - accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) end end + TaylorSeries.zero!(_4ϕj[N]) (_4ϕj[N]).coeffs[1] = constant_term(4) * constant_term(newtonianNb_Potential[N]) - (_4ϕj[N]).coeffs[2:order + 1] .= zero((_4ϕj[N]).coeffs[1]) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 + #= /Users/Jorge/projects/neos240702/neosjetcoeffs.jl:455 =# Threads.@threads for i = 1:10 + TaylorSeries.zero!(ϕi_plus_4ϕj[i]) (ϕi_plus_4ϕj[i]).coeffs[1] = constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]) - (ϕi_plus_4ϕj[i]).coeffs[2:order + 1] .= zero((ϕi_plus_4ϕj[i]).coeffs[1]) - (tmp845[i]).coeffs[1] = constant_term(2) * constant_term(v2[i]) - (tmp845[i]).coeffs[2:order + 1] .= zero((tmp845[i]).coeffs[1]) - (tmp847[i]).coeffs[1] = constant_term(4) * constant_term(vi_dot_vj[i]) - (tmp847[i]).coeffs[2:order + 1] .= zero((tmp847[i]).coeffs[1]) - (tmp848[i]).coeffs[1] = constant_term(tmp845[i]) - constant_term(tmp847[i]) - (tmp848[i]).coeffs[2:order + 1] .= zero((tmp848[i]).coeffs[1]) - (sj2_plus_2si2_minus_4vivj[i]).coeffs[1] = constant_term(tmp848[i]) + constant_term(v2[N]) - (sj2_plus_2si2_minus_4vivj[i]).coeffs[2:order + 1] .= zero((sj2_plus_2si2_minus_4vivj[i]).coeffs[1]) + TaylorSeries.zero!(tmp5711[i]) + (tmp5711[i]).coeffs[1] = constant_term(2) * constant_term(v2[i]) + TaylorSeries.zero!(tmp5713[i]) + (tmp5713[i]).coeffs[1] = constant_term(4) * constant_term(vi_dot_vj[i]) + TaylorSeries.zero!(tmp5714[i]) + (tmp5714[i]).coeffs[1] = constant_term(tmp5711[i]) - constant_term(tmp5713[i]) + TaylorSeries.zero!(sj2_plus_2si2_minus_4vivj[i]) + (sj2_plus_2si2_minus_4vivj[i]).coeffs[1] = constant_term(tmp5714[i]) + constant_term(v2[N]) + TaylorSeries.zero!(ϕs_and_vs[i]) (ϕs_and_vs[i]).coeffs[1] = constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]) - (ϕs_and_vs[i]).coeffs[2:order + 1] .= zero((ϕs_and_vs[i]).coeffs[1]) + TaylorSeries.zero!(Xij_t_Ui[i]) (Xij_t_Ui[i]).coeffs[1] = constant_term(X[i]) * constant_term(ui[i]) - (Xij_t_Ui[i]).coeffs[2:order + 1] .= zero((Xij_t_Ui[i]).coeffs[1]) + TaylorSeries.zero!(Yij_t_Vi[i]) (Yij_t_Vi[i]).coeffs[1] = constant_term(Y[i]) * constant_term(vi[i]) - (Yij_t_Vi[i]).coeffs[2:order + 1] .= zero((Yij_t_Vi[i]).coeffs[1]) + TaylorSeries.zero!(Zij_t_Wi[i]) (Zij_t_Wi[i]).coeffs[1] = constant_term(Z[i]) * constant_term(wi[i]) - (Zij_t_Wi[i]).coeffs[2:order + 1] .= zero((Zij_t_Wi[i]).coeffs[1]) - (tmp854[i]).coeffs[1] = constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]) - (tmp854[i]).coeffs[2:order + 1] .= zero((tmp854[i]).coeffs[1]) - (Rij_dot_Vi[i]).coeffs[1] = constant_term(tmp854[i]) + constant_term(Zij_t_Wi[i]) - (Rij_dot_Vi[i]).coeffs[2:order + 1] .= zero((Rij_dot_Vi[i]).coeffs[1]) - (tmp857[i]).coeffs[1] = constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)) - (tmp857[i]).coeffs[2:order + 1] .= zero((tmp857[i]).coeffs[1]) - (pn1t7[i]).coeffs[1] = constant_term(tmp857[i]) / constant_term(r_p2[i]) - (pn1t7[i]).coeffs[2:order + 1] .= zero((pn1t7[i]).coeffs[1]) - (tmp860[i]).coeffs[1] = constant_term(1.5) * constant_term(pn1t7[i]) - (tmp860[i]).coeffs[2:order + 1] .= zero((tmp860[i]).coeffs[1]) - (pn1t2_7[i]).coeffs[1] = constant_term(ϕs_and_vs[i]) - constant_term(tmp860[i]) - (pn1t2_7[i]).coeffs[2:order + 1] .= zero((pn1t2_7[i]).coeffs[1]) + TaylorSeries.zero!(tmp5720[i]) + (tmp5720[i]).coeffs[1] = constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]) + TaylorSeries.zero!(Rij_dot_Vi[i]) + (Rij_dot_Vi[i]).coeffs[1] = constant_term(tmp5720[i]) + constant_term(Zij_t_Wi[i]) + TaylorSeries.zero!(tmp5723[i]) + (tmp5723[i]).coeffs[1] = constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)) + TaylorSeries.zero!(pn1t7[i]) + (pn1t7[i]).coeffs[1] = constant_term(tmp5723[i]) / constant_term(r_p2[i]) + TaylorSeries.zero!(tmp5726[i]) + (tmp5726[i]).coeffs[1] = constant_term(1.5) * constant_term(pn1t7[i]) + TaylorSeries.zero!(pn1t2_7[i]) + (pn1t2_7[i]).coeffs[1] = constant_term(ϕs_and_vs[i]) - constant_term(tmp5726[i]) + TaylorSeries.zero!(pn1t1_7[i]) (pn1t1_7[i]).coeffs[1] = constant_term(c_p2) + constant_term(pn1t2_7[i]) - (pn1t1_7[i]).coeffs[2:order + 1] .= zero((pn1t1_7[i]).coeffs[1]) + TaylorSeries.zero!(pNX_t_X[i]) (pNX_t_X[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(X[i]) - (pNX_t_X[i]).coeffs[2:order + 1] .= zero((pNX_t_X[i]).coeffs[1]) + TaylorSeries.zero!(pNY_t_Y[i]) (pNY_t_Y[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(Y[i]) - (pNY_t_Y[i]).coeffs[2:order + 1] .= zero((pNY_t_Y[i]).coeffs[1]) + TaylorSeries.zero!(pNZ_t_Z[i]) (pNZ_t_Z[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(Z[i]) - (pNZ_t_Z[i]).coeffs[2:order + 1] .= zero((pNZ_t_Z[i]).coeffs[1]) - (tmp867[i]).coeffs[1] = constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]) - (tmp867[i]).coeffs[2:order + 1] .= zero((tmp867[i]).coeffs[1]) - (tmp868[i]).coeffs[1] = constant_term(tmp867[i]) + constant_term(pNZ_t_Z[i]) - (tmp868[i]).coeffs[2:order + 1] .= zero((tmp868[i]).coeffs[1]) - (tmp869[i]).coeffs[1] = constant_term(0.5) * constant_term(tmp868[i]) - (tmp869[i]).coeffs[2:order + 1] .= zero((tmp869[i]).coeffs[1]) - (pn1[i]).coeffs[1] = constant_term(pn1t1_7[i]) + constant_term(tmp869[i]) - (pn1[i]).coeffs[2:order + 1] .= zero((pn1[i]).coeffs[1]) + TaylorSeries.zero!(tmp5733[i]) + (tmp5733[i]).coeffs[1] = constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]) + TaylorSeries.zero!(tmp5734[i]) + (tmp5734[i]).coeffs[1] = constant_term(tmp5733[i]) + constant_term(pNZ_t_Z[i]) + TaylorSeries.zero!(tmp5735[i]) + (tmp5735[i]).coeffs[1] = constant_term(0.5) * constant_term(tmp5734[i]) + TaylorSeries.zero!(pn1[i]) + (pn1[i]).coeffs[1] = constant_term(pn1t1_7[i]) + constant_term(tmp5735[i]) + TaylorSeries.zero!(X_t_pn1[i]) (X_t_pn1[i]).coeffs[1] = constant_term(newton_acc_X[i]) * constant_term(pn1[i]) - (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) + TaylorSeries.zero!(Y_t_pn1[i]) (Y_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Y[i]) * constant_term(pn1[i]) - (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) + TaylorSeries.zero!(Z_t_pn1[i]) (Z_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Z[i]) * constant_term(pn1[i]) - (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) + TaylorSeries.zero!(pNX_t_pn3[i]) (pNX_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(pn3[i]) - (pNX_t_pn3[i]).coeffs[2:order + 1] .= zero((pNX_t_pn3[i]).coeffs[1]) + TaylorSeries.zero!(pNY_t_pn3[i]) (pNY_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]) - (pNY_t_pn3[i]).coeffs[2:order + 1] .= zero((pNY_t_pn3[i]).coeffs[1]) + TaylorSeries.zero!(pNZ_t_pn3[i]) (pNZ_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(pn3[i]) - (pNZ_t_pn3[i]).coeffs[2:order + 1] .= zero((pNZ_t_pn3[i]).coeffs[1]) end for i = 1:10 - (tmp877[i]).coeffs[1] = constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]) - (tmp877[i]).coeffs[2:order + 1] .= zero((tmp877[i]).coeffs[1]) - (termpnx[i]).coeffs[1] = constant_term(X_t_pn1[i]) + constant_term(tmp877[i]) - (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) + TaylorSeries.zero!(tmp5743[i]) + (tmp5743[i]).coeffs[1] = constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]) + TaylorSeries.zero!(termpnx[i]) + (termpnx[i]).coeffs[1] = constant_term(X_t_pn1[i]) + constant_term(tmp5743[i]) + TaylorSeries.zero!(sumpnx[i]) (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) - (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) + TaylorSeries.zero!(pntempX) pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) - pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) - (tmp880[i]).coeffs[1] = constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]) - (tmp880[i]).coeffs[2:order + 1] .= zero((tmp880[i]).coeffs[1]) - (termpny[i]).coeffs[1] = constant_term(Y_t_pn1[i]) + constant_term(tmp880[i]) - (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) + TaylorSeries.zero!(tmp5746[i]) + (tmp5746[i]).coeffs[1] = constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]) + TaylorSeries.zero!(termpny[i]) + (termpny[i]).coeffs[1] = constant_term(Y_t_pn1[i]) + constant_term(tmp5746[i]) + TaylorSeries.zero!(sumpny[i]) (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) - (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) + TaylorSeries.zero!(pntempY) pntempY.coeffs[1] = identity(constant_term(sumpny[i])) - pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) - (tmp883[i]).coeffs[1] = constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]) - (tmp883[i]).coeffs[2:order + 1] .= zero((tmp883[i]).coeffs[1]) - (termpnz[i]).coeffs[1] = constant_term(Z_t_pn1[i]) + constant_term(tmp883[i]) - (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) + TaylorSeries.zero!(tmp5749[i]) + (tmp5749[i]).coeffs[1] = constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]) + TaylorSeries.zero!(termpnz[i]) + (termpnz[i]).coeffs[1] = constant_term(Z_t_pn1[i]) + constant_term(tmp5749[i]) + TaylorSeries.zero!(sumpnz[i]) (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) - (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) + TaylorSeries.zero!(pntempZ) pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) - pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) end - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 + #= /Users/Jorge/projects/neos240702/neosjetcoeffs.jl:508 =# Threads.@threads for i = 11:Nm1 + TaylorSeries.zero!(X_t_pn1[i]) (X_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_X[i]) - (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) + TaylorSeries.zero!(Y_t_pn1[i]) (Y_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Y[i]) - (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) + TaylorSeries.zero!(Z_t_pn1[i]) (Z_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Z[i]) - (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) end for i = 11:Nm1 + TaylorSeries.zero!(termpnx[i]) (termpnx[i]).coeffs[1] = identity(constant_term(X_t_pn1[i])) - (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) + TaylorSeries.zero!(sumpnx[i]) (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) - (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) + TaylorSeries.zero!(pntempX) pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) - pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) + TaylorSeries.zero!(termpny[i]) (termpny[i]).coeffs[1] = identity(constant_term(Y_t_pn1[i])) - (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) + TaylorSeries.zero!(sumpny[i]) (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) - (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) + TaylorSeries.zero!(pntempY) pntempY.coeffs[1] = identity(constant_term(sumpny[i])) - pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) + TaylorSeries.zero!(termpnz[i]) (termpnz[i]).coeffs[1] = identity(constant_term(Z_t_pn1[i])) - (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) + TaylorSeries.zero!(sumpnz[i]) (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) - (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) + TaylorSeries.zero!(pntempZ) pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) - pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) end + TaylorSeries.zero!(postNewtonX) postNewtonX.coeffs[1] = constant_term(pntempX) * constant_term(c_m2) - postNewtonX.coeffs[2:order + 1] .= zero(postNewtonX.coeffs[1]) + TaylorSeries.zero!(postNewtonY) postNewtonY.coeffs[1] = constant_term(pntempY) * constant_term(c_m2) - postNewtonY.coeffs[2:order + 1] .= zero(postNewtonY.coeffs[1]) + TaylorSeries.zero!(postNewtonZ) postNewtonZ.coeffs[1] = constant_term(pntempZ) * constant_term(c_m2) - postNewtonZ.coeffs[2:order + 1] .= zero(postNewtonZ.coeffs[1]) - tmp895.coeffs[1] = constant_term(Y[1]) * constant_term(W[1]) - tmp895.coeffs[2:order + 1] .= zero(tmp895.coeffs[1]) - tmp896.coeffs[1] = constant_term(Z[1]) * constant_term(V[1]) - tmp896.coeffs[2:order + 1] .= zero(tmp896.coeffs[1]) - hx.coeffs[1] = constant_term(tmp895) - constant_term(tmp896) - hx.coeffs[2:order + 1] .= zero(hx.coeffs[1]) - tmp898.coeffs[1] = constant_term(Z[1]) * constant_term(U[1]) - tmp898.coeffs[2:order + 1] .= zero(tmp898.coeffs[1]) - tmp899.coeffs[1] = constant_term(X[1]) * constant_term(W[1]) - tmp899.coeffs[2:order + 1] .= zero(tmp899.coeffs[1]) - hy.coeffs[1] = constant_term(tmp898) - constant_term(tmp899) - hy.coeffs[2:order + 1] .= zero(hy.coeffs[1]) - tmp901.coeffs[1] = constant_term(X[1]) * constant_term(V[1]) - tmp901.coeffs[2:order + 1] .= zero(tmp901.coeffs[1]) - tmp902.coeffs[1] = constant_term(Y[1]) * constant_term(U[1]) - tmp902.coeffs[2:order + 1] .= zero(tmp902.coeffs[1]) - hz.coeffs[1] = constant_term(tmp901) - constant_term(tmp902) - hz.coeffs[2:order + 1] .= zero(hz.coeffs[1]) - tmp904.coeffs[1] = constant_term(hz) * constant_term(Y[1]) - tmp904.coeffs[2:order + 1] .= zero(tmp904.coeffs[1]) - tmp905.coeffs[1] = constant_term(hy) * constant_term(Z[1]) - tmp905.coeffs[2:order + 1] .= zero(tmp905.coeffs[1]) - t_x.coeffs[1] = constant_term(tmp904) - constant_term(tmp905) - t_x.coeffs[2:order + 1] .= zero(t_x.coeffs[1]) - tmp907.coeffs[1] = constant_term(hx) * constant_term(Z[1]) - tmp907.coeffs[2:order + 1] .= zero(tmp907.coeffs[1]) - tmp908.coeffs[1] = constant_term(hz) * constant_term(X[1]) - tmp908.coeffs[2:order + 1] .= zero(tmp908.coeffs[1]) - t_y.coeffs[1] = constant_term(tmp907) - constant_term(tmp908) - t_y.coeffs[2:order + 1] .= zero(t_y.coeffs[1]) - tmp910.coeffs[1] = constant_term(hy) * constant_term(X[1]) - tmp910.coeffs[2:order + 1] .= zero(tmp910.coeffs[1]) - tmp911.coeffs[1] = constant_term(hx) * constant_term(Y[1]) - tmp911.coeffs[2:order + 1] .= zero(tmp911.coeffs[1]) - t_z.coeffs[1] = constant_term(tmp910) - constant_term(tmp911) - t_z.coeffs[2:order + 1] .= zero(t_z.coeffs[1]) - tmp914.coeffs[1] = constant_term(t_x) ^ float(constant_term(2)) - tmp914.coeffs[2:order + 1] .= zero(tmp914.coeffs[1]) - tmp916.coeffs[1] = constant_term(t_y) ^ float(constant_term(2)) - tmp916.coeffs[2:order + 1] .= zero(tmp916.coeffs[1]) - tmp917.coeffs[1] = constant_term(tmp914) + constant_term(tmp916) - tmp917.coeffs[2:order + 1] .= zero(tmp917.coeffs[1]) - tmp919.coeffs[1] = constant_term(t_z) ^ float(constant_term(2)) - tmp919.coeffs[2:order + 1] .= zero(tmp919.coeffs[1]) - tmp920.coeffs[1] = constant_term(tmp917) + constant_term(tmp919) - tmp920.coeffs[2:order + 1] .= zero(tmp920.coeffs[1]) - t_norm.coeffs[1] = sqrt(constant_term(tmp920)) - t_norm.coeffs[2:order + 1] .= zero(t_norm.coeffs[1]) + TaylorSeries.zero!(tmp5761) + tmp5761.coeffs[1] = constant_term(Y[1]) * constant_term(W[1]) + TaylorSeries.zero!(tmp5762) + tmp5762.coeffs[1] = constant_term(Z[1]) * constant_term(V[1]) + TaylorSeries.zero!(hx) + hx.coeffs[1] = constant_term(tmp5761) - constant_term(tmp5762) + TaylorSeries.zero!(tmp5764) + tmp5764.coeffs[1] = constant_term(Z[1]) * constant_term(U[1]) + TaylorSeries.zero!(tmp5765) + tmp5765.coeffs[1] = constant_term(X[1]) * constant_term(W[1]) + TaylorSeries.zero!(hy) + hy.coeffs[1] = constant_term(tmp5764) - constant_term(tmp5765) + TaylorSeries.zero!(tmp5767) + tmp5767.coeffs[1] = constant_term(X[1]) * constant_term(V[1]) + TaylorSeries.zero!(tmp5768) + tmp5768.coeffs[1] = constant_term(Y[1]) * constant_term(U[1]) + TaylorSeries.zero!(hz) + hz.coeffs[1] = constant_term(tmp5767) - constant_term(tmp5768) + TaylorSeries.zero!(tmp5770) + tmp5770.coeffs[1] = constant_term(hz) * constant_term(Y[1]) + TaylorSeries.zero!(tmp5771) + tmp5771.coeffs[1] = constant_term(hy) * constant_term(Z[1]) + TaylorSeries.zero!(t_x) + t_x.coeffs[1] = constant_term(tmp5770) - constant_term(tmp5771) + TaylorSeries.zero!(tmp5773) + tmp5773.coeffs[1] = constant_term(hx) * constant_term(Z[1]) + TaylorSeries.zero!(tmp5774) + tmp5774.coeffs[1] = constant_term(hz) * constant_term(X[1]) + TaylorSeries.zero!(t_y) + t_y.coeffs[1] = constant_term(tmp5773) - constant_term(tmp5774) + TaylorSeries.zero!(tmp5776) + tmp5776.coeffs[1] = constant_term(hy) * constant_term(X[1]) + TaylorSeries.zero!(tmp5777) + tmp5777.coeffs[1] = constant_term(hx) * constant_term(Y[1]) + TaylorSeries.zero!(t_z) + t_z.coeffs[1] = constant_term(tmp5776) - constant_term(tmp5777) + TaylorSeries.zero!(tmp5780) + tmp5780.coeffs[1] = constant_term(t_x) ^ float(constant_term(2)) + TaylorSeries.zero!(tmp5782) + tmp5782.coeffs[1] = constant_term(t_y) ^ float(constant_term(2)) + TaylorSeries.zero!(tmp5783) + tmp5783.coeffs[1] = constant_term(tmp5780) + constant_term(tmp5782) + TaylorSeries.zero!(tmp5785) + tmp5785.coeffs[1] = constant_term(t_z) ^ float(constant_term(2)) + TaylorSeries.zero!(tmp5786) + tmp5786.coeffs[1] = constant_term(tmp5783) + constant_term(tmp5785) + TaylorSeries.zero!(t_norm) + t_norm.coeffs[1] = sqrt(constant_term(tmp5786)) + TaylorSeries.zero!(t_x_unit) t_x_unit.coeffs[1] = constant_term(t_x) / constant_term(t_norm) - t_x_unit.coeffs[2:order + 1] .= zero(t_x_unit.coeffs[1]) + TaylorSeries.zero!(t_y_unit) t_y_unit.coeffs[1] = constant_term(t_y) / constant_term(t_norm) - t_y_unit.coeffs[2:order + 1] .= zero(t_y_unit.coeffs[1]) + TaylorSeries.zero!(t_z_unit) t_z_unit.coeffs[1] = constant_term(t_z) / constant_term(t_norm) - t_z_unit.coeffs[2:order + 1] .= zero(t_z_unit.coeffs[1]) - tmp925.coeffs[1] = constant_term(X[1]) / constant_term(r_p1d2[1]) - tmp925.coeffs[2:order + 1] .= zero(tmp925.coeffs[1]) - r_x_unit.coeffs[1] = -(constant_term(tmp925)) - r_x_unit.coeffs[2:order + 1] .= zero(r_x_unit.coeffs[1]) - tmp927.coeffs[1] = constant_term(Y[1]) / constant_term(r_p1d2[1]) - tmp927.coeffs[2:order + 1] .= zero(tmp927.coeffs[1]) - r_y_unit.coeffs[1] = -(constant_term(tmp927)) - r_y_unit.coeffs[2:order + 1] .= zero(r_y_unit.coeffs[1]) - tmp929.coeffs[1] = constant_term(Z[1]) / constant_term(r_p1d2[1]) - tmp929.coeffs[2:order + 1] .= zero(tmp929.coeffs[1]) - r_z_unit.coeffs[1] = -(constant_term(tmp929)) - r_z_unit.coeffs[2:order + 1] .= zero(r_z_unit.coeffs[1]) + TaylorSeries.zero!(tmp5791) + tmp5791.coeffs[1] = constant_term(X[1]) / constant_term(r_p1d2[1]) + TaylorSeries.zero!(r_x_unit) + r_x_unit.coeffs[1] = -(constant_term(tmp5791)) + TaylorSeries.zero!(tmp5793) + tmp5793.coeffs[1] = constant_term(Y[1]) / constant_term(r_p1d2[1]) + TaylorSeries.zero!(r_y_unit) + r_y_unit.coeffs[1] = -(constant_term(tmp5793)) + TaylorSeries.zero!(tmp5795) + tmp5795.coeffs[1] = constant_term(Z[1]) / constant_term(r_p1d2[1]) + TaylorSeries.zero!(r_z_unit) + r_z_unit.coeffs[1] = -(constant_term(tmp5795)) + TaylorSeries.zero!(g_r) g_r.coeffs[1] = identity(constant_term(r_p2[1])) - g_r.coeffs[2:order + 1] .= zero(g_r.coeffs[1]) + TaylorSeries.zero!(A2_t_g_r) A2_t_g_r.coeffs[1] = constant_term(q[7]) / constant_term(g_r) - A2_t_g_r.coeffs[2:order + 1] .= zero(A2_t_g_r.coeffs[1]) + TaylorSeries.zero!(A1_t_g_r) A1_t_g_r.coeffs[1] = constant_term(q[8]) / constant_term(g_r) - A1_t_g_r.coeffs[2:order + 1] .= zero(A1_t_g_r.coeffs[1]) - tmp933.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_x_unit) - tmp933.coeffs[2:order + 1] .= zero(tmp933.coeffs[1]) - tmp934.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_x_unit) - tmp934.coeffs[2:order + 1] .= zero(tmp934.coeffs[1]) - NGAx.coeffs[1] = constant_term(tmp933) + constant_term(tmp934) - NGAx.coeffs[2:order + 1] .= zero(NGAx.coeffs[1]) - tmp936.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_y_unit) - tmp936.coeffs[2:order + 1] .= zero(tmp936.coeffs[1]) - tmp937.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_y_unit) - tmp937.coeffs[2:order + 1] .= zero(tmp937.coeffs[1]) - NGAy.coeffs[1] = constant_term(tmp936) + constant_term(tmp937) - NGAy.coeffs[2:order + 1] .= zero(NGAy.coeffs[1]) - tmp939.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_z_unit) - tmp939.coeffs[2:order + 1] .= zero(tmp939.coeffs[1]) - tmp940.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_z_unit) - tmp940.coeffs[2:order + 1] .= zero(tmp940.coeffs[1]) - NGAz.coeffs[1] = constant_term(tmp939) + constant_term(tmp940) - NGAz.coeffs[2:order + 1] .= zero(NGAz.coeffs[1]) - tmp942.coeffs[1] = constant_term(postNewtonX) + constant_term(accX) - tmp942.coeffs[2:order + 1] .= zero(tmp942.coeffs[1]) - (dq[4]).coeffs[1] = constant_term(tmp942) + constant_term(NGAx) - (dq[4]).coeffs[2:order + 1] .= zero((dq[4]).coeffs[1]) - tmp944.coeffs[1] = constant_term(postNewtonY) + constant_term(accY) - tmp944.coeffs[2:order + 1] .= zero(tmp944.coeffs[1]) - (dq[5]).coeffs[1] = constant_term(tmp944) + constant_term(NGAy) - (dq[5]).coeffs[2:order + 1] .= zero((dq[5]).coeffs[1]) - tmp946.coeffs[1] = constant_term(postNewtonZ) + constant_term(accZ) - tmp946.coeffs[2:order + 1] .= zero(tmp946.coeffs[1]) - (dq[6]).coeffs[1] = constant_term(tmp946) + constant_term(NGAz) - (dq[6]).coeffs[2:order + 1] .= zero((dq[6]).coeffs[1]) + TaylorSeries.zero!(tmp5799) + tmp5799.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_x_unit) + TaylorSeries.zero!(tmp5800) + tmp5800.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_x_unit) + TaylorSeries.zero!(NGAx) + NGAx.coeffs[1] = constant_term(tmp5799) + constant_term(tmp5800) + TaylorSeries.zero!(tmp5802) + tmp5802.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_y_unit) + TaylorSeries.zero!(tmp5803) + tmp5803.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_y_unit) + TaylorSeries.zero!(NGAy) + NGAy.coeffs[1] = constant_term(tmp5802) + constant_term(tmp5803) + TaylorSeries.zero!(tmp5805) + tmp5805.coeffs[1] = constant_term(A2_t_g_r) * constant_term(t_z_unit) + TaylorSeries.zero!(tmp5806) + tmp5806.coeffs[1] = constant_term(A1_t_g_r) * constant_term(r_z_unit) + TaylorSeries.zero!(NGAz) + NGAz.coeffs[1] = constant_term(tmp5805) + constant_term(tmp5806) + TaylorSeries.zero!(tmp5808) + tmp5808.coeffs[1] = constant_term(postNewtonX) + constant_term(accX) + TaylorSeries.zero!(dq[4]) + (dq[4]).coeffs[1] = constant_term(tmp5808) + constant_term(NGAx) + TaylorSeries.zero!(tmp5810) + tmp5810.coeffs[1] = constant_term(postNewtonY) + constant_term(accY) + TaylorSeries.zero!(dq[5]) + (dq[5]).coeffs[1] = constant_term(tmp5810) + constant_term(NGAy) + TaylorSeries.zero!(tmp5812) + tmp5812.coeffs[1] = constant_term(postNewtonZ) + constant_term(accZ) + TaylorSeries.zero!(dq[6]) + (dq[6]).coeffs[1] = constant_term(tmp5812) + constant_term(NGAz) + TaylorSeries.zero!(dq[7]) (dq[7]).coeffs[1] = identity(constant_term(zero_q_1)) - (dq[7]).coeffs[2:order + 1] .= zero((dq[7]).coeffs[1]) + TaylorSeries.zero!(dq[8]) + (dq[8]).coeffs[1] = identity(constant_term(zero_q_1)) for __idx = eachindex(q) (q[__idx]).coeffs[2] = (dq[__idx]).coeffs[1] end @@ -1352,7 +1479,10 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! TaylorSeries.identity!(dq[2], q[5], ord) TaylorSeries.identity!(dq[3], q[6], ord) TaylorSeries.identity!(newtonianNb_Potential[N], zero_q_1, ord) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 + TaylorSeries.mul!(_4dq[1], 4, dq[1], ord) + TaylorSeries.mul!(_4dq[2], 4, dq[2], ord) + TaylorSeries.mul!(_4dq[3], 4, dq[3], ord) + #= /Users/Jorge/projects/neos240702/neosjetcoeffs.jl:253 =# Threads.@threads for i = 1:Nm1 TaylorSeries.identity!(ui[i], ss16asteph_t[3 * ((N - 1) + i) - 2], ord) TaylorSeries.identity!(vi[i], ss16asteph_t[3 * ((N - 1) + i) - 1], ord) TaylorSeries.identity!(wi[i], ss16asteph_t[3 * ((N - 1) + i)], ord) @@ -1362,35 +1492,32 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! TaylorSeries.subst!(U[i], ui[i], dq[1], ord) TaylorSeries.subst!(V[i], vi[i], dq[2], ord) TaylorSeries.subst!(W[i], wi[i], dq[3], ord) - TaylorSeries.mul!(tmp687[1], 4, dq[1], ord) - TaylorSeries.mul!(tmp689[i], 3, ui[i], ord) - TaylorSeries.subst!(_4U_m_3X[i], tmp687[1], tmp689[i], ord) - TaylorSeries.mul!(tmp692[2], 4, dq[2], ord) - TaylorSeries.mul!(tmp694[i], 3, vi[i], ord) - TaylorSeries.subst!(_4V_m_3Y[i], tmp692[2], tmp694[i], ord) - TaylorSeries.mul!(tmp697[3], 4, dq[3], ord) - TaylorSeries.mul!(tmp699[i], 3, wi[i], ord) - TaylorSeries.subst!(_4W_m_3Z[i], tmp697[3], tmp699[i], ord) + TaylorSeries.mul!(tmp5559[i], -3, ui[i], ord) + TaylorSeries.add!(_4U_m_3X[i], tmp5559[i], _4dq[1], ord) + TaylorSeries.mul!(tmp5562[i], -3, vi[i], ord) + TaylorSeries.add!(_4V_m_3Y[i], tmp5562[i], _4dq[2], ord) + TaylorSeries.mul!(tmp5565[i], -3, wi[i], ord) + TaylorSeries.add!(_4W_m_3Z[i], tmp5565[i], _4dq[3], ord) TaylorSeries.mul!(pn2x[i], X[i], _4U_m_3X[i], ord) TaylorSeries.mul!(pn2y[i], Y[i], _4V_m_3Y[i], ord) TaylorSeries.mul!(pn2z[i], Z[i], _4W_m_3Z[i], ord) TaylorSeries.mul!(UU[i], ui[i], dq[1], ord) TaylorSeries.mul!(VV[i], vi[i], dq[2], ord) TaylorSeries.mul!(WW[i], wi[i], dq[3], ord) - TaylorSeries.add!(tmp707[i], UU[i], VV[i], ord) - TaylorSeries.add!(vi_dot_vj[i], tmp707[i], WW[i], ord) - TaylorSeries.pow!(tmp710[i], X[i], 2, ord) - TaylorSeries.pow!(tmp712[i], Y[i], 2, ord) - TaylorSeries.add!(tmp713[i], tmp710[i], tmp712[i], ord) - TaylorSeries.pow!(tmp715[i], Z[i], 2, ord) - TaylorSeries.add!(r_p2[i], tmp713[i], tmp715[i], ord) + TaylorSeries.add!(tmp5573[i], UU[i], VV[i], ord) + TaylorSeries.add!(vi_dot_vj[i], tmp5573[i], WW[i], ord) + TaylorSeries.pow!(tmp5576[i], X[i], 2, ord) + TaylorSeries.pow!(tmp5578[i], Y[i], 2, ord) + TaylorSeries.add!(tmp5579[i], tmp5576[i], tmp5578[i], ord) + TaylorSeries.pow!(tmp5581[i], Z[i], 2, ord) + TaylorSeries.add!(r_p2[i], tmp5579[i], tmp5581[i], ord) TaylorSeries.sqrt!(r_p1d2[i], r_p2[i], ord) TaylorSeries.pow!(r_p3d2[i], r_p2[i], 1.5, ord) TaylorSeries.pow!(r_p7d2[i], r_p2[i], 3.5, ord) TaylorSeries.div!(newtonianCoeff[i], μ[i], r_p3d2[i], ord) - TaylorSeries.add!(tmp723[i], pn2x[i], pn2y[i], ord) - TaylorSeries.add!(tmp724[i], tmp723[i], pn2z[i], ord) - TaylorSeries.mul!(pn2[i], newtonianCoeff[i], tmp724[i], ord) + TaylorSeries.add!(tmp5589[i], pn2x[i], pn2y[i], ord) + TaylorSeries.add!(tmp5590[i], tmp5589[i], pn2z[i], ord) + TaylorSeries.mul!(pn2[i], newtonianCoeff[i], tmp5590[i], ord) TaylorSeries.mul!(newton_acc_X[i], X[i], newtonianCoeff[i], ord) TaylorSeries.mul!(newton_acc_Y[i], Y[i], newtonianCoeff[i], ord) TaylorSeries.mul!(newton_acc_Z[i], Z[i], newtonianCoeff[i], ord) @@ -1400,51 +1527,51 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! TaylorSeries.mul!(V_t_pn2[i], pn2[i], V[i], ord) TaylorSeries.mul!(W_t_pn2[i], pn2[i], W[i], ord) if UJ_interaction[i] - TaylorSeries.subst!(tmp735[i], X[i], ord) - TaylorSeries.mul!(t31[i], tmp735[i], M_[1, 3, i], ord) - TaylorSeries.subst!(tmp737[i], Y[i], ord) - TaylorSeries.mul!(t32[i], tmp737[i], M_[2, 3, i], ord) - TaylorSeries.subst!(tmp739[i], Z[i], ord) - TaylorSeries.mul!(t33[i], tmp739[i], M_[3, 3, i], ord) - TaylorSeries.add!(tmp741[i], t31[i], t32[i], ord) - TaylorSeries.add!(r_sin_ϕ[i], tmp741[i], t33[i], ord) + TaylorSeries.subst!(tmp5601[i], X[i], ord) + TaylorSeries.mul!(t31[i], tmp5601[i], M_[1, 3, i], ord) + TaylorSeries.subst!(tmp5603[i], Y[i], ord) + TaylorSeries.mul!(t32[i], tmp5603[i], M_[2, 3, i], ord) + TaylorSeries.subst!(tmp5605[i], Z[i], ord) + TaylorSeries.mul!(t33[i], tmp5605[i], M_[3, 3, i], ord) + TaylorSeries.add!(tmp5607[i], t31[i], t32[i], ord) + TaylorSeries.add!(r_sin_ϕ[i], tmp5607[i], t33[i], ord) TaylorSeries.div!(sin_ϕ[i], r_sin_ϕ[i], r_p1d2[i], ord) - TaylorSeries.asin!(ϕ[i], sin_ϕ[i], tmp948[i], ord) - TaylorSeries.sincos!(tmp949[i], cos_ϕ[i], ϕ[i], ord) + TaylorSeries.asin!(ϕ[i], sin_ϕ[i], tmp5814[i], ord) + TaylorSeries.sincos!(tmp5815[i], cos_ϕ[i], ϕ[i], ord) TaylorSeries.pow!(sin2_ϕ[i], sin_ϕ[i], 2, ord) TaylorSeries.pow!(sin3_ϕ[i], sin_ϕ[i], 3, ord) - TaylorSeries.mul!(tmp751[i], 1.5, sin2_ϕ[i], ord) - TaylorSeries.subst!(P_2_sin_ϕ[i], tmp751[i], 0.5, ord) + TaylorSeries.mul!(tmp5617[i], 1.5, sin2_ϕ[i], ord) + TaylorSeries.subst!(P_2_sin_ϕ[i], tmp5617[i], 0.5, ord) TaylorSeries.mul!(∂P_2_sin_ϕ[i], 3, sin_ϕ[i], ord) - TaylorSeries.mul!(tmp757[i], -1.5, sin_ϕ[i], ord) - TaylorSeries.mul!(tmp759[i], 2.5, sin3_ϕ[i], ord) - TaylorSeries.add!(P_3_sin_ϕ[i], tmp757[i], tmp759[i], ord) - TaylorSeries.mul!(tmp763[i], 7.5, sin2_ϕ[i], ord) - TaylorSeries.add!(∂P_3_sin_ϕ[i], -1.5, tmp763[i], ord) - TaylorSeries.pow!(tmp766[i], r_p2[i], 2, ord) - TaylorSeries.div!(tmp767[i], Λ2[i], tmp766[i], ord) - TaylorSeries.subst!(Λ2j_div_r4[i], tmp767[i], ord) - TaylorSeries.pow!(tmp770[i], r_p1d2[i], 5, ord) - TaylorSeries.div!(tmp771[i], Λ3[i], tmp770[i], ord) - TaylorSeries.subst!(Λ3j_div_r5[i], tmp771[i], ord) - TaylorSeries.subst!(tmp773[i], cos_ϕ[i], ord) - TaylorSeries.mul!(m_c_ϕ_∂P_2[i], tmp773[i], ∂P_2_sin_ϕ[i], ord) - TaylorSeries.subst!(tmp775[i], cos_ϕ[i], ord) - TaylorSeries.mul!(m_c_ϕ_∂P_3[i], tmp775[i], ∂P_3_sin_ϕ[i], ord) - TaylorSeries.mul!(tmp778[i], Λ2j_div_r4[i], 3, ord) - TaylorSeries.mul!(F_J2_ξ[i], tmp778[i], P_2_sin_ϕ[i], ord) + TaylorSeries.mul!(tmp5623[i], -1.5, sin_ϕ[i], ord) + TaylorSeries.mul!(tmp5625[i], 2.5, sin3_ϕ[i], ord) + TaylorSeries.add!(P_3_sin_ϕ[i], tmp5623[i], tmp5625[i], ord) + TaylorSeries.mul!(tmp5629[i], 7.5, sin2_ϕ[i], ord) + TaylorSeries.add!(∂P_3_sin_ϕ[i], -1.5, tmp5629[i], ord) + TaylorSeries.pow!(tmp5632[i], r_p2[i], 2, ord) + TaylorSeries.div!(tmp5633[i], Λ2[i], tmp5632[i], ord) + TaylorSeries.subst!(Λ2j_div_r4[i], tmp5633[i], ord) + TaylorSeries.pow!(tmp5636[i], r_p1d2[i], 5, ord) + TaylorSeries.div!(tmp5637[i], Λ3[i], tmp5636[i], ord) + TaylorSeries.subst!(Λ3j_div_r5[i], tmp5637[i], ord) + TaylorSeries.subst!(tmp5639[i], cos_ϕ[i], ord) + TaylorSeries.mul!(m_c_ϕ_∂P_2[i], tmp5639[i], ∂P_2_sin_ϕ[i], ord) + TaylorSeries.subst!(tmp5641[i], cos_ϕ[i], ord) + TaylorSeries.mul!(m_c_ϕ_∂P_3[i], tmp5641[i], ∂P_3_sin_ϕ[i], ord) + TaylorSeries.mul!(tmp5644[i], Λ2j_div_r4[i], 3, ord) + TaylorSeries.mul!(F_J2_ξ[i], tmp5644[i], P_2_sin_ϕ[i], ord) TaylorSeries.mul!(F_J2_ζ[i], Λ2j_div_r4[i], m_c_ϕ_∂P_2[i], ord) - TaylorSeries.mul!(tmp782[i], Λ3j_div_r5[i], 4, ord) - TaylorSeries.mul!(F_J3_ξ[i], tmp782[i], P_3_sin_ϕ[i], ord) + TaylorSeries.mul!(tmp5648[i], Λ3j_div_r5[i], 4, ord) + TaylorSeries.mul!(F_J3_ξ[i], tmp5648[i], P_3_sin_ϕ[i], ord) TaylorSeries.mul!(F_J3_ζ[i], Λ3j_div_r5[i], m_c_ϕ_∂P_3[i], ord) TaylorSeries.identity!(F_J_ξ[i], F_J2_ξ[i], ord) TaylorSeries.identity!(F_J_ζ[i], F_J2_ζ[i], ord) - TaylorSeries.subst!(tmp785[i], X[i], ord) - TaylorSeries.div!(ξx[i], tmp785[i], r_p1d2[i], ord) - TaylorSeries.subst!(tmp787[i], Y[i], ord) - TaylorSeries.div!(ξy[i], tmp787[i], r_p1d2[i], ord) - TaylorSeries.subst!(tmp789[i], Z[i], ord) - TaylorSeries.div!(ξz[i], tmp789[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp5651[i], X[i], ord) + TaylorSeries.div!(ξx[i], tmp5651[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp5653[i], Y[i], ord) + TaylorSeries.div!(ξy[i], tmp5653[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp5655[i], Z[i], ord) + TaylorSeries.div!(ξz[i], tmp5655[i], r_p1d2[i], ord) TaylorSeries.mul!(ηx1[i], M_[2, 3, i], ξz[i], ord) TaylorSeries.mul!(ηy1[i], M_[3, 3, i], ξx[i], ord) TaylorSeries.mul!(ηz1[i], M_[1, 3, i], ξy[i], ord) @@ -1473,57 +1600,57 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! TaylorSeries.add!(F_J2_y[i], F_J2_y1[i], F_J2_y2[i], ord) TaylorSeries.add!(F_J2_z[i], F_J2_z1[i], F_J2_z2[i], ord) end - TaylorSeries.pow!(tmp819[i], ui[i], 2, ord) - TaylorSeries.pow!(tmp821[i], vi[i], 2, ord) - TaylorSeries.add!(tmp822[i], tmp819[i], tmp821[i], ord) - TaylorSeries.pow!(tmp824[i], wi[i], 2, ord) - TaylorSeries.add!(v2[i], tmp822[i], tmp824[i], ord) + TaylorSeries.pow!(tmp5685[i], ui[i], 2, ord) + TaylorSeries.pow!(tmp5687[i], vi[i], 2, ord) + TaylorSeries.add!(tmp5688[i], tmp5685[i], tmp5687[i], ord) + TaylorSeries.pow!(tmp5690[i], wi[i], 2, ord) + TaylorSeries.add!(v2[i], tmp5688[i], tmp5690[i], ord) end - TaylorSeries.pow!(tmp827, q[4], 2, ord) - TaylorSeries.pow!(tmp829, q[5], 2, ord) - TaylorSeries.add!(tmp830, tmp827, tmp829, ord) - TaylorSeries.pow!(tmp832, q[6], 2, ord) - TaylorSeries.add!(v2[N], tmp830, tmp832, ord) + TaylorSeries.pow!(tmp5693, q[4], 2, ord) + TaylorSeries.pow!(tmp5695, q[5], 2, ord) + TaylorSeries.add!(tmp5696, tmp5693, tmp5695, ord) + TaylorSeries.pow!(tmp5698, q[6], 2, ord) + TaylorSeries.add!(v2[N], tmp5696, tmp5698, ord) for i = 1:Nm1 TaylorSeries.add!(temp_004[i], newtonian1b_Potential[i], newtonianNb_Potential[N], ord) TaylorSeries.identity!(newtonianNb_Potential[N], temp_004[i], ord) if UJ_interaction[i] - TaylorSeries.mul!(tmp835[i], μ[i], F_J2_x[i], ord) - TaylorSeries.subst!(temp_accX_i[i], accX, tmp835[i], ord) + TaylorSeries.mul!(tmp5701[i], μ[i], F_J2_x[i], ord) + TaylorSeries.subst!(temp_accX_i[i], accX, tmp5701[i], ord) TaylorSeries.identity!(accX, temp_accX_i[i], ord) - TaylorSeries.mul!(tmp837[i], μ[i], F_J2_y[i], ord) - TaylorSeries.subst!(temp_accY_i[i], accY, tmp837[i], ord) + TaylorSeries.mul!(tmp5703[i], μ[i], F_J2_y[i], ord) + TaylorSeries.subst!(temp_accY_i[i], accY, tmp5703[i], ord) TaylorSeries.identity!(accY, temp_accY_i[i], ord) - TaylorSeries.mul!(tmp839[i], μ[i], F_J2_z[i], ord) - TaylorSeries.subst!(temp_accZ_i[i], accZ, tmp839[i], ord) + TaylorSeries.mul!(tmp5705[i], μ[i], F_J2_z[i], ord) + TaylorSeries.subst!(temp_accZ_i[i], accZ, tmp5705[i], ord) TaylorSeries.identity!(accZ, temp_accZ_i[i], ord) end end TaylorSeries.mul!(_4ϕj[N], 4, newtonianNb_Potential[N], ord) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 + #= /Users/Jorge/projects/neos240702/neosjetcoeffs.jl:455 =# Threads.@threads for i = 1:10 TaylorSeries.add!(ϕi_plus_4ϕj[i], newtonianNb_Potential_t[i], _4ϕj[N], ord) - TaylorSeries.mul!(tmp845[i], 2, v2[i], ord) - TaylorSeries.mul!(tmp847[i], 4, vi_dot_vj[i], ord) - TaylorSeries.subst!(tmp848[i], tmp845[i], tmp847[i], ord) - TaylorSeries.add!(sj2_plus_2si2_minus_4vivj[i], tmp848[i], v2[N], ord) + TaylorSeries.mul!(tmp5711[i], 2, v2[i], ord) + TaylorSeries.mul!(tmp5713[i], 4, vi_dot_vj[i], ord) + TaylorSeries.subst!(tmp5714[i], tmp5711[i], tmp5713[i], ord) + TaylorSeries.add!(sj2_plus_2si2_minus_4vivj[i], tmp5714[i], v2[N], ord) TaylorSeries.subst!(ϕs_and_vs[i], sj2_plus_2si2_minus_4vivj[i], ϕi_plus_4ϕj[i], ord) TaylorSeries.mul!(Xij_t_Ui[i], X[i], ui[i], ord) TaylorSeries.mul!(Yij_t_Vi[i], Y[i], vi[i], ord) TaylorSeries.mul!(Zij_t_Wi[i], Z[i], wi[i], ord) - TaylorSeries.add!(tmp854[i], Xij_t_Ui[i], Yij_t_Vi[i], ord) - TaylorSeries.add!(Rij_dot_Vi[i], tmp854[i], Zij_t_Wi[i], ord) - TaylorSeries.pow!(tmp857[i], Rij_dot_Vi[i], 2, ord) - TaylorSeries.div!(pn1t7[i], tmp857[i], r_p2[i], ord) - TaylorSeries.mul!(tmp860[i], 1.5, pn1t7[i], ord) - TaylorSeries.subst!(pn1t2_7[i], ϕs_and_vs[i], tmp860[i], ord) + TaylorSeries.add!(tmp5720[i], Xij_t_Ui[i], Yij_t_Vi[i], ord) + TaylorSeries.add!(Rij_dot_Vi[i], tmp5720[i], Zij_t_Wi[i], ord) + TaylorSeries.pow!(tmp5723[i], Rij_dot_Vi[i], 2, ord) + TaylorSeries.div!(pn1t7[i], tmp5723[i], r_p2[i], ord) + TaylorSeries.mul!(tmp5726[i], 1.5, pn1t7[i], ord) + TaylorSeries.subst!(pn1t2_7[i], ϕs_and_vs[i], tmp5726[i], ord) TaylorSeries.add!(pn1t1_7[i], c_p2, pn1t2_7[i], ord) TaylorSeries.mul!(pNX_t_X[i], acceph_t[3i - 2], X[i], ord) TaylorSeries.mul!(pNY_t_Y[i], acceph_t[3i - 1], Y[i], ord) TaylorSeries.mul!(pNZ_t_Z[i], acceph_t[3i], Z[i], ord) - TaylorSeries.add!(tmp867[i], pNX_t_X[i], pNY_t_Y[i], ord) - TaylorSeries.add!(tmp868[i], tmp867[i], pNZ_t_Z[i], ord) - TaylorSeries.mul!(tmp869[i], 0.5, tmp868[i], ord) - TaylorSeries.add!(pn1[i], pn1t1_7[i], tmp869[i], ord) + TaylorSeries.add!(tmp5733[i], pNX_t_X[i], pNY_t_Y[i], ord) + TaylorSeries.add!(tmp5734[i], tmp5733[i], pNZ_t_Z[i], ord) + TaylorSeries.mul!(tmp5735[i], 0.5, tmp5734[i], ord) + TaylorSeries.add!(pn1[i], pn1t1_7[i], tmp5735[i], ord) TaylorSeries.mul!(X_t_pn1[i], newton_acc_X[i], pn1[i], ord) TaylorSeries.mul!(Y_t_pn1[i], newton_acc_Y[i], pn1[i], ord) TaylorSeries.mul!(Z_t_pn1[i], newton_acc_Z[i], pn1[i], ord) @@ -1532,20 +1659,20 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! TaylorSeries.mul!(pNZ_t_pn3[i], acceph_t[3i], pn3[i], ord) end for i = 1:10 - TaylorSeries.add!(tmp877[i], U_t_pn2[i], pNX_t_pn3[i], ord) - TaylorSeries.add!(termpnx[i], X_t_pn1[i], tmp877[i], ord) + TaylorSeries.add!(tmp5743[i], U_t_pn2[i], pNX_t_pn3[i], ord) + TaylorSeries.add!(termpnx[i], X_t_pn1[i], tmp5743[i], ord) TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) TaylorSeries.identity!(pntempX, sumpnx[i], ord) - TaylorSeries.add!(tmp880[i], V_t_pn2[i], pNY_t_pn3[i], ord) - TaylorSeries.add!(termpny[i], Y_t_pn1[i], tmp880[i], ord) + TaylorSeries.add!(tmp5746[i], V_t_pn2[i], pNY_t_pn3[i], ord) + TaylorSeries.add!(termpny[i], Y_t_pn1[i], tmp5746[i], ord) TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) TaylorSeries.identity!(pntempY, sumpny[i], ord) - TaylorSeries.add!(tmp883[i], W_t_pn2[i], pNZ_t_pn3[i], ord) - TaylorSeries.add!(termpnz[i], Z_t_pn1[i], tmp883[i], ord) + TaylorSeries.add!(tmp5749[i], W_t_pn2[i], pNZ_t_pn3[i], ord) + TaylorSeries.add!(termpnz[i], Z_t_pn1[i], tmp5749[i], ord) TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) TaylorSeries.identity!(pntempZ, sumpnz[i], ord) end - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 + #= /Users/Jorge/projects/neos240702/neosjetcoeffs.jl:508 =# Threads.@threads for i = 11:Nm1 TaylorSeries.mul!(X_t_pn1[i], c_p2, newton_acc_X[i], ord) TaylorSeries.mul!(Y_t_pn1[i], c_p2, newton_acc_Y[i], ord) TaylorSeries.mul!(Z_t_pn1[i], c_p2, newton_acc_Z[i], ord) @@ -1564,58 +1691,59 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads! TaylorSeries.mul!(postNewtonX, pntempX, c_m2, ord) TaylorSeries.mul!(postNewtonY, pntempY, c_m2, ord) TaylorSeries.mul!(postNewtonZ, pntempZ, c_m2, ord) - TaylorSeries.mul!(tmp895, Y[1], W[1], ord) - TaylorSeries.mul!(tmp896, Z[1], V[1], ord) - TaylorSeries.subst!(hx, tmp895, tmp896, ord) - TaylorSeries.mul!(tmp898, Z[1], U[1], ord) - TaylorSeries.mul!(tmp899, X[1], W[1], ord) - TaylorSeries.subst!(hy, tmp898, tmp899, ord) - TaylorSeries.mul!(tmp901, X[1], V[1], ord) - TaylorSeries.mul!(tmp902, Y[1], U[1], ord) - TaylorSeries.subst!(hz, tmp901, tmp902, ord) - TaylorSeries.mul!(tmp904, hz, Y[1], ord) - TaylorSeries.mul!(tmp905, hy, Z[1], ord) - TaylorSeries.subst!(t_x, tmp904, tmp905, ord) - TaylorSeries.mul!(tmp907, hx, Z[1], ord) - TaylorSeries.mul!(tmp908, hz, X[1], ord) - TaylorSeries.subst!(t_y, tmp907, tmp908, ord) - TaylorSeries.mul!(tmp910, hy, X[1], ord) - TaylorSeries.mul!(tmp911, hx, Y[1], ord) - TaylorSeries.subst!(t_z, tmp910, tmp911, ord) - TaylorSeries.pow!(tmp914, t_x, 2, ord) - TaylorSeries.pow!(tmp916, t_y, 2, ord) - TaylorSeries.add!(tmp917, tmp914, tmp916, ord) - TaylorSeries.pow!(tmp919, t_z, 2, ord) - TaylorSeries.add!(tmp920, tmp917, tmp919, ord) - TaylorSeries.sqrt!(t_norm, tmp920, ord) + TaylorSeries.mul!(tmp5761, Y[1], W[1], ord) + TaylorSeries.mul!(tmp5762, Z[1], V[1], ord) + TaylorSeries.subst!(hx, tmp5761, tmp5762, ord) + TaylorSeries.mul!(tmp5764, Z[1], U[1], ord) + TaylorSeries.mul!(tmp5765, X[1], W[1], ord) + TaylorSeries.subst!(hy, tmp5764, tmp5765, ord) + TaylorSeries.mul!(tmp5767, X[1], V[1], ord) + TaylorSeries.mul!(tmp5768, Y[1], U[1], ord) + TaylorSeries.subst!(hz, tmp5767, tmp5768, ord) + TaylorSeries.mul!(tmp5770, hz, Y[1], ord) + TaylorSeries.mul!(tmp5771, hy, Z[1], ord) + TaylorSeries.subst!(t_x, tmp5770, tmp5771, ord) + TaylorSeries.mul!(tmp5773, hx, Z[1], ord) + TaylorSeries.mul!(tmp5774, hz, X[1], ord) + TaylorSeries.subst!(t_y, tmp5773, tmp5774, ord) + TaylorSeries.mul!(tmp5776, hy, X[1], ord) + TaylorSeries.mul!(tmp5777, hx, Y[1], ord) + TaylorSeries.subst!(t_z, tmp5776, tmp5777, ord) + TaylorSeries.pow!(tmp5780, t_x, 2, ord) + TaylorSeries.pow!(tmp5782, t_y, 2, ord) + TaylorSeries.add!(tmp5783, tmp5780, tmp5782, ord) + TaylorSeries.pow!(tmp5785, t_z, 2, ord) + TaylorSeries.add!(tmp5786, tmp5783, tmp5785, ord) + TaylorSeries.sqrt!(t_norm, tmp5786, ord) TaylorSeries.div!(t_x_unit, t_x, t_norm, ord) TaylorSeries.div!(t_y_unit, t_y, t_norm, ord) TaylorSeries.div!(t_z_unit, t_z, t_norm, ord) - TaylorSeries.div!(tmp925, X[1], r_p1d2[1], ord) - TaylorSeries.subst!(r_x_unit, tmp925, ord) - TaylorSeries.div!(tmp927, Y[1], r_p1d2[1], ord) - TaylorSeries.subst!(r_y_unit, tmp927, ord) - TaylorSeries.div!(tmp929, Z[1], r_p1d2[1], ord) - TaylorSeries.subst!(r_z_unit, tmp929, ord) + TaylorSeries.div!(tmp5791, X[1], r_p1d2[1], ord) + TaylorSeries.subst!(r_x_unit, tmp5791, ord) + TaylorSeries.div!(tmp5793, Y[1], r_p1d2[1], ord) + TaylorSeries.subst!(r_y_unit, tmp5793, ord) + TaylorSeries.div!(tmp5795, Z[1], r_p1d2[1], ord) + TaylorSeries.subst!(r_z_unit, tmp5795, ord) TaylorSeries.identity!(g_r, r_p2[1], ord) TaylorSeries.div!(A2_t_g_r, q[7], g_r, ord) TaylorSeries.div!(A1_t_g_r, q[8], g_r, ord) - TaylorSeries.mul!(tmp933, A2_t_g_r, t_x_unit, ord) - TaylorSeries.mul!(tmp934, A1_t_g_r, r_x_unit, ord) - TaylorSeries.add!(NGAx, tmp933, tmp934, ord) - TaylorSeries.mul!(tmp936, A2_t_g_r, t_y_unit, ord) - TaylorSeries.mul!(tmp937, A1_t_g_r, r_y_unit, ord) - TaylorSeries.add!(NGAy, tmp936, tmp937, ord) - TaylorSeries.mul!(tmp939, A2_t_g_r, t_z_unit, ord) - TaylorSeries.mul!(tmp940, A1_t_g_r, r_z_unit, ord) - TaylorSeries.add!(NGAz, tmp939, tmp940, ord) - TaylorSeries.add!(tmp942, postNewtonX, accX, ord) - TaylorSeries.add!(dq[4], tmp942, NGAx, ord) - TaylorSeries.add!(tmp944, postNewtonY, accY, ord) - TaylorSeries.add!(dq[5], tmp944, NGAy, ord) - TaylorSeries.add!(tmp946, postNewtonZ, accZ, ord) - TaylorSeries.add!(dq[6], tmp946, NGAz, ord) + TaylorSeries.mul!(tmp5799, A2_t_g_r, t_x_unit, ord) + TaylorSeries.mul!(tmp5800, A1_t_g_r, r_x_unit, ord) + TaylorSeries.add!(NGAx, tmp5799, tmp5800, ord) + TaylorSeries.mul!(tmp5802, A2_t_g_r, t_y_unit, ord) + TaylorSeries.mul!(tmp5803, A1_t_g_r, r_y_unit, ord) + TaylorSeries.add!(NGAy, tmp5802, tmp5803, ord) + TaylorSeries.mul!(tmp5805, A2_t_g_r, t_z_unit, ord) + TaylorSeries.mul!(tmp5806, A1_t_g_r, r_z_unit, ord) + TaylorSeries.add!(NGAz, tmp5805, tmp5806, ord) + TaylorSeries.add!(tmp5808, postNewtonX, accX, ord) + TaylorSeries.add!(dq[4], tmp5808, NGAx, ord) + TaylorSeries.add!(tmp5810, postNewtonY, accY, ord) + TaylorSeries.add!(dq[5], tmp5810, NGAy, ord) + TaylorSeries.add!(tmp5812, postNewtonZ, accZ, ord) + TaylorSeries.add!(dq[6], tmp5812, NGAz, ord) TaylorSeries.identity!(dq[7], zero_q_1, ord) + TaylorSeries.identity!(dq[8], zero_q_1, ord) for __idx = eachindex(q) (q[__idx]).coeffs[ordnext + 1] = (dq[__idx]).coeffs[ordnext] / ordnext end @@ -1651,6 +1779,7 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_t U = Array{S}(undef, N) V = Array{S}(undef, N) W = Array{S}(undef, N) + _4dq = Array{S}(undef, 3) _4U_m_3X = Array{S}(undef, N) _4V_m_3Y = Array{S}(undef, N) _4W_m_3Z = Array{S}(undef, N) @@ -1757,89 +1886,162 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_t dq[2] = Taylor1(identity(constant_term(q[5])), order) dq[3] = Taylor1(identity(constant_term(q[6])), order) newtonianNb_Potential[N] = Taylor1(identity(constant_term(zero_q_1)), order) - tmp1317 = Array{Taylor1{_S}}(undef, size(dq)) - tmp1317 .= Taylor1(zero(constant_term(q[1])), order) - tmp1319 = Array{Taylor1{_S}}(undef, size(ui)) - tmp1319 .= Taylor1(zero(constant_term(q[1])), order) - tmp1322 = Array{Taylor1{_S}}(undef, size(dq)) - tmp1322 .= Taylor1(zero(constant_term(q[1])), order) - tmp1324 = Array{Taylor1{_S}}(undef, size(vi)) - tmp1324 .= Taylor1(zero(constant_term(q[1])), order) - tmp1327 = Array{Taylor1{_S}}(undef, size(dq)) - tmp1327 .= Taylor1(zero(constant_term(q[1])), order) - tmp1329 = Array{Taylor1{_S}}(undef, size(wi)) - tmp1329 .= Taylor1(zero(constant_term(q[1])), order) + _4dq[1] = Taylor1(constant_term(4) * constant_term(dq[1]), order) + _4dq[2] = Taylor1(constant_term(4) * constant_term(dq[2]), order) + _4dq[3] = Taylor1(constant_term(4) * constant_term(dq[3]), order) + tmp6194 = Array{Taylor1{_S}}(undef, size(ui)) + for i = CartesianIndices(tmp6194) + tmp6194[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6197 = Array{Taylor1{_S}}(undef, size(vi)) + for i = CartesianIndices(tmp6197) + tmp6197[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6200 = Array{Taylor1{_S}}(undef, size(wi)) + for i = CartesianIndices(tmp6200) + tmp6200[i] = Taylor1(zero(constant_term(q[1])), order) + end pn2x = Array{Taylor1{_S}}(undef, size(X)) - pn2x .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(pn2x) + pn2x[i] = Taylor1(zero(constant_term(q[1])), order) + end pn2y = Array{Taylor1{_S}}(undef, size(Y)) - pn2y .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(pn2y) + pn2y[i] = Taylor1(zero(constant_term(q[1])), order) + end pn2z = Array{Taylor1{_S}}(undef, size(Z)) - pn2z .= Taylor1(zero(constant_term(q[1])), order) - tmp1337 = Array{Taylor1{_S}}(undef, size(UU)) - tmp1337 .= Taylor1(zero(constant_term(q[1])), order) - tmp1340 = Array{Taylor1{_S}}(undef, size(X)) - tmp1340 .= Taylor1(zero(constant_term(q[1])), order) - tmp1342 = Array{Taylor1{_S}}(undef, size(Y)) - tmp1342 .= Taylor1(zero(constant_term(q[1])), order) - tmp1343 = Array{Taylor1{_S}}(undef, size(tmp1340)) - tmp1343 .= Taylor1(zero(constant_term(q[1])), order) - tmp1345 = Array{Taylor1{_S}}(undef, size(Z)) - tmp1345 .= Taylor1(zero(constant_term(q[1])), order) - tmp1353 = Array{Taylor1{_S}}(undef, size(pn2x)) - tmp1353 .= Taylor1(zero(constant_term(q[1])), order) - tmp1354 = Array{Taylor1{_S}}(undef, size(tmp1353)) - tmp1354 .= Taylor1(zero(constant_term(q[1])), order) - tmp1449 = Array{Taylor1{_S}}(undef, size(ui)) - tmp1449 .= Taylor1(zero(constant_term(q[1])), order) - tmp1451 = Array{Taylor1{_S}}(undef, size(vi)) - tmp1451 .= Taylor1(zero(constant_term(q[1])), order) - tmp1452 = Array{Taylor1{_S}}(undef, size(tmp1449)) - tmp1452 .= Taylor1(zero(constant_term(q[1])), order) - tmp1454 = Array{Taylor1{_S}}(undef, size(wi)) - tmp1454 .= Taylor1(zero(constant_term(q[1])), order) - tmp1365 = Array{Taylor1{_S}}(undef, size(X)) - tmp1365 .= Taylor1(zero(constant_term(q[1])), order) - tmp1367 = Array{Taylor1{_S}}(undef, size(Y)) - tmp1367 .= Taylor1(zero(constant_term(q[1])), order) - tmp1369 = Array{Taylor1{_S}}(undef, size(Z)) - tmp1369 .= Taylor1(zero(constant_term(q[1])), order) - tmp1371 = Array{Taylor1{_S}}(undef, size(t31)) - tmp1371 .= Taylor1(zero(constant_term(q[1])), order) - tmp1528 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp1528 .= Taylor1(zero(constant_term(q[1])), order) - tmp1529 = Array{Taylor1{_S}}(undef, size(ϕ)) - tmp1529 .= Taylor1(zero(constant_term(q[1])), order) - tmp1381 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp1381 .= Taylor1(zero(constant_term(q[1])), order) - tmp1387 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) - tmp1387 .= Taylor1(zero(constant_term(q[1])), order) - tmp1389 = Array{Taylor1{_S}}(undef, size(sin3_ϕ)) - tmp1389 .= Taylor1(zero(constant_term(q[1])), order) - tmp1393 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) - tmp1393 .= Taylor1(zero(constant_term(q[1])), order) - tmp1396 = Array{Taylor1{_S}}(undef, size(r_p2)) - tmp1396 .= Taylor1(zero(constant_term(q[1])), order) - tmp1397 = Array{Taylor1{_S}}(undef, size(Λ2)) - tmp1397 .= Taylor1(zero(constant_term(q[1])), order) - tmp1400 = Array{Taylor1{_S}}(undef, size(r_p1d2)) - tmp1400 .= Taylor1(zero(constant_term(q[1])), order) - tmp1401 = Array{Taylor1{_S}}(undef, size(Λ3)) - tmp1401 .= Taylor1(zero(constant_term(q[1])), order) - tmp1403 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp1403 .= Taylor1(zero(constant_term(q[1])), order) - tmp1405 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) - tmp1405 .= Taylor1(zero(constant_term(q[1])), order) - tmp1408 = Array{Taylor1{_S}}(undef, size(Λ2j_div_r4)) - tmp1408 .= Taylor1(zero(constant_term(q[1])), order) - tmp1412 = Array{Taylor1{_S}}(undef, size(Λ3j_div_r5)) - tmp1412 .= Taylor1(zero(constant_term(q[1])), order) - tmp1415 = Array{Taylor1{_S}}(undef, size(X)) - tmp1415 .= Taylor1(zero(constant_term(q[1])), order) - tmp1417 = Array{Taylor1{_S}}(undef, size(Y)) - tmp1417 .= Taylor1(zero(constant_term(q[1])), order) - tmp1419 = Array{Taylor1{_S}}(undef, size(Z)) - tmp1419 .= Taylor1(zero(constant_term(q[1])), order) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 + for i = CartesianIndices(pn2z) + pn2z[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6208 = Array{Taylor1{_S}}(undef, size(UU)) + for i = CartesianIndices(tmp6208) + tmp6208[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6211 = Array{Taylor1{_S}}(undef, size(X)) + for i = CartesianIndices(tmp6211) + tmp6211[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6213 = Array{Taylor1{_S}}(undef, size(Y)) + for i = CartesianIndices(tmp6213) + tmp6213[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6214 = Array{Taylor1{_S}}(undef, size(tmp6211)) + for i = CartesianIndices(tmp6214) + tmp6214[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6216 = Array{Taylor1{_S}}(undef, size(Z)) + for i = CartesianIndices(tmp6216) + tmp6216[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6224 = Array{Taylor1{_S}}(undef, size(pn2x)) + for i = CartesianIndices(tmp6224) + tmp6224[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6225 = Array{Taylor1{_S}}(undef, size(tmp6224)) + for i = CartesianIndices(tmp6225) + tmp6225[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6320 = Array{Taylor1{_S}}(undef, size(ui)) + for i = CartesianIndices(tmp6320) + tmp6320[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6322 = Array{Taylor1{_S}}(undef, size(vi)) + for i = CartesianIndices(tmp6322) + tmp6322[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6323 = Array{Taylor1{_S}}(undef, size(tmp6320)) + for i = CartesianIndices(tmp6323) + tmp6323[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6325 = Array{Taylor1{_S}}(undef, size(wi)) + for i = CartesianIndices(tmp6325) + tmp6325[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6236 = Array{Taylor1{_S}}(undef, size(X)) + for i = CartesianIndices(tmp6236) + tmp6236[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6238 = Array{Taylor1{_S}}(undef, size(Y)) + for i = CartesianIndices(tmp6238) + tmp6238[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6240 = Array{Taylor1{_S}}(undef, size(Z)) + for i = CartesianIndices(tmp6240) + tmp6240[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6242 = Array{Taylor1{_S}}(undef, size(t31)) + for i = CartesianIndices(tmp6242) + tmp6242[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6399 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) + for i = CartesianIndices(tmp6399) + tmp6399[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6400 = Array{Taylor1{_S}}(undef, size(ϕ)) + for i = CartesianIndices(tmp6400) + tmp6400[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6252 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) + for i = CartesianIndices(tmp6252) + tmp6252[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6258 = Array{Taylor1{_S}}(undef, size(sin_ϕ)) + for i = CartesianIndices(tmp6258) + tmp6258[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6260 = Array{Taylor1{_S}}(undef, size(sin3_ϕ)) + for i = CartesianIndices(tmp6260) + tmp6260[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6264 = Array{Taylor1{_S}}(undef, size(sin2_ϕ)) + for i = CartesianIndices(tmp6264) + tmp6264[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6267 = Array{Taylor1{_S}}(undef, size(r_p2)) + for i = CartesianIndices(tmp6267) + tmp6267[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6268 = Array{Taylor1{_S}}(undef, size(Λ2)) + for i = CartesianIndices(tmp6268) + tmp6268[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6271 = Array{Taylor1{_S}}(undef, size(r_p1d2)) + for i = CartesianIndices(tmp6271) + tmp6271[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6272 = Array{Taylor1{_S}}(undef, size(Λ3)) + for i = CartesianIndices(tmp6272) + tmp6272[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6274 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) + for i = CartesianIndices(tmp6274) + tmp6274[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6276 = Array{Taylor1{_S}}(undef, size(cos_ϕ)) + for i = CartesianIndices(tmp6276) + tmp6276[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6279 = Array{Taylor1{_S}}(undef, size(Λ2j_div_r4)) + for i = CartesianIndices(tmp6279) + tmp6279[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6283 = Array{Taylor1{_S}}(undef, size(Λ3j_div_r5)) + for i = CartesianIndices(tmp6283) + tmp6283[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6286 = Array{Taylor1{_S}}(undef, size(X)) + for i = CartesianIndices(tmp6286) + tmp6286[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6288 = Array{Taylor1{_S}}(undef, size(Y)) + for i = CartesianIndices(tmp6288) + tmp6288[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6290 = Array{Taylor1{_S}}(undef, size(Z)) + for i = CartesianIndices(tmp6290) + tmp6290[i] = Taylor1(zero(constant_term(q[1])), order) + end + #= /Users/Jorge/projects/neos240702/neosjetcoeffs.jl:829 =# Threads.@threads for i = 1:Nm1 ui[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])), order) vi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])), order) wi[i] = Taylor1(identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])), order) @@ -1849,35 +2051,32 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_t U[i] = Taylor1(constant_term(ui[i]) - constant_term(dq[1]), order) V[i] = Taylor1(constant_term(vi[i]) - constant_term(dq[2]), order) W[i] = Taylor1(constant_term(wi[i]) - constant_term(dq[3]), order) - tmp1317[1] = Taylor1(constant_term(4) * constant_term(dq[1]), order) - tmp1319[i] = Taylor1(constant_term(3) * constant_term(ui[i]), order) - _4U_m_3X[i] = Taylor1(constant_term(tmp1317[1]) - constant_term(tmp1319[i]), order) - tmp1322[2] = Taylor1(constant_term(4) * constant_term(dq[2]), order) - tmp1324[i] = Taylor1(constant_term(3) * constant_term(vi[i]), order) - _4V_m_3Y[i] = Taylor1(constant_term(tmp1322[2]) - constant_term(tmp1324[i]), order) - tmp1327[3] = Taylor1(constant_term(4) * constant_term(dq[3]), order) - tmp1329[i] = Taylor1(constant_term(3) * constant_term(wi[i]), order) - _4W_m_3Z[i] = Taylor1(constant_term(tmp1327[3]) - constant_term(tmp1329[i]), order) + tmp6194[i] = Taylor1(constant_term(-3) * constant_term(ui[i]), order) + _4U_m_3X[i] = Taylor1(constant_term(tmp6194[i]) + constant_term(_4dq[1]), order) + tmp6197[i] = Taylor1(constant_term(-3) * constant_term(vi[i]), order) + _4V_m_3Y[i] = Taylor1(constant_term(tmp6197[i]) + constant_term(_4dq[2]), order) + tmp6200[i] = Taylor1(constant_term(-3) * constant_term(wi[i]), order) + _4W_m_3Z[i] = Taylor1(constant_term(tmp6200[i]) + constant_term(_4dq[3]), order) pn2x[i] = Taylor1(constant_term(X[i]) * constant_term(_4U_m_3X[i]), order) pn2y[i] = Taylor1(constant_term(Y[i]) * constant_term(_4V_m_3Y[i]), order) pn2z[i] = Taylor1(constant_term(Z[i]) * constant_term(_4W_m_3Z[i]), order) UU[i] = Taylor1(constant_term(ui[i]) * constant_term(dq[1]), order) VV[i] = Taylor1(constant_term(vi[i]) * constant_term(dq[2]), order) WW[i] = Taylor1(constant_term(wi[i]) * constant_term(dq[3]), order) - tmp1337[i] = Taylor1(constant_term(UU[i]) + constant_term(VV[i]), order) - vi_dot_vj[i] = Taylor1(constant_term(tmp1337[i]) + constant_term(WW[i]), order) - tmp1340[i] = Taylor1(constant_term(X[i]) ^ float(constant_term(2)), order) - tmp1342[i] = Taylor1(constant_term(Y[i]) ^ float(constant_term(2)), order) - tmp1343[i] = Taylor1(constant_term(tmp1340[i]) + constant_term(tmp1342[i]), order) - tmp1345[i] = Taylor1(constant_term(Z[i]) ^ float(constant_term(2)), order) - r_p2[i] = Taylor1(constant_term(tmp1343[i]) + constant_term(tmp1345[i]), order) + tmp6208[i] = Taylor1(constant_term(UU[i]) + constant_term(VV[i]), order) + vi_dot_vj[i] = Taylor1(constant_term(tmp6208[i]) + constant_term(WW[i]), order) + tmp6211[i] = Taylor1(constant_term(X[i]) ^ float(constant_term(2)), order) + tmp6213[i] = Taylor1(constant_term(Y[i]) ^ float(constant_term(2)), order) + tmp6214[i] = Taylor1(constant_term(tmp6211[i]) + constant_term(tmp6213[i]), order) + tmp6216[i] = Taylor1(constant_term(Z[i]) ^ float(constant_term(2)), order) + r_p2[i] = Taylor1(constant_term(tmp6214[i]) + constant_term(tmp6216[i]), order) r_p1d2[i] = Taylor1(sqrt(constant_term(r_p2[i])), order) r_p3d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(1.5)), order) r_p7d2[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(3.5)), order) newtonianCoeff[i] = Taylor1(constant_term(μ[i]) / constant_term(r_p3d2[i]), order) - tmp1353[i] = Taylor1(constant_term(pn2x[i]) + constant_term(pn2y[i]), order) - tmp1354[i] = Taylor1(constant_term(tmp1353[i]) + constant_term(pn2z[i]), order) - pn2[i] = Taylor1(constant_term(newtonianCoeff[i]) * constant_term(tmp1354[i]), order) + tmp6224[i] = Taylor1(constant_term(pn2x[i]) + constant_term(pn2y[i]), order) + tmp6225[i] = Taylor1(constant_term(tmp6224[i]) + constant_term(pn2z[i]), order) + pn2[i] = Taylor1(constant_term(newtonianCoeff[i]) * constant_term(tmp6225[i]), order) newton_acc_X[i] = Taylor1(constant_term(X[i]) * constant_term(newtonianCoeff[i]), order) newton_acc_Y[i] = Taylor1(constant_term(Y[i]) * constant_term(newtonianCoeff[i]), order) newton_acc_Z[i] = Taylor1(constant_term(Z[i]) * constant_term(newtonianCoeff[i]), order) @@ -1887,53 +2086,53 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_t V_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(V[i]), order) W_t_pn2[i] = Taylor1(constant_term(pn2[i]) * constant_term(W[i]), order) if UJ_interaction[i] - tmp1365[i] = Taylor1(-(constant_term(X[i])), order) - t31[i] = Taylor1(constant_term(tmp1365[i]) * constant_term(M_[1, 3, i]), order) - tmp1367[i] = Taylor1(-(constant_term(Y[i])), order) - t32[i] = Taylor1(constant_term(tmp1367[i]) * constant_term(M_[2, 3, i]), order) - tmp1369[i] = Taylor1(-(constant_term(Z[i])), order) - t33[i] = Taylor1(constant_term(tmp1369[i]) * constant_term(M_[3, 3, i]), order) - tmp1371[i] = Taylor1(constant_term(t31[i]) + constant_term(t32[i]), order) - r_sin_ϕ[i] = Taylor1(constant_term(tmp1371[i]) + constant_term(t33[i]), order) + tmp6236[i] = Taylor1(-(constant_term(X[i])), order) + t31[i] = Taylor1(constant_term(tmp6236[i]) * constant_term(M_[1, 3, i]), order) + tmp6238[i] = Taylor1(-(constant_term(Y[i])), order) + t32[i] = Taylor1(constant_term(tmp6238[i]) * constant_term(M_[2, 3, i]), order) + tmp6240[i] = Taylor1(-(constant_term(Z[i])), order) + t33[i] = Taylor1(constant_term(tmp6240[i]) * constant_term(M_[3, 3, i]), order) + tmp6242[i] = Taylor1(constant_term(t31[i]) + constant_term(t32[i]), order) + r_sin_ϕ[i] = Taylor1(constant_term(tmp6242[i]) + constant_term(t33[i]), order) sin_ϕ[i] = Taylor1(constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]), order) ϕ[i] = Taylor1(asin(constant_term(sin_ϕ[i])), order) - tmp1528[i] = Taylor1(sqrt(1 - constant_term(sin_ϕ[i]) ^ 2), order) + tmp6399[i] = Taylor1(sqrt(1 - constant_term(sin_ϕ[i]) ^ 2), order) cos_ϕ[i] = Taylor1(cos(constant_term(ϕ[i])), order) - tmp1529[i] = Taylor1(sin(constant_term(ϕ[i])), order) + tmp6400[i] = Taylor1(sin(constant_term(ϕ[i])), order) sin2_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(2)), order) sin3_ϕ[i] = Taylor1(constant_term(sin_ϕ[i]) ^ float(constant_term(3)), order) - tmp1381[i] = Taylor1(constant_term(1.5) * constant_term(sin2_ϕ[i]), order) - P_2_sin_ϕ[i] = Taylor1(constant_term(tmp1381[i]) - constant_term(0.5), order) + tmp6252[i] = Taylor1(constant_term(1.5) * constant_term(sin2_ϕ[i]), order) + P_2_sin_ϕ[i] = Taylor1(constant_term(tmp6252[i]) - constant_term(0.5), order) ∂P_2_sin_ϕ[i] = Taylor1(constant_term(3) * constant_term(sin_ϕ[i]), order) - tmp1387[i] = Taylor1(constant_term(-1.5) * constant_term(sin_ϕ[i]), order) - tmp1389[i] = Taylor1(constant_term(2.5) * constant_term(sin3_ϕ[i]), order) - P_3_sin_ϕ[i] = Taylor1(constant_term(tmp1387[i]) + constant_term(tmp1389[i]), order) - tmp1393[i] = Taylor1(constant_term(7.5) * constant_term(sin2_ϕ[i]), order) - ∂P_3_sin_ϕ[i] = Taylor1(constant_term(-1.5) + constant_term(tmp1393[i]), order) - tmp1396[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(2)), order) - tmp1397[i] = Taylor1(constant_term(Λ2[i]) / constant_term(tmp1396[i]), order) - Λ2j_div_r4[i] = Taylor1(-(constant_term(tmp1397[i])), order) - tmp1400[i] = Taylor1(constant_term(r_p1d2[i]) ^ float(constant_term(5)), order) - tmp1401[i] = Taylor1(constant_term(Λ3[i]) / constant_term(tmp1400[i]), order) - Λ3j_div_r5[i] = Taylor1(-(constant_term(tmp1401[i])), order) - tmp1403[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) - m_c_ϕ_∂P_2[i] = Taylor1(constant_term(tmp1403[i]) * constant_term(∂P_2_sin_ϕ[i]), order) - tmp1405[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) - m_c_ϕ_∂P_3[i] = Taylor1(constant_term(tmp1405[i]) * constant_term(∂P_3_sin_ϕ[i]), order) - tmp1408[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(3), order) - F_J2_ξ[i] = Taylor1(constant_term(tmp1408[i]) * constant_term(P_2_sin_ϕ[i]), order) + tmp6258[i] = Taylor1(constant_term(-1.5) * constant_term(sin_ϕ[i]), order) + tmp6260[i] = Taylor1(constant_term(2.5) * constant_term(sin3_ϕ[i]), order) + P_3_sin_ϕ[i] = Taylor1(constant_term(tmp6258[i]) + constant_term(tmp6260[i]), order) + tmp6264[i] = Taylor1(constant_term(7.5) * constant_term(sin2_ϕ[i]), order) + ∂P_3_sin_ϕ[i] = Taylor1(constant_term(-1.5) + constant_term(tmp6264[i]), order) + tmp6267[i] = Taylor1(constant_term(r_p2[i]) ^ float(constant_term(2)), order) + tmp6268[i] = Taylor1(constant_term(Λ2[i]) / constant_term(tmp6267[i]), order) + Λ2j_div_r4[i] = Taylor1(-(constant_term(tmp6268[i])), order) + tmp6271[i] = Taylor1(constant_term(r_p1d2[i]) ^ float(constant_term(5)), order) + tmp6272[i] = Taylor1(constant_term(Λ3[i]) / constant_term(tmp6271[i]), order) + Λ3j_div_r5[i] = Taylor1(-(constant_term(tmp6272[i])), order) + tmp6274[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) + m_c_ϕ_∂P_2[i] = Taylor1(constant_term(tmp6274[i]) * constant_term(∂P_2_sin_ϕ[i]), order) + tmp6276[i] = Taylor1(-(constant_term(cos_ϕ[i])), order) + m_c_ϕ_∂P_3[i] = Taylor1(constant_term(tmp6276[i]) * constant_term(∂P_3_sin_ϕ[i]), order) + tmp6279[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(3), order) + F_J2_ξ[i] = Taylor1(constant_term(tmp6279[i]) * constant_term(P_2_sin_ϕ[i]), order) F_J2_ζ[i] = Taylor1(constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]), order) - tmp1412[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(4), order) - F_J3_ξ[i] = Taylor1(constant_term(tmp1412[i]) * constant_term(P_3_sin_ϕ[i]), order) + tmp6283[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(4), order) + F_J3_ξ[i] = Taylor1(constant_term(tmp6283[i]) * constant_term(P_3_sin_ϕ[i]), order) F_J3_ζ[i] = Taylor1(constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]), order) F_J_ξ[i] = Taylor1(identity(constant_term(F_J2_ξ[i])), order) F_J_ζ[i] = Taylor1(identity(constant_term(F_J2_ζ[i])), order) - tmp1415[i] = Taylor1(-(constant_term(X[i])), order) - ξx[i] = Taylor1(constant_term(tmp1415[i]) / constant_term(r_p1d2[i]), order) - tmp1417[i] = Taylor1(-(constant_term(Y[i])), order) - ξy[i] = Taylor1(constant_term(tmp1417[i]) / constant_term(r_p1d2[i]), order) - tmp1419[i] = Taylor1(-(constant_term(Z[i])), order) - ξz[i] = Taylor1(constant_term(tmp1419[i]) / constant_term(r_p1d2[i]), order) + tmp6286[i] = Taylor1(-(constant_term(X[i])), order) + ξx[i] = Taylor1(constant_term(tmp6286[i]) / constant_term(r_p1d2[i]), order) + tmp6288[i] = Taylor1(-(constant_term(Y[i])), order) + ξy[i] = Taylor1(constant_term(tmp6288[i]) / constant_term(r_p1d2[i]), order) + tmp6290[i] = Taylor1(-(constant_term(Z[i])), order) + ξz[i] = Taylor1(constant_term(tmp6290[i]) / constant_term(r_p1d2[i]), order) ηx1[i] = Taylor1(constant_term(M_[2, 3, i]) * constant_term(ξz[i]), order) ηy1[i] = Taylor1(constant_term(M_[3, 3, i]) * constant_term(ξx[i]), order) ηz1[i] = Taylor1(constant_term(M_[1, 3, i]) * constant_term(ξy[i]), order) @@ -1962,95 +2161,133 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_t F_J2_y[i] = Taylor1(constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]), order) F_J2_z[i] = Taylor1(constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]), order) end - tmp1449[i] = Taylor1(constant_term(ui[i]) ^ float(constant_term(2)), order) - tmp1451[i] = Taylor1(constant_term(vi[i]) ^ float(constant_term(2)), order) - tmp1452[i] = Taylor1(constant_term(tmp1449[i]) + constant_term(tmp1451[i]), order) - tmp1454[i] = Taylor1(constant_term(wi[i]) ^ float(constant_term(2)), order) - v2[i] = Taylor1(constant_term(tmp1452[i]) + constant_term(tmp1454[i]), order) + tmp6320[i] = Taylor1(constant_term(ui[i]) ^ float(constant_term(2)), order) + tmp6322[i] = Taylor1(constant_term(vi[i]) ^ float(constant_term(2)), order) + tmp6323[i] = Taylor1(constant_term(tmp6320[i]) + constant_term(tmp6322[i]), order) + tmp6325[i] = Taylor1(constant_term(wi[i]) ^ float(constant_term(2)), order) + v2[i] = Taylor1(constant_term(tmp6323[i]) + constant_term(tmp6325[i]), order) end - tmp1457 = Taylor1(constant_term(q[4]) ^ float(constant_term(2)), order) - tmp1459 = Taylor1(constant_term(q[5]) ^ float(constant_term(2)), order) - tmp1460 = Taylor1(constant_term(tmp1457) + constant_term(tmp1459), order) - tmp1462 = Taylor1(constant_term(q[6]) ^ float(constant_term(2)), order) - v2[N] = Taylor1(constant_term(tmp1460) + constant_term(tmp1462), order) + tmp6328 = Taylor1(constant_term(q[4]) ^ float(constant_term(2)), order) + tmp6330 = Taylor1(constant_term(q[5]) ^ float(constant_term(2)), order) + tmp6331 = Taylor1(constant_term(tmp6328) + constant_term(tmp6330), order) + tmp6333 = Taylor1(constant_term(q[6]) ^ float(constant_term(2)), order) + v2[N] = Taylor1(constant_term(tmp6331) + constant_term(tmp6333), order) temp_004 = Array{Taylor1{_S}}(undef, size(newtonian1b_Potential)) - temp_004 .= Taylor1(zero(constant_term(q[1])), order) - tmp1465 = Array{Taylor1{_S}}(undef, size(μ)) - tmp1465 .= Taylor1(zero(constant_term(q[1])), order) - tmp1467 = Array{Taylor1{_S}}(undef, size(μ)) - tmp1467 .= Taylor1(zero(constant_term(q[1])), order) - tmp1469 = Array{Taylor1{_S}}(undef, size(μ)) - tmp1469 .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(temp_004) + temp_004[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6336 = Array{Taylor1{_S}}(undef, size(μ)) + for i = CartesianIndices(tmp6336) + tmp6336[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6338 = Array{Taylor1{_S}}(undef, size(μ)) + for i = CartesianIndices(tmp6338) + tmp6338[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6340 = Array{Taylor1{_S}}(undef, size(μ)) + for i = CartesianIndices(tmp6340) + tmp6340[i] = Taylor1(zero(constant_term(q[1])), order) + end for i = 1:Nm1 temp_004[i] = Taylor1(constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]), order) newtonianNb_Potential[N] = Taylor1(identity(constant_term(temp_004[i])), order) if UJ_interaction[i] - tmp1465[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_x[i]), order) - temp_accX_i[i] = Taylor1(constant_term(accX) - constant_term(tmp1465[i]), order) + tmp6336[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_x[i]), order) + temp_accX_i[i] = Taylor1(constant_term(accX) - constant_term(tmp6336[i]), order) accX = Taylor1(identity(constant_term(temp_accX_i[i])), order) - tmp1467[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_y[i]), order) - temp_accY_i[i] = Taylor1(constant_term(accY) - constant_term(tmp1467[i]), order) + tmp6338[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_y[i]), order) + temp_accY_i[i] = Taylor1(constant_term(accY) - constant_term(tmp6338[i]), order) accY = Taylor1(identity(constant_term(temp_accY_i[i])), order) - tmp1469[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_z[i]), order) - temp_accZ_i[i] = Taylor1(constant_term(accZ) - constant_term(tmp1469[i]), order) + tmp6340[i] = Taylor1(constant_term(μ[i]) * constant_term(F_J2_z[i]), order) + temp_accZ_i[i] = Taylor1(constant_term(accZ) - constant_term(tmp6340[i]), order) accZ = Taylor1(identity(constant_term(temp_accZ_i[i])), order) end end _4ϕj[N] = Taylor1(constant_term(4) * constant_term(newtonianNb_Potential[N]), order) - tmp1475 = Array{Taylor1{_S}}(undef, size(v2)) - tmp1475 .= Taylor1(zero(constant_term(q[1])), order) - tmp1477 = Array{Taylor1{_S}}(undef, size(vi_dot_vj)) - tmp1477 .= Taylor1(zero(constant_term(q[1])), order) - tmp1478 = Array{Taylor1{_S}}(undef, size(tmp1475)) - tmp1478 .= Taylor1(zero(constant_term(q[1])), order) + tmp6346 = Array{Taylor1{_S}}(undef, size(v2)) + for i = CartesianIndices(tmp6346) + tmp6346[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6348 = Array{Taylor1{_S}}(undef, size(vi_dot_vj)) + for i = CartesianIndices(tmp6348) + tmp6348[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6349 = Array{Taylor1{_S}}(undef, size(tmp6346)) + for i = CartesianIndices(tmp6349) + tmp6349[i] = Taylor1(zero(constant_term(q[1])), order) + end Xij_t_Ui = Array{Taylor1{_S}}(undef, size(X)) - Xij_t_Ui .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(Xij_t_Ui) + Xij_t_Ui[i] = Taylor1(zero(constant_term(q[1])), order) + end Yij_t_Vi = Array{Taylor1{_S}}(undef, size(Y)) - Yij_t_Vi .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(Yij_t_Vi) + Yij_t_Vi[i] = Taylor1(zero(constant_term(q[1])), order) + end Zij_t_Wi = Array{Taylor1{_S}}(undef, size(Z)) - Zij_t_Wi .= Taylor1(zero(constant_term(q[1])), order) - tmp1484 = Array{Taylor1{_S}}(undef, size(Xij_t_Ui)) - tmp1484 .= Taylor1(zero(constant_term(q[1])), order) - Rij_dot_Vi = Array{Taylor1{_S}}(undef, size(tmp1484)) - Rij_dot_Vi .= Taylor1(zero(constant_term(q[1])), order) - tmp1487 = Array{Taylor1{_S}}(undef, size(Rij_dot_Vi)) - tmp1487 .= Taylor1(zero(constant_term(q[1])), order) - pn1t7 = Array{Taylor1{_S}}(undef, size(tmp1487)) - pn1t7 .= Taylor1(zero(constant_term(q[1])), order) - tmp1490 = Array{Taylor1{_S}}(undef, size(pn1t7)) - tmp1490 .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(Zij_t_Wi) + Zij_t_Wi[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6355 = Array{Taylor1{_S}}(undef, size(Xij_t_Ui)) + for i = CartesianIndices(tmp6355) + tmp6355[i] = Taylor1(zero(constant_term(q[1])), order) + end + Rij_dot_Vi = Array{Taylor1{_S}}(undef, size(tmp6355)) + for i = CartesianIndices(Rij_dot_Vi) + Rij_dot_Vi[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6358 = Array{Taylor1{_S}}(undef, size(Rij_dot_Vi)) + for i = CartesianIndices(tmp6358) + tmp6358[i] = Taylor1(zero(constant_term(q[1])), order) + end + pn1t7 = Array{Taylor1{_S}}(undef, size(tmp6358)) + for i = CartesianIndices(pn1t7) + pn1t7[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6361 = Array{Taylor1{_S}}(undef, size(pn1t7)) + for i = CartesianIndices(tmp6361) + tmp6361[i] = Taylor1(zero(constant_term(q[1])), order) + end pn1t2_7 = Array{Taylor1{_S}}(undef, size(ϕs_and_vs)) - pn1t2_7 .= Taylor1(zero(constant_term(q[1])), order) - tmp1497 = Array{Taylor1{_S}}(undef, size(pNX_t_X)) - tmp1497 .= Taylor1(zero(constant_term(q[1])), order) - tmp1498 = Array{Taylor1{_S}}(undef, size(tmp1497)) - tmp1498 .= Taylor1(zero(constant_term(q[1])), order) - tmp1499 = Array{Taylor1{_S}}(undef, size(tmp1498)) - tmp1499 .= Taylor1(zero(constant_term(q[1])), order) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 + for i = CartesianIndices(pn1t2_7) + pn1t2_7[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6368 = Array{Taylor1{_S}}(undef, size(pNX_t_X)) + for i = CartesianIndices(tmp6368) + tmp6368[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6369 = Array{Taylor1{_S}}(undef, size(tmp6368)) + for i = CartesianIndices(tmp6369) + tmp6369[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6370 = Array{Taylor1{_S}}(undef, size(tmp6369)) + for i = CartesianIndices(tmp6370) + tmp6370[i] = Taylor1(zero(constant_term(q[1])), order) + end + #= /Users/Jorge/projects/neos240702/neosjetcoeffs.jl:1031 =# Threads.@threads for i = 1:10 ϕi_plus_4ϕj[i] = Taylor1(constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]), order) - tmp1475[i] = Taylor1(constant_term(2) * constant_term(v2[i]), order) - tmp1477[i] = Taylor1(constant_term(4) * constant_term(vi_dot_vj[i]), order) - tmp1478[i] = Taylor1(constant_term(tmp1475[i]) - constant_term(tmp1477[i]), order) - sj2_plus_2si2_minus_4vivj[i] = Taylor1(constant_term(tmp1478[i]) + constant_term(v2[N]), order) + tmp6346[i] = Taylor1(constant_term(2) * constant_term(v2[i]), order) + tmp6348[i] = Taylor1(constant_term(4) * constant_term(vi_dot_vj[i]), order) + tmp6349[i] = Taylor1(constant_term(tmp6346[i]) - constant_term(tmp6348[i]), order) + sj2_plus_2si2_minus_4vivj[i] = Taylor1(constant_term(tmp6349[i]) + constant_term(v2[N]), order) ϕs_and_vs[i] = Taylor1(constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]), order) Xij_t_Ui[i] = Taylor1(constant_term(X[i]) * constant_term(ui[i]), order) Yij_t_Vi[i] = Taylor1(constant_term(Y[i]) * constant_term(vi[i]), order) Zij_t_Wi[i] = Taylor1(constant_term(Z[i]) * constant_term(wi[i]), order) - tmp1484[i] = Taylor1(constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]), order) - Rij_dot_Vi[i] = Taylor1(constant_term(tmp1484[i]) + constant_term(Zij_t_Wi[i]), order) - tmp1487[i] = Taylor1(constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)), order) - pn1t7[i] = Taylor1(constant_term(tmp1487[i]) / constant_term(r_p2[i]), order) - tmp1490[i] = Taylor1(constant_term(1.5) * constant_term(pn1t7[i]), order) - pn1t2_7[i] = Taylor1(constant_term(ϕs_and_vs[i]) - constant_term(tmp1490[i]), order) + tmp6355[i] = Taylor1(constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]), order) + Rij_dot_Vi[i] = Taylor1(constant_term(tmp6355[i]) + constant_term(Zij_t_Wi[i]), order) + tmp6358[i] = Taylor1(constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)), order) + pn1t7[i] = Taylor1(constant_term(tmp6358[i]) / constant_term(r_p2[i]), order) + tmp6361[i] = Taylor1(constant_term(1.5) * constant_term(pn1t7[i]), order) + pn1t2_7[i] = Taylor1(constant_term(ϕs_and_vs[i]) - constant_term(tmp6361[i]), order) pn1t1_7[i] = Taylor1(constant_term(c_p2) + constant_term(pn1t2_7[i]), order) pNX_t_X[i] = Taylor1(constant_term(acceph_t[3i - 2]) * constant_term(X[i]), order) pNY_t_Y[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(Y[i]), order) pNZ_t_Z[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(Z[i]), order) - tmp1497[i] = Taylor1(constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]), order) - tmp1498[i] = Taylor1(constant_term(tmp1497[i]) + constant_term(pNZ_t_Z[i]), order) - tmp1499[i] = Taylor1(constant_term(0.5) * constant_term(tmp1498[i]), order) - pn1[i] = Taylor1(constant_term(pn1t1_7[i]) + constant_term(tmp1499[i]), order) + tmp6368[i] = Taylor1(constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]), order) + tmp6369[i] = Taylor1(constant_term(tmp6368[i]) + constant_term(pNZ_t_Z[i]), order) + tmp6370[i] = Taylor1(constant_term(0.5) * constant_term(tmp6369[i]), order) + pn1[i] = Taylor1(constant_term(pn1t1_7[i]) + constant_term(tmp6370[i]), order) X_t_pn1[i] = Taylor1(constant_term(newton_acc_X[i]) * constant_term(pn1[i]), order) Y_t_pn1[i] = Taylor1(constant_term(newton_acc_Y[i]) * constant_term(pn1[i]), order) Z_t_pn1[i] = Taylor1(constant_term(newton_acc_Z[i]) * constant_term(pn1[i]), order) @@ -2058,39 +2295,57 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_t pNY_t_pn3[i] = Taylor1(constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]), order) pNZ_t_pn3[i] = Taylor1(constant_term(acceph_t[3i]) * constant_term(pn3[i]), order) end - tmp1507 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) - tmp1507 .= Taylor1(zero(constant_term(q[1])), order) + tmp6378 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) + for i = CartesianIndices(tmp6378) + tmp6378[i] = Taylor1(zero(constant_term(q[1])), order) + end termpnx = Array{Taylor1{_S}}(undef, size(X_t_pn1)) - termpnx .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(termpnx) + termpnx[i] = Taylor1(zero(constant_term(q[1])), order) + end sumpnx = Array{Taylor1{_S}}(undef, size(termpnx)) - sumpnx .= Taylor1(zero(constant_term(q[1])), order) - tmp1510 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) - tmp1510 .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(sumpnx) + sumpnx[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6381 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) + for i = CartesianIndices(tmp6381) + tmp6381[i] = Taylor1(zero(constant_term(q[1])), order) + end termpny = Array{Taylor1{_S}}(undef, size(Y_t_pn1)) - termpny .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(termpny) + termpny[i] = Taylor1(zero(constant_term(q[1])), order) + end sumpny = Array{Taylor1{_S}}(undef, size(termpny)) - sumpny .= Taylor1(zero(constant_term(q[1])), order) - tmp1513 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) - tmp1513 .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(sumpny) + sumpny[i] = Taylor1(zero(constant_term(q[1])), order) + end + tmp6384 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) + for i = CartesianIndices(tmp6384) + tmp6384[i] = Taylor1(zero(constant_term(q[1])), order) + end termpnz = Array{Taylor1{_S}}(undef, size(Z_t_pn1)) - termpnz .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(termpnz) + termpnz[i] = Taylor1(zero(constant_term(q[1])), order) + end sumpnz = Array{Taylor1{_S}}(undef, size(termpnz)) - sumpnz .= Taylor1(zero(constant_term(q[1])), order) + for i = CartesianIndices(sumpnz) + sumpnz[i] = Taylor1(zero(constant_term(q[1])), order) + end for i = 1:10 - tmp1507[i] = Taylor1(constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]), order) - termpnx[i] = Taylor1(constant_term(X_t_pn1[i]) + constant_term(tmp1507[i]), order) + tmp6378[i] = Taylor1(constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]), order) + termpnx[i] = Taylor1(constant_term(X_t_pn1[i]) + constant_term(tmp6378[i]), order) sumpnx[i] = Taylor1(constant_term(pntempX) + constant_term(termpnx[i]), order) pntempX = Taylor1(identity(constant_term(sumpnx[i])), order) - tmp1510[i] = Taylor1(constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]), order) - termpny[i] = Taylor1(constant_term(Y_t_pn1[i]) + constant_term(tmp1510[i]), order) + tmp6381[i] = Taylor1(constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]), order) + termpny[i] = Taylor1(constant_term(Y_t_pn1[i]) + constant_term(tmp6381[i]), order) sumpny[i] = Taylor1(constant_term(pntempY) + constant_term(termpny[i]), order) pntempY = Taylor1(identity(constant_term(sumpny[i])), order) - tmp1513[i] = Taylor1(constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]), order) - termpnz[i] = Taylor1(constant_term(Z_t_pn1[i]) + constant_term(tmp1513[i]), order) + tmp6384[i] = Taylor1(constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]), order) + termpnz[i] = Taylor1(constant_term(Z_t_pn1[i]) + constant_term(tmp6384[i]), order) sumpnz[i] = Taylor1(constant_term(pntempZ) + constant_term(termpnz[i]), order) pntempZ = Taylor1(identity(constant_term(sumpnz[i])), order) end - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 + #= /Users/Jorge/projects/neos240702/neosjetcoeffs.jl:1084 =# Threads.@threads for i = 11:Nm1 X_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_X[i]), order) Y_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Y[i]), order) Z_t_pn1[i] = Taylor1(constant_term(c_p2) * constant_term(newton_acc_Z[i]), order) @@ -2112,16 +2367,16 @@ function TaylorIntegration._allocate_jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_t dq[4] = Taylor1(constant_term(postNewtonX) + constant_term(accX), order) dq[5] = Taylor1(constant_term(postNewtonY) + constant_term(accY), order) dq[6] = Taylor1(constant_term(postNewtonZ) + constant_term(accZ), order) - return TaylorIntegration.RetAlloc{Taylor1{_S}}([tmp1457, tmp1459, tmp1460, tmp1462, pntempX, pntempY, pntempZ, accX, accY, accZ, postNewtonX, postNewtonY, postNewtonZ], [X, Y, Z, r_p2, r_p1d2, r_p3d2, r_p7d2, newtonianCoeff, ui, vi, wi, U, V, W, _4U_m_3X, _4V_m_3Y, _4W_m_3Z, UU, VV, WW, newtonian1b_Potential, newtonianNb_Potential, newton_acc_X, newton_acc_Y, newton_acc_Z, v2, vi_dot_vj, pn2, U_t_pn2, V_t_pn2, W_t_pn2, pn3, pNX_t_pn3, pNY_t_pn3, pNZ_t_pn3, _4ϕj, ϕi_plus_4ϕj, sj2_plus_2si2_minus_4vivj, ϕs_and_vs, pn1t1_7, pNX_t_X, pNY_t_Y, pNZ_t_Z, pn1, X_t_pn1, Y_t_pn1, Z_t_pn1, t31, t32, t33, r_sin_ϕ, sin_ϕ, ϕ, cos_ϕ, sin2_ϕ, sin3_ϕ, F_J2_x, F_J2_y, F_J2_z, F_J2_x1, F_J2_y1, F_J2_z1, F_J2_x2, F_J2_y2, F_J2_z2, temp_accX_i, temp_accY_i, temp_accZ_i, P_2_sin_ϕ, ∂P_2_sin_ϕ, P_3_sin_ϕ, ∂P_3_sin_ϕ, m_c_ϕ_∂P_2, m_c_ϕ_∂P_3, Λ2j_div_r4, Λ3j_div_r5, F_J_ξ, F_J_ζ, F_J2_ξ, F_J2_ζ, F_J3_ξ, F_J3_ζ, ξx, ξy, ξz, ηx, ηy, ηz, ηx1, ηy1, ηz1, ηx2, ηy2, ηz2, ζx, ζy, ζz, ζx1, ζy1, ζz1, ζx2, ζy2, ζz2, tmp1317, tmp1319, tmp1322, tmp1324, tmp1327, tmp1329, pn2x, pn2y, pn2z, tmp1337, tmp1340, tmp1342, tmp1343, tmp1345, tmp1353, tmp1354, tmp1365, tmp1367, tmp1369, tmp1371, tmp1528, tmp1529, tmp1381, tmp1387, tmp1389, tmp1393, tmp1396, tmp1397, tmp1400, tmp1401, tmp1403, tmp1405, tmp1408, tmp1412, tmp1415, tmp1417, tmp1419, tmp1449, tmp1451, tmp1452, tmp1454, temp_004, tmp1465, tmp1467, tmp1469, tmp1475, tmp1477, tmp1478, Xij_t_Ui, Yij_t_Vi, Zij_t_Wi, tmp1484, Rij_dot_Vi, tmp1487, pn1t7, tmp1490, pn1t2_7, tmp1497, tmp1498, tmp1499, tmp1507, termpnx, sumpnx, tmp1510, termpny, sumpny, tmp1513, termpnz, sumpnz], [Array{Taylor1{_S}, 2}(undef, 0, 0)], [Array{Taylor1{_S}, 3}(undef, 0, 0, 0)], [Array{Taylor1{_S}, 4}(undef, 0, 0, 0, 0)]) + return TaylorIntegration.RetAlloc{Taylor1{_S}}([tmp6328, tmp6330, tmp6331, tmp6333, pntempX, pntempY, pntempZ, accX, accY, accZ, postNewtonX, postNewtonY, postNewtonZ], [X, Y, Z, r_p2, r_p1d2, r_p3d2, r_p7d2, newtonianCoeff, ui, vi, wi, U, V, W, _4dq, _4U_m_3X, _4V_m_3Y, _4W_m_3Z, UU, VV, WW, newtonian1b_Potential, newtonianNb_Potential, newton_acc_X, newton_acc_Y, newton_acc_Z, v2, vi_dot_vj, pn2, U_t_pn2, V_t_pn2, W_t_pn2, pn3, pNX_t_pn3, pNY_t_pn3, pNZ_t_pn3, _4ϕj, ϕi_plus_4ϕj, sj2_plus_2si2_minus_4vivj, ϕs_and_vs, pn1t1_7, pNX_t_X, pNY_t_Y, pNZ_t_Z, pn1, X_t_pn1, Y_t_pn1, Z_t_pn1, t31, t32, t33, r_sin_ϕ, sin_ϕ, ϕ, cos_ϕ, sin2_ϕ, sin3_ϕ, F_J2_x, F_J2_y, F_J2_z, F_J2_x1, F_J2_y1, F_J2_z1, F_J2_x2, F_J2_y2, F_J2_z2, temp_accX_i, temp_accY_i, temp_accZ_i, P_2_sin_ϕ, ∂P_2_sin_ϕ, P_3_sin_ϕ, ∂P_3_sin_ϕ, m_c_ϕ_∂P_2, m_c_ϕ_∂P_3, Λ2j_div_r4, Λ3j_div_r5, F_J_ξ, F_J_ζ, F_J2_ξ, F_J2_ζ, F_J3_ξ, F_J3_ζ, ξx, ξy, ξz, ηx, ηy, ηz, ηx1, ηy1, ηz1, ηx2, ηy2, ηz2, ζx, ζy, ζz, ζx1, ζy1, ζz1, ζx2, ζy2, ζz2, tmp6194, tmp6197, tmp6200, pn2x, pn2y, pn2z, tmp6208, tmp6211, tmp6213, tmp6214, tmp6216, tmp6224, tmp6225, tmp6236, tmp6238, tmp6240, tmp6242, tmp6399, tmp6400, tmp6252, tmp6258, tmp6260, tmp6264, tmp6267, tmp6268, tmp6271, tmp6272, tmp6274, tmp6276, tmp6279, tmp6283, tmp6286, tmp6288, tmp6290, tmp6320, tmp6322, tmp6323, tmp6325, temp_004, tmp6336, tmp6338, tmp6340, tmp6346, tmp6348, tmp6349, Xij_t_Ui, Yij_t_Vi, Zij_t_Wi, tmp6355, Rij_dot_Vi, tmp6358, pn1t7, tmp6361, pn1t2_7, tmp6368, tmp6369, tmp6370, tmp6378, termpnx, sumpnx, tmp6381, termpny, sumpny, tmp6384, termpnz, sumpnz], [Array{Taylor1{_S}, 2}(undef, 0, 0)], [Array{Taylor1{_S}, 3}(undef, 0, 0, 0)], [Array{Taylor1{_S}, 4}(undef, 0, 0, 0, 0)]) end # TaylorIntegration.jetcoeffs! method for src/propagation/asteroid_dynamical_models.jl: RNp1BP_pN_A_J23E_J2S_eph_threads! function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, t::Taylor1{_T}, q::AbstractArray{Taylor1{_S}, _N}, dq::AbstractArray{Taylor1{_S}, _N}, params, __ralloc::TaylorIntegration.RetAlloc{Taylor1{_S}}) where {_T <: Real, _S <: Number, _N} order = t.order - tmp1457 = __ralloc.v0[1] - tmp1459 = __ralloc.v0[2] - tmp1460 = __ralloc.v0[3] - tmp1462 = __ralloc.v0[4] + tmp6328 = __ralloc.v0[1] + tmp6330 = __ralloc.v0[2] + tmp6331 = __ralloc.v0[3] + tmp6333 = __ralloc.v0[4] pntempX = __ralloc.v0[5] pntempY = __ralloc.v0[6] pntempZ = __ralloc.v0[7] @@ -2145,164 +2400,162 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, U = __ralloc.v1[12] V = __ralloc.v1[13] W = __ralloc.v1[14] - _4U_m_3X = __ralloc.v1[15] - _4V_m_3Y = __ralloc.v1[16] - _4W_m_3Z = __ralloc.v1[17] - UU = __ralloc.v1[18] - VV = __ralloc.v1[19] - WW = __ralloc.v1[20] - newtonian1b_Potential = __ralloc.v1[21] - newtonianNb_Potential = __ralloc.v1[22] - newton_acc_X = __ralloc.v1[23] - newton_acc_Y = __ralloc.v1[24] - newton_acc_Z = __ralloc.v1[25] - v2 = __ralloc.v1[26] - vi_dot_vj = __ralloc.v1[27] - pn2 = __ralloc.v1[28] - U_t_pn2 = __ralloc.v1[29] - V_t_pn2 = __ralloc.v1[30] - W_t_pn2 = __ralloc.v1[31] - pn3 = __ralloc.v1[32] - pNX_t_pn3 = __ralloc.v1[33] - pNY_t_pn3 = __ralloc.v1[34] - pNZ_t_pn3 = __ralloc.v1[35] - _4ϕj = __ralloc.v1[36] - ϕi_plus_4ϕj = __ralloc.v1[37] - sj2_plus_2si2_minus_4vivj = __ralloc.v1[38] - ϕs_and_vs = __ralloc.v1[39] - pn1t1_7 = __ralloc.v1[40] - pNX_t_X = __ralloc.v1[41] - pNY_t_Y = __ralloc.v1[42] - pNZ_t_Z = __ralloc.v1[43] - pn1 = __ralloc.v1[44] - X_t_pn1 = __ralloc.v1[45] - Y_t_pn1 = __ralloc.v1[46] - Z_t_pn1 = __ralloc.v1[47] - t31 = __ralloc.v1[48] - t32 = __ralloc.v1[49] - t33 = __ralloc.v1[50] - r_sin_ϕ = __ralloc.v1[51] - sin_ϕ = __ralloc.v1[52] - ϕ = __ralloc.v1[53] - cos_ϕ = __ralloc.v1[54] - sin2_ϕ = __ralloc.v1[55] - sin3_ϕ = __ralloc.v1[56] - F_J2_x = __ralloc.v1[57] - F_J2_y = __ralloc.v1[58] - F_J2_z = __ralloc.v1[59] - F_J2_x1 = __ralloc.v1[60] - F_J2_y1 = __ralloc.v1[61] - F_J2_z1 = __ralloc.v1[62] - F_J2_x2 = __ralloc.v1[63] - F_J2_y2 = __ralloc.v1[64] - F_J2_z2 = __ralloc.v1[65] - temp_accX_i = __ralloc.v1[66] - temp_accY_i = __ralloc.v1[67] - temp_accZ_i = __ralloc.v1[68] - P_2_sin_ϕ = __ralloc.v1[69] - ∂P_2_sin_ϕ = __ralloc.v1[70] - P_3_sin_ϕ = __ralloc.v1[71] - ∂P_3_sin_ϕ = __ralloc.v1[72] - m_c_ϕ_∂P_2 = __ralloc.v1[73] - m_c_ϕ_∂P_3 = __ralloc.v1[74] - Λ2j_div_r4 = __ralloc.v1[75] - Λ3j_div_r5 = __ralloc.v1[76] - F_J_ξ = __ralloc.v1[77] - F_J_ζ = __ralloc.v1[78] - F_J2_ξ = __ralloc.v1[79] - F_J2_ζ = __ralloc.v1[80] - F_J3_ξ = __ralloc.v1[81] - F_J3_ζ = __ralloc.v1[82] - ξx = __ralloc.v1[83] - ξy = __ralloc.v1[84] - ξz = __ralloc.v1[85] - ηx = __ralloc.v1[86] - ηy = __ralloc.v1[87] - ηz = __ralloc.v1[88] - ηx1 = __ralloc.v1[89] - ηy1 = __ralloc.v1[90] - ηz1 = __ralloc.v1[91] - ηx2 = __ralloc.v1[92] - ηy2 = __ralloc.v1[93] - ηz2 = __ralloc.v1[94] - ζx = __ralloc.v1[95] - ζy = __ralloc.v1[96] - ζz = __ralloc.v1[97] - ζx1 = __ralloc.v1[98] - ζy1 = __ralloc.v1[99] - ζz1 = __ralloc.v1[100] - ζx2 = __ralloc.v1[101] - ζy2 = __ralloc.v1[102] - ζz2 = __ralloc.v1[103] - tmp1317 = __ralloc.v1[104] - tmp1319 = __ralloc.v1[105] - tmp1322 = __ralloc.v1[106] - tmp1324 = __ralloc.v1[107] - tmp1327 = __ralloc.v1[108] - tmp1329 = __ralloc.v1[109] - pn2x = __ralloc.v1[110] - pn2y = __ralloc.v1[111] - pn2z = __ralloc.v1[112] - tmp1337 = __ralloc.v1[113] - tmp1340 = __ralloc.v1[114] - tmp1342 = __ralloc.v1[115] - tmp1343 = __ralloc.v1[116] - tmp1345 = __ralloc.v1[117] - tmp1353 = __ralloc.v1[118] - tmp1354 = __ralloc.v1[119] - tmp1365 = __ralloc.v1[120] - tmp1367 = __ralloc.v1[121] - tmp1369 = __ralloc.v1[122] - tmp1371 = __ralloc.v1[123] - tmp1528 = __ralloc.v1[124] - tmp1529 = __ralloc.v1[125] - tmp1381 = __ralloc.v1[126] - tmp1387 = __ralloc.v1[127] - tmp1389 = __ralloc.v1[128] - tmp1393 = __ralloc.v1[129] - tmp1396 = __ralloc.v1[130] - tmp1397 = __ralloc.v1[131] - tmp1400 = __ralloc.v1[132] - tmp1401 = __ralloc.v1[133] - tmp1403 = __ralloc.v1[134] - tmp1405 = __ralloc.v1[135] - tmp1408 = __ralloc.v1[136] - tmp1412 = __ralloc.v1[137] - tmp1415 = __ralloc.v1[138] - tmp1417 = __ralloc.v1[139] - tmp1419 = __ralloc.v1[140] - tmp1449 = __ralloc.v1[141] - tmp1451 = __ralloc.v1[142] - tmp1452 = __ralloc.v1[143] - tmp1454 = __ralloc.v1[144] - temp_004 = __ralloc.v1[145] - tmp1465 = __ralloc.v1[146] - tmp1467 = __ralloc.v1[147] - tmp1469 = __ralloc.v1[148] - tmp1475 = __ralloc.v1[149] - tmp1477 = __ralloc.v1[150] - tmp1478 = __ralloc.v1[151] - Xij_t_Ui = __ralloc.v1[152] - Yij_t_Vi = __ralloc.v1[153] - Zij_t_Wi = __ralloc.v1[154] - tmp1484 = __ralloc.v1[155] - Rij_dot_Vi = __ralloc.v1[156] - tmp1487 = __ralloc.v1[157] - pn1t7 = __ralloc.v1[158] - tmp1490 = __ralloc.v1[159] - pn1t2_7 = __ralloc.v1[160] - tmp1497 = __ralloc.v1[161] - tmp1498 = __ralloc.v1[162] - tmp1499 = __ralloc.v1[163] - tmp1507 = __ralloc.v1[164] - termpnx = __ralloc.v1[165] - sumpnx = __ralloc.v1[166] - tmp1510 = __ralloc.v1[167] - termpny = __ralloc.v1[168] - sumpny = __ralloc.v1[169] - tmp1513 = __ralloc.v1[170] - termpnz = __ralloc.v1[171] - sumpnz = __ralloc.v1[172] + _4dq = __ralloc.v1[15] + _4U_m_3X = __ralloc.v1[16] + _4V_m_3Y = __ralloc.v1[17] + _4W_m_3Z = __ralloc.v1[18] + UU = __ralloc.v1[19] + VV = __ralloc.v1[20] + WW = __ralloc.v1[21] + newtonian1b_Potential = __ralloc.v1[22] + newtonianNb_Potential = __ralloc.v1[23] + newton_acc_X = __ralloc.v1[24] + newton_acc_Y = __ralloc.v1[25] + newton_acc_Z = __ralloc.v1[26] + v2 = __ralloc.v1[27] + vi_dot_vj = __ralloc.v1[28] + pn2 = __ralloc.v1[29] + U_t_pn2 = __ralloc.v1[30] + V_t_pn2 = __ralloc.v1[31] + W_t_pn2 = __ralloc.v1[32] + pn3 = __ralloc.v1[33] + pNX_t_pn3 = __ralloc.v1[34] + pNY_t_pn3 = __ralloc.v1[35] + pNZ_t_pn3 = __ralloc.v1[36] + _4ϕj = __ralloc.v1[37] + ϕi_plus_4ϕj = __ralloc.v1[38] + sj2_plus_2si2_minus_4vivj = __ralloc.v1[39] + ϕs_and_vs = __ralloc.v1[40] + pn1t1_7 = __ralloc.v1[41] + pNX_t_X = __ralloc.v1[42] + pNY_t_Y = __ralloc.v1[43] + pNZ_t_Z = __ralloc.v1[44] + pn1 = __ralloc.v1[45] + X_t_pn1 = __ralloc.v1[46] + Y_t_pn1 = __ralloc.v1[47] + Z_t_pn1 = __ralloc.v1[48] + t31 = __ralloc.v1[49] + t32 = __ralloc.v1[50] + t33 = __ralloc.v1[51] + r_sin_ϕ = __ralloc.v1[52] + sin_ϕ = __ralloc.v1[53] + ϕ = __ralloc.v1[54] + cos_ϕ = __ralloc.v1[55] + sin2_ϕ = __ralloc.v1[56] + sin3_ϕ = __ralloc.v1[57] + F_J2_x = __ralloc.v1[58] + F_J2_y = __ralloc.v1[59] + F_J2_z = __ralloc.v1[60] + F_J2_x1 = __ralloc.v1[61] + F_J2_y1 = __ralloc.v1[62] + F_J2_z1 = __ralloc.v1[63] + F_J2_x2 = __ralloc.v1[64] + F_J2_y2 = __ralloc.v1[65] + F_J2_z2 = __ralloc.v1[66] + temp_accX_i = __ralloc.v1[67] + temp_accY_i = __ralloc.v1[68] + temp_accZ_i = __ralloc.v1[69] + P_2_sin_ϕ = __ralloc.v1[70] + ∂P_2_sin_ϕ = __ralloc.v1[71] + P_3_sin_ϕ = __ralloc.v1[72] + ∂P_3_sin_ϕ = __ralloc.v1[73] + m_c_ϕ_∂P_2 = __ralloc.v1[74] + m_c_ϕ_∂P_3 = __ralloc.v1[75] + Λ2j_div_r4 = __ralloc.v1[76] + Λ3j_div_r5 = __ralloc.v1[77] + F_J_ξ = __ralloc.v1[78] + F_J_ζ = __ralloc.v1[79] + F_J2_ξ = __ralloc.v1[80] + F_J2_ζ = __ralloc.v1[81] + F_J3_ξ = __ralloc.v1[82] + F_J3_ζ = __ralloc.v1[83] + ξx = __ralloc.v1[84] + ξy = __ralloc.v1[85] + ξz = __ralloc.v1[86] + ηx = __ralloc.v1[87] + ηy = __ralloc.v1[88] + ηz = __ralloc.v1[89] + ηx1 = __ralloc.v1[90] + ηy1 = __ralloc.v1[91] + ηz1 = __ralloc.v1[92] + ηx2 = __ralloc.v1[93] + ηy2 = __ralloc.v1[94] + ηz2 = __ralloc.v1[95] + ζx = __ralloc.v1[96] + ζy = __ralloc.v1[97] + ζz = __ralloc.v1[98] + ζx1 = __ralloc.v1[99] + ζy1 = __ralloc.v1[100] + ζz1 = __ralloc.v1[101] + ζx2 = __ralloc.v1[102] + ζy2 = __ralloc.v1[103] + ζz2 = __ralloc.v1[104] + tmp6194 = __ralloc.v1[105] + tmp6197 = __ralloc.v1[106] + tmp6200 = __ralloc.v1[107] + pn2x = __ralloc.v1[108] + pn2y = __ralloc.v1[109] + pn2z = __ralloc.v1[110] + tmp6208 = __ralloc.v1[111] + tmp6211 = __ralloc.v1[112] + tmp6213 = __ralloc.v1[113] + tmp6214 = __ralloc.v1[114] + tmp6216 = __ralloc.v1[115] + tmp6224 = __ralloc.v1[116] + tmp6225 = __ralloc.v1[117] + tmp6236 = __ralloc.v1[118] + tmp6238 = __ralloc.v1[119] + tmp6240 = __ralloc.v1[120] + tmp6242 = __ralloc.v1[121] + tmp6399 = __ralloc.v1[122] + tmp6400 = __ralloc.v1[123] + tmp6252 = __ralloc.v1[124] + tmp6258 = __ralloc.v1[125] + tmp6260 = __ralloc.v1[126] + tmp6264 = __ralloc.v1[127] + tmp6267 = __ralloc.v1[128] + tmp6268 = __ralloc.v1[129] + tmp6271 = __ralloc.v1[130] + tmp6272 = __ralloc.v1[131] + tmp6274 = __ralloc.v1[132] + tmp6276 = __ralloc.v1[133] + tmp6279 = __ralloc.v1[134] + tmp6283 = __ralloc.v1[135] + tmp6286 = __ralloc.v1[136] + tmp6288 = __ralloc.v1[137] + tmp6290 = __ralloc.v1[138] + tmp6320 = __ralloc.v1[139] + tmp6322 = __ralloc.v1[140] + tmp6323 = __ralloc.v1[141] + tmp6325 = __ralloc.v1[142] + temp_004 = __ralloc.v1[143] + tmp6336 = __ralloc.v1[144] + tmp6338 = __ralloc.v1[145] + tmp6340 = __ralloc.v1[146] + tmp6346 = __ralloc.v1[147] + tmp6348 = __ralloc.v1[148] + tmp6349 = __ralloc.v1[149] + Xij_t_Ui = __ralloc.v1[150] + Yij_t_Vi = __ralloc.v1[151] + Zij_t_Wi = __ralloc.v1[152] + tmp6355 = __ralloc.v1[153] + Rij_dot_Vi = __ralloc.v1[154] + tmp6358 = __ralloc.v1[155] + pn1t7 = __ralloc.v1[156] + tmp6361 = __ralloc.v1[157] + pn1t2_7 = __ralloc.v1[158] + tmp6368 = __ralloc.v1[159] + tmp6369 = __ralloc.v1[160] + tmp6370 = __ralloc.v1[161] + tmp6378 = __ralloc.v1[162] + termpnx = __ralloc.v1[163] + sumpnx = __ralloc.v1[164] + tmp6381 = __ralloc.v1[165] + termpny = __ralloc.v1[166] + sumpny = __ralloc.v1[167] + tmp6384 = __ralloc.v1[168] + termpnz = __ralloc.v1[169] + sumpnz = __ralloc.v1[170] local jd0 = params[4] local dsj2k = t + (jd0 - JD_J2000) local ss16asteph_t = evaleph(params[1], dsj2k, q[1]) @@ -2314,447 +2567,446 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, local Nm1 = N - 1 local μ = params[7] local zero_q_1 = auxzero(q[1]) + TaylorSeries.zero!(pntempX) pntempX.coeffs[1] = identity(constant_term(zero_q_1)) - pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) + TaylorSeries.zero!(pntempY) pntempY.coeffs[1] = identity(constant_term(zero_q_1)) - pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) + TaylorSeries.zero!(pntempZ) pntempZ.coeffs[1] = identity(constant_term(zero_q_1)) - pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) + TaylorSeries.zero!(accX) accX.coeffs[1] = identity(constant_term(zero_q_1)) - accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) + TaylorSeries.zero!(accY) accY.coeffs[1] = identity(constant_term(zero_q_1)) - accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) + TaylorSeries.zero!(accZ) accZ.coeffs[1] = identity(constant_term(zero_q_1)) - accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) local M_ = Array{S}(undef, 3, 3, N) - local M_ .= zero_q_1 - local M_[:, :, ea] .= (t2c_jpl_de430(dsj2k))[:, :] .+ zero_q_1 + local M_[:, :, ea] = t2c_jpl_de430(dsj2k) .+ zero_q_1 + TaylorSeries.zero!(dq[1]) (dq[1]).coeffs[1] = identity(constant_term(q[4])) - (dq[1]).coeffs[2:order + 1] .= zero((dq[1]).coeffs[1]) + TaylorSeries.zero!(dq[2]) (dq[2]).coeffs[1] = identity(constant_term(q[5])) - (dq[2]).coeffs[2:order + 1] .= zero((dq[2]).coeffs[1]) + TaylorSeries.zero!(dq[3]) (dq[3]).coeffs[1] = identity(constant_term(q[6])) - (dq[3]).coeffs[2:order + 1] .= zero((dq[3]).coeffs[1]) + TaylorSeries.zero!(newtonianNb_Potential[N]) (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(zero_q_1)) - (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 + TaylorSeries.zero!(_4dq[1]) + (_4dq[1]).coeffs[1] = constant_term(4) * constant_term(dq[1]) + TaylorSeries.zero!(_4dq[2]) + (_4dq[2]).coeffs[1] = constant_term(4) * constant_term(dq[2]) + TaylorSeries.zero!(_4dq[3]) + (_4dq[3]).coeffs[1] = constant_term(4) * constant_term(dq[3]) + #= /Users/Jorge/projects/neos240702/neosjetcoeffs.jl:829 =# Threads.@threads for i = 1:Nm1 + TaylorSeries.zero!(ui[i]) (ui[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 2])) - (ui[i]).coeffs[2:order + 1] .= zero((ui[i]).coeffs[1]) + TaylorSeries.zero!(vi[i]) (vi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i) - 1])) - (vi[i]).coeffs[2:order + 1] .= zero((vi[i]).coeffs[1]) + TaylorSeries.zero!(wi[i]) (wi[i]).coeffs[1] = identity(constant_term(ss16asteph_t[3 * ((N - 1) + i)])) - (wi[i]).coeffs[2:order + 1] .= zero((wi[i]).coeffs[1]) + TaylorSeries.zero!(X[i]) (X[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 2]) - constant_term(q[1]) - (X[i]).coeffs[2:order + 1] .= zero((X[i]).coeffs[1]) + TaylorSeries.zero!(Y[i]) (Y[i]).coeffs[1] = constant_term(ss16asteph_t[3i - 1]) - constant_term(q[2]) - (Y[i]).coeffs[2:order + 1] .= zero((Y[i]).coeffs[1]) + TaylorSeries.zero!(Z[i]) (Z[i]).coeffs[1] = constant_term(ss16asteph_t[3i]) - constant_term(q[3]) - (Z[i]).coeffs[2:order + 1] .= zero((Z[i]).coeffs[1]) + TaylorSeries.zero!(U[i]) (U[i]).coeffs[1] = constant_term(ui[i]) - constant_term(dq[1]) - (U[i]).coeffs[2:order + 1] .= zero((U[i]).coeffs[1]) + TaylorSeries.zero!(V[i]) (V[i]).coeffs[1] = constant_term(vi[i]) - constant_term(dq[2]) - (V[i]).coeffs[2:order + 1] .= zero((V[i]).coeffs[1]) + TaylorSeries.zero!(W[i]) (W[i]).coeffs[1] = constant_term(wi[i]) - constant_term(dq[3]) - (W[i]).coeffs[2:order + 1] .= zero((W[i]).coeffs[1]) - (tmp1317[1]).coeffs[1] = constant_term(4) * constant_term(dq[1]) - (tmp1317[1]).coeffs[2:order + 1] .= zero((tmp1317[1]).coeffs[1]) - (tmp1319[i]).coeffs[1] = constant_term(3) * constant_term(ui[i]) - (tmp1319[i]).coeffs[2:order + 1] .= zero((tmp1319[i]).coeffs[1]) - (_4U_m_3X[i]).coeffs[1] = constant_term(tmp1317[1]) - constant_term(tmp1319[i]) - (_4U_m_3X[i]).coeffs[2:order + 1] .= zero((_4U_m_3X[i]).coeffs[1]) - (tmp1322[2]).coeffs[1] = constant_term(4) * constant_term(dq[2]) - (tmp1322[2]).coeffs[2:order + 1] .= zero((tmp1322[2]).coeffs[1]) - (tmp1324[i]).coeffs[1] = constant_term(3) * constant_term(vi[i]) - (tmp1324[i]).coeffs[2:order + 1] .= zero((tmp1324[i]).coeffs[1]) - (_4V_m_3Y[i]).coeffs[1] = constant_term(tmp1322[2]) - constant_term(tmp1324[i]) - (_4V_m_3Y[i]).coeffs[2:order + 1] .= zero((_4V_m_3Y[i]).coeffs[1]) - (tmp1327[3]).coeffs[1] = constant_term(4) * constant_term(dq[3]) - (tmp1327[3]).coeffs[2:order + 1] .= zero((tmp1327[3]).coeffs[1]) - (tmp1329[i]).coeffs[1] = constant_term(3) * constant_term(wi[i]) - (tmp1329[i]).coeffs[2:order + 1] .= zero((tmp1329[i]).coeffs[1]) - (_4W_m_3Z[i]).coeffs[1] = constant_term(tmp1327[3]) - constant_term(tmp1329[i]) - (_4W_m_3Z[i]).coeffs[2:order + 1] .= zero((_4W_m_3Z[i]).coeffs[1]) + TaylorSeries.zero!(tmp6194[i]) + (tmp6194[i]).coeffs[1] = constant_term(-3) * constant_term(ui[i]) + TaylorSeries.zero!(_4U_m_3X[i]) + (_4U_m_3X[i]).coeffs[1] = constant_term(tmp6194[i]) + constant_term(_4dq[1]) + TaylorSeries.zero!(tmp6197[i]) + (tmp6197[i]).coeffs[1] = constant_term(-3) * constant_term(vi[i]) + TaylorSeries.zero!(_4V_m_3Y[i]) + (_4V_m_3Y[i]).coeffs[1] = constant_term(tmp6197[i]) + constant_term(_4dq[2]) + TaylorSeries.zero!(tmp6200[i]) + (tmp6200[i]).coeffs[1] = constant_term(-3) * constant_term(wi[i]) + TaylorSeries.zero!(_4W_m_3Z[i]) + (_4W_m_3Z[i]).coeffs[1] = constant_term(tmp6200[i]) + constant_term(_4dq[3]) + TaylorSeries.zero!(pn2x[i]) (pn2x[i]).coeffs[1] = constant_term(X[i]) * constant_term(_4U_m_3X[i]) - (pn2x[i]).coeffs[2:order + 1] .= zero((pn2x[i]).coeffs[1]) + TaylorSeries.zero!(pn2y[i]) (pn2y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(_4V_m_3Y[i]) - (pn2y[i]).coeffs[2:order + 1] .= zero((pn2y[i]).coeffs[1]) + TaylorSeries.zero!(pn2z[i]) (pn2z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(_4W_m_3Z[i]) - (pn2z[i]).coeffs[2:order + 1] .= zero((pn2z[i]).coeffs[1]) + TaylorSeries.zero!(UU[i]) (UU[i]).coeffs[1] = constant_term(ui[i]) * constant_term(dq[1]) - (UU[i]).coeffs[2:order + 1] .= zero((UU[i]).coeffs[1]) + TaylorSeries.zero!(VV[i]) (VV[i]).coeffs[1] = constant_term(vi[i]) * constant_term(dq[2]) - (VV[i]).coeffs[2:order + 1] .= zero((VV[i]).coeffs[1]) + TaylorSeries.zero!(WW[i]) (WW[i]).coeffs[1] = constant_term(wi[i]) * constant_term(dq[3]) - (WW[i]).coeffs[2:order + 1] .= zero((WW[i]).coeffs[1]) - (tmp1337[i]).coeffs[1] = constant_term(UU[i]) + constant_term(VV[i]) - (tmp1337[i]).coeffs[2:order + 1] .= zero((tmp1337[i]).coeffs[1]) - (vi_dot_vj[i]).coeffs[1] = constant_term(tmp1337[i]) + constant_term(WW[i]) - (vi_dot_vj[i]).coeffs[2:order + 1] .= zero((vi_dot_vj[i]).coeffs[1]) - (tmp1340[i]).coeffs[1] = constant_term(X[i]) ^ float(constant_term(2)) - (tmp1340[i]).coeffs[2:order + 1] .= zero((tmp1340[i]).coeffs[1]) - (tmp1342[i]).coeffs[1] = constant_term(Y[i]) ^ float(constant_term(2)) - (tmp1342[i]).coeffs[2:order + 1] .= zero((tmp1342[i]).coeffs[1]) - (tmp1343[i]).coeffs[1] = constant_term(tmp1340[i]) + constant_term(tmp1342[i]) - (tmp1343[i]).coeffs[2:order + 1] .= zero((tmp1343[i]).coeffs[1]) - (tmp1345[i]).coeffs[1] = constant_term(Z[i]) ^ float(constant_term(2)) - (tmp1345[i]).coeffs[2:order + 1] .= zero((tmp1345[i]).coeffs[1]) - (r_p2[i]).coeffs[1] = constant_term(tmp1343[i]) + constant_term(tmp1345[i]) - (r_p2[i]).coeffs[2:order + 1] .= zero((r_p2[i]).coeffs[1]) + TaylorSeries.zero!(tmp6208[i]) + (tmp6208[i]).coeffs[1] = constant_term(UU[i]) + constant_term(VV[i]) + TaylorSeries.zero!(vi_dot_vj[i]) + (vi_dot_vj[i]).coeffs[1] = constant_term(tmp6208[i]) + constant_term(WW[i]) + TaylorSeries.zero!(tmp6211[i]) + (tmp6211[i]).coeffs[1] = constant_term(X[i]) ^ float(constant_term(2)) + TaylorSeries.zero!(tmp6213[i]) + (tmp6213[i]).coeffs[1] = constant_term(Y[i]) ^ float(constant_term(2)) + TaylorSeries.zero!(tmp6214[i]) + (tmp6214[i]).coeffs[1] = constant_term(tmp6211[i]) + constant_term(tmp6213[i]) + TaylorSeries.zero!(tmp6216[i]) + (tmp6216[i]).coeffs[1] = constant_term(Z[i]) ^ float(constant_term(2)) + TaylorSeries.zero!(r_p2[i]) + (r_p2[i]).coeffs[1] = constant_term(tmp6214[i]) + constant_term(tmp6216[i]) + TaylorSeries.zero!(r_p1d2[i]) (r_p1d2[i]).coeffs[1] = sqrt(constant_term(r_p2[i])) - (r_p1d2[i]).coeffs[2:order + 1] .= zero((r_p1d2[i]).coeffs[1]) + TaylorSeries.zero!(r_p3d2[i]) (r_p3d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(1.5)) - (r_p3d2[i]).coeffs[2:order + 1] .= zero((r_p3d2[i]).coeffs[1]) + TaylorSeries.zero!(r_p7d2[i]) (r_p7d2[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(3.5)) - (r_p7d2[i]).coeffs[2:order + 1] .= zero((r_p7d2[i]).coeffs[1]) + TaylorSeries.zero!(newtonianCoeff[i]) (newtonianCoeff[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p3d2[i]) - (newtonianCoeff[i]).coeffs[2:order + 1] .= zero((newtonianCoeff[i]).coeffs[1]) - (tmp1353[i]).coeffs[1] = constant_term(pn2x[i]) + constant_term(pn2y[i]) - (tmp1353[i]).coeffs[2:order + 1] .= zero((tmp1353[i]).coeffs[1]) - (tmp1354[i]).coeffs[1] = constant_term(tmp1353[i]) + constant_term(pn2z[i]) - (tmp1354[i]).coeffs[2:order + 1] .= zero((tmp1354[i]).coeffs[1]) - (pn2[i]).coeffs[1] = constant_term(newtonianCoeff[i]) * constant_term(tmp1354[i]) - (pn2[i]).coeffs[2:order + 1] .= zero((pn2[i]).coeffs[1]) + TaylorSeries.zero!(tmp6224[i]) + (tmp6224[i]).coeffs[1] = constant_term(pn2x[i]) + constant_term(pn2y[i]) + TaylorSeries.zero!(tmp6225[i]) + (tmp6225[i]).coeffs[1] = constant_term(tmp6224[i]) + constant_term(pn2z[i]) + TaylorSeries.zero!(pn2[i]) + (pn2[i]).coeffs[1] = constant_term(newtonianCoeff[i]) * constant_term(tmp6225[i]) + TaylorSeries.zero!(newton_acc_X[i]) (newton_acc_X[i]).coeffs[1] = constant_term(X[i]) * constant_term(newtonianCoeff[i]) - (newton_acc_X[i]).coeffs[2:order + 1] .= zero((newton_acc_X[i]).coeffs[1]) + TaylorSeries.zero!(newton_acc_Y[i]) (newton_acc_Y[i]).coeffs[1] = constant_term(Y[i]) * constant_term(newtonianCoeff[i]) - (newton_acc_Y[i]).coeffs[2:order + 1] .= zero((newton_acc_Y[i]).coeffs[1]) + TaylorSeries.zero!(newton_acc_Z[i]) (newton_acc_Z[i]).coeffs[1] = constant_term(Z[i]) * constant_term(newtonianCoeff[i]) - (newton_acc_Z[i]).coeffs[2:order + 1] .= zero((newton_acc_Z[i]).coeffs[1]) + TaylorSeries.zero!(newtonian1b_Potential[i]) (newtonian1b_Potential[i]).coeffs[1] = constant_term(μ[i]) / constant_term(r_p1d2[i]) - (newtonian1b_Potential[i]).coeffs[2:order + 1] .= zero((newtonian1b_Potential[i]).coeffs[1]) + TaylorSeries.zero!(pn3[i]) (pn3[i]).coeffs[1] = constant_term(3.5) * constant_term(newtonian1b_Potential[i]) - (pn3[i]).coeffs[2:order + 1] .= zero((pn3[i]).coeffs[1]) + TaylorSeries.zero!(U_t_pn2[i]) (U_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(U[i]) - (U_t_pn2[i]).coeffs[2:order + 1] .= zero((U_t_pn2[i]).coeffs[1]) + TaylorSeries.zero!(V_t_pn2[i]) (V_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(V[i]) - (V_t_pn2[i]).coeffs[2:order + 1] .= zero((V_t_pn2[i]).coeffs[1]) + TaylorSeries.zero!(W_t_pn2[i]) (W_t_pn2[i]).coeffs[1] = constant_term(pn2[i]) * constant_term(W[i]) - (W_t_pn2[i]).coeffs[2:order + 1] .= zero((W_t_pn2[i]).coeffs[1]) if UJ_interaction[i] - (tmp1365[i]).coeffs[1] = -(constant_term(X[i])) - (tmp1365[i]).coeffs[2:order + 1] .= zero((tmp1365[i]).coeffs[1]) - (t31[i]).coeffs[1] = constant_term(tmp1365[i]) * constant_term(M_[1, 3, i]) - (t31[i]).coeffs[2:order + 1] .= zero((t31[i]).coeffs[1]) - (tmp1367[i]).coeffs[1] = -(constant_term(Y[i])) - (tmp1367[i]).coeffs[2:order + 1] .= zero((tmp1367[i]).coeffs[1]) - (t32[i]).coeffs[1] = constant_term(tmp1367[i]) * constant_term(M_[2, 3, i]) - (t32[i]).coeffs[2:order + 1] .= zero((t32[i]).coeffs[1]) - (tmp1369[i]).coeffs[1] = -(constant_term(Z[i])) - (tmp1369[i]).coeffs[2:order + 1] .= zero((tmp1369[i]).coeffs[1]) - (t33[i]).coeffs[1] = constant_term(tmp1369[i]) * constant_term(M_[3, 3, i]) - (t33[i]).coeffs[2:order + 1] .= zero((t33[i]).coeffs[1]) - (tmp1371[i]).coeffs[1] = constant_term(t31[i]) + constant_term(t32[i]) - (tmp1371[i]).coeffs[2:order + 1] .= zero((tmp1371[i]).coeffs[1]) - (r_sin_ϕ[i]).coeffs[1] = constant_term(tmp1371[i]) + constant_term(t33[i]) - (r_sin_ϕ[i]).coeffs[2:order + 1] .= zero((r_sin_ϕ[i]).coeffs[1]) + TaylorSeries.zero!(tmp6236[i]) + (tmp6236[i]).coeffs[1] = -(constant_term(X[i])) + TaylorSeries.zero!(t31[i]) + (t31[i]).coeffs[1] = constant_term(tmp6236[i]) * constant_term(M_[1, 3, i]) + TaylorSeries.zero!(tmp6238[i]) + (tmp6238[i]).coeffs[1] = -(constant_term(Y[i])) + TaylorSeries.zero!(t32[i]) + (t32[i]).coeffs[1] = constant_term(tmp6238[i]) * constant_term(M_[2, 3, i]) + TaylorSeries.zero!(tmp6240[i]) + (tmp6240[i]).coeffs[1] = -(constant_term(Z[i])) + TaylorSeries.zero!(t33[i]) + (t33[i]).coeffs[1] = constant_term(tmp6240[i]) * constant_term(M_[3, 3, i]) + TaylorSeries.zero!(tmp6242[i]) + (tmp6242[i]).coeffs[1] = constant_term(t31[i]) + constant_term(t32[i]) + TaylorSeries.zero!(r_sin_ϕ[i]) + (r_sin_ϕ[i]).coeffs[1] = constant_term(tmp6242[i]) + constant_term(t33[i]) + TaylorSeries.zero!(sin_ϕ[i]) (sin_ϕ[i]).coeffs[1] = constant_term(r_sin_ϕ[i]) / constant_term(r_p1d2[i]) - (sin_ϕ[i]).coeffs[2:order + 1] .= zero((sin_ϕ[i]).coeffs[1]) + TaylorSeries.zero!(ϕ[i]) (ϕ[i]).coeffs[1] = asin(constant_term(sin_ϕ[i])) - (ϕ[i]).coeffs[2:order + 1] .= zero((ϕ[i]).coeffs[1]) - (tmp1528[i]).coeffs[1] = sqrt(1 - constant_term(sin_ϕ[i]) ^ 2) - (tmp1528[i]).coeffs[2:order + 1] .= zero((tmp1528[i]).coeffs[1]) + TaylorSeries.zero!(tmp6399[i]) + (tmp6399[i]).coeffs[1] = sqrt(1 - constant_term(sin_ϕ[i]) ^ 2) + TaylorSeries.zero!(cos_ϕ[i]) (cos_ϕ[i]).coeffs[1] = cos(constant_term(ϕ[i])) - (cos_ϕ[i]).coeffs[2:order + 1] .= zero((cos_ϕ[i]).coeffs[1]) - (tmp1529[i]).coeffs[1] = sin(constant_term(ϕ[i])) - (tmp1529[i]).coeffs[2:order + 1] .= zero((tmp1529[i]).coeffs[1]) + TaylorSeries.zero!(tmp6400[i]) + (tmp6400[i]).coeffs[1] = sin(constant_term(ϕ[i])) + TaylorSeries.zero!(sin2_ϕ[i]) (sin2_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(2)) - (sin2_ϕ[i]).coeffs[2:order + 1] .= zero((sin2_ϕ[i]).coeffs[1]) + TaylorSeries.zero!(sin3_ϕ[i]) (sin3_ϕ[i]).coeffs[1] = constant_term(sin_ϕ[i]) ^ float(constant_term(3)) - (sin3_ϕ[i]).coeffs[2:order + 1] .= zero((sin3_ϕ[i]).coeffs[1]) - (tmp1381[i]).coeffs[1] = constant_term(1.5) * constant_term(sin2_ϕ[i]) - (tmp1381[i]).coeffs[2:order + 1] .= zero((tmp1381[i]).coeffs[1]) - (P_2_sin_ϕ[i]).coeffs[1] = constant_term(tmp1381[i]) - constant_term(0.5) - (P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_2_sin_ϕ[i]).coeffs[1]) + TaylorSeries.zero!(tmp6252[i]) + (tmp6252[i]).coeffs[1] = constant_term(1.5) * constant_term(sin2_ϕ[i]) + TaylorSeries.zero!(P_2_sin_ϕ[i]) + (P_2_sin_ϕ[i]).coeffs[1] = constant_term(tmp6252[i]) - constant_term(0.5) + TaylorSeries.zero!(∂P_2_sin_ϕ[i]) (∂P_2_sin_ϕ[i]).coeffs[1] = constant_term(3) * constant_term(sin_ϕ[i]) - (∂P_2_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_2_sin_ϕ[i]).coeffs[1]) - (tmp1387[i]).coeffs[1] = constant_term(-1.5) * constant_term(sin_ϕ[i]) - (tmp1387[i]).coeffs[2:order + 1] .= zero((tmp1387[i]).coeffs[1]) - (tmp1389[i]).coeffs[1] = constant_term(2.5) * constant_term(sin3_ϕ[i]) - (tmp1389[i]).coeffs[2:order + 1] .= zero((tmp1389[i]).coeffs[1]) - (P_3_sin_ϕ[i]).coeffs[1] = constant_term(tmp1387[i]) + constant_term(tmp1389[i]) - (P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((P_3_sin_ϕ[i]).coeffs[1]) - (tmp1393[i]).coeffs[1] = constant_term(7.5) * constant_term(sin2_ϕ[i]) - (tmp1393[i]).coeffs[2:order + 1] .= zero((tmp1393[i]).coeffs[1]) - (∂P_3_sin_ϕ[i]).coeffs[1] = constant_term(-1.5) + constant_term(tmp1393[i]) - (∂P_3_sin_ϕ[i]).coeffs[2:order + 1] .= zero((∂P_3_sin_ϕ[i]).coeffs[1]) - (tmp1396[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(2)) - (tmp1396[i]).coeffs[2:order + 1] .= zero((tmp1396[i]).coeffs[1]) - (tmp1397[i]).coeffs[1] = constant_term(Λ2[i]) / constant_term(tmp1396[i]) - (tmp1397[i]).coeffs[2:order + 1] .= zero((tmp1397[i]).coeffs[1]) - (Λ2j_div_r4[i]).coeffs[1] = -(constant_term(tmp1397[i])) - (Λ2j_div_r4[i]).coeffs[2:order + 1] .= zero((Λ2j_div_r4[i]).coeffs[1]) - (tmp1400[i]).coeffs[1] = constant_term(r_p1d2[i]) ^ float(constant_term(5)) - (tmp1400[i]).coeffs[2:order + 1] .= zero((tmp1400[i]).coeffs[1]) - (tmp1401[i]).coeffs[1] = constant_term(Λ3[i]) / constant_term(tmp1400[i]) - (tmp1401[i]).coeffs[2:order + 1] .= zero((tmp1401[i]).coeffs[1]) - (Λ3j_div_r5[i]).coeffs[1] = -(constant_term(tmp1401[i])) - (Λ3j_div_r5[i]).coeffs[2:order + 1] .= zero((Λ3j_div_r5[i]).coeffs[1]) - (tmp1403[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) - (tmp1403[i]).coeffs[2:order + 1] .= zero((tmp1403[i]).coeffs[1]) - (m_c_ϕ_∂P_2[i]).coeffs[1] = constant_term(tmp1403[i]) * constant_term(∂P_2_sin_ϕ[i]) - (m_c_ϕ_∂P_2[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_2[i]).coeffs[1]) - (tmp1405[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) - (tmp1405[i]).coeffs[2:order + 1] .= zero((tmp1405[i]).coeffs[1]) - (m_c_ϕ_∂P_3[i]).coeffs[1] = constant_term(tmp1405[i]) * constant_term(∂P_3_sin_ϕ[i]) - (m_c_ϕ_∂P_3[i]).coeffs[2:order + 1] .= zero((m_c_ϕ_∂P_3[i]).coeffs[1]) - (tmp1408[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(3) - (tmp1408[i]).coeffs[2:order + 1] .= zero((tmp1408[i]).coeffs[1]) - (F_J2_ξ[i]).coeffs[1] = constant_term(tmp1408[i]) * constant_term(P_2_sin_ϕ[i]) - (F_J2_ξ[i]).coeffs[2:order + 1] .= zero((F_J2_ξ[i]).coeffs[1]) + TaylorSeries.zero!(tmp6258[i]) + (tmp6258[i]).coeffs[1] = constant_term(-1.5) * constant_term(sin_ϕ[i]) + TaylorSeries.zero!(tmp6260[i]) + (tmp6260[i]).coeffs[1] = constant_term(2.5) * constant_term(sin3_ϕ[i]) + TaylorSeries.zero!(P_3_sin_ϕ[i]) + (P_3_sin_ϕ[i]).coeffs[1] = constant_term(tmp6258[i]) + constant_term(tmp6260[i]) + TaylorSeries.zero!(tmp6264[i]) + (tmp6264[i]).coeffs[1] = constant_term(7.5) * constant_term(sin2_ϕ[i]) + TaylorSeries.zero!(∂P_3_sin_ϕ[i]) + (∂P_3_sin_ϕ[i]).coeffs[1] = constant_term(-1.5) + constant_term(tmp6264[i]) + TaylorSeries.zero!(tmp6267[i]) + (tmp6267[i]).coeffs[1] = constant_term(r_p2[i]) ^ float(constant_term(2)) + TaylorSeries.zero!(tmp6268[i]) + (tmp6268[i]).coeffs[1] = constant_term(Λ2[i]) / constant_term(tmp6267[i]) + TaylorSeries.zero!(Λ2j_div_r4[i]) + (Λ2j_div_r4[i]).coeffs[1] = -(constant_term(tmp6268[i])) + TaylorSeries.zero!(tmp6271[i]) + (tmp6271[i]).coeffs[1] = constant_term(r_p1d2[i]) ^ float(constant_term(5)) + TaylorSeries.zero!(tmp6272[i]) + (tmp6272[i]).coeffs[1] = constant_term(Λ3[i]) / constant_term(tmp6271[i]) + TaylorSeries.zero!(Λ3j_div_r5[i]) + (Λ3j_div_r5[i]).coeffs[1] = -(constant_term(tmp6272[i])) + TaylorSeries.zero!(tmp6274[i]) + (tmp6274[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) + TaylorSeries.zero!(m_c_ϕ_∂P_2[i]) + (m_c_ϕ_∂P_2[i]).coeffs[1] = constant_term(tmp6274[i]) * constant_term(∂P_2_sin_ϕ[i]) + TaylorSeries.zero!(tmp6276[i]) + (tmp6276[i]).coeffs[1] = -(constant_term(cos_ϕ[i])) + TaylorSeries.zero!(m_c_ϕ_∂P_3[i]) + (m_c_ϕ_∂P_3[i]).coeffs[1] = constant_term(tmp6276[i]) * constant_term(∂P_3_sin_ϕ[i]) + TaylorSeries.zero!(tmp6279[i]) + (tmp6279[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(3) + TaylorSeries.zero!(F_J2_ξ[i]) + (F_J2_ξ[i]).coeffs[1] = constant_term(tmp6279[i]) * constant_term(P_2_sin_ϕ[i]) + TaylorSeries.zero!(F_J2_ζ[i]) (F_J2_ζ[i]).coeffs[1] = constant_term(Λ2j_div_r4[i]) * constant_term(m_c_ϕ_∂P_2[i]) - (F_J2_ζ[i]).coeffs[2:order + 1] .= zero((F_J2_ζ[i]).coeffs[1]) - (tmp1412[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(4) - (tmp1412[i]).coeffs[2:order + 1] .= zero((tmp1412[i]).coeffs[1]) - (F_J3_ξ[i]).coeffs[1] = constant_term(tmp1412[i]) * constant_term(P_3_sin_ϕ[i]) - (F_J3_ξ[i]).coeffs[2:order + 1] .= zero((F_J3_ξ[i]).coeffs[1]) + TaylorSeries.zero!(tmp6283[i]) + (tmp6283[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(4) + TaylorSeries.zero!(F_J3_ξ[i]) + (F_J3_ξ[i]).coeffs[1] = constant_term(tmp6283[i]) * constant_term(P_3_sin_ϕ[i]) + TaylorSeries.zero!(F_J3_ζ[i]) (F_J3_ζ[i]).coeffs[1] = constant_term(Λ3j_div_r5[i]) * constant_term(m_c_ϕ_∂P_3[i]) - (F_J3_ζ[i]).coeffs[2:order + 1] .= zero((F_J3_ζ[i]).coeffs[1]) + TaylorSeries.zero!(F_J_ξ[i]) (F_J_ξ[i]).coeffs[1] = identity(constant_term(F_J2_ξ[i])) - (F_J_ξ[i]).coeffs[2:order + 1] .= zero((F_J_ξ[i]).coeffs[1]) + TaylorSeries.zero!(F_J_ζ[i]) (F_J_ζ[i]).coeffs[1] = identity(constant_term(F_J2_ζ[i])) - (F_J_ζ[i]).coeffs[2:order + 1] .= zero((F_J_ζ[i]).coeffs[1]) - (tmp1415[i]).coeffs[1] = -(constant_term(X[i])) - (tmp1415[i]).coeffs[2:order + 1] .= zero((tmp1415[i]).coeffs[1]) - (ξx[i]).coeffs[1] = constant_term(tmp1415[i]) / constant_term(r_p1d2[i]) - (ξx[i]).coeffs[2:order + 1] .= zero((ξx[i]).coeffs[1]) - (tmp1417[i]).coeffs[1] = -(constant_term(Y[i])) - (tmp1417[i]).coeffs[2:order + 1] .= zero((tmp1417[i]).coeffs[1]) - (ξy[i]).coeffs[1] = constant_term(tmp1417[i]) / constant_term(r_p1d2[i]) - (ξy[i]).coeffs[2:order + 1] .= zero((ξy[i]).coeffs[1]) - (tmp1419[i]).coeffs[1] = -(constant_term(Z[i])) - (tmp1419[i]).coeffs[2:order + 1] .= zero((tmp1419[i]).coeffs[1]) - (ξz[i]).coeffs[1] = constant_term(tmp1419[i]) / constant_term(r_p1d2[i]) - (ξz[i]).coeffs[2:order + 1] .= zero((ξz[i]).coeffs[1]) + TaylorSeries.zero!(tmp6286[i]) + (tmp6286[i]).coeffs[1] = -(constant_term(X[i])) + TaylorSeries.zero!(ξx[i]) + (ξx[i]).coeffs[1] = constant_term(tmp6286[i]) / constant_term(r_p1d2[i]) + TaylorSeries.zero!(tmp6288[i]) + (tmp6288[i]).coeffs[1] = -(constant_term(Y[i])) + TaylorSeries.zero!(ξy[i]) + (ξy[i]).coeffs[1] = constant_term(tmp6288[i]) / constant_term(r_p1d2[i]) + TaylorSeries.zero!(tmp6290[i]) + (tmp6290[i]).coeffs[1] = -(constant_term(Z[i])) + TaylorSeries.zero!(ξz[i]) + (ξz[i]).coeffs[1] = constant_term(tmp6290[i]) / constant_term(r_p1d2[i]) + TaylorSeries.zero!(ηx1[i]) (ηx1[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξz[i]) - (ηx1[i]).coeffs[2:order + 1] .= zero((ηx1[i]).coeffs[1]) + TaylorSeries.zero!(ηy1[i]) (ηy1[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξx[i]) - (ηy1[i]).coeffs[2:order + 1] .= zero((ηy1[i]).coeffs[1]) + TaylorSeries.zero!(ηz1[i]) (ηz1[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξy[i]) - (ηz1[i]).coeffs[2:order + 1] .= zero((ηz1[i]).coeffs[1]) + TaylorSeries.zero!(ηx2[i]) (ηx2[i]).coeffs[1] = constant_term(M_[3, 3, i]) * constant_term(ξy[i]) - (ηx2[i]).coeffs[2:order + 1] .= zero((ηx2[i]).coeffs[1]) + TaylorSeries.zero!(ηy2[i]) (ηy2[i]).coeffs[1] = constant_term(M_[1, 3, i]) * constant_term(ξz[i]) - (ηy2[i]).coeffs[2:order + 1] .= zero((ηy2[i]).coeffs[1]) + TaylorSeries.zero!(ηz2[i]) (ηz2[i]).coeffs[1] = constant_term(M_[2, 3, i]) * constant_term(ξx[i]) - (ηz2[i]).coeffs[2:order + 1] .= zero((ηz2[i]).coeffs[1]) + TaylorSeries.zero!(ηx[i]) (ηx[i]).coeffs[1] = constant_term(ηx1[i]) - constant_term(ηx2[i]) - (ηx[i]).coeffs[2:order + 1] .= zero((ηx[i]).coeffs[1]) + TaylorSeries.zero!(ηy[i]) (ηy[i]).coeffs[1] = constant_term(ηy1[i]) - constant_term(ηy2[i]) - (ηy[i]).coeffs[2:order + 1] .= zero((ηy[i]).coeffs[1]) + TaylorSeries.zero!(ηz[i]) (ηz[i]).coeffs[1] = constant_term(ηz1[i]) - constant_term(ηz2[i]) - (ηz[i]).coeffs[2:order + 1] .= zero((ηz[i]).coeffs[1]) + TaylorSeries.zero!(ζx1[i]) (ζx1[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηz[i]) - (ζx1[i]).coeffs[2:order + 1] .= zero((ζx1[i]).coeffs[1]) + TaylorSeries.zero!(ζy1[i]) (ζy1[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηx[i]) - (ζy1[i]).coeffs[2:order + 1] .= zero((ζy1[i]).coeffs[1]) + TaylorSeries.zero!(ζz1[i]) (ζz1[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηy[i]) - (ζz1[i]).coeffs[2:order + 1] .= zero((ζz1[i]).coeffs[1]) + TaylorSeries.zero!(ζx2[i]) (ζx2[i]).coeffs[1] = constant_term(ξz[i]) * constant_term(ηy[i]) - (ζx2[i]).coeffs[2:order + 1] .= zero((ζx2[i]).coeffs[1]) + TaylorSeries.zero!(ζy2[i]) (ζy2[i]).coeffs[1] = constant_term(ξx[i]) * constant_term(ηz[i]) - (ζy2[i]).coeffs[2:order + 1] .= zero((ζy2[i]).coeffs[1]) + TaylorSeries.zero!(ζz2[i]) (ζz2[i]).coeffs[1] = constant_term(ξy[i]) * constant_term(ηx[i]) - (ζz2[i]).coeffs[2:order + 1] .= zero((ζz2[i]).coeffs[1]) + TaylorSeries.zero!(ζx[i]) (ζx[i]).coeffs[1] = constant_term(ζx1[i]) - constant_term(ζx2[i]) - (ζx[i]).coeffs[2:order + 1] .= zero((ζx[i]).coeffs[1]) + TaylorSeries.zero!(ζy[i]) (ζy[i]).coeffs[1] = constant_term(ζy1[i]) - constant_term(ζy2[i]) - (ζy[i]).coeffs[2:order + 1] .= zero((ζy[i]).coeffs[1]) + TaylorSeries.zero!(ζz[i]) (ζz[i]).coeffs[1] = constant_term(ζz1[i]) - constant_term(ζz2[i]) - (ζz[i]).coeffs[2:order + 1] .= zero((ζz[i]).coeffs[1]) + TaylorSeries.zero!(F_J2_x1[i]) (F_J2_x1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξx[i]) - (F_J2_x1[i]).coeffs[2:order + 1] .= zero((F_J2_x1[i]).coeffs[1]) + TaylorSeries.zero!(F_J2_y1[i]) (F_J2_y1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξy[i]) - (F_J2_y1[i]).coeffs[2:order + 1] .= zero((F_J2_y1[i]).coeffs[1]) + TaylorSeries.zero!(F_J2_z1[i]) (F_J2_z1[i]).coeffs[1] = constant_term(F_J_ξ[i]) * constant_term(ξz[i]) - (F_J2_z1[i]).coeffs[2:order + 1] .= zero((F_J2_z1[i]).coeffs[1]) + TaylorSeries.zero!(F_J2_x2[i]) (F_J2_x2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζx[i]) - (F_J2_x2[i]).coeffs[2:order + 1] .= zero((F_J2_x2[i]).coeffs[1]) + TaylorSeries.zero!(F_J2_y2[i]) (F_J2_y2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζy[i]) - (F_J2_y2[i]).coeffs[2:order + 1] .= zero((F_J2_y2[i]).coeffs[1]) + TaylorSeries.zero!(F_J2_z2[i]) (F_J2_z2[i]).coeffs[1] = constant_term(F_J_ζ[i]) * constant_term(ζz[i]) - (F_J2_z2[i]).coeffs[2:order + 1] .= zero((F_J2_z2[i]).coeffs[1]) + TaylorSeries.zero!(F_J2_x[i]) (F_J2_x[i]).coeffs[1] = constant_term(F_J2_x1[i]) + constant_term(F_J2_x2[i]) - (F_J2_x[i]).coeffs[2:order + 1] .= zero((F_J2_x[i]).coeffs[1]) + TaylorSeries.zero!(F_J2_y[i]) (F_J2_y[i]).coeffs[1] = constant_term(F_J2_y1[i]) + constant_term(F_J2_y2[i]) - (F_J2_y[i]).coeffs[2:order + 1] .= zero((F_J2_y[i]).coeffs[1]) + TaylorSeries.zero!(F_J2_z[i]) (F_J2_z[i]).coeffs[1] = constant_term(F_J2_z1[i]) + constant_term(F_J2_z2[i]) - (F_J2_z[i]).coeffs[2:order + 1] .= zero((F_J2_z[i]).coeffs[1]) end - (tmp1449[i]).coeffs[1] = constant_term(ui[i]) ^ float(constant_term(2)) - (tmp1449[i]).coeffs[2:order + 1] .= zero((tmp1449[i]).coeffs[1]) - (tmp1451[i]).coeffs[1] = constant_term(vi[i]) ^ float(constant_term(2)) - (tmp1451[i]).coeffs[2:order + 1] .= zero((tmp1451[i]).coeffs[1]) - (tmp1452[i]).coeffs[1] = constant_term(tmp1449[i]) + constant_term(tmp1451[i]) - (tmp1452[i]).coeffs[2:order + 1] .= zero((tmp1452[i]).coeffs[1]) - (tmp1454[i]).coeffs[1] = constant_term(wi[i]) ^ float(constant_term(2)) - (tmp1454[i]).coeffs[2:order + 1] .= zero((tmp1454[i]).coeffs[1]) - (v2[i]).coeffs[1] = constant_term(tmp1452[i]) + constant_term(tmp1454[i]) - (v2[i]).coeffs[2:order + 1] .= zero((v2[i]).coeffs[1]) + TaylorSeries.zero!(tmp6320[i]) + (tmp6320[i]).coeffs[1] = constant_term(ui[i]) ^ float(constant_term(2)) + TaylorSeries.zero!(tmp6322[i]) + (tmp6322[i]).coeffs[1] = constant_term(vi[i]) ^ float(constant_term(2)) + TaylorSeries.zero!(tmp6323[i]) + (tmp6323[i]).coeffs[1] = constant_term(tmp6320[i]) + constant_term(tmp6322[i]) + TaylorSeries.zero!(tmp6325[i]) + (tmp6325[i]).coeffs[1] = constant_term(wi[i]) ^ float(constant_term(2)) + TaylorSeries.zero!(v2[i]) + (v2[i]).coeffs[1] = constant_term(tmp6323[i]) + constant_term(tmp6325[i]) end - tmp1457.coeffs[1] = constant_term(q[4]) ^ float(constant_term(2)) - tmp1457.coeffs[2:order + 1] .= zero(tmp1457.coeffs[1]) - tmp1459.coeffs[1] = constant_term(q[5]) ^ float(constant_term(2)) - tmp1459.coeffs[2:order + 1] .= zero(tmp1459.coeffs[1]) - tmp1460.coeffs[1] = constant_term(tmp1457) + constant_term(tmp1459) - tmp1460.coeffs[2:order + 1] .= zero(tmp1460.coeffs[1]) - tmp1462.coeffs[1] = constant_term(q[6]) ^ float(constant_term(2)) - tmp1462.coeffs[2:order + 1] .= zero(tmp1462.coeffs[1]) - (v2[N]).coeffs[1] = constant_term(tmp1460) + constant_term(tmp1462) - (v2[N]).coeffs[2:order + 1] .= zero((v2[N]).coeffs[1]) + TaylorSeries.zero!(tmp6328) + tmp6328.coeffs[1] = constant_term(q[4]) ^ float(constant_term(2)) + TaylorSeries.zero!(tmp6330) + tmp6330.coeffs[1] = constant_term(q[5]) ^ float(constant_term(2)) + TaylorSeries.zero!(tmp6331) + tmp6331.coeffs[1] = constant_term(tmp6328) + constant_term(tmp6330) + TaylorSeries.zero!(tmp6333) + tmp6333.coeffs[1] = constant_term(q[6]) ^ float(constant_term(2)) + TaylorSeries.zero!(v2[N]) + (v2[N]).coeffs[1] = constant_term(tmp6331) + constant_term(tmp6333) for i = 1:Nm1 + TaylorSeries.zero!(temp_004[i]) (temp_004[i]).coeffs[1] = constant_term(newtonian1b_Potential[i]) + constant_term(newtonianNb_Potential[N]) - (temp_004[i]).coeffs[2:order + 1] .= zero((temp_004[i]).coeffs[1]) + TaylorSeries.zero!(newtonianNb_Potential[N]) (newtonianNb_Potential[N]).coeffs[1] = identity(constant_term(temp_004[i])) - (newtonianNb_Potential[N]).coeffs[2:order + 1] .= zero((newtonianNb_Potential[N]).coeffs[1]) if UJ_interaction[i] - (tmp1465[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_x[i]) - (tmp1465[i]).coeffs[2:order + 1] .= zero((tmp1465[i]).coeffs[1]) - (temp_accX_i[i]).coeffs[1] = constant_term(accX) - constant_term(tmp1465[i]) - (temp_accX_i[i]).coeffs[2:order + 1] .= zero((temp_accX_i[i]).coeffs[1]) + TaylorSeries.zero!(tmp6336[i]) + (tmp6336[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_x[i]) + TaylorSeries.zero!(temp_accX_i[i]) + (temp_accX_i[i]).coeffs[1] = constant_term(accX) - constant_term(tmp6336[i]) + TaylorSeries.zero!(accX) accX.coeffs[1] = identity(constant_term(temp_accX_i[i])) - accX.coeffs[2:order + 1] .= zero(accX.coeffs[1]) - (tmp1467[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_y[i]) - (tmp1467[i]).coeffs[2:order + 1] .= zero((tmp1467[i]).coeffs[1]) - (temp_accY_i[i]).coeffs[1] = constant_term(accY) - constant_term(tmp1467[i]) - (temp_accY_i[i]).coeffs[2:order + 1] .= zero((temp_accY_i[i]).coeffs[1]) + TaylorSeries.zero!(tmp6338[i]) + (tmp6338[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_y[i]) + TaylorSeries.zero!(temp_accY_i[i]) + (temp_accY_i[i]).coeffs[1] = constant_term(accY) - constant_term(tmp6338[i]) + TaylorSeries.zero!(accY) accY.coeffs[1] = identity(constant_term(temp_accY_i[i])) - accY.coeffs[2:order + 1] .= zero(accY.coeffs[1]) - (tmp1469[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_z[i]) - (tmp1469[i]).coeffs[2:order + 1] .= zero((tmp1469[i]).coeffs[1]) - (temp_accZ_i[i]).coeffs[1] = constant_term(accZ) - constant_term(tmp1469[i]) - (temp_accZ_i[i]).coeffs[2:order + 1] .= zero((temp_accZ_i[i]).coeffs[1]) + TaylorSeries.zero!(tmp6340[i]) + (tmp6340[i]).coeffs[1] = constant_term(μ[i]) * constant_term(F_J2_z[i]) + TaylorSeries.zero!(temp_accZ_i[i]) + (temp_accZ_i[i]).coeffs[1] = constant_term(accZ) - constant_term(tmp6340[i]) + TaylorSeries.zero!(accZ) accZ.coeffs[1] = identity(constant_term(temp_accZ_i[i])) - accZ.coeffs[2:order + 1] .= zero(accZ.coeffs[1]) end end + TaylorSeries.zero!(_4ϕj[N]) (_4ϕj[N]).coeffs[1] = constant_term(4) * constant_term(newtonianNb_Potential[N]) - (_4ϕj[N]).coeffs[2:order + 1] .= zero((_4ϕj[N]).coeffs[1]) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 + #= /Users/Jorge/projects/neos240702/neosjetcoeffs.jl:1031 =# Threads.@threads for i = 1:10 + TaylorSeries.zero!(ϕi_plus_4ϕj[i]) (ϕi_plus_4ϕj[i]).coeffs[1] = constant_term(newtonianNb_Potential_t[i]) + constant_term(_4ϕj[N]) - (ϕi_plus_4ϕj[i]).coeffs[2:order + 1] .= zero((ϕi_plus_4ϕj[i]).coeffs[1]) - (tmp1475[i]).coeffs[1] = constant_term(2) * constant_term(v2[i]) - (tmp1475[i]).coeffs[2:order + 1] .= zero((tmp1475[i]).coeffs[1]) - (tmp1477[i]).coeffs[1] = constant_term(4) * constant_term(vi_dot_vj[i]) - (tmp1477[i]).coeffs[2:order + 1] .= zero((tmp1477[i]).coeffs[1]) - (tmp1478[i]).coeffs[1] = constant_term(tmp1475[i]) - constant_term(tmp1477[i]) - (tmp1478[i]).coeffs[2:order + 1] .= zero((tmp1478[i]).coeffs[1]) - (sj2_plus_2si2_minus_4vivj[i]).coeffs[1] = constant_term(tmp1478[i]) + constant_term(v2[N]) - (sj2_plus_2si2_minus_4vivj[i]).coeffs[2:order + 1] .= zero((sj2_plus_2si2_minus_4vivj[i]).coeffs[1]) + TaylorSeries.zero!(tmp6346[i]) + (tmp6346[i]).coeffs[1] = constant_term(2) * constant_term(v2[i]) + TaylorSeries.zero!(tmp6348[i]) + (tmp6348[i]).coeffs[1] = constant_term(4) * constant_term(vi_dot_vj[i]) + TaylorSeries.zero!(tmp6349[i]) + (tmp6349[i]).coeffs[1] = constant_term(tmp6346[i]) - constant_term(tmp6348[i]) + TaylorSeries.zero!(sj2_plus_2si2_minus_4vivj[i]) + (sj2_plus_2si2_minus_4vivj[i]).coeffs[1] = constant_term(tmp6349[i]) + constant_term(v2[N]) + TaylorSeries.zero!(ϕs_and_vs[i]) (ϕs_and_vs[i]).coeffs[1] = constant_term(sj2_plus_2si2_minus_4vivj[i]) - constant_term(ϕi_plus_4ϕj[i]) - (ϕs_and_vs[i]).coeffs[2:order + 1] .= zero((ϕs_and_vs[i]).coeffs[1]) + TaylorSeries.zero!(Xij_t_Ui[i]) (Xij_t_Ui[i]).coeffs[1] = constant_term(X[i]) * constant_term(ui[i]) - (Xij_t_Ui[i]).coeffs[2:order + 1] .= zero((Xij_t_Ui[i]).coeffs[1]) + TaylorSeries.zero!(Yij_t_Vi[i]) (Yij_t_Vi[i]).coeffs[1] = constant_term(Y[i]) * constant_term(vi[i]) - (Yij_t_Vi[i]).coeffs[2:order + 1] .= zero((Yij_t_Vi[i]).coeffs[1]) + TaylorSeries.zero!(Zij_t_Wi[i]) (Zij_t_Wi[i]).coeffs[1] = constant_term(Z[i]) * constant_term(wi[i]) - (Zij_t_Wi[i]).coeffs[2:order + 1] .= zero((Zij_t_Wi[i]).coeffs[1]) - (tmp1484[i]).coeffs[1] = constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]) - (tmp1484[i]).coeffs[2:order + 1] .= zero((tmp1484[i]).coeffs[1]) - (Rij_dot_Vi[i]).coeffs[1] = constant_term(tmp1484[i]) + constant_term(Zij_t_Wi[i]) - (Rij_dot_Vi[i]).coeffs[2:order + 1] .= zero((Rij_dot_Vi[i]).coeffs[1]) - (tmp1487[i]).coeffs[1] = constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)) - (tmp1487[i]).coeffs[2:order + 1] .= zero((tmp1487[i]).coeffs[1]) - (pn1t7[i]).coeffs[1] = constant_term(tmp1487[i]) / constant_term(r_p2[i]) - (pn1t7[i]).coeffs[2:order + 1] .= zero((pn1t7[i]).coeffs[1]) - (tmp1490[i]).coeffs[1] = constant_term(1.5) * constant_term(pn1t7[i]) - (tmp1490[i]).coeffs[2:order + 1] .= zero((tmp1490[i]).coeffs[1]) - (pn1t2_7[i]).coeffs[1] = constant_term(ϕs_and_vs[i]) - constant_term(tmp1490[i]) - (pn1t2_7[i]).coeffs[2:order + 1] .= zero((pn1t2_7[i]).coeffs[1]) + TaylorSeries.zero!(tmp6355[i]) + (tmp6355[i]).coeffs[1] = constant_term(Xij_t_Ui[i]) + constant_term(Yij_t_Vi[i]) + TaylorSeries.zero!(Rij_dot_Vi[i]) + (Rij_dot_Vi[i]).coeffs[1] = constant_term(tmp6355[i]) + constant_term(Zij_t_Wi[i]) + TaylorSeries.zero!(tmp6358[i]) + (tmp6358[i]).coeffs[1] = constant_term(Rij_dot_Vi[i]) ^ float(constant_term(2)) + TaylorSeries.zero!(pn1t7[i]) + (pn1t7[i]).coeffs[1] = constant_term(tmp6358[i]) / constant_term(r_p2[i]) + TaylorSeries.zero!(tmp6361[i]) + (tmp6361[i]).coeffs[1] = constant_term(1.5) * constant_term(pn1t7[i]) + TaylorSeries.zero!(pn1t2_7[i]) + (pn1t2_7[i]).coeffs[1] = constant_term(ϕs_and_vs[i]) - constant_term(tmp6361[i]) + TaylorSeries.zero!(pn1t1_7[i]) (pn1t1_7[i]).coeffs[1] = constant_term(c_p2) + constant_term(pn1t2_7[i]) - (pn1t1_7[i]).coeffs[2:order + 1] .= zero((pn1t1_7[i]).coeffs[1]) + TaylorSeries.zero!(pNX_t_X[i]) (pNX_t_X[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(X[i]) - (pNX_t_X[i]).coeffs[2:order + 1] .= zero((pNX_t_X[i]).coeffs[1]) + TaylorSeries.zero!(pNY_t_Y[i]) (pNY_t_Y[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(Y[i]) - (pNY_t_Y[i]).coeffs[2:order + 1] .= zero((pNY_t_Y[i]).coeffs[1]) + TaylorSeries.zero!(pNZ_t_Z[i]) (pNZ_t_Z[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(Z[i]) - (pNZ_t_Z[i]).coeffs[2:order + 1] .= zero((pNZ_t_Z[i]).coeffs[1]) - (tmp1497[i]).coeffs[1] = constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]) - (tmp1497[i]).coeffs[2:order + 1] .= zero((tmp1497[i]).coeffs[1]) - (tmp1498[i]).coeffs[1] = constant_term(tmp1497[i]) + constant_term(pNZ_t_Z[i]) - (tmp1498[i]).coeffs[2:order + 1] .= zero((tmp1498[i]).coeffs[1]) - (tmp1499[i]).coeffs[1] = constant_term(0.5) * constant_term(tmp1498[i]) - (tmp1499[i]).coeffs[2:order + 1] .= zero((tmp1499[i]).coeffs[1]) - (pn1[i]).coeffs[1] = constant_term(pn1t1_7[i]) + constant_term(tmp1499[i]) - (pn1[i]).coeffs[2:order + 1] .= zero((pn1[i]).coeffs[1]) + TaylorSeries.zero!(tmp6368[i]) + (tmp6368[i]).coeffs[1] = constant_term(pNX_t_X[i]) + constant_term(pNY_t_Y[i]) + TaylorSeries.zero!(tmp6369[i]) + (tmp6369[i]).coeffs[1] = constant_term(tmp6368[i]) + constant_term(pNZ_t_Z[i]) + TaylorSeries.zero!(tmp6370[i]) + (tmp6370[i]).coeffs[1] = constant_term(0.5) * constant_term(tmp6369[i]) + TaylorSeries.zero!(pn1[i]) + (pn1[i]).coeffs[1] = constant_term(pn1t1_7[i]) + constant_term(tmp6370[i]) + TaylorSeries.zero!(X_t_pn1[i]) (X_t_pn1[i]).coeffs[1] = constant_term(newton_acc_X[i]) * constant_term(pn1[i]) - (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) + TaylorSeries.zero!(Y_t_pn1[i]) (Y_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Y[i]) * constant_term(pn1[i]) - (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) + TaylorSeries.zero!(Z_t_pn1[i]) (Z_t_pn1[i]).coeffs[1] = constant_term(newton_acc_Z[i]) * constant_term(pn1[i]) - (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) + TaylorSeries.zero!(pNX_t_pn3[i]) (pNX_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 2]) * constant_term(pn3[i]) - (pNX_t_pn3[i]).coeffs[2:order + 1] .= zero((pNX_t_pn3[i]).coeffs[1]) + TaylorSeries.zero!(pNY_t_pn3[i]) (pNY_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i - 1]) * constant_term(pn3[i]) - (pNY_t_pn3[i]).coeffs[2:order + 1] .= zero((pNY_t_pn3[i]).coeffs[1]) + TaylorSeries.zero!(pNZ_t_pn3[i]) (pNZ_t_pn3[i]).coeffs[1] = constant_term(acceph_t[3i]) * constant_term(pn3[i]) - (pNZ_t_pn3[i]).coeffs[2:order + 1] .= zero((pNZ_t_pn3[i]).coeffs[1]) end for i = 1:10 - (tmp1507[i]).coeffs[1] = constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]) - (tmp1507[i]).coeffs[2:order + 1] .= zero((tmp1507[i]).coeffs[1]) - (termpnx[i]).coeffs[1] = constant_term(X_t_pn1[i]) + constant_term(tmp1507[i]) - (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) + TaylorSeries.zero!(tmp6378[i]) + (tmp6378[i]).coeffs[1] = constant_term(U_t_pn2[i]) + constant_term(pNX_t_pn3[i]) + TaylorSeries.zero!(termpnx[i]) + (termpnx[i]).coeffs[1] = constant_term(X_t_pn1[i]) + constant_term(tmp6378[i]) + TaylorSeries.zero!(sumpnx[i]) (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) - (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) + TaylorSeries.zero!(pntempX) pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) - pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) - (tmp1510[i]).coeffs[1] = constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]) - (tmp1510[i]).coeffs[2:order + 1] .= zero((tmp1510[i]).coeffs[1]) - (termpny[i]).coeffs[1] = constant_term(Y_t_pn1[i]) + constant_term(tmp1510[i]) - (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) + TaylorSeries.zero!(tmp6381[i]) + (tmp6381[i]).coeffs[1] = constant_term(V_t_pn2[i]) + constant_term(pNY_t_pn3[i]) + TaylorSeries.zero!(termpny[i]) + (termpny[i]).coeffs[1] = constant_term(Y_t_pn1[i]) + constant_term(tmp6381[i]) + TaylorSeries.zero!(sumpny[i]) (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) - (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) + TaylorSeries.zero!(pntempY) pntempY.coeffs[1] = identity(constant_term(sumpny[i])) - pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) - (tmp1513[i]).coeffs[1] = constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]) - (tmp1513[i]).coeffs[2:order + 1] .= zero((tmp1513[i]).coeffs[1]) - (termpnz[i]).coeffs[1] = constant_term(Z_t_pn1[i]) + constant_term(tmp1513[i]) - (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) + TaylorSeries.zero!(tmp6384[i]) + (tmp6384[i]).coeffs[1] = constant_term(W_t_pn2[i]) + constant_term(pNZ_t_pn3[i]) + TaylorSeries.zero!(termpnz[i]) + (termpnz[i]).coeffs[1] = constant_term(Z_t_pn1[i]) + constant_term(tmp6384[i]) + TaylorSeries.zero!(sumpnz[i]) (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) - (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) + TaylorSeries.zero!(pntempZ) pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) - pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) end - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 + #= /Users/Jorge/projects/neos240702/neosjetcoeffs.jl:1084 =# Threads.@threads for i = 11:Nm1 + TaylorSeries.zero!(X_t_pn1[i]) (X_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_X[i]) - (X_t_pn1[i]).coeffs[2:order + 1] .= zero((X_t_pn1[i]).coeffs[1]) + TaylorSeries.zero!(Y_t_pn1[i]) (Y_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Y[i]) - (Y_t_pn1[i]).coeffs[2:order + 1] .= zero((Y_t_pn1[i]).coeffs[1]) + TaylorSeries.zero!(Z_t_pn1[i]) (Z_t_pn1[i]).coeffs[1] = constant_term(c_p2) * constant_term(newton_acc_Z[i]) - (Z_t_pn1[i]).coeffs[2:order + 1] .= zero((Z_t_pn1[i]).coeffs[1]) end for i = 11:Nm1 + TaylorSeries.zero!(termpnx[i]) (termpnx[i]).coeffs[1] = identity(constant_term(X_t_pn1[i])) - (termpnx[i]).coeffs[2:order + 1] .= zero((termpnx[i]).coeffs[1]) + TaylorSeries.zero!(sumpnx[i]) (sumpnx[i]).coeffs[1] = constant_term(pntempX) + constant_term(termpnx[i]) - (sumpnx[i]).coeffs[2:order + 1] .= zero((sumpnx[i]).coeffs[1]) + TaylorSeries.zero!(pntempX) pntempX.coeffs[1] = identity(constant_term(sumpnx[i])) - pntempX.coeffs[2:order + 1] .= zero(pntempX.coeffs[1]) + TaylorSeries.zero!(termpny[i]) (termpny[i]).coeffs[1] = identity(constant_term(Y_t_pn1[i])) - (termpny[i]).coeffs[2:order + 1] .= zero((termpny[i]).coeffs[1]) + TaylorSeries.zero!(sumpny[i]) (sumpny[i]).coeffs[1] = constant_term(pntempY) + constant_term(termpny[i]) - (sumpny[i]).coeffs[2:order + 1] .= zero((sumpny[i]).coeffs[1]) + TaylorSeries.zero!(pntempY) pntempY.coeffs[1] = identity(constant_term(sumpny[i])) - pntempY.coeffs[2:order + 1] .= zero(pntempY.coeffs[1]) + TaylorSeries.zero!(termpnz[i]) (termpnz[i]).coeffs[1] = identity(constant_term(Z_t_pn1[i])) - (termpnz[i]).coeffs[2:order + 1] .= zero((termpnz[i]).coeffs[1]) + TaylorSeries.zero!(sumpnz[i]) (sumpnz[i]).coeffs[1] = constant_term(pntempZ) + constant_term(termpnz[i]) - (sumpnz[i]).coeffs[2:order + 1] .= zero((sumpnz[i]).coeffs[1]) + TaylorSeries.zero!(pntempZ) pntempZ.coeffs[1] = identity(constant_term(sumpnz[i])) - pntempZ.coeffs[2:order + 1] .= zero(pntempZ.coeffs[1]) end + TaylorSeries.zero!(postNewtonX) postNewtonX.coeffs[1] = constant_term(pntempX) * constant_term(c_m2) - postNewtonX.coeffs[2:order + 1] .= zero(postNewtonX.coeffs[1]) + TaylorSeries.zero!(postNewtonY) postNewtonY.coeffs[1] = constant_term(pntempY) * constant_term(c_m2) - postNewtonY.coeffs[2:order + 1] .= zero(postNewtonY.coeffs[1]) + TaylorSeries.zero!(postNewtonZ) postNewtonZ.coeffs[1] = constant_term(pntempZ) * constant_term(c_m2) - postNewtonZ.coeffs[2:order + 1] .= zero(postNewtonZ.coeffs[1]) + TaylorSeries.zero!(dq[4]) (dq[4]).coeffs[1] = constant_term(postNewtonX) + constant_term(accX) - (dq[4]).coeffs[2:order + 1] .= zero((dq[4]).coeffs[1]) + TaylorSeries.zero!(dq[5]) (dq[5]).coeffs[1] = constant_term(postNewtonY) + constant_term(accY) - (dq[5]).coeffs[2:order + 1] .= zero((dq[5]).coeffs[1]) + TaylorSeries.zero!(dq[6]) (dq[6]).coeffs[1] = constant_term(postNewtonZ) + constant_term(accZ) - (dq[6]).coeffs[2:order + 1] .= zero((dq[6]).coeffs[1]) for __idx = eachindex(q) (q[__idx]).coeffs[2] = (dq[__idx]).coeffs[1] end @@ -2770,7 +3022,10 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorSeries.identity!(dq[2], q[5], ord) TaylorSeries.identity!(dq[3], q[6], ord) TaylorSeries.identity!(newtonianNb_Potential[N], zero_q_1, ord) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:245 =# Threads.@threads for i = 1:Nm1 + TaylorSeries.mul!(_4dq[1], 4, dq[1], ord) + TaylorSeries.mul!(_4dq[2], 4, dq[2], ord) + TaylorSeries.mul!(_4dq[3], 4, dq[3], ord) + #= /Users/Jorge/projects/neos240702/neosjetcoeffs.jl:829 =# Threads.@threads for i = 1:Nm1 TaylorSeries.identity!(ui[i], ss16asteph_t[3 * ((N - 1) + i) - 2], ord) TaylorSeries.identity!(vi[i], ss16asteph_t[3 * ((N - 1) + i) - 1], ord) TaylorSeries.identity!(wi[i], ss16asteph_t[3 * ((N - 1) + i)], ord) @@ -2780,35 +3035,32 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorSeries.subst!(U[i], ui[i], dq[1], ord) TaylorSeries.subst!(V[i], vi[i], dq[2], ord) TaylorSeries.subst!(W[i], wi[i], dq[3], ord) - TaylorSeries.mul!(tmp1317[1], 4, dq[1], ord) - TaylorSeries.mul!(tmp1319[i], 3, ui[i], ord) - TaylorSeries.subst!(_4U_m_3X[i], tmp1317[1], tmp1319[i], ord) - TaylorSeries.mul!(tmp1322[2], 4, dq[2], ord) - TaylorSeries.mul!(tmp1324[i], 3, vi[i], ord) - TaylorSeries.subst!(_4V_m_3Y[i], tmp1322[2], tmp1324[i], ord) - TaylorSeries.mul!(tmp1327[3], 4, dq[3], ord) - TaylorSeries.mul!(tmp1329[i], 3, wi[i], ord) - TaylorSeries.subst!(_4W_m_3Z[i], tmp1327[3], tmp1329[i], ord) + TaylorSeries.mul!(tmp6194[i], -3, ui[i], ord) + TaylorSeries.add!(_4U_m_3X[i], tmp6194[i], _4dq[1], ord) + TaylorSeries.mul!(tmp6197[i], -3, vi[i], ord) + TaylorSeries.add!(_4V_m_3Y[i], tmp6197[i], _4dq[2], ord) + TaylorSeries.mul!(tmp6200[i], -3, wi[i], ord) + TaylorSeries.add!(_4W_m_3Z[i], tmp6200[i], _4dq[3], ord) TaylorSeries.mul!(pn2x[i], X[i], _4U_m_3X[i], ord) TaylorSeries.mul!(pn2y[i], Y[i], _4V_m_3Y[i], ord) TaylorSeries.mul!(pn2z[i], Z[i], _4W_m_3Z[i], ord) TaylorSeries.mul!(UU[i], ui[i], dq[1], ord) TaylorSeries.mul!(VV[i], vi[i], dq[2], ord) TaylorSeries.mul!(WW[i], wi[i], dq[3], ord) - TaylorSeries.add!(tmp1337[i], UU[i], VV[i], ord) - TaylorSeries.add!(vi_dot_vj[i], tmp1337[i], WW[i], ord) - TaylorSeries.pow!(tmp1340[i], X[i], 2, ord) - TaylorSeries.pow!(tmp1342[i], Y[i], 2, ord) - TaylorSeries.add!(tmp1343[i], tmp1340[i], tmp1342[i], ord) - TaylorSeries.pow!(tmp1345[i], Z[i], 2, ord) - TaylorSeries.add!(r_p2[i], tmp1343[i], tmp1345[i], ord) + TaylorSeries.add!(tmp6208[i], UU[i], VV[i], ord) + TaylorSeries.add!(vi_dot_vj[i], tmp6208[i], WW[i], ord) + TaylorSeries.pow!(tmp6211[i], X[i], 2, ord) + TaylorSeries.pow!(tmp6213[i], Y[i], 2, ord) + TaylorSeries.add!(tmp6214[i], tmp6211[i], tmp6213[i], ord) + TaylorSeries.pow!(tmp6216[i], Z[i], 2, ord) + TaylorSeries.add!(r_p2[i], tmp6214[i], tmp6216[i], ord) TaylorSeries.sqrt!(r_p1d2[i], r_p2[i], ord) TaylorSeries.pow!(r_p3d2[i], r_p2[i], 1.5, ord) TaylorSeries.pow!(r_p7d2[i], r_p2[i], 3.5, ord) TaylorSeries.div!(newtonianCoeff[i], μ[i], r_p3d2[i], ord) - TaylorSeries.add!(tmp1353[i], pn2x[i], pn2y[i], ord) - TaylorSeries.add!(tmp1354[i], tmp1353[i], pn2z[i], ord) - TaylorSeries.mul!(pn2[i], newtonianCoeff[i], tmp1354[i], ord) + TaylorSeries.add!(tmp6224[i], pn2x[i], pn2y[i], ord) + TaylorSeries.add!(tmp6225[i], tmp6224[i], pn2z[i], ord) + TaylorSeries.mul!(pn2[i], newtonianCoeff[i], tmp6225[i], ord) TaylorSeries.mul!(newton_acc_X[i], X[i], newtonianCoeff[i], ord) TaylorSeries.mul!(newton_acc_Y[i], Y[i], newtonianCoeff[i], ord) TaylorSeries.mul!(newton_acc_Z[i], Z[i], newtonianCoeff[i], ord) @@ -2818,51 +3070,51 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorSeries.mul!(V_t_pn2[i], pn2[i], V[i], ord) TaylorSeries.mul!(W_t_pn2[i], pn2[i], W[i], ord) if UJ_interaction[i] - TaylorSeries.subst!(tmp1365[i], X[i], ord) - TaylorSeries.mul!(t31[i], tmp1365[i], M_[1, 3, i], ord) - TaylorSeries.subst!(tmp1367[i], Y[i], ord) - TaylorSeries.mul!(t32[i], tmp1367[i], M_[2, 3, i], ord) - TaylorSeries.subst!(tmp1369[i], Z[i], ord) - TaylorSeries.mul!(t33[i], tmp1369[i], M_[3, 3, i], ord) - TaylorSeries.add!(tmp1371[i], t31[i], t32[i], ord) - TaylorSeries.add!(r_sin_ϕ[i], tmp1371[i], t33[i], ord) + TaylorSeries.subst!(tmp6236[i], X[i], ord) + TaylorSeries.mul!(t31[i], tmp6236[i], M_[1, 3, i], ord) + TaylorSeries.subst!(tmp6238[i], Y[i], ord) + TaylorSeries.mul!(t32[i], tmp6238[i], M_[2, 3, i], ord) + TaylorSeries.subst!(tmp6240[i], Z[i], ord) + TaylorSeries.mul!(t33[i], tmp6240[i], M_[3, 3, i], ord) + TaylorSeries.add!(tmp6242[i], t31[i], t32[i], ord) + TaylorSeries.add!(r_sin_ϕ[i], tmp6242[i], t33[i], ord) TaylorSeries.div!(sin_ϕ[i], r_sin_ϕ[i], r_p1d2[i], ord) - TaylorSeries.asin!(ϕ[i], sin_ϕ[i], tmp1528[i], ord) - TaylorSeries.sincos!(tmp1529[i], cos_ϕ[i], ϕ[i], ord) + TaylorSeries.asin!(ϕ[i], sin_ϕ[i], tmp6399[i], ord) + TaylorSeries.sincos!(tmp6400[i], cos_ϕ[i], ϕ[i], ord) TaylorSeries.pow!(sin2_ϕ[i], sin_ϕ[i], 2, ord) TaylorSeries.pow!(sin3_ϕ[i], sin_ϕ[i], 3, ord) - TaylorSeries.mul!(tmp1381[i], 1.5, sin2_ϕ[i], ord) - TaylorSeries.subst!(P_2_sin_ϕ[i], tmp1381[i], 0.5, ord) + TaylorSeries.mul!(tmp6252[i], 1.5, sin2_ϕ[i], ord) + TaylorSeries.subst!(P_2_sin_ϕ[i], tmp6252[i], 0.5, ord) TaylorSeries.mul!(∂P_2_sin_ϕ[i], 3, sin_ϕ[i], ord) - TaylorSeries.mul!(tmp1387[i], -1.5, sin_ϕ[i], ord) - TaylorSeries.mul!(tmp1389[i], 2.5, sin3_ϕ[i], ord) - TaylorSeries.add!(P_3_sin_ϕ[i], tmp1387[i], tmp1389[i], ord) - TaylorSeries.mul!(tmp1393[i], 7.5, sin2_ϕ[i], ord) - TaylorSeries.add!(∂P_3_sin_ϕ[i], -1.5, tmp1393[i], ord) - TaylorSeries.pow!(tmp1396[i], r_p2[i], 2, ord) - TaylorSeries.div!(tmp1397[i], Λ2[i], tmp1396[i], ord) - TaylorSeries.subst!(Λ2j_div_r4[i], tmp1397[i], ord) - TaylorSeries.pow!(tmp1400[i], r_p1d2[i], 5, ord) - TaylorSeries.div!(tmp1401[i], Λ3[i], tmp1400[i], ord) - TaylorSeries.subst!(Λ3j_div_r5[i], tmp1401[i], ord) - TaylorSeries.subst!(tmp1403[i], cos_ϕ[i], ord) - TaylorSeries.mul!(m_c_ϕ_∂P_2[i], tmp1403[i], ∂P_2_sin_ϕ[i], ord) - TaylorSeries.subst!(tmp1405[i], cos_ϕ[i], ord) - TaylorSeries.mul!(m_c_ϕ_∂P_3[i], tmp1405[i], ∂P_3_sin_ϕ[i], ord) - TaylorSeries.mul!(tmp1408[i], Λ2j_div_r4[i], 3, ord) - TaylorSeries.mul!(F_J2_ξ[i], tmp1408[i], P_2_sin_ϕ[i], ord) + TaylorSeries.mul!(tmp6258[i], -1.5, sin_ϕ[i], ord) + TaylorSeries.mul!(tmp6260[i], 2.5, sin3_ϕ[i], ord) + TaylorSeries.add!(P_3_sin_ϕ[i], tmp6258[i], tmp6260[i], ord) + TaylorSeries.mul!(tmp6264[i], 7.5, sin2_ϕ[i], ord) + TaylorSeries.add!(∂P_3_sin_ϕ[i], -1.5, tmp6264[i], ord) + TaylorSeries.pow!(tmp6267[i], r_p2[i], 2, ord) + TaylorSeries.div!(tmp6268[i], Λ2[i], tmp6267[i], ord) + TaylorSeries.subst!(Λ2j_div_r4[i], tmp6268[i], ord) + TaylorSeries.pow!(tmp6271[i], r_p1d2[i], 5, ord) + TaylorSeries.div!(tmp6272[i], Λ3[i], tmp6271[i], ord) + TaylorSeries.subst!(Λ3j_div_r5[i], tmp6272[i], ord) + TaylorSeries.subst!(tmp6274[i], cos_ϕ[i], ord) + TaylorSeries.mul!(m_c_ϕ_∂P_2[i], tmp6274[i], ∂P_2_sin_ϕ[i], ord) + TaylorSeries.subst!(tmp6276[i], cos_ϕ[i], ord) + TaylorSeries.mul!(m_c_ϕ_∂P_3[i], tmp6276[i], ∂P_3_sin_ϕ[i], ord) + TaylorSeries.mul!(tmp6279[i], Λ2j_div_r4[i], 3, ord) + TaylorSeries.mul!(F_J2_ξ[i], tmp6279[i], P_2_sin_ϕ[i], ord) TaylorSeries.mul!(F_J2_ζ[i], Λ2j_div_r4[i], m_c_ϕ_∂P_2[i], ord) - TaylorSeries.mul!(tmp1412[i], Λ3j_div_r5[i], 4, ord) - TaylorSeries.mul!(F_J3_ξ[i], tmp1412[i], P_3_sin_ϕ[i], ord) + TaylorSeries.mul!(tmp6283[i], Λ3j_div_r5[i], 4, ord) + TaylorSeries.mul!(F_J3_ξ[i], tmp6283[i], P_3_sin_ϕ[i], ord) TaylorSeries.mul!(F_J3_ζ[i], Λ3j_div_r5[i], m_c_ϕ_∂P_3[i], ord) TaylorSeries.identity!(F_J_ξ[i], F_J2_ξ[i], ord) TaylorSeries.identity!(F_J_ζ[i], F_J2_ζ[i], ord) - TaylorSeries.subst!(tmp1415[i], X[i], ord) - TaylorSeries.div!(ξx[i], tmp1415[i], r_p1d2[i], ord) - TaylorSeries.subst!(tmp1417[i], Y[i], ord) - TaylorSeries.div!(ξy[i], tmp1417[i], r_p1d2[i], ord) - TaylorSeries.subst!(tmp1419[i], Z[i], ord) - TaylorSeries.div!(ξz[i], tmp1419[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp6286[i], X[i], ord) + TaylorSeries.div!(ξx[i], tmp6286[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp6288[i], Y[i], ord) + TaylorSeries.div!(ξy[i], tmp6288[i], r_p1d2[i], ord) + TaylorSeries.subst!(tmp6290[i], Z[i], ord) + TaylorSeries.div!(ξz[i], tmp6290[i], r_p1d2[i], ord) TaylorSeries.mul!(ηx1[i], M_[2, 3, i], ξz[i], ord) TaylorSeries.mul!(ηy1[i], M_[3, 3, i], ξx[i], ord) TaylorSeries.mul!(ηz1[i], M_[1, 3, i], ξy[i], ord) @@ -2891,57 +3143,57 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorSeries.add!(F_J2_y[i], F_J2_y1[i], F_J2_y2[i], ord) TaylorSeries.add!(F_J2_z[i], F_J2_z1[i], F_J2_z2[i], ord) end - TaylorSeries.pow!(tmp1449[i], ui[i], 2, ord) - TaylorSeries.pow!(tmp1451[i], vi[i], 2, ord) - TaylorSeries.add!(tmp1452[i], tmp1449[i], tmp1451[i], ord) - TaylorSeries.pow!(tmp1454[i], wi[i], 2, ord) - TaylorSeries.add!(v2[i], tmp1452[i], tmp1454[i], ord) + TaylorSeries.pow!(tmp6320[i], ui[i], 2, ord) + TaylorSeries.pow!(tmp6322[i], vi[i], 2, ord) + TaylorSeries.add!(tmp6323[i], tmp6320[i], tmp6322[i], ord) + TaylorSeries.pow!(tmp6325[i], wi[i], 2, ord) + TaylorSeries.add!(v2[i], tmp6323[i], tmp6325[i], ord) end - TaylorSeries.pow!(tmp1457, q[4], 2, ord) - TaylorSeries.pow!(tmp1459, q[5], 2, ord) - TaylorSeries.add!(tmp1460, tmp1457, tmp1459, ord) - TaylorSeries.pow!(tmp1462, q[6], 2, ord) - TaylorSeries.add!(v2[N], tmp1460, tmp1462, ord) + TaylorSeries.pow!(tmp6328, q[4], 2, ord) + TaylorSeries.pow!(tmp6330, q[5], 2, ord) + TaylorSeries.add!(tmp6331, tmp6328, tmp6330, ord) + TaylorSeries.pow!(tmp6333, q[6], 2, ord) + TaylorSeries.add!(v2[N], tmp6331, tmp6333, ord) for i = 1:Nm1 TaylorSeries.add!(temp_004[i], newtonian1b_Potential[i], newtonianNb_Potential[N], ord) TaylorSeries.identity!(newtonianNb_Potential[N], temp_004[i], ord) if UJ_interaction[i] - TaylorSeries.mul!(tmp1465[i], μ[i], F_J2_x[i], ord) - TaylorSeries.subst!(temp_accX_i[i], accX, tmp1465[i], ord) + TaylorSeries.mul!(tmp6336[i], μ[i], F_J2_x[i], ord) + TaylorSeries.subst!(temp_accX_i[i], accX, tmp6336[i], ord) TaylorSeries.identity!(accX, temp_accX_i[i], ord) - TaylorSeries.mul!(tmp1467[i], μ[i], F_J2_y[i], ord) - TaylorSeries.subst!(temp_accY_i[i], accY, tmp1467[i], ord) + TaylorSeries.mul!(tmp6338[i], μ[i], F_J2_y[i], ord) + TaylorSeries.subst!(temp_accY_i[i], accY, tmp6338[i], ord) TaylorSeries.identity!(accY, temp_accY_i[i], ord) - TaylorSeries.mul!(tmp1469[i], μ[i], F_J2_z[i], ord) - TaylorSeries.subst!(temp_accZ_i[i], accZ, tmp1469[i], ord) + TaylorSeries.mul!(tmp6340[i], μ[i], F_J2_z[i], ord) + TaylorSeries.subst!(temp_accZ_i[i], accZ, tmp6340[i], ord) TaylorSeries.identity!(accZ, temp_accZ_i[i], ord) end end TaylorSeries.mul!(_4ϕj[N], 4, newtonianNb_Potential[N], ord) - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:447 =# Threads.@threads for i = 1:10 + #= /Users/Jorge/projects/neos240702/neosjetcoeffs.jl:1031 =# Threads.@threads for i = 1:10 TaylorSeries.add!(ϕi_plus_4ϕj[i], newtonianNb_Potential_t[i], _4ϕj[N], ord) - TaylorSeries.mul!(tmp1475[i], 2, v2[i], ord) - TaylorSeries.mul!(tmp1477[i], 4, vi_dot_vj[i], ord) - TaylorSeries.subst!(tmp1478[i], tmp1475[i], tmp1477[i], ord) - TaylorSeries.add!(sj2_plus_2si2_minus_4vivj[i], tmp1478[i], v2[N], ord) + TaylorSeries.mul!(tmp6346[i], 2, v2[i], ord) + TaylorSeries.mul!(tmp6348[i], 4, vi_dot_vj[i], ord) + TaylorSeries.subst!(tmp6349[i], tmp6346[i], tmp6348[i], ord) + TaylorSeries.add!(sj2_plus_2si2_minus_4vivj[i], tmp6349[i], v2[N], ord) TaylorSeries.subst!(ϕs_and_vs[i], sj2_plus_2si2_minus_4vivj[i], ϕi_plus_4ϕj[i], ord) TaylorSeries.mul!(Xij_t_Ui[i], X[i], ui[i], ord) TaylorSeries.mul!(Yij_t_Vi[i], Y[i], vi[i], ord) TaylorSeries.mul!(Zij_t_Wi[i], Z[i], wi[i], ord) - TaylorSeries.add!(tmp1484[i], Xij_t_Ui[i], Yij_t_Vi[i], ord) - TaylorSeries.add!(Rij_dot_Vi[i], tmp1484[i], Zij_t_Wi[i], ord) - TaylorSeries.pow!(tmp1487[i], Rij_dot_Vi[i], 2, ord) - TaylorSeries.div!(pn1t7[i], tmp1487[i], r_p2[i], ord) - TaylorSeries.mul!(tmp1490[i], 1.5, pn1t7[i], ord) - TaylorSeries.subst!(pn1t2_7[i], ϕs_and_vs[i], tmp1490[i], ord) + TaylorSeries.add!(tmp6355[i], Xij_t_Ui[i], Yij_t_Vi[i], ord) + TaylorSeries.add!(Rij_dot_Vi[i], tmp6355[i], Zij_t_Wi[i], ord) + TaylorSeries.pow!(tmp6358[i], Rij_dot_Vi[i], 2, ord) + TaylorSeries.div!(pn1t7[i], tmp6358[i], r_p2[i], ord) + TaylorSeries.mul!(tmp6361[i], 1.5, pn1t7[i], ord) + TaylorSeries.subst!(pn1t2_7[i], ϕs_and_vs[i], tmp6361[i], ord) TaylorSeries.add!(pn1t1_7[i], c_p2, pn1t2_7[i], ord) TaylorSeries.mul!(pNX_t_X[i], acceph_t[3i - 2], X[i], ord) TaylorSeries.mul!(pNY_t_Y[i], acceph_t[3i - 1], Y[i], ord) TaylorSeries.mul!(pNZ_t_Z[i], acceph_t[3i], Z[i], ord) - TaylorSeries.add!(tmp1497[i], pNX_t_X[i], pNY_t_Y[i], ord) - TaylorSeries.add!(tmp1498[i], tmp1497[i], pNZ_t_Z[i], ord) - TaylorSeries.mul!(tmp1499[i], 0.5, tmp1498[i], ord) - TaylorSeries.add!(pn1[i], pn1t1_7[i], tmp1499[i], ord) + TaylorSeries.add!(tmp6368[i], pNX_t_X[i], pNY_t_Y[i], ord) + TaylorSeries.add!(tmp6369[i], tmp6368[i], pNZ_t_Z[i], ord) + TaylorSeries.mul!(tmp6370[i], 0.5, tmp6369[i], ord) + TaylorSeries.add!(pn1[i], pn1t1_7[i], tmp6370[i], ord) TaylorSeries.mul!(X_t_pn1[i], newton_acc_X[i], pn1[i], ord) TaylorSeries.mul!(Y_t_pn1[i], newton_acc_Y[i], pn1[i], ord) TaylorSeries.mul!(Z_t_pn1[i], newton_acc_Z[i], pn1[i], ord) @@ -2950,20 +3202,20 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorSeries.mul!(pNZ_t_pn3[i], acceph_t[3i], pn3[i], ord) end for i = 1:10 - TaylorSeries.add!(tmp1507[i], U_t_pn2[i], pNX_t_pn3[i], ord) - TaylorSeries.add!(termpnx[i], X_t_pn1[i], tmp1507[i], ord) + TaylorSeries.add!(tmp6378[i], U_t_pn2[i], pNX_t_pn3[i], ord) + TaylorSeries.add!(termpnx[i], X_t_pn1[i], tmp6378[i], ord) TaylorSeries.add!(sumpnx[i], pntempX, termpnx[i], ord) TaylorSeries.identity!(pntempX, sumpnx[i], ord) - TaylorSeries.add!(tmp1510[i], V_t_pn2[i], pNY_t_pn3[i], ord) - TaylorSeries.add!(termpny[i], Y_t_pn1[i], tmp1510[i], ord) + TaylorSeries.add!(tmp6381[i], V_t_pn2[i], pNY_t_pn3[i], ord) + TaylorSeries.add!(termpny[i], Y_t_pn1[i], tmp6381[i], ord) TaylorSeries.add!(sumpny[i], pntempY, termpny[i], ord) TaylorSeries.identity!(pntempY, sumpny[i], ord) - TaylorSeries.add!(tmp1513[i], W_t_pn2[i], pNZ_t_pn3[i], ord) - TaylorSeries.add!(termpnz[i], Z_t_pn1[i], tmp1513[i], ord) + TaylorSeries.add!(tmp6384[i], W_t_pn2[i], pNZ_t_pn3[i], ord) + TaylorSeries.add!(termpnz[i], Z_t_pn1[i], tmp6384[i], ord) TaylorSeries.add!(sumpnz[i], pntempZ, termpnz[i], ord) TaylorSeries.identity!(pntempZ, sumpnz[i], ord) end - #= C:\Users\luisi\.julia\dev\NEOs.jl\cosa.jl:500 =# Threads.@threads for i = 11:Nm1 + #= /Users/Jorge/projects/neos240702/neosjetcoeffs.jl:1084 =# Threads.@threads for i = 11:Nm1 TaylorSeries.mul!(X_t_pn1[i], c_p2, newton_acc_X[i], ord) TaylorSeries.mul!(Y_t_pn1[i], c_p2, newton_acc_Y[i], ord) TaylorSeries.mul!(Z_t_pn1[i], c_p2, newton_acc_Z[i], ord) @@ -2990,4 +3242,4 @@ function TaylorIntegration.jetcoeffs!(::Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, end end return nothing -end \ No newline at end of file +end diff --git a/test/propagation.jl b/test/propagation.jl index f0bcf841..8ba56cbe 100644 --- a/test/propagation.jl +++ b/test/propagation.jl @@ -26,7 +26,6 @@ using InteractiveUtils: methodswith @testset "Orbit propagation without nongravs: 2023 DW" begin - objname = "2023DW" # Dynamical function dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! # Initial time [Julian date] @@ -151,7 +150,6 @@ using InteractiveUtils: methodswith @testset "Orbit propagation with nongravs: (99942) Apophis" begin - objname = "Apophis" # Dynamical function dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! # Initial time [Julian date] @@ -270,15 +268,20 @@ using InteractiveUtils: methodswith # Time of integration [years] nyears = 0.02 # Perturbation to nominal initial condition (Taylor1 jet transport) - dq = NEOs.scaled_variables() + dq = NEOs.scaled_variables(order=1) # Initial conditions q0 = [-0.9170913888342959, -0.37154308794738056, -0.1610606989484252, - 0.009701519087787077, -0.012766026792868212, -0.0043488589639194275] .+ dq + 0.009701519087787077, -0.012766026792868212, -0.0043488589639194275] + dq # Propagation parameters params = NEOParameters(maxsteps = 10, order = 25, abstol = 1e-20, parse_eqs = true) - # Propagate orbit - sol = NEOs.propagate(dynamics, jd0, nyears, q0, params) + # test parsed vs non-parsed propagation + sol = NEOs.propagate(dynamics, jd0, 1.0, q0, params) + params = NEOParameters(params, parse_eqs = false) + solnp = NEOs.propagate(dynamics, jd0, 1.0, q0, params) + @test sol.t == solnp.t + # TODO: fix roundoff differences near deep close approach in 2029 + @test norm(sol.x-solnp.x, Inf)/norm(solnp.x, Inf) < 4e-18 # 3.757708512785821e-20 jldsave("test.jld2"; sol) recovered_sol = JLD2.load("test.jld2", "sol") @test sol == recovered_sol @@ -311,24 +314,41 @@ using InteractiveUtils: methodswith @testset "Jet transport orbit propagation and astrometric observables: (99942) Apophis" begin - objname::String = "Apophis" - # Dynamical function - dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! - # Initial date of integration [julian days] - jd0::Float64 = datetime2julian(DateTime(2004, 6, 1)) - # Time of integration [years] + # Dynamical functions + dynamicsg = RNp1BP_pN_A_J23E_J2S_eph_threads! + dynamicsng = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! + # integration parameters nyears::Float64 = 10.0 - # JPL #199 solution for Apophis at June 1st, 2004 - q00::Vector{Float64} = [-1.0506627988664696, -0.060643124245514164, -0.0499709975200415, 0.0029591416313078838, -0.014232335581939919, -0.0052184125285361415, -2.898870403031058e-14, -0.0] varorder::Int = 1 - dq::Vector{TaylorN{Float64}} = NEOs.scaled_variables("δx", vcat(fill(1e-8, 6), 1e-14), order = varorder) - q0::Vector{TaylorN{Float64}} = q00 .+ vcat(dq, 0dq[1]) - # Propagation parameters - params = NEOParameters(maxsteps = 2_000, order = 25, abstol = 1e-20, parse_eqs = true) - - # Propagate orbit + jd0::Float64 = datetime2julian(DateTime(2004,6,1)) #Julian date of integration initial time + # 7-DOF nominal solution from pha/apophis.jl script at epoch 2004-06-01T00:00:00.000 (TDB) + q00::Vector{Float64} = [-1.0506627988664696, -0.060643124245514164, -0.0499709975200415, 0.0029591416313078838, -0.014232335581939919, -0.0052184125285361415, -2.898870403031058e-14, 0.0] + scalings::Vector{Float64} = vcat(fill(1e-8, 6), 1e-14) + dq::Vector{TaylorN{Float64}} = NEOs.scaled_variables("δx", scalings, order = varorder) + q0::Vector{TaylorN{Float64}} = q00 + vcat(dq, zero(dq[1])) + + # test parsed vs non-parsed propagation: gravity-only model + params = NEOParameters(maxsteps=10, order=25, abstol=1e-20, parse_eqs=true) + sol = NEOs.propagate(dynamicsg, jd0, nyears, q0[1:6], params) + params = NEOParameters(params, parse_eqs=false) + solnp = NEOs.propagate(dynamicsg, jd0, nyears, q0[1:6], params) + @test sol.t == solnp.t + @test norm(sol.x-solnp.x, Inf) < 1e-16 + @test sol == solnp + + # test parsed vs non-parsed propagation: nongravitational model + params = NEOParameters(params, parse_eqs=true) + sol = NEOs.propagate(dynamicsng, jd0, nyears, q0, params) + params = NEOParameters(params, parse_eqs=false) + solnp = NEOs.propagate(dynamicsng, jd0, nyears, q0, params) + @test sol.t == solnp.t + @test norm(sol.x-solnp.x, Inf) < 1e-16 + @test sol == solnp + + # propagate orbit (nongrav model) + params = NEOParameters(params, maxsteps = 2_000, parse_eqs = true) sol = NEOs.propagate( - dynamics, + dynamicsng, jd0, nyears, q0, @@ -342,17 +362,21 @@ using InteractiveUtils: methodswith # Earth's ephemeris eph_ea = selecteph(sseph_obs, ea) + # Apophis + # Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec + xva(et) = auday2kmsec(sol(et/daysec)) + # Earth + # Change x, v units, resp., from au, au/day to km, km/sec + xve(et) = auday2kmsec(eph_ea(et/daysec)) + # Sun + # Change x, v units, resp., from au, au/day to km, km/sec + xvs(et) = auday2kmsec(eph_su(et/daysec)) + # Read optical astrometry file obs_radec_mpc_apophis = read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) # Compute optical astrometry residuals - _res_radec_ = NEOs.residuals( - obs_radec_mpc_apophis, - params, - xve = t -> auday2kmsec(eph_ea(t/daysec)), - xvs = t -> auday2kmsec(eph_su(t/daysec)), - xva = t -> auday2kmsec(sol(t/daysec)) - ) + _res_radec_ = NEOs.residuals(obs_radec_mpc_apophis, params; xvs, xve, xva) res_radec, w_radec = NEOs.unfold(_res_radec_) nobsopt = round(Int, length(res_radec)) @@ -376,29 +400,27 @@ using InteractiveUtils: methodswith deldop_2005_2013 = NEOs.read_radar_jpl(joinpath("data", "99942_RADAR_2005_2013.dat")) # Compute mean radar (time-delay and Doppler-shift) residuals - @time res_del, w_del, res_dop, w_dop = residuals( - deldop_2005_2013[1:4], - xve = t -> auday2kmsec(eph_ea(t/daysec)), - xvs = t -> auday2kmsec(eph_su(t/daysec)), - xva = t -> auday2kmsec(sol(t/daysec)), - niter=10, - tord=10 - ) + @time res_del, w_del, res_dop, w_dop = residuals(deldop_2005_2013[1:4]; xvs, xve, + xva, niter=10, tord=10) + # Doppler astrometry normalized residuals (i.e., residual/sigma) at nominal solution @test abs(res_dop[1]()) ≤ deldop_2005_2013[1].Δν_σ - @test abs(res_del[1]()) ≤ deldop_2005_2013[2].Δτ_σ @test abs(res_dop[2]()) ≤ deldop_2005_2013[2].Δν_σ - @test abs(res_del[2]()) ≤ deldop_2005_2013[2].Δτ_σ @test abs(res_dop[3]()) ≤ deldop_2005_2013[3].Δν_σ @test abs(res_dop[4]()) ≤ deldop_2005_2013[4].Δν_σ + # delay astrometry normalized residuals (i.e., residual/sigma) at nominal solution + @test abs(res_del[1]()) ≤ deldop_2005_2013[2].Δτ_σ + @test abs(res_del[2]()) ≤ deldop_2005_2013[2].Δτ_σ dq_sample = 2ones(7) - @test abs(res_dop[1](dq_sample)) ≥ deldop_2005_2013[1].Δν_σ - @test abs(res_del[1](dq_sample)) ≥ deldop_2005_2013[2].Δτ_σ - @test abs(res_dop[2](dq_sample)) ≥ deldop_2005_2013[2].Δν_σ - @test abs(res_del[2](dq_sample)) ≥ deldop_2005_2013[2].Δτ_σ - @test abs(res_dop[3](dq_sample)) ≥ deldop_2005_2013[3].Δν_σ - @test abs(res_dop[4](dq_sample)) ≥ deldop_2005_2013[4].Δν_σ + # Doppler astrometry normalized residuals at non-nominal solution + @test abs(res_dop[1]()) ≤ abs(res_dop[1](dq_sample)) + @test abs(res_dop[2]()) ≤ abs(res_dop[2](dq_sample)) + @test abs(res_dop[3]()) ≤ abs(res_dop[3](dq_sample)) + @test abs(res_dop[4]()) ≤ abs(res_dop[4](dq_sample)) + # delay astrometry normalized residuals at non-nominal solution + @test abs(res_del[1]()) ≤ abs(res_del[1](dq_sample)) + @test abs(res_del[2]()) ≤ abs(res_del[2](dq_sample)) end end From c9099e490fecc74fc3c3e766ad6cf9c0e82c96b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20P=C3=A9rez-Hern=C3=A1ndez?= Date: Wed, 28 Feb 2024 17:33:14 +0100 Subject: [PATCH 149/173] Fix tests --- test/propagation.jl | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/test/propagation.jl b/test/propagation.jl index 8ba56cbe..557fb83e 100644 --- a/test/propagation.jl +++ b/test/propagation.jl @@ -41,12 +41,10 @@ using InteractiveUtils: methodswith # Initial time [days since J2000] t0 = jd0 - PE.J2000 - # Solar System ephemeris - sseph = loadpeeph(NEOs.sseph, t0 - nyears*yr, t0 + nyears*yr) # Sun's ephemeris - eph_su = selecteph(sseph, su) + eph_su = selecteph(NEOs.sseph, su, t0 - nyears*yr, t0 + nyears*yr) # Earth's ephemeris - eph_ea = selecteph(sseph, ea) + eph_ea = selecteph(NEOs.sseph, ea, t0 - nyears*yr, t0 + nyears*yr) # Warmup propagation (forward) NEOs.propagate( @@ -166,12 +164,10 @@ using InteractiveUtils: methodswith # Initial time [days since J2000] t0 = jd0 - PE.J2000 - # Solar System ephemeris - sseph = loadpeeph(NEOs.sseph, t0, t0 + nyears*yr) # Sun's ephemeris - eph_su = selecteph(sseph, su) + eph_su = selecteph(NEOs.sseph, su, t0, t0 + nyears*yr) # Earth's ephemeris - eph_ea = selecteph(sseph, ea) + eph_ea = selecteph(NEOs.sseph, ea, t0, t0 + nyears*yr) # Warmup propagation sol = NEOs.propagate( @@ -355,12 +351,10 @@ using InteractiveUtils: methodswith params ) - # Solar System ephemeris - sseph_obs = loadpeeph(NEOs.sseph, sol.t0, sol.t0 + sol.t[end]) # Sun's ephemeris - eph_su = selecteph(sseph_obs, su) + eph_su = selecteph(NEOs.sseph, su, sol.t0, sol.t0 + sol.t[end]) # Earth's ephemeris - eph_ea = selecteph(sseph_obs, ea) + eph_ea = selecteph(NEOs.sseph, ea, sol.t0, sol.t0 + sol.t[end]) # Apophis # Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec From 2643a10e6f76b3224976bd783abb4ea76c33206f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 8 Mar 2024 08:42:26 -0600 Subject: [PATCH 150/173] Custom print for AdmissibleRegion --- src/orbit_determination/tooshortarc.jl | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index d7b3ee78..aef30782 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -55,6 +55,20 @@ end iszero(x::AdmissibleRegion{T}) where {T <: AbstractFloat} = x == zero(AdmissibleRegion{T}) +# Print method for AdmissibleRegion +# Examples: +# AE: [11.55523, 13.29296, -1.01625, -0.55432] t: 2019-10-23T05:23:27.384 obs: Palomar Mountain--ZTF +# AE: [358.56604, 1.25546, -2.05305, -1.91538] t: 2019-11-01T09:03:26.280 obs: Pan-STARRS 1, Haleakala +function show(io::IO, A::AdmissibleRegion{T}) where {T <: Real} + v = string( + @sprintf("%.5f", rad2deg(A.α)), ", ", + @sprintf("%.5f", rad2deg(A.δ)), ", ", + @sprintf("%.5f", rad2deg(A.v_α)), ", ", + @sprintf("%.5f", rad2deg(A.v_δ)), "", + ) + print(io, "AE: [", v, "]", " t: ", A.date, " obs: ", A.observatory.name) +end + # Outer constructor function AdmissibleRegion(tracklet::Tracklet{T}, params::NEOParameters{T}) where {T <: AbstractFloat} # Unfold From 66c3e8b5bc58bab8543ed47242e569eb70f32143 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 8 Mar 2024 14:46:45 -0600 Subject: [PATCH 151/173] Change Gauss/TSA order in OD --- src/NEOs.jl | 2 +- .../orbit_determination.jl | 32 +++++++++---------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index 606cd9b7..b68f47d4 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -72,7 +72,7 @@ export gauss_method, gaussinitcond, gauss_refinement # Outlier rejection export outlier_rejection # Orbit determination -export issinglearc, istsa, orbitdetermination +export issinglearc, isgauss, orbitdetermination include("constants.jl") include("observations/process_radar.jl") diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index 7aad0ece..00e31888 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -20,28 +20,25 @@ function issinglearc(radec::Vector{RadecMPC{T}}, arc::Day = Day(30)) where {T <: end @doc raw""" - istsa(tracklets::Vector{Tracklet{T}}) where {T <: AbstractFloat} - istsa(sol::NEOSolution{T, T}) where {T <: AbstractFloat} + isgauss(sol::NEOSolution{T, T}) where {T <: AbstractFloat} -Check whether `sol` was computed via [`tooshortarc`](@ref) (`true`) or -via [`gaussinitcond`](@ref) (`false`). +Check whether `sol` was computed via [`gaussinitcond`](@ref) (`true`) or +via [`tooshortarc`](@ref) (`false`). """ -function istsa(tracklets::Vector{Tracklet{T}}) where {T <: AbstractFloat} +function isgauss(tracklets::Vector{Tracklet{T}}) where {T <: AbstractFloat} # Observing stations obs = observatory.(tracklets) - # Satellite observatories can only be handled by Gauss - any(issatellite.(obs)) && return false + # TSA is not well suited for satellite observatories + any(issatellite.(obs)) && return true # Gauss cannot handle less than 3 tracklets - length(tracklets) < 3 && return true + length(tracklets) < 3 && return false # Time span Δ = numberofdays(tracklets) # Gauss aproximation do not work with less than 1 day - Δ < 1 && return true - # All observations come from the same observatory - return allequal(obs) && Δ < 5 + return Δ > 1 end -istsa(sol::NEOSolution{T, T}) where {T <: AbstractFloat} = istsa(sol.tracklets) +isgauss(sol::NEOSolution{T, T}) where {T <: AbstractFloat} = isgauss(sol.tracklets) @doc raw""" adaptative_maxsteps(radec::Vector{RadecMPC{T}}) where {T <: AbstractFloat} @@ -91,13 +88,14 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, params::NEOParameters{T} end # Reduce tracklets by polynomial regression tracklets = reduce_tracklets(radec) - # Case 1: Too Short Arc (TSA) - if istsa(tracklets) - sol = tooshortarc(radec, tracklets, params; dynamics) - # Case 2: Gauss Method - else + # Case 1: Gauss Method + if isgauss(tracklets) sol = gaussinitcond(radec, tracklets, params; dynamics) end + # Case 2: Too Short Arc (TSA) + if iszero(sol) || nrms(sol) > params.gaussQmax + sol = tooshortarc(radec, tracklets, params; dynamics) + end return sol::NEOSolution{T, T} end From 2957a5d9cca5b6dc7bb906f9f31704186ddb9c18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Fri, 8 Mar 2024 15:19:44 -0600 Subject: [PATCH 152/173] jplcompare --- src/NEOs.jl | 4 ++-- src/orbit_determination/neosolution.jl | 27 +++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index b68f47d4..6f7044a9 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -26,8 +26,8 @@ using StatsBase: mean, std using LsqFit: curve_fit using Roots: find_zeros using Clustering: kmeans - using Downloads: download +using HORIZONS: smb_spk # Constants export d_EM_km, d_EM_au @@ -72,7 +72,7 @@ export gauss_method, gaussinitcond, gauss_refinement # Outlier rejection export outlier_rejection # Orbit determination -export issinglearc, isgauss, orbitdetermination +export jplcompare, issinglearc, isgauss, orbitdetermination include("constants.jl") include("observations/process_radar.jl") diff --git a/src/orbit_determination/neosolution.jl b/src/orbit_determination/neosolution.jl index f6b7cf2a..d5dd57c7 100644 --- a/src/orbit_determination/neosolution.jl +++ b/src/orbit_determination/neosolution.jl @@ -169,4 +169,29 @@ function nms(sol::NEOSolution{T, T}) where {T <: Real} end end -sigmas(sol::NEOSolution{T, T}) where {T <: Real} = sqrt.(diag(sol.fit.Γ)) .* sol.scalings \ No newline at end of file +sigmas(sol::NEOSolution{T, T}) where {T <: Real} = sqrt.(diag(sol.fit.Γ)) .* sol.scalings + +@doc raw""" + jplcompare(des::String, sol::NEOSolution{T, U}) where {T <: Real, U <: Number} + +Return `abs.(sol() - R) ./ sigmas(sol)`, where `R` is JPL's state vector of object +`des` at `sol`'s initial epoch. +""" +function jplcompare(des::String, sol::NEOSolution{T, U}) where {T <: Real, U <: Number} + # NEOs barycentric state vector + q1 = cte.(sol()) + # Time of first (last) observation + t0, tf = date(sol.tracklets[1].radec[1]), date(sol.tracklets[end].radec[end]) + # Download JPL ephemerides + bsp = smb_spk("DES = $(des);", t0, tf) + # Object ID + id = parse(Int, bsp[1:end-4]) + # Load JPL ephemerides + furnsh(bsp) + # Delete ephemerides file + rm(bsp) + # JPL barycentric state vector + q2 = kmsec2auday(spkgeo(id, julian2etsecs(sol.bwd.t0 + PE.J2000), "J2000", 0)[1]) + # Absolute difference in sigma units + return abs.(q1 - q2) ./ sigmas(sol) +end \ No newline at end of file From c025b76ff4ccbbe5a4aae1fc953ff4a172c53d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20P=C3=A9rez-Hern=C3=A1ndez?= Date: Sun, 10 Mar 2024 22:58:04 +0100 Subject: [PATCH 153/173] Update Apophis script --- pha/Project.toml | 2 +- pha/apophis.jl | 25 ++++++++++++------------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/pha/Project.toml b/pha/Project.toml index bd0ff937..dbbe504c 100644 --- a/pha/Project.toml +++ b/pha/Project.toml @@ -14,4 +14,4 @@ StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" TaylorIntegration = "92b13dbe-c966-51a2-8445-caca9f8a7d42" [compat] -NEOs = "0.7" +NEOs = "0.8" diff --git a/pha/apophis.jl b/pha/apophis.jl index 7c8bdca8..92143233 100644 --- a/pha/apophis.jl +++ b/pha/apophis.jl @@ -124,10 +124,9 @@ function main(dynamics::D, maxsteps::Int, jd0_datetime::DateTime, nyears_bwd::T, jd0 = datetime2julian(jd0_datetime) print_header("Integrator warmup", 2) - _ = NEOs.propagate(dynamics, 1, jd0, nyears_fwd, q0, Val(true); - order, abstol, parse_eqs) - _ = NEOs.propagate_root(dynamics, 1, jd0, nyears_fwd, q0, Val(true); - order, abstol, parse_eqs) + params = NEOParameters(;maxsteps=1, order, abstol, parse_eqs) + _ = NEOs.propagate(dynamics, jd0, nyears_fwd, q0, params) + _ = NEOs.propagate_root(dynamics, jd0, nyears_fwd, q0, params) println() print_header("Main integration", 2) @@ -135,8 +134,8 @@ function main(dynamics::D, maxsteps::Int, jd0_datetime::DateTime, nyears_bwd::T, println("• Initial time of integration: ", string(jd0_datetime)) println("• Final time of integration: ", julian2datetime(jd0 + tmax)) - sol_bwd = NEOs.propagate(dynamics, maxsteps, jd0, nyears_bwd, q0, Val(true); - order, abstol, parse_eqs) + params = NEOParameters(;maxsteps, order, abstol, parse_eqs) + sol_bwd = NEOs.propagate(dynamics, jd0, nyears_bwd, q0, params) jldsave("Apophis_bwd.jld2"; sol_bwd) # sol_bwd = JLD2.load("Apophis_bwd.jld2", "sol_bwd") @@ -144,16 +143,15 @@ function main(dynamics::D, maxsteps::Int, jd0_datetime::DateTime, nyears_bwd::T, println("• Initial time of integration: ", string(jd0_datetime)) println("• Final time of integration: ", julian2datetime(jd0 + tmax)) - sol_fwd, tvS, xvS, gvS = NEOs.propagate_root(dynamics, maxsteps, jd0, nyears_fwd, q0, Val(true); - order, abstol, parse_eqs) + sol_fwd, tvS, xvS, gvS = NEOs.propagate_root(dynamics, jd0, nyears_fwd, q0, params) jldsave("Apophis_fwd.jld2"; sol_fwd, tvS, xvS, gvS) # sol_fwd = JLD2.load("Apophis_fwd.jld2", "sol_bwd") println() - # load Solar System ephemeris - sseph::TaylorInterpolant{Float64,Float64,2} = loadpeeph(NEOs.sseph, sol_bwd.t0+sol_bwd.t[end], sol_fwd.t0+sol_fwd.t[end]) - eph_su::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, su) - eph_ea::TaylorInterpolant{Float64,Float64,2} = selecteph(sseph, ea) + # Load Sun ephemeris + eph_su = selecteph(NEOs.sseph, su, sol_bwd.t0+sol_bwd.t[end], sol_fwd.t0+sol_fwd.t[end]) + # Load Earth ephemeris + eph_ea = selecteph(NEOs.sseph, ea, sol_bwd.t0+sol_bwd.t[end], sol_fwd.t0+sol_fwd.t[end]) # Apophis # Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec @@ -175,7 +173,8 @@ function main(dynamics::D, maxsteps::Int, jd0_datetime::DateTime, nyears_bwd::T, deldop = vcat(deldop_2005_2013,deldop_2021) # Compute optical residuals - res_radec_all, w_radec_all = NEOs.residuals(radec; xvs, xve, xva) + _res_radec_all_ = NEOs.residuals(radec; xvs, xve, xva) + res_radec_all, w_radec_all = NEOs.unfold(_res_radec_all_) jldsave("Apophis_res_w_radec.jld2"; res_radec_all, w_radec_all) # JLD2.@load "Apophis_res_w_radec.jld2" From d9b9671eff203437766e8421581b5c69bf89539e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sun, 10 Mar 2024 16:19:27 -0600 Subject: [PATCH 154/173] Custom print for NEOParameters --- src/orbit_determination/neosolution.jl | 2 ++ src/propagation/parameters.jl | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/orbit_determination/neosolution.jl b/src/orbit_determination/neosolution.jl index d5dd57c7..176fe035 100644 --- a/src/orbit_determination/neosolution.jl +++ b/src/orbit_determination/neosolution.jl @@ -178,6 +178,8 @@ Return `abs.(sol() - R) ./ sigmas(sol)`, where `R` is JPL's state vector of obje `des` at `sol`'s initial epoch. """ function jplcompare(des::String, sol::NEOSolution{T, U}) where {T <: Real, U <: Number} + # Load Solar System ephemerides + loadjpleph() # NEOs barycentric state vector q1 = cte.(sol()) # Time of first (last) observation diff --git a/src/propagation/parameters.jl b/src/propagation/parameters.jl index 4136429a..8ce1d012 100644 --- a/src/propagation/parameters.jl +++ b/src/propagation/parameters.jl @@ -31,6 +31,23 @@ struct NEOParameters{T <: AbstractFloat} # Inner constructor is generated by default end +# Print method for NEOParameters +function show(io::IO, p::NEOParameters{T}) where {T <: AbstractFloat} + params = [ + :maxsteps, :order, :abstol, :parse_eqs, :bwdoffset, + :fwdoffset, :coeffstol, :niter, :max_triplets, :varorder, + :gaussQmax, :H_max, :a_max, :maxiter, :tsaQmax, :max_per + ] + s = Vector{String}(undef, length(params)+1) + s[1] = "NEOParameters{$T}:\n" + for i in eachindex(params) + x = string(params[i], ":") + s[i+1] = string(" ", rpad(x, 15), getfield(p, params[i]), "\n") + end + + print(io, join(s)) +end + # Outer constructors @doc raw""" From 733a468c95c3b2bd583eb48e80c3bcf323d9d52b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20P=C3=A9rez-Hern=C3=A1ndez?= Date: Wed, 20 Mar 2024 20:30:17 +0100 Subject: [PATCH 155/173] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index de1ec3b5..b72ace97 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ notebooks/figs EOP_IAU*.TXT Manifest.toml *.DS_Store +.vscode \ No newline at end of file From 3008fbd8183da4954e9ae3e7cd74c0aedc63d6a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20P=C3=A9rez-Hern=C3=A1ndez?= Date: Wed, 20 Mar 2024 20:42:47 +0100 Subject: [PATCH 156/173] Update some comments and docstrings --- src/orbit_determination/gauss_method.jl | 4 ++-- src/orbit_determination/orbit_determination.jl | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 095d51e1..6fce2045 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -537,10 +537,10 @@ function gaussinitcond(radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T} end end - # Case: all solutions were unsuccesful + # Case: all solutions were unsuccessful if isinf(best_Q) return zero(NEOSolution{T, T}) - # Case: at least one solution was succesful + # Case: at least one solution was successful else return best_sol end diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index 00e31888..8bd2f012 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -8,7 +8,7 @@ include("gauss_method.jl") issinglearc(radec::Vector{RadecMPC{T}}, arc::Day = Day(30)) where {T <: AbstractFloat} Check whether `radec` is a single observational arc, i.e. no two consecutive observations -are more than `arc` days appart. The function assumes `radec` is sorted. +are more than `arc` days apart. The function assumes `radec` is sorted. """ function issinglearc(radec::Vector{RadecMPC{T}}, arc::Day = Day(30)) where {T <: AbstractFloat} for i in 2:length(radec) @@ -34,7 +34,7 @@ function isgauss(tracklets::Vector{Tracklet{T}}) where {T <: AbstractFloat} length(tracklets) < 3 && return false # Time span Δ = numberofdays(tracklets) - # Gauss aproximation do not work with less than 1 day + # Gauss approximation does not work with less than 1 day return Δ > 1 end @@ -76,7 +76,7 @@ Initial Orbit Determination (IOD) routine. function orbitdetermination(radec::Vector{RadecMPC{T}}, params::NEOParameters{T}; dynamics::D = newtonian!) where {T <: AbstractFloat, D} - # Allocate memory for output + # Allocate NEOSolution for output sol = zero(NEOSolution{T, T}) # Maximum number of steps params = NEOParameters(params; maxsteps = adaptative_maxsteps(radec)) From a5d2680d773dec6496cc5af7d673b684f411d22a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 20 Mar 2024 15:02:40 -0600 Subject: [PATCH 157/173] Fix initial guess in LS --- src/orbit_determination/least_squares.jl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/orbit_determination/least_squares.jl b/src/orbit_determination/least_squares.jl index 83d686f1..4c0dc8ff 100644 --- a/src/orbit_determination/least_squares.jl +++ b/src/orbit_determination/least_squares.jl @@ -461,9 +461,11 @@ function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, # Mean square residual Q = chi2(res, w)/nobs # Vector of x - x = zeros(T, npar, niters + 1) + x = Matrix{T}(undef, npar, niters + 1) # First guess - x[:, 1] = x0 + for i in size(x, 2) + x[:, i] .= x0 + end # Vector of errors error = Vector{T}(undef, niters + 1) # Error of first guess @@ -571,9 +573,11 @@ function levenbergmarquardt(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T} # Pre-allocate memory _dQ_ = zeros(T, npar) _d2Q_ = zeros(T, npar, npar) - x = zeros(T, npar, niters + 1) + x = Matrix{T}(undef, npar, niters + 1) # First guess - x[:, 1] = x0 + for i in size(x, 2) + x[:, i] .= x0 + end # Iteration for i in 1:niters # Current x From 25c4c171e5bb718d844dfefe55df73f719c48d4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 20 Mar 2024 15:12:30 -0600 Subject: [PATCH 158/173] Allow jd0::U in tooshortarc --- src/orbit_determination/tooshortarc.jl | 39 ++++++++++++++++---------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index aef30782..19615075 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -343,37 +343,46 @@ function bary2topo(A::AdmissibleRegion{T}, q0::Vector{U}) where {T <: AbstractFl end @doc raw""" - attr2bary(A::AdmissibleRegion{T}, a::Vector{U}) where {T <: AbstractFloat, U <: Number} + attr2bary(A::AdmissibleRegion{T}, a::Vector{U}, + params::NEOParameters{T}) where {T <: AbstractFloat, U <: Number} -Convert attributable elements `a` to to barycentric cartesian coordinates. -`A` fixes the observer. +Convert attributable elements `a` to barycentric cartesian coordinates. """ -function attr2bary(A::AdmissibleRegion{T}, a::Vector{U}) where {T <: AbstractFloat, U <: Number} +function attr2bary(A::AdmissibleRegion{T}, a::Vector{U}, + params::NEOParameters{T}) where {T <: AbstractFloat, U <: Number} # Unfold α, δ, v_α, v_δ, ρ, v_ρ = a + # Light-time correction to epoch + t = datetime2days(A.date) - ρ/c_au_per_day + et = julian2etsecs(datetime2julian(A.date) - cte(cte(ρ))/c_au_per_day) + # Line of sight vectors ρ_unit, ρ_α, ρ_δ = topounitpdv(α, δ) + # Heliocentric position of the observer + q = params.eph_ea(t) + kmsec2auday(obsposvelECI(A.observatory, et)) - params.eph_su(t) # Barycentric position - r = A.q[1:3] + ρ * ρ_unit + sseph(su, datetime2days(A.date))[1:3] + r = q[1:3] + ρ * ρ_unit + params.eph_su(t)[1:3] # Barycentric velocity - v = A.q[4:6] + v_ρ * ρ_unit + ρ * v_α * ρ_α + ρ * v_δ * ρ_δ - + sseph(su, datetime2days(A.date))[4:6] + v = q[4:6] + v_ρ * ρ_unit + ρ * v_α * ρ_α + ρ * v_δ * ρ_δ + + params.eph_su(t)[4:6] # Barycentric state vector return vcat(r, v) end # Propagate an orbit and compute residuals -function propres(radec::Vector{RadecMPC{T}}, jd0::T, q0::Vector{U}, - params::NEOParameters{T}; dynamics::D=newtonian!) where {D, T <: AbstractFloat, U <: Number} +function propres(radec::Vector{RadecMPC{T}}, jd0::U, q0::Vector{V}, params::NEOParameters{T}; + dynamics::D = newtonian!) where {D, T <: AbstractFloat, U <: Number, V <: Number} # Time of first (last) observation t0, tf = datetime2julian(date(radec[1])), datetime2julian(date(radec[end])) + # Epoch (plain) + _jd0_ = cte(cte(jd0)) # Years in backward (forward) integration - nyears_bwd = -(jd0 - t0 + params.bwdoffset) / yr - nyears_fwd = (tf - jd0 + params.fwdoffset) / yr + nyears_bwd = -(_jd0_ - t0 + params.bwdoffset) / yr + nyears_fwd = (tf - _jd0_ + params.fwdoffset) / yr # Backward (forward) integration bwd = propagate(dynamics, jd0, nyears_bwd, q0, params) fwd = propagate(dynamics, jd0, nyears_fwd, q0, params) - if !issuccessfulprop(bwd, t0 - jd0; tol = params.coeffstol) || - !issuccessfulprop(fwd, tf - jd0; tol = params.coeffstol) + if !issuccessfulprop(bwd, t0 - _jd0_; tol = params.coeffstol) || + !issuccessfulprop(fwd, tf - _jd0_; tol = params.coeffstol) return bwd, fwd, Vector{OpticalResidual{T, U}}(undef, 0) end # O-C residuals @@ -443,7 +452,7 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T # Attributable elements a = vcat(LOS + dq[1:4], ρ, v_ρ) # Barycentric state vector - q = attr2bary(A, a) + q = attr2bary(A, a, params) # Propagation and residuals _, _, res = propres(radec, jd0 - ρ/c_au_per_day, q, params; dynamics) iszero(length(res)) && break @@ -458,7 +467,7 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T a = vcat(a0[1:4], 10^(x + dq[5]), v_ρ + dq[6]) end # Barycentric state vector - q = attr2bary(A, a) + q = attr2bary(A, a, params) # Propagation and residuals _, _, res = propres(radec, jd0 - ρ/c_au_per_day, q, params; dynamics) iszero(length(res)) && break From abf94960ab7e8d53c2fd1a3614a3ccb387a527d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 20 Mar 2024 15:18:23 -0600 Subject: [PATCH 159/173] Allow jdo::U in propagation --- src/propagation/propagation.jl | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/propagation/propagation.jl b/src/propagation/propagation.jl index d09927a0..e97f1b93 100644 --- a/src/propagation/propagation.jl +++ b/src/propagation/propagation.jl @@ -66,25 +66,26 @@ function issuccessfulprop(sol::TaylorInterpolant, t::T; tol::T = 10.0) where {T end @doc raw""" - propagate_params(jd0::T, tspan::T, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, - abstol::T = abstol) where {T <: Real, U <: Number} + propagate_params(jd0::U, tspan::T, q0::Vector{V}; μ_ast::Vector = μ_ast343_DE430[1:end], + order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number, V <: Number} Return the parameters needed for `propagate`, `propagate_root` and `propagate_lyap`. # Arguments -- `jd0::T`: initial Julian date. +- `jd0::U`: initial Julian date. - `tspan::T`: time span of the integration [in years]. -- `q0::Vector{U}`: vector of initial conditions. +- `q0::Vector{V}`: vector of initial conditions. - `μ_ast::Vector`: vector of gravitational parameters. - `order::Int`: order of the Taylor expansions to be used in the integration. - `abstol::T`: absolute tolerance. """ -function propagate_params(jd0::T, tspan::T, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, - abstol::T = abstol) where {T <: Real, U <: Number} - +function propagate_params(jd0::U, tspan::T, q0::Vector{V}; μ_ast::Vector = μ_ast343_DE430[1:end], + order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number, V <: Number} + # Epoch (plain) + _jd0_ = cte(cte(jd0)) # Time limits [days since J2000] - days_0, days_f = minmax(jd0, jd0 + tspan*yr) .- JD_J2000 + days_0, days_f = minmax(_jd0_, _jd0_ + tspan*yr) .- JD_J2000 # Load Solar System ephemeris [au, au/day] _sseph = convert(T, loadpeeph(sseph, days_0, days_f)) @@ -130,21 +131,21 @@ function propagate_params(jd0::T, tspan::T, q0::Vector{U}; μ_ast::Vector = μ_a end @doc raw""" - propagate(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, - params::NEOParameters{T}) where {T <: Real, U <: Number, D} + propagate(dynamics::D, jd0::U, tspan::T, q0::Vector{V}, + params::NEOParameters{T}) where {T <: Real, U <: Number, V <: Number, D} Integrate the orbit of a NEO via the Taylor method. # Arguments - `dynamics::D`: dynamical model function. -- `jd0::T`: initial Julian date. +- `jd0::U`: initial Julian date. - `tspan::T`: time span of the integration [in years]. -- `q0::Vector{U}`: vector of initial conditions. +- `q0::Vector{V}`: vector of initial conditions. - `params::NEOParameters{T}`: see [`NEOParameters`](@ref). """ -function propagate(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, - params::NEOParameters{T}) where {T <: Real, U <: Number, D} +function propagate(dynamics::D, jd0::U, tspan::T, q0::Vector{V}, + params::NEOParameters{T}) where {T <: Real, U <: Number, V <: Number, D} # Unfold maxsteps, μ_ast, order, abstol, parse_eqs = params.maxsteps, params.μ_ast, params.order, @@ -162,7 +163,9 @@ function propagate(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, maxsteps = maxsteps, parse_eqs = parse_eqs) if issorted(tv) || issorted(tv, rev = true) - return TaylorInterpolant(jd0 - JD_J2000, tv, psol) + # Epoch (plain) + _jd0_ = cte(cte(jd0)) + return TaylorInterpolant(_jd0_ - JD_J2000, tv, psol) else return zero(TaylorInterpolant{T, U, 2, SubArray{T, 1}, SubArray{Taylor1{U}, 2}}) end From 814d1e15b66204f1f7e4be991f66db67c4afa479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 20 Mar 2024 15:38:02 -0600 Subject: [PATCH 160/173] Fix first guess in LS --- src/orbit_determination/least_squares.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/orbit_determination/least_squares.jl b/src/orbit_determination/least_squares.jl index 4c0dc8ff..8ca8b604 100644 --- a/src/orbit_determination/least_squares.jl +++ b/src/orbit_determination/least_squares.jl @@ -463,7 +463,7 @@ function newtonls(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, # Vector of x x = Matrix{T}(undef, npar, niters + 1) # First guess - for i in size(x, 2) + for i in axes(x, 2) x[:, i] .= x0 end # Vector of errors @@ -575,7 +575,7 @@ function levenbergmarquardt(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T} _d2Q_ = zeros(T, npar, npar) x = Matrix{T}(undef, npar, niters + 1) # First guess - for i in size(x, 2) + for i in axes(x, 2) x[:, i] .= x0 end # Iteration From a54cf8fe4f90185a19a9fe323c7f57527a1888a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Wed, 20 Mar 2024 16:07:08 -0600 Subject: [PATCH 161/173] propagate_params(..., ::NEOParameters{T}) --- src/constants.jl | 1 + src/propagation/propagation.jl | 35 +++++++++++++++------------------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/constants.jl b/src/constants.jl index 23bcd43e..b0d97c25 100644 --- a/src/constants.jl +++ b/src/constants.jl @@ -11,6 +11,7 @@ const sseph::TaylorInterpolant{Float64, Float64, 2, Vector{Float64}, Matrix{Tayl const acceph::TaylorInterpolant{Float64, Float64, 2, Vector{Float64}, Matrix{Taylor1{Float64}}} = JLD2.load(sseph_artifact_path, "acc_eph") const poteph::TaylorInterpolant{Float64, Float64, 2, Vector{Float64}, Matrix{Taylor1{Float64}}} = JLD2.load(sseph_artifact_path, "pot_eph") const ttmtdb::TaylorInterpolant{Float64, Float64, 1, Vector{Float64}, Vector{Taylor1{Float64}}} = TaylorInterpolant(sseph.t0, sseph.t, sseph.x[:,end]) +const SSEPHORDER::Int = get_order(sseph.x[1]) # Earth orientation parameters (eop) 2000 const eop_IAU2000A::EopIau2000A = fetch_iers_eop(Val(:IAU2000A)) diff --git a/src/propagation/propagation.jl b/src/propagation/propagation.jl index e97f1b93..50ed7c1b 100644 --- a/src/propagation/propagation.jl +++ b/src/propagation/propagation.jl @@ -66,8 +66,8 @@ function issuccessfulprop(sol::TaylorInterpolant, t::T; tol::T = 10.0) where {T end @doc raw""" - propagate_params(jd0::U, tspan::T, q0::Vector{V}; μ_ast::Vector = μ_ast343_DE430[1:end], - order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number, V <: Number} + propagate_params(jd0::U, tspan::T, q0::Vector{V}, + params::NEOParameters{T}) where {T <: Real, U <: Number, V <: Number} Return the parameters needed for `propagate`, `propagate_root` and `propagate_lyap`. @@ -76,12 +76,10 @@ Return the parameters needed for `propagate`, `propagate_root` and `propagate_ly - `jd0::U`: initial Julian date. - `tspan::T`: time span of the integration [in years]. - `q0::Vector{V}`: vector of initial conditions. -- `μ_ast::Vector`: vector of gravitational parameters. -- `order::Int`: order of the Taylor expansions to be used in the integration. -- `abstol::T`: absolute tolerance. +- `params::NEOParameters{T}`: see `Propagation Parameters` of [`NEOParameters`](@ref). """ -function propagate_params(jd0::U, tspan::T, q0::Vector{V}; μ_ast::Vector = μ_ast343_DE430[1:end], - order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number, V <: Number} +function propagate_params(jd0::U, tspan::T, q0::Vector{V}, + params::NEOParameters{T}) where {T <: Real, U <: Number, V <: Number} # Epoch (plain) _jd0_ = cte(cte(jd0)) # Time limits [days since J2000] @@ -103,7 +101,7 @@ function propagate_params(jd0::U, tspan::T, q0::Vector{V}; μ_ast::Vector = μ_a N = Nm1 + 1 # Vector of G*m values - μ = convert(Vector{T}, vcat( μ_DE430[1:11], μ_ast[1:Nm1-11], zero(T) ) ) + μ = convert(Vector{T}, vcat( μ_DE430[1:11], params.μ_ast[1:Nm1-11], zero(T) ) ) # Check: number of SS bodies (N) in ephemeris must be equal to length of GM vector (μ) @assert N == length(μ) "Total number of bodies in ephemeris must be equal to length of GM vector μ" @@ -148,14 +146,13 @@ function propagate(dynamics::D, jd0::U, tspan::T, q0::Vector{V}, params::NEOParameters{T}) where {T <: Real, U <: Number, V <: Number, D} # Unfold - maxsteps, μ_ast, order, abstol, parse_eqs = params.maxsteps, params.μ_ast, params.order, - params.abstol, params.parse_eqs + maxsteps, order, abstol, parse_eqs = params.maxsteps, params.order, params.abstol, params.parse_eqs # Check order - @assert order <= get_order(sseph.x[1]) "order ($(order)) must be less or equal than SS ephemeris order ($(get_order(sseph.x[1])))" + @assert order <= SSEPHORDER "order ($order) must be less or equal than SS ephemeris order ($SSEPHORDER)" # Parameters for taylorinteg - _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast = μ_ast, order = order, abstol = abstol) + _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0, params) # Propagate orbit @@ -198,14 +195,13 @@ function propagate_root(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, nrabstol::T = eps(T)) where {T <: Real, U <: Number, D} # Unfold - maxsteps, μ_ast, order, abstol, parse_eqs = params.maxsteps, params.μ_ast, params.order, - params.abstol, params.parse_eqs + maxsteps, order, abstol, parse_eqs = params.maxsteps, params.order, params.abstol, params.parse_eqs # Check order - @assert order <= get_order(sseph.x[1]) "order ($(order)) must be less or equal than SS ephemeris order ($(get_order(sseph.x[1])))" + @assert order <= SSEPHORDER "order ($order) must be less or equal than SS ephemeris order ($SSEPHORDER)" # Parameters for neosinteg - _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast = μ_ast, order = order, abstol = abstol) + _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0, params) # Propagate orbit @time tv, xv, psol, tvS, xvS, gvS = taylorinteg(dynamics, rvelea, _q0, _t0, _tmax, order, abstol, Val(true), _params; @@ -233,14 +229,13 @@ function propagate_lyap(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, params::NEOParameters{T}) where {T <: Real, U <: Number, D} # Unfold - maxsteps, μ_ast, order, abstol, parse_eqs = params.maxsteps, params.μ_ast, params.order, - params.abstol, params.parse_eqs + maxsteps, order, abstol, parse_eqs = params.maxsteps, params.order, params.abstol, params.parse_eqs # Check order - @assert order <= get_order(sseph.x[1]) "order ($(order)) must be less or equal than SS ephemeris order ($(get_order(sseph.x[1])))" + @assert order <= SSEPHORDER "order ($order) must be less or equal than SS ephemeris order ($SSEPHORDER)" # Parameters for taylorinteg - _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast = μ_ast, order = order, abstol = abstol) + _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0, params) # Propagate orbit @time sol = lyap_taylorinteg(dynamics, _q0, _t0, _tmax, order, abstol, _params; From b67b85ec7f3e4b5d0bf443cce1388194d6fbf464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20P=C3=A9rez-Hern=C3=A1ndez?= Date: Fri, 22 Mar 2024 23:00:01 +0100 Subject: [PATCH 162/173] Add some internal variables as kwargs in methods --- src/orbit_determination/gauss_method.jl | 9 ++++----- src/orbit_determination/tooshortarc.jl | 9 +++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index 6fce2045..3cd1d1f0 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -149,8 +149,8 @@ Solve Lagrange polynomial. See also [`lagrange`](@ref). """ -function solve_lagrange(a::T, b::T, c::T; niter::Int = 5) where {T <: Real} - return find_zeros(x -> lagrange(x, a, b, c), 0.00465047, 40.0) +function solve_lagrange(a::T, b::T, c::T; niter::Int = 5, rmin = 0.00465047, rmax = 40.0) where {T <: Real} + return find_zeros(x -> lagrange(x, a, b, c), rmin, rmax) end function solve_lagrange(a::TaylorN{T}, b::TaylorN{T}, c::TaylorN{T}; niter::Int = 5) where {T <: Real} @@ -393,9 +393,8 @@ function gauss_triplets(dates::Vector{DateTime}, Δ_min::Period, Δ_max::Period, return triplets[1:n] end -function gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_iter::Int = 100) - Δ_min = Hour(20) - Δ_max = Day(7) +function gauss_triplets(dates::Vector{DateTime}, max_triplets::Int = 10, max_iter::Int = 100; + Δ_min = Hour(20), Δ_max = Day(7)) triplets = Vector{Vector{Int}}(undef, 0) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 19615075..0602de2f 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -411,7 +411,7 @@ residual over and admissible region `A`. """ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, params::NEOParameters{T}; scale::Symbol = :linear, η::T = 25.0, - μ::T = 0.75, ν::T = 0.9, ϵ::T = 1e-8, Qtol::T = 0.001, + μ::T = 0.75, ν::T = 0.9, ϵ::T = 1e-8, Qtol::T = 0.001, order::Int = 2, dynamics::D = newtonian!) where {T <: AbstractFloat, D} # Initial time of integration [julian days] jd0 = datetime2julian(A.date) @@ -428,7 +428,7 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T end scalings[6] = (A.v_ρ_domain[2] - A.v_ρ_domain[1]) / 1_000 # Jet transport variables - dq = scaled_variables("dx", scalings, order = 2) + dq = scaled_variables("dx", scalings; order) # Maximum number of iterations maxiter = params.maxiter # Allocate memory @@ -543,7 +543,8 @@ admissible region via least squares. This function will set the (global) `TaylorSeries` variables to `dx₁ dx₂ dx₃ dx₄ dx₅ dx₆`. """ function tsals(A::AdmissibleRegion{T}, radec::Vector{RadecMPC{T}}, tracklets::Vector{Tracklet{T}}, - i::Int, ρ::T, v_ρ::T, params::NEOParameters{T}; maxiter::Int = 5, dynamics::D=newtonian!) where {T <: AbstractFloat, D} + i::Int, ρ::T, v_ρ::T, params::NEOParameters{T}; maxiter::Int = 5, dynamics::D = newtonian!, + order = 6) where {T <: AbstractFloat, D} # Initial time of integration [julian days] # (corrected for light-time) jd0 = datetime2julian(A.date) - ρ / c_au_per_day @@ -552,7 +553,7 @@ function tsals(A::AdmissibleRegion{T}, radec::Vector{RadecMPC{T}}, tracklets::Ve # Scaling factors scalings = abs.(q0) ./ 10^5 # Jet transport variables - dq = scaled_variables("dx", scalings, order = 6) + dq = scaled_variables("dx", scalings; order) # Origin x0 = zeros(T, 6) # Subset of radec for orbit fit From f623d9259499ad3efc1b6cd0d6dcba091c8f18f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 23 Mar 2024 07:11:50 -0600 Subject: [PATCH 163/173] Adapt diffcorr for idxs --- src/orbit_determination/least_squares.jl | 29 ++++++++++++------------ 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/orbit_determination/least_squares.jl b/src/orbit_determination/least_squares.jl index 8ca8b604..3e4067c7 100644 --- a/src/orbit_determination/least_squares.jl +++ b/src/orbit_determination/least_squares.jl @@ -357,8 +357,7 @@ See also [`BHC`](@ref). See sections 5.2 and 5.3 of https://doi.org/10.1017/CBO9781139175371. """ function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, - niters::Int = 5) where {T <: Real} - # TO DO: Adapt diffcorr for idxs + niters::Int = 5, idxs::AbstractVector{Int} = eachindex(x0)) where {T <: Real} # Degrees of freedom npar = length(x0) # Design matrix B, H array and normal matrix C @@ -369,7 +368,9 @@ function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, # Vector of x x = Matrix{T}(undef, npar, niters + 1) # First guess - x[:, 1] = x0 + for i in axes(x, 2) + x[:, i] .= x0 + end # Vector of errors error = Vector{T}(undef, niters + 1) # Error of first guess @@ -379,13 +380,13 @@ function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, # Current x xi = x[:, i] # D matrix evaluated in xi - D = D_mat(xi) + D = D_mat(xi)[idxs] # C matrix evaluated in xi - C = C_mat(xi) #.+ ξTH_mat(xi) + C = C_mat(xi)[idxs, idxs] #.+ ξTH_mat(xi) # Update rule Δx = - inv(C)*D # New x - x[:, i+1] = xi + Δx + x[idxs, i+1] = xi[idxs] + Δx # Error error2 = ( (Δx') * (C*Δx) ) / npar if error2 ≥ 0 @@ -402,7 +403,7 @@ function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, # Normal C matrix evaluated in x_new C = C_mat(x_new) # Covariance matrix - Γ = inv(C) + Γ = inv(C[idxs, idxs]) if any(diag(Γ) .< 0) return LeastSquaresFit(false, x_new, Γ, :diffcorr) @@ -412,11 +413,11 @@ function diffcorr(res::Vector{TaylorN{T}}, w::Vector{T}, x0::Vector{T}, end function diffcorr(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, - niters::Int = 5) where {T <: Real} + niters::Int = 5, idxs::AbstractVector{Int} = eachindex(x0)) where {T <: Real} # Unfold residuals and weights _res_, _w_ = unfold(res) - return diffcorr(_res_, _w_, x0, niters) + return diffcorr(_res_, _w_, x0, niters, idxs) end @doc raw""" @@ -644,8 +645,8 @@ end tryls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, niters::Int = 5) where {T <: Real} -Return the best least squares fit between two routines: [`newtonls`](@ref) and -[`diffcorr`](@ref). +Return the best least squares fit between three routines: [`newtonls`](@ref), +[`diffcorr`](@ref) and [`levenbergmarquardt`](@ref). # Arguments @@ -655,17 +656,17 @@ Return the best least squares fit between two routines: [`newtonls`](@ref) and """ function tryls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, niters::Int = 5, idxs::AbstractVector{Int} = eachindex(x0), - order::Vector{Symbol} = [:newton, :lm]) where {T <: Real} + order::Vector{Symbol} = [:newton, :diffcorr, :lm]) where {T <: Real} # Allocate memory fit = zero(LeastSquaresFit{T}) # Least squares methods in order for i in eachindex(order) if order[i] == :newton fit = newtonls(res, x0, niters, idxs) - elseif order[i] == :lm - fit = levenbergmarquardt(res, x0, niters, idxs) elseif order[i] == :diffcorr fit = diffcorr(res, x0, niters, idxs) + elseif order[i] == :lm + fit = levenbergmarquardt(res, x0, niters, idxs) end fit.success && break end From 3389d3779ad955e89820e1fb501d048e1024f07f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 23 Mar 2024 10:58:17 -0600 Subject: [PATCH 164/173] Reduce integrations in adam --- src/orbit_determination/least_squares.jl | 2 +- src/orbit_determination/tooshortarc.jl | 51 ++++++++++++------------ 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/orbit_determination/least_squares.jl b/src/orbit_determination/least_squares.jl index 3e4067c7..c2ac8eb1 100644 --- a/src/orbit_determination/least_squares.jl +++ b/src/orbit_determination/least_squares.jl @@ -656,7 +656,7 @@ Return the best least squares fit between three routines: [`newtonls`](@ref), """ function tryls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, niters::Int = 5, idxs::AbstractVector{Int} = eachindex(x0), - order::Vector{Symbol} = [:newton, :diffcorr, :lm]) where {T <: Real} + order::Vector{Symbol} = [:newton, :diffcorr]) where {T <: Real} # Allocate memory fit = zero(LeastSquaresFit{T}) # Least squares methods in order diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl index 0602de2f..9805bc40 100644 --- a/src/orbit_determination/tooshortarc.jl +++ b/src/orbit_determination/tooshortarc.jl @@ -354,7 +354,9 @@ function attr2bary(A::AdmissibleRegion{T}, a::Vector{U}, α, δ, v_α, v_δ, ρ, v_ρ = a # Light-time correction to epoch t = datetime2days(A.date) - ρ/c_au_per_day - et = julian2etsecs(datetime2julian(A.date) - cte(cte(ρ))/c_au_per_day) + # TO DO: `et::TaylorN` is too slow for `adam` due to + # SatelliteToolboxTransformations overloads in src/observations/topocentric.jl + et = datetime2et(A.date) - cte(cte(ρ))/c_au_per_sec # Line of sight vectors ρ_unit, ρ_α, ρ_δ = topounitpdv(α, δ) # Heliocentric position of the observer @@ -397,14 +399,14 @@ end @doc raw""" adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T, params::NEOParameters{T}; scale::Symbol = :linear, η::T = 25.0, - μ::T = 0.75, ν::T = 0.9, ϵ::T = 1e-8, Qtol::T = 0.001, + μ::T = 0.75, ν::T = 0.9, ϵ::T = 1e-8, Qtol::T = 0.001, order::Int = 2, dynamics::D = newtonian!) where {T <: AbstractFloat, D} Adaptative moment estimation (ADAM) minimizer of normalized mean square residual over and admissible region `A`. !!! warning - This function will set the (global) `TaylorSeries` variables to `dx dy`. + This function will set the (global) `TaylorSeries` variables to `dx₁ dx₂ dx₃ dx₄ dx₅ dx₆`. !!! reference See Algorithm 1 of https://doi.org/10.48550/arXiv.1412.6980. @@ -415,11 +417,11 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T dynamics::D = newtonian!) where {T <: AbstractFloat, D} # Initial time of integration [julian days] jd0 = datetime2julian(A.date) - # Nominal Line-Of-Sight - LOS = [A.α, A.δ, A.v_α, A.v_δ] + # Attributable elements + ae = [A.α, A.δ, A.v_α, A.v_δ, zero(T), zero(T)] # Scaling factors scalings = Vector{T}(undef, 6) - scalings[1:4] .= LOS ./ 1e6 + scalings[1:4] .= abs.(ae[1:4]) ./ 1e6 if scale == :linear scalings[5] = (A.ρ_domain[2] - A.ρ_domain[1]) / 1_000 elseif scale == :log @@ -428,7 +430,7 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T end scalings[6] = (A.v_ρ_domain[2] - A.v_ρ_domain[1]) / 1_000 # Jet transport variables - dq = scaled_variables("dx", scalings; order) + dae = scaled_variables("dx", scalings; order) # Maximum number of iterations maxiter = params.maxiter # Allocate memory @@ -450,34 +452,31 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T ρs[t] = ρ v_ρs[t] = v_ρ # Attributable elements - a = vcat(LOS + dq[1:4], ρ, v_ρ) - # Barycentric state vector - q = attr2bary(A, a, params) - # Propagation and residuals - _, _, res = propres(radec, jd0 - ρ/c_au_per_day, q, params; dynamics) - iszero(length(res)) && break - # Least squares fit - fit = tryls(res, x0, 5, 1:4) - # Minimized attributable elements - a0 = a(fit.x) - # Attributable elements if scale == :linear - a = vcat(a0[1:4], ρ + dq[5], v_ρ + dq[6]) + ae[5], ae[6] = ρ, v_ρ + AE = ae + dae elseif scale == :log - a = vcat(a0[1:4], 10^(x + dq[5]), v_ρ + dq[6]) + ae[5], ae[6] = x, v_ρ + AE = [ae[1] + dae[1], ae[2] + dae[2], ae[3] + dae[3], + ae[4] + dae[4], 10^(ae[5] + dae[5]), ae[6] + dae[6]] end # Barycentric state vector - q = attr2bary(A, a, params) + q = attr2bary(A, AE, params) # Propagation and residuals + # TO DO: `ρ::TaylorN` is too slow for `adam` due to evaluations + # within the dynamical model _, _, res = propres(radec, jd0 - ρ/c_au_per_day, q, params; dynamics) iszero(length(res)) && break + # Least squares fit + fit = tryls(res, x0, 5, 1:4) + x1 .= fit.x # Current Q Q = nms(res) - Qs[t] = Q(x0) + Qs[t] = Q(x1) # Convergence condition t > 1 && abs(Qs[t] - Qs[t-1]) / Qs[t] < Qtol && break # Gradient of objective function - g_t = TaylorSeries.gradient(Q)(x0)[5:6] + g_t = TaylorSeries.gradient(Q)(x1)[5:6] # First momentum m .= μ * m + (1 - μ) * g_t _m_ .= m / (1 - μ^t) @@ -485,11 +484,11 @@ function adam(radec::Vector{RadecMPC{T}}, A::AdmissibleRegion{T}, ρ::T, v_ρ::T n .= ν * n + (1 - ν) * g_t .^ 2 _n_ .= n / (1 - ν^t) # Step - x1[5:6] = x0[5:6] - η * _m_ ./ (sqrt.(_n_) .+ ϵ) + x1[5:6] = x1[5:6] - η * _m_ ./ (sqrt.(_n_) .+ ϵ) # Update values - ρ, v_ρ = bary2topo(A, q(x1)) + ae .= AE(x1) # Projection - ρ, v_ρ = boundary_projection(A, ρ, v_ρ) + ρ, v_ρ = boundary_projection(A, ae[5], ae[6]) if scale == :log x = log10(ρ) end From 640a0650dd617aa80ff0b5527865f34d271e3fa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 23 Mar 2024 11:49:22 -0600 Subject: [PATCH 165/173] Minor fix --- src/orbit_determination/least_squares.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/orbit_determination/least_squares.jl b/src/orbit_determination/least_squares.jl index c2ac8eb1..3e4067c7 100644 --- a/src/orbit_determination/least_squares.jl +++ b/src/orbit_determination/least_squares.jl @@ -656,7 +656,7 @@ Return the best least squares fit between three routines: [`newtonls`](@ref), """ function tryls(res::Vector{OpticalResidual{T, TaylorN{T}}}, x0::Vector{T}, niters::Int = 5, idxs::AbstractVector{Int} = eachindex(x0), - order::Vector{Symbol} = [:newton, :diffcorr]) where {T <: Real} + order::Vector{Symbol} = [:newton, :diffcorr, :lm]) where {T <: Real} # Allocate memory fit = zero(LeastSquaresFit{T}) # Least squares methods in order From d80b2986fc02b4f3c3318e22e2c6b639c6f1836d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 23 Mar 2024 12:33:50 -0600 Subject: [PATCH 166/173] orbitdetermination(::Vector{RadecMPC}, ::NEOSolution,...) --- .../orbit_determination.jl | 62 +++++++++++++++++++ test/orbit_determination.jl | 61 +++++++++++++++++- 2 files changed, 121 insertions(+), 2 deletions(-) diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl index 8bd2f012..cc09d816 100644 --- a/src/orbit_determination/orbit_determination.jl +++ b/src/orbit_determination/orbit_determination.jl @@ -99,3 +99,65 @@ function orbitdetermination(radec::Vector{RadecMPC{T}}, params::NEOParameters{T} return sol::NEOSolution{T, T} end + +@doc raw""" + orbitdetermination(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, params::NEOParameters{T}; + dynamics::D = newtonian!, maxiter::Int = 5) where {T <: AbstractFloat, D} + +Fit an orbit to `radec` using `sol` as initial condition. + +# Arguments + +- `radec::Vector{RadecMPC{T}}`: vector of observations. +- `sol::NEOSolution{T, T}:` least squares orbit. +- `params::NEOParameters{T}`: see [`NEOParameters`](@ref). +- `dynamics::D`: dynamical model. +- `maxiter::Int`: maximum number of iterations. +""" +function orbitdetermination(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, params::NEOParameters{T}; + dynamics::D = newtonian!, maxiter::Int = 5) where {T <: AbstractFloat, D} + # Reduce tracklets by polynomial regression + tracklets = reduce_tracklets(radec) + # Epoch [julian days] + jd0 = sol.bwd.t0 + PE.J2000 + # Barycentric initial conditions + q0 = sol(sol.bwd.t0) + # Scaling factors + scalings = abs.(q0) ./ 10^6 + # Jet transport variables + dq = scaled_variables("δx", scalings; order = params.varorder) + # Origin + x0 = zeros(T, 6) + # Allocate memory + best_Q = nrms(sol) + # Least squares + for _ in 1:maxiter + # Initial conditions + q = q0 + dq + # Propagation and residuals + bwd, fwd, res = propres(radec, jd0, q, params; dynamics) + iszero(length(res)) && break + # Orbit fit + fit = tryls(res, x0, params.niter) + !fit.success && break + # Update solution + sol = evalfit(NEOSolution(tracklets, bwd, fwd, res, fit, scalings)) + # NRMS + Q = nrms(res, fit) + # Convergence condition + if abs(best_Q - Q) < 0.1 + break + else + best_Q = Q + end + # Update initial conditions + q0 = q(fit.x) + end + # Case: all solutions were unsuccesful + if isinf(best_Q) + return zero(NEOSolution{T, T}) + # Case: at least one solution was succesful + else + return sol + end +end \ No newline at end of file diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index c801e2ef..e9e365ba 100644 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -44,14 +44,41 @@ using NEOs: NEOSolution, numberofdays @test iszero(count(outlier.(sol.res))) # Least squares fit @test sol.fit.success - @test all( sigmas(sol) .< 1e-4 ) - @test nrms(sol) < 0.38 + @test all( sigmas(sol) .< 4e-7 ) + @test nrms(sol) < 0.36 # Scalig factors @test all(sol.scalings .== 1e-6) # Compatibility with JPL JPL = [-1.1003339484439327, 0.20772201506095814, 0.04202338912370205, -0.004735538686138557, -0.010626685053348663, -0.006016258344003866] @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 6) + + # Refine orbit + sol1 = orbitdetermination(radec, sol, params) + + # Orbit solution + @test isa(sol1, NEOSolution{Float64, Float64}) + # Tracklets + @test sol1.tracklets == sol.tracklets + # Backward integration + @test datetime2days(date(radec[1])) > sol1.bwd.t0 + sol1.bwd.t[end] + @test all( norm.(sol1.bwd.x, Inf) .< 1.2 ) + @test isempty(sol1.t_bwd) && isempty(sol1.x_bwd) && isempty(sol1.g_bwd) + # Forward integration + @test datetime2days(date(radec[end])) < sol1.fwd.t0 + sol1.fwd.t[end] + @test all( norm.(sol1.fwd.x, Inf) .< 1.2 ) + @test isempty(sol1.t_fwd) && isempty(sol1.x_fwd) && isempty(sol1.g_fwd) + # Vector of residuals + @test length(sol1.res) == 123 + @test iszero(count(outlier.(sol1.res))) + # Least squares fit + @test sol1.fit.success + @test all( sigmas(sol1) .< 5e-5 ) + @test nrms(sol1) < 0.36 + # Scalig factors + @test all(sol1.scalings .< 2e-6) + # Compatibility with JPL + @test all(abs.(sol1() - JPL) ./ sigmas(sol1) .< 0.3) end @testset "Too Short Arc" begin @@ -239,6 +266,36 @@ using NEOs: NEOSolution, numberofdays JPL = [0.9741070119227359, 0.21515061351517384, 0.09390897837680391, -0.007890445009307178, 0.016062726197198392, 0.006136042043681892] @test all(abs.(sol() - JPL) ./ sigmas(sol) .< 0.3) + + # Update orbit with more observations + sol1 = orbitdetermination(radec[1:30], sol, params) + + # Orbit solution + @test isa(sol1, NEOSolution{Float64, Float64}) + # Tracklets + @test length(sol1.tracklets) == 5 + @test sol1.tracklets[1].radec[1] == radec[idxs[1]] + @test sol1.tracklets[end].radec[end] == radec[30] + @test issorted(sol1.tracklets) + # Backward integration + @test datetime2days(date(radec[idxs[1]])) > sol1.bwd.t0 + sol1.bwd.t[end] + @test all( norm.(sol1.bwd.x, Inf) .< 1 ) + @test isempty(sol1.t_bwd) && isempty(sol1.x_bwd) && isempty(sol1.g_bwd) + # Forward integration + @test datetime2days(date(radec[idxs[end]])) < sol1.fwd.t0 + sol1.fwd.t[end] + @test all( norm.(sol1.fwd.x, Inf) .< 1e4 ) + @test isempty(sol1.t_fwd) && isempty(sol1.x_fwd) && isempty(sol1.g_fwd) + # Vector of residuals + @test length(sol1.res) == 30 + @test iszero(count(outlier.(sol1.res))) + # Least squares fit + @test sol1.fit.success + @test all( sigmas(sol1) .< 2e-6 ) + @test nrms(sol1) < 0.37 + # Scalig factors + @test all(sol1.scalings .< 1e-6) + # Compatibility with JPL + @test all(abs.(sol1() - JPL) ./ sigmas(sol1) .< 1.6) end end \ No newline at end of file From 74156be408202b220ac951cbf657cc3cb97b6159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Sat, 23 Mar 2024 12:34:34 -0600 Subject: [PATCH 167/173] Minor fix --- test/orbit_determination.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index e9e365ba..54d10168 100644 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -274,7 +274,7 @@ using NEOs: NEOSolution, numberofdays @test isa(sol1, NEOSolution{Float64, Float64}) # Tracklets @test length(sol1.tracklets) == 5 - @test sol1.tracklets[1].radec[1] == radec[idxs[1]] + @test sol1.tracklets[1].radec[1] == radec[1] @test sol1.tracklets[end].radec[end] == radec[30] @test issorted(sol1.tracklets) # Backward integration From 5c206df749902ecf8867c08848f5a564611947c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Mon, 25 Mar 2024 14:22:28 -0600 Subject: [PATCH 168/173] Test 2008 TC3 sigmas(sol1) --- test/orbit_determination.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index 54d10168..6488a149 100644 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -296,6 +296,8 @@ using NEOs: NEOSolution, numberofdays @test all(sol1.scalings .< 1e-6) # Compatibility with JPL @test all(abs.(sol1() - JPL) ./ sigmas(sol1) .< 1.6) + # Parameters uncertainty + @test all(sigmas(sol1) .< sigmas(sol)) end end \ No newline at end of file From 30762da66a954258cd24e2245806688fdce49104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Mon, 25 Mar 2024 14:58:06 -0600 Subject: [PATCH 169/173] Spelling corrections in test/orbit_determination.jl --- test/orbit_determination.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index 6488a149..5bdade34 100644 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -46,7 +46,7 @@ using NEOs: NEOSolution, numberofdays @test sol.fit.success @test all( sigmas(sol) .< 4e-7 ) @test nrms(sol) < 0.36 - # Scalig factors + # Scaling factors @test all(sol.scalings .== 1e-6) # Compatibility with JPL JPL = [-1.1003339484439327, 0.20772201506095814, 0.04202338912370205, @@ -75,7 +75,7 @@ using NEOs: NEOSolution, numberofdays @test sol1.fit.success @test all( sigmas(sol1) .< 5e-5 ) @test nrms(sol1) < 0.36 - # Scalig factors + # Scaling factors @test all(sol1.scalings .< 2e-6) # Compatibility with JPL @test all(abs.(sol1() - JPL) ./ sigmas(sol1) .< 0.3) @@ -118,7 +118,7 @@ using NEOs: NEOSolution, numberofdays @test sol.fit.success @test all( sigmas(sol) .< 6e-3 ) @test nrms(sol) < 0.85 - # Scalig factors + # Scaling factors @test all(sol.scalings .< 1e-5) # Compatibility with JPL JPL = [-0.9698333701500199, 0.24036461256880043, 0.10288887522619743, @@ -165,7 +165,7 @@ using NEOs: NEOSolution, numberofdays @test sol.fit.success @test all( sigmas(sol) .< 5e-4 ) @test nrms(sol) < 0.25 - # Scalig factors + # Scaling factors @test all(sol.scalings .< 8e-7) # Compatibility with JPL JPL = [0.7673358221902306, 0.6484904294813807, 0.2932331617634889, @@ -213,7 +213,7 @@ using NEOs: NEOSolution, numberofdays @test sol.fit.success @test all( sigmas(sol) .< 1e-3 ) @test nrms(sol) < 0.13 - # Scalig factors + # Scaling factors @test all(sol.scalings .< 1e-5) # Compatibility with JPL JPL = [-0.17932853771087842, 0.8874166708545763, 0.38414497114153867, @@ -229,7 +229,7 @@ using NEOs: NEOSolution, numberofdays params = NEOParameters(coeffstol = Inf, bwdoffset = 0.007, fwdoffset = 0.007) # Observations with <1" weight - idxs = findall(x -> x < 1, w8sveres17.(radec)) + idxs = findall(x -> w8sveres17(x) < 1, radec) # Restricted Orbit Determination sol = orbitdetermination(radec[idxs], params) @@ -260,7 +260,7 @@ using NEOs: NEOSolution, numberofdays @test sol.fit.success @test all( sigmas(sol) .< 2e-5 ) @test nrms(sol) < 0.30 - # Scalig factors + # Scaling factors @test all(sol.scalings .< 1e-5) # Compatibility with JPL JPL = [0.9741070119227359, 0.21515061351517384, 0.09390897837680391, @@ -292,7 +292,7 @@ using NEOs: NEOSolution, numberofdays @test sol1.fit.success @test all( sigmas(sol1) .< 2e-6 ) @test nrms(sol1) < 0.37 - # Scalig factors + # Scaling factors @test all(sol1.scalings .< 1e-6) # Compatibility with JPL @test all(abs.(sol1() - JPL) ./ sigmas(sol1) .< 1.6) From d7972f1b0cc24785086cdee80da4ad0da569b7df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Ram=C3=ADrez=20Montoya?= Date: Mon, 25 Mar 2024 16:06:01 -0600 Subject: [PATCH 170/173] test/extensions.jl -> test/dataframe.jl --- test/{extensions.jl => dataframe.jl} | 4 ++-- test/runtests.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename test/{extensions.jl => dataframe.jl} (96%) diff --git a/test/extensions.jl b/test/dataframe.jl similarity index 96% rename from test/extensions.jl rename to test/dataframe.jl index c0512ff4..ef108526 100644 --- a/test/extensions.jl +++ b/test/dataframe.jl @@ -1,5 +1,5 @@ using NEOs -using Dates +using Dates using Tables using DataFrames using Query @@ -7,7 +7,7 @@ using Test using NEOs: read_radec_mpc, RadecMPC, read_radar_jpl, RadarJPL -@testset "DataFramesExt" begin +@testset "DataFrame(::AbstractAstrometry)" begin # RadecMPC radec_2023DW = read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) diff --git a/test/runtests.jl b/test/runtests.jl index d1a830a8..edb2c07e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -5,7 +5,7 @@ testfiles = ( "observations.jl", "propagation.jl", "orbit_determination.jl", - "extensions.jl" + "dataframe.jl" ) for file in testfiles From 7902080bb718f01a30ee49017d9bfcfd63a8b715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20P=C3=A9rez-Hern=C3=A1ndez?= Date: Tue, 26 Mar 2024 16:25:06 +0100 Subject: [PATCH 171/173] Rename test/dataframe.jl -> test/dataframes.jl --- test/{dataframe.jl => dataframes.jl} | 0 test/runtests.jl | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename test/{dataframe.jl => dataframes.jl} (100%) diff --git a/test/dataframe.jl b/test/dataframes.jl similarity index 100% rename from test/dataframe.jl rename to test/dataframes.jl diff --git a/test/runtests.jl b/test/runtests.jl index edb2c07e..1eebed02 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -5,7 +5,7 @@ testfiles = ( "observations.jl", "propagation.jl", "orbit_determination.jl", - "dataframe.jl" + "dataframes.jl" ) for file in testfiles From 8886cc45a56e57100c33b0df9cfe0c843e18308f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20P=C3=A9rez-Hern=C3=A1ndez?= Date: Tue, 26 Mar 2024 16:44:26 +0100 Subject: [PATCH 172/173] Add commented test and TODO --- test/orbit_determination.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/orbit_determination.jl b/test/orbit_determination.jl index 5bdade34..baa5578f 100644 --- a/test/orbit_determination.jl +++ b/test/orbit_determination.jl @@ -298,6 +298,8 @@ using NEOs: NEOSolution, numberofdays @test all(abs.(sol1() - JPL) ./ sigmas(sol1) .< 1.6) # Parameters uncertainty @test all(sigmas(sol1) .< sigmas(sol)) + # TODO: understand better differences wrt JPL solutions + # @test nrms(sol1) < nrms(sol) end end \ No newline at end of file From a0408eba4b6abdab40519570e443ffbab60ffeaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20P=C3=A9rez-Hern=C3=A1ndez?= Date: Tue, 26 Mar 2024 18:08:16 +0100 Subject: [PATCH 173/173] Remove dep (Tables) in tests environment --- test/Project.toml | 1 - test/dataframes.jl | 1 - test/runtests.jl | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/test/Project.toml b/test/Project.toml index 11d054fc..a20a2e7c 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -11,6 +11,5 @@ PlanetaryEphemeris = "d83715d0-7e5f-11e9-1a59-4137b20d8363" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Query = "1a8c2f83-1ff3-5112-b086-8aa67b057ba1" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" -Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" TaylorIntegration = "92b13dbe-c966-51a2-8445-caca9f8a7d42" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/dataframes.jl b/test/dataframes.jl index ef108526..60a78681 100644 --- a/test/dataframes.jl +++ b/test/dataframes.jl @@ -1,6 +1,5 @@ using NEOs using Dates -using Tables using DataFrames using Query using Test diff --git a/test/runtests.jl b/test/runtests.jl index 1eebed02..ad9cd3f3 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -5,7 +5,7 @@ testfiles = ( "observations.jl", "propagation.jl", "orbit_determination.jl", - "dataframes.jl" + "dataframes.jl", ) for file in testfiles