8 #include <gtest/gtest.h> 14 using std::shared_ptr;
19 std::vector<std::string>
integratorNames = {
"euler",
"rk4",
"rk78",
"rk5 variable",
"ode45",
"modified midpoint"};
20 std::vector<std::string>
integratorCalls = {
"const",
"nSteps",
"adaptive",
"times"};
24 std::random_device rd;
25 std::mt19937 eng(rd());
26 std::uniform_real_distribution<> distr(min, max);
33 #ifdef PLOTTING_ENABLED 38 std::cout <<
"plotting " << stateTrajectories.size() <<
" trajectories" << std::endl;
39 for (
size_t i = 0;
i < stateTrajectories.size();
i++)
41 if (timeTrajectories[
i].size() != stateTrajectories[
i].size())
42 throw std::runtime_error(
"Cannot plot data, x and y not equal length");
44 std::vector<double> position;
45 for (
size_t j = 0; j < stateTrajectories[
i].size(); j++)
47 position.push_back(stateTrajectories[
i][j](0) + (stateTrajectories.size() -
i - 1));
50 int type = ((int)
i) / 4;
54 plot::subplot(5, std::round(stateTrajectories.size() / 5.0) + 1,
i + 1);
55 plot::plot(timeTrajectories[
i].toImplementation(), position);
70 TEST(IntegrationTest, derivativeTest)
75 shared_ptr<SecondOrderSystem> oscillator;
78 std::vector<std::shared_ptr<Integrator<stateSize>>> integrators;
83 for (
size_t i = 0;
i < nTests;
i++)
87 Time finalTime = startTime + 1.0;
88 size_t nsteps = 1.0 / dt;
92 initialState << 1.0, 0.0;
99 while (w_n * w_n - zeta * zeta <= 0)
105 oscillator->checkParameters();
112 integrators.push_back(
115 integrators.push_back(
121 double w_d = std::sqrt(w_n * w_n - zeta * zeta);
122 double phase = std::atan(w_d / zeta);
123 double A = 1.0 / std::sin(phase);
124 auto solution = [w_d, zeta, phase, A](
125 Time t) {
return A * std::exp(-zeta *
t) * std::sin(w_d * t + phase); };
129 size_t integratorFunctions = 4;
130 size_t nIntegrators = integrators.size();
131 size_t nResults = nIntegrators * integratorFunctions;
133 std::vector<StateVectorArray<stateSize>> stateTrajectories(nResults);
134 std::vector<TimeArray> timeTrajectories(nResults);
135 std::vector<StateVector<stateSize>> finalStates(nResults);
139 for (
size_t j = 0; j < nIntegrators; j++)
143 initialStateLocal = initialState;
148 integrators[j]->integrate_const(initialStateLocal, startTime, finalTime, dt,
149 stateTrajectories[j * integratorFunctions + 0], timeTrajectories[j * integratorFunctions + 0]);
151 initialStateLocal = initialState;
155 integrators[j]->integrate_n_steps(initialStateLocal, startTime, nsteps, dt,
156 stateTrajectories[j * integratorFunctions + 1], timeTrajectories[j * integratorFunctions + 1]);
158 initialStateLocal = initialState;
162 integrators[j]->integrate_adaptive(initialStateLocal, startTime, finalTime,
163 stateTrajectories[j * integratorFunctions + 2], timeTrajectories[j * integratorFunctions + 2], dt);
165 initialStateLocal = initialState;
167 for (
size_t k = 0; k < nsteps + 1; k++)
169 timeTrajectories[j * integratorFunctions + 3].push_back(k * dt);
174 integrators[j]->integrate_times(initialStateLocal, timeTrajectories[j * integratorFunctions + 3],
175 stateTrajectories[j * integratorFunctions + 3], dt);
178 for (
size_t j = 0; j < nResults; j++)
183 ASSERT_GT(stateTrajectories[j].size(), 2);
184 ASSERT_GT(timeTrajectories[j].size(), 2);
187 ASSERT_LT((stateTrajectories[j].front() - initialState).array().abs().maxCoeff(), 1e-6);
188 ASSERT_EQ(stateTrajectories[j].size(), timeTrajectories[j].size());
191 ASSERT_NEAR(timeTrajectories[j].front(), startTime, dt);
192 ASSERT_NEAR(timeTrajectories[j].back(), finalTime, dt);
195 for (
size_t k = 1; k < timeTrajectories[j].size(); k++)
197 ASSERT_GT(timeTrajectories[j][k], timeTrajectories[j][k - 1]);
199 if (j % 4 == 0 || j % 4 == 1)
202 ASSERT_NEAR(timeTrajectories[j][k] - timeTrajectories[j][k - 1], dt, 1e-6);
209 for (
size_t k = 1; k < stateTrajectories[j].size(); k++)
211 double derivativeNumDiff = stateTrajectories[j][k](0) - stateTrajectories[j][k - 1](0);
212 double derivativeAnalytical =
213 solution(timeTrajectories[j][k]) - solution(timeTrajectories[j][k - 1]);
215 ASSERT_NEAR(derivativeNumDiff, derivativeAnalytical, 1e-2);
221 ASSERT_NEAR(stateTrajectories[j].back()(0), stateTrajectories[j - 1].back()(0), 5e-2);
232 std::cout <<
"Caught exception." << std::endl;
void plotResults(std::vector< StateVectorArray< stateSize >> &stateTrajectories, std::vector< TimeArray > &timeTrajectories)
Definition: IntegrationTest.h:31
An discrete array (vector) of a particular data type.
Definition: DiscreteArray.h:22
std::vector< std::string > integratorCalls
Definition: IntegrationTest.h:20
Definition: Integrator.h:32
bool ion()
Enable interactive mode.
Definition: plot.cpp:736
bool plotResult
Definition: IntegrationTest.h:17
Definition: Integrator.h:35
clear all close all load ct GNMSLog0 mat reformat t
tpl::SecondOrderSystem< double > SecondOrderSystem
harmonic oscillator (double)
Definition: SecondOrderSystem.h:220
bool plot(const Eigen::Ref< const Eigen::MatrixXd > &x, const Eigen::Ref< const Eigen::MatrixXd > &y, const std::map< std::string, std::string > &keywords)
Create an x/y plot with properties as map.
Definition: plot.cpp:786
Definition: StateVector.h:12
Standard Integrator.
Definition: Integrator.h:62
Definition: Integrator.h:33
TEST(IntegrationTest, derivativeTest)
Definition: IntegrationTest.h:70
void show(bool block=true)
Definition: plot.cpp:913
std::vector< std::string > integratorNames
Definition: IntegrationTest.h:19
const size_t stateSize
Definition: IntegrationTest.h:16
Definition: Integrator.h:37
Definition: Integrator.h:36
void title(const std::string &titlestr)
Definition: plot.cpp:883
double uniformRandomNumber(double min, double max)
Definition: IntegrationTest.h:22
bool subplot(const size_t nrows, const size_t ncols, const size_t plot_number)
Create a subplot.
Definition: plot.cpp:779
double Time
Definition: Time.h:11
Definition: Integrator.h:34
bool figure(std::string i="")
Create a new figure.
Definition: plot.cpp:744