mirror of
https://github.com/nasa/trick.git
synced 2024-12-18 20:57:55 +00:00
Add double integral example to trick_utils/SAIntegrator #1058
This commit is contained in:
parent
64caa968da
commit
fc83dbe6f3
@ -25,6 +25,7 @@ Some examples of using these integrators can be found in the **examples/** direc
|
||||
* [CannonBall](examples/CannonBall/README.md) uses the RK2Integrator.
|
||||
* [MassSpringDamper](examples/MassSpringDamper/README.md) uses the EulerCromerIntegrator.
|
||||
* [Orbit](examples/Orbit/README.md) uses the EulerCromerIntegrator.
|
||||
* [DoubleIntegral](examples/DoubleIntegral/README.md) shows an example of a double integral.
|
||||
|
||||
<a id=class-Integrator></a>
|
||||
## class Integrator
|
||||
@ -252,4 +253,4 @@ SemiImplicitEuler(double dt, int N, double* xp[], double* vp[], derivsFunc gfunc
|
||||
| vp |```double*```|Array of pointers to the variables from which we ```load()``` and to which we ```unload()``` the integrator's velocity values .|
|
||||
| gfunc |[derivsFunc](#typedef-derivsFunc)| A function that returns acceleration |
|
||||
| ffunc |[derivsFunc](#typedef-derivsFunc)| A function that returns velocity |
|
||||
|user_data |```void*```| A pointer to user defined data that will be passed to a derivsFunc when called by the Integrator. |
|
||||
|user_data |```void*```| A pointer to user defined data that will be passed to a derivsFunc when called by the Integrator. |
|
||||
|
@ -0,0 +1,53 @@
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include "SAIntegrator.hh"
|
||||
|
||||
struct IContext {
|
||||
SA::RK2Integrator* integ;
|
||||
double start;
|
||||
double end;
|
||||
};
|
||||
|
||||
void deriv_y( double y, double state_y[], double derivs_y[], void* udata) {
|
||||
double& x = state_y[0];
|
||||
derivs_y[0] = 0.0; // (dx/dy) = 0, Hold x constant.
|
||||
derivs_y[1] = cos(x)*cos(y); // area = ∫ f(X,y) dy
|
||||
}
|
||||
|
||||
void deriv_x( double x, double state_x[], double derivs_x[], void* udata) {
|
||||
IContext* context = (IContext*)udata;
|
||||
double area = 0.0;
|
||||
double* state_y[2] = { &x, &area };
|
||||
SA::RK2Integrator* integ_y = context->integ;
|
||||
integ_y->set_in_vars(state_y);
|
||||
integ_y->set_out_vars(state_y);
|
||||
integ_y->setTime(context->start);
|
||||
while (integ_y->getTime() <= context->end) {
|
||||
integ_y->load();
|
||||
integ_y->step();
|
||||
integ_y->unload();
|
||||
}
|
||||
derivs_x[0] = area; // volume = ∫ area dx
|
||||
}
|
||||
|
||||
double doubleIntegral( double x_start, double x_end, double y_start, double y_end ) {
|
||||
double volume = 0.0;
|
||||
double dx = 0.01;
|
||||
double dy = 0.01;
|
||||
double* state_x[1] = { &volume };
|
||||
SA::RK2Integrator integ_y (dy, 2, NULL, NULL, deriv_y, NULL);
|
||||
IContext y_integ_context = {&integ_y, y_start, y_end};
|
||||
SA::RK2Integrator integ_x (dx, 1, state_x, state_x, deriv_x, &y_integ_context);
|
||||
integ_x.setTime(x_start);
|
||||
while (integ_x.getTime()<=x_end) { // x-end
|
||||
integ_x.load();
|
||||
integ_x.step();
|
||||
integ_x.unload();
|
||||
}
|
||||
return volume;
|
||||
}
|
||||
|
||||
int main ( int argc, char* argv[]) {
|
||||
double vol = doubleIntegral( -M_PI/2.0, M_PI/2.0, -M_PI/2.0, M_PI/2.0 );
|
||||
printf("Volume = %g.\n", vol);
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
# Double Integral
|
||||
|
||||
This is a code example of how one can do a double integral.
|
||||
|
||||
This example code computes the following definate integral :
|
||||
|
||||
![Equation](images/Equation.png)
|
||||
|
||||
using the SA::RK2Integrator, with dx = dy = 0.01
|
||||
|
||||
```
|
||||
$ make
|
||||
$ ./DoubleIntegral
|
||||
Volume = 3.99989.
|
||||
```
|
||||
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
@ -0,0 +1,19 @@
|
||||
|
||||
RM = rm -rf
|
||||
CC = cc
|
||||
CPP = c++
|
||||
|
||||
CXXFLAGS = -g -Wall
|
||||
INCLUDE_DIRS = -I../../include
|
||||
LIBDIR = ../../lib
|
||||
|
||||
all: DoubleIntegral
|
||||
|
||||
DoubleIntegral:
|
||||
$(CPP) $(CXXFLAGS) DoubleIntegral.cpp ${INCLUDE_DIRS} -L${LIBDIR} -lSAInteg -o DoubleIntegral
|
||||
|
||||
clean:
|
||||
${RM} DoubleIntegral.dSYM
|
||||
|
||||
spotless: clean
|
||||
${RM} DoubleIntegral
|
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
data = np.genfromtxt('cannon.csv',
|
||||
delimiter=',',
|
||||
skip_header=1,
|
||||
skip_footer=1,
|
||||
names=['t', 'px', 'py', 'vx', 'vx'],
|
||||
dtype=(float, float, float, float, float)
|
||||
)
|
||||
|
||||
curve1 = plt.plot(data['px'], data['py'], 'C1-')
|
||||
plt.title('Cannonball Trajectory')
|
||||
plt.xlabel('pos-x')
|
||||
plt.ylabel('pos-y')
|
||||
plt.grid(True)
|
||||
plt.show()
|
@ -3,13 +3,16 @@ examples:
|
||||
@make -C CannonBall
|
||||
@make -C MassSpringDamper
|
||||
@make -C Orbit
|
||||
@make -C DoubleIntegral
|
||||
|
||||
clean:
|
||||
@make -C CannonBall clean
|
||||
@make -C MassSpringDamper clean
|
||||
@make -C Orbit clean
|
||||
@make -C DoubleIntegral clean
|
||||
|
||||
spotless:
|
||||
@make -C CannonBall spotless
|
||||
@make -C MassSpringDamper spotless
|
||||
@make -C Orbit spotless
|
||||
@make -C DoubleIntegral spotless
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
namespace SA {
|
||||
|
||||
|
||||
class Integrator {
|
||||
protected:
|
||||
double time;
|
||||
@ -13,6 +13,7 @@ namespace SA {
|
||||
virtual void load() = 0;
|
||||
virtual void unload() = 0;
|
||||
double getTime() {return time;}
|
||||
void setTime(double t) {time = t;}
|
||||
};
|
||||
|
||||
typedef void (*derivsFunc)( double t, double state[], double derivs[], void* user_data);
|
||||
@ -32,10 +33,11 @@ namespace SA {
|
||||
public:
|
||||
FirstOrderODEIntegrator( double dt, int N, double* in_vars[], double* out_vars[], derivsFunc func, void* user_data);
|
||||
~FirstOrderODEIntegrator();
|
||||
// void init(double dt, int N, double* in_vars[], double* out_vars[], derivsFunc func);
|
||||
virtual void undo_step();
|
||||
void load();
|
||||
void unload();
|
||||
void set_in_vars( double* in_vars[]);
|
||||
void set_out_vars( double* out_vars[]);
|
||||
};
|
||||
|
||||
class FirstOrderODEVariableStepIntegrator : public FirstOrderODEIntegrator {
|
||||
|
@ -21,15 +21,29 @@ SA::FirstOrderODEIntegrator::~FirstOrderODEIntegrator() {
|
||||
}
|
||||
void SA::FirstOrderODEIntegrator::load() {
|
||||
reset = false;
|
||||
for (int i=0 ; i<state_size; i++ ) {
|
||||
istate[i] = *(orig_vars[i]);
|
||||
if (orig_vars != NULL) {
|
||||
for (int i=0 ; i<state_size; i++ ) {
|
||||
istate[i] = *(orig_vars[i]);
|
||||
}
|
||||
} else {
|
||||
std::cerr << "Error: SA::FirstOrderODEIntegrator::load(). orig_vars is not set." << std::endl;
|
||||
}
|
||||
}
|
||||
void SA::FirstOrderODEIntegrator::unload() {
|
||||
for (int i=0 ; i<state_size; i++ ) {
|
||||
*(dest_vars[i]) = ostate[i];
|
||||
if (dest_vars != NULL) {
|
||||
for (int i=0 ; i<state_size; i++ ) {
|
||||
*(dest_vars[i]) = ostate[i];
|
||||
}
|
||||
} else {
|
||||
std::cerr << "Error: SA::FirstOrderODEIntegrator::load(). dest_vars is not set." << std::endl;
|
||||
}
|
||||
}
|
||||
void SA::FirstOrderODEIntegrator::set_in_vars( double* in_vars[]){
|
||||
orig_vars = in_vars;
|
||||
}
|
||||
void SA::FirstOrderODEIntegrator::set_out_vars( double* out_vars[]){
|
||||
dest_vars = out_vars;
|
||||
}
|
||||
void SA::FirstOrderODEIntegrator::undo_step() {
|
||||
if (!reset) { // If we've not already reset the integrator, then reset it.
|
||||
for (int i=0 ; i<state_size; i++ ) {
|
||||
|
Loading…
Reference in New Issue
Block a user