I am writing a code to integrate some ODEs using a leapfrog method, I have to supply a function including the derivatives to my integration method, however I'm getting a "void value not ignored as it ought to be error". I've gotten this in the past when I've mistaken types with function pointers but as far as I can see the function doesn't assign anything anywhere, it should just execute?
So my source file is here
#include "nrutil.h"
#include <math.h>
#include <stdio.h>
void leapvel(int n, double x[], double v[], double dt2, void (*derivs)(double, double [], double []))
{
double dvdt[n];
int i;
(*derivs)(n, x, dvdt);
for(i = 0; i < n; i )
v[i] = dt2*dvdt[i];
}
void output(int n, double x[], double v[], double t, double dt, void (*derivs)(double, double [], double []))
{
int i;
double vv[n], dvdt[n];
printf("%f", t);
for(i = 0; i < n; i )
printf(" %f", x[i]);
/*sync velocity*/
for (i = 0; i < n; i )
vv[i] = v[i];
if (t > 0)
{
(*derivs)(n,x,dvdt);
for (i = 0; i < n; i )
vv[i] -= 0.5*dt*dvdt[i];
}
printf("\n");
}
void leap(int n, double x[], double v[], double* t, double dt, void (*derivs)(double, double [], double []))
{
double dvdt[n];
int i;
for (i = 0; i < n; i )
x[i] = dt*v[i];
(*derivs)(n, x, dvdt);
for (i = 0; i < n; i )
v[i] = dt*dvdt[i];
*t = dt;
}
void leapfrog(int n, double x[], double v[], double t, double dt, double t_max, void (*derivs)(double, double [], double []))
{
/* integration time! */
/* parameters, the user has to set these, and to be honest it's going to be cumbersome either way in command line or just editing the code */
/* but since we have to run this twice! */
/* double t = 0, x[n] = {0}, v[n] = {1};
double t_max = 15, dt = 1;*/
/*this is the number of equations in derivs*/
/*int n = 1*/
int i;
output(n, x, v, t, dt, *derivs);
leapvel(n, x, v, 0.5*dt, *derivs);
while (t < t_max)
{
leap(n, x, v, &t, dt, *derivs);
output(n, x, v, t, dt, *derivs);
}
}
This is referenced in a short file I do intend to make a header once I figure this out as it's better practice than simply just including the source file however, for now this is what I have
#include <math.h>
void leapfrog(int n, double x[], double v[], double t, double dt, double t_max, void (*derivs)(double, double [], double []));
void derivs(int n, double x[], double dvdt[])
{
int i;
double accel = 0.0;
for(i = 0; i < n; i )
{
accel = -x[i];
dvdt[i] = accel;
}
}
int main()
{
/*frog goes {number of equations], {x initial conditions}, {v initial}, [t bottom], [t step], [t max], derivs(n,
* x[], dvdt[]) */
int n = 1;
double x[n];
double v[n];
x[0] = 0;
v[0] = 1;
double t = 0;
double dt = 1;
double t_max = 15;
double dvdt[n];
leapfrog(n, x, v, t, dt, t_max, *derivs(n, x, dvdt)); /*I get the error on this line*/
return 0;
}
I'm probably missing something obvious here but I'm not sure.
I've tried to make the function a void pointer type function but that obviously is dangerous, and has undefined behavior, so I have a pointer to a void function now, but that gives this error. If I remove the arguments it has other weird behavior. I'm not sure how to make this work. Removing the arguments gives too few arguments obviously as it's declare above, but when I give it what it wants it gives the error.
This means the error is probably in the source file shown off first, but I can't seem to find it in there, as far as I can see I don't directly assign it to anything so all should be fine.
CodePudding user response:
If you want to pass the function derivs
as an argument to a function, you just write derivs
. Just like the way you pass any other variable. You don't write sin(double x)
; it's just sin(x)
. Same with functions.
Here, you are calling derivs
and then attempting to dereference its non-existent return value:
leapfrog(n, x, v, t, dt, t_max, *derivs(n, x, dvdt))
The compiler objects, because there is obvious no return value to dereference. But the real error was writing a function call rather than just providing the function. You should write:
leapfrog(n, x, v, t, dt, t_max, derivs)
For obscure reasons, the compiler might not complain about this incorrect function call:
output(n, x, v, t, dt, *derivs);
where you are attempting to pass the function itself rather than a pointer to a function. If you look at the prototype for output
, you'll see that the last parameter is a pointer to a function, so that's what you should pass it. Anyway, there is no other option, because in C functions are not usable as objects; you can only use pointers to functions. So that call (and the other similar ones) should be written as output(n, x, v, t, dt, derivs)
. Unsurprisingly, that's pretty similar to the way leapfrog
should be called.