Add copy-constructors, assignment operators, insertion operators to SAIntegrator classes. #1091

This commit is contained in:
Penn, John M 047828115 2020-12-17 15:58:29 -06:00
parent 939b3002d1
commit 870e7e9a41
19 changed files with 1587 additions and 289 deletions

View File

@ -13,6 +13,7 @@
* [class RK2Integrator](#class-RK2Integrator)
* [class RK4Integrator](#class-RK4Integrator)
* [class RK3_8Integrator](#class-RK3_8Integrator)
* [typedef Derivs2Func](#typedef-Derivs2Func)
* [class EulerCromerIntegrator](#class-EulerCromerIntegrator)
* [class ABM2Integrator](#class-ABM2Integrator)
* [class ABM4Integrator](#class-ABM4Integrator)
@ -53,10 +54,13 @@ This base-class represents a numerical **integrator**.
|h |```double```| Default integration step-size |
|udata |```void*``` | A pointer to user defined data that will be passed to user-defined functions when called by the Integrator. |
### Destructor
#### ```virtual ~Integrator() {}```
### Public Member Functions
<a id=method-Integrator::step></a>
@ -172,6 +176,15 @@ where:
| derivs_func |[```DerivsFunc```](#typedef-DerivsFunc)| Function thats generates the function (the derivatives) to be integrated. |
|user_data |```void*``` | A pointer to user defined data that will be passed to a DerivsFunc when called by the Integrator. |
In addition to the above constructor, this class provides:
* a copy constructor,
* a destructor,
* an assignment operator,
* an insertion operator,
* the public member functions inherited from [class Integrator](#class-Integrator),
* and the following public member functions:
### Public Member Functions
<a id=method-FirstOrderODEIntegrator::load></a>
@ -307,6 +320,25 @@ Those inherited from [FirstOrderODEIntegrator](#class-FirstOrderODEIntegrator) p
### Constructor
```
FirstOrderODEVariableStepIntegrator( double h,
unsigned int N,
double* in_vars[],
double* out_vars[],
DerivsFunc dfunc,
void* udata);
```
[Constructor Parameters](#FOODEConstructorParameters) are those of [FirstOrderODEIntegrator](#class-FirstOrderODEIntegrator).
In addition to the above constructor, this class provides:
* a copy constructor,
* a destructor,
* an assignment operator,
* an insertion operator,
* the public member functions inherited from [FirstOrderODEIntegrator](#class-FirstOrderODEIntegrator),
* and the following public member functions:
<a id=FirstOrderODEVariableStepIntegrator::publicMemberFunctions></a>
### Public Member Functions
@ -401,6 +433,15 @@ EulerIntegrator( double h,
```
Constructor Parameters are those of [FirstOrderODEVariableStepIntegrator](#class-FirstOrderODEVariableStepIntegrator).
In addition to the above constructor, this class provides:
* a copy constructor,
* a destructor,
* an assignment operator,
* an insertion operator,
* the public member functions inherited from [FirstOrderODEVariableStepIntegrator](#class-FirstOrderODEVariableStepIntegrator),
* and the following public member functions:
### Public Member Functions
* All of the [Public Member Functions of FirstOrderODEVariableStepIntegrator](#FirstOrderODEVariableStepIntegrator::publicMemberFunctions), plus :
@ -434,6 +475,15 @@ HeunsMethod( double h,
```
[Constructor Parameters](#FOODEConstructorParameters) are those of [FirstOrderODEIntegrator](#class-FirstOrderODEIntegrator).
In addition to the above constructor, this class provides:
* a copy constructor,
* a destructor,
* an assignment operator,
* an insertion operator,
* the public member functions inherited from [FirstOrderODEVariableStepIntegrator](#class-FirstOrderODEVariableStepIntegrator),
* and the following public member functions:
### Public Member Functions
* All of the [Public Member Functions of FirstOrderODEVariableStepIntegrator](#FirstOrderODEVariableStepIntegrator::publicMemberFunctions).
@ -463,10 +513,19 @@ RK2Integrator( double h,
double* in_vars[],
double* out_vars[],
DerivsFunc func,
void* user_data)
void* user_data)
```
[Constructor Parameters](#FOODEConstructorParameters) are those of [FirstOrderODEIntegrator](#class-FirstOrderODEIntegrator).
In addition to the above constructor, this class provides:
* a copy constructor,
* a destructor,
* an assignment operator,
* an insertion operator,
* the public member functions inherited from [FirstOrderODEVariableStepIntegrator](#class-FirstOrderODEVariableStepIntegrator),
* and the following public member functions:
### Public Member Functions
* All of the [Public Member Functions of FirstOrderODEVariableStepIntegrator](#FirstOrderODEVariableStepIntegrator::publicMemberFunctions).
@ -501,6 +560,15 @@ RK4Integrator( double h,
```
[Constructor Parameters](#FOODEConstructorParameters) are those of [FirstOrderODEIntegrator](#class-FirstOrderODEIntegrator).
In addition to the above constructor, this class provides:
* a copy constructor,
* a destructor,
* an assignment operator,
* an insertion operator,
* the public member functions inherited from [FirstOrderODEVariableStepIntegrator](#class-FirstOrderODEVariableStepIntegrator),
* and the following public member functions:
### Public Member Functions
* All of the [Public Member Functions of FirstOrderODEVariableStepIntegrator](#FirstOrderODEVariableStepIntegrator::publicMemberFunctions).
@ -535,6 +603,15 @@ RK3_8Integrator( double h,
[Constructor Parameters](#FOODEConstructorParameters) are those of
[FirstOrderODEIntegrator](#class-FirstOrderODEIntegrator).
In addition to the above constructor, this class provides:
* a copy constructor,
* a destructor,
* an assignment operator,
* an insertion operator,
* the public member functions inherited from [FirstOrderODEVariableStepIntegrator](#class-FirstOrderODEVariableStepIntegrator),
* and the following public member functions:
### Public Member Functions
* All of the [Public Member Functions of FirstOrderODEVariableStepIntegrator](#FirstOrderODEVariableStepIntegrator::publicMemberFunctions).
@ -567,6 +644,14 @@ ABM2Integrator ( double h,
```
[Constructor Parameters](#FOODEConstructorParameters) are those of [FirstOrderODEIntegrator](#class-FirstOrderODEIntegrator).
In addition to the above constructor, this class provides:
* a copy constructor,
* a destructor,
* an assignment operator,
* an insertion operator,
* the public member functions inherited from [[FirstOrderODEIntegrator](#class-FirstOrderODEIntegrator).
<a id=class-ABM4Integrator></a>
## class ABM4Integrator
Derived from [FirstOrderODEIntegrator](#class-FirstOrderODEIntegrator).
@ -589,6 +674,44 @@ ABM4Integrator ( double h,
[Constructor Parameters](#FOODEConstructorParameters) are those of [FirstOrderODEIntegrator](#class-FirstOrderODEIntegrator).
In addition to the above constructor, this class provides:
* a copy constructor,
* a destructor,
* an assignment operator,
* an insertion operator,
* the public member functions inherited from [FirstOrderODEIntegrator](#class-FirstOrderODEIntegrator).
<a id=typedef-Derivs2Func></a>
## typedef Derivs2Func
### Description
This typedef defines a type of C/C++ function whose purpose is to populate
an array of accelerations, given velocities and positions.
```
typedef void (*Derivs2Func)( double t, double x[], double v[], double a[], void* udata);
```
where:
|Parameter|Type |Direction|Description|
|---------|-------------|---------|-----------|
|t |```double``` |IN |Independent variable.|
|x |```double*```|IN |Array of position values.|
|v |```double*```|IN |Array of velocity values.|
|a |```double*```|OUT |Array into which accelerations are to be returned.|
|udata |```void*``` |IN |Pointer to user_data.|
#### Example
```
void G( double t, double x[], double v[], double g_out[], void* udata) {
MassSpringDamper* msd = (MassSpringDamper*)udata;
g_out[0] = -(msd->k/msd->mass) * x[0]
-(msd->c/msd->mass) * v[0];
}
```
<a id=class-EulerCromerIntegrator></a>
## class EulerCromerIntegrator
Derived from [Integrator](#class-Integrator).
@ -596,6 +719,12 @@ Derived from [Integrator](#class-Integrator).
### Description
EulerCromer is integration method that conserves energy in oscillatory systems better than Runge-Kutta. So, it's good for mass-spring-damper systems, and orbital systems.
It calculates the next state, from the current state as follows:
![EulerCromerEqs](images/EulerCromerEqs.png)
**a(v(n), x(n), t)** [above] is the function of type [```Derivs2Func```](#typedef-Derivs2Func) below.
### Data Members
Those inherited from [Integrator](#class-Integrator) plus:
@ -609,9 +738,9 @@ Those inherited from [Integrator](#class-Integrator) plus:
| pos_out |```double*``` |Protected|Position output array.|
| vel_out |```double*``` |Protected|Velocity output array.|
| g_out |```double*``` |Protected|Array of accelerations returned from gderivs.|
| f_out |```double*``` |Protected|Array of velocities returned from fderivs.|
| gderivs |[```DerivsFunc```](#typedef-DerivsFunc)|Protected|A function that returns accelerations.|
| fderivs |[```DerivsFunc```](#typedef-DerivsFunc)|Protected|A function that returns velocities.|
| gderivs |[```Derivs2Func```](#typedef-Derivs2Func)|Protected|A function that returns accelerations.|
| last_h |```double```|Value of h used in the last integration step.|
### Constructor
```
@ -619,8 +748,7 @@ EulerCromerIntegrator(double dt,
int N,
double* xp[],
double* vp[],
DerivsFunc gfunc,
DerivsFunc ffunc,
Derivs2Func gfunc,
void* user_data)
```
@ -630,10 +758,17 @@ EulerCromerIntegrator(double dt,
| N |```int``` |Sets nDimensions above.|
| xp |```double*```|Sets pos_p above.|
| vp |```double*```|Sets vel_p above.|
| gfunc |[```DerivsFunc```](#typedef-DerivsFunc)| Sets gderivs above. |
| ffunc |[```DerivsFunc```](#typedef-DerivsFunc)| Sets fderivs above. |
| gfunc |[```Derivs2Func```](#typedef-Derivs2Func)| Sets gderivs above. |
|user_data |```void*``` | Sets Integrator::user_data. |
In addition to the above constructor, this class provides:
* a copy constructor,
* a destructor,
* an assignment operator,
* an insertion operator,
* the public member functions inherited from [Integrator](#class-Integrator).
### Public Member Functions
#### ```void step( double dt)```

View File

@ -48,10 +48,7 @@ int main ( int argc, char* argv[]) {
double dt = 0.01;
double t = 0.0;
SA::RK2Integrator integ(dt, 6, state_var_p, state_var_p, calc_derivs, NULL);
RootFinder root_finder(0.00000000001, Negative);
integ.add_Rootfinder(&root_finder, &impact);
integ.add_Rootfinder(0.00000000001, Negative, &impact);
init_state(cannon);
print_header();
print_state( t, cannon);

View File

@ -13,7 +13,7 @@ void init_state ( MassSpringDamper& msd ) {
msd.pos = 2.0;
msd.vel = 0.0;
msd.k = 1.0;
msd.c = 0.0;
msd.c = 0.2;
msd.mass = 5.0;
}
void print_header() {
@ -22,31 +22,24 @@ void print_header() {
void print_state( double t, MassSpringDamper& msd ) {
printf ("%10.10f, %10.10f, %10.10f\n", t, msd.pos, msd.vel);
}
void G( double t, double x[], double g_out[], void* udata) {
void G( double t, double x[], double v[], double g_out[], void* udata) {
MassSpringDamper* msd = (MassSpringDamper*)udata;
g_out[0] = -(msd->k/msd->mass) * x[0];
}
void F( double t, double v[], double f_out[], void* udata) {
f_out[0] = v[0];
f_out[1] = v[1];
g_out[0] = -(msd->k/msd->mass) * x[0]
-(msd->c/msd->mass) * v[0];
}
int main ( int argc, char* argv[]) {
MassSpringDamper msd;
double time = 0.0;
double* x_p[N_DIMENSIONS] = { &msd.pos };
double* v_p[N_DIMENSIONS] = { &msd.vel };
unsigned count = 0;
double dt = 0.001;
double time = count * dt;
init_state(msd);
print_header();
print_state(time, msd);
SA::EulerCromerIntegrator integ(dt, N_DIMENSIONS, x_p, v_p, G, F, &msd);
SA::EulerCromerIntegrator integ(dt, N_DIMENSIONS, x_p, v_p, G, &msd);
while (time < 50) {
integ.load();
integ.step();
integ.unload();
count ++;
time = count * dt;
integ.integrate();
time = integ.getIndyVar();
print_state(time, msd);
}
}

View File

@ -25,33 +25,25 @@ void print_state( double t, Orbit& orbit ) {
printf ("%10.10f, %10.10f, %10.10f, %10.10f, %10.10f\n",
t, orbit.pos[0], orbit.pos[1], orbit.vel[0], orbit.vel[1]);
}
void G( double t, double x[], double g_out[], void* udata) {
void G( double t, double pos[], double vel[], double acc_out[], void* udata) {
Orbit* orbit = (Orbit*)udata;
double d = sqrt( x[0]*x[0] + x[1]*x[1]);
g_out[0] = -x[0] * GRAVITATIONAL_CONSTANT * orbit->planet_mass / (d*d*d);
g_out[1] = -x[1] * GRAVITATIONAL_CONSTANT * orbit->planet_mass / (d*d*d);
}
void F( double t, double v[], double f_out[], void* udata) {
f_out[0] = v[0];
f_out[1] = v[1];
double d = sqrt( pos[0]*pos[0] + pos[1]*pos[1]);
acc_out[0] = -pos[0] * GRAVITATIONAL_CONSTANT * orbit->planet_mass / (d*d*d);
acc_out[1] = -pos[1] * GRAVITATIONAL_CONSTANT * orbit->planet_mass / (d*d*d);
}
int main ( int argc, char* argv[]) {
Orbit orbit;
double time = 0.0;
double* x_p[2] = { &orbit.pos[0], &orbit.pos[1] };
double* v_p[2] = { &orbit.vel[0], &orbit.vel[1] };
unsigned count = 0;
double dt = 0.1;
double time = count * dt;
init_state(orbit);
print_header();
print_state(time, orbit);
SA::EulerCromerIntegrator integ(dt, 2, x_p, v_p, G, F, &orbit);
while (time < 6000) {
integ.load();
integ.step();
integ.unload();
count ++;
time = count * dt;
SA::EulerCromerIntegrator integ(dt, 2, x_p, v_p, G, &orbit);
while (time < 5600) {
integ.integrate();
time = integ.getIndyVar();
print_state(time, orbit);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -1,3 +1,4 @@
#include <iostream>
typedef enum {
Negative = -1,
@ -12,6 +13,7 @@ class RootFinder {
RootFinder();
RootFinder (double tolerance, SlopeConstraint constraint);
double find_roots( double x, double f_error );
friend std::ostream& operator<<(std::ostream& os, const RootFinder& rf);
private:
double f_upper;
double x_upper;

View File

@ -1,4 +1,6 @@
#include "Rootfinder.hh"
#include <iostream>
namespace SA {
class Integrator {
@ -9,7 +11,8 @@ namespace SA {
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) {};
Integrator();
Integrator(double h, void* udata);
virtual ~Integrator() {}
virtual void load();
virtual void unload();
@ -18,8 +21,11 @@ namespace SA {
virtual double undo_integrate();
double getIndyVar();
void setIndyVar(double v);
friend std::ostream& operator<<(std::ostream& os, const SA::Integrator& I);
};
std::ostream& operator<<(std::ostream& os, const Integrator& I);
typedef void (*DerivsFunc)( double x, double state[], double derivs[], void* udata);
class FirstOrderODEIntegrator : public Integrator {
@ -30,21 +36,23 @@ 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.
// void advanceIndyVar(); // Inherited from Integrator::advanceIndyVar()
public:
FirstOrderODEIntegrator( double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata);
FirstOrderODEIntegrator();
FirstOrderODEIntegrator( double h, unsigned int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata);
FirstOrderODEIntegrator(const FirstOrderODEIntegrator& other);
FirstOrderODEIntegrator& operator=( const FirstOrderODEIntegrator& other);
virtual ~FirstOrderODEIntegrator();
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);
friend std::ostream& operator<<(std::ostream& os, const SA::FirstOrderODEIntegrator& I);
};
std::ostream& operator<<(std::ostream& os, const FirstOrderODEIntegrator& I);
typedef double (*RootErrorFunc)( double x, double state[], RootFinder* root_finder, void* udata);
@ -54,82 +62,96 @@ namespace SA {
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();
FirstOrderODEVariableStepIntegrator( double h, unsigned int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata);
FirstOrderODEVariableStepIntegrator( const FirstOrderODEVariableStepIntegrator& other);
FirstOrderODEVariableStepIntegrator& operator=( const FirstOrderODEVariableStepIntegrator& rhs);
~FirstOrderODEVariableStepIntegrator();
// 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
void add_Rootfinder( double tolerance, SlopeConstraint constraint, RootErrorFunc rfunc);
friend std::ostream& operator<<(std::ostream& os, const SA::FirstOrderODEVariableStepIntegrator& I);
private:
void find_roots(double h, unsigned int depth);
};
std::ostream& operator<<(std::ostream& os, const FirstOrderODEVariableStepIntegrator& I);
class EulerIntegrator : public FirstOrderODEVariableStepIntegrator {
public:
double *derivs;
EulerIntegrator( double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata);
EulerIntegrator();
EulerIntegrator( double h, unsigned int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata);
EulerIntegrator(const EulerIntegrator& other);
EulerIntegrator& operator=( const EulerIntegrator& rhs);
~EulerIntegrator();
// 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
void variable_step( double h);
friend std::ostream& operator<<(std::ostream& os, const SA::EulerIntegrator& I);
};
std::ostream& operator<<(std::ostream& os, const EulerIntegrator& I);
class HeunsMethod : public FirstOrderODEVariableStepIntegrator {
public:
double *wstate;
double *derivs[2];
HeunsMethod( double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata);
HeunsMethod();
HeunsMethod( double h, unsigned int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata);
HeunsMethod(const HeunsMethod& other);
HeunsMethod& operator=( const HeunsMethod& rhs);
~HeunsMethod();
void variable_step( double h); // Overrides FirstOrderODEVariableStepIntegrator::variable_step()
void variable_step( double h);
friend std::ostream& operator<<(std::ostream& os, const SA::HeunsMethod& I);
};
std::ostream& operator<<(std::ostream& os, const HeunsMethod& I);
class RK2Integrator : public FirstOrderODEVariableStepIntegrator {
public:
double *wstate;
double *derivs[2];
RK2Integrator( double h, int N, double* in_vars[], double* out_vars[], DerivsFunc derivs_func, void* udata);
RK2Integrator();
RK2Integrator( double h, unsigned int N, double* in_vars[], double* out_vars[], DerivsFunc derivs_func, void* udata);
RK2Integrator(const RK2Integrator& other);
RK2Integrator& operator=( const RK2Integrator& rhs);
~RK2Integrator();
void variable_step( double h); // Overrides FirstOrderODEVariableStepIntegrator::variable_step()
void variable_step( double h);
friend std::ostream& operator<<(std::ostream& os, const SA::RK2Integrator& I);
};
std::ostream& operator<<(std::ostream& os, const RK2Integrator& I);
class RK4Integrator : public FirstOrderODEVariableStepIntegrator {
public:
double *wstate[3];
double *derivs[4];
RK4Integrator( double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata);
RK4Integrator();
RK4Integrator( double h, unsigned int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata);
RK4Integrator(const RK4Integrator& other);
RK4Integrator& operator=( const RK4Integrator& rhs);
~RK4Integrator();
void variable_step( double h); // Overrides FirstOrderODEVariableStepIntegrator::variable_step()
void variable_step( double h);
friend std::ostream& operator<<(std::ostream& os, const SA::RK4Integrator& I);
};
std::ostream& operator<<(std::ostream& os, const RK4Integrator& I);
class RK3_8Integrator : public FirstOrderODEVariableStepIntegrator {
public:
double *wstate[4];
double *wstate[3];
double *derivs[4];
RK3_8Integrator( double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata);
RK3_8Integrator();
RK3_8Integrator( double h, unsigned int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata);
RK3_8Integrator(const RK3_8Integrator& other);
RK3_8Integrator& operator=( const RK3_8Integrator& rhs);
~RK3_8Integrator();
void variable_step( double h); // Overrides FirstOrderODEVariableStepIntegrator::variable_step()
void variable_step( double h);
friend std::ostream& operator<<(std::ostream& os, const SA::RK3_8Integrator& I);
};
std::ostream& operator<<(std::ostream& os, const RK3_8Integrator& I);
typedef void (*Derivs2Func)( double t, double x[], double v[], double derivs[], void* udata);
class EulerCromerIntegrator : public Integrator {
protected:
@ -141,19 +163,24 @@ namespace SA {
double* pos_out;
double* vel_out;
double* g_out;
double* f_out;
DerivsFunc gderivs;
DerivsFunc fderivs;
double last_h;
Derivs2Func gderivs;
public:
EulerCromerIntegrator(double dt, int N, double* xp[], double* vp[], DerivsFunc g, DerivsFunc f , void* udata);
EulerCromerIntegrator();
EulerCromerIntegrator(double dt, unsigned int N, double* xp[], double* vp[], Derivs2Func g, void* udata);
EulerCromerIntegrator(const EulerCromerIntegrator& other);
EulerCromerIntegrator& operator=( const EulerCromerIntegrator& rhs);
~EulerCromerIntegrator();
void advanceIndyVar(double h);
void step( double dt);
void step();
void load();
void unload();
double undo_integrate();
friend std::ostream& operator<<(std::ostream& os, const SA::EulerCromerIntegrator& I);
};
std::ostream& operator<<(std::ostream& os, const EulerCromerIntegrator& I);
// AdamsBashforthMoulton Self Priming
class ABMIntegrator : public FirstOrderODEIntegrator {
@ -165,11 +192,15 @@ namespace SA {
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(unsigned int history_size, double h, unsigned int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata);
ABMIntegrator(const ABMIntegrator& other);
ABMIntegrator& operator=( const ABMIntegrator& rhs);
~ABMIntegrator();
void step();
double undo_integrate();
friend std::ostream& operator<<(std::ostream& os, const ABMIntegrator& I);
};
std::ostream& operator<<(std::ostream& os, const ABMIntegrator& I);
// AdamsBashforthMoulton 2 with RK2 Priming
class ABM2Integrator : public FirstOrderODEIntegrator {
@ -179,13 +210,17 @@ namespace SA {
unsigned int bufferSize;
unsigned int hix;
unsigned int currentHistorySize;
FirstOrderODEVariableStepIntegrator* priming_integrator;
RK2Integrator* priming_integrator;
public:
ABM2Integrator( double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata);
ABM2Integrator( double h, unsigned int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata);
ABM2Integrator(const ABM2Integrator& other);
ABM2Integrator& operator=( const ABM2Integrator& rhs);
~ABM2Integrator();
void step();
double undo_integrate();
friend std::ostream& operator<<(std::ostream& os, const ABM2Integrator& I);
};
std::ostream& operator<<(std::ostream& os, const ABM2Integrator& I);
// AdamsBashforthMoulton 4 with RK4 Priming
class ABM4Integrator : public FirstOrderODEIntegrator {
@ -195,11 +230,15 @@ namespace SA {
unsigned int bufferSize;
unsigned int hix;
unsigned int currentHistorySize;
FirstOrderODEVariableStepIntegrator* priming_integrator;
RK4Integrator* priming_integrator;
public:
ABM4Integrator( double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata);
ABM4Integrator( double h, unsigned int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata);
ABM4Integrator(const ABM4Integrator& other);
ABM4Integrator& operator=( const ABM4Integrator& rhs);
~ABM4Integrator();
void step();
double undo_integrate();
friend std::ostream& operator<<(std::ostream& os, const ABM4Integrator& I);
};
std::ostream& operator<<(std::ostream& os, const ABM4Integrator& I);
}

View File

@ -14,12 +14,18 @@ void RootFinder::init( double tolerance, SlopeConstraint constraint) {
void RootFinder::init() {
init(0.00000000001, Unconstrained);
}
RootFinder::RootFinder (double tolerance, SlopeConstraint constraint) {
init(tolerance, constraint);
}
// Default Constructor
RootFinder::RootFinder () {
init();
}
// Constructor
RootFinder::RootFinder (double tolerance, SlopeConstraint constraint) {
init(tolerance, constraint);
}
// Copy Constructor: The default copy_constructor should suffice.
// Assignment Operator: The default assignment operator should suffice.
// Destructor: The default destructor should suffice.
// Given the values of the independent variable, and the function,
// estimate the distance of the independent variable from functions root.
double RootFinder::find_roots( double x, double f_error ) {
@ -86,3 +92,15 @@ double RootFinder::find_roots( double x, double f_error ) {
iterations = 0;
return (DBL_MAX);
}
std::ostream& operator<<(std::ostream& os, const RootFinder& rf) {
os << "\n--- RootFinder ---";
os << "\nupper: {" << rf.f_upper << ',' << rf.x_upper << ',' << rf.upper_set << "}";
os << "\nlower: {" << rf.f_lower << ',' << rf.x_lower << ',' << rf.lower_set << "}";
os << "\nprev_f_error: " << rf.prev_f_error;
os << "\nf_error_tol:" << rf.prev_f_error;
os << "\niterations:" << rf.prev_f_error;
os << "\nslope_constraint:" << rf.slope_constraint;
os << "\nf_slope:" << rf.f_slope;
return os;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,86 @@
#include <gtest/gtest.h>
#include <iostream>
#include "SAIntegrator.hh"
#include <math.h>
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(EulerIntegrator_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, 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);
}

View File

@ -156,4 +156,65 @@ TEST(FirstOrderODEIntegrator_unittest, test_4) {
double x = integ.getIndyVar();
EXPECT_NEAR(x, 0.6, EXCEPTABLE_ERROR);
}
TEST(FirstOrderODEIntegrator_unittest, test_copy_constructor) {
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 integ1( h, N, varptrs, varptrs, calc_derivs, NULL);
// Do an integration step to change array values to non-zero.
integ1.integrate();
// Use the copy-constructor to create create a duplicate FirstOrderODEIntegrator.
SA::FirstOrderODEIntegrator integ2(integ1);
// We don't want to unload integ1 here because it will then effect integ2,
// since both are pointing to the same input/output arrays.
integ1.load(); integ1.step();
integ2.load(); integ2.step();
// Create a text representation for each of the FirstOrderODEIntegrators.
std::stringstream ss1;
std::stringstream ss2;
ss1 << integ1 << std::endl;
ss2 << integ2 << std::endl;
// Compare the text representations. They should be identical.
int result = ss1.str().compare(ss2.str());
EXPECT_EQ(result, 0);
}
TEST(FirstOrderODEIntegrator_unittest, test_assignment_operator) {
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 integ1( h, N, varptrs, varptrs, calc_derivs, NULL);
// Do an integration step to change array values to non-zero.
integ1.integrate();
// Use the assignment-operator to create a duplicate FirstOrderODEIntegrator.
SA::FirstOrderODEIntegrator integ2 = integ1;
// We don't want to unload integ1 here because it will then effect integ2,
// since both are pointing to the same input/output arrays.
integ1.load(); integ1.step();
integ2.load(); integ2.step();
// Create a text representation for each of the FirstOrderODEIntegrators.
std::stringstream ss1;
std::stringstream ss2;
ss1 << integ1 << std::endl;
ss2 << integ2 << std::endl;
// Compare the text representations. They should be identical.
int result = ss1.str().compare(ss2.str());
EXPECT_EQ(result, 0);
}

View File

@ -38,69 +38,6 @@ void deriv1( double t __attribute__((unused)),
#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};
@ -108,11 +45,11 @@ TEST(FirstOrderODEVariableStepIntegrator_unittest, RungeKutta38_1) {
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);
SA::RK3_8Integrator integ1(dt, 4, state_var_p, state_var_p, deriv4, NULL);
while (t < 2.0) {
integ.load();
integ.step();
integ.unload();
integ1.load();
integ1.step();
integ1.unload();
count ++;
t = count * dt;
}
@ -120,53 +57,17 @@ TEST(FirstOrderODEVariableStepIntegrator_unittest, RungeKutta38_1) {
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);
// Use the copy-constructor to create create a duplicate RK3_8Integrator.
SA::RK3_8Integrator integ2(integ1);
// Create a text representation for each of the RK3_8Integrator.
std::stringstream ss1;
std::stringstream ss2;
ss1 << integ1 << std::endl;
ss2 << integ2 << std::endl;
// Compare the text representations. They should be identical.
int result = ss1.str().compare(ss2.str());
EXPECT_EQ(result, 0);
}

View File

@ -13,12 +13,25 @@ SAI_LIBOBJS = ${SAI_OBJDIR}/Integrator.o
LIBDIRS = -L${SAI_LIBDIR} -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib
TEST_PROGRAMS = SAIntegrator_unittest\
FirstOrderODEIntegrator_unittest\
FirstOrderODEVariableStepIntegrator_unittest\
EulerIntegrator_unittest\
RK2Integrator_unittest\
RK4Integrator_unittest\
RK3_8Integrator_unittest\
RootFinder_unittest
all: test
test: SAIntegrator_unittest FirstOrderODEIntegrator_unittest FirstOrderODEVariableStepIntegrator_unittest RootFinder_unittest
test: $(TEST_PROGRAMS)
./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
./EulerIntegrator_unittest --gtest_output=xml:${TRICK_HOME}/trick_test/EulerIntegrator_unittest.xml
./RK2Integrator_unittest --gtest_output=xml:${TRICK_HOME}/trick_test/RK2Integrator_unittest.xml
./RK4Integrator_unittest --gtest_output=xml:${TRICK_HOME}/trick_test/RK4Integrator_unittest.xml
./RK3_8Integrator_unittest --gtest_output=xml:${TRICK_HOME}/trick_test/RK3_8Integrator_unittest.xml
./RootFinder_unittest --gtest_output=xml:${TRICK_HOME}/trick_test/RootFinder_unittest.xml
SAIntegrator_unittest.o : SAIntegrator_unittest.cc
@ -38,7 +51,31 @@ FirstOrderODEVariableStepIntegrator_unittest.o : FirstOrderODEVariableStepIntegr
FirstOrderODEVariableStepIntegrator_unittest : ${SAI_LIBDIR}/${SAI_LIBNAME} FirstOrderODEVariableStepIntegrator_unittest.o
$(TRICK_CXX) $(TRICK_CPPFLAGS) -o $@ $^ ${LIBDIRS} -lSAInteg -lgtest -lgtest_main -lpthread
# ====
EulerIntegrator_unittest.o : EulerIntegrator_unittest.cc
$(TRICK_CXX) $(TRICK_CPPFLAGS) $(INCLUDE_DIRS) -c $<
EulerIntegrator_unittest : ${SAI_LIBDIR}/${SAI_LIBNAME} EulerIntegrator_unittest.o
$(TRICK_CXX) $(TRICK_CPPFLAGS) -o $@ $^ ${LIBDIRS} -lSAInteg -lgtest -lgtest_main -lpthread
# ====
RK2Integrator_unittest.o : RK2Integrator_unittest.cc
$(TRICK_CXX) $(TRICK_CPPFLAGS) $(INCLUDE_DIRS) -c $<
RK2Integrator_unittest : ${SAI_LIBDIR}/${SAI_LIBNAME} RK2Integrator_unittest.o
$(TRICK_CXX) $(TRICK_CPPFLAGS) -o $@ $^ ${LIBDIRS} -lSAInteg -lgtest -lgtest_main -lpthread
# ====
RK4Integrator_unittest.o : RK4Integrator_unittest.cc
$(TRICK_CXX) $(TRICK_CPPFLAGS) $(INCLUDE_DIRS) -c $<
RK4Integrator_unittest : ${SAI_LIBDIR}/${SAI_LIBNAME} RK4Integrator_unittest.o
$(TRICK_CXX) $(TRICK_CPPFLAGS) -o $@ $^ ${LIBDIRS} -lSAInteg -lgtest -lgtest_main -lpthread
# ====
RK3_8Integrator_unittest.o : RK3_8Integrator_unittest.cc
$(TRICK_CXX) $(TRICK_CPPFLAGS) $(INCLUDE_DIRS) -c $<
RK3_8Integrator_unittest : ${SAI_LIBDIR}/${SAI_LIBNAME} RK3_8Integrator_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 $<
@ -52,4 +89,11 @@ clean:
${RM} *.o
spotless: clean
${RM} SAIntegrator_unittest
${RM} FirstOrderODEIntegrator_unittest
${RM} FirstOrderODEVariableStepIntegrator_unittest
${RM} EulerIntegrator_unittest
${RM} RK2Integrator_unittest
${RM} RK4Integrator_unittest
${RM} RK3_8Integrator_unittest
${RM} RootFinder_unittest

View File

@ -0,0 +1,116 @@
#include <gtest/gtest.h>
#include <iostream>
#include "SAIntegrator.hh"
#include <math.h>
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;
}
#define EXCEPTABLE_ERROR 0.00000000001
TEST(RK2Integrator_unittest, test_load_step_unload) {
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 integ1(dt, 4, state_var_p, state_var_p, deriv2, NULL);
while (t < 2.0) {
integ1.load();
integ1.step();
integ1.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(RK2Integrator_unittest, test_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 dt = 0.01;
unsigned int count = 0;
double t = count * dt;
SA::RK2Integrator integ1(dt, 4, state_var_p, state_var_p, deriv2, NULL);
while (t < 2.0) {
integ1.integrate();
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(RK2Integrator_unittest, copy_constructor) {
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 integ1(dt, 4, state_var_p, state_var_p, deriv2, NULL);
while (t < 2.0) {
integ1.integrate();
count ++;
t = count * dt;
}
// Use the copy-constructor to create create a duplicate RK2Integrator.
SA::RK2Integrator integ2(integ1);
// Create a text representation for each of the RK2Integrators.
std::stringstream ss1;
std::stringstream ss2;
ss1 << integ1 << std::endl;
ss2 << integ2 << std::endl;
// Compare the text representations. They should be identical.
int result = ss1.str().compare(ss2.str());
EXPECT_EQ(result, 0);
}
TEST(RK2Integrator_unittest, assignment_operator) {
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 integ1(dt, 4, state_var_p, state_var_p, deriv2, NULL);
while (t < 2.0) {
integ1.integrate();
count ++;
t = count * dt;
}
// Use the assignment operator to create create a duplicate RK2Integrator.
SA::RK2Integrator integ2;
integ2 = integ1;
// Create a text representation for each of the RK2Integrators.
std::stringstream ss1;
std::stringstream ss2;
ss1 << integ1 << std::endl;
ss2 << integ2 << std::endl;
// Compare the text representations. They should be identical.
int result = ss1.str().compare(ss2.str());
EXPECT_EQ(result, 0);
}

View File

@ -0,0 +1,52 @@
#include <gtest/gtest.h>
#include <iostream>
#include "SAIntegrator.hh"
#include <math.h>
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;
}
#define EXCEPTABLE_ERROR 0.00000000001
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 integ1(dt, 4, state_var_p, state_var_p, deriv4, NULL);
while (t < 2.0) {
integ1.load();
integ1.step();
integ1.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);
// Use the copy-constructor to create create a duplicate RK3_8Integrator.
SA::RK3_8Integrator integ2(integ1);
// Create a text representation for each of the RK3_8Integrator.
std::stringstream ss1;
std::stringstream ss2;
ss1 << integ1 << std::endl;
ss2 << integ2 << std::endl;
// Compare the text representations. They should be identical.
int result = ss1.str().compare(ss2.str());
EXPECT_EQ(result, 0);
}

View File

@ -0,0 +1,52 @@
#include <gtest/gtest.h>
#include <iostream>
#include "SAIntegrator.hh"
#include <math.h>
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;
}
#define EXCEPTABLE_ERROR 0.00000000001
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 integ1(dt, 4, state_var_p, state_var_p, deriv4, NULL);
while (t < 2.0) {
integ1.load();
integ1.step();
integ1.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);
// Use the copy-constructor to create create a duplicate RK4Integrator.
SA::RK4Integrator integ2(integ1);
// Create a text representation for each of the RK4Integrator.
std::stringstream ss1;
std::stringstream ss2;
ss1 << integ1 << std::endl;
ss2 << integ2 << std::endl;
// Compare the text representations. They should be identical.
int result = ss1.str().compare(ss2.str());
EXPECT_EQ(result, 0);
}

View File

@ -78,3 +78,12 @@ TEST(RootFinder_unittest, Negative_constraint_with_positive_slope_function) {
root_error = root_finder->find_roots(9, func_positive_slope(9));
EXPECT_NEAR(root_error, DBL_MAX, EXCEPTABLE_ERROR);
}
TEST(RootFinder_unittest, serialize) {
RootFinder* root_finder = new RootFinder ( 0.00000000001, Negative );
double root_error;
root_error = root_finder->find_roots(8, func_positive_slope(8));
EXPECT_NEAR(root_error, DBL_MAX, EXCEPTABLE_ERROR);
root_error = root_finder->find_roots(9, func_positive_slope(9));
EXPECT_NEAR(root_error, DBL_MAX, EXCEPTABLE_ERROR);
}

View File

@ -72,3 +72,35 @@ TEST(Integrator, test_undo_integrate) {
x = integ.getIndyVar();
EXPECT_NEAR(x, 4.0, EXCEPTABLE_ERROR);
}
TEST(Integrator, test_copy_constructor) {
std::stringstream ss1;
std::stringstream ss2;
double h = 0.1;
void* udata = NULL;
SA::Integrator integ( h, udata);
integ.setIndyVar(4.0);
integ.integrate();
// Test Copy Constructor
SA::Integrator integ2(integ);
ss1 << integ << std::endl;
ss2 << integ2 << std::endl;
int result = ss1.str().compare(ss2.str());
EXPECT_EQ(result, 0);
}
TEST(Integrator, test_assignment_operator) {
std::stringstream ss1;
std::stringstream ss2;
double h = 0.1;
void* udata = NULL;
SA::Integrator integ( h, udata);
integ.setIndyVar(4.0);
integ.integrate();
// Test Copy Constructor
SA::Integrator integ2 = integ;
ss1 << integ << std::endl;
ss2 << integ2 << std::endl;
int result = ss1.str().compare(ss2.str());
EXPECT_EQ(result, 0);
}