diff --git a/trick_source/trick_utils/SAIntegrator/README.md b/trick_source/trick_utils/SAIntegrator/README.md
index 3159a145..15e74572 100644
--- a/trick_source/trick_utils/SAIntegrator/README.md
+++ b/trick_source/trick_utils/SAIntegrator/README.md
@@ -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
@@ -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
@@ -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:
+
### 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).
+
## 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).
+
+
+
+## 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];
+}
+```
+
## 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)```
diff --git a/trick_source/trick_utils/SAIntegrator/examples/CannonBall/CannonBall.cpp b/trick_source/trick_utils/SAIntegrator/examples/CannonBall/CannonBall.cpp
index 05a0d80a..a896b8a3 100644
--- a/trick_source/trick_utils/SAIntegrator/examples/CannonBall/CannonBall.cpp
+++ b/trick_source/trick_utils/SAIntegrator/examples/CannonBall/CannonBall.cpp
@@ -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);
diff --git a/trick_source/trick_utils/SAIntegrator/examples/MassSpringDamper/MassSpringDamper.cpp b/trick_source/trick_utils/SAIntegrator/examples/MassSpringDamper/MassSpringDamper.cpp
index a1aa2fc8..e207b6f0 100644
--- a/trick_source/trick_utils/SAIntegrator/examples/MassSpringDamper/MassSpringDamper.cpp
+++ b/trick_source/trick_utils/SAIntegrator/examples/MassSpringDamper/MassSpringDamper.cpp
@@ -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);
}
}
diff --git a/trick_source/trick_utils/SAIntegrator/examples/MassSpringDamper/plot_position.py b/trick_source/trick_utils/SAIntegrator/examples/MassSpringDamper/plot_position.py
old mode 100644
new mode 100755
diff --git a/trick_source/trick_utils/SAIntegrator/examples/Orbit/Orbit.cpp b/trick_source/trick_utils/SAIntegrator/examples/Orbit/Orbit.cpp
index 85c56f0b..e68c7d29 100644
--- a/trick_source/trick_utils/SAIntegrator/examples/Orbit/Orbit.cpp
+++ b/trick_source/trick_utils/SAIntegrator/examples/Orbit/Orbit.cpp
@@ -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);
}
}
diff --git a/trick_source/trick_utils/SAIntegrator/images/EulerCromerEqs.png b/trick_source/trick_utils/SAIntegrator/images/EulerCromerEqs.png
new file mode 100644
index 00000000..dfa52e31
Binary files /dev/null and b/trick_source/trick_utils/SAIntegrator/images/EulerCromerEqs.png differ
diff --git a/trick_source/trick_utils/SAIntegrator/include/Rootfinder.hh b/trick_source/trick_utils/SAIntegrator/include/Rootfinder.hh
index 43e01425..327d0e0c 100644
--- a/trick_source/trick_utils/SAIntegrator/include/Rootfinder.hh
+++ b/trick_source/trick_utils/SAIntegrator/include/Rootfinder.hh
@@ -1,3 +1,4 @@
+#include
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;
diff --git a/trick_source/trick_utils/SAIntegrator/include/SAIntegrator.hh b/trick_source/trick_utils/SAIntegrator/include/SAIntegrator.hh
index 30153ab1..41e148c4 100644
--- a/trick_source/trick_utils/SAIntegrator/include/SAIntegrator.hh
+++ b/trick_source/trick_utils/SAIntegrator/include/SAIntegrator.hh
@@ -1,4 +1,6 @@
#include "Rootfinder.hh"
+#include
+
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);
}
diff --git a/trick_source/trick_utils/SAIntegrator/src/RootFinder.cpp b/trick_source/trick_utils/SAIntegrator/src/RootFinder.cpp
index d3044dee..3fd0f62b 100644
--- a/trick_source/trick_utils/SAIntegrator/src/RootFinder.cpp
+++ b/trick_source/trick_utils/SAIntegrator/src/RootFinder.cpp
@@ -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;
+}
diff --git a/trick_source/trick_utils/SAIntegrator/src/SAIntegrator.cpp b/trick_source/trick_utils/SAIntegrator/src/SAIntegrator.cpp
index f93ecedb..3232c65d 100644
--- a/trick_source/trick_utils/SAIntegrator/src/SAIntegrator.cpp
+++ b/trick_source/trick_utils/SAIntegrator/src/SAIntegrator.cpp
@@ -1,8 +1,33 @@
#include
-#include
+#include
+#include // std::cout, std::cerr
+#include // std::copy
#include "SAIntegrator.hh"
+static void nil_dfunc( double x,
+ double state[] __attribute__((unused)),
+ double derivs[],
+ void* udata __attribute__((unused))) {
+ derivs[0] = 0.0;
+}
+static void nil_gfunc( double t,
+ double x[] __attribute__((unused)),
+ double v[] __attribute__((unused)),
+ double derivs[],
+ void* udata __attribute__((unused))) {
+ derivs[0] = 0.0;
+}
+// ------------------------------------------------------------
+// Class Integrator
+// ------------------------------------------------------------
+// Default Constructor
+SA::Integrator::Integrator()
+: X_in(0.0), X_out(0.0), default_h(1.0), user_data(NULL) {};
+// Constructor
+SA::Integrator::Integrator(double h, void* udata)
+: X_in(0.0), X_out(0.0), default_h(h), user_data(udata) {};
+
void SA::Integrator::advanceIndyVar() {
X_out = X_in + default_h;
}
@@ -30,21 +55,80 @@ double SA::Integrator::getIndyVar() {
void SA::Integrator::setIndyVar(double v) {
X_out = v;
}
+// Insertion Operator
+std::ostream& SA::operator<<(std::ostream& os, const Integrator& I) {
+ os << "\n--- Integrator ---";
+ os << "\nX_in : " << I.X_in;
+ os << "\nX_out : " << I.X_out;
+ os << "\ndefault_h : " << I.default_h;
+ os << "\nuser_data : " << I.user_data;
+ return os;
+}
// ------------------------------------------------------------
+// Class FirstOrderODEIntegrator
+// ------------------------------------------------------------
+// Default Constructor
+SA::FirstOrderODEIntegrator::FirstOrderODEIntegrator()
+: Integrator() {
+ state_size = 0;
+ inVars = NULL;
+ outVars = NULL;
+ inState = new double[state_size];
+ outState = new double[state_size];
+ derivs_func = nil_dfunc;
+}
+// Constructor
SA::FirstOrderODEIntegrator::FirstOrderODEIntegrator(
- double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata)
+ double h, unsigned int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata)
: Integrator(h, udata) {
state_size = N;
inVars = in_vars;
outVars = out_vars;
inState = new double[state_size];
outState = new double[state_size];
+ if (dfunc == NULL) throw std::invalid_argument("dfunc must be non-NULL.");
derivs_func = dfunc;
}
+// Copy Constructor
+SA::FirstOrderODEIntegrator::FirstOrderODEIntegrator(const FirstOrderODEIntegrator& other)
+: Integrator(other) {
+ state_size = other.state_size;
+ inVars = other.inVars;
+ outVars = other.outVars;
+ inState = new double[state_size];
+ std::copy( other.inState, other.inState + state_size, inState);
+ outState = new double[state_size];
+ std::copy( other.outState, other.outState + state_size, outState);
+ derivs_func = other.derivs_func;
+}
+// Assignment Operator
+SA::FirstOrderODEIntegrator& SA::FirstOrderODEIntegrator::operator=( const SA::FirstOrderODEIntegrator& rhs) {
+ if (this != &rhs) {
+ // Call base assignment operator
+ Integrator::operator=(rhs);
+ // Duplicate rhs arrays
+ double* new_inState = new double[rhs.state_size];
+ std::copy( rhs.inState, rhs.inState + rhs.state_size, new_inState);
+ double* new_outState = new double[rhs.state_size];
+ std::copy( rhs.outState, rhs.outState + rhs.state_size, new_outState);
+ // Delete lhs arrays & replace with rhs arrays
+ if (inState != NULL) delete inState;
+ inState = new_inState;
+ if (outState != NULL) delete outState;
+ outState = new_outState;
+ // Copy primitive members
+ state_size = rhs.state_size;
+ inVars = rhs.inVars;
+ outVars = rhs.outVars;
+ derivs_func = rhs.derivs_func;
+ }
+ return *this;
+}
+// Destructor
SA::FirstOrderODEIntegrator::~FirstOrderODEIntegrator() {
- delete inState;
- delete outState;
+ if (inState != NULL) delete inState;
+ if (outState != NULL) delete outState;
}
void SA::FirstOrderODEIntegrator::load() {
if (inVars != NULL) {
@@ -82,13 +166,16 @@ double** SA::FirstOrderODEIntegrator::set_out_vars( double* out_vars[]){
return (ret);
}
double SA::FirstOrderODEIntegrator::undo_integrate() {
- for (unsigned int i=0 ; i " << *(I.root_finder);
+ }
+ return os;
+}
// ------------------------------------------------------------
+// Class EulerIntegrator
+// ------------------------------------------------------------
+// Default Constructor
+SA::EulerIntegrator::EulerIntegrator()
+: FirstOrderODEVariableStepIntegrator() {
+ derivs = new double[state_size];
+}
+// Constructor
SA::EulerIntegrator::EulerIntegrator(
- double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata)
+ double h, unsigned int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata)
: FirstOrderODEVariableStepIntegrator(h, N, in_vars, out_vars, dfunc, udata) {
derivs = new double[N];
}
+// Copy Constructor
+SA::EulerIntegrator::EulerIntegrator(const EulerIntegrator& other)
+ : FirstOrderODEVariableStepIntegrator(other) {
+ derivs = new double[state_size];
+ std::copy( other.derivs, other.derivs + state_size, derivs);
+}
+// Assignment Operator
+SA::EulerIntegrator& SA::EulerIntegrator::operator=( const SA::EulerIntegrator& rhs) {
+ if (this != &rhs) {
+ double* new_derivs = 0;
+ try {
+ new_derivs = new double[rhs.state_size];
+ } catch (...) {
+ delete new_derivs;
+ throw;
+ }
+ FirstOrderODEVariableStepIntegrator::operator=(rhs);
+ if (derivs != NULL) delete derivs;
+ derivs = new_derivs;
+ std::copy( rhs.derivs, rhs.derivs + state_size, derivs);
+ }
+ return *this;
+}
+//Destructor
SA::EulerIntegrator::~EulerIntegrator() {
- delete derivs;
+ if (derivs != NULL) delete derivs;
}
void SA::EulerIntegrator::variable_step( double h) {
(*derivs_func)( X_in, inState, derivs, user_data);
@@ -168,19 +367,72 @@ void SA::EulerIntegrator::variable_step( double h) {
}
advanceIndyVar(h);
}
+// Insertion Operator
+std::ostream& SA::operator<<(std::ostream& os, const EulerIntegrator& I) {
+ os << (SA::FirstOrderODEVariableStepIntegrator)I;
+ os << "\n--- EulerIntegrator ---";
+ os << "\nderivs :";
+ stream_double_array(os, I.state_size, I.derivs);
+ return os;
+}
// ------------------------------------------------------------
+// Class HeunsMethod
+// ------------------------------------------------------------
+// Default Constructor
+SA::HeunsMethod::HeunsMethod()
+: FirstOrderODEVariableStepIntegrator() {
+ wstate = new double[state_size];
+ for (unsigned int i = 0; i < 2 ; i++) {
+ derivs[i] = new double[state_size];
+ }
+}
+// Constructor
SA::HeunsMethod::HeunsMethod(
- double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata)
+ double h, unsigned int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata)
: FirstOrderODEVariableStepIntegrator(h, N, in_vars, out_vars, dfunc, udata) {
wstate = new double[N];
for (unsigned int i = 0; i < 2 ; i++) {
derivs[i] = new double[N];
}
}
+// Copy Constructor
+SA::HeunsMethod::HeunsMethod(const HeunsMethod& other)
+ : FirstOrderODEVariableStepIntegrator(other) {
+ wstate = new double[state_size];
+ std::copy(other.wstate, other.wstate+state_size, wstate);
+ for (unsigned int i=0 ; i<2; i++ ) {
+ derivs[i] = new double[state_size];
+ std::copy(other.derivs[i], other.derivs[i]+state_size, derivs[i]);
+ }
+}
+// Assignment Operator
+SA::HeunsMethod& SA::HeunsMethod::operator=( const SA::HeunsMethod& rhs) {
+ if (this != &rhs) {
+ // Call base assignment operator
+ FirstOrderODEVariableStepIntegrator::operator=(rhs);
+ // Duplicate rhs arrays
+ double* new_wstate = new double[rhs.state_size];
+ std::copy(rhs.wstate, rhs.wstate + rhs.state_size, new_wstate);
+ double* new_derivs[2];
+ for (unsigned int i=0 ; i<2; i++ ) {
+ new_derivs[i] = new double[rhs.state_size];
+ std::copy(rhs.derivs[i], rhs.derivs[i] + rhs.state_size, new_derivs[i]);
+ }
+ // Delete lhs arrays & replace with rhs arrays
+ if (wstate != NULL) delete wstate;
+ wstate = new_wstate;
+ for (unsigned int i=0 ; i<2; i++ ) {
+ if (derivs[i] != NULL) delete derivs[i];
+ derivs[i] = new_derivs[i];
+ }
+ }
+ return *this;
+}
+// Destructor
SA::HeunsMethod::~HeunsMethod() {
- delete wstate;
+ if (wstate != NULL) delete wstate;
for (unsigned int i = 0; i < 2 ; i++) {
- delete derivs[i];
+ if (derivs[i] != NULL) delete derivs[i];
}
}
void SA::HeunsMethod::variable_step( double h) {
@@ -194,19 +446,78 @@ void SA::HeunsMethod::variable_step( double h) {
}
advanceIndyVar(h);
}
+// Insertion Operator
+std::ostream& SA::operator<<(std::ostream& os, const HeunsMethod& I) {
+ os << (SA::FirstOrderODEVariableStepIntegrator)I;
+ os << "\n--- HeunsMethod ---";
+ os << "\nderivs :[";
+ for (int i=0; i<2 ; i++) {
+ os << "\n";
+ stream_double_array(os, I.state_size, I.derivs[i]);
+ }
+ os << "\n]";
+ os << "\nwstate :";
+ stream_double_array(os, I.state_size, I.wstate);
+ return os;
+}
// ------------------------------------------------------------
+// Class RK2Integrator
+// ------------------------------------------------------------
+// Default Constructor
+SA::RK2Integrator::RK2Integrator()
+ : FirstOrderODEVariableStepIntegrator() {
+ wstate = new double[state_size];
+ for (unsigned int i = 0; i < 2 ; i++) {
+ derivs[i] = new double[state_size];
+ }
+}
+// Constructor
SA::RK2Integrator::RK2Integrator(
- double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata)
+ double h, unsigned int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata)
: FirstOrderODEVariableStepIntegrator(h, N, in_vars, out_vars, dfunc, udata) {
wstate = new double[N];
for (unsigned int i = 0; i < 2 ; i++) {
derivs[i] = new double[N];
}
}
+// Copy Constructor
+SA::RK2Integrator::RK2Integrator(const RK2Integrator& other)
+ : FirstOrderODEVariableStepIntegrator(other) {
+ wstate = new double[state_size];
+ std::copy(other.wstate, other.wstate+state_size, wstate);
+ for (unsigned int i=0 ; i<2; i++ ) {
+ derivs[i] = new double[state_size];
+ std::copy(other.derivs[i], other.derivs[i]+state_size, derivs[i]);
+ }
+}
+// Assignment Operator
+SA::RK2Integrator& SA::RK2Integrator::operator=( const SA::RK2Integrator& rhs) {
+ if (this != &rhs) {
+ // Call base assignment operator
+ FirstOrderODEVariableStepIntegrator::operator=(rhs);
+ // Duplicate rhs arrays
+ double* new_wstate = new double[rhs.state_size];
+ std::copy(rhs.wstate, rhs.wstate + rhs.state_size, new_wstate);
+ double* new_derivs[2];
+ for (unsigned int i=0 ; i<2; i++ ) {
+ new_derivs[i] = new double[rhs.state_size];
+ std::copy(rhs.derivs[i], rhs.derivs[i] + rhs.state_size, new_derivs[i]);
+ }
+ // Delete lhs arrays & replace with rhs arrays
+ if (wstate != NULL) delete wstate;
+ wstate = new_wstate;
+ for (unsigned int i=0 ; i<2; i++ ) {
+ if (derivs[i] != NULL) delete derivs[i];
+ derivs[i] = new_derivs[i];
+ }
+ }
+ return *this;
+}
+// Destructor
SA::RK2Integrator::~RK2Integrator() {
- delete (wstate);
+ if (wstate != NULL) delete (wstate);
for (unsigned int i = 0; i < 2 ; i++) {
- delete derivs[i];
+ if (derivs[i] != NULL) delete derivs[i];
}
}
void SA::RK2Integrator::variable_step( double h) {
@@ -220,9 +531,36 @@ void SA::RK2Integrator::variable_step( double h) {
}
advanceIndyVar(h);
}
+// Insertion Operator
+std::ostream& SA::operator<<(std::ostream& os, const RK2Integrator& I) {
+ os << (SA::FirstOrderODEVariableStepIntegrator)I;
+ os << "\n--- RK2Integrator ---";
+ os << "\nderivs :[";
+ for (int i=0; i<2 ; i++) {
+ os << "\n";
+ stream_double_array(os, I.state_size, I.derivs[i]);
+ }
+ os << "\n]";
+ os << "\nwstate :";
+ stream_double_array(os, I.state_size, I.wstate);
+ return os;
+}
// ------------------------------------------------------------
+// Class RK4Integrator
+// ------------------------------------------------------------
+// Default Constructor
+SA::RK4Integrator::RK4Integrator()
+ : FirstOrderODEVariableStepIntegrator() {
+ for (unsigned int i = 0; i < 3 ; i++) {
+ wstate[i] = new double[state_size];
+ }
+ for (unsigned int i = 0; i < 4 ; i++) {
+ derivs[i] = new double[state_size];
+ }
+}
+// Constructor
SA::RK4Integrator::RK4Integrator(
- double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata)
+ double h, unsigned int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata)
: FirstOrderODEVariableStepIntegrator(h, N, in_vars, out_vars, dfunc, udata) {
for (unsigned int i = 0; i < 3 ; i++) {
wstate[i] = new double[N];
@@ -231,12 +569,53 @@ SA::RK4Integrator::RK4Integrator(
derivs[i] = new double[N];
}
}
+// Copy Constructor
+SA::RK4Integrator::RK4Integrator(const RK4Integrator& other)
+ : FirstOrderODEVariableStepIntegrator(other) {
+ for (unsigned int i=0 ; i<3; i++ ) {
+ wstate[i] = new double[state_size];
+ std::copy(other.wstate[i], other.wstate[i]+state_size, wstate[i]);
+ }
+ for (unsigned int i=0 ; i<4; i++ ) {
+ derivs[i] = new double[state_size];
+ std::copy(other.derivs[i], other.derivs[i]+state_size, derivs[i]);
+ }
+}
+// Assignment Operator
+SA::RK4Integrator& SA::RK4Integrator::operator=( const SA::RK4Integrator& rhs) {
+ if (this != &rhs) {
+ // Call base assignment operator
+ FirstOrderODEVariableStepIntegrator::operator=(rhs);
+ // Duplicate rhs arrays
+ double* new_wstate[3];
+ for (unsigned int i=0 ; i<3; i++ ) {
+ new_wstate[i] = new double[rhs.state_size];
+ std::copy(rhs.wstate[i], rhs.wstate[i] + rhs.state_size, new_wstate[i]);
+ }
+ double* new_derivs[4];
+ for (unsigned int i=0 ; i<4; i++ ) {
+ new_derivs[i] = new double[rhs.state_size];
+ std::copy(rhs.derivs[i], rhs.derivs[i]+ rhs.state_size, new_derivs[i]);
+ }
+ // Delete lhs arrays & replace with rhs arrays
+ for (unsigned int i=0 ; i<3; i++ ) {
+ if (wstate[i] != NULL) delete wstate[i];
+ wstate[i] = new_wstate[i];
+ }
+ for (unsigned int i=0 ; i<4; i++ ) {
+ if (derivs[i] != NULL) delete derivs[i];
+ derivs[i] = new_derivs[i];
+ }
+ }
+ return *this;
+}
+// Destructor
SA::RK4Integrator::~RK4Integrator() {
for (unsigned int i = 0; i < 3 ; i++) {
- delete (wstate[i]);
+ if (wstate[i] != NULL) delete (wstate[i]);
}
for (unsigned int i = 0; i < 4 ; i++) {
- delete (derivs[i]);
+ if (derivs[i] != NULL) delete (derivs[i]);
}
}
void SA::RK4Integrator::variable_step( double h) {
@@ -261,9 +640,40 @@ void SA::RK4Integrator::variable_step( double h) {
}
advanceIndyVar(h);
}
+// Insertion Operator
+std::ostream& SA::operator<<(std::ostream& os, const RK4Integrator& I) {
+ os << (SA::FirstOrderODEVariableStepIntegrator)I;
+ os << "\n--- RK4Integrator ---";
+ os << "\nderivs :[";
+ for (int i=0; i<4 ; i++) {
+ os << "\n";
+ stream_double_array(os, I.state_size, I.derivs[i]);
+ }
+ os << "\n]";
+ os << "\nwstate :[";
+ for (int i=0; i<3 ; i++) {
+ os << "\n";
+ stream_double_array(os, I.state_size, I.wstate[i]);
+ }
+ os << "\n]";
+ return os;
+}
// ------------------------------------------------------------
+// Class RK3_8Integrator
+// ------------------------------------------------------------
+// Default Constructor
+SA::RK3_8Integrator::RK3_8Integrator()
+ : FirstOrderODEVariableStepIntegrator() {
+ for (unsigned int i = 0; i < 3 ; i++) {
+ wstate[i] = new double[state_size];
+ }
+ for (unsigned int i = 0; i < 4 ; i++) {
+ derivs[i] = new double[state_size];
+ }
+}
+// Constructor
SA::RK3_8Integrator::RK3_8Integrator(
- double h, int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata)
+ double h, unsigned int N, double* in_vars[], double* out_vars[], DerivsFunc dfunc, void* udata)
: FirstOrderODEVariableStepIntegrator(h, N, in_vars, out_vars ,dfunc, udata) {
for (unsigned int i = 0; i < 3 ; i++) {
wstate[i] = new double[N];
@@ -272,12 +682,53 @@ SA::RK3_8Integrator::RK3_8Integrator(
derivs[i] = new double[N];
}
}
+// Copy Constructor
+SA::RK3_8Integrator::RK3_8Integrator(const RK3_8Integrator& other)
+ : FirstOrderODEVariableStepIntegrator(other) {
+ for (unsigned int i=0 ; i<3; i++ ) {
+ wstate[i] = new double[state_size];
+ std::copy(other.wstate[i], other.wstate[i]+state_size, wstate[i]);
+ }
+ for (unsigned int i=0 ; i<4; i++ ) {
+ derivs[i] = new double[state_size];
+ std::copy(other.derivs[i], other.derivs[i]+state_size, derivs[i]);
+ }
+}
+// Assignment Operator
+SA::RK3_8Integrator& SA::RK3_8Integrator::operator=( const SA::RK3_8Integrator& rhs) {
+ if (this != &rhs) {
+ // Call base assignment operator
+ FirstOrderODEVariableStepIntegrator::operator=(rhs);
+ // Duplicate rhs arrays
+ double* new_wstate[3];
+ for (unsigned int i=0 ; i<3; i++ ) {
+ new_wstate[i] = new double[rhs.state_size];
+ std::copy(rhs.wstate[i], rhs.wstate[i] + rhs.state_size, new_wstate[i]);
+ }
+ double* new_derivs[4];
+ for (unsigned int i=0 ; i<4; i++ ) {
+ new_derivs[i] = new double[rhs.state_size];
+ std::copy(rhs.derivs[i], rhs.derivs[i] + rhs.state_size, new_derivs[i]);
+ }
+ // Delete lhs arrays & replace with rhs arrays
+ for (unsigned int i=0 ; i<3; i++ ) {
+ if (wstate[i] != NULL) delete wstate[i];
+ wstate[i] = new_wstate[i];
+ }
+ for (unsigned int i=0 ; i<4; i++ ) {
+ if (derivs[i] != NULL) delete derivs[i];
+ derivs[i] = new_derivs[i];
+ }
+ }
+ return *this;
+}
+// Destructor
SA::RK3_8Integrator::~RK3_8Integrator() {
for (unsigned int i = 0; i < 3 ; i++) {
- delete (wstate[i]);
+ if (wstate[i] != NULL) delete (wstate[i]);
}
for (unsigned int i = 0; i < 4 ; i++) {
- delete (derivs[i]);
+ if (derivs[i] != NULL) delete (derivs[i]);
}
}
void SA::RK3_8Integrator::variable_step( double h) {
@@ -302,73 +753,194 @@ void SA::RK3_8Integrator::variable_step( double h) {
}
advanceIndyVar(h);
}
+// Insertion Operator
+std::ostream& SA::operator<<(std::ostream& os, const RK3_8Integrator& I) {
+ os << (SA::FirstOrderODEVariableStepIntegrator)I;
+ os << "\n--- RK3_8Integrator ---";
+ os << "\nderivs :[";
+ for (int i=0; i<4 ; i++) {
+ os << "\n";
+ stream_double_array(os, I.state_size, I.derivs[i]);
+ }
+ os << "\n]";
+ os << "\nwstate :[";
+ for (int i=0; i<3 ; i++) {
+ os << "\n";
+ stream_double_array(os, I.state_size, I.wstate[i]);
+ }
+ os << "\n]";
+ return os;
+}
+
// ------------------------------------------------------------
+// Class EulerCromerIntegrator
+// ------------------------------------------------------------
+// Default Constructor
+SA::EulerCromerIntegrator::EulerCromerIntegrator()
+ :Integrator() {
+ nDimensions = 1;
+ last_h = 0.0;
+ pos_p = NULL;
+ pos_in = new double[nDimensions];
+ pos_out = new double[nDimensions];
+ vel_p = NULL;
+ vel_in = new double[nDimensions];
+ vel_out = new double[nDimensions];
+ g_out = new double[nDimensions];
+ gderivs = nil_gfunc;
+}
+// Constructor
SA::EulerCromerIntegrator::EulerCromerIntegrator(
- double dt, int N, double* xp[], double* vp[], DerivsFunc gfunc, DerivsFunc ffunc, void* udata)
+ double dt, unsigned int N, double* xp[], double* vp[], Derivs2Func gfunc, void* udata)
:Integrator(dt, udata) {
nDimensions = N;
- pos_p = new double*[N];
+ last_h = 0.0;
+ pos_p = xp;
pos_in = new double[N];
pos_out = new double[N];
- vel_p = new double*[N];
+ vel_p = vp;
vel_in = new double[N];
vel_out = new double[N];
g_out = new double[N];
- f_out = new double[N];
-
- for (int i=0 ; i 5)) {
+ throw std::invalid_argument("history_size must be in the range [1..5].");
+ }
algorithmHistorySize=history_size; // The amount of history that we intend to use in this ABM integrator.
bufferSize=algorithmHistorySize+1; // The size of the buffer needs to be one more than the history so that an integration step can be reset.
hix=0;
@@ -399,6 +977,51 @@ SA::ABMIntegrator::ABMIntegrator ( int history_size, double h, int N, double* in
}
composite_deriv = new double[state_size];
}
+// Copy Constructor
+SA::ABMIntegrator::ABMIntegrator(const ABMIntegrator& other)
+: FirstOrderODEIntegrator(other) {
+ bufferSize = other.bufferSize;
+ algorithmHistorySize = other.algorithmHistorySize;
+ hix = other.hix;
+ currentHistorySize = other.currentHistorySize;
+ deriv_history = new double*[bufferSize];
+ for (unsigned int i=0; i
+#include
+#include "SAIntegrator.hh"
+#include
+
+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);
+}
diff --git a/trick_source/trick_utils/SAIntegrator/unittest/FirstOrderODEIntegrator_unittest.cc b/trick_source/trick_utils/SAIntegrator/unittest/FirstOrderODEIntegrator_unittest.cc
index 022358f8..e617b80d 100644
--- a/trick_source/trick_utils/SAIntegrator/unittest/FirstOrderODEIntegrator_unittest.cc
+++ b/trick_source/trick_utils/SAIntegrator/unittest/FirstOrderODEIntegrator_unittest.cc
@@ -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);
}
diff --git a/trick_source/trick_utils/SAIntegrator/unittest/FirstOrderODEVariableStepIntegrator_unittest.cc b/trick_source/trick_utils/SAIntegrator/unittest/FirstOrderODEVariableStepIntegrator_unittest.cc
index 14675eac..5f5b56e1 100644
--- a/trick_source/trick_utils/SAIntegrator/unittest/FirstOrderODEVariableStepIntegrator_unittest.cc
+++ b/trick_source/trick_utils/SAIntegrator/unittest/FirstOrderODEVariableStepIntegrator_unittest.cc
@@ -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);
}
diff --git a/trick_source/trick_utils/SAIntegrator/unittest/Makefile b/trick_source/trick_utils/SAIntegrator/unittest/Makefile
index 1a078d94..c67a288a 100644
--- a/trick_source/trick_utils/SAIntegrator/unittest/Makefile
+++ b/trick_source/trick_utils/SAIntegrator/unittest/Makefile
@@ -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
diff --git a/trick_source/trick_utils/SAIntegrator/unittest/RK2Integrator_unittest.cc b/trick_source/trick_utils/SAIntegrator/unittest/RK2Integrator_unittest.cc
new file mode 100644
index 00000000..604589fd
--- /dev/null
+++ b/trick_source/trick_utils/SAIntegrator/unittest/RK2Integrator_unittest.cc
@@ -0,0 +1,116 @@
+#include
+#include
+#include "SAIntegrator.hh"
+#include
+
+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);
+}
diff --git a/trick_source/trick_utils/SAIntegrator/unittest/RK3_8Integrator_unittest.cc b/trick_source/trick_utils/SAIntegrator/unittest/RK3_8Integrator_unittest.cc
new file mode 100644
index 00000000..a2e6e433
--- /dev/null
+++ b/trick_source/trick_utils/SAIntegrator/unittest/RK3_8Integrator_unittest.cc
@@ -0,0 +1,52 @@
+#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;
+}
+
+#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);
+}
diff --git a/trick_source/trick_utils/SAIntegrator/unittest/RK4Integrator_unittest.cc b/trick_source/trick_utils/SAIntegrator/unittest/RK4Integrator_unittest.cc
new file mode 100644
index 00000000..9c319282
--- /dev/null
+++ b/trick_source/trick_utils/SAIntegrator/unittest/RK4Integrator_unittest.cc
@@ -0,0 +1,52 @@
+#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;
+}
+
+#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);
+}
diff --git a/trick_source/trick_utils/SAIntegrator/unittest/RootFinder_unittest.cc b/trick_source/trick_utils/SAIntegrator/unittest/RootFinder_unittest.cc
index 7ac35dbe..bb0cd33a 100644
--- a/trick_source/trick_utils/SAIntegrator/unittest/RootFinder_unittest.cc
+++ b/trick_source/trick_utils/SAIntegrator/unittest/RootFinder_unittest.cc
@@ -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);
+}
diff --git a/trick_source/trick_utils/SAIntegrator/unittest/SAIntegrator_unittest.cc b/trick_source/trick_utils/SAIntegrator/unittest/SAIntegrator_unittest.cc
index 96c2a0d9..0088a56f 100644
--- a/trick_source/trick_utils/SAIntegrator/unittest/SAIntegrator_unittest.cc
+++ b/trick_source/trick_utils/SAIntegrator/unittest/SAIntegrator_unittest.cc
@@ -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);
+}