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: ab556f7571cc
Choose a base ref
...
head repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: f4413fb805c2
Choose a head ref
  • 7 commits
  • 4 files changed
  • 1 contributor

Commits on Mar 8, 2019

  1. Make the Ephemeris fully thread-safe, and take advantage of the fact …

    …that ContinuousTrajectory is now thread-safe. Improve error reporting.
    pleroy committed Mar 8, 2019
    Copy the full SHA
    43908d1 View commit details
  2. Lint.

    pleroy committed Mar 8, 2019
    Copy the full SHA
    100675f View commit details

Commits on Mar 9, 2019

  1. Copy the full SHA
    ad632b0 View commit details
  2. Copy the full SHA
    4c26d6d View commit details

Commits on Mar 10, 2019

  1. Copy the full SHA
    7fd860e View commit details
  2. After egg's review.

    pleroy committed Mar 10, 2019
    Copy the full SHA
    a81d39f View commit details
  3. Merge pull request #2088 from pleroy/ThreadSafeEphemeris

    Make the Ephemeris fully thread-safe and improve error reporting
    pleroy authored Mar 10, 2019
    Copy the full SHA
    f4413fb View commit details
Showing with 120 additions and 80 deletions.
  1. +10 −1 base/status.cpp
  2. +6 −0 base/status.hpp
  3. +32 −29 physics/ephemeris.hpp
  4. +72 −50 physics/ephemeris_body.hpp
