Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert PileUp and its test to DiscreteTraject0ry #3175

Merged
merged 20 commits into from
Oct 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 88 additions & 51 deletions ksp_plugin/pile_up.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ PileUp::PileUp(
ephemeris_(ephemeris),
adaptive_step_parameters_(std::move(adaptive_step_parameters)),
fixed_step_parameters_(std::move(fixed_step_parameters)),
history_(make_not_null_unique<DiscreteTrajectory<Barycentric>>()),
history_(trajectory_.segments().begin()),
deletion_callback_(std::move(deletion_callback)) {
LOG(INFO) << "Constructing pile up at " << this;
MechanicalSystem<Barycentric, NonRotatingPileUp> mechanical_system;
Expand All @@ -85,7 +85,7 @@ PileUp::PileUp(
part->rigid_motion(), part->mass(), part->inertia_tensor());
}
auto const barycentre = mechanical_system.centre_of_mass();
history_->Append(t, barycentre);
trajectory_.Append(t, barycentre);

angular_momentum_ = mechanical_system.AngularMomentum();

Expand All @@ -97,7 +97,7 @@ PileUp::PileUp(
}
MakeEulerSolver(mechanical_system.InertiaTensor(), t);

psychohistory_ = history_->NewForkAtLast();
psychohistory_ = trajectory_.NewSegment();

RecomputeFromParts();
}
Expand Down Expand Up @@ -176,9 +176,9 @@ void PileUp::WriteToMessage(not_null<serialization::PileUp*> message) const {
for (not_null<Part*> const part : parts_) {
message->add_part_id(part->part_id());
}
history_->WriteToMessage(message->mutable_history(),
/*forks=*/{psychohistory_},
/*exact=*/{});
trajectory_.WriteToMessage(message->mutable_history(),
/*forks=*/{history_, psychohistory_},
/*exact=*/{});
for (auto const& [part, rigid_motion] : actual_part_rigid_motion_) {
rigid_motion.WriteToMessage(&(
(*message->mutable_actual_part_rigid_motion())[part->part_id()]));
Expand Down Expand Up @@ -213,17 +213,20 @@ not_null<std::unique_ptr<PileUp>> PileUp::ReadFromMessage(

bool const is_pre_cartan = !message.has_adaptive_step_parameters() ||
!message.has_fixed_step_parameters();
bool const is_pre_cesàro = message.history().children().empty();
bool const is_pre_cesàro = message.history().children().empty() &&
message.history().segment_size() == 0;
bool const is_pre_frege = message.actual_part_degrees_of_freedom_size() > 0 ||
message.apparent_part_degrees_of_freedom_size() > 0;
bool const is_pre_frobenius = message.rigid_pile_up().empty() ||
!message.has_angular_momentum();
bool const is_pre_ζήνων = message.history().segment_size() == 0;
LOG_IF(WARNING, is_pre_frobenius)
<< "Reading pre-"
<< (is_pre_cartan ? "Cartan"
: is_pre_cesàro ? u8"Cesàro"
: is_pre_frege ? "Frege"
: "Frobenius") << " PileUp";
: is_pre_ζήνων ? "Frobenius"
: u8"pre-Ζήνων") << " PileUp";

std::unique_ptr<PileUp> pile_up;
if (is_pre_cesàro) {
Expand All @@ -232,10 +235,11 @@ not_null<std::unique_ptr<PileUp>> PileUp::ReadFromMessage(
new PileUp(std::move(parts),
DefaultPsychohistoryParameters(),
DefaultHistoryParameters(),
DiscreteTrajectory<Barycentric>::ReadFromMessage(
DiscreteTraject0ry<Barycentric>::ReadFromMessage(
message.history(),
/*forks=*/{}),
/*psychohistory=*/nullptr,
/*history=*/std::nullopt,
/*psychohistory=*/std::nullopt,
/*angular_momentum=*/{},
ephemeris,
std::move(deletion_callback)));
Expand All @@ -247,52 +251,81 @@ not_null<std::unique_ptr<PileUp>> PileUp::ReadFromMessage(
message.adaptive_step_parameters()),
Ephemeris<Barycentric>::FixedStepParameters::ReadFromMessage(
message.fixed_step_parameters()),
DiscreteTrajectory<Barycentric>::ReadFromMessage(
DiscreteTraject0ry<Barycentric>::ReadFromMessage(
message.history(),
/*forks=*/{}),
/*psychohistory=*/nullptr,
/*history=*/std::nullopt,
/*psychohistory=*/std::nullopt,
/*angular_momentum=*/{},
ephemeris,
std::move(deletion_callback)));
}
// Fork a psychohistory for compatibility if there is a non-authoritative
// point.
if (pile_up->history_->Size() == 2) {
Instant const history_begin_time = pile_up->history_->front().time;
if (pile_up->history_->size() == 2) {
DiscreteTraject0ry<Barycentric> psychohistory;
for (auto const [time, degrees_of_freedom] : *pile_up->history_) {
psychohistory.Append(time, degrees_of_freedom);
}
pile_up->trajectory_.ForgetAfter(std::next(pile_up->history_->begin()));
pile_up->psychohistory_ =
pile_up->history_->NewForkWithCopy(history_begin_time);
pile_up->history_->ForgetAfter(history_begin_time);
pile_up->trajectory_.AttachSegments(std::move(psychohistory));
} else {
pile_up->psychohistory_ = pile_up->history_->NewForkAtLast();
pile_up->psychohistory_ = pile_up->trajectory_.NewSegment();
}
} else {
DiscreteTrajectory<Barycentric>* psychohistory = nullptr;
not_null<std::unique_ptr<DiscreteTrajectory<Barycentric>>> history =
DiscreteTrajectory<Barycentric>::ReadFromMessage(
message.history(),
/*forks=*/{&psychohistory});
if (is_pre_frobenius) {
DiscreteTrajectorySegmentIterator<Barycentric> psychohistory;
auto trajectory = DiscreteTraject0ry<Barycentric>::ReadFromMessage(
message.history(),
/*forks=*/{&psychohistory});
pile_up = std::unique_ptr<PileUp>(
new PileUp(
std::move(parts),
Ephemeris<Barycentric>::AdaptiveStepParameters::ReadFromMessage(
message.adaptive_step_parameters()),
Ephemeris<Barycentric>::FixedStepParameters::ReadFromMessage(
message.fixed_step_parameters()),
std::move(history),
std::move(trajectory),
/*history=*/std::nullopt,
psychohistory,
/*angular_momentum=*/{},
ephemeris,
std::move(deletion_callback)));
} else if (is_pre_ζήνων) {
DiscreteTrajectorySegmentIterator<Barycentric> psychohistory;
auto trajectory = DiscreteTraject0ry<Barycentric>::ReadFromMessage(
message.history(),
/*forks=*/{&psychohistory});
pile_up = std::unique_ptr<PileUp>(
new PileUp(
std::move(parts),
Ephemeris<Barycentric>::AdaptiveStepParameters::ReadFromMessage(
message.adaptive_step_parameters()),
Ephemeris<Barycentric>::FixedStepParameters::ReadFromMessage(
message.fixed_step_parameters()),
std::move(trajectory),
/*history=*/std::nullopt,
psychohistory,
Bivector<AngularMomentum, NonRotatingPileUp>::ReadFromMessage(
message.angular_momentum()),
ephemeris,
std::move(deletion_callback)));
} else {
DiscreteTrajectorySegmentIterator<Barycentric> history;
DiscreteTrajectorySegmentIterator<Barycentric> psychohistory;
auto trajectory = DiscreteTraject0ry<Barycentric>::ReadFromMessage(
message.history(),
/*forks=*/{&history, &psychohistory});
pile_up = std::unique_ptr<PileUp>(
new PileUp(
std::move(parts),
Ephemeris<Barycentric>::AdaptiveStepParameters::ReadFromMessage(
message.adaptive_step_parameters()),
Ephemeris<Barycentric>::FixedStepParameters::ReadFromMessage(
message.fixed_step_parameters()),
std::move(history),
std::move(trajectory),
history,
psychohistory,
Bivector<AngularMomentum, NonRotatingPileUp>::ReadFromMessage(
message.angular_momentum()),
Expand Down Expand Up @@ -364,8 +397,9 @@ PileUp::PileUp(
std::list<not_null<Part*>>&& parts,
Ephemeris<Barycentric>::AdaptiveStepParameters adaptive_step_parameters,
Ephemeris<Barycentric>::FixedStepParameters fixed_step_parameters,
not_null<std::unique_ptr<DiscreteTrajectory<Barycentric>>> history,
DiscreteTrajectory<Barycentric>* const psychohistory,
DiscreteTraject0ry<Barycentric> trajectory,
std::optional<DiscreteTrajectorySegmentIterator<Barycentric>> history,
std::optional<DiscreteTrajectorySegmentIterator<Barycentric>> psychohistory,
Bivector<AngularMomentum, NonRotatingPileUp> const& angular_momentum,
not_null<Ephemeris<Barycentric>*> const ephemeris,
std::function<void()> deletion_callback)
Expand All @@ -374,10 +408,18 @@ PileUp::PileUp(
ephemeris_(ephemeris),
adaptive_step_parameters_(std::move(adaptive_step_parameters)),
fixed_step_parameters_(std::move(fixed_step_parameters)),
history_(std::move(history)),
psychohistory_(psychohistory),
trajectory_(std::move(trajectory)),
angular_momentum_(angular_momentum),
deletion_callback_(std::move(deletion_callback)) {}
deletion_callback_(std::move(deletion_callback)) {
if (history.has_value()) {
history_ = history.value();
} else {
history_ = trajectory_.segments().begin();
}
if (psychohistory.has_value()) {
psychohistory_ = psychohistory.value();
}
}

void PileUp::MakeEulerSolver(
InertiaTensor<NonRotatingPileUp> const& inertia_tensor,
Expand Down Expand Up @@ -540,28 +582,26 @@ void PileUp::DeformPileUpIfNeeded(Instant const& t) {
}

absl::Status PileUp::AdvanceTime(Instant const& t) {
CHECK_NOTNULL(psychohistory_);

absl::Status status;
auto const history_last = --history_->end();
Instant const history_last = history_->back().time;
if (intrinsic_force_ == Vector<Force, Barycentric>{}) {
// Remove the fork.
history_->DeleteFork(psychohistory_);
trajectory_.DeleteSegments(psychohistory_);
if (fixed_instance_ == nullptr) {
fixed_instance_ = ephemeris_->NewInstance(
{history_.get()},
{&trajectory_},
Ephemeris<Barycentric>::NoIntrinsicAccelerations,
fixed_step_parameters_);
}
CHECK_LT(history_->back().time, t);
status = ephemeris_->FlowWithFixedStep(t, *fixed_instance_);
psychohistory_ = history_->NewForkAtLast();
psychohistory_ = trajectory_.NewSegment();
if (history_->back().time < t) {
// Do not clear the |fixed_instance_| here, we will use it for the next
// fixed-step integration.
status.Update(
ephemeris_->FlowWithAdaptiveStep(
psychohistory_,
&trajectory_,
Ephemeris<Barycentric>::NoIntrinsicAcceleration,
t,
adaptive_step_parameters_,
Expand All @@ -574,40 +614,37 @@ absl::Status PileUp::AdvanceTime(Instant const& t) {
// We make the |psychohistory_|, if any, authoritative, i.e. append it to
// the end of the |history_|. We integrate on top of it, and it gets
// appended authoritatively to the part tails.
auto const psychohistory_end = psychohistory_->end();
auto it = psychohistory_->Fork();
for (++it; it != psychohistory_end; ++it) {
history_->Append(it->time, it->degrees_of_freedom);
auto const psychohistory_trajectory =
trajectory_.DetachSegments(psychohistory_);
for (auto const& [time, degrees_of_freedom] : psychohistory_trajectory) {
trajectory_.Append(time, degrees_of_freedom);
}
history_->DeleteFork(psychohistory_);

auto const intrinsic_acceleration =
[a = intrinsic_force_ / mass_](Instant const& t) { return a; };
status = ephemeris_->FlowWithAdaptiveStep(
history_.get(),
&trajectory_,
intrinsic_acceleration,
t,
adaptive_step_parameters_,
Ephemeris<Barycentric>::unlimited_max_ephemeris_steps);
psychohistory_ = history_->NewForkAtLast();
psychohistory_ = trajectory_.NewSegment();
}

CHECK_NOTNULL(psychohistory_);

// Append the |history_| to the parts' history and the |psychohistory_| to the
// parts' psychohistory. Drop the history of the pile-up, we won't need it
// anymore.
auto const history_end = history_->end();
auto const psychohistory_end = psychohistory_->end();
auto it = history_last;
for (++it; it != history_end; ++it) {
for (auto it = trajectory_.upper_bound(history_last);
it != history_end;
++it) {
AppendToPart<&Part::AppendToHistory>(it);
}
it = psychohistory_->Fork();
for (++it; it != psychohistory_end; ++it) {
for (auto it = history_end; it != psychohistory_end; ++it) {
AppendToPart<&Part::AppendToPsychohistory>(it);
}
history_->ForgetBefore(psychohistory_->Fork()->time);
trajectory_.ForgetBefore(psychohistory_->front().time);

return status;
}
Expand All @@ -631,7 +668,7 @@ void PileUp::NudgeParts() const {
}

template<PileUp::AppendToPartTrajectory append_to_part_trajectory>
void PileUp::AppendToPart(DiscreteTrajectory<Barycentric>::Iterator it) const {
void PileUp::AppendToPart(DiscreteTraject0ry<Barycentric>::iterator it) const {
auto const& pile_up_dof = it->degrees_of_freedom;
RigidMotion<Barycentric, NonRotatingPileUp> const barycentric_to_pile_up(
RigidTransformation<Barycentric, NonRotatingPileUp>(
Expand Down
25 changes: 17 additions & 8 deletions ksp_plugin/pile_up.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
#include "geometry/grassmann.hpp"
#include "geometry/named_quantities.hpp"
#include "integrators/integrators.hpp"
#include "physics/discrete_trajectory.hpp"
#include "physics/discrete_traject0ry.hpp"
#include "physics/discrete_trajectory_segment_iterator.hpp"
#include "physics/ephemeris.hpp"
#include "physics/euler_solver.hpp"
#include "physics/massless_body.hpp"
Expand Down Expand Up @@ -45,7 +46,8 @@ using geometry::NonRotating;
using geometry::RigidTransformation;
using geometry::Vector;
using integrators::Integrator;
using physics::DiscreteTrajectory;
using physics::DiscreteTraject0ry;
using physics::DiscreteTrajectorySegmentIterator;
using physics::DegreesOfFreedom;
using physics::Ephemeris;
using physics::EulerSolver;
Expand Down Expand Up @@ -144,13 +146,16 @@ class PileUp {
using AppendToPartTrajectory =
void (Part::*)(Instant const&, DegreesOfFreedom<Barycentric> const&);

// For deserialization.
// For deserialization. The iterators are optional for compatibility with
// old saves.
PileUp(
std::list<not_null<Part*>>&& parts,
Ephemeris<Barycentric>::AdaptiveStepParameters adaptive_step_parameters,
Ephemeris<Barycentric>::FixedStepParameters fixed_step_parameters,
not_null<std::unique_ptr<DiscreteTrajectory<Barycentric>>> history,
DiscreteTrajectory<Barycentric>* psychohistory,
DiscreteTraject0ry<Barycentric> trajectory,
std::optional<DiscreteTrajectorySegmentIterator<Barycentric>> history,
std::optional<DiscreteTrajectorySegmentIterator<Barycentric>>
psychohistory,
Bivector<AngularMomentum, NonRotatingPileUp> const& angular_momentum,
not_null<Ephemeris<Barycentric>*> ephemeris,
std::function<void()> deletion_callback);
Expand Down Expand Up @@ -180,7 +185,7 @@ class PileUp {
void NudgeParts() const;

template<AppendToPartTrajectory append_to_part_trajectory>
void AppendToPart(DiscreteTrajectory<Barycentric>::Iterator it) const;
void AppendToPart(DiscreteTraject0ry<Barycentric>::iterator it) const;

// Wrapped in a |unique_ptr| to be moveable.
not_null<std::unique_ptr<absl::Mutex>> lock_;
Expand All @@ -200,11 +205,15 @@ class PileUp {
// angular velocity of a part remains constant.
Bivector<AngularMomentum, NonRotatingPileUp> angular_momentum_change_;

// The trajectory of the pile-up, composed of (at most) two segments, the
// history and the psychohistory.
DiscreteTraject0ry<Barycentric> trajectory_;

// The |history_| is the past trajectory of the pile-up. It is normally
// integrated with a fixed step using |fixed_instance_|, except in the
// presence of intrinsic acceleration. It is authoritative in the sense that
// it is never going to change.
not_null<std::unique_ptr<DiscreteTrajectory<Barycentric>>> history_;
DiscreteTrajectorySegmentIterator<Barycentric> history_;

// The |psychohistory_| is the recent past trajectory of the pile-up. Since
// we need to draw something between the last point of the |history_| and the
Expand All @@ -214,7 +223,7 @@ class PileUp {
// match the |history_| that we'll ultimately compute. The name comes from
// the fact that we are trying to predict the future, but since we are not as
// good as Hari Seldon we only do it over a short period of time.
DiscreteTrajectory<Barycentric>* psychohistory_ = nullptr;
DiscreteTrajectorySegmentIterator<Barycentric> psychohistory_;

// The angular momentum of the pile up with respect to its centre of mass.
Bivector<AngularMomentum, NonRotatingPileUp> angular_momentum_;
Expand Down
Loading