diff --git a/trick_source/trick_utils/SAIntegrator/examples/CannonBall/CannonBall.cpp b/trick_source/trick_utils/SAIntegrator/examples/CannonBall/CannonBall.cpp index 0d00754e..05a0d80a 100644 --- a/trick_source/trick_utils/SAIntegrator/examples/CannonBall/CannonBall.cpp +++ b/trick_source/trick_utils/SAIntegrator/examples/CannonBall/CannonBall.cpp @@ -27,15 +27,9 @@ void calc_derivs( double t, double state[], double derivs[], void* udata) { double impact( double t, double state[], RootFinder* root_finder, void* udata) { double root_error = root_finder->find_roots(t, state[1]); if (root_error == 0.0) { - printf("---------------------------------------------------------------\n"); - printf("Impact at t = %5.10f x = %5.10f y = %5.10f.\n", t, state[0], state[1]); - printf("---------------------------------------------------------------\n"); root_finder->init(); - state[1] = 0.0000000001; // pos_y - state[2] = 0.0; // vel_x - state[3] = 0.0; // vel_y - state[4] = 0.0; // acc_x - state[5] = 0.0; // acc_y + state[2] = 0.9 * state[2]; + state[3] = -0.9 * state[3]; } return (root_error); } @@ -55,17 +49,14 @@ int main ( int argc, char* argv[]) { double t = 0.0; SA::RK2Integrator integ(dt, 6, state_var_p, state_var_p, calc_derivs, NULL); -// Uncomment the following two lines to have the RootFinder detect impact. -// RootFinder root_finder(0.00000000001, Negative); -// integ.add_Rootfinder(&root_finder, &impact); + RootFinder root_finder(0.00000000001, Negative); + integ.add_Rootfinder(&root_finder, &impact); init_state(cannon); print_header(); print_state( t, cannon); - while (t < 5.3) { - integ.load(); - integ.step(); - integ.unload(); + while (t < 20.0) { + integ.integrate(); t = integ.getIndyVar(); print_state( t, cannon); } diff --git a/trick_source/trick_utils/SAIntegrator/examples/DoubleIntegral/DoubleIntegral.cpp b/trick_source/trick_utils/SAIntegrator/examples/DoubleIntegral/DoubleIntegral.cpp index 91822b07..c712177e 100644 --- a/trick_source/trick_utils/SAIntegrator/examples/DoubleIntegral/DoubleIntegral.cpp +++ b/trick_source/trick_utils/SAIntegrator/examples/DoubleIntegral/DoubleIntegral.cpp @@ -23,9 +23,7 @@ void deriv_x( double x, double state_x[], double derivs_x[], void* udata) { integ_y->set_out_vars(state_y); integ_y->setIndyVar(context->start); while (integ_y->getIndyVar() <= context->end) { - integ_y->load(); - integ_y->step(); - integ_y->unload(); + integ_y->integrate(); } derivs_x[0] = area; // volume = ∫ area dx } @@ -40,9 +38,7 @@ double doubleIntegral( double x_start, double x_end, double y_start, double y_en SA::RK2Integrator integ_x (dx, 1, state_x, state_x, deriv_x, &y_integ_context); integ_x.setIndyVar(x_start); while (integ_x.getIndyVar()<=x_end) { - integ_x.load(); - integ_x.step(); - integ_x.unload(); + integ_x.integrate(); } return volume; } diff --git a/trick_source/trick_utils/SAIntegrator/include/SAIntegrator.hh b/trick_source/trick_utils/SAIntegrator/include/SAIntegrator.hh index 357dea95..30153ab1 100644 --- a/trick_source/trick_utils/SAIntegrator/include/SAIntegrator.hh +++ b/trick_source/trick_utils/SAIntegrator/include/SAIntegrator.hh @@ -7,12 +7,15 @@ namespace SA { double X_out; // Independent Variable Out double default_h; // Default step-size void* user_data; // User data + void advanceIndyVar(); public: Integrator(double h, void* udata): X_in(0.0), X_out(0.0), default_h(h), user_data(udata) {}; virtual ~Integrator() {} - virtual void step(); virtual void load(); virtual void unload(); + virtual void step(); + void integrate(); + virtual double undo_integrate(); double getIndyVar(); void setIndyVar(double v); }; @@ -27,30 +30,47 @@ namespace SA { double** inVars; // Array of pointers to the variables whose values comprise the input state vector. double** outVars; // Array of pointers to the variables to which the output state vector values are to be disseminated. DerivsFunc derivs_func; // Pointer to the function that calculates the derivatives to be integrated. - double last_h; // What was the last step-size? For undo_step(). - + // void advanceIndyVar(); // Inherited from Integrator::advanceIndyVar() public: FirstOrderODEIntegrator( double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata); virtual ~FirstOrderODEIntegrator(); - virtual double undo_step(); - void load(); - void unload(); - void load_from_outState(); - double** set_in_vars( double* in_vars[]); - double** set_out_vars( double* out_vars[]); + void load(); // Overrides Integrator::load(), Final + void unload(); // Overrides Integrator::unload(), Final + virtual void step(); // Overrides Integrator::step(). Virtual + // integrate(); Inherited from Integrator::integrate(), Final + virtual double undo_integrate(); // Overrides Integrator::undo_integrate(), Virtual + void load_from_outState(); // New, Final + double** set_in_vars( double* in_vars[]); // New, Final + double** set_out_vars( double* out_vars[]);// New, Final + // double getIndyVar(); + // void setIndyVar(double v); }; typedef double (*RootErrorFunc)( double x, double state[], RootFinder* root_finder, void* udata); class FirstOrderODEVariableStepIntegrator : public FirstOrderODEIntegrator { + private: RootFinder* root_finder; RootErrorFunc root_error_func; + protected: + double last_h; + // void advanceIndyVar(); // Inherited from Integrator::advanceIndyVar(), Final + void advanceIndyVar( double h); public: FirstOrderODEVariableStepIntegrator( double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata); ~FirstOrderODEVariableStepIntegrator(); - virtual void variable_step( double h); - void add_Rootfinder( RootFinder* root_finder, RootErrorFunc rfunc); - void step(); + // load(); Inherited from FirstOrderODEIntegrator, Final + // unload(); Inherited from FirstOrderODEIntegrator, Final + void step(); // Overrides FirstOrderODEIntegrator::step(), Final + // integrate(); // Inherited from Integrator + double undo_integrate(); // Overrides FirstOrderODEIntegrator::undo_integrate(), Final + // load_from_outState(); // Inherited from FirstOrderODEIntegrator, Final + // set_in_vars(); // Inherited from FirstOrderODEIntegrator, Final + // set_out_vars(); // Inherited from FirstOrderODEIntegrator, Final + virtual void variable_step( double h); // New, Should be overridden in derived classes, Virtual + void add_Rootfinder( RootFinder* root_finder, RootErrorFunc rfunc); // New, Final + // double getIndyVar(); // Inherited from Integrator + // void setIndyVar(double v); // Inherited from Integrator private: void find_roots(double h, unsigned int depth); }; @@ -60,7 +80,19 @@ namespace SA { double *derivs; EulerIntegrator( double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata); ~EulerIntegrator(); - void variable_step( double h); + // load(); Inherited from FirstOrderODEIntegrator + // unload(); Inherited from FirstOrderODEIntegrator + // void step(); Inherited from FirstOrderODEVariableStepIntegrator + // void integrate() Inherited from FirstOrderODEVariableStepIntegrator + // double undo_integrate(); Inherited from FirstOrderODEVariableStepIntegrator + // load_from_outState(); Inherited from FirstOrderODEIntegrator + // set_in_vars(); Inherited from FirstOrderODEIntegrator + // set_out_vars(); Inherited from FirstOrderODEIntegrator + void variable_step( double h); // Overrides FirstOrderODEVariableStepIntegrator::variable_step() + // void integrate(double h) Inherited from FirstOrderODEVariableStepIntegrator + // void add_Rootfinder( RootFinder* root_finder, RootErrorFunc rfunc); Inherited from FirstOrderODEVariableStepIntegrator + // double getIndyVar(); Inherited from Integrator + // void setIndyVar(double v); Inherited from Integrator }; class HeunsMethod : public FirstOrderODEVariableStepIntegrator { @@ -69,7 +101,7 @@ namespace SA { double *derivs[2]; HeunsMethod( double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata); ~HeunsMethod(); - void variable_step( double h); + void variable_step( double h); // Overrides FirstOrderODEVariableStepIntegrator::variable_step() }; class RK2Integrator : public FirstOrderODEVariableStepIntegrator { @@ -78,7 +110,7 @@ namespace SA { double *derivs[2]; RK2Integrator( double h, int N, double* in_vars[], double* out_vars[], DerivsFunc derivs_func, void* udata); ~RK2Integrator(); - void variable_step( double h); + void variable_step( double h); // Overrides FirstOrderODEVariableStepIntegrator::variable_step() }; class RK4Integrator : public FirstOrderODEVariableStepIntegrator { @@ -87,7 +119,7 @@ namespace SA { double *derivs[4]; RK4Integrator( double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata); ~RK4Integrator(); - void variable_step( double h); + void variable_step( double h); // Overrides FirstOrderODEVariableStepIntegrator::variable_step() }; class RK3_8Integrator : public FirstOrderODEVariableStepIntegrator { @@ -96,18 +128,18 @@ namespace SA { double *derivs[4]; RK3_8Integrator( double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata); ~RK3_8Integrator(); - void variable_step( double h); + void variable_step( double h); // Overrides FirstOrderODEVariableStepIntegrator::variable_step() }; class EulerCromerIntegrator : public Integrator { protected: - unsigned int state_size; - double** x_p; - double** v_p; - double* x_in; - double* v_in; - double* x_out; - double* v_out; + unsigned int nDimensions; + double** pos_p; + double** vel_p; + double* pos_in; + double* vel_in; + double* pos_out; + double* vel_out; double* g_out; double* f_out; DerivsFunc gderivs; @@ -120,25 +152,26 @@ namespace SA { void step(); void load(); void unload(); + double undo_integrate(); }; - // class ABMIntegrator : public FirstOrderODEIntegrator { - // protected: - // double ** deriv_history; - // double * composite_deriv; - // unsigned int bufferSize; - // unsigned int algorithmHistorySize; - // unsigned int hix; - // unsigned int currentHistorySize; - // - // public: - // ABMIntegrator(int history_size, double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata); - // ~ABMIntegrator(); - // void step(); - // void undo_step(); - // }; + // AdamsBashforthMoulton Self Priming + class ABMIntegrator : public FirstOrderODEIntegrator { + protected: + double ** deriv_history; + double * composite_deriv; + unsigned int bufferSize; + unsigned int algorithmHistorySize; + unsigned int hix; + unsigned int currentHistorySize; + public: + ABMIntegrator(int history_size, double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata); + ~ABMIntegrator(); + void step(); + double undo_integrate(); + }; - // AdamsBashforthMoulton 2 + // AdamsBashforthMoulton 2 with RK2 Priming class ABM2Integrator : public FirstOrderODEIntegrator { protected: double ** deriv_history; @@ -147,15 +180,14 @@ namespace SA { unsigned int hix; unsigned int currentHistorySize; FirstOrderODEVariableStepIntegrator* priming_integrator; - public: ABM2Integrator( double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata); ~ABM2Integrator(); void step(); - double undo_step(); + double undo_integrate(); }; - // AdamsBashforthMoulton 4 + // AdamsBashforthMoulton 4 with RK4 Priming class ABM4Integrator : public FirstOrderODEIntegrator { protected: double ** deriv_history; @@ -164,11 +196,10 @@ namespace SA { unsigned int hix; unsigned int currentHistorySize; FirstOrderODEVariableStepIntegrator* priming_integrator; - public: ABM4Integrator( double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata); ~ABM4Integrator(); void step(); - double undo_step(); + double undo_integrate(); }; } diff --git a/trick_source/trick_utils/SAIntegrator/src/SAIntegrator.cpp b/trick_source/trick_utils/SAIntegrator/src/SAIntegrator.cpp index e52abc99..f93ecedb 100644 --- a/trick_source/trick_utils/SAIntegrator/src/SAIntegrator.cpp +++ b/trick_source/trick_utils/SAIntegrator/src/SAIntegrator.cpp @@ -3,11 +3,33 @@ #include #include "SAIntegrator.hh" -void SA::Integrator::step() { X_out = X_in + default_h; } -void SA::Integrator::load() { X_in = X_out; } -void SA::Integrator::unload() {} -double SA::Integrator::getIndyVar() { return X_out; } -void SA::Integrator::setIndyVar(double v) { X_out = v; } +void SA::Integrator::advanceIndyVar() { + X_out = X_in + default_h; +} +void SA::Integrator::step() { + advanceIndyVar(); +} +void SA::Integrator::load() { + X_in = X_out; +} +void SA::Integrator::unload() { + std::cout << "SA::Integrator : Nothing to unload." << std::endl; +} +void SA::Integrator::integrate() { + load(); + step(); + unload(); +} +double SA::Integrator::undo_integrate() { + X_out = X_in; + return (default_h); +} +double SA::Integrator::getIndyVar() { + return X_out; +} +void SA::Integrator::setIndyVar(double v) { + X_out = v; +} // ------------------------------------------------------------ SA::FirstOrderODEIntegrator::FirstOrderODEIntegrator( @@ -59,13 +81,24 @@ double** SA::FirstOrderODEIntegrator::set_out_vars( double* out_vars[]){ outVars = out_vars; return (ret); } -double SA::FirstOrderODEIntegrator::undo_step() { - for (unsigned int i=0 ; i +#include +#include "SAIntegrator.hh" +#include + +#define EXCEPTABLE_ERROR 0.00000000001 + +void calc_derivs( double x __attribute__((unused)), + double state[] __attribute__((unused)), + double derivs[], + void* udata __attribute__((unused))) { + derivs[0] = 1.0; + derivs[1] = 1.0; + derivs[2] = 1.0; + derivs[3] = 1.0; +} + +/* +The default integration algorithm for FirstOrderODEIntegrator is Euler integration. +Tests: + * getIndyVar + * integrate + * load + * step + * unload +*/ +TEST(FirstOrderODEIntegrator_unittest, test_1) { + double h = 0.1; + unsigned int N = 4; + double vars[4] = {1.0, 2.0, 3.0, 4.0} ; + double* varptrs[4] = {&vars[0], &vars[1], &vars[2], &vars[3]}; + double x; + + SA::FirstOrderODEIntegrator integ( h, N, varptrs, varptrs, calc_derivs, NULL); + + x = integ.getIndyVar(); + EXPECT_NEAR(x, 0.0, EXCEPTABLE_ERROR); + + integ.integrate(); + EXPECT_NEAR(vars[0], 1.1, EXCEPTABLE_ERROR); + EXPECT_NEAR(vars[1], 2.1, EXCEPTABLE_ERROR); + EXPECT_NEAR(vars[2], 3.1, EXCEPTABLE_ERROR); + EXPECT_NEAR(vars[3], 4.1, EXCEPTABLE_ERROR); + + x = integ.getIndyVar(); + EXPECT_NEAR(x, 0.1, EXCEPTABLE_ERROR); +} +/* +Tests: + * getIndyVar + * integrate + * load + * step + * unload + * undo_integrate +*/ +TEST(FirstOrderODEIntegrator_unittest, test_2) { + double h = 0.1; + unsigned int N = 4; + double vars[4] = {1.0, 2.0, 3.0, 4.0} ; + double* varptrs[4] = {&vars[0], &vars[1], &vars[2], &vars[3]}; + double x; + + SA::FirstOrderODEIntegrator integ( h, N, varptrs, varptrs, calc_derivs, NULL); + + integ.integrate(); + EXPECT_NEAR(vars[0], 1.1, EXCEPTABLE_ERROR); + EXPECT_NEAR(vars[1], 2.1, EXCEPTABLE_ERROR); + EXPECT_NEAR(vars[2], 3.1, EXCEPTABLE_ERROR); + EXPECT_NEAR(vars[3], 4.1, EXCEPTABLE_ERROR); + + x = integ.getIndyVar(); + EXPECT_NEAR(x, 0.1, EXCEPTABLE_ERROR); + + integ.undo_integrate(); + EXPECT_NEAR(vars[0], 1.0, EXCEPTABLE_ERROR); + EXPECT_NEAR(vars[1], 2.0, EXCEPTABLE_ERROR); + EXPECT_NEAR(vars[2], 3.0, EXCEPTABLE_ERROR); + EXPECT_NEAR(vars[3], 4.0, EXCEPTABLE_ERROR); + + x = integ.getIndyVar(); + EXPECT_NEAR(x, 0.0, EXCEPTABLE_ERROR); +} + +/* +Tests: + * getIndyVar + * integrate + * load + * step + * unload + * load_from_outState +*/ +TEST(FirstOrderODEIntegrator_unittest, test_3) { + double h = 0.1; + unsigned int N = 4; + double vars[4] = {1.0, 2.0, 3.0, 4.0}; + double* varptrs[4] = {&vars[0], &vars[1], &vars[2], &vars[3]}; + + SA::FirstOrderODEIntegrator integ( h, N, varptrs, varptrs, calc_derivs, NULL); + + integ.integrate(); + for (int i=0; i<5 ; i++) { + integ.load_from_outState(); + integ.step(); + } + integ.unload(); + EXPECT_NEAR(vars[0], 1.6, EXCEPTABLE_ERROR); + EXPECT_NEAR(vars[1], 2.6, EXCEPTABLE_ERROR); + EXPECT_NEAR(vars[2], 3.6, EXCEPTABLE_ERROR); + EXPECT_NEAR(vars[3], 4.6, EXCEPTABLE_ERROR); + + double x = integ.getIndyVar(); + EXPECT_NEAR(x, 0.6, EXCEPTABLE_ERROR); +} + +/* +Tests: + * getIndyVar + * integrate + * load + * step + * unload + * load_from_outState + * set_out_vars +*/ +TEST(FirstOrderODEIntegrator_unittest, test_4) { + double h = 0.1; + unsigned int N = 4; + + double vars[4] = {1.0, 2.0, 3.0, 4.0}; + double* varptrs[4] = {&vars[0], &vars[1], &vars[2], &vars[3]}; + double altvars[4]; + double* altvarptrs[4] = {&altvars[0], &altvars[1], &altvars[2], &altvars[3]}; + + SA::FirstOrderODEIntegrator integ( h, N, varptrs, varptrs, calc_derivs, NULL); + + integ.integrate(); + for (int i=0; i<5 ; i++) { + integ.load_from_outState(); + integ.step(); + } + integ.set_out_vars( altvarptrs); + integ.unload(); + EXPECT_NEAR(altvars[0], 1.6, EXCEPTABLE_ERROR); + EXPECT_NEAR(altvars[1], 2.6, EXCEPTABLE_ERROR); + EXPECT_NEAR(altvars[2], 3.6, EXCEPTABLE_ERROR); + EXPECT_NEAR(altvars[3], 4.6, EXCEPTABLE_ERROR); + + integ.set_out_vars( varptrs); + integ.unload(); + EXPECT_NEAR(vars[0], 1.6, EXCEPTABLE_ERROR); + EXPECT_NEAR(vars[1], 2.6, EXCEPTABLE_ERROR); + EXPECT_NEAR(vars[2], 3.6, EXCEPTABLE_ERROR); + EXPECT_NEAR(vars[3], 4.6, EXCEPTABLE_ERROR); + + double x = integ.getIndyVar(); + EXPECT_NEAR(x, 0.6, EXCEPTABLE_ERROR); +} diff --git a/trick_source/trick_utils/SAIntegrator/unittest/FirstOrderODEVariableStepIntegrator_unittest.cc b/trick_source/trick_utils/SAIntegrator/unittest/FirstOrderODEVariableStepIntegrator_unittest.cc new file mode 100644 index 00000000..14675eac --- /dev/null +++ b/trick_source/trick_utils/SAIntegrator/unittest/FirstOrderODEVariableStepIntegrator_unittest.cc @@ -0,0 +1,172 @@ +#include +#include +#include "SAIntegrator.hh" +#include + +void deriv4( double t, + double state[] __attribute__((unused)), + double derivs[], + void* udata __attribute__((unused))) { + double t2 = t*t; + double t3 = t2*t; + derivs[0] = 3.0*t3 - 3.0*t2 - 3.0*t + 4.0; + derivs[1] = 2.0*t3 + 1.0*t2 - 5.0*t + 7.0; + derivs[2] = t3 + t2 + 5.0*t + 4.0; + derivs[3] = t3 - 6.0*t2 + 4.0*t + 12.0; +} + +void deriv2( double t, + double state[] __attribute__((unused)), + double derivs[], + void* udata __attribute__((unused))) { + + derivs[0] = -2.0*t + 3.0; + derivs[1] = 5.0*t + 4.0; + derivs[2] = 3.0*t - 3.0; + derivs[3] = 5.0*t + 4.0; +} + +void deriv1( double t __attribute__((unused)), + double state[] __attribute__((unused)), + double derivs[], + void* udata __attribute__((unused))) { + derivs[0] = 4.0; + derivs[1] = -4.0; + derivs[2] = M_PI; + derivs[3] = -M_PI; +} + +#define EXCEPTABLE_ERROR 0.00000000001 + +TEST(FirstOrderODEVariableStepIntegrator_unittest, EulerIntegrator_1) { + + double state[4] = {0.0, 0.0, 0.0, 0.0}; + double* state_var_p[4] = { &(state[0]), &(state[1]), &(state[2]), &(state[3])}; + double dt = 0.01; + unsigned int count = 0; + double t = count * dt; + SA::EulerIntegrator integ(dt, 4, state_var_p, state_var_p, deriv1, NULL); + while (t < 2.0) { + integ.load(); + integ.step(); + integ.unload(); + count ++; + t = count * dt; + } + EXPECT_NEAR(state[0], 8.0, EXCEPTABLE_ERROR); + EXPECT_NEAR(state[1], -8.0, EXCEPTABLE_ERROR); + EXPECT_NEAR(state[2], (2*M_PI), EXCEPTABLE_ERROR); + EXPECT_NEAR(state[3], (-2*M_PI), EXCEPTABLE_ERROR); +} + +TEST(FirstOrderODEVariableStepIntegrator_unittest, RungeKutta2_1) { + + double state[4] = {0.0, 0.0, 0.0, 0.0}; + double* state_var_p[4] = { &(state[0]), &(state[1]), &(state[2]), &(state[3]) }; + double dt = 0.01; + unsigned int count = 0; + double t = count * dt; + SA::RK2Integrator integ(dt, 4, state_var_p, state_var_p, deriv2, NULL); + while (t < 2.0) { + integ.load(); + integ.step(); + integ.unload(); + count ++; + t = count * dt; + } + EXPECT_NEAR(state[0], 2.0, EXCEPTABLE_ERROR); + EXPECT_NEAR(state[1], 18.0, EXCEPTABLE_ERROR); + EXPECT_NEAR(state[2], 0.0, EXCEPTABLE_ERROR); + EXPECT_NEAR(state[3], 18.0, EXCEPTABLE_ERROR); +} + +TEST(FirstOrderODEVariableStepIntegrator_unittest, RungeKutta4_1) { + + double state[4] = {0.0, 0.0, 0.0, 0.0}; + double* state_var_p[4] = { &(state[0]), &(state[1]), &(state[2]), &(state[3]) }; + double dt = 0.01; + unsigned int count = 0; + double t = count * dt; + SA::RK4Integrator integ(dt, 4, state_var_p, state_var_p, deriv4, NULL); + while (t < 2.0) { + integ.load(); + integ.step(); + integ.unload(); + count ++; + t = count * dt; + } + EXPECT_NEAR(state[0], 6.0, EXCEPTABLE_ERROR); + EXPECT_NEAR(state[1], (14.0+2/3.0), EXCEPTABLE_ERROR); + EXPECT_NEAR(state[2], (24+2/3.0), EXCEPTABLE_ERROR); + EXPECT_NEAR(state[3], 20.0, EXCEPTABLE_ERROR); +} + +TEST(FirstOrderODEVariableStepIntegrator_unittest, RungeKutta38_1) { + + double state[4] = {0.0, 0.0, 0.0, 0.0}; + double* state_var_p[4] = { &(state[0]), &(state[1]), &(state[2]), &(state[3]) }; + double dt = 0.01; + unsigned int count = 0; + double t = count * dt; + SA::RK3_8Integrator integ(dt, 4, state_var_p, state_var_p, deriv4, NULL); + while (t < 2.0) { + integ.load(); + integ.step(); + integ.unload(); + count ++; + t = count * dt; + } + EXPECT_NEAR(state[0], 6.0, EXCEPTABLE_ERROR); + EXPECT_NEAR(state[1], (14.0+2/3.0), EXCEPTABLE_ERROR); + EXPECT_NEAR(state[2], (24+2/3.0), EXCEPTABLE_ERROR); + EXPECT_NEAR(state[3], 20.0, EXCEPTABLE_ERROR); +} + +TEST(FirstOrderODEVariableStepIntegrator_unittest, EulerIntegrator_undo_integrate) { + + double state[4] = {0.0, 0.0, 0.0, 0.0}; + double* state_var_p[4] = { &(state[0]), &(state[1]), &(state[2]), &(state[3])}; + double dx = 0.1; + double x; + + SA::EulerIntegrator integ(dx, 4, state_var_p, state_var_p, deriv1, NULL); + integ.load(); + integ.step(); + integ.unload(); + + x = integ.getIndyVar(); + EXPECT_NEAR(state[0], (4.0/10.0), EXCEPTABLE_ERROR); + EXPECT_NEAR(state[1], (-4.0/10.0), EXCEPTABLE_ERROR); + EXPECT_NEAR(state[2], (M_PI/10.0), EXCEPTABLE_ERROR); + EXPECT_NEAR(state[3], (-M_PI/10.0), EXCEPTABLE_ERROR); + EXPECT_NEAR(x, 0.1, EXCEPTABLE_ERROR); + + integ.undo_integrate(); + + x = integ.getIndyVar(); + EXPECT_NEAR(state[0], 0.0, EXCEPTABLE_ERROR); + EXPECT_NEAR(state[1], 0.0, EXCEPTABLE_ERROR); + EXPECT_NEAR(state[2], 0.0, EXCEPTABLE_ERROR); + EXPECT_NEAR(state[3], 0.0, EXCEPTABLE_ERROR); + EXPECT_NEAR(x, 0.0, EXCEPTABLE_ERROR); + + integ.undo_integrate(); + + x = integ.getIndyVar(); + EXPECT_NEAR(state[0], 0.0, EXCEPTABLE_ERROR); + EXPECT_NEAR(state[1], 0.0, EXCEPTABLE_ERROR); + EXPECT_NEAR(state[2], 0.0, EXCEPTABLE_ERROR); + EXPECT_NEAR(state[3], 0.0, EXCEPTABLE_ERROR); + EXPECT_NEAR(x, 0.0, EXCEPTABLE_ERROR); + + integ.load(); + integ.step(); + integ.unload(); + + x = integ.getIndyVar(); + EXPECT_NEAR(state[0], (4.0/10.0), EXCEPTABLE_ERROR); + EXPECT_NEAR(state[1], (-4.0/10.0), EXCEPTABLE_ERROR); + EXPECT_NEAR(state[2], (M_PI/10.0), EXCEPTABLE_ERROR); + EXPECT_NEAR(state[3], (-M_PI/10.0), EXCEPTABLE_ERROR); + EXPECT_NEAR(x, 0.1, EXCEPTABLE_ERROR); +} diff --git a/trick_source/trick_utils/SAIntegrator/unittest/Makefile b/trick_source/trick_utils/SAIntegrator/unittest/Makefile index 5bf083dd..1a078d94 100644 --- a/trick_source/trick_utils/SAIntegrator/unittest/Makefile +++ b/trick_source/trick_utils/SAIntegrator/unittest/Makefile @@ -15,8 +15,10 @@ LIBDIRS = -L${SAI_LIBDIR} -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib all: test -test: SAIntegrator_unittest RootFinder_unittest +test: SAIntegrator_unittest FirstOrderODEIntegrator_unittest FirstOrderODEVariableStepIntegrator_unittest RootFinder_unittest ./SAIntegrator_unittest --gtest_output=xml:${TRICK_HOME}/trick_test/SAIntegrator_unittest.xml + ./FirstOrderODEIntegrator_unittest --gtest_output=xml:${TRICK_HOME}/trick_test/FirstOrderODEIntegrator_unittest.xml + ./FirstOrderODEVariableStepIntegrator_unittest --gtest_output=xml:${TRICK_HOME}/trick_test/FirstOrderODEVariableStepIntegrator_unittest.xml ./RootFinder_unittest --gtest_output=xml:${TRICK_HOME}/trick_test/RootFinder_unittest.xml SAIntegrator_unittest.o : SAIntegrator_unittest.cc @@ -25,6 +27,18 @@ SAIntegrator_unittest.o : SAIntegrator_unittest.cc SAIntegrator_unittest : ${SAI_LIBDIR}/${SAI_LIBNAME} SAIntegrator_unittest.o $(TRICK_CXX) $(TRICK_CPPFLAGS) -o $@ $^ ${LIBDIRS} -lSAInteg -lgtest -lgtest_main -lpthread +FirstOrderODEIntegrator_unittest.o : FirstOrderODEIntegrator_unittest.cc + $(TRICK_CXX) $(TRICK_CPPFLAGS) $(INCLUDE_DIRS) -c $< + +FirstOrderODEIntegrator_unittest : ${SAI_LIBDIR}/${SAI_LIBNAME} FirstOrderODEIntegrator_unittest.o + $(TRICK_CXX) $(TRICK_CPPFLAGS) -o $@ $^ ${LIBDIRS} -lSAInteg -lgtest -lgtest_main -lpthread + +FirstOrderODEVariableStepIntegrator_unittest.o : FirstOrderODEVariableStepIntegrator_unittest.cc + $(TRICK_CXX) $(TRICK_CPPFLAGS) $(INCLUDE_DIRS) -c $< + +FirstOrderODEVariableStepIntegrator_unittest : ${SAI_LIBDIR}/${SAI_LIBNAME} FirstOrderODEVariableStepIntegrator_unittest.o + $(TRICK_CXX) $(TRICK_CPPFLAGS) -o $@ $^ ${LIBDIRS} -lSAInteg -lgtest -lgtest_main -lpthread + RootFinder_unittest.o : RootFinder_unittest.cc $(TRICK_CXX) $(TRICK_CPPFLAGS) $(INCLUDE_DIRS) -c $< @@ -38,4 +52,4 @@ clean: ${RM} *.o spotless: clean - ${RM} SAIntegrator_unittest + ${RM} FirstOrderODEVariableStepIntegrator_unittest diff --git a/trick_source/trick_utils/SAIntegrator/unittest/SAIntegrator_unittest.cc b/trick_source/trick_utils/SAIntegrator/unittest/SAIntegrator_unittest.cc index 7764ae2b..96c2a0d9 100644 --- a/trick_source/trick_utils/SAIntegrator/unittest/SAIntegrator_unittest.cc +++ b/trick_source/trick_utils/SAIntegrator/unittest/SAIntegrator_unittest.cc @@ -3,170 +3,72 @@ #include "SAIntegrator.hh" #include -void deriv4( double t, - double state[] __attribute__((unused)), - double derivs[], - void* udata __attribute__((unused))) { - double t2 = t*t; - double t3 = t2*t; - derivs[0] = 3.0*t3 - 3.0*t2 - 3.0*t + 4.0; - derivs[1] = 2.0*t3 + 1.0*t2 - 5.0*t + 7.0; - derivs[2] = t3 + t2 + 5.0*t + 4.0; - derivs[3] = t3 - 6.0*t2 + 4.0*t + 12.0; -} - -void deriv2( double t, - double state[] __attribute__((unused)), - double derivs[], - void* udata __attribute__((unused))) { - - derivs[0] = -2.0*t + 3.0; - derivs[1] = 5.0*t + 4.0; - derivs[2] = 3.0*t - 3.0; - derivs[3] = 5.0*t + 4.0; -} - -void deriv1( double t __attribute__((unused)), - double state[] __attribute__((unused)), - double derivs[], - void* udata __attribute__((unused))) { - derivs[0] = 4.0; - derivs[1] = -4.0; - derivs[2] = M_PI; - derivs[3] = -M_PI; -} - #define EXCEPTABLE_ERROR 0.00000000001 -TEST(SAIntegrator_unittest, EulerIntegrator_1) { +TEST(Integrator, test_getIndyVar_and_setIndyVar) { + double h = 0.1; + void* udata = NULL; + double x; - double state[4] = {0.0, 0.0, 0.0, 0.0}; - double* state_var_p[4] = { &(state[0]), &(state[1]), &(state[2]), &(state[3])}; - double dt = 0.01; - unsigned int count = 0; - double t = count * dt; - SA::EulerIntegrator integ(dt, 4, state_var_p, state_var_p, deriv1, NULL); - while (t < 2.0) { - integ.load(); - integ.step(); - integ.unload(); - count ++; - t = count * dt; - } - EXPECT_NEAR(state[0], 8.0, EXCEPTABLE_ERROR); - EXPECT_NEAR(state[1], -8.0, EXCEPTABLE_ERROR); - EXPECT_NEAR(state[2], (2*M_PI), EXCEPTABLE_ERROR); - EXPECT_NEAR(state[3], (-2*M_PI), EXCEPTABLE_ERROR); + SA::Integrator integ( h, udata); + //Confirm that initial value of the independent variable is 0.0; + x = integ.getIndyVar(); + EXPECT_NEAR(x, 0.0, EXCEPTABLE_ERROR); + + //Set the independent variable, and then confirm that it's the value we set.; + integ.setIndyVar(3.0); + x = integ.getIndyVar(); + EXPECT_NEAR(x, 3.0, EXCEPTABLE_ERROR); +} +TEST(Integrator, test_load_and_step) { + double h = 0.1; + void* udata = NULL; + double x; + + SA::Integrator integ( h, udata); + integ.setIndyVar(4.0); + + integ.load(); + integ.step(); + x = integ.getIndyVar(); + EXPECT_NEAR(x, 4.1, EXCEPTABLE_ERROR); + + integ.load(); + integ.step(); + x = integ.getIndyVar(); + EXPECT_NEAR(x, 4.2, EXCEPTABLE_ERROR); } -TEST(SAIntegrator_unittest, RungeKutta2_1) { +TEST(Integrator, test_integrate) { + double h = 0.1; + void* udata = NULL; + double x; - double state[4] = {0.0, 0.0, 0.0, 0.0}; - double* state_var_p[4] = { &(state[0]), &(state[1]), &(state[2]), &(state[3]) }; - double dt = 0.01; - unsigned int count = 0; - double t = count * dt; - SA::RK2Integrator integ(dt, 4, state_var_p, state_var_p, deriv2, NULL); - while (t < 2.0) { - integ.load(); - integ.step(); - integ.unload(); - count ++; - t = count * dt; - } - EXPECT_NEAR(state[0], 2.0, EXCEPTABLE_ERROR); - EXPECT_NEAR(state[1], 18.0, EXCEPTABLE_ERROR); - EXPECT_NEAR(state[2], 0.0, EXCEPTABLE_ERROR); - EXPECT_NEAR(state[3], 18.0, EXCEPTABLE_ERROR); + SA::Integrator integ( h, udata); + integ.setIndyVar(4.0); + + integ.integrate(); + x = integ.getIndyVar(); + EXPECT_NEAR(x, 4.1, EXCEPTABLE_ERROR); + + integ.integrate(); + x = integ.getIndyVar(); + EXPECT_NEAR(x, 4.2, EXCEPTABLE_ERROR); } -TEST(SAIntegrator_unittest, RungeKutta4_1) { +TEST(Integrator, test_undo_integrate) { + double h = 0.1; + void* udata = NULL; + double x; - double state[4] = {0.0, 0.0, 0.0, 0.0}; - double* state_var_p[4] = { &(state[0]), &(state[1]), &(state[2]), &(state[3]) }; - double dt = 0.01; - unsigned int count = 0; - double t = count * dt; - SA::RK4Integrator integ(dt, 4, state_var_p, state_var_p, deriv4, NULL); - while (t < 2.0) { - integ.load(); - integ.step(); - integ.unload(); - count ++; - t = count * dt; - } - EXPECT_NEAR(state[0], 6.0, EXCEPTABLE_ERROR); - EXPECT_NEAR(state[1], (14.0+2/3.0), EXCEPTABLE_ERROR); - EXPECT_NEAR(state[2], (24+2/3.0), EXCEPTABLE_ERROR); - EXPECT_NEAR(state[3], 20.0, EXCEPTABLE_ERROR); -} - -TEST(SAIntegrator_unittest, RungeKutta38_1) { - - double state[4] = {0.0, 0.0, 0.0, 0.0}; - double* state_var_p[4] = { &(state[0]), &(state[1]), &(state[2]), &(state[3]) }; - double dt = 0.01; - unsigned int count = 0; - double t = count * dt; - SA::RK3_8Integrator integ(dt, 4, state_var_p, state_var_p, deriv4, NULL); - while (t < 2.0) { - integ.load(); - integ.step(); - integ.unload(); - count ++; - t = count * dt; - } - EXPECT_NEAR(state[0], 6.0, EXCEPTABLE_ERROR); - EXPECT_NEAR(state[1], (14.0+2/3.0), EXCEPTABLE_ERROR); - EXPECT_NEAR(state[2], (24+2/3.0), EXCEPTABLE_ERROR); - EXPECT_NEAR(state[3], 20.0, EXCEPTABLE_ERROR); -} - -TEST(SAIntegrator_unittest, EulerIntegrator_undo_step) { - - double state[4] = {0.0, 0.0, 0.0, 0.0}; - double* state_var_p[4] = { &(state[0]), &(state[1]), &(state[2]), &(state[3])}; - double dx = 0.1; - double x; - - SA::EulerIntegrator integ(dx, 4, state_var_p, state_var_p, deriv1, NULL); - integ.load(); - integ.step(); - integ.unload(); - - x = integ.getIndyVar(); - EXPECT_NEAR(state[0], (4.0/10.0), EXCEPTABLE_ERROR); - EXPECT_NEAR(state[1], (-4.0/10.0), EXCEPTABLE_ERROR); - EXPECT_NEAR(state[2], (M_PI/10.0), EXCEPTABLE_ERROR); - EXPECT_NEAR(state[3], (-M_PI/10.0), EXCEPTABLE_ERROR); - EXPECT_NEAR(x, 0.1, EXCEPTABLE_ERROR); - - integ.undo_step(); - - x = integ.getIndyVar(); - EXPECT_NEAR(state[0], 0.0, EXCEPTABLE_ERROR); - EXPECT_NEAR(state[1], 0.0, EXCEPTABLE_ERROR); - EXPECT_NEAR(state[2], 0.0, EXCEPTABLE_ERROR); - EXPECT_NEAR(state[3], 0.0, EXCEPTABLE_ERROR); - EXPECT_NEAR(x, 0.0, EXCEPTABLE_ERROR); - - integ.undo_step(); - - x = integ.getIndyVar(); - EXPECT_NEAR(state[0], 0.0, EXCEPTABLE_ERROR); - EXPECT_NEAR(state[1], 0.0, EXCEPTABLE_ERROR); - EXPECT_NEAR(state[2], 0.0, EXCEPTABLE_ERROR); - EXPECT_NEAR(state[3], 0.0, EXCEPTABLE_ERROR); - EXPECT_NEAR(x, 0.0, EXCEPTABLE_ERROR); - - integ.load(); - integ.step(); - integ.unload(); - - x = integ.getIndyVar(); - EXPECT_NEAR(state[0], (4.0/10.0), EXCEPTABLE_ERROR); - EXPECT_NEAR(state[1], (-4.0/10.0), EXCEPTABLE_ERROR); - EXPECT_NEAR(state[2], (M_PI/10.0), EXCEPTABLE_ERROR); - EXPECT_NEAR(state[3], (-M_PI/10.0), EXCEPTABLE_ERROR); - EXPECT_NEAR(x, 0.1, EXCEPTABLE_ERROR); + SA::Integrator integ( h, udata); + integ.setIndyVar(4.0); + + integ.integrate(); + x = integ.getIndyVar(); + EXPECT_NEAR(x, 4.1, EXCEPTABLE_ERROR); + + integ.undo_integrate(); + x = integ.getIndyVar(); + EXPECT_NEAR(x, 4.0, EXCEPTABLE_ERROR); }