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/.gitignore b/.gitignore index df74e796..b72ace97 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ jldeph/ notebooks/figs EOP_IAU*.TXT Manifest.toml +*.DS_Store +.vscode \ No newline at end of file diff --git a/Project.toml b/Project.toml index f8e4c235..fdb418a7 100644 --- a/Project.toml +++ b/Project.toml @@ -1,11 +1,13 @@ 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" 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" Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" @@ -14,55 +16,44 @@ HORIZONS = "5a3ac768-beb4-554a-9c98-3342fe3377f5" HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" Healpix = "9f4e344d-96bc-545a-84a3-ae6b9e1b672b" InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" -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" +LsqFit = "2fda8390-95c7-5789-9bda-21331edee243" PlanetaryEphemeris = "d83715d0-7e5f-11e9-1a59-4137b20d8363" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Quadmath = "be4d8f0f-7fa4-5f49-b795-2f01399ab2dd" -Requires = "ae029012-a4dd-5104-9daa-d747884805df" +Roots = "f2b01f46-fcfa-551c-844a-d8ac1e96c665" 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] Artifacts = "1" AutoHashEquals = "0.2" +Clustering = "0.15" DataFrames = "1.5" DelimitedFiles = "1" Downloads = "1" -HORIZONS = "0.3" +HORIZONS = "0.4" HTTP = "1.9.5" Healpix = "4" -IntervalArithmetic = "0.20, 0.22" -IntervalRootFinding = "0.5.11" JLD2 = "0.4" +JSON = "0.21" LazyArtifacts = "1" -PlanetaryEphemeris = "0.7" +PlanetaryEphemeris = "0.8" Quadmath = "0.5" -Requires = "0.5.2, 1" SPICE = "0.2" SatelliteToolboxTransformations = "0.1" Scratch = "1.2" StatsBase = "0.33, 0.34" Tables = "1.10" -TaylorIntegration = "0.14" -TaylorSeries = "0.16" -julia = "1.6" - -[extras] -DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" -Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" +TaylorIntegration = "0.15" +TaylorSeries = "0.17" +julia = "1.9" diff --git a/ext/DataFramesExt.jl b/ext/DataFramesExt.jl deleted file mode 100644 index 2e98d1e9..00000000 --- a/ext/DataFramesExt.jl +++ /dev/null @@ -1,33 +0,0 @@ -module DataFramesExt - -import Base: convert -import NEOs: AbstractAstrometry - -if isdefined(Base, :get_extension) - using DataFrames: DataFrame, nrow, eachcol, eachrow - import Tables: istable, rowaccess, rows, schema, Schema -else - using ..DataFrames: DataFrame, nrow, eachcol, eachrow - 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) - -end # module \ No newline at end of file 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 964cd558..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,21 +143,18 @@ 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]) - # 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 @@ -177,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" @@ -233,9 +230,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) @@ -248,19 +245,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 @@ -316,3 +313,36 @@ function main() 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 index bf969524..6f7044a9 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -2,74 +2,83 @@ module NEOs # __precompile__(false) -if !isdefined(Base, :get_extension) - using Requires -end - -import Base: hash, ==, show, isless, isnan, convert -import PlanetaryEphemeris as PE +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 -using Distributed, JLD2, TaylorIntegration, Printf, DelimitedFiles, Test, LinearAlgebra, - Dates, SPICE, Quadmath, LazyArtifacts, TaylorSeries, - 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 -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 AutoHashEquals, Dates, Printf, JSON, SatelliteToolboxTransformations, TaylorSeries, + TaylorIntegration, SPICE, JLD2, LazyArtifacts, LinearAlgebra, LinearAlgebra, + DelimitedFiles, Scratch, Quadmath, Test, InteractiveUtils, Distributed using HTTP: get -using IntervalRootFinding: roots, interval, Interval, mid +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 +using HORIZONS: smb_spk # 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, 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, +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 +export ra, dec, date, observatory, read_radec_mpc, write_radec_mpc, get_radec_mpc, + fetch_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 +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 -# Osculating -export pv2kep, yarkp2adot # Topocentric -export obs_pos_ECEF, obsposvelECI +export obsposECEF, obsposvelECI # Process radec -export compute_radec, debiasing, w8sveres17, radec_astrometry, residuals +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 # 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 propagate, propagate_lyap, propagate_root - -export valsecchi_circle, nrms, chi2, newtonls, newtonls_6v, diffcorr, newtonls_Q, bopik +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 jplcompare, issinglearc, isgauss, 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("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 index 3fe519ba..b0d97c25 100644 --- a/src/constants.jl +++ b/src/constants.jl @@ -5,12 +5,139 @@ 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]) +const SSEPHORDER::Int = get_order(sseph.x[1]) + +# 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 mpc_catalogues_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 mpc_observatories_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=" # MPC observations url @@ -69,4 +196,11 @@ 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 +# 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 index 737ef32f..a35af112 100644 --- a/src/init.jl +++ b/src/init.jl @@ -1,24 +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 + # Load catalogues CatalogueCodes_path = joinpath(scratch_path[], "CatalogueCodes.txt") if isfile(CatalogueCodes_path) - global mpc_catalogues[] = read_catalogues_mpc(CatalogueCodes_path) - else + global CATALOGUES_MPC[] = read_catalogues_mpc(CatalogueCodes_path) + else update_catalogues_mpc() - end - # Load observatories + end + # Load observatories ObsCodes_path = joinpath(scratch_path[], "ObsCodes.txt") if isfile(ObsCodes_path) - global mpc_observatories[] = read_observatories_mpc(ObsCodes_path) - else + global OBSERVATORIES_MPC[] = 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/catalogue_mpc.jl b/src/observations/catalogue_mpc.jl index 6a240432..8271edf9 100644 --- a/src/observations/catalogue_mpc.jl +++ b/src/observations/catalogue_mpc.jl @@ -1,12 +1,15 @@ @doc raw""" CatalogueMPC -An astrometric reference catalogue in MPC format. The format is described in https://minorplanetcenter.net/iau/info/CatalogueCodes.html. +An astrometric reference catalogue in MPC format. # Fields -- `code::String`: catalogue's identifier. +- `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 @@ -47,92 +50,58 @@ function show(io::IO, m::CatalogueMPC) end end -# Regular expression to parse a catalogue in MPC format -const mpc_catalogue_regex = r"\s{2}(?P\w{1})\s{4}(?P.*)" +neoparse(x::RegexMatch, i::Int, ::Type{String}) = String(strip(x[i])) @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) - @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"])) -end - -@doc raw""" - read_catalogues_mpc(filename::String) - -Return the matches of `NEOs.mpc_catalogue_regex` in `filename` as `CatalogueMPC`. -""" -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 + # 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""" - get_raw_html(url::String) + read_catalogues_mpc(s::String) -Return the raw html text of webpage `url`. +Return the matches of `NEOs.CATALOGUE_MPC_REGEX` in `s` as `Vector{CatalogueMPC}`. +`s` can be either a filename or a text. """ -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 !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(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,21 +115,22 @@ 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 @doc raw""" - download_scratch(url::String, filename::String; connect_timeout=180, readtimeout=180) + 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`. +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) +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) @@ -171,9 +141,6 @@ function download_scratch(url::String, filename::String; connect_timeout=180, re return path, txt end -# List of MPC catalogues -const mpc_catalogues = Ref{Vector{CatalogueMPC}}([unknowncat()]) - @doc raw""" update_catalogues_mpc() @@ -181,13 +148,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 @@ -195,12 +162,12 @@ end @doc raw""" search_cat_code(catcode::String) -Return the catalogue in `NEOs.mpc_catalogues` that matches `catcode`. +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, mpc_catalogues[]) + idxs = findall(x -> x.code == catcode, CATALOGUES_MPC[]) L_i = length(idxs) # No catalog matches catcode @@ -208,10 +175,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/jpl_eph.jl b/src/observations/jpl_eph.jl index bba0c18f..88ad4938 100644 --- a/src/observations/jpl_eph.jl +++ b/src/observations/jpl_eph.jl @@ -2,7 +2,8 @@ @doc raw""" loadjpleph() -Load JPL ephemerides (NAIF IDs, DE430 TT-TDB and ephemerides, #197 and #199 solutions for Apophis). +Load JPL ephemerides (NAIF IDs, DE430 TT-TDB and ephemerides, #197 and #199 solutions for +Apophis). See also [`SPICE.furnsh`](@ref). """ @@ -115,27 +116,23 @@ 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) + 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: +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. + 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]) +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) @@ -143,16 +140,13 @@ function loadpeeph(eph::TaylorInterpolant{Float64, Float64, 2} = sseph, t_0::Rea 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]. +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/observations/observatory_mpc.jl b/src/observations/observatory_mpc.jl index df1a2392..d0be2709 100644 --- a/src/observations/observatory_mpc.jl +++ b/src/observations/observatory_mpc.jl @@ -1,37 +1,71 @@ @doc raw""" - ObservatoryMPC{T <: AbstractFloat} + ObservatoryMPC{T <: AbstractFloat} -An observatory in MPC format. The format is described in https://minorplanetcenter.net/iau/lists/ObsCodesF.html. +An observatory in MPC format. -# Fields +# 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. +- `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. """ -@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""" unknownobs() -Return a `ObservatoryMPC` with no code, coordinates or name. +Return a `ObservatoryMPC` with no code, coordinates or name. """ unknownobs() = ObservatoryMPC("", NaN, NaN, NaN, "") @@ -42,131 +76,87 @@ Check whether `m` equals `unknownobs()`. """ function isunknown(m::ObservatoryMPC{T}) where {T <: AbstractFloat} return m == unknownobs() -end +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. +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: +# 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} +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, replace(x[i], " " => "")) + if isnothing(y) return NaN - # The result is a float else - return p + return y end end @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"]), - ) - -end - -@doc raw""" - read_observatories_mpc(filename::String) - -Return the matches of `NEOs.mpc_observatory_regex` in `filename` 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 + # 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 -# Header of MPC observatories file -const mpc_observatories_header = "Code Long. cos sin Name" - @doc raw""" - parse_observatories_mpc(text::String) + read_observatories_mpc(s::String) -Return de matches of `NEOs.mpc_observatory_regex` in `text` as `ObservatoryMPC`. +Return the matches of `NEOs.OBSERVATORY_MPC_REGEX` in `s` as `Vector{ObservatoryMPC{Float64}}`. +`s` can be either a filename or a text. """ -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 @@ -176,12 +166,12 @@ end 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 + # NaN => empty string if isnan(x) - long_s = repeat(" ", 9) - else + 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 @@ -192,7 +182,7 @@ end 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 + # NaN => empty string if isnan(x) cos_s = repeat(" ", 8) else @@ -213,40 +203,29 @@ 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 + 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 - # Longitude string + # Longitude string long_s = mpc_long_str(obs.long) - # Cosine string + # Cosine string cos_s = mpc_cos_str(obs.cos) - # Sine string string + # 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 - ]) - end + obs_s = string(obs.code, long_s, cos_s, sin_s, obs.name) + end return obs_s end @@ -254,50 +233,47 @@ end @doc raw""" write_observatories_mpc(obs::Vector{ObservatoryMPC{T}}, filename::String) where {T <: AbstractFloat} -Write `obs` to `filename` in MPC format. +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 observatories + # Header + 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 end -# List of mpc observatories -const mpc_observatories = 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(mpc_observatories_url, "ObsCodes.txt") - # Parse observatories - obs = parse_observatories_mpc(txt) - # Write observatories to local file + # 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 mpc_observatories[] = read_observatories_mpc(ObsCodes_path) + # Update global variable + global OBSERVATORIES_MPC[] = read_observatories_mpc(ObsCodes_path) - return nothing + return nothing 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,14 +281,14 @@ 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 - - return observatory - + + return observatory + end \ No newline at end of file diff --git a/src/observations/process_radar.jl b/src/observations/process_radar.jl index a5536117..a0e9f373 100644 --- 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("tracklet.jl") include("process_radec.jl") @doc raw""" @@ -18,13 +19,14 @@ where ``\mu_\odot = GM_\odot`` is the gravitational parameter of the sun, and `` 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. + +!!! 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) @@ -42,8 +44,6 @@ Return the Doppler shift (in units of `F_tx`) 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. @@ -53,6 +53,9 @@ See https://doi.org/10.1103/PhysRevLett.17.933. - `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.) @@ -73,18 +76,20 @@ 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). + +!!! 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 @@ -159,18 +164,19 @@ of ionized electrons in interplanetary medium (electrons/cm^3), and ``s`` is the 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). + +!!! 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 @@ -240,8 +246,7 @@ function tropo_delay(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Numbe 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_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 @@ -252,22 +257,30 @@ where ``f`` is the transmitter frequency (MHz) and ``\tau`` is the time-delay at 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]. + +# 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} +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) @@ -464,14 +477,10 @@ function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; tord:: 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} + 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. @@ -479,21 +488,25 @@ Return time-delay and Doppler shift. - `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. +- `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} +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 @@ -568,8 +581,7 @@ function radar_astrometry(astradardata::Vector{RadarJPL{T}}; xva::AstEph, kwargs end @doc raw""" - residuals(obs::Vector{RadarJPL{T}}, niter::Int = 10; debias_table::String = "2018", - xvs = sunposvel, xve = earthposvel, xva) where {T <: AbstractFloat} + 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. @@ -579,13 +591,19 @@ 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]. + +# 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 diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index 657efa5e..038628fa 100644 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -1,47 +1,153 @@ @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} + OpticalResidual{T <: Real, U <: Number} -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. +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. -- `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]. +- `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} + 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 @@ -64,7 +170,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, @@ -73,14 +179,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 @@ -94,7 +200,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 @@ -103,6 +209,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] @@ -112,7 +219,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 @@ -126,15 +233,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])) @@ -171,25 +278,17 @@ 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 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: +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. @@ -234,8 +333,8 @@ function select_debiasing_table(debias_table::String = "2018") end @doc raw""" - debiasing(obs::RadecMPC{T}, mpc_catalogue_codes_201X::Vector{String}, truth::String, resol::Resolution, - bias_matrix::Matrix{T}) where {T <: AbstractFloat} + 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). @@ -247,8 +346,8 @@ Return total debiasing correction in right ascension and declination (both in ar - `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} +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 @@ -380,13 +479,51 @@ function w8sveres17(obs::RadecMPC{T}) where {T <: AbstractFloat} 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} + 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 -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. +@doc raw""" + residuals(obs::Vector{RadecMPC{T}}; kwargs...) where {T <: AbstractFloat, AstEph} -See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and [`Healpix.ang2pixRing`](@ref). +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 @@ -394,22 +531,31 @@ See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and # Keyword arguments -- `niter::Int`: number of light-time solution iterations. -- `debias_table::String`: possible values are: +- `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`: 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]. +- `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 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} + 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_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 @@ -417,93 +563,40 @@ 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) + # Relax factors + rex = relax_factor(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) + # Vector of residuals + res = Vector{OpticalResidual{T, S}}(undef, N_obs) # Iterate over the observations - Threads.@threads for i in 1:n_optical_obs - - # Time of observation - datetime_obs[i] = obs[i].date + 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 = 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]) - - 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 -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 + w8 = w8sveres17(obs[i]) -- `obs::Vector{RadecMPC{T}}`: vector of observations. - -# Keyword arguments + # 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 + ) -- `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[2] .- x_jt[6] .- x_jt[4] - # 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) + end - return res, w -end + return res +end \ No newline at end of file diff --git a/src/observations/radar_jpl.jl b/src/observations/radar_jpl.jl index 293511f7..262de5d7 100644 --- a/src/observations/radar_jpl.jl +++ b/src/observations/radar_jpl.jl @@ -7,9 +7,9 @@ A radar measurement in JPL format. - `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`: 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. @@ -25,8 +25,8 @@ A radar measurement in JPL format. 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. +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 @@ -42,16 +42,20 @@ Convert a match of `NEOs.jpl_radar_regex` to `RadarJPL`. A `Val{false}` indicate 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) + 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) +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""" @@ -68,9 +72,6 @@ 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 @@ -82,11 +83,12 @@ function show(io::IO, r::RadarJPL{T}) where {T <: AbstractFloat} doppler = hasdoppler(r) if delay && doppler - measurement_s = join([" Δτ: ", string(r.Δτ), " ", r.Δτ_units, " Δν: ", string(r.Δν), " ", r.Δν_units]) + measurement_s = string(" Δτ: ", string(r.Δτ), " ", r.Δτ_units, " Δν: ", + string(r.Δν), " ", r.Δν_units) elseif delay - measurement_s = join([" Δτ: ", string(r.Δτ), " ", r.Δτ_units]) + measurement_s = string(" Δτ: ", string(r.Δτ), " ", r.Δτ_units) elseif doppler - measurement_s = join([" Δν: ", string(r.Δν), " ", r.Δν_units]) + measurement_s = string(" Δν: ", string(r.Δν), " ", r.Δν_units) else measurement_s = " No measurements " end @@ -96,7 +98,6 @@ function show(io::IO, r::RadarJPL{T}) where {T <: AbstractFloat} 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 @@ -131,33 +132,6 @@ Check whether the transmission frequency `f_MHz` (in MHz) belongs to the X band """ 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) @@ -171,9 +145,9 @@ for (X, Y) in Iterators.product( (:(Val{false}), :(RegexMatch)), (:(Val{false}), end if $X == RegexMatch - date = DateTime(delay["date"], jpl_radar_dateformat) + date = DateTime(delay["date"], RADAR_JPL_DATEFORMAT) elseif $Y == RegexMatch - date = DateTime(doppler["date"], jpl_radar_dateformat) + date = DateTime(doppler["date"], RADAR_JPL_DATEFORMAT) else date = DateTime(2000, 1, 1) end @@ -238,14 +212,14 @@ end @doc raw""" read_radar_jpl(filename::String) -Return the matches of `NEOs.jpl_radar_regex` in `filename` as `Vector{RadarJPL}`. +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.(jpl_radar_regex, lines) + matches = match.(RADAR_JPL_REGEX, lines) # Eliminate nothings filter!(!isnothing, matches) # Number of matches @@ -318,17 +292,12 @@ function read_radar_jpl(filename::String) 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} - +# 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, jpl_radar_dateformat), + Dates.format(radar.date, RADAR_JPL_DATEFORMAT), @sprintf("%.2f", radar.Δτ), @sprintf("%1.3f", radar.Δτ_σ), radar.Δτ_units, @@ -345,7 +314,7 @@ function jpl_radar_str(radar::RadarJPL{T}) where {T <: AbstractFloat} if hasdoppler(radar) doppler_s = join([ radar.id, - Dates.format(radar.date, jpl_radar_dateformat), + Dates.format(radar.date, RADAR_JPL_DATEFORMAT), @sprintf("%.4f", radar.Δν), @sprintf("%1.3f", radar.Δν_σ), radar.Δν_units, @@ -360,7 +329,7 @@ function jpl_radar_str(radar::RadarJPL{T}) where {T <: AbstractFloat} end # Join everything - radar_s = join([delay_s, doppler_s]) + radar_s = string(delay_s, doppler_s) return radar_s end @@ -373,7 +342,7 @@ 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]) + line = string(radar[i]) write(file, line) end end diff --git a/src/observations/radec_mpc.jl b/src/observations/radec_mpc.jl index caa40457..de5dbfb3 100644 --- a/src/observations/radec_mpc.jl +++ b/src/observations/radec_mpc.jl @@ -1,10 +1,13 @@ +# 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 (α, δ) 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. +An optical (right ascension, declination) measurement in MPC format. # Fields @@ -17,11 +20,15 @@ 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. - `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 @@ -33,14 +40,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 +56,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) @@ -61,8 +68,8 @@ 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 +# 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 @@ -77,6 +84,7 @@ 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 @@ -86,72 +94,29 @@ 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})" - ] -)) - -@doc raw""" - datetime(year::Int, month::Int, day::Int, utc::T) where {T <: Real} +# Order in AbstractAstrometry is given by date +isless(a::T, b::T) where {T <: AbstractAstrometry} = a.date < b.date -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 @@ -161,17 +126,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 @@ -180,164 +144,76 @@ 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 mpc_observatories[] 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 - ) -end - -@doc raw""" - read_radec_mpc(filename::String) - -Return the matches of `NEOs.mpc_radec_regex` in `filename` as `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) - - return obs +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""" - parse_radec_mpc(text::String) - parse_radec_mpc(f::F, text::String) where F + RadecMPC(m::RegexMatch) -Return the matches of `NEOs.mpc_radec_regex` in `text`. A function `f(m::RegexMatch) -> Bool` -can be passed to filter the matches. +Convert a match of `NEOs.RADEC_MPC_REGEX` to `RadecMPC`. """ -function parse_radec_mpc(f::F, text::String) where F - - # Vector of observations - radecs = 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)) +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 - # If there is at least one observation - if length(radecs) > 0 - # Sort observations by date - sort!(radecs) - # Eliminate repeated observations - unique!(radecs) - end + end, 1:length(types)) - return radecs + return RadecMPC(args...) 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. +Return the matches of `NEOs.RADEC_MPC_REGEX` in `s` as `Vector{RadecMPC{Float64}}`. +`s` can be either a filename or a text. """ -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 +function read_radec_mpc(s::String) + if !contains(s, "\n") && isfile(s) + # Read MPC formatted file + s = String(read(s)) end - # If there is at least one observation - if length(obs) > 0 - # Sort observations by date - sort!(obs) - # Eliminate repeated observations - unique!(obs) + # 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 obs + return radec 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) @@ -362,13 +238,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 @@ -396,13 +266,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 @@ -432,52 +296,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 = string(abs(x)) + y = lpad(y, 10) + 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 @@ -490,25 +377,73 @@ 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 @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::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 save the output to `filename`. +Download MPC optical astrometry of NEO `id` and return the output as `Vector{RadecMPC{Float64}}`. """ -function get_radec_mpc(id::AbstractString, filename::AbstractString) - # 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 -end \ No newline at end of file +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 index b9d5bb3e..742a56ac 100644 --- a/src/observations/topocentric.jl +++ b/src/observations/topocentric.jl @@ -1,43 +1,189 @@ -# 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 ", Date(m.start), " to ", Date(m.stop), + " at UTC", @sprintf("%+d", m.utc)) +end @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} + hours_from_UTC(lon::T) where {T <: Real} -Return the observer's geocentric `[x, y, z]` position vector in Earth-Centered Earth-Fixed (ECEF) reference frame. +Return the naive hour difference between longitude `lon` [rad] and UTC. """ -function obs_pos_ECEF(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} +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 !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 + 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) - # Cilindrical components of Earth-Centered Earth-Fixed position of observer - λ_deg = observatory.long # deg - u = observatory.cos * RE # km - v = observatory.sin * RE # km + # ECEF position + pos_ECEF = convert(Vector{eltype(pv_ECEF.r)}, pv_ECEF.r) - # 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 + 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 - # Earth-Centered Earth-Fixed position position of observer - pos_ECEF = [x_gc, y_gc, z_gc] # 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 - return pos_ECEF + # 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 @@ -97,10 +243,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::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 @@ -109,38 +254,60 @@ 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). +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). +- `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}}}} - # 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) +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} @@ -149,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 diff --git a/src/observations/tracklet.jl b/src/observations/tracklet.jl new file mode 100644 index 00000000..60746af4 --- /dev/null +++ b/src/observations/tracklet.jl @@ -0,0 +1,182 @@ +@doc raw""" + Tracklet{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. +- `idxs::Vector{Int}`: indices of original `radec` that entered the tracklet. +""" +@auto_hash_equals struct Tracklet{T <: AbstractFloat} + radec::Vector{RadecMPC{T}} + observatory::ObservatoryMPC{T} + night::TimeOfDay + date::DateTime + α::T + δ::T + v_α::T + v_δ::T + mag::T + nobs::Int + indices::Vector{Int} + # Inner constructor + 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} + + return new{T}(radec, observatory, night, date, α, δ, v_α, v_δ, mag, nobs, indices) + end +end + +# 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 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 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) + +# 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 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) + indices = getfield(df, :rows) + # 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 Tracklet{T}(radec, observatory, night, date, α, + δ, v_α, v_δ, mag, nobs, indices) + 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 + + # Polynomial regression + α_coef = polyfit(df.t_rel, df.α) + δ_coef = polyfit(df.t_rel, df.δ) + + # Evaluate polynomials at mean date + α = 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)) + + return Tracklet{T}(radec, observatory, night, date, α, δ, v_α, + v_δ, mag, nobs, indices) +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. +""" +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 tracklets vector + tracklets = Vector{Tracklet{T}}(undef, gdf.ngroups) + # Reduce tracklets + Threads.@threads for i in 1:gdf.ngroups + rows = getfield(gdf[i], :rows) + tracklets[i] = Tracklet(radec[rows], gdf[i]) + 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 index 822cede7..2ad37651 100644 --- a/src/observations/units.jl +++ b/src/observations/units.jl @@ -1,23 +1,23 @@ @doc raw""" - julian2etsecs(jd) + julian2etsecs(jd::T) where {T <: Number} Convert the Julian date `jd` to ephemeris seconds since J2000. See also [`etsecs2julian`](@ref). """ -function julian2etsecs(jd) - return (jd-JD_J2000)*daysec +function julian2etsecs(jd::T) where {T <: Number} + return (jd - JD_J2000) * daysec end @doc raw""" - etsecs2julian(et) + etsecs2julian(et::T) where {T <: Number} Convert `et` ephemeris seconds since J2000 to Julian date. See also [`julian2etsecs`](@ref). """ -function etsecs2julian(et) - return JD_J2000 + et/daysec +function etsecs2julian(et::T) where {T <: Number} + return JD_J2000 + et / daysec end @doc raw""" @@ -41,21 +41,21 @@ function datetime2et(x::DateTime) return tt_seconds - ttmtdb_tt(tt_seconds) end -datetime2et(x::AbstractAstrometry) = datetime2et(x.date) +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::Number) = 2000 + et/daysec/yr +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::Number) = 2000 + d/yr +days_to_200X(d::T) where {T <: Number} = 2000 + d/yr @doc raw""" datetime_to_200X(x::DateTime) @@ -76,10 +76,10 @@ datetime2days(x::DateTime) = datetime2julian(x) - JD_J2000 Convert `d` days since J2000 to `DateTime`. """ -days2datetime(d::Number) = julian2datetime(d + JD_J2000) +days2datetime(d::T) where {T <: Number} = julian2datetime(d + JD_J2000) @doc raw""" - tdb_utc(et::Number) + tdb_utc(et::T) where {T <: Number} Given `et`, a number of TDB seconds past J2000.0 epoch, compute the difference (TDB-UTC) @@ -90,18 +90,20 @@ TDB-UTC & = (TDB-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). +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::Number) +function tdb_utc(et::T) where {T <: Number} # TT-TDB tt_tdb_et = ttmtdb(et/daysec) # TT-TAI @@ -120,22 +122,23 @@ function tdb_utc(et::Number) end @doc raw""" - tt_tdb_tt(tt::Real) + 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. -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. +- `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::Real; niter=5) +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) @@ -151,28 +154,28 @@ function ttmtdb_tt(tt::Real; niter=5) end @doc raw""" - rad2arcsec(x) + rad2arcsec(x::T) where {T <: Number} Convert radians to arcseconds. See also [`arcsec2rad`](@ref) and [`mas2rad`](@ref). """ -rad2arcsec(x) = 3600 * rad2deg(x) # rad2deg(rad) -> deg; 3600 * deg -> arcsec +rad2arcsec(x::T) where {T <: Number} = 3600 * rad2deg(x) # rad2deg(rad) -> deg; 3600 * deg -> arcsec @doc raw""" - arcsec2rad(x) + arcsec2rad(x::T) where {T <: Number} Convert arcseconds to radians. See also [`rad2arcsec`](@ref) and [`mas2rad`](@ref). """ -arcsec2rad(x) = deg2rad(x / 3600) # arcsec/3600 -> deg; deg2rad(deg) -> rad +arcsec2rad(x::T) where {T <: Number} = deg2rad(x / 3600) # arcsec/3600 -> deg; deg2rad(deg) -> rad @doc raw""" - mas2rad(x) + mas2rad(x::T) where {T <: Number} 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 +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 index 85e3dde1..3cd1d1f0 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -1,26 +1,27 @@ -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). # 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. -- `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} + ρ::Vector{U} D::Matrix{U} R_vec::Matrix{T} ρ_vec::Matrix{U} @@ -30,25 +31,26 @@ See also [`gauss_method`](@ref). 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) + # 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}, 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) +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: -# unique Gauss solution (r = 1.0800950907383229) +# 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, "Gauss solution (r = ", norm(cte.(g.statevect[1:3])), " AU)") end @doc raw""" @@ -77,7 +79,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""" @@ -86,7 +89,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""" @@ -114,43 +118,53 @@ 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 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. 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) +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} # 0-th order solution - sol_0, status = solve_lagrange(cte(a), cte(b), cte(c)) - # Discard empty solutions - idxs = findall(x -> x != :empty, status) + sol_0 = solve_lagrange(cte(a), cte(b), cte(c)) # Vector of solutions - sol = Vector{TaylorN{T}}(undef, length(idxs)) - # Iterate non-empty 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[idxs[i]] - r_2 = sol_0[idxs[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 @@ -158,81 +172,88 @@ function solve_lagrange(a::TaylorN{T}, b::TaylorN{T}, c::TaylorN{T}; niter::Int sol[i] = r_2 end - return sol, status[idxs] + 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}}; xve::EarthEph = et -> kmsec2auday(getposvel(399, 10, et)), - niter::Int = 10) where {T <: AbstractFloat, EarthEph} - 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} + 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). 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 - `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]. -- `niter::Int`: Number of iterations for Newton's method. +- `α::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}}; xve::EarthEph = et -> kmsec2auday(getposvel(399, 10, et)), niter::Int = 5) where {T <: AbstractFloat, EarthEph} +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, α, δ; xve = xve, niter = niter) + return gauss_method(observatories, dates, α, δ, params) 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} +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" - # 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)) - # Heliocentric state vector of the Earth [au, au/day] - G_vec = xve.(t_et) - + 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, :] = 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, :]) @@ -241,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 @@ -250,21 +271,21 @@ 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, status = solve_lagrange(a, b, c; niter = niter) + sol = solve_lagrange(a, b, c; niter = params.niter) # 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)))""") @@ -277,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) @@ -301,13 +324,224 @@ 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 + ) + 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 - 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]) +@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 - return sort!(sol_gauss, by = x -> norm(x.statevect[1:3])) + 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 unsuccessful + if isinf(best_Q) + return zero(NEOSolution{T, T}) + # Case: at least one solution was successful + 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 new file mode 100644 index 00000000..3e4067c7 --- /dev/null +++ b/src/orbit_determination/least_squares.jl @@ -0,0 +1,820 @@ +@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, idxs::AbstractVector{Int} = eachindex(x0)) 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 + for i in axes(x, 2) + x[:, i] .= x0 + end + # 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)[idxs] + # C matrix evaluated in xi + C = C_mat(xi)[idxs, idxs] #.+ ξTH_mat(xi) + # Update rule + Δx = - inv(C)*D + # New x + x[idxs, i+1] = xi[idxs] + Δ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[idxs, idxs]) + + 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, idxs::AbstractVector{Int} = eachindex(x0)) where {T <: Real} + # Unfold residuals and weights + _res_, _w_ = unfold(res) + + return diffcorr(_res_, _w_, x0, niters, idxs) +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 = Matrix{T}(undef, npar, niters + 1) + # First guess + for i in axes(x, 2) + x[:, i] .= x0 + end + # 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 = Matrix{T}(undef, npar, niters + 1) + # First guess + for i in axes(x, 2) + x[:, i] .= x0 + end + # 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 three routines: [`newtonls`](@ref), +[`diffcorr`](@ref) and [`levenbergmarquardt`](@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, :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] == :diffcorr + fit = diffcorr(res, x0, niters, idxs) + elseif order[i] == :lm + fit = levenbergmarquardt(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 new file mode 100644 index 00000000..176fe035 --- /dev/null +++ b/src/orbit_determination/neosolution.jl @@ -0,0 +1,199 @@ +@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 + +@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} + # Load Solar System ephemerides + loadjpleph() + # 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 diff --git a/src/orbit_determination/orbit_determination.jl b/src/orbit_determination/orbit_determination.jl new file mode 100644 index 00000000..cc09d816 --- /dev/null +++ b/src/orbit_determination/orbit_determination.jl @@ -0,0 +1,163 @@ +include("osculating.jl") +include("least_squares.jl") +include("neosolution.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 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) + if date(radec[i]) - date(radec[i-1]) > arc + return false + end + end + return true +end + +@doc raw""" + isgauss(sol::NEOSolution{T, T}) where {T <: AbstractFloat} + +Check whether `sol` was computed via [`gaussinitcond`](@ref) (`true`) or +via [`tooshortarc`](@ref) (`false`). +""" +function isgauss(tracklets::Vector{Tracklet{T}}) where {T <: AbstractFloat} + # Observing stations + obs = observatory.(tracklets) + # TSA is not well suited for satellite observatories + any(issatellite.(obs)) && return true + # Gauss cannot handle less than 3 tracklets + length(tracklets) < 3 && return false + # Time span + Δ = numberofdays(tracklets) + # Gauss approximation does not work with less than 1 day + return Δ > 1 +end + +isgauss(sol::NEOSolution{T, T}) where {T <: AbstractFloat} = isgauss(sol.tracklets) + +@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 500 +end + +@doc raw""" + orbitdetermination(radec::Vector{RadecMPC{T}}, params::NEOParameters{T}; + dynamics::D = newtonian!) where {T <: AbstractFloat, D} + +Initial Orbit Determination (IOD) routine. + +# Arguments + +- `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} + + # Allocate NEOSolution for output + sol = zero(NEOSolution{T, T}) + # Maximum number of steps + params = NEOParameters(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::NEOSolution{T, T} + end + # Reduce tracklets by polynomial regression + tracklets = reduce_tracklets(radec) + # 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 + +@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/src/orbit_determination/osculating.jl b/src/orbit_determination/osculating.jl index ac3c370b..cf290738 100644 --- a/src/orbit_determination/osculating.jl +++ b/src/orbit_determination/osculating.jl @@ -40,7 +40,8 @@ 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) + 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 @@ -55,18 +56,18 @@ end # 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") + 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), 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") + 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 @@ -85,21 +86,24 @@ function equatorial2ecliptic(xas::Vector{T}) where {T <: Number} end @doc raw""" - pv2kep(xas, μ = μ_S, jd = JD_J2000, frame::Symbol = :equatorial) + 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 a `OsculatingElements` object. +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). +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. +- `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; μ = μ_S, jd = JD_J2000, frame::Symbol = :equatorial) +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 @@ -167,14 +171,15 @@ where ``A_2`` is the Yarkovsky parameter, ``\mu_\odot = GM_\odot`` is the Sun's ``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. + +!!! 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(μ)) diff --git a/src/orbit_determination/tooshortarc.jl b/src/orbit_determination/tooshortarc.jl new file mode 100644 index 00000000..9805bc40 --- /dev/null +++ b/src/orbit_determination/tooshortarc.jl @@ -0,0 +1,718 @@ +@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. +- `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. +- `ρ_domain::Vector{T}`: range domain. +- `v_ρ_domain::Vector{T}`: range-rate domain. +- `Fs::Matrix{T}`: boundary points. +- `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 + H_max::T + a_max::T + ρ_unit::Vector{T} + ρ_α::Vector{T} + ρ_δ::Vector{T} + q::Vector{T} + coeffs::Vector{T} + ρ_domain::Vector{T} + v_ρ_domain::Vector{T} + Fs::Matrix{T} + 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), 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}) + +# 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 + 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] + t_days = datetime2days(t_datetime) + # Time of observation [et seconds] + t_et = datetime2et(t_datetime) + # Heliocentric position of the observer + 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) + # Maximum range (heliocentric constraint) + ρ_max = max_range(coeffs, a_max) + iszero(ρ_max) && return zero(AdmissibleRegion{T}) + # Minimum range + if isnan(h) + if R_SI < ρ_max + # Earth's sphere of influence radius + ρ_min = R_SI + else + # Earth's physical radius + ρ_min = R_EA + end + else + # Tiny object boundary + ρ_min = 10^((h - H_max)/5) + end + ρ_min > ρ_max && return zero(AdmissibleRegion{T}) + # Range domain + ρ_domain = [ρ_min, ρ_max] + # Range rate domain + 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, a_max, ρ_max)[1] + # Boundary points + Fs = Matrix{T}(undef, 3, 2) + Fs[1, :] .= [ρ_min, v_ρ_min] + Fs[2, :] .= [ρ_min, v_ρ_max] + Fs[3, :] .= [ρ_max, v_ρ_mid] + + return AdmissibleRegion{T}(t_datetime, α, δ, v_α, v_δ, H_max, a_max, + ρ, ρ_α, ρ_δ, q, coeffs, ρ_domain, v_ρ_domain, + Fs, obs) +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 [`AdmissibleRegion`](@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""" + 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_W(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} + +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} + 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 [`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} + 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} + +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}, 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, A.a_max, ρ) + +@doc raw""" + admsreg_V(A::AdmissibleRegion{T}, ρ::S) where {T <: AbstractFloat, S <: Number} + +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}, 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, 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}, 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, A.a_max, ρ) + +@doc raw""" + 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` and maximum semimajor axis `a_max`. +""" +function max_range(coeffs::Vector{T}, a_max::T) where {T <: AbstractFloat} + # Initial guess + 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 + niter = 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 + end + + return ρ_max +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 + x_min, x_max = A.ρ_domain + y_min, y_max = A.v_ρ_domain + # ρ = x_min + if 0.0 <= t <= 1.0 + return [x_min, y_min + t * (y_max - y_min)] + else + # Upper curve + if 1.0 <= t <= 2.0 + ρ = 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 - x_min) + v_ρ = range_rate(A, ρ)[1] + 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(ρ, A.ρ_domain[1], A.ρ_domain[2]) + # Project range-rate + 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 + +# 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] + y_range = range_rate(A, P[1]) + if length(y_range) == 1 + return P[2] == y_range[1] + else + return y_range[1] <= P[2] <= y_range[2] + end + 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 + ρ = euclid3D(r - A.q) + # Topocentric range rate + 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 + +@doc raw""" + attr2bary(A::AdmissibleRegion{T}, a::Vector{U}, + params::NEOParameters{T}) where {T <: AbstractFloat, U <: Number} + +Convert attributable elements `a` to barycentric cartesian coordinates. +""" +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 + # 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 + q = params.eph_ea(t) + kmsec2auday(obsposvelECI(A.observatory, et)) - params.eph_su(t) + # Barycentric position + r = q[1:3] + ρ * ρ_unit + params.eph_su(t)[1:3] + # Barycentric velocity + 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::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 + # 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) + return bwd, fwd, Vector{OpticalResidual{T, U}}(undef, 0) + end + # O-C residuals + res = residuals(radec, params; + 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 + +@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, 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₁ dx₂ dx₃ dx₄ dx₅ dx₆`. + +!!! 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}; scale::Symbol = :linear, η::T = 25.0, + μ::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) + # Attributable elements + ae = [A.α, A.δ, A.v_α, A.v_δ, zero(T), zero(T)] + # Scaling factors + scalings = Vector{T}(undef, 6) + scalings[1:4] .= abs.(ae[1:4]) ./ 1e6 + if scale == :linear + scalings[5] = (A.ρ_domain[2] - A.ρ_domain[1]) / 1_000 + elseif scale == :log + x = log10(ρ) + 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 + dae = scaled_variables("dx", scalings; order) + # Maximum number of iterations + maxiter = params.maxiter + # Allocate memory + ρs = Vector{T}(undef, maxiter+1) + v_ρs = Vector{T}(undef, maxiter+1) + Qs = fill(T(Inf), maxiter+1) + # Origin + x0 = zeros(T, 6) + x1 = zeros(T, 6) + # First momentum + m = zeros(T, 2) + _m_ = zeros(T, 2) + # Second momentum + n = zeros(T, 2) + _n_ = zeros(T, 2) + # Gradient descent + for t in 1:maxiter+1 + # Current position in admissible region + ρs[t] = ρ + v_ρs[t] = v_ρ + # Attributable elements + if scale == :linear + ae[5], ae[6] = ρ, v_ρ + AE = ae + dae + elseif scale == :log + 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, 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(x1) + # Convergence condition + t > 1 && abs(Qs[t] - Qs[t-1]) / Qs[t] < Qtol && break + # Gradient of objective function + g_t = TaylorSeries.gradient(Q)(x1)[5:6] + # 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[5:6] = x1[5:6] - η * _m_ ./ (sqrt.(_n_) .+ ϵ) + # Update values + ae .= AE(x1) + # Projection + ρ, v_ρ = boundary_projection(A, ae[5], ae[6]) + if scale == :log + x = log10(ρ) + end + end + # Find point with smallest Q + t = argmin(Qs) + + 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, dynamics::D=newtonian!) where {T <: AbstractFloat, D} + # 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; dynamics) + 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(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. + +!!! warning + 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!, + order = 6) where {T <: AbstractFloat, D} + # 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) + # 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 _ in 1:maxiter + # Initial conditions + q = q0 + dq + # Propagation & residuals + bwd, fwd, res = propres(radec, jd0, q, params; dynamics) + iszero(length(res)) && break + # Orbit fit + fit = tryls(res[idxs], x0, params.niter) + !fit.success && break + # 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) + 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 + # 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 +function tsatrackletorder(x::Tracklet{T}, y::Tracklet{T}) where {T <: AbstractFloat} + if x.nobs == y.nobs + return x.date > y.date + else + return x.nobs > y.nobs + 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}; + scale::Symbol = :log, dynamics::D = newtonian!) where {T <: AbstractFloat, D} + # Center + if scale == :linear + ρ = sum(A.ρ_domain) / 2 + elseif scale == :log + ρ = A.ρ_domain[1] + end + v_ρ = sum(A.v_ρ_domain) / 2 + # ADAM minimization over admissible region + ρ, v_ρ, Q = adam(radec, A, ρ, v_ρ, params; scale, 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} + +Return initial conditions by minimizing the normalized root mean square residual +over the admissible region. + +# Arguments + +- `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 model. + +!!! warning + 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} + + # Allocate memory for output + best_sol = zero(NEOSolution{T, T}) + # Sort tracklets by tsatrackletorder + idxs = sortperm(tracklets, lt = tsatrackletorder) + + # Iterate tracklets + for i in idxs + # Admissible region + A = AdmissibleRegion(tracklets[i], params) + iszero(A) && continue + # 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; + scale = :log, dynamics) + # Break condition + nrms(sol1) < params.tsaQmax && return sol1 + sol2 = _tooshortarc(A, radec, tracklets, i, params; + scale = :linear, dynamics) + # Break condition + nrms(sol2) < params.tsaQmax && return sol2 + else + sol1 = _tooshortarc(A, radec, tracklets, i, params; + scale = :linear, dynamics) + # Break condition + nrms(sol1) < params.tsaQmax && return sol1 + sol2 = _tooshortarc(A, radec, tracklets, i, params; + scale = :log, dynamics) + # Break condition + nrms(sol2) < params.tsaQmax && return sol2 + end + # Update best solution + if nrms(sol1) < nrms(best_sol) + best_sol = sol1 + elseif nrms(sol2) < nrms(best_sol) + best_sol = sol2 + end + end + + return best_sol +end \ No newline at end of file diff --git a/src/postprocessing/b_plane.jl b/src/postprocessing/b_plane.jl index 174d0c42..76436030 100644 --- a/src/postprocessing/b_plane.jl +++ b/src/postprocessing/b_plane.jl @@ -10,13 +10,14 @@ encounter. ``\mu_P`` is the planet's gravitational parameter, ``R_P`` is the pla 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). + +!!! 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) ) @@ -28,7 +29,7 @@ end 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. +- `ξ` = ``\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``. @@ -40,6 +41,9 @@ close encounter. Returns a named tuple with the following fields: - `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) @@ -130,8 +134,6 @@ and then substitutes into `valsecchi_circle(U_y, U_norm, k, h; m_pl=3.0034896149 `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). @@ -139,6 +141,9 @@ See section 2.1 in page 1181 of https://doi.org/10.1051/0004-6361:20031039. - `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 @@ -166,14 +171,15 @@ where ``c = m/U^2`` with ``m`` the mass of the planet and ``U = ||\mathbf{U}||`` 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. + +!!! 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 @@ -200,4 +206,4 @@ function valsecchi_circle(U_y, U_norm, k, h; m_pl=3.003489614915764e-6, a_pl=1.0 D0 = c*sinθ/(cosθ0p-cosθ) return R0, D0 -end +end \ No newline at end of file diff --git a/src/postprocessing/least_squares.jl b/src/postprocessing/least_squares.jl deleted file mode 100644 index 664c0521..00000000 --- a/src/postprocessing/least_squares.jl +++ /dev/null @@ -1,437 +0,0 @@ -include("b_plane.jl") - -@doc raw""" - nrms(res, w) - -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. - -""" -function nrms(res, w) - # Have as many residuals as weights - @assert length(res) == length(w) - # Normalized root mean square error - return sqrt( chi2(res, w)/length(res) ) -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) - -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(res, w, x0, niters=5) - -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 - -- `res`: Vector of residuals. -- `w`: Vector of weights. -- `x_0`: First guess for the initial conditions. -- `niters`: 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) - # 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 false, x[:, i+1], inv(C) - 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 true, x_new, Γ -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 - -- `res`: Vector of residuals. -- `w`: Vector of weights. -- `x_0`: First guess for the initial conditions. -- `niters`: 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) - # 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 false, x[:, i+1], inv(C) - 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 true, x_new, Γ -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 diff --git a/src/postprocessing/outlier_rejection.jl b/src/postprocessing/outlier_rejection.jl new file mode 100644 index 00000000..bfd0b8f0 --- /dev/null +++ b/src/postprocessing/outlier_rejection.jl @@ -0,0 +1,159 @@ +include("b_plane.jl") + +@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""" + outlier_rejection(radec::Vector{RadecMPC{T}}, sol::NEOSolution{T, T}, + 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. + +# Arguments + +- `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} + + # Origin + x0 = zeros(T, 6) + # Julian day to start propagation + jd0 = sol.bwd.t0 + PE.J2000 + # Initial conditions (T) + q0 = sol(sol.bwd.t0) + # Scaling factors + scalings = abs.(q0) ./ 10^6 + # Jet transport perturbation + dq = scaled_variables("δx", scalings; order = params.varorder) + # Initial conditions (jet transport) + q = q0 .+ dq + + # Propagation and residuals + 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) + + # NRMS (with 0 outliers) + Q_0 = nrms(res, fit) + + if Q_0 < 1 + return evalfit(NEOSolution(sol.tracklets, bwd, fwd, res, fit, scalings)) + end + + # Number of observations + N_radec = length(radec) + # Maximum allowed outliers + max_drop = ceil(Int, N_radec * params.max_per / 100) + # Boolean mask (0: included in fit, 1: outlier) + new_outliers = BitVector(zeros(Int, 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, x0, params.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, x0, params.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, x0, params.niter) + + return evalfit(NEOSolution(sol.tracklets, bwd, fwd, res, fit, scalings)) + 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; init = [1, max_drop + 1]) + # 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, x0, params.niter) + + return evalfit(NEOSolution(sol.tracklets, bwd, fwd, res, fit, scalings)) +end \ No newline at end of file diff --git a/src/propagation/asteroid_dynamical_models.jl b/src/propagation/asteroid_dynamical_models.jl index 6a6535c1..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 @@ -307,7 +310,7 @@ 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_[:, :, 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 @@ -874,7 +884,7 @@ 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_[:, :, 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] @@ -1173,4 +1186,106 @@ function RNp1BP_pN_A_J23E_J2S_eph_threads!(dq, q, params, t) dq[6] = postNewtonZ + accZ nothing -end \ No newline at end of file +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 diff --git a/src/propagation/jetcoeffs.jl b/src/propagation/jetcoeffs.jl index 7fc1c275..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) @@ -138,94 +139,168 @@ 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) .+ zero_q_1 + 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) + _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(_S), 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(_S), 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(_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 + 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) @@ -235,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) - 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) + 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) - 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) + 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) - 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) + 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) @@ -273,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] - 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) + 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) - tmp1604[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) - tmp1605[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) - 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) + 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) - 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) + 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) - 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) + 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) - 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) + 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) @@ -348,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 - 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) + 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 - 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) + 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(_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) + 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] - 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) + 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) - 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) + 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) - 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) + 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) - 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) + 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(_S), 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(_S), 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(_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)) - 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)) - pn1t7 .= Taylor1(zero(_S), order) - tmp1516 = Array{Taylor1{_S}}(undef, size(pn1t7)) - tmp1516 .= Taylor1(zero(_S), 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(_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 + 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) - 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) + 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) - 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) + 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) - 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) + 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) @@ -444,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 - tmp1533 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) - tmp1533 .= Taylor1(zero(_S), 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(_S), 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(_S), order) - tmp1536 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) - tmp1536 .= Taylor1(zero(_S), 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(_S), 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(_S), order) - tmp1539 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) - tmp1539 .= Taylor1(zero(_S), 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(_S), 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(_S), order) + for i = CartesianIndices(sumpnz) + sumpnz[i] = Taylor1(zero(constant_term(q[1])), order) + end 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) + 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) - 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) + 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) - 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) + 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\ex.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) @@ -495,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) - 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) + 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) - 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) + 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) - 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) + 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}}([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)]) + 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 - 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] + 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] @@ -628,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] - tmp1343 = __ralloc.v1[104] - tmp1345 = __ralloc.v1[105] - tmp1348 = __ralloc.v1[106] - tmp1350 = __ralloc.v1[107] - tmp1353 = __ralloc.v1[108] - tmp1355 = __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] - 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] - Xij_t_Ui = __ralloc.v1[152] - Yij_t_Vi = __ralloc.v1[153] - Zij_t_Wi = __ralloc.v1[154] - tmp1510 = __ralloc.v1[155] - Rij_dot_Vi = __ralloc.v1[156] - tmp1513 = __ralloc.v1[157] - pn1t7 = __ralloc.v1[158] - tmp1516 = __ralloc.v1[159] - pn1t2_7 = __ralloc.v1[160] - tmp1523 = __ralloc.v1[161] - tmp1524 = __ralloc.v1[162] - tmp1525 = __ralloc.v1[163] - tmp1533 = __ralloc.v1[164] - termpnx = __ralloc.v1[165] - sumpnx = __ralloc.v1[166] - tmp1536 = __ralloc.v1[167] - termpny = __ralloc.v1[168] - sumpny = __ralloc.v1[169] - tmp1539 = __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]) @@ -797,544 +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_[:, :, 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\ex.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]) - (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]) - (_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]) - (_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]) - (_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]) - (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]) - (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]) - (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]) - (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]) - (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] - (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]) - (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]) - (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]) - (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]) - (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]) - (tmp1604[i]).coeffs[1] = sqrt(1 - constant_term(sin_ϕ[i]) ^ 2) - (tmp1604[i]).coeffs[2:order + 1] .= zero((tmp1604[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]) - (tmp1605[i]).coeffs[1] = sin(constant_term(ϕ[i])) - (tmp1605[i]).coeffs[2:order + 1] .= zero((tmp1605[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]) - (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) - (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]) - (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]) - (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]) - (∂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])) - (Λ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])) - (Λ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]) - (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]) - (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]) - (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]) - (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]) - (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]) - (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]) - (ξ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]) - (ξ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]) - (ξ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 - (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]) - (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 - 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) - (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] - (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]) - (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]) - (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]) - (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]) - (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]) - (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\ex.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]) - (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]) - (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]) - (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]) - (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]) - (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]) - (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]) - (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]) - (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 - (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]) - (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]) - (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]) - (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]) - (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]) - (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\ex.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]) - 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) - 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) - 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) - 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) - 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) - 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) - 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)) - 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]) - 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)) - 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)) - 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)) - 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]) - 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) - 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) - 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) - 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) - (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) - (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) - (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 @@ -1350,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\ex.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) @@ -1360,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!(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!(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!(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!(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!(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!(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) @@ -1398,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!(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!(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], tmp1604[i], ord) - TaylorSeries.sincos!(tmp1605[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!(tmp1407[i], 1.5, sin2_ϕ[i], ord) - TaylorSeries.subst!(P_2_sin_ϕ[i], tmp1407[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!(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!(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!(tmp1438[i], Λ3j_div_r5[i], 4, ord) - TaylorSeries.mul!(F_J3_ξ[i], tmp1438[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!(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!(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) @@ -1471,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!(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!(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!(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!(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!(tmp1491[i], μ[i], F_J2_x[i], ord) - TaylorSeries.subst!(temp_accX_i[i], accX, tmp1491[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!(tmp1493[i], μ[i], F_J2_y[i], ord) - TaylorSeries.subst!(temp_accY_i[i], accY, tmp1493[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!(tmp1495[i], μ[i], F_J2_z[i], ord) - TaylorSeries.subst!(temp_accZ_i[i], accZ, tmp1495[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\ex.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!(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!(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!(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!(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!(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!(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) @@ -1530,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!(tmp1533[i], U_t_pn2[i], pNX_t_pn3[i], ord) - TaylorSeries.add!(termpnx[i], X_t_pn1[i], tmp1533[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!(tmp1536[i], V_t_pn2[i], pNY_t_pn3[i], ord) - TaylorSeries.add!(termpny[i], Y_t_pn1[i], tmp1536[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!(tmp1539[i], W_t_pn2[i], pNZ_t_pn3[i], ord) - TaylorSeries.add!(termpnz[i], Z_t_pn1[i], tmp1539[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\ex.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) @@ -1562,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!(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!(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!(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!(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!(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!(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 @@ -1649,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) @@ -1749,94 +1880,168 @@ 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) .+ zero_q_1 + 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) + _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(_S), 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(_S), 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(_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 + 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) @@ -1846,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) - 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) + 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) - 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) + 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) - 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) + 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) @@ -1884,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] - 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) + 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) - tmp2183[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) - tmp2184[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) - 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) + 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) - 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) + 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) - 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) + 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) - 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) + 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) @@ -1959,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 - 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) + 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 - 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) + 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(_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) + 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] - 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) + 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) - 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) + 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) - 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) + 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) - 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) + 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(_S), 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(_S), 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(_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)) - 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)) - pn1t7 .= Taylor1(zero(_S), order) - tmp2145 = Array{Taylor1{_S}}(undef, size(pn1t7)) - tmp2145 .= Taylor1(zero(_S), 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(_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 + 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) - 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) + 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) - 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) + 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) - 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) + 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) @@ -2055,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 - tmp2162 = Array{Taylor1{_S}}(undef, size(U_t_pn2)) - tmp2162 .= Taylor1(zero(_S), 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(_S), 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(_S), order) - tmp2165 = Array{Taylor1{_S}}(undef, size(V_t_pn2)) - tmp2165 .= Taylor1(zero(_S), 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(_S), 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(_S), order) - tmp2168 = Array{Taylor1{_S}}(undef, size(W_t_pn2)) - tmp2168 .= Taylor1(zero(_S), 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(_S), 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(_S), order) + for i = CartesianIndices(sumpnz) + sumpnz[i] = Taylor1(zero(constant_term(q[1])), order) + end 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) + 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) - 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) + 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) - 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) + 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\ex.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) @@ -2109,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}}([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}}([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 - tmp2112 = __ralloc.v0[1] - tmp2114 = __ralloc.v0[2] - tmp2115 = __ralloc.v0[3] - tmp2117 = __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] @@ -2142,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] - tmp1972 = __ralloc.v1[104] - tmp1974 = __ralloc.v1[105] - tmp1977 = __ralloc.v1[106] - tmp1979 = __ralloc.v1[107] - tmp1982 = __ralloc.v1[108] - tmp1984 = __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] - 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] - Xij_t_Ui = __ralloc.v1[152] - Yij_t_Vi = __ralloc.v1[153] - Zij_t_Wi = __ralloc.v1[154] - tmp2139 = __ralloc.v1[155] - Rij_dot_Vi = __ralloc.v1[156] - tmp2142 = __ralloc.v1[157] - pn1t7 = __ralloc.v1[158] - tmp2145 = __ralloc.v1[159] - pn1t2_7 = __ralloc.v1[160] - tmp2152 = __ralloc.v1[161] - tmp2153 = __ralloc.v1[162] - tmp2154 = __ralloc.v1[163] - tmp2162 = __ralloc.v1[164] - termpnx = __ralloc.v1[165] - sumpnx = __ralloc.v1[166] - tmp2165 = __ralloc.v1[167] - termpny = __ralloc.v1[168] - sumpny = __ralloc.v1[169] - tmp2168 = __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]) @@ -2311,446 +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_[:, :, 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\ex.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]) - (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]) - (_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]) - (_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]) - (_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]) - (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]) - (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]) - (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]) - (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]) - (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] - (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]) - (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]) - (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]) - (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]) - (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]) - (tmp2183[i]).coeffs[1] = sqrt(1 - constant_term(sin_ϕ[i]) ^ 2) - (tmp2183[i]).coeffs[2:order + 1] .= zero((tmp2183[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]) - (tmp2184[i]).coeffs[1] = sin(constant_term(ϕ[i])) - (tmp2184[i]).coeffs[2:order + 1] .= zero((tmp2184[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]) - (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) - (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]) - (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]) - (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]) - (∂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])) - (Λ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])) - (Λ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]) - (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]) - (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]) - (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]) - (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]) - (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]) - (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]) - (ξ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]) - (ξ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]) - (ξ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 - (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]) - (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 - 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) - (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] - (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]) - (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]) - (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]) - (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]) - (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]) - (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\ex.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]) - (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]) - (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]) - (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]) - (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]) - (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]) - (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]) - (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]) - (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 - (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]) - (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]) - (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]) - (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]) - (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]) - (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\ex.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 @@ -2766,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\ex.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) @@ -2776,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!(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!(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!(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!(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!(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!(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) @@ -2814,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!(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!(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], tmp2183[i], ord) - TaylorSeries.sincos!(tmp2184[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!(tmp2036[i], 1.5, sin2_ϕ[i], ord) - TaylorSeries.subst!(P_2_sin_ϕ[i], tmp2036[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!(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!(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!(tmp2067[i], Λ3j_div_r5[i], 4, ord) - TaylorSeries.mul!(F_J3_ξ[i], tmp2067[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!(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!(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) @@ -2887,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!(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!(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!(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!(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!(tmp2120[i], μ[i], F_J2_x[i], ord) - TaylorSeries.subst!(temp_accX_i[i], accX, tmp2120[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!(tmp2122[i], μ[i], F_J2_y[i], ord) - TaylorSeries.subst!(temp_accY_i[i], accY, tmp2122[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!(tmp2124[i], μ[i], F_J2_z[i], ord) - TaylorSeries.subst!(temp_accZ_i[i], accZ, tmp2124[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\ex.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!(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!(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!(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!(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!(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!(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) @@ -2946,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!(tmp2162[i], U_t_pn2[i], pNX_t_pn3[i], ord) - TaylorSeries.add!(termpnx[i], X_t_pn1[i], tmp2162[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!(tmp2165[i], V_t_pn2[i], pNY_t_pn3[i], ord) - TaylorSeries.add!(termpny[i], Y_t_pn1[i], tmp2165[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!(tmp2168[i], W_t_pn2[i], pNZ_t_pn3[i], ord) - TaylorSeries.add!(termpnz[i], Z_t_pn1[i], tmp2168[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\ex.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) @@ -2986,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/src/propagation/parameters.jl b/src/propagation/parameters.jl new file mode 100644 index 00000000..8ce1d012 --- /dev/null +++ b/src/propagation/parameters.jl @@ -0,0 +1,136 @@ +struct NEOParameters{T <: AbstractFloat} + # Propagation parameters + maxsteps::Int + μ_ast::Vector{T} + order::Int + abstol::T + parse_eqs::Bool + bwdoffset::T + fwdoffset::T + coeffstol::T + # Residuals parameters + mpc_catalogue_codes_201X::Vector{String} + 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 + max_triplets::Int + varorder::Int + gaussQmax::T + # Admissible Region parameters + H_max::T + a_max::T + maxiter::Int + tsaQmax::T + # Outlier rejection parameters + max_per::T + # 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""" + NEOParameters([params::NEOParameters{T};] kwargs...) where {T <: AbstractFloat} + +Parameters for all orbit determination functions. + +# Propagation Parameters + +- `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`). +- `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 + +- `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`). +- `gaussQmax::T`: nrms threshold (default: `5.0`). + +# Admissible Region Parameters + +- `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`). + +# Outlier Rejection Parameters + +- `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 = 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 + _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, + 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} + fields = fieldnames(NEOParameters{T}) + vals = Vector{Any}(undef, length(fields)) + for i in eachindex(vals) + if fields[i] in keys(kwargs) + vals[i] = kwargs[fields[i]] + else + vals[i] = getfield(params, i) + end + end + + return NEOParameters{T}(vals...) +end + +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 a8281d8e..50ed7c1b 100644 --- a/src/propagation/propagation.jl +++ b/src/propagation/propagation.jl @@ -1,10 +1,7 @@ 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) +include("parameters.jl") @doc raw""" rvelea(dx, x, params, t) @@ -30,7 +27,8 @@ function rvelea(dx, x, params, t) end @doc raw""" - scaled_variables(c::Vector{T} = fill(1e-6, 6), names::String = "δx"; order::Int = 5) where {T <: Real} + 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`. """ @@ -44,26 +42,48 @@ function scaled_variables(names::String = "δx", c::Vector{T} = fill(1e-6, 6); o return dq end +function issuccessfulprop(sol::TaylorInterpolant, t::T; tol::T = 10.0) where {T <: Real} + # Zero TaylorInterpolant + iszero(sol) && return false + # Forward integration + if issorted(sol.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) + # 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 + return false + end + # All coefficients are below tol + return all( norm.(view(sol.x, 1:i, :), Inf) .< tol ) +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}, + params::NEOParameters{T}) 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. -- `μ_ast::Vector`: vector of gravitational parameters. -- `order::Int`: order of the Taylor expansions to be used in the integration. -- `abstol::T`: absolute tolerance. +- `q0::Vector{V}`: vector of initial conditions. +- `params::NEOParameters{T}`: see `Propagation Parameters` of [`NEOParameters`](@ref). """ -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}, + params::NEOParameters{T}) 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)) @@ -81,7 +101,7 @@ function propagate_params(jd0::T, tspan::T, q0::Vector{U}; μ_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 μ" @@ -109,178 +129,113 @@ 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, 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. -- `maxsteps::Int`: maximum number of steps for the integration. -- `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. -- `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 +- `q0::Vector{V}`: vector of initial conditions. +- `params::NEOParameters{T}`: see [`NEOParameters`](@ref). +""" +function propagate(dynamics::D, jd0::U, tspan::T, q0::Vector{V}, + params::NEOParameters{T}) where {T <: Real, U <: Number, V <: Number, D} + + # Unfold + maxsteps, order, abstol, parse_eqs = params.maxsteps, params.order, params.abstol, params.parse_eqs + + # Check order + @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, params) + + # Propagate orbit + + @time tv, xv, psol = taylorinteg(dynamics, _q0, _t0, _tmax, order, abstol, Val(true), _params; + maxsteps = maxsteps, parse_eqs = parse_eqs) + + if issorted(tv) || issorted(tv, rev = true) + # 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 +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], - order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number, D} + propagate_root(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, + 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 `rvelea`. +Integrate the orbit of a NEO via the Taylor method while finding the zeros of +`NEOs.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. -- `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. +- `params::NEOParameters{T}`: see [`NEOParameters`](@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. -- `μ_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} - - # Parameters for taylorinteg - _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast, order, abstol) - - # Propagate orbit - - @time sol = taylorinteg(dynamics, _q0, _t0, _tmax, order, abstol, $V_dense(), _params; - maxsteps, 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, order, - abstol = _abstol, 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, order, - abstol, parse_eqs) - # Forward integration - fwd = propagate(dynamics, maxsteps, jd0, nyears_fwd, q0, $V_dense(); μ_ast, order, - abstol, 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} - - # Parameters for neosinteg - _q0, _t0, _tmax, _params = propagate_params(jd0, tspan, q0; μ_ast, order, 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 - - 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) +""" +function propagate_root(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, + params::NEOParameters{T}; eventorder::Int = 0, newtoniter::Int = 10, + nrabstol::T = eps(T)) where {T <: Real, U <: Number, D} - 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 + # Unfold + maxsteps, order, abstol, parse_eqs = params.maxsteps, params.order, params.abstol, params.parse_eqs - 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 <= SSEPHORDER "order ($order) must be less or equal than SS ephemeris order ($SSEPHORDER)" - # 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, params) - 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""" - 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} + propagate_lyap(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, + params::NEOParameters{T}) 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. -""" 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} +- `params::NEOParameters{T}`: see [`NEOParameters`](@ref). +""" +function propagate_lyap(dynamics::D, jd0::T, tspan::T, q0::Vector{U}, + params::NEOParameters{T}) where {T <: Real, U <: Number, D} + + # Unfold + maxsteps, order, abstol, parse_eqs = params.maxsteps, params.order, params.abstol, params.parse_eqs + + # Check order + @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; 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/extensions.jl b/test/dataframes.jl similarity index 96% rename from test/extensions.jl rename to test/dataframes.jl index c0512ff4..60a78681 100644 --- a/test/extensions.jl +++ b/test/dataframes.jl @@ -1,13 +1,12 @@ using NEOs -using Dates -using Tables +using Dates using DataFrames using Query 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/observations.jl b/test/observations.jl index ef7a7fc8..166467d8 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 @@ -9,15 +10,15 @@ using NEOs: src_path @testset "CatalogueMPC" begin - using NEOs: mpc_catalogue_regex, CatalogueMPC + using NEOs: CATALOGUE_MPC_REGEX, CatalogueMPC, isunknown - # 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 +35,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") @@ -51,15 +52,15 @@ using NEOs: src_path @testset "ObservatoryMPC" begin - using NEOs: mpc_observatory_regex, ObservatoryMPC + using NEOs: OBSERVATORY_MPC_REGEX, ObservatoryMPC, isunknown - # 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 +69,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 +98,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") @@ -116,24 +117,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 +149,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) @@ -157,31 +158,10 @@ 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) source_radec = read_radec_mpc(source_file) @@ -190,7 +170,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) @@ -202,14 +182,14 @@ using NEOs: src_path @testset "RadarJPL" begin - using NEOs: jpl_radar_regex, RadarJPL, jpl_radar_dateformat + 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(jpl_radar_regex, apophis_s) + 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", jpl_radar_dateformat) + @test apophis.date == DateTime("2005-01-27 23:31:00", RADAR_JPL_DATEFORMAT) @test isnan(apophis.Δτ) @test isnan(apophis.Δτ_σ) @test apophis.Δτ_units == "" @@ -238,4 +218,87 @@ 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 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 new file mode 100644 index 00000000..baa5578f --- /dev/null +++ b/test/orbit_determination.jl @@ -0,0 +1,305 @@ +# 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) .< 4e-7 ) + @test nrms(sol) < 0.36 + # Scaling 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 + # Scaling 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 + # 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 + # Scaling 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 + # Scaling 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 + # Scaling 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 -> w8sveres17(x) < 1, 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 + # Scaling 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) + + # 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[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 + # Scaling factors + @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)) + # TODO: understand better differences wrt JPL solutions + # @test nrms(sol1) < nrms(sol) + end + +end \ No newline at end of file diff --git a/test/propagation.jl b/test/propagation.jl index eba5a141..557fb83e 100644 --- a/test/propagation.jl +++ b/test/propagation.jl @@ -26,52 +26,52 @@ using InteractiveUtils: methodswith @testset "Orbit propagation without nongravs: 2023 DW" begin - objname = "2023DW" - maxsteps = 1000 - nyears = 0.2 + # Dynamical function dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! # Initial time [Julian date] - jd0 = datetime2julian(DateTime(2023,2,25,0,0,0)) + 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 - # 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) + 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 (backward and forward) + # Warmup propagation (forward) NEOs.propagate( dynamics, - 1, jd0, - -nyears, nyears, q0, - Val(true), - order = 25, - abstol = 1e-20, - parse_eqs = true + params ) - - # propagate orbit - sol_bwd, sol = NEOs.propagate( + # Propagate orbit + params = NEOParameters(params; maxsteps = 1_000) + sol_bwd = NEOs.propagate( dynamics, - maxsteps, jd0, -nyears, + q0, + params + ) + sol = NEOs.propagate( + dynamics, + jd0, nyears, q0, - Val(true), - order = 25, - abstol = 1e-20, - parse_eqs = true + params ) - # check that solution saves correctly + # 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") @@ -83,61 +83,63 @@ using InteractiveUtils: methodswith @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] + 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] + 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")) + obs_radec_mpc_2023DW = 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)) + 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-2 - @test std_radec0 ≈ 0.736 atol=1e-2 - @test rms_radec0 ≈ 0.992 atol=1e-2 + 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 + # Propagate orbit with perturbed initial conditions q1 = q0 + vcat(1e-3randn(3), 1e-5randn(3)) sol1 = NEOs.propagate( dynamics, - maxsteps, jd0, nyears, q1, - Val(true), - order = 25, - abstol = 1e-20, - parse_eqs = true + params ) - # check that solution saves correctly + # 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( + # 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)) + 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))) + rms_radec1 = nrms(res1, ones(length(res1))) @test abs(mean_radec1) ≥ abs(mean_radec0) @test std_radec1 ≥ std_radec0 @@ -146,66 +148,63 @@ using InteractiveUtils: methodswith @testset "Orbit propagation with nongravs: (99942) Apophis" begin - # integration parameters - objname = "Apophis" - maxsteps = 5000 - nyears = 9.0 + # Dynamical function dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! # Initial time [Julian date] - jd0 = datetime2julian(DateTime(2004,6,1)) + 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 - # 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) + 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 + # Warmup propagation sol = NEOs.propagate( dynamics, - 1, jd0, nyears, q0, - Val(true), - order = 25, - abstol = 1e-20, - parse_eqs = true + params ) - - # propagate orbit + # Propagate orbit + params = NEOParameters(params, maxsteps = 5_000) sol = NEOs.propagate( dynamics, - maxsteps, jd0, nyears, q0, - Val(true), - order = 25, - abstol = 1e-20, - parse_eqs = true + params ) - # check that solution saves correctly + # 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")) + obs_radec_mpc_apophis = 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)) + 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) @@ -217,8 +216,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.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 @@ -230,11 +229,11 @@ using InteractiveUtils: methodswith # 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 + 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) @@ -251,7 +250,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.366 atol=1e-3 end @testset "Jet transport propagation and TaylorN serialization" begin @@ -259,29 +258,33 @@ using InteractiveUtils: methodswith # 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 + 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) - local dq = NEOs.scaled_variables() - # Initial date of integration (julian days) - local jd0 = datetime2julian(DateTime(2029, 4, 13, 20)) + dq = NEOs.scaled_variables(order=1) # 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, Val(true); order, abstol, parse_eqs) + 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) + + # 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 rm("test.jld2") - sol, tvS, xvS, gvS = NEOs.propagate_root(dynamics, 1, jd0, 0.02, q0, Val(true); order, abstol, parse_eqs) - @test sol isa TaylorInterpolant + 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") @@ -294,9 +297,10 @@ using InteractiveUtils: methodswith @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)))] + # 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 @@ -306,47 +310,68 @@ using InteractiveUtils: methodswith @testset "Jet transport orbit propagation and astrometric observables: (99942) Apophis" begin + # Dynamical functions + dynamicsg = RNp1BP_pN_A_J23E_J2S_eph_threads! + dynamicsng = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! # 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 + # 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, - maxsteps, + dynamicsng, jd0, nyears, q0, - Val(true), - order = 25, - abstol = 1e-20, - parse_eqs = true + params ) - 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) + eph_su = selecteph(NEOs.sseph, su, sol.t0, sol.t0 + sol.t[end]) # Earth's ephemeris - eph_ea::TaylorInterpolant{Float64,Float64,2} = 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 + 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 = 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, w_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_ = NEOs.residuals(obs_radec_mpc_apophis, params; xvs, xve, xva) + res_radec, w_radec = NEOs.unfold(_res_radec_) nobsopt = round(Int, length(res_radec)) # Compute mean optical astrometric residual (right ascension and declination) @@ -358,8 +383,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.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 @@ -369,29 +394,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 diff --git a/test/runtests.jl b/test/runtests.jl index 148d198e..ad9cd3f3 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,7 +4,8 @@ testfiles = ( "osculating.jl", "observations.jl", "propagation.jl", - "extensions.jl" + "orbit_determination.jl", + "dataframes.jl", ) for file in testfiles