Invalid Operands 4th order Runge-Kutta

I am not entirely sure that what I have done is correct. I followed an example given in my notes, adapting the code to suit the required problem.

My problem comes in line 41:
 
  gsl_odeiv_system gsl_sys = {calc_derivs, NULL, n_equations, &q &F };


With error:
1
2
3
4
5
Pendulum1.cc: In function ‘int main()’:
Pendulum1.cc:41:67: error: invalid operands of types ‘double*’ and ‘double’ to binary ‘operator&’
   gsl_odeiv_system gsl_sys = {calc_derivs, NULL, n_equations, &q &F };
                                                                   ^
make: *** [Pendulum1] Error 1


I believe it is to do with how I have two parameters that I am changing in my ODE equations, whereas the function for the gsl_sys only wants one. But I am not sure how to go about using both parameters.

Any help is appreciated.

Entire code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// RK4 solution to x''= -sin(x) -q*x' + Fsin(2t/3) where x' = dx/dt
// relabelling theta to x for convenience
// adaptation from /ux/PHYSICS/PART_2/c++/ex/ode_ring1.cc
#include <iostream>
#include <cmath>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_odeiv.h>

// function evaluates the derivatives of the two variables x and x'
int calc_derivs (double t, const double y[], double dydx[], void *params)
{
  double q  = * (double*) (params); // defining q
  double F = * (double*) (params); // defining F
  dydx[0] = y[1]; // 1st order differential equation (1)
  dydx[1] = - sin(y[0]) - q * y[1] + F * sin(2*t/3); // 1st order differential equation (2)
  return GSL_SUCCESS;
}

int main()
{
  // initial conditions
  double q = 0.0;
  double F = 0.0;
  const int n_equations = 2;
  double y[n_equations] = {0.01,0.0};
  double t = 0.0;

  // creating stepping function
  gsl_odeiv_step* gsl_step =
	gsl_odeiv_step_alloc( gsl_odeiv_step_rk4, n_equations );

  // adaptive step control - fixed steps
  gsl_odeiv_control* gsl_control = NULL;

  // evolution function
  gsl_odeiv_evolve* gsl_evolve =
	gsl_odeiv_evolve_alloc (n_equations);

  // system needed by GSL: 4th arg is a pointer to any parameters needed by the evaluator. 2nd arg points to the jacobian function if needed (it's not needed here)

  gsl_odeiv_system gsl_sys = {calc_derivs, NULL, n_equations, &q &F };
  double t_max = 20.0;
  double h     = 1e-3;

  // main loop: advance solution until t_max reached

  while ( t < t_max )
    {
      std::cout << t << " " << y[0] << " " << y[1] << "\n";

      int status =
        gsl_odeiv_evolve_apply( gsl_evolve, gsl_control, gsl_step,
                                &gsl_sys, &t, t_max, &h, y );
      if (status != GSL_SUCCESS)
        break;
    }

  // tidy up the GSL objects for neatness

  gsl_odeiv_evolve_free ( gsl_evolve );
  gsl_odeiv_step_free ( gsl_step );

  return 0;
}
I honestly have no idea what this code does but, this looked wrong atleast to me, feel free to correct me -

gsl_odeiv_system gsl_sys = {calc_derivs, NULL, n_equations, &q &F };

Like 41 like you said. What is that equal sign doing there? Can you create whatever you are creating and then having it equal a thing in between curly braces?
Honestly I'm not completely sure myself.

I searched around on the gsl website and found the form of the system data type:
https://www.gnu.org/software/gsl/manual/html_node/Defining-the-ODE-System.html
(Hopefully I'm allowed to post the weblink)
So this is what convinced me that this is correct (other than the &q &F)

The code in my example from the notes, uses the same line but the ODE from the notes uses one parameter, whereas the problem I have uses two parameters: q, F.

What I am trying to do with this code, is to use the runge-kutta method from the gsl library to integrate the ODE given in line 1, starting from (y[0],y[1]) = (0.01,0.0).

Initial settings are q = F = 0

Then I want the program to write out t, x, w (t, y[0], y[1]).

Would it help if I posted the original code from my notes?
Would it help me? Not the slightest, no idea whats going on, but Im almost certain the code at line 41 is something that cannot be done. I mean, you're creating a variable or whatever of type gsl_odeiv_system gsl_sys. You cant have it equal whatever this is - {calc_derivs, NULL, n_equations, &q &F };

There's a lot of smart people on this forum, if you dont get answers right now hopefull you will get an answer when one of them shows up =)
From my understanding, it's not meant to be a variable. It's just setting the data requirements for the system of ODE's for the GSL library:

 
gsl_odeiv2_system = (function, jacobian, dimensions, parameters)


So I guess, regardless of what is happening, my main question is how I can point to more than one parameter within that one section.
From the docs (http://www.inference.phy.cam.ac.uk/pjc51/local/gsl/manual/gsl-ref_25.html):
void * params
This is a pointer to the arbitrary parameters of the system.


Using your example:
1
2
double params[2] = { q, F };
gsl_odeiv_system gsl_sys = {calc_derivs, NULL, n_equations, params };
Thanks norm b, that worked.

Could you possibly explain why "&params" is not required in this case. From my understanding, the "&" allows us to address to the pointer. So why does that change when we pass the pointers through an array? If that's what we are doing.
You're welcome.

There is a good description of the relationship between arrays and pointers here:
http://www.learncpp.com/cpp-tutorial/68-pointers-arrays-and-pointer-arithmetic/

With &params you would be taking the address of a pointer to the first element of the array not the address of the first element (**params to dereference).
Topic archived. No new replies allowed.