diff --git a/doc/changelog.rst b/doc/changelog.rst index f099874a..7247c329 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -9,6 +9,8 @@ Changelog New ~~~ +- Add model for the circular restricted three-body problem + (`#135 `__). - The LLVM SLP vectorizer can now be enabled (`#134 `__). This feature is opt-in due to the fact that enabling it diff --git a/doc/notebooks/Box control for Formation Flying Satellites.ipynb b/doc/notebooks/Box control for Formation Flying Satellites.ipynb index 18e83602..1cf8034e 100644 --- a/doc/notebooks/Box control for Formation Flying Satellites.ipynb +++ b/doc/notebooks/Box control for Formation Flying Satellites.ipynb @@ -62,7 +62,7 @@ "where $f_h$ is the perturbative acceleration acting on the satellite along the $\\hat{\\mathbf e}_h$ direction.\n", "\n", "## The Equations of Motion\n", - "We consider the dynamics of both the Chief and the Deputy expressed in terms of their position and velocity in $\\mathcal F_i$ and subject to the J2 term only (the expression of additional terms for the Earth gravitational potential can be found [here](https://space.stackexchange.com/questions/22266/j2-long-period-perturbations-in-the-inclination):\n", + "We consider the dynamics of both the Chief and the Deputy expressed in terms of their position and velocity in $\\mathcal F_i$ and subject to the J2 term only:\n", "\n", "$$\n", "\\left\\{\n", diff --git a/heyoka/_test_model.py b/heyoka/_test_model.py index a04713ce..3b27c771 100644 --- a/heyoka/_test_model.py +++ b/heyoka/_test_model.py @@ -252,3 +252,21 @@ def test_pendulum(self): ) ), ) + + def test_cr3bp(self): + from . import model, make_vars + + x, px, y = make_vars("x", "px", "y") + + dyn = model.cr3bp() + self.assertEqual(dyn[0][0], x) + self.assertEqual(dyn[0][1], px + y) + + dyn = model.cr3bp(mu=1.0 / 2**4) + self.assertTrue("0.06250000000" in str(dyn[3][1])) + + jac = model.cr3bp_jacobi() + self.assertTrue("0.00100000" in str(jac)) + + jac = model.cr3bp_jacobi(mu=1.0 / 2**4) + self.assertTrue("0.06250000000" in str(jac)) diff --git a/heyoka/expose_expression.cpp b/heyoka/expose_expression.cpp index dd8ea439..aafd8e08 100644 --- a/heyoka/expose_expression.cpp +++ b/heyoka/expose_expression.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -201,7 +202,7 @@ void expose_expression(py::module_ &m) .def("__copy__", copy_wrapper) .def("__deepcopy__", deepcopy_wrapper, "memo"_a) // Hashing. - .def("__hash__", [](const heyoka::expression &e) { return heyoka::hash(e); }) + .def("__hash__", [](const heyoka::expression &e) { return std::hash{}(e); }) // Pickle support. .def(py::pickle(&pickle_getstate_wrapper, &pickle_setstate_wrapper)); diff --git a/heyoka/expose_models.cpp b/heyoka/expose_models.cpp index 45d0830c..8333665b 100644 --- a/heyoka/expose_models.cpp +++ b/heyoka/expose_models.cpp @@ -180,6 +180,17 @@ auto mascon_impl(const Op &op, const V &Gconst, const std::vector &masses, co hy::kw::omega = omega_vec); } +// Common logic to expose cr3bp helpers. +template +auto cr3bp_impl(const Op &op, const V &mu) +{ + namespace hy = heyoka; + + const auto muval = ex_from_variant(mu); + + return op(hy::kw::mu = muval); +} + } // namespace } // namespace detail @@ -343,6 +354,14 @@ void expose_models(py::module_ &m) }, "pl_idx"_a, "time"_a = hy::time, "thresh"_a.noconvert() = 1e-9); m.def("_model_get_vsop2013_mus", &hy::model::get_vsop2013_mus); + + // CR3BP. + m.def( + "_model_cr3bp", [](const vex_t &mu) { return detail::cr3bp_impl(hy::model::cr3bp, mu); }, + "mu"_a.noconvert() = 1e-3); + m.def( + "_model_cr3bp_jacobi", [](const vex_t &mu) { return detail::cr3bp_impl(hy::model::cr3bp_jacobi, mu); }, + "mu"_a.noconvert() = 1e-3); } } // namespace heyoka_py