-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
39371eb
commit 0054d65
Showing
6 changed files
with
242 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
// Copyright 2020, 2021, 2022, 2023 Francesco Biscani ([email protected]), Dario Izzo ([email protected]) | ||
// | ||
// This file is part of the heyoka library. | ||
// | ||
// This Source Code Form is subject to the terms of the Mozilla | ||
// Public License v. 2.0. If a copy of the MPL was not distributed | ||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
|
||
#include <cmath> | ||
#include <stdexcept> | ||
#include <utility> | ||
#include <variant> | ||
#include <vector> | ||
|
||
#include <fmt/core.h> | ||
|
||
#include <heyoka/config.hpp> | ||
#include <heyoka/expression.hpp> | ||
#include <heyoka/math/pow.hpp> | ||
#include <heyoka/math/sqrt.hpp> | ||
#include <heyoka/model/cr3bp.hpp> | ||
#include <heyoka/number.hpp> | ||
|
||
HEYOKA_BEGIN_NAMESPACE | ||
|
||
namespace model::detail | ||
{ | ||
|
||
namespace | ||
{ | ||
|
||
void cr3bp_check_mu(const expression &mu) | ||
{ | ||
if (const auto *nptr = std::get_if<number>(&mu.value())) { | ||
std::visit( | ||
[](const auto &v) { | ||
using std::isfinite; | ||
|
||
if (!isfinite(v) || v <= 0 || v >= .5) { | ||
throw std::invalid_argument(fmt::format("The 'mu' parameter in a CR3BP must be in the range (0, " | ||
"0.5), but a value of {} was provided instead", | ||
v)); | ||
} | ||
}, | ||
nptr->value()); | ||
} | ||
} | ||
|
||
} // namespace | ||
|
||
std::vector<std::pair<expression, expression>> cr3bp_impl(const expression &mu) | ||
{ | ||
cr3bp_check_mu(mu); | ||
|
||
// Init the state variables, | ||
auto [px, py, pz, x, y, z] = make_vars("px", "py", "pz", "x", "y", "z"); | ||
|
||
// x - mu. | ||
// NOTE: leave it unfixed so that constant folding can take place | ||
// in the computation of x - mu + 1 in the common case where mu is a numerical | ||
// constant. This allows for better ILP as x - mu and x + (-mu + 1.) can be | ||
// computed in parallel. | ||
const auto x_m_mu = x - mu; | ||
// x - mu + 1. | ||
const auto x_m_mu_p1 = x_m_mu + 1.; | ||
// y**2 + z**2. | ||
const auto y_p_z_2 = fix_nn(y * y + z * z); | ||
// rp1**2. | ||
const auto rp1_2 = x_m_mu * x_m_mu + y_p_z_2; | ||
// rp2**2. | ||
const auto rp2_2 = x_m_mu_p1 * x_m_mu_p1 + y_p_z_2; | ||
// (1 - mu) / rp1**3. | ||
const auto g1 = fix_nn((1. - mu) * pow(rp1_2, -3. / 2)); | ||
// mu / rp2**3. | ||
const auto g2 = fix_nn(mu * pow(rp2_2, -3. / 2)); | ||
// g1 + g2. | ||
const auto g1_g2 = fix_nn(g1 + g2); | ||
|
||
const auto xdot = px + y; | ||
const auto ydot = py - x; | ||
const auto zdot = pz; | ||
const auto pxdot = py - g1 * x_m_mu - g2 * x_m_mu_p1; | ||
const auto pydot = -px - g1_g2 * y; | ||
const auto pzdot = -g1_g2 * z; | ||
|
||
return {prime(x) = xdot, prime(y) = ydot, prime(z) = zdot, prime(px) = pxdot, prime(py) = pydot, prime(pz) = pzdot}; | ||
} | ||
|
||
expression cr3bp_jacobi_impl(const expression &mu) | ||
{ | ||
cr3bp_check_mu(mu); | ||
|
||
// Init the state variables, | ||
auto [px, py, pz, x, y, z] = make_vars("px", "py", "pz", "x", "y", "z"); | ||
|
||
// x - mu. | ||
const auto x_m_mu = x - mu; | ||
// x - mu + 1. | ||
const auto x_m_mu_p1 = x_m_mu + 1.; | ||
// y**2 + z**2. | ||
const auto y_p_z_2 = fix_nn(y * y + z * z); | ||
// rp1**2. | ||
const auto rp1_2 = x_m_mu * x_m_mu + y_p_z_2; | ||
// rp2**2. | ||
const auto rp2_2 = x_m_mu_p1 * x_m_mu_p1 + y_p_z_2; | ||
// (1 - mu) / rp1. | ||
const auto g1 = fix_nn((1. - mu) / sqrt(rp1_2)); | ||
// mu / rp2. | ||
const auto g2 = fix_nn(mu / sqrt(rp2_2)); | ||
|
||
const auto kin = 0.5 * fix_nn(px * px + py * py + pz * pz); | ||
|
||
return kin + y * px - x * py - g1 - g2; | ||
} | ||
|
||
} // namespace model::detail | ||
|
||
HEYOKA_END_NAMESPACE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
// Copyright 2020, 2021, 2022, 2023 Francesco Biscani ([email protected]), Dario Izzo ([email protected]) | ||
// | ||
// This file is part of the heyoka library. | ||
// | ||
// This Source Code Form is subject to the terms of the Mozilla | ||
// Public License v. 2.0. If a copy of the MPL was not distributed | ||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
|
||
#include <initializer_list> | ||
#include <stdexcept> | ||
#include <vector> | ||
|
||
#include <heyoka/expression.hpp> | ||
#include <heyoka/kw.hpp> | ||
#include <heyoka/llvm_state.hpp> | ||
#include <heyoka/model/cr3bp.hpp> | ||
#include <heyoka/taylor.hpp> | ||
|
||
#include "catch.hpp" | ||
#include "test_utils.hpp" | ||
|
||
using namespace heyoka; | ||
using namespace heyoka_test; | ||
|
||
TEST_CASE("basic") | ||
{ | ||
using Catch::Matchers::Message; | ||
|
||
{ | ||
auto dyn = model::cr3bp(); | ||
|
||
REQUIRE(dyn.size() == 6u); | ||
REQUIRE(dyn[0].first == "x"_var); | ||
REQUIRE(dyn[1].first == "y"_var); | ||
REQUIRE(dyn[2].first == "z"_var); | ||
REQUIRE(dyn[3].first == "px"_var); | ||
REQUIRE(dyn[4].first == "py"_var); | ||
REQUIRE(dyn[5].first == "pz"_var); | ||
} | ||
|
||
// Energy conservation. | ||
{ | ||
auto dyn = model::cr3bp(); | ||
|
||
const std::vector init_state = {-0.45, 0.80, 0.00, -0.80, -0.45, 0.58}; | ||
|
||
auto ta = taylor_adaptive{dyn, init_state}; | ||
|
||
REQUIRE(ta.get_decomposition().size() == 36u); | ||
|
||
ta.propagate_until(20.); | ||
|
||
auto [x, y, z, px, py, pz] = make_vars("x", "y", "z", "px", "py", "pz"); | ||
|
||
llvm_state s; | ||
|
||
const auto dc = add_cfunc<double>(s, "jac", {model::cr3bp_jacobi()}, kw::vars = {x, y, z, px, py, pz}); | ||
|
||
REQUIRE(dc.size() == 25u); | ||
|
||
s.compile(); | ||
|
||
auto *cf | ||
= reinterpret_cast<void (*)(double *, const double *, const double *, const double *)>(s.jit_lookup("jac")); | ||
double E0 = 0; | ||
cf(&E0, init_state.data(), nullptr, nullptr); | ||
|
||
double E = 0; | ||
cf(&E, ta.get_state().data(), nullptr, nullptr); | ||
|
||
REQUIRE(E == approximately(E0)); | ||
} | ||
|
||
// With custom mu. | ||
{ | ||
auto dyn = model::cr3bp(kw::mu = 1e-2); | ||
|
||
const std::vector init_state = {-0.45, 0.80, 0.00, -0.80, -0.45, 0.58}; | ||
|
||
auto ta = taylor_adaptive{dyn, init_state}; | ||
|
||
REQUIRE(ta.get_decomposition().size() == 36u); | ||
|
||
ta.propagate_until(20.); | ||
|
||
auto [x, y, z, px, py, pz] = make_vars("x", "y", "z", "px", "py", "pz"); | ||
|
||
llvm_state s; | ||
|
||
const auto dc | ||
= add_cfunc<double>(s, "jac", {model::cr3bp_jacobi(kw::mu = 1e-2)}, kw::vars = {x, y, z, px, py, pz}); | ||
|
||
REQUIRE(dc.size() == 25u); | ||
|
||
s.compile(); | ||
|
||
auto *cf | ||
= reinterpret_cast<void (*)(double *, const double *, const double *, const double *)>(s.jit_lookup("jac")); | ||
double E0 = 0; | ||
cf(&E0, init_state.data(), nullptr, nullptr); | ||
|
||
double E = 0; | ||
cf(&E, ta.get_state().data(), nullptr, nullptr); | ||
|
||
REQUIRE(E == approximately(E0)); | ||
} | ||
|
||
// Error modes. | ||
REQUIRE_THROWS_MATCHES(model::cr3bp(kw::mu = -1.), std::invalid_argument, | ||
Message("The 'mu' parameter in a CR3BP must be in the range (0, " | ||
"0.5), but a value of -1 was provided instead")); | ||
REQUIRE_THROWS_MATCHES(model::cr3bp_jacobi(kw::mu = 1.), std::invalid_argument, | ||
Message("The 'mu' parameter in a CR3BP must be in the range (0, " | ||
"0.5), but a value of 1 was provided instead")); | ||
} |