33#include < optional>
44#include < vector>
55
6+ #include " astronomy/time_scales.hpp"
67#include " base/status_utilities.hpp" // 🧙 For CHECK_OK.
78#include " benchmark/benchmark.h"
89#include " geometry/barycentre_calculator.hpp"
910#include " geometry/frame.hpp"
1011#include " geometry/instant.hpp"
1112#include " geometry/space.hpp"
1213#include " glog/logging.h"
14+ #include " integrators/methods.hpp"
15+ #include " integrators/symmetric_linear_multistep_integrator.hpp"
1316#include " ksp_plugin/frames.hpp"
1417#include " physics/degrees_of_freedom.hpp"
1518#include " physics/discrete_trajectory.hpp"
19+ #include " physics/discrete_trajectory_segment.hpp"
1620#include " physics/discrete_trajectory_types.hpp"
21+ #include " physics/ephemeris.hpp"
22+ #include " physics/kepler_orbit.hpp"
23+ #include " physics/massless_body.hpp"
24+ #include " physics/solar_system.hpp"
1725#include " quantities/quantities.hpp"
1826#include " quantities/si.hpp"
1927#include " testing_utilities/discrete_trajectory_factories.hpp"
28+ #include " testing_utilities/solar_system_factory.hpp"
2029
2130namespace principia {
2231namespace physics {
2332
33+ using namespace principia ::astronomy::_time_scales;
2434using namespace principia ::geometry::_barycentre_calculator;
2535using namespace principia ::geometry::_frame;
2636using namespace principia ::geometry::_instant;
2737using namespace principia ::geometry::_space;
38+ using namespace principia ::integrators::_methods;
39+ using namespace principia ::integrators::_symmetric_linear_multistep_integrator;
2840using namespace principia ::ksp_plugin::_frames;
2941using namespace principia ::physics::_degrees_of_freedom;
3042using namespace principia ::physics::_discrete_trajectory;
43+ using namespace principia ::physics::_discrete_trajectory_segment;
3144using namespace principia ::physics::_discrete_trajectory_types;
45+ using namespace principia ::physics::_ephemeris;
46+ using namespace principia ::physics::_kepler_orbit;
47+ using namespace principia ::physics::_massless_body;
48+ using namespace principia ::physics::_solar_system;
3249using namespace principia ::quantities::_quantities;
3350using namespace principia ::quantities::_si;
3451using namespace principia ::testing_utilities::_discrete_trajectory_factories;
52+ using namespace principia ::testing_utilities::_solar_system_factory;
3553
3654namespace {
3755
56+ Ephemeris<Barycentric>::FixedStepParameters EphemerisParameters () {
57+ return Ephemeris<Barycentric>::FixedStepParameters (
58+ SymmetricLinearMultistepIntegrator<
59+ QuinlanTremaine1990Order12,
60+ Ephemeris<Barycentric>::NewtonianMotionEquation>(),
61+ /* step=*/ 10 * Minute);
62+ }
63+
64+ Ephemeris<Barycentric>::FixedStepParameters HistoryParameters () {
65+ return Ephemeris<Barycentric>::FixedStepParameters (
66+ SymmetricLinearMultistepIntegrator<
67+ Quinlan1999Order8A,
68+ Ephemeris<Barycentric>::NewtonianMotionEquation>(),
69+ /* step=*/ 10 * Second);
70+ }
71+
3872// Constructs a trajectory by assigning the points in `timeline` to segments
3973// defined by `splits`, which must be doubles in [0, 1].
4074DiscreteTrajectory<World> MakeTrajectory (Timeline<World> const & timeline,
@@ -396,6 +430,69 @@ void BM_DiscreteTrajectoryEvaluateDegreesOfFreedomInterpolated(
396430 }
397431}
398432
433+ void BM_DiscreteTrajectoryDownsampling (benchmark::State& state) {
434+ static DiscreteTrajectory<Barycentric> const * const goes_8_trajectory = []() {
435+ SolarSystem<Barycentric> const solar_system (
436+ SOLUTION_DIR / " astronomy" / " sol_gravity_model.proto.txt" ,
437+ SOLUTION_DIR / " astronomy" /
438+ " sol_initial_state_jd_2451545_000000000.proto.txt" ,
439+ /* ignore_frame=*/ true );
440+ auto const ephemeris = solar_system.MakeEphemeris (
441+ /* accuracy_parameters=*/ {/* fitting_tolerance=*/ 1 * Milli (Metre),
442+ /* geopotential_tolerance=*/ 0x1p-24 },
443+ EphemerisParameters ());
444+ auto const earth = solar_system.massive_body (
445+ *ephemeris, SolarSystemFactory::name (SolarSystemFactory::Earth));
446+
447+ // Two-line elements for GOES-8:
448+ // 1 23051U 94022A 00004.06628221 -.00000243 00000-0 00000-0 0 9630
449+ // 2 23051 0.4232 97.7420 0004776 192.8349 121.5613 1.00264613 28364
450+ constexpr Instant goes_8_epoch = " JD2451548.56628221" _UT1;
451+ KeplerianElements<Barycentric> goes_8_elements;
452+ goes_8_elements.inclination = 0.4232 * Degree;
453+ goes_8_elements.longitude_of_ascending_node = 97.7420 * Degree;
454+ goes_8_elements.eccentricity = 0.0004776 ;
455+ goes_8_elements.argument_of_periapsis = 192.8349 * Degree;
456+ goes_8_elements.mean_anomaly = 121.5613 * Degree;
457+ goes_8_elements.mean_motion = 1.00264613 * (2 * π * Radian / Day);
458+ CHECK_OK (ephemeris->Prolong (goes_8_epoch));
459+ KeplerOrbit<Barycentric> const goes_8_orbit (
460+ *earth, MasslessBody{}, goes_8_elements, goes_8_epoch);
461+
462+ // First build a realistic trajectory without downsampling.
463+ auto * const goes_8_trajectory = new DiscreteTrajectory<Barycentric>;
464+ CHECK_OK (goes_8_trajectory->Append (
465+ goes_8_epoch,
466+ ephemeris->trajectory (earth)->EvaluateDegreesOfFreedom (goes_8_epoch) +
467+ goes_8_orbit.StateVectors (goes_8_epoch)));
468+ auto goes_8_instance =
469+ ephemeris->NewInstance ({goes_8_trajectory},
470+ Ephemeris<Barycentric>::NoIntrinsicAccelerations,
471+ HistoryParameters ());
472+ CHECK_OK (ephemeris->FlowWithFixedStep (goes_8_epoch + 100 * Day,
473+ *goes_8_instance));
474+
475+ return goes_8_trajectory;
476+ }();
477+
478+ // Now append the same points to a trajectory with downsampling.
479+ DiscreteTrajectory<Barycentric> downsampled_trajectory;
480+ for (auto _ : state) {
481+ downsampled_trajectory.clear ();
482+ downsampled_trajectory.segments ().begin ()->SetDownsampling (
483+ DiscreteTrajectorySegment<Barycentric>::DownsamplingParameters{
484+ .max_dense_intervals = 10'000 , .tolerance = 10 * Metre});
485+ for (auto const & [t, degrees_of_freedom] : *goes_8_trajectory) {
486+ CHECK_OK (downsampled_trajectory.Append (t, degrees_of_freedom));
487+ }
488+ }
489+ state.SetLabel ((std::stringstream ()
490+ << goes_8_trajectory->size ()
491+ << " points before downsampling, "
492+ << downsampled_trajectory.size () << " after" )
493+ .str ());
494+ }
495+
399496BENCHMARK (BM_DiscreteTrajectoryFront);
400497BENCHMARK (BM_DiscreteTrajectoryFrontEmpty);
401498BENCHMARK (BM_DiscreteTrajectoryBack);
@@ -419,6 +516,7 @@ BENCHMARK(BM_DiscreteTrajectoryFind)->Range(8, 1024);
419516BENCHMARK (BM_DiscreteTrajectoryLowerBound)->Range (8 , 1024 );
420517BENCHMARK (BM_DiscreteTrajectoryEvaluateDegreesOfFreedomExact);
421518BENCHMARK (BM_DiscreteTrajectoryEvaluateDegreesOfFreedomInterpolated);
519+ BENCHMARK (BM_DiscreteTrajectoryDownsampling);
422520
423521} // namespace physics
424522} // namespace principia
0 commit comments