Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 21ce442de90f
Choose a base ref
...
head repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 45f6327bea11
Choose a head ref
  • 13 commits
  • 7 files changed
  • 1 contributor

Commits on Aug 20, 2021

  1. Remove prehistory_.

    pleroy committed Aug 20, 2021
    Copy the full SHA
    34ab0e7 View commit details
  2. Add present_.

    pleroy committed Aug 20, 2021
    Copy the full SHA
    9cb8519 View commit details

Commits on Aug 21, 2021

  1. Copy the full SHA
    5858e92 View commit details
  2. A better name.

    pleroy committed Aug 21, 2021
    Copy the full SHA
    8b692ec View commit details
  3. Copy the full SHA
    05398e0 View commit details
  4. Copy the full SHA
    7a5cb27 View commit details
  5. Copy the full SHA
    3f83a86 View commit details

Commits on Aug 22, 2021

  1. Copy the full SHA
    d6c9384 View commit details
  2. Copy the full SHA
    cf089c2 View commit details
  3. Copy the full SHA
    559f341 View commit details
  4. Cleanup.

    pleroy committed Aug 22, 2021
    Copy the full SHA
    ed64dfc View commit details
  5. More cleanup.

    pleroy committed Aug 22, 2021
    Copy the full SHA
    7e5e1af View commit details
  6. Merge pull request #3110 from pleroy/Prehistory

    The prehistory is dead, long live the backstory
    pleroy authored Aug 22, 2021
    Copy the full SHA
    45f6327 View commit details
Showing with 100 additions and 105 deletions.
  1. +1 −1 ksp_plugin/plugin.cpp
  2. +60 −67 ksp_plugin/vessel.cpp
  3. +17 −16 ksp_plugin/vessel.hpp
  4. +8 −10 ksp_plugin_test/plugin_test.cpp
  5. +9 −9 ksp_plugin_test/vessel_test.cpp
  6. +1 −0 physics/checkpointer_body.hpp
  7. +4 −2 serialization/ksp_plugin.proto
2 changes: 1 addition & 1 deletion ksp_plugin/plugin.cpp
Original file line number Diff line number Diff line change
@@ -573,7 +573,7 @@ void Plugin::FreeVesselsAndPartsAndCollectPileUps(Time const& Δt) {
Instant const vessel_time =
is_loaded(vessel) ? current_time_ - Δt : current_time_;
if (kept_vessels_.erase(vessel) > 0) {
vessel->CreatePrehistoryIfNeeded(vessel_time);
vessel->CreateHistoryIfNeeded(vessel_time);
++it;
} else {
loaded_vessels_.erase(vessel);
127 changes: 60 additions & 67 deletions ksp_plugin/vessel.cpp
Original file line number Diff line number Diff line change
@@ -74,9 +74,9 @@ Vessel::Vessel(GUID guid,
checkpointer_(make_not_null_unique<Checkpointer<serialization::Vessel>>(
MakeCheckpointerWriter(),
MakeCheckpointerReader())),
prehistory_(make_not_null_unique<DiscreteTrajectory<Barycentric>>()) {
// Can't create the |history_|, |psychohistory_| and |prediction_| here
// because |prehistory_| is empty;
history_(make_not_null_unique<DiscreteTrajectory<Barycentric>>()) {
// Can't create the |psychohistory_| and |prediction_| here because
// |history_| is empty;
}

Vessel::~Vessel() {
@@ -177,21 +177,22 @@ void Vessel::DetectCollapsibilityChange() {
if (!is_collapsible_) {
// If the segment that is being closed is not collapsible, we have no way
// to reconstruct it, so we must serialize it in a checkpoint. Note that
// the last point of the history specifies the initial conditions of the
// the last point of the backstory specifies the initial conditions of the
// next (collapsible) segment.
checkpointer_->WriteToCheckpoint(history_->Fork()->time);
checkpointer_->WriteToCheckpoint(backstory_->back().time);
}
auto psychohistory = psychohistory_->DetachFork();
history_ = history_->NewForkAtLast();
history_->SetDownsampling(MaxDenseIntervals, DownsamplingTolerance);
history_->AttachFork(std::move(psychohistory));
backstory_ = history_->NewForkAtLast();
backstory_->SetDownsampling(MaxDenseIntervals,
DownsamplingTolerance);
backstory_->AttachFork(std::move(psychohistory));
is_collapsible_ = becomes_collapsible;
}
}

void Vessel::CreatePrehistoryIfNeeded(Instant const& t) {
void Vessel::CreateHistoryIfNeeded(Instant const& t) {
CHECK(!parts_.empty());
if (prehistory_->Empty()) {
if (history_->Empty()) {
LOG(INFO) << "Preparing history of vessel " << ShortDebugString()
<< " at " << t;
BarycentreCalculator<DegreesOfFreedom<Barycentric>, Mass> calculator;
@@ -200,11 +201,10 @@ void Vessel::CreatePrehistoryIfNeeded(Instant const& t) {
part.rigid_motion()({RigidPart::origin, RigidPart::unmoving}),
part.mass());
});
prehistory_->Append(t, calculator.Get());
CHECK(history_ == nullptr);
CHECK(psychohistory_ == nullptr);
history_ = prehistory_->NewForkAtLast();
history_->SetDownsampling(MaxDenseIntervals, DownsamplingTolerance);
history_->Append(t, calculator.Get());
backstory_ = history_.get();
psychohistory_ = history_->NewForkAtLast();
prediction_ = psychohistory_->NewForkAtLast();
}
@@ -267,11 +267,11 @@ void Vessel::AdvanceTime() {
// history as well as the psychohistory, if the history of the part was
// obtained using an adaptive step integrator, which is the case during a
// burn. See #2931.
history_->DeleteFork(psychohistory_);
backstory_->DeleteFork(psychohistory_);
AppendToVesselTrajectory(&Part::history_begin,
&Part::history_end,
*history_);
psychohistory_ = history_->NewForkAtLast();
*backstory_);
psychohistory_ = backstory_->NewForkAtLast();

// The reason why we may want to skip the start of the psychohistory is
// subtle. Say that we have a vessel A with points at t₀, t₀ + 10 s,
@@ -459,10 +459,10 @@ void Vessel::WriteToMessage(not_null<serialization::Vessel*> const message,
message->add_kept_parts(part_id);
}
// Starting with Gateaux we don't save the prediction, see #2685.
prehistory_->WriteToMessage(message->mutable_prehistory(),
/*exclude=*/{prediction_},
/*tracked=*/{history_, psychohistory_},
/*exact=*/{});
history_->WriteToMessage(message->mutable_history(),
/*exclude=*/{prediction_},
/*tracked=*/{backstory_, psychohistory_},
/*exact=*/{});
if (flight_plan_ != nullptr) {
flight_plan_->WriteToMessage(message->mutable_flight_plan());
}
@@ -475,15 +475,15 @@ not_null<std::unique_ptr<Vessel>> Vessel::ReadFromMessage(
std::function<void(PartId)> const& deletion_callback) {
bool const is_pre_cesàro = message.has_psychohistory_is_authoritative();
bool const is_pre_chasles = message.has_prediction();
bool const is_pre_陈景润 = message.has_history() &&
!message.history().has_downsampling();
bool const is_pre_陈景润 = !message.history().has_downsampling();
// TODO(phl): Decide in which version it goes.
bool const is_pre_grothendieck_haar = !message.has_prehistory();
bool const is_pre_grothendieck_haar =
!message.history().has_tracked_position();
LOG_IF(WARNING, is_pre_grothendieck_haar)
<< "Reading pre-"
<< (is_pre_cesàro ? u8"Cesàro"
: is_pre_chasles ? "Chasles"
: is_pre_陈景润 ? u8"陈景润"
: is_pre_陈景润 ? u8"陈景润"
: "Grothendieck/Haar")
<< " Vessel";

@@ -515,13 +515,10 @@ not_null<std::unique_ptr<Vessel>> Vessel::ReadFromMessage(
auto const psychohistory =
DiscreteTrajectory<Barycentric>::ReadFromMessage(message.history(),
/*tracked=*/{});
// The |prehistory_| has been created by the constructor above. Reconstruct
// the |history_| from the |psychohistory|.
// The |history_| has been created by the constructor above. Reconstruct
// it from the |psychohistory|.
CHECK(!psychohistory->Empty());
auto it = psychohistory->begin();
vessel->prehistory_->Append(it->time, it->degrees_of_freedom);
vessel->history_ = vessel->prehistory_->NewForkAtLast();
for (++it; it != psychohistory->end();) {
for (auto it = psychohistory->begin(); it != psychohistory->end();) {
auto const& [time, degrees_of_freedom] = *it;
++it;
if (it == psychohistory->end() &&
@@ -535,43 +532,33 @@ not_null<std::unique_ptr<Vessel>> Vessel::ReadFromMessage(
if (message.psychohistory_is_authoritative()) {
vessel->psychohistory_ = vessel->history_->NewForkAtLast();
}
vessel->backstory_ = vessel->psychohistory_->parent();
vessel->prediction_ = vessel->psychohistory_->NewForkAtLast();
} else if (is_pre_chasles) {
auto history = DiscreteTrajectory<Barycentric>::ReadFromMessage(
vessel->history_ = DiscreteTrajectory<Barycentric>::ReadFromMessage(
message.history(),
/*tracked=*/{&vessel->psychohistory_});
vessel->prehistory_->Append(history->begin()->time,
history->begin()->degrees_of_freedom);
vessel->history_ = history.get();
vessel->prehistory_->AttachFork(std::move(history));
vessel->backstory_ = vessel->psychohistory_->parent();
vessel->prediction_ = vessel->psychohistory_->NewForkAtLast();
} else if (is_pre_grothendieck_haar) {
vessel->history_ = DiscreteTrajectory<Barycentric>::ReadFromMessage(
message.history(),
/*tracked=*/{&vessel->psychohistory_,
&vessel->prediction_});
vessel->backstory_ = vessel->psychohistory_->parent();
} else {
if (is_pre_grothendieck_haar) {
// The history is guaranteed to be non-empty because of the way
// CreateHistoryIfNeeded used to work.
auto history = DiscreteTrajectory<Barycentric>::ReadFromMessage(
message.history(),
/*tracked=*/{&vessel->psychohistory_, &vessel->prediction_});
vessel->prehistory_->Append(history->begin()->time,
history->begin()->degrees_of_freedom);
vessel->history_ = history.get();
vessel->prehistory_->AttachFork(std::move(history));
} else {
vessel->prehistory_ = DiscreteTrajectory<Barycentric>::ReadFromMessage(
message.prehistory(),
/*tracked=*/{&vessel->history_,
&vessel->psychohistory_});
}
// After Grothendieck/Haar there is no empty prediction so we must create
// one here.
if (vessel->prediction_ == nullptr) {
vessel->prediction_ = vessel->psychohistory_->NewForkAtLast();
}
// Necessary after Εὔδοξος because the ephemeris has not been prolonged
// during deserialization. Doesn't hurt prior to Εὔδοξος.
ephemeris->Prolong(vessel->prediction_->back().time);
vessel->history_ = DiscreteTrajectory<Barycentric>::ReadFromMessage(
message.history(),
/*tracked=*/{&vessel->backstory_,
&vessel->psychohistory_});
vessel->prediction_ = vessel->psychohistory_->NewForkAtLast();
// TODO(phl): Need to restore is_collapsible_ somehow.
}

// Necessary after Εὔδοξος because the ephemeris has not been prolonged
// during deserialization. Doesn't hurt prior to Εὔδοξος.
ephemeris->Prolong(vessel->prediction_->back().time);

if (is_pre_陈景润) {
vessel->history_->SetDownsampling(MaxDenseIntervals,
DownsamplingTolerance);
@@ -597,13 +584,19 @@ void Vessel::FillContainingPileUpsFromMessage(

Checkpointer<serialization::Vessel>::Writer Vessel::MakeCheckpointerWriter() {
return [this](not_null<serialization::Vessel::Checkpoint*> const message) {
auto const penultimate_history_segment = history_->parent();
auto last_history_segment = history_->DetachFork();
last_history_segment->WriteToMessage(message->mutable_segment(),
/*excluded=*/{psychohistory_},
/*tracked=*/{},
/*exact=*/{psychohistory_->Fork()});
penultimate_history_segment->AttachFork(std::move(last_history_segment));
if (backstory_ == history_.get()) {
history_->WriteToMessage(message->mutable_segment(),
/*excluded=*/{psychohistory_},
/*tracked=*/{},
/*exact=*/{psychohistory_->Fork()});
} else {
auto backstory = backstory_->DetachFork();
backstory->WriteToMessage(message->mutable_segment(),
/*excluded=*/{psychohistory_},
/*tracked=*/{},
/*exact=*/{psychohistory_->Fork()});
history_->AttachFork(std::move(backstory));
}
};
}

@@ -629,7 +622,7 @@ Vessel::Vessel()
checkpointer_(make_not_null_unique<Checkpointer<serialization::Vessel>>(
/*reader=*/nullptr,
/*writer=*/nullptr)),
prehistory_(make_not_null_unique<DiscreteTrajectory<Barycentric>>()),
history_(make_not_null_unique<DiscreteTrajectory<Barycentric>>()),
prognosticator_(nullptr, 20ms) {}

absl::StatusOr<std::unique_ptr<DiscreteTrajectory<Barycentric>>>
33 changes: 17 additions & 16 deletions ksp_plugin/vessel.hpp
Original file line number Diff line number Diff line change
@@ -106,11 +106,11 @@ class Vessel {
// if needed. Must be called after the pile-ups have been collected.
virtual void DetectCollapsibilityChange();

// If the prehistory is empty, appends a single point to it, computed as the
// If the history is empty, appends a single point to it, computed as the
// barycentre of all parts. |parts_| must not be empty. After this call,
// |prehistory_| is never empty again and the history and psychohistory are
// usable. Must be called (at least) at the creation of the vessel.
virtual void CreatePrehistoryIfNeeded(Instant const& t);
// |history_| is never empty again and the psychohistory is usable. Must be
// called (at least) after the creation of the vessel.
virtual void CreateHistoryIfNeeded(Instant const& t);

// Disables downsampling for the history of this vessel. This is useful when
// the vessel collided with a celestial, as downsampling might run into
@@ -272,9 +272,8 @@ class Vessel {
not_null<Celestial const*> parent_;
not_null<Ephemeris<Barycentric>*> const ephemeris_;

// When reading a pre-Grothendieck/Haar save, the existing history becomes the
// first (and only) segment of the |history_|. It must be non-collapsible as
// we don't know anything about it.
// When reading a pre-Grothendieck/Haar save, the existing history must be
// non-collapsible as we don't know anything about it.
bool is_collapsible_ = false;

std::map<PartId, not_null<std::unique_ptr<Part>>> parts_;
@@ -284,16 +283,18 @@ class Vessel {

// See the comments in pile_up.hpp for an explanation of the terminology.

// The |prehistory_| contains exactly one point, added by
// CreatePrehistoryIfNeeded.
not_null<std::unique_ptr<DiscreteTrajectory<Barycentric>>> prehistory_;
// The |history_| is empty until the first call to CreateHistoryIfNeeded.
// It is made of a series of forks, alternatively non-collapsible and
// collapsible.
not_null<std::unique_ptr<DiscreteTrajectory<Barycentric>>> history_;

// The |history_| is forked off the end of the |prehistory_|, the
// |psychohistory_| is forked off the end of the |history_| and the
// |prediction_| is forked off the end of the |psychohistory_|. The
// |history_| contains a number of segments which alternate it terms of the
// collapsibility of the vessel.
DiscreteTrajectory<Barycentric>* history_ = nullptr;
// The last (most recent) segment of the |history_| prior to the
// |psychohistory_|. May be identical to |history_|, therefore not always a
// fork. Always identical to |psychohistory_->parent()|.
DiscreteTrajectory<Barycentric>* backstory_ = nullptr;

// The |psychohistory_| is forked off the end of the |history_| and the
// |prediction_| is forked off the end of the |psychohistory_|.
DiscreteTrajectory<Barycentric>* psychohistory_ = nullptr;
DiscreteTrajectory<Barycentric>* prediction_ = nullptr;

18 changes: 8 additions & 10 deletions ksp_plugin_test/plugin_test.cpp
Original file line number Diff line number Diff line change
@@ -435,17 +435,15 @@ TEST_F(PluginTest, Serialization) {
EXPECT_EQ(1, message.vessel_size());
EXPECT_EQ(SolarSystemFactory::Earth, message.vessel(0).parent_index());
EXPECT_TRUE(message.vessel(0).vessel().has_flight_plan());
EXPECT_TRUE(message.vessel(0).vessel().has_prehistory());
auto const& vessel_0_prehistory = message.vessel(0).vessel().prehistory();
EXPECT_EQ(1, vessel_0_prehistory.zfp().timeline_size());
auto const& vessel_0_history_a =
vessel_0_prehistory.children(0).trajectories(0);
EXPECT_EQ(0, vessel_0_history_a.zfp().timeline_size());
auto const& vessel_0_history_b =
vessel_0_history_a.children(0).trajectories(0);
EXPECT_EQ(6, vessel_0_history_b.zfp().timeline_size());

EXPECT_TRUE(message.vessel(0).vessel().has_history());
auto const& vessel_0_history = message.vessel(0).vessel().history();
EXPECT_EQ(1, vessel_0_history.zfp().timeline_size());
auto const& vessel_0_backstory =
vessel_0_history.children(0).trajectories(0);
EXPECT_EQ(6, vessel_0_backstory.zfp().timeline_size());
auto const& vessel_0_psychohistory =
vessel_0_history_b.children(0).trajectories(0);
vessel_0_backstory.children(0).trajectories(0);
EXPECT_EQ(1, vessel_0_psychohistory.zfp().timeline_size());
EXPECT_EQ(0, vessel_0_psychohistory.children_size());

18 changes: 9 additions & 9 deletions ksp_plugin_test/vessel_test.cpp
Original file line number Diff line number Diff line change
@@ -178,7 +178,7 @@ TEST_F(VesselTest, PrepareHistory) {
ephemeris_,
FlowWithAdaptiveStep(_, _, astronomy::J2000 + 2 * Second, _, _))
.Times(AnyNumber());
vessel_.CreatePrehistoryIfNeeded(astronomy::J2000 + 1 * Second);
vessel_.CreateHistoryIfNeeded(astronomy::J2000 + 1 * Second);

EXPECT_EQ(1, vessel_.psychohistory().Size());
EXPECT_EQ(astronomy::J2000 + 1 * Second,
@@ -207,7 +207,7 @@ TEST_F(VesselTest, AdvanceTime) {
ephemeris_,
FlowWithAdaptiveStep(_, _, astronomy::J2000 + 2 * Second, _, _))
.Times(AnyNumber());
vessel_.CreatePrehistoryIfNeeded(astronomy::J2000);
vessel_.CreateHistoryIfNeeded(astronomy::J2000);

p1_->AppendToHistory(
astronomy::J2000 + 0.5 * Second,
@@ -308,7 +308,7 @@ TEST_F(VesselTest, Prediction) {
Return(absl::OkStatus())))
.WillRepeatedly(Return(absl::OkStatus()));

vessel_.CreatePrehistoryIfNeeded(astronomy::J2000);
vessel_.CreateHistoryIfNeeded(astronomy::J2000);
// Polling for the integration to happen.
do {
vessel_.RefreshPrediction(astronomy::J2000 + 1 * Second);
@@ -380,7 +380,7 @@ TEST_F(VesselTest, PredictBeyondTheInfinite) {
60.0 * Metre / Second,
50.0 * Metre / Second}))),
Return(absl::OkStatus())));
vessel_.CreatePrehistoryIfNeeded(astronomy::J2000);
vessel_.CreateHistoryIfNeeded(astronomy::J2000);
// Polling for the integration to happen.
do {
vessel_.RefreshPrediction();
@@ -419,7 +419,7 @@ TEST_F(VesselTest, FlightPlan) {
.Times(AnyNumber());
std::vector<not_null<MassiveBody const*>> const bodies;
ON_CALL(ephemeris_, bodies()).WillByDefault(ReturnRef(bodies));
vessel_.CreatePrehistoryIfNeeded(astronomy::J2000);
vessel_.CreateHistoryIfNeeded(astronomy::J2000);

EXPECT_FALSE(vessel_.has_flight_plan());
EXPECT_CALL(
@@ -504,7 +504,7 @@ TEST_F(VesselTest, Checkpointing) {
ephemeris_,
FlowWithAdaptiveStep(_, _, astronomy::J2000 + 30 * Second, _, _))
.Times(AnyNumber());
vessel_.CreatePrehistoryIfNeeded(astronomy::J2000);
vessel_.CreateHistoryIfNeeded(astronomy::J2000);

auto const pile_up =
std::make_shared<PileUp>(/*parts=*/std::list<not_null<Part*>>{p1_, p2_},
@@ -614,7 +614,7 @@ TEST_F(VesselTest, Checkpointing) {
CHECK_EQ(0, message.checkpoint(0).time().scalar().magnitude());
CHECK_EQ(0, message.checkpoint(0).segment().children_size());
CHECK_EQ(1, message.checkpoint(0).segment().zfp().timeline_size());
CHECK_EQ(10, message.checkpoint(1).time().scalar().magnitude());
CHECK_EQ(25, message.checkpoint(1).time().scalar().magnitude());
CHECK_EQ(0, message.checkpoint(1).segment().children_size());
CHECK_EQ(16, message.checkpoint(1).segment().zfp().timeline_size());
}
@@ -634,7 +634,7 @@ TEST_F(VesselTest, SerializationSuccess) {
ephemeris_,
FlowWithAdaptiveStep(_, _, astronomy::J2000 + 2 * Second, _, _))
.Times(AnyNumber());
vessel_.CreatePrehistoryIfNeeded(astronomy::J2000);
vessel_.CreateHistoryIfNeeded(astronomy::J2000);

EXPECT_CALL(
ephemeris_,
@@ -652,7 +652,7 @@ TEST_F(VesselTest, SerializationSuccess) {
serialization::Vessel message;
vessel_.WriteToMessage(&message,
serialization_index_for_pile_up.AsStdFunction());
EXPECT_TRUE(message.has_prehistory());
EXPECT_TRUE(message.has_history());
EXPECT_TRUE(message.has_flight_plan());

EXPECT_CALL(ephemeris_, Prolong(_)).Times(2);
Loading