Take a look at the following transfer function:
With Matlab Simulink:
The result is
In State-space representation, the system can be modeled as follows:
In Matlab, we can model the system in the state-space representation:
which yields the following plot:
which is exactly the result generated by using transfer function. I'm trying to generate same results with odeint but failed. This is the code
#include <iostream>
#include <Eigen/Dense>
#include <boost/numeric/odeint.hpp>
#include <iomanip>
#include <fstream>
using namespace std;
using namespace boost::numeric::odeint;
typedef std::vector< double > state_type;
void equations(const state_type &y, state_type &dy, double x)
{
Eigen::MatrixXd A(3, 3), B(3,1);
/*
x = y[0]
dx = y[1] = dy[0]
ddx = y[2] = dy[1]
dddx = dy[2]
*/
const double r(1);
A << 0, 1, 0,
0, 0, 1,
-24, -26, -9;
B << 0, 0, 1;
//#####################( ODE Equations )################################
Eigen::MatrixXd X(3, 1), dX(3,1);
X << y[0], y[1], y[2];
dX = A*X + B*r;
dy[0] = dX(0,0);
dy[1] = dX(1,0);
dy[2] = dX(2,0);
}
int main(int argc, char **argv)
{
const double dt = 0.01;
runge_kutta_dopri5 < state_type > stepper;
state_type y(3);
// initial values
y[0] = 0.0; // x1
y[1] = 0.0; // x2
y[2] = 0.0; // x3
ofstream data("file.txt");
for (double t(0.0); t <= 5.0; t += dt){
data << t << " " << 2*y[0] << " " << 7*y[1] << " " << 1*y[2] << std::endl;
stepper.do_step(equations, y, t, dt);
}
return 0;
}
And this is the result for all state vector
None of the preceding variables match the results generated by Matlab. Any suggestions to fix this code?
Look at the expression you have for y. When you multiply a 1x3 matrix with a 3x1 matrix, the result should be a 1x1 matrix, where the value of the single element is the dot product of the two matrices. What you're currently doing is element-wise multiplication when you write to data instead of calculating the dot product.
Related
I'm new in the world of C++ and I'm having some trouble with the boost library. In my problem I want to solve a ODE-System with 5 equations. It isn't a stiff problem. As iterative method I used both integreate(rhs, x0, t0, tf, size_step, write_output) and integreate_adaptive(stepper, sys, x0, t0, tf, size_step, write_output). Both these method actually integrate the equations but giving me non-sense results changing the size of the step from 0.001 to 5 almost randomly. The equations and data are correct. What can I do to fix this problem? Here is the code:
#include <iostream>
#include <vector>
#include <boost/numeric/odeint.hpp>
#include <fstream>
#include <boost/array.hpp>
using namespace std;
using namespace boost::numeric::odeint;
//DATA
double Lin = 20000; // kg/h
double Gdry = 15000; // kg/h
double P = 760; // mmHg
double TinH2O = 50; // °C
double ToutH2O = 25; // °C
double Tinair = 20; // °C
double Z = 0.5; // relative humidity
double Cu = 0.26; // kcal/kg*K
double CpL = 1; // kcal/kg*K
double DHev = 580; // kcal/kg
double hga = 4000; // kcal/m/h/K
double hla = 30000; // kcal/m/h/K
double A = -49.705; // Pev 1st coeff mmHg vs °C
double B = 2.71; // Pev 2nd coeff mmHg vs °C
double Usair = 0.62*(A + B*Tinair) / P;
double Uair = Z*Usair;
double Kua = hga / Cu;
double L0 = 19292; // kg/h
typedef vector< double > state_type;
vector <double> pack_height;
vector <double> Umidity;
vector <double> T_liquid;
vector <double> T_gas;
vector <double> Liquid_flow;
vector <double> Gas_flow;
void rhs(const state_type& x , state_type& dxdt , const double z )
{// U Tl Tg L G
double Ti = (hla*x[1] + hga*x[2] + Kua*DHev*(x[0] - 0.62*A / P)) / (hla + hga + Kua*DHev*0.62*B / P);
double Ui = 0.62*(A + B*Ti) / P;
dxdt[0] = Kua*(Ui - x[0]) / Gdry / 100;
dxdt[1] = hla*(x[1] - Ti) / x[3] / CpL / 100;
dxdt[2] = hga*(Ti - x[2]) / Gdry / Cu / 100;
dxdt[3] = Kua*(Ui - x[0]) / 100;
dxdt[4] = Kua*(Ui - x[0]) / 100;
}
void write_output(const state_type& x, const double z)
{
pack_height.push_back(z);
Umidity.push_back(x[0]);
T_liquid.push_back(x[1]);
T_gas.push_back(x[2]);
Liquid_flow.push_back(x[3]);
Gas_flow.push_back(x[4]);
cout << z << " " << x[0] << " " << x[1] << " " << x[2] << " " << x[3] << " " << x[4] << endl;
}
int main()
{
state_type x(5);
x[0] = Uair;
x[1] = ToutH2O;
x[2] = Tinair;
x[3] = L0;
x[4] = Gdry;
double z0 = 0.0;
double zf = 5.5;
double stepsize = 0.001;
integrate( rhs , x , z0 , zf , stepsize , write_output );
return 0;
}
And this is the final results that i get from the prompt:
0 0.00183349 25 20 19292 15000
0.001 0.00183356 25 20 19292 15000
0.0055 0.0018339 25.0002 20.0001 19292 15000
0.02575 0.00183542 25.001 20.0007 19292 15000
0.116875 0.00184228 25.0046 20.003 19292.1 15000.1
0.526938 0.00187312 25.0206 20.0135 19292.6 15000.6
2.37222 0.00201203 25.0928 20.0608 19294.7 15002.7
5.5 0.00224788 25.2155 20.142 19298.2 15006.2
Only the first iteration has the right-asked stepsize.. and obiviously the solution is not the right one.. what can i do? Thank you in advance. :)
If you read the documentation, then you will find that the constant step-size routines are integrate_const and integrate_n_steps, or possibly integrate_adaptive with a non-controlled stepper.
The short call to integrate uses the standard dopri5 stepper with adaptive step size, so that the changing step size is no surprise. You could possibly use the dense output of the stepper to interpolate values at equidistant times.
I'm trying to write a very simple C++ program which outputs a lookup table with the corresponding x and y values of sinus function. The code that I wrote is the following:
#include "stdafx.h"
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
double hw = 4.0;
int nsteps = 30;
const double PI = 3.14159;
const double maxx = hw * PI;
const double deltax = maxx / nsteps;
double x = 0.0;
for (int i = 0; i < nsteps; i++) {
const double f = sin(x);
cerr << x << "\t" << f << endl;
x = x + deltax;
}
return 0;
}
Now the program is working, but my problem is, that the values are not getting aligned properly as showed in the following picture
So is there any way, to achieve that the second column of the values will actually be a column and all the values are aligned at the same position? What could I use instead of \t?
The above answer provides an incorrect solution because the alignment is not set correctly. I would use a function to handle the formatting:
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
void printxy(double x, double y, int width){
cout << setw(width) << x << "\t";
if (y < 0) cout << "\b";
cout << setw(width) << y << "\n";
}
int main(){
double hw = 4.0;
int nsteps = 30;
const double PI = 3.14159;
const double maxx = hw * PI;
const double deltax = maxx / nsteps;
double x = 0.0;
int decimals = 6;
int width = 8; //Adjust as needed for large numbers/many decimals
cout << std::setprecision(decimals);
cout << std::setw(width);
cout.setf(ios::left);
for (int i = 0; i < nsteps; i++) {
const double y = sin(x);
printxy(x, y, width);
x = x + deltax;
}
}
The output is now formatted correctly:
0 0
0.418879 0.406736
0.837757 0.743144
1.25664 0.951056
1.67551 0.994522
2.09439 0.866026
2.51327 0.587787
2.93215 0.207914
3.35103 -0.207909
3.76991 -0.587783
4.18879 -0.866024
4.60767 -0.994521
5.02654 -0.951058
5.44542 -0.743148
5.8643 -0.406741
6.28318 -5.30718e-06
6.70206 0.406731
7.12094 0.743141
7.53982 0.951055
7.95869 0.994523
8.37757 0.866029
8.79645 0.587791
9.21533 0.207919
9.63421 -0.207904
10.0531 -0.587778
10.472 -0.866021
10.8908 -0.994521
11.3097 -0.951059
11.7286 -0.743151
12.1475 -0.406746
I would also discourage the use of cerr for these kinds of printing operations. It is intended for printing errors. Use cout instead (it works the same way for all practical purposes).
I should also mention that endl is a ticking bomb: it flushes the output, meaning that the internal buffer of the stream is written out (be it the console, a file or whatever). When applications scale and become more IO intensive, this can become a significant performance problem: the buffer that is intended to increase the IO performance is potentially unused due to frequent endl insertions. The solution is to use the newline character '\n'.
Use std::setprecision() to set count number for decimal after point, and std::setw() to set width of output length. Include <iomanip> needed, example:
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
int main()
{
double hw = 4.0;
int nsteps = 30;
const double PI = 3.14159;
const double maxx = hw * PI;
const double deltax = maxx / nsteps;
double x = 0.0;
cerr << std::setprecision(8);
for (int i = 0; i < nsteps; i++) {
const double f = sin(x);
cerr << std::setw(20) << x << std::setw(20) << f << endl;
x = x + deltax;
}
return 0;
}
Output is:
0 0
0.41887867 0.40673632
0.83775733 0.74314435
1.256636 0.95105619
1.6755147 0.99452204
2.0943933 0.86602629
2.513272 0.58778697
2.9321507 0.20791411
3.3510293 -0.20790892
3.769908 -0.58778268
4.1887867 -0.86602363
//...
I made a GBM function in C++ and I believe I am getting too much of a range of stock prices when I start with an initial price of 100 the output can be from [50,400]. I am not sure what I am doing wrong in my code, I am guessing there is something wrong with the way I seed the random standard normal numbers. Please have a look at the function and let me know if there is anything I shold modify or change.
Here is the function:
std::vector<double> GBM(const int M, const int N, const double T, const double r, const double q, const double sigma, const double S0){
double dt = T/N;
std::vector<double> Z;
std::vector<double> S;
S.push_back(S0);
std::mt19937 e2(time(0));
std::normal_distribution<double> dist(0.0, 1.0);
for(int i = 0; i < M; i++){
Z.push_back(dist(e2));
}
double drift = exp(dt*((r - q)-0.5*sigma*sigma));
double vol = sqrt(sigma*sigma*dt);
for(int i = 1; i < M; i++){
S.push_back(S[i-1] * drift * exp(vol*Z[i]));
}
return S;
}
Here is the main.cpp file that utilizes the function above:
#include <iostream>
#include "LSM.h"
#include <cmath>
#include <ctime>
#include <Eigen/Core>
#include <Eigen/SVD>
#include <iostream>
#include <vector>
#include <random>
std::vector<double> GBM(const int M, const int N, const double T, const double r, const double q, const double sigma, const double S0);
int main(){
const double r = 0.04; // Riskless interest rate
const double q = 0.0; // Divident yield
const double sigma = 0.20; // Volatility of stock
const double T = 1; // Time (expiry)
const int N = 1000; // Number of time steps
const double K = 100.0; // Strike price
const double S0 = 100.0; // Initial stock price
const int M = 10000; // Number of paths
const int R = 2; // Choice of basis for Laguerre polynomial
//LSM Option_value(r,q,sigma,T,N,K,S0,M,R);
std::vector<double> s = GBM(M,N,T,r,q,sigma,S0);
for(int i = 0; i < M; i++){
std::cout << s[i] << std::endl;
}
return 0;
}
A typical output that one should get starting with an initial stock price of 100 is below:
153.5093
132.0190
96.2550
106.5196
58.8447
135.3935
107.1194
101.2022
134.2812
82.2146
87.9162
74.9333
88.9137
207.5150
123.7893
95.8526
120.0831
96.3990
103.3806
113.8258
100.6409
92.0724
81.1704
121.9925
114.3798
117.8366
86.1070
74.4885
82.6013
78.0202
97.0586
119.7626
89.0520
72.2328
92.1998
84.7180
138.9160
91.0091
105.2096
91.3323
79.0289
115.9377
75.4887
123.2049
101.1904
95.9454
82.4181
108.8314
123.0198
76.8494
94.8827
149.5911
95.6969
143.3498
87.0939
77.3033
105.8185
122.3455
79.8208
112.9913
120.1649
131.3052
136.8246
96.5455
109.0187
87.1363
103.1835
106.3896
143.9496
119.1357
99.9114
111.1409
79.0563
147.1506
105.7851
99.7089
117.8770
99.7602
73.1796
125.8698
109.4367
135.5020
88.1979
129.8502
121.1233
76.7520
86.5296
118.6721
83.2511
116.3950
99.8795
70.6895
64.9578
111.4750
102.6343
82.8765
90.3479
106.8873
106.3850
119.3399
Function GBM should simulate 1 path every time. So no need to supply M. And the path length is, in your code, defined by N instead of M.
If you implement this change, GBM return the whole simulated path.
Then you need to call GBM M times in order to calculate all the simulations.
Also there is no need to store all the random numbers generated.
Based on your sample, something like this:
#include <iostream>
#include <vector>
#include <random>
// Random generator initialize (only once).
static std::mt19937 rng(time(0));
std::vector<double> GBM(const int N, const double T, const double r,
const double q, const double sigma, const double S0)
{
double dt = T/N;
std::vector<double> S;
S.push_back(S0);
std::normal_distribution<double> dist(0.0, 1.0);
double drift = exp(dt*((r - q)-0.5*sigma*sigma));
double vol = sqrt(sigma*sigma*dt);
for(int i = 1; i < N; i++){
double Z = dist(rng);
S.push_back(S[i-1] * drift * exp(vol*Z));
}
return S;
}
int main(){
const double r = 0.04; // Riskless interest rate
const double q = 0.0; // Divident yield
const double sigma = 0.20; // Volatility of stock
const double T = 1; // Time (expiry)
const int N = 1000; // Number of time steps
const double S0 = 100.0; // Initial stock price
const int M = 100; // Number of paths
for (int sindx = 0; sindx < M; sindx++)
{
std::vector<double> s = GBM(N,T,r,q,sigma,S0);
std::cout << "Simulation " << sindx << ": "
<< s[0] << ", " << s[1] << " ... " << s[N-2] << ", " << s[N-1]
<< std::endl;
}
return 0;
}
From the comments behind the constants, you want to simulate 10000 paths of an integration from 0 to 1 using 1000 subdivision steps, i.e., a step size of 0.001.
What you are doing is integrating one path over 10000 steps of step size 0.001, that is, from 0 to 10.
If you do this correctly, the result should look like a list of
S0 * exp( ((r-q)-0.5*sigma*sigma)*T + sigma*sqrt(T)*Z[i] )
as the value of the GBM at time T only depends on W(T) which is distributed as N(0,T) or sqrt(T)*N(0,1).
I'm fairly new with C++ and I'm trying to use it via Rcpp to speed up my R code.
The below code integrates from from t0 to t1- this is done in the "lorenz" function. Test4 integrates using "lorenz" "counts" number of times. However at time "t1" the state of the system is modified in "write_lorenz" before the system is rerun and this is where the problem is. If I run the same program over and over again by calling test4 from R, printing to the screen always produces the same result, however, my returned matrix "u" does not, and seems to eventually converge to whatever "t1" is which is the problem.
My input values don't change so I'm wondering if there a memory leak, or if something else is going on, how to fix it.
Also I'm wondering if my initialization of "u" is incorrect and I should be using the "new" command.
What I tried was
NumericMatrix* u = NULL;
*u = new NumericMatrix;
and then I tried accessing the elements of the matrix as *u(1,2) for instance, but accessing the elements this way caused an error saying u was not a function.
Any help would be greatly appreciated
I modified this code from the following site
http://headmyshoulder.github.io/odeint-v2/examples.html
so I could use it with Rcpp
//###################################R Code ###############################
library(Rcpp)
sourceCpp("test4.cpp")
sigma <- 10.0
R <-28.0
b <- 8.0 / 3.0
a2 <- c(10.0 , 1.0 , 1.0) #initial conditions X0,I0,Y0
L2 <- c(0.0 , 2.0 , 0.1) #initial time, kick time, error
counts <- 2
kick <-1.0; # kick size
pars <-c(sigma,R,b,kick)
test4(a=a,L2=L2,counts=counts,pars= pars)
// C ++ code
//[[Rcpp::depends(BH)]]
//[[Rcpp::depends(RcppEigen)]]
//[[Rcpp::plugins("cpp11")]]
#include <Rcpp.h>
#include <RcppEigen.h>
#include <math.h>
#include <boost/array.hpp>
#include <boost/numeric/odeint.hpp>
#include <boost/algorithm/string.hpp>
using namespace boost::numeric::odeint;
using namespace std;
using namespace Rcpp;
using namespace Eigen;
double sigma =0;
double e =0;
double b =0 ;
double t0 =0;
double t1 = 0;
double kick =0;
double X0 = 0;
double I0 =0;
double Y0 =0;
double N = 0;
int counter =0;
typedef boost::array< double , 3 > state_type;
NumericMatrix u(4,5);
void lorenz( const state_type &x , state_type &dxdt , double t )
{
dxdt[0] = sigma * ( x[1] - x[0] );
dxdt[1] = e * x[0] - x[1] - x[0] * x[2];
dxdt[2] = -b * x[2] + x[0] * x[1];
}
void write_lorenz( const state_type &x , const double t )
{
if(t==t1){
X0 = x[0];
I0 = x[1];
Y0 = x[2];
N = X0+I0+Y0;
X0 = X0 + exp(kick*N);
counter++;
//for some reason cout and u don't match for multiple runs of the
//program
cout << t << '\t' << X0 << '\t' << I0 << '\t' << Y0 << endl;
u(counter,0) = t;
u(counter,1) = X0;
u(counter,2) = I0;
u(counter,3) = Y0;
}
}
// [[Rcpp::export]]
NumericMatrix test4(NumericVector a, NumericVector L2,int counts,NumericVector pars)
{
double error; // control integration error
// initialize model parameters
//maybe these should be parenthesis?
sigma = pars[0]; //# average per capita birh rate 1-10(the mean is 4.7)
e = pars[1]; // # per capita average growth rate
b= pars[2];
kick = pars[3]; // kick size
//cout << sigma << R << b << kick << endl;
//myfile.open (ST);
X0 = a[0]; I0 =a[1]; Y0 = a[2];
int i = 0;
t0 = L2[0];
t1 = L2[1];
error = L2[2];
u(0,0) = t0;
u(0,1) = X0;
u(0,2) = I0;
u(0,3) = Y0;
// initial conditions
for(i=0;i<counts;i++)
{
state_type x = { X0 , I0 , Y0 };
integrate( lorenz , x , t0 , t1 , error , write_lorenz );
}
return u; // the variable I hope will be global
}
Here is a simple adaptation of the pure C++ file you linked to. We simply define a struct of three vectors into which we push the elements of each iterations--as opposed to printing them to standard output.
For data structures that grow, we prefer C++ standard library types (as our types have to be like R types, their internals do not match well to increasing one-by-one which is expensive for them). So at the end, we just copy into an R data.frame.
#include <boost/array.hpp>
#include <boost/numeric/odeint.hpp>
#include <Rcpp.h>
// [[Rcpp::depends(BH)]]
// [[Rcpp::plugins(cpp11)]]
using namespace std;
using namespace boost::numeric::odeint;
const double sigma = 10.0, r = 28.0, b = 8.0 / 3.0;
typedef boost::array< double , 3 > state_type;
void lorenz( const state_type &x , state_type &dxdt , double t ) {
dxdt[0] = sigma * ( x[1] - x[0] );
dxdt[1] = r * x[0] - x[1] - x[0] * x[2];
dxdt[2] = -b * x[2] + x[0] * x[1];
}
struct foo { std::vector<double> a, b, c; };
struct foo f;
void append_lorenz(const state_type &x , const double t ) {
f.a.push_back(x[0]);
f.b.push_back(x[1]);
f.c.push_back(x[2]);
}
using namespace Rcpp;
// [[Rcpp::export]]
DataFrame callMain() {
state_type x = { 10.0 , 1.0 , 1.0 }; // initial conditions
integrate( lorenz , x , 0.0 , 25.0 , 0.1 , append_lorenz );
return DataFrame::create(Named("a") = f.a,
Named("b") = f.b,
Named("c") = f.c);
}
/*** R
res <- callMain()
print(head(res))
*/
Here is the output of the R code (intentially limited to fist few rows):
R> sourceCpp("/tmp/lorenz.cpp")
R> res <- callMain()
R> print(head(res))
a b c
1 10.00000 1.00000 1.00000
2 9.40816 2.99719 1.12779
3 8.92164 5.35684 1.46991
4 8.68193 7.82671 2.05762
5 8.73730 10.42718 2.94783
6 9.11080 13.10452 4.18849
R>
Would you please help me with my problem. I'm trying to write a program where objects in different class interact. I base my model on the gsl library to resolve my ordinary differential equations (ode).
Instances of different classes consume each other, so they get or loose mass when they eat or are eaten.
My 2 ode are like b[i] = sum of consumption - sum of consumed. I calculate consumption as follow, with 1 being the consumer and 0, the prey.
conso[1] = y[0] * x[1] * y[1]
The original code comes from "sample code using gsl routines" as follow with modifications. The instances of class A and B are included in maps of class C.
I'm new to c++ and I don't see how I can integrate a loop in the ode to make it calculate what has been consumed by each instance, and remove it from the other instances that have been eaten. The best would be to use functions and variables that are in the istances class but the function where the ode are has to be static. I thought about array but it seems that arrays can't be parameters of the odes.
The other problem is that for each instance, the parameters has to change and be taken in the class, but how I did here, in the loop with the iterators, the ode will work for the last instance... Again I would have like to use an array of class C that take the parameter of the instances in class A and B, but because the function is static I can't use the array of the class "C". I'm in real trouble !
Do you have any ideas ? Thank you !
// include files
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
#include <gsl/gsl_errno.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_odeiv.h>
// ************************* C.h ****************************
class C
{
public :
C(std::map(std::map<std::string,A> &A, std::map<std::string,B> &B);
~C();
int integ(void);
int static rhs (double t, const double y[], double f[], void *params_ptr);
private :
std::map<std::string,A> &A,
std::map<std::string,B> &B,
};
//*************************** C.cpp ****************************
int C::integ (void)
{
int dimension = 2; // number of differential equations
double eps_abs = 1.e-8; // absolute error requested
double eps_rel = 1.e-10; // relative error requested
// define the type of routine for making steps:
const gsl_odeiv_step_type *type_ptr = gsl_odeiv_step_rkf45;
// allocate/initialize the stepper, the control function, and the
// evolution function.
gsl_odeiv_step *step_ptr = gsl_odeiv_step_alloc (type_ptr, dimension);
gsl_odeiv_control *control_ptr = gsl_odeiv_control_y_new (eps_abs, eps_rel);
gsl_odeiv_evolve *evolve_ptr = gsl_odeiv_evolve_alloc (dimension);
gsl_odeiv_system my_system; // structure with the rhs function, etc.
// parameter for the diffeq
for(itA=A.begin(); itA!=A.end(); ++itA)
{
x = itA->second.getx();
my_system.params = &x; // parameters to pass to rhs
}
for(itB=B.begin(); itB!=B.end(); ++itB)
{
z = itB->second.getz();
my_system.params = &z; // parameters to pass to rhs
}
double y[2]; // current solution vector
double t, t_next; // current and next independent variable
double tmin, tmax, delta_t; // range of t and step size for output
double h = 1e-6; // starting step size for ode solver
// load values into the my_system structure
my_system.function = rhs; // the right-hand-side functions dy[i]/dt
my_system.dimension = dimension; // number of diffeq's
tmin = 0.; // starting t value
tmax = 100.; // final t value
delta_t = 1.;
for(itA=A.begin(); itA!=A.end(); ++itA)
{
y[0] = itA->second.getY(); // initial y value
}
for(itB=B.begin(); itB!=B.end(); ++itB)
{
y[1] = itB->second.getY(); // initial y value
}
t = tmin; // initialize t
// print initial values
cout << scientific << setprecision (5) << setw (12) << t << " "
<< setw (12) << y[0] << " " << setw (12) << y[1] << endl;
// step to tmax from tmin
for (t_next = tmin + delta_t; t_next <= tmax; t_next += delta_t)
{
while (t < t_next) // evolve from t to t_next
{
gsl_odeiv_evolve_apply (evolve_ptr, control_ptr, step_ptr,
&my_system, &t, t_next, &h, y);
}
// print at t = t_next
cout << scientific << setprecision (5) << setw (12) << t << " "
<< setw (12) << y[0] << " " << setw (12) << y[1] << endl;
}
// all done; free up the gsl_odeiv stuff
gsl_odeiv_evolve_free (evolve_ptr);
gsl_odeiv_control_free (control_ptr);
gsl_odeiv_step_free (step_ptr);
return 0;
}
//*************************** rhs ****************************
int C :: rhs (double , const double y[], double f[], void *params_ptr)
{
// get parameter(s) from params_ptr; here, just a double
double x = *(double *) params_ptr;
double z = *(double *) params_ptr;
// evaluate the right-hand-side functions at t
f[1] = x * y[1] + sum consumption - sum consumed; //objects of class A
f[0] = - z * y[0] - sum consumed; //objects of class B
return GSL_SUCCESS; // GSL_SUCCESS defined in gsl/errno.h as 0
}
I tried to add consumption, but it says "error: 'void' must be the first and only parameter if
specified" :
int C :: rhs (double , const double y[], double f[], void *params_ptr, void conso)
{
// get parameter(s) from params_ptr; here, just a double
double x = *(double *) params_ptr;
double z = *(double *) params_ptr;
// evaluate the right-hand-side functions at t
f[0] = z * y[0]; //objects of class A
f[1] = - x * y[1] + conso; //objects of class B
return GSL_SUCCESS; // GSL_SUCCESS defined in gsl/errno.h as 0
}
//***And in int C :: integ :
for(itA=A.begin(); itA!=A.end(); ++itA)
{
for(itB=B.begin(); itB!=B.end(); ++itB)
{
void conso = itA->second.conso(itB->second, x);
}
}
//***With in class A :
void A :: conso(Group &prey, double x)
{
double conso=0;
conso = x * y * prey.gety();
}