Antkeeper  0.0.1
ephemeris.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Christopher J. Howard
3  *
4  * This file is part of Antkeeper source code.
5  *
6  * Antkeeper source code is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Antkeeper source code is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
21 #include <bit>
22 #include <cstdint>
25 
27 static constexpr std::size_t jpl_de_offset_time = 0xA5C;
28 
30 static constexpr std::size_t jpl_de_offset_table1 = 0xA88;
31 
33 static constexpr std::size_t jpl_de_offset_denum = 0xB18;
34 
36 static constexpr std::size_t jpl_de_offset_table2 = 0xB1C;
37 
39 static constexpr std::size_t jpl_de_offset_table3 = 0xB28;
40 
42 static constexpr std::int32_t jpl_de_denum_endian_mask = 0xFFFF0000;
43 
45 static constexpr std::size_t jpl_de_table1_count = 12;
46 
48 static constexpr std::size_t jpl_de_table2_count = 1;
49 
51 static constexpr std::size_t jpl_de_table3_count = 2;
52 
54 static constexpr std::size_t jpl_de_max_item_count = jpl_de_table1_count + jpl_de_table2_count + jpl_de_table3_count;
55 
57 static constexpr std::size_t jpl_de_constant_limit = 400;
58 
60 static constexpr std::size_t jpl_de_constant_length = 6;
61 
63 enum
64 {
67 
70 
73 
76 
79 
82 
85 
88 
91 
94 
97 
100 
103 
106 
109 };
110 
112 static constexpr std::uint8_t jpl_de_component_count[jpl_de_max_item_count] =
113 {
114  3, // Mercury: x,y,z (km)
115  3, // Venus: x,y,z (km)
116  3, // Earth-Moon barycenter: x,y,z (km)
117  3, // Mars: x,y,z (km)
118  3, // Jupiter: x,y,z (km)
119  3, // Saturn: x,y,z (km)
120  3, // Uranus: x,y,z (km)
121  3, // Neptune: x,y,z (km)
122  3, // Pluto: x,y,z (km)
123  3, // Moon: x,y,z (km)
124  3, // Sun: x,y,z (km)
125  2, // Earth nutation: d_psi,d_epsilon (radians)
126  3, // Lunar mantle libration: phi,theta,ps (radians)
127  3, // Lunar mantle angular velocity: omega_x,omega_y,omega_z (radians/day)
128  1 // TT-TDB: t (seconds)
129 };
130 
139 template <>
141 {
142  ephemeris.trajectories.clear();
143 
144  // Init file reading function pointers
145  std::size_t (deserialize_context::*read32)(std::byte*, std::size_t) = &deserialize_context::read32<std::endian::native>;
146  std::size_t (deserialize_context::*read64)(std::byte*, std::size_t) = &deserialize_context::read64<std::endian::native>;
147 
148  // Read DE version number
149  std::int32_t denum;
150  ctx.seek(jpl_de_offset_denum);
151  ctx.read8(reinterpret_cast<std::byte*>(&denum), sizeof(std::int32_t));
152 
153  // If file endianness does not match host endianness
154  if (denum & jpl_de_denum_endian_mask)
155  {
156  // Use endian-swapping read functions
157  if constexpr (std::endian::native == std::endian::little)
158  {
159  read32 = &deserialize_context::read32<std::endian::big>;
160  read64 = &deserialize_context::read64<std::endian::big>;
161  }
162  else
163  {
164  read32 = &deserialize_context::read32<std::endian::little>;
165  read64 = &deserialize_context::read64<std::endian::little>;
166  }
167  }
168 
169  // Read ephemeris time
170  double ephemeris_time[3];
171  ctx.seek(jpl_de_offset_time);
172  std::invoke(read64, ctx, reinterpret_cast<std::byte*>(ephemeris_time), 3);
173 
174  // Make time relative to J2000 epoch
175  const double epoch = 2451545.0;
176  ephemeris_time[0] -= epoch;
177  ephemeris_time[1] -= epoch;
178 
179  // Read number of constants
180  std::int32_t constant_count;
181  std::invoke(read32, ctx, reinterpret_cast<std::byte*>(&constant_count), 1);
182 
183  // Read first coefficient table
184  std::int32_t coeff_table[jpl_de_max_item_count][3];
185  ctx.seek(jpl_de_offset_table1);
186  std::invoke(read32, ctx, reinterpret_cast<std::byte*>(coeff_table), jpl_de_table1_count * 3);
187 
188  // Read second coefficient table
189  ctx.seek(jpl_de_offset_table2);
190  std::invoke(read32, ctx, reinterpret_cast<std::byte*>(&coeff_table[jpl_de_table1_count][0]), jpl_de_table2_count * 3);
191 
192  // Seek past extra constant names
193  if (constant_count > jpl_de_constant_limit)
194  {
195  ctx.seek(jpl_de_offset_table3 + (constant_count - jpl_de_constant_limit) * jpl_de_constant_length);
196  }
197 
198  // Read third coefficient table
199  std::invoke(read32, ctx, reinterpret_cast<std::byte*>(&coeff_table[jpl_de_table1_count + jpl_de_table2_count][0]), jpl_de_table3_count * 3);
200 
201  // Calculate number of coefficients per record
202  std::int32_t record_coeff_count = 0;
203  for (int i = 0; i < jpl_de_max_item_count; ++i)
204  {
205  std::int32_t coeff_count = coeff_table[i][0] + coeff_table[i][1] * coeff_table[i][2] * static_cast<std::int32_t>(jpl_de_component_count[i]) - 1;
206  record_coeff_count = std::max(record_coeff_count, coeff_count);
207  }
208 
209  // Calculate record size and record count
210  std::size_t record_size = record_coeff_count * sizeof(double);
211  std::size_t record_count = static_cast<std::size_t>((ephemeris_time[1] - ephemeris_time[0]) / ephemeris_time[2]);
212 
213  // Calculate coefficient strides
214  std::size_t strides[11];
215  for (int i = 0; i < 11; ++i)
216  {
217  strides[i] = coeff_table[i][2] * coeff_table[i][1] * 3;
218  }
219 
220  // Resize ephemeris to accommodate items 0-10
221  ephemeris.trajectories.resize(11);
222 
223  // Init trajectories
224  for (int i = 0; i < 11; ++i)
225  {
226  auto& trajectory = ephemeris.trajectories[i];
227  trajectory.t0 = ephemeris_time[0];
228  trajectory.t1 = ephemeris_time[1];
229  trajectory.dt = ephemeris_time[2] / static_cast<double>(coeff_table[i][2]);
230  trajectory.n = coeff_table[i][1];
231  trajectory.a.resize(record_count * strides[i]);
232  }
233 
234  // Read coefficients
235  for (std::size_t i = 0; i < record_count; ++i)
236  {
237  // Seek to coefficient record
238  ctx.seek((i + 2) * record_size + 2 * sizeof(double));
239 
240  for (int j = 0; j < 11; ++j)
241  {
242  std::invoke(read64, ctx, reinterpret_cast<std::byte*>(&ephemeris.trajectories[j].a[i * strides[j]]), strides[j]);
243  }
244  }
245 }
246 
247 template <>
248 std::unique_ptr<physics::orbit::ephemeris<double>> resource_loader<physics::orbit::ephemeris<double>>::load(::resource_manager& resource_manager, deserialize_context& ctx)
249 {
250  auto resource = std::make_unique<physics::orbit::ephemeris<double>>();
251 
252  deserializer<physics::orbit::ephemeris<double>>().deserialize(*resource, ctx);
253 
254  return resource;
255 }
Templated resource loader.
Manages the loading, caching, and saving of resources.
@ jpl_de_id_saturn
Saturn.
Definition: ephemeris.cpp:81
@ jpl_de_id_earth_nutation
Earth nutation.
Definition: ephemeris.cpp:99
@ jpl_de_id_moon
Moon.
Definition: ephemeris.cpp:93
@ jpl_de_id_luma_angular_velocity
Lunar mantle angular velocity.
Definition: ephemeris.cpp:105
@ jpl_de_id_mercury
Mercury.
Definition: ephemeris.cpp:66
@ jpl_de_id_sun
Sun.
Definition: ephemeris.cpp:96
@ jpl_de_id_venus
Venus.
Definition: ephemeris.cpp:69
@ jpl_de_id_luma_libration
Lunar mantle libration.
Definition: ephemeris.cpp:102
@ jpl_de_id_mars
Mars.
Definition: ephemeris.cpp:75
@ jpl_de_id_pluto
Pluto.
Definition: ephemeris.cpp:90
@ jpl_de_id_tt_tdb
TT-TDB.
Definition: ephemeris.cpp:108
@ jpl_de_id_neptune
Neptune.
Definition: ephemeris.cpp:87
@ jpl_de_id_embary
Earth-Moon barycenter.
Definition: ephemeris.cpp:72
@ jpl_de_id_uranus
Uranus.
Definition: ephemeris.cpp:84
@ jpl_de_id_jupiter
Jupiter.
Definition: ephemeris.cpp:78
constexpr vector< T, N > max(const vector< T, N > &x, const vector< T, N > &y)
Returns a vector containing the maximum elements of two vectors.
Definition: vector.hpp:1328
Provides access to a deserialization state.
virtual void seek(std::size_t offset)=0
Seeks to a position in the file.
virtual std::size_t read8(std::byte *data, std::size_t count) noexcept(false)=0
Reads 8-bit (byte) data.
Specializations of deserializer define the deserialization process for a given type.
Table of orbital trajectories.
Definition: ephemeris.hpp:36
std::vector< trajectory< T > > trajectories
Table of orbital trajectories.
Definition: ephemeris.hpp:38