11 changes: 10 additions & 1 deletion base/status.cpp
Original file line number Diff line number Diff line change
@@ -46,7 +46,16 @@
namespace principia {
namespace base {

inline std::string ErrorToString(Error const error) {
Error operator|(Error const left, Error const right) {
return left == Error::OK ? right : left;
}

Error& operator|=(Error& left, Error const right) {
left = left | right;
return left;
}

std::string ErrorToString(Error const error) {
switch (error) {
case Error::OK:
return "OK";
6 changes: 6 additions & 0 deletions base/status.hpp
Original file line number Diff line number Diff line change
@@ -40,6 +40,9 @@

#include "glog/logging.h"

// TODO(phl): Many of the functions in this file should be made constexpr.
// Also, we should use string_view.

namespace principia {
namespace base {

@@ -65,6 +68,9 @@ enum class Error {
DATA_LOSS = 15,
};

Error operator|(Error left, Error right);
Error& operator|=(Error& left, Error right);

std::string ErrorToString(Error error);

class Status final {
61 changes: 32 additions & 29 deletions physics/ephemeris.hpp
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ namespace principia {
namespace physics {
namespace internal_ephemeris {

using base::Error;
using base::not_null;
using base::Status;
using geometry::Instant;
@@ -171,20 +172,25 @@ class Ephemeris {
not_null<MassiveBody const*> body) const;

// Returns true if at least one of the trajectories is empty.
virtual bool empty() const EXCLUDES(lock_);
virtual bool empty() const;

// The maximum of the |t_min|s of the trajectories.
virtual Instant t_min() const EXCLUDES(lock_);
// The mimimum of the |t_max|s of the trajectories.
virtual Instant t_max() const EXCLUDES(lock_);
virtual Instant t_max() const;

virtual FixedStepSizeIntegrator<NewtonianMotionEquation> const&
planetary_integrator() const;

virtual Status last_severe_integration_status() const;

// Calls |ForgetBefore| on all trajectories. On return |t_min() == t|.
virtual void ForgetBefore(Instant const& t);
// Calls |ForgetBefore| on all trajectories. On return |t_min() == t|. This
// function is thread-hostile in the sense that it can cause |t_min()| to
// increase, so if it is called is parallel with code that iterates over the
// trajectories of the ephemeris, it can cause trouble.
// TODO(phl): Consider eliminating this function and truncating on
// serialization/deserialization.
virtual void ForgetBefore(Instant const& t) EXCLUDES(lock_);

// Prolongs the ephemeris up to at least |t|. After the call, |t_max() >= t|.
virtual void Prolong(Instant const& t) EXCLUDES(lock_);
@@ -212,7 +218,7 @@ class Ephemeris {
Instant const& t,
AdaptiveStepParameters const& parameters,
std::int64_t max_ephemeris_steps,
bool last_point_only);
bool last_point_only) EXCLUDES(lock_);

// Same as above, but uses a generalized integrator.
virtual Status FlowWithAdaptiveStep(
@@ -221,37 +227,38 @@ class Ephemeris {
Instant const& t,
GeneralizedAdaptiveStepParameters const& parameters,
std::int64_t max_ephemeris_steps,
bool last_point_only);
bool last_point_only) EXCLUDES(lock_);

// Integrates, until at most |t|, the trajectories followed by massless
// bodies in the gravitational potential described by |*this|. If
// |t > t_max()|, calls |Prolong(t)| beforehand. The trajectories and
// integration parameters are given by the |instance|.
virtual Status FlowWithFixedStep(
Instant const& t,
typename Integrator<NewtonianMotionEquation>::Instance& instance);
typename Integrator<NewtonianMotionEquation>::Instance& instance)
EXCLUDES(lock_);

// Returns the gravitational acceleration on a massless body located at the
// given |position| at time |t|.
virtual Vector<Acceleration, Frame>
ComputeGravitationalAccelerationOnMasslessBody(
Position<Frame> const& position,
Instant const& t) const;
Instant const& t) const EXCLUDES(lock_);

// Returns the gravitational acceleration on the massless body having the
// given |trajectory| at time |t|. |t| must be one of the times of the
// |trajectory|.
virtual Vector<Acceleration, Frame>
ComputeGravitationalAccelerationOnMasslessBody(
not_null<DiscreteTrajectory<Frame>*> trajectory,
Instant const& t) const;
Instant const& t) const EXCLUDES(lock_);

// Returns the gravitational acceleration on the massive |body| at time |t|.
// |body| must be one of the bodies of this object.
virtual Vector<Acceleration, Frame>
ComputeGravitationalAccelerationOnMassiveBody(
not_null<MassiveBody const*> body,
Instant const& t) const REQUIRES_SHARED(lock_);
Instant const& t) const EXCLUDES(lock_);

// Computes the apsides of the relative trajectory of |body1| and |body2}.
// Appends to the given trajectories two point for each apsis, one for |body1|
@@ -274,9 +281,9 @@ class Ephemeris {
int serialization_index) const;

virtual void WriteToMessage(
not_null<serialization::Ephemeris*> message) const;
not_null<serialization::Ephemeris*> message) const EXCLUDES(lock_);
static not_null<std::unique_ptr<Ephemeris>> ReadFromMessage(
serialization::Ephemeris const& message);
serialization::Ephemeris const& message) EXCLUDES(lock_);

protected:
// For mocking purposes, leaves everything uninitialized and uses the given
@@ -302,9 +309,6 @@ class Ephemeris {

Checkpoint GetCheckpoint() REQUIRES_SHARED(lock_);

// Same as t_max, but |lock_| must be held.
Instant t_max_locked() const REQUIRES_SHARED(lock_);

// Note the return by copy: the returned value is usable even if the
// |instance_| is being integrated.
Instant instance_time() const EXCLUDES(lock_);
@@ -333,10 +337,9 @@ class Ephemeris {
// Computes the accelerations due to one body, |body1| (with index |b1| in the
// |bodies_| and |trajectories_| arrays) on massless bodies at the given
// |positions|. The template parameter specifies what we know about the
// massive body, and therefore what forces apply. Returns false iff a
// collision occurred, i.e., the massless body is inside |body1|.
// massive body, and therefore what forces apply.
template<bool body1_is_oblate>
bool ComputeGravitationalAccelerationByMassiveBodyOnMasslessBodies(
Error ComputeGravitationalAccelerationByMassiveBodyOnMasslessBodies(
Instant const& t,
MassiveBody const& body1,
std::size_t const b1,
@@ -348,13 +351,14 @@ class Ephemeris {
void ComputeMassiveBodiesGravitationalAccelerations(
Instant const& t,
std::vector<Position<Frame>> const& positions,
std::vector<Vector<Acceleration, Frame>>& accelerations) const;
std::vector<Vector<Acceleration, Frame>>& accelerations) const
REQUIRES_SHARED(lock_);

// Computes the acceleration exerted by the massive bodies in |bodies_| on
// massless bodies. The massless bodies are at the given |positions|.
// Returns false iff a collision occurred, i.e., the massless body is inside
// one of the |bodies_|.
bool ComputeMasslessBodiesGravitationalAccelerations(
Error ComputeMasslessBodiesGravitationalAccelerations(
Instant const& t,
std::vector<Position<Frame>> const& positions,
std::vector<Vector<Acceleration, Frame>>& accelerations) const
@@ -368,7 +372,7 @@ class Ephemeris {
Instant const& t,
ODEAdaptiveStepParameters<ODE> const& parameters,
std::int64_t max_ephemeris_steps,
bool last_point_only);
bool last_point_only) EXCLUDES(lock_);

// Computes an estimate of the ratio |tolerance / error|.
static double ToleranceToErrorRatio(
@@ -377,11 +381,6 @@ class Ephemeris {
Time const& current_step_size,
typename NewtonianMotionEquation::SystemStateError const& error);

// Guards |instance_|, |trajectories_|, and |bodies_to_trajectories_| during
// integration. Note that the thread-safety annotations are incomplete
// because we do not attempt to protect all the operations, only integration.
mutable absl::Mutex lock_;

// The bodies in the order in which they were given at construction.
std::vector<not_null<MassiveBody const*>> unowned_bodies_;

@@ -404,12 +403,16 @@ class Ephemeris {

AccuracyParameters const accuracy_parameters_;
FixedStepParameters const fixed_step_parameters_;
std::unique_ptr<
typename Integrator<NewtonianMotionEquation>::Instance> instance_;

// The fields above this line are fixed at construction and therefore not
// protected. Note that |ContinuousTrajectory| is thread-safe.
mutable absl::Mutex lock_;
std::unique_ptr<typename Integrator<NewtonianMotionEquation>::Instance>
instance_ GUARDED_BY(lock_);

// These are the states other that the last which we preserve in order to
// implement compact serialization. The vector is time-ordered.
std::vector<Checkpoint> checkpoints_;
std::vector<Checkpoint> checkpoints_ GUARDED_BY(lock_);

int number_of_oblate_bodies_ = 0;
int number_of_spherical_bodies_ = 0;
Loading