Medusa  1.1
Coordinate Free Mehless Method implementation
test/integrators/AdamsBashforth_test.cpp
#include "gtest/gtest.h"
namespace mm {
TEST(Integrators, ABStiff) {
/*
* Solving:
* y' = -20(y-2), y(0) = 3
*
* with solution x = exp(-t)
*/
std::function<Eigen::VectorXd(double, const Eigen::VectorXd&)> func =
[](double, const Eigen::VectorXd& y) {
return -20*(y-2*Eigen::VectorXd::Ones(1));
};
Eigen::VectorXd y0(1); y0 << 3.0;
double tmax = 10.0;
double step = 0.005;
auto solver_ab1 = integrators::ExplicitMultistep::AB1().solve(func, 0.0, tmax, step, y0);
auto solver_ab2 = integrators::ExplicitMultistep::AB2().solve(func, 0.0, tmax, step, y0);
auto solver_ab3 = integrators::ExplicitMultistep::AB3().solve(func, 0.0, tmax, step, y0);
auto solver_ab4 = integrators::ExplicitMultistep::AB4().solve(func, 0.0, tmax, step, y0);
auto solver_ab5 = integrators::ExplicitMultistep::AB5().solve<RKExplicit<double, 6>>(
func, 0.0, tmax, step, y0);
auto stepper_ab1 = solver_ab1.begin();
auto stepper_ab2 = solver_ab2.begin();
auto stepper_ab3 = solver_ab3.begin();
auto stepper_ab4 = solver_ab4.begin();
auto stepper_ab5 = solver_ab5.begin();
while (stepper_ab4) {
++stepper_ab1;
++stepper_ab2;
++stepper_ab3;
++stepper_ab4;
++stepper_ab5;
}
double correct = 2.0 + std::exp(-20.0*stepper_ab4.time());
EXPECT_NEAR(correct, stepper_ab1.value()[0], 1e-4);
EXPECT_NEAR(correct, stepper_ab2.value()[0], 1e-5);
EXPECT_NEAR(correct, stepper_ab3.value()[0], 1e-6);
EXPECT_NEAR(correct, stepper_ab4.value()[0], 1e-7);
EXPECT_NEAR(correct, stepper_ab5.value()[0], 1e-8);
}
TEST(Integrators, ABCircle) {
/*
* Solving:
* x' = -y
* y' = x
*
* with solution (x, y) = (cos(t), sin(t))
*/
std::function<Eigen::VectorXd(double, const Eigen::VectorXd&)> func =
[](double, const Eigen::VectorXd& y) {
Eigen::VectorXd r(2);
r(0) = -y(1);
r(1) = y(0);
return r;
};
double tmax = 2*PI;
double step = 0.1;
Eigen::VectorXd y0(2); y0 << 1.0, 0.0;
auto solver_ab1 = integrators::ExplicitMultistep::AB1().solve(func, 0.0, tmax, step, y0);
auto solver_ab2 = integrators::ExplicitMultistep::AB2().solve(func, 0.0, tmax, step, y0);
auto solver_ab3 = integrators::ExplicitMultistep::AB3().solve(func, 0.0, tmax, step, y0);
auto solver_ab4 = integrators::ExplicitMultistep::AB4().solve(func, 0.0, tmax, step, y0);
auto solver_ab5 = integrators::ExplicitMultistep::AB5().solve<RKExplicit<double, 6>>(
func, 0.0, tmax, step, y0);
auto stepper_ab1 = solver_ab1.begin();
auto stepper_ab2 = solver_ab2.begin();
auto stepper_ab3 = solver_ab3.begin();
auto stepper_ab4 = solver_ab4.begin();
auto stepper_ab5 = solver_ab5.begin();
while (stepper_ab4) {
++stepper_ab1;
++stepper_ab2;
++stepper_ab3;
++stepper_ab4;
++stepper_ab5;
}
double correctx = std::cos(stepper_ab4.time()), correcty = std::sin(stepper_ab4.time());
EXPECT_NEAR(correctx, stepper_ab4.value()[0], 5e-4);
EXPECT_NEAR(correcty, stepper_ab4.value()[1], 5e-4);
EXPECT_NEAR(correctx, stepper_ab3.value()[0], 5e-3);
EXPECT_NEAR(correcty, stepper_ab3.value()[1], 5e-3);
EXPECT_NEAR(correctx, stepper_ab2.value()[0], 5e-2);
EXPECT_NEAR(correcty, stepper_ab2.value()[1], 5e-2);
EXPECT_NEAR(correctx, stepper_ab1.value()[0], 1e-0);
EXPECT_NEAR(correcty, stepper_ab1.value()[1], 1e-0);
}
TEST(Integrators, ExplicitOfOrderAB) {
// Test that this compiles
integrators::ExplicitMultistep::of_order<1>();
integrators::ExplicitMultistep::of_order<2>();
integrators::ExplicitMultistep::of_order<3>();
integrators::ExplicitMultistep::of_order<4>();
integrators::ExplicitMultistep::of_order<5>();
}
TEST(Integrators, DISABLED_ABUsageExample) {
/*
* Solving:
* x' = -y
* y' = x
*
* with solution (x, y) = (cos(t), sin(t))
*/
std::function<Eigen::VectorXd(double, const Eigen::VectorXd&)> func =
[](double, const Eigen::VectorXd& y) {
Eigen::VectorXd r(2);
r(0) = -y(1);
r(1) = y(0);
return r;
};
double tmax = 2*PI;
double dt = 0.1;
Eigen::VectorXd y0(2); y0 << 1.0, 0.0;
auto solver = integrators::ExplicitMultistep::AB3().solve(func, 0.0, tmax, dt, y0);
std::cout << solver << std::endl;
for (auto step : solver) {
std::cout << step << std::endl;
if (step.is_last()) {
std::cout << "This is the last step." << std::endl;
}
// Read/write access to current time and value.
step.time();
step.value();
}
}
} // namespace mm
mm::integrators::ExplicitMultistep::AB2
static AdamsBashforth< scalar_t, 2 > AB2()
Two step AB method.
Definition: AdamsBashforth_fwd.hpp:255
mm
Root namespace for the whole library.
Definition: Gaussian.hpp:14
mm::integrators::ExplicitMultistep::AB1
static AdamsBashforth< scalar_t, 1 > AB1()
Standard Euler's method.
Definition: AdamsBashforth_fwd.hpp:248
mm::integrators::ExplicitMultistep::AB4
static AdamsBashforth< scalar_t, 4 > AB4()
Four step AB method.
Definition: AdamsBashforth_fwd.hpp:269
mm::integrators::ExplicitMultistep::AB5
static AdamsBashforth< scalar_t, 5 > AB5()
Five step AB method.
Definition: AdamsBashforth_fwd.hpp:276
AdamsBashforth.hpp
mm::integrators::ExplicitMultistep::AB3
static AdamsBashforth< scalar_t, 3 > AB3()
Three step AB method.
Definition: AdamsBashforth_fwd.hpp:262
mm::PI
static const double PI
Mathematical constant pi in double precision.
Definition: Config.hpp:44
mm::integrators::Explicit::Fehlberg5
RKExplicit< scalar_t, 6 > Fehlberg5()
Fifth order method appearing in Fehlberg's method.
Definition: RKExplicit.hpp:79