I'm new to C and I'm trying to calculate the kinetic energy from certain values (px and py) but my routine accuses always as main mistake subscripted value is neither array nor pointer vector nor. Can anyone help me because all I know I've tried.
The error occurs in the kinetic function
thanks
My routine
#include <stdio.h>
#include <stdlib.h>
#ifndef RAN2_H_
#define RAN2_H_
void UniformBox(long, long *, double, double, double *, double *, double *, double *);
void kinetic(long, double, double, double);
#endif /* RAN2_H_ */
#include "ran2.h"
float ran2(long*);
void UniformBox(long n, long *idum, double L, double p0, double *rx, double *ry, double *px, double *py){
long i;
for(i = 0 ; i < n ; i++){
rx[i] = ((double)ran2(idum))*L;
ry[i] = ((double)ran2(idum))*L;
px[i] = ((double)ran2(idum) -.5)*2*p0;
py[i] = ((double)ran2(idum) -.5)*2*p0;
}
return;
}
void kinetic(long n, double x, double y, double kint){
long i;
for(i = 0 ; i < n ; i++){
kint[i] = (x*x)+(y*y);
}
return;
}
void UniformBox(long, long *, double, double, double *, double *, double *, double *);
void kinetic(long n, double x, double y, double kint);
int main(){
long i, n, seed, idum;
double *rx, *ry, *px, *py;
double L, p0, kint;
n = 1000;
L = 2.0;
p0 = 1.22;
seed = 10;
idum = -seed;
FILE *init = fopen("initialPosition.dat", "w");
rx = (double *) malloc((double) n * sizeof(double));
ry = (double *) malloc((double) n * sizeof(double));
px = (double *) malloc((double) n * sizeof(double));
py = (double *) malloc((double) n * sizeof(double));
UniformBox(n, &idum, L, p0, rx, ry, px, py);
kinetic(n, px, py, kint);
for(i = 0 ; i < n ; i++){
printf("%lf\t%lf\t%lf\t%lf\t%lf\n", rx[i], ry[i], px[i], py[i], kint[i]);
fprintf(init,"%lf\t%lf\t%lf\t%lf\n", rx[i], ry[i], px[i], py[i]);
}
fclose(init);
free(rx);
free(ry);
free(px);
free(py);
return 0;
}
I've fixed the compile errors. A few things to note.
I removed multiple incompatible function prototypes.
Aside from kinetic's kint needing to be a pointer, x and y needed to be pointers. Note that this is conjecture on my part, based on the totality of the code. Also note the change inside the loop from x to x[i]. Otherwise, things didn't make sense [to me].
In main, I added a malloc for kint
Anyway, here's the code [please pardon the gratuitous style cleanup]:
#include <stdio.h>
#include <stdlib.h>
#ifndef RAN2_H_
#define RAN2_H_
float ran2(long *);
#endif /* RAN2_H_ */
//#include "ran2.h"
void
UniformBox(long n, long *idum, double L, double p0, double *rx, double *ry,
double *px, double *py)
{
long i;
for (i = 0; i < n; i++) {
rx[i] = ((double) ran2(idum)) * L;
ry[i] = ((double) ran2(idum)) * L;
px[i] = ((double) ran2(idum) - .5) * 2 * p0;
py[i] = ((double) ran2(idum) - .5) * 2 * p0;
}
return;
}
void
kinetic(long n, double *x, double *y, double *kint)
{
long i;
for (i = 0; i < n; i++) {
kint[i] = (x[i] * x[i]) + (y[i] * y[i]);
}
return;
}
int
main()
{
long i, n;
long seed, idum;
double *rx, *ry;
double *px, *py;
double L, p0;
double *kint;
n = 1000;
L = 2.0;
p0 = 1.22;
seed = 10;
idum = -seed;
FILE *init = fopen("initialPosition.dat", "w");
rx = (double *) malloc((double) n * sizeof(double));
ry = (double *) malloc((double) n * sizeof(double));
px = (double *) malloc((double) n * sizeof(double));
py = (double *) malloc((double) n * sizeof(double));
kint = (double *) malloc((double) n * sizeof(double));
UniformBox(n, &idum, L, p0, rx, ry, px, py);
kinetic(n, px, py, kint);
for (i = 0; i < n; i++) {
printf("%lf\t%lf\t%lf\t%lf\t%lf\n", rx[i], ry[i], px[i], py[i], kint[i]);
fprintf(init, "%lf\t%lf\t%lf\t%lf\n", rx[i], ry[i], px[i], py[i]);
}
fclose(init);
free(rx);
free(ry);
free(px);
free(py);
return 0;
}
In C , you must pass arrays into a function by reference. Thus, your function header should be
void kinetic(long n, double x, double y, double * kint);
You could also use the [] notation like is suggested in the comments.
Related
I am quite new to programming with C, so hope someone can bear with me and help me solve the issue I am facing.
I am writing a code to estimate the value of pi with Monte-Carlo method. however, when I build and debug I get an error that says:
"Exception thrown: write access violation.
a was 0x1110112.
I get this error in generate_random_array function
in this line of code:
a[i] = (((double)rand() / (double)RAND_MAX) * 2.0 ) - 1.0;
I am posting the whole code as well for reference.
note: I am using visual studio with MSVC compiler
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void generate_random_array(int sz, double a[]);
void count_points_inside_circle(int sz, double x[], double y[], int* counter);
int main()
{
int tot = 1000000000;
int incircle_c = 0;
double distance_sq, pi;
double* x = NULL;
double* y = NULL;
/*create arrays in the heap*/
x = malloc(tot * sizeof(double));
y = malloc(tot * sizeof(double));
/*generate random locations*/
generate_random_array(tot, x);
generate_random_array(tot, y);
/*count the points inside te circle by checking the location distance*/
count_points_inside_circle(tot, x, y, &incircle_c);
/*estimate pi*/
pi = 4.0 * incircle_c / (double)tot;
printf("pi estimated value using %d samples was found to be %lf", tot, pi);
free(x);
free(y);
return 0;
}
void generate_random_array(int sz, double a[]) {
int i;
srand(time(NULL));
for (i = 0; i < sz; i++)
a[i] = (((double)rand() / (double)RAND_MAX) * 2.0 ) - 1.0;
}
void count_points_inside_circle(int sz, double x[], double y[],int* counter_p) {
int i;
double distance_sq;
for (i = 0; i < sz; i++) {
distance_sq = x[i] * x[i] + y[i] * y[i];
if (distance_sq <= 1)
(*counter_p)++;
}
}
You must always check the pointer returned from malloc against NULL. For example:
x = malloc(n * sizeof *x);
if (x == NULL) { /* Handle the failure and/or exit */ }
On the other hand, this task doesn't require use of an array (or allocated space used as an array) at all; you need only the number of points inside the circle and the number of total points generated. It could be simply done like that:
#include <stdio.h>
#include <stdlib.h>
double estimate_pi (unsigned trial_count)
{
const double rr = (double)RAND_MAX * RAND_MAX;
unsigned inner_point_count = 0;
unsigned i;
for (i = 0; i < trial_count; ++i) {
double x = rand();
double y = rand();
if (x * x + y * y <= rr)
++inner_point_count;
}
return 4.0 * inner_point_count / trial_count;
}
int main (void)
{
printf("%f\n", estimate_pi(1000000000));
return 0;
}
Note that, quality of random number generator used by the standard library significantly affects the result of this simulation.
I am solving 1 D heat conduction equation.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void grid(int nx, double xst, double xen, double *x, double *dx)
{
int i;
*dx = (xen-xst)/(double)(nx-1);
for(i=0; i<nx; i++)
x[i] = (double)i * (*dx); // ensure x[0] == 0.0 and x[nx-1] == 1.0
}
void get_exact_solution(int nx, double time, double *x, double *Texact)
{
// calculates exact solution
int i;
for(i=0; i<nx; i++)
Texact[i] = erf((x[i]-0.5)/2.0/sqrt(time));
}
void enforce_bcs(int nx, double *x, double *T)
{
T[0] = -1.0;
T[nx-1] = 1.0;
}
void set_initial_condition(int nx, double *x, double *T)
{
int i;
for(i=0; i<nx; i++)
T[i] = tanh((x[i]-0.5)/0.1);
enforce_bcs(nx,x,T); //ensure BCs are satisfied at t = 0
}
void get_rhs(int nx, double dx, double *x, double *T, double *rhs)
{
int i;
double dxsq = dx*dx;
// compute rhs. For this problem, d2T/dx2
for(i=1; i<nx-1; i++)
rhs[i] = (T[i+1]+T[i-1]-2.0*T[i])/dxsq;
}
void timestep_Euler(int nx, double dt, double dx, double *x, double *T, double *rhs)
{
int i;
// compute rhs
get_rhs(nx,dx,x,T,rhs);
// (Forward) Euler scheme
for(i=1; i<nx-1; i++)
T[i] = T[i] + dt*rhs[i]; // T^(it+1)[i] = T^(it)[i] + dt * rhs[i];
// set Dirichlet BCs
enforce_bcs(nx,x,T);
}
void output_soln(int nx, int it, double tcurr, double *x, double *T)
{
int i;
FILE* fp;
char fname[100];
sprintf(fname, "T_x_%04d.dat", it);
//printf("\n%s\n", fname);
fp = fopen(fname, "w");
for(i=0; i<nx; i++)
fprintf(fp, "%lf %lf\n", x[i], T[i]);
fclose(fp);
}
int main()
{
int nx;
double *x, *T, *rhs, tst, ten, xst, xen, dx, dt, tcurr, *Texact;
int i, it, num_time_steps, it_print;
FILE* fp;
nx =10; //grid points
xst = 0, //starting and ending in space
xen = 1;
tst=0; // start and end in time
ten=1
printf("Inputs are: %d %lf %lf %lf %lf\n", nx, xst, xen, tst, ten);
x = (double *)malloc(nx*sizeof(double));
T = (double *)malloc(nx*sizeof(double));
Texact = (double *)malloc(nx*sizeof(double));
rhs = (double *)malloc(nx*sizeof(double));
grid(nx,xst,xen,x,&dx); // initialize the grid
set_initial_condition(nx,x,T); // initial condition
// prepare for time loop
dt = 0.001;
num_time_steps = (int)((ten-tst)/dt) + 1; // why add 1 to this?
it_print = num_time_steps/10; // write out approximately 10 intermediate results
// start time stepping loop
for(it=0; it<num_time_steps; it++)
{
tcurr = tst + (double)it * dt;
timestep_Euler(nx,dt,dx,x,T,rhs); // update T
// output soln every it_print time steps
//if(it%it_print==0)
//output_soln(nx,it,tcurr,x,T);
}
get_exact_solution( nx, ten, x, Texact);
int loop;
double sq_diff,total,err;
total = 0;
for(loop = 0; loop < nx; loop++)
printf("%f ", T[loop]);
printf("\n");
for(loop = 0; loop < nx; loop++)
printf("%f ", Texact[loop]);
for(loop = 0; loop < nx; loop++){
sq_diff = (T[loop] - Texact[loop])*(T[loop] - Texact[loop]);
total = total+sq_diff;
}
err = sqrt(total);
printf("\n L2 Norm error = %f",err);
printf("\n");
free(rhs);
free(T);
free(x);
return 0;
}
Ideally, increasing number of grid point (nx in the program) should decrease the Error that I have calculated on final Time ten using exact solution Texact and numerical solution T.
The error should decrease with small increase in nx till the solution is stable and follows stability criteria (Von Neumann stability criteria.). But in my case this is not happening and error is increasing with increase in nx.
I am calculating the L2_norm error between T and Texact.
Texact is calculated by the function get_exact_solution.
This plot shows the problem for different cases.
Please help in correcting this program.
I just got GSL set up on my windows box and I am trying to learn how to use the nonlinear fitting functions. First thing I did was pull an example directly off their website: https://www.gnu.org/software/gsl/manual/html_node/Example-programs-for-Nonlinear-Least_002dSquares-Fitting.html
which is here:
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_blas.h>
#include <gsl/gsl_multifit_nlin.h>
#define N 40
#define FIT(i) gsl_vector_get(s->x, i)
#define ERR(i) sqrt(gsl_matrix_get(covar,i,i))
struct data {
size_t n;
double * y;
double * sigma;
};
int expb_f (const gsl_vector * x, void *data, gsl_vector * f)
{
size_t n = ((struct data *)data)->n;
double *y = ((struct data *)data)->y;
double *sigma = ((struct data *) data)->sigma;
double A = gsl_vector_get (x, 0);
double lambda = gsl_vector_get (x, 1);
double b = gsl_vector_get (x, 2);
size_t i;
for (i = 0; i < n; i++)
{
/* Model Yi = A * exp(-lambda * i) + b */
double t = i;
double Yi = A * exp (-lambda * t) + b;
gsl_vector_set (f, i, (Yi - y[i])/sigma[i]);
}
return GSL_SUCCESS;
}
int expb_df (const gsl_vector * x, void *data, gsl_matrix * J)
{
size_t n = ((struct data *)data)->n;
double *sigma = ((struct data *) data)->sigma;
double A = gsl_vector_get (x, 0);
double lambda = gsl_vector_get (x, 1);
size_t i;
for (i = 0; i < n; i++)
{
/* Jacobian matrix J(i,j) = dfi / dxj, */
/* where fi = (Yi - yi)/sigma[i], */
/* Yi = A * exp(-lambda * i) + b */
/* and the xj are the parameters (A,lambda,b) */
double t = i;
double s = sigma[i];
double e = exp(-lambda * t);
gsl_matrix_set (J, i, 0, e/s);
gsl_matrix_set (J, i, 1, -t * A * e/s);
gsl_matrix_set (J, i, 2, 1/s);
}
return GSL_SUCCESS;
}
int expb_fdf (const gsl_vector * x, void *data, gsl_vector * f, gsl_matrix * J)
{
expb_f (x, data, f);
expb_df (x, data, J);
return GSL_SUCCESS;
}
void print_state (size_t iter, gsl_multifit_fdfsolver * s);
int main (void)
{
const gsl_multifit_fdfsolver_type *T;
gsl_multifit_fdfsolver *s;
int status;
unsigned int i, iter = 0;
const size_t n = N;
const size_t p = 3;
gsl_matrix *covar = gsl_matrix_alloc (p, p);
double y[N], sigma[N];
struct data d = { n, y, sigma};
gsl_multifit_function_fdf f;
double x_init[3] = { 1.0, 0.0, 0.0 };
gsl_vector_view x = gsl_vector_view_array (x_init, p);
const gsl_rng_type * type;
gsl_rng * r;
gsl_rng_env_setup();
type = gsl_rng_default;
r = gsl_rng_alloc (type);
f.f = &expb_f;
f.df = &expb_df;
f.fdf = &expb_fdf;
f.n = n;
f.p = p;
f.params = &d;
/* This is the data to be fitted */
for (i = 0; i < n; i++)
{
double t = i;
y[i] = 1.0 + 5 * exp (-0.1 * t) + gsl_ran_gaussian (r, 0.1);
sigma[i] = 0.1;
printf ("data: %u %g %g\n", i, y[i], sigma[i]);
};
T = gsl_multifit_fdfsolver_lmsder;
s = gsl_multifit_fdfsolver_alloc (T, n, p);
gsl_multifit_fdfsolver_set (s, &f, &x.vector);
print_state (iter, s);
do
{
iter++;
status = gsl_multifit_fdfsolver_iterate (s);
printf ("status = %s\n", gsl_strerror (status));
print_state (iter, s);
if (status)
break;
status = gsl_multifit_test_delta (s->dx, s->x,
1e-4, 1e-4);
}
while (status == GSL_CONTINUE && iter < 500);
gsl_multifit_covar (s->J, 0.0, covar);
{
double chi = gsl_blas_dnrm2(s->f);
double dof = n - p;
double c = GSL_MAX_DBL(1, chi / sqrt(dof));
printf("chisq/dof = %g\n", pow(chi, 2.0) / dof);
printf ("A = %.5f +/- %.5f\n", FIT(0), c*ERR(0));
printf ("lambda = %.5f +/- %.5f\n", FIT(1), c*ERR(1));
printf ("b = %.5f +/- %.5f\n", FIT(2), c*ERR(2));
}
printf ("status = %s\n", gsl_strerror (status));
gsl_multifit_fdfsolver_free (s);
gsl_matrix_free (covar);
gsl_rng_free (r);
return 0;
}
void print_state (size_t iter, gsl_multifit_fdfsolver * s)
{
printf ("iter: %3u x = % 15.8f % 15.8f % 15.8f "
"|f(x)| = %g\n",
iter,
gsl_vector_get (s->x, 0),
gsl_vector_get (s->x, 1),
gsl_vector_get (s->x, 2),
gsl_blas_dnrm2 (s->f));
}
Ideally it should simply generate a short data set that follows a decaying exponential with some white noise on top and then fit it.
To get it running in Code::Blocks in windows I followed the procedure outlined here: installing GSL on Windows XP 32bit for use with codeblocks
It compiles without warnings even with -Wall and -Wextra flags. However, it fails on the line: gsl_multifit_fdfsolver_set (s, &f, &x.vector); with the error: multifit\fdfsolver.c:132: ERROR: vector length does not match solver. Default GSL error handler invoked.
I was a little surprised to find this in what should be raw example code, but here we are. So I am hoping someone more knowledgeable than I can tell me what I am doing wrong with this simple example.
Figured it out: They were allocating their initial vector wrong. The fixed code is here:
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_blas.h>
#include <gsl/gsl_multifit_nlin.h>
#define N 40
#define FIT(i) gsl_vector_get(s->x, i)
#define ERR(i) sqrt(gsl_matrix_get(covar,i,i))
struct data {
size_t n;
double * y;
double * sigma;
};
int expb_f (const gsl_vector * x, void *data, gsl_vector * f)
{
size_t n = ((struct data *)data)->n;
double *y = ((struct data *)data)->y;
double *sigma = ((struct data *) data)->sigma;
double A = gsl_vector_get (x, 0);
double lambda = gsl_vector_get (x, 1);
double b = gsl_vector_get (x, 2);
size_t i;
for (i = 0; i < n; i++)
{
/* Model Yi = A * exp(-lambda * i) + b */
double t = i;
double Yi = A * exp (-lambda * t) + b;
gsl_vector_set (f, i, (Yi - y[i])/sigma[i]);
}
return GSL_SUCCESS;
}
int expb_df (const gsl_vector * x, void *data, gsl_matrix * J)
{
size_t n = ((struct data *)data)->n;
double *sigma = ((struct data *) data)->sigma;
double A = gsl_vector_get (x, 0);
double lambda = gsl_vector_get (x, 1);
size_t i;
for (i = 0; i < n; i++)
{
/* Jacobian matrix J(i,j) = dfi / dxj, */
/* where fi = (Yi - yi)/sigma[i], */
/* Yi = A * exp(-lambda * i) + b */
/* and the xj are the parameters (A,lambda,b) */
double t = i;
double s = sigma[i];
double e = exp(-lambda * t);
gsl_matrix_set (J, i, 0, e/s);
gsl_matrix_set (J, i, 1, -t * A * e/s);
gsl_matrix_set (J, i, 2, 1/s);
}
return GSL_SUCCESS;
}
int expb_fdf (const gsl_vector * x, void *data, gsl_vector * f, gsl_matrix * J)
{
expb_f (x, data, f);
expb_df (x, data, J);
return GSL_SUCCESS;
}
void print_state (size_t iter, gsl_multifit_fdfsolver * s);
int main (void)
{
const gsl_multifit_fdfsolver_type *T;
gsl_multifit_fdfsolver *s;
int status;
unsigned int i, iter = 0;
const size_t n = N;
const size_t p = 3;
gsl_matrix *covar = gsl_matrix_alloc (p, p);
double y[N], sigma[N];
struct data d = { n, y, sigma};
gsl_multifit_function_fdf f;
gsl_vector *x = gsl_vector_alloc(p);
for (i=0; i<p; i++)
{
gsl_vector_set(x,i,i==0 ? 1 : 0);
}
const gsl_rng_type * type;
gsl_rng * r;
gsl_rng_env_setup();
type = gsl_rng_default;
r = gsl_rng_alloc (type);
f.f = &expb_f;
f.df = &expb_df;
f.fdf = &expb_fdf;
f.n = n;
f.p = p;
f.params = &d;
/* This is the data to be fitted */
for (i = 0; i < n; i++)
{
double t = i;
y[i] = 1.0 + 5 * exp (-0.1 * t) + gsl_ran_gaussian (r, 0.1);
sigma[i] = 0.1;
printf ("data: %u %g %g\n", i, y[i], sigma[i]);
};
T = gsl_multifit_fdfsolver_lmsder;
s = gsl_multifit_fdfsolver_alloc (T, n, p);
gsl_multifit_fdfsolver_set (s, &f, x);
print_state (iter, s);
do
{
iter++;
status = gsl_multifit_fdfsolver_iterate (s);
printf ("status = %s\n", gsl_strerror (status));
print_state (iter, s);
if (status)
break;
status = gsl_multifit_test_delta (s->dx, s->x,
1e-4, 1e-4);
}
while (status == GSL_CONTINUE && iter < 500);
gsl_multifit_covar (s->J, 0.0, covar);
{
double chi = gsl_blas_dnrm2(s->f);
double dof = n - p;
double c = GSL_MAX_DBL(1, chi / sqrt(dof));
printf("chisq/dof = %g\n", pow(chi, 2.0) / dof);
printf ("A = %.5f +/- %.5f\n", FIT(0), c*ERR(0));
printf ("lambda = %.5f +/- %.5f\n", FIT(1), c*ERR(1));
printf ("b = %.5f +/- %.5f\n", FIT(2), c*ERR(2));
}
printf ("status = %s\n", gsl_strerror (status));
gsl_multifit_fdfsolver_free (s);
gsl_matrix_free (covar);
gsl_rng_free (r);
gsl_vector_free(x);
return 0;
}
void print_state (size_t iter, gsl_multifit_fdfsolver * s)
{
printf ("iter: %3u x = % 15.8f % 15.8f % 15.8f "
"|f(x)| = %g\n",
iter,
gsl_vector_get (s->x, 0),
gsl_vector_get (s->x, 1),
gsl_vector_get (s->x, 2),
gsl_blas_dnrm2 (s->f));
}
I'm trying to compile the following C-code:
struct data {
size_t n;
double * y;
double * sigma;
};
int
expb_f (const gsl_vector * x, void *data,
gsl_vector * f)
{
size_t n = ((struct data *)data)->n;
double *y = ((struct data *)data)->y;
double *sigma = ((struct data *) data)->sigma;
double A = gsl_vector_get (x, 0);
double lambda = gsl_vector_get (x, 1);
double b = gsl_vector_get (x, 2);
size_t i;
for (i = 0; i < n; i++)
{
/* Model Yi = A * exp(-lambda * i) + b */
double t = i;
double Yi = A * exp (-lambda * t) + b;
gsl_vector_set (f, i, (Yi - y[i])/sigma[i]);
}
return GSL_SUCCESS;
}
int
expb_df (const gsl_vector * x, void *data,
gsl_matrix * J)
{
size_t n = ((struct data *)data)->n;
double *sigma = ((struct data *) data)->sigma;
double A = gsl_vector_get (x, 0);
double lambda = gsl_vector_get (x, 1);
size_t i;
for (i = 0; i < n; i++)
{
/* Jacobian matrix J(i,j) = dfi / dxj, */
/* where fi = (Yi - yi)/sigma[i], */
/* Yi = A * exp(-lambda * i) + b */
/* and the xj are the parameters (A,lambda,b) */
double t = i;
double s = sigma[i];
double e = exp(-lambda * t);
gsl_matrix_set (J, i, 0, e/s);
gsl_matrix_set (J, i, 1, -t * A * e/s);
gsl_matrix_set (J, i, 2, 1/s);
}
return GSL_SUCCESS;
}
int
expb_fdf (const gsl_vector * x, void *data,
gsl_vector * f, gsl_matrix * J)
{
expb_f (x, data, f);
expb_df (x, data, J);
return GSL_SUCCESS;
}
My source is http://www.gnu.org/software/gsl/manual/html_node/Example-programs-for-Nonlinear-Least_002dSquares-Fitting.html#Example-programs-for-Nonlinear-Least_002dSquares-Fitting
The issue is that whenever I try to compile it I get the following error "alt.c:8:1: error: unknown type name ‘gsl_vector’
expb_f (const gsl_vector * x, void *data,"
I'm unsure of how to go about fixing this and would really appreciate any advice.
You need the include for the Gnu Scientific Library, xxx for the appropriate include.
#include <gsl/xxx.h>
You need to include gsl_vector.h, directly or indirectly
I've wanted to create program that generates fractals on my GPU.
First I created a working project in C, after that I tried to convert it into CUDA/C.
Unfortunately, after I did it I saw that there is a difference in results of CPU and GPU.
I spend few hours thinking what I did wrong and it's a mystery to me.
IMO: It seems that there is a difference of calculating values in while loop, therefore it ends earlier than in normal CPU function.
Question: is there any possibility that it is true? And if, what can I do to avoid that kind of computing error?
Here's my entire code:
// C libs
#include <stdint.h>
#include <stdio.h>
#include <iostream>
// Help libs
#include <windows.h>
#include <math.h>
// CUDA libs
#include "cuda.h"
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
__global__ void calulateFractal(unsigned char *a, int N, double c_re, double c_im, int width, int height, double minX, double maxX, double minY, double maxY, double ratioX, double ratioY, int maxLevel)
{
int i = blockIdx.x * blockDim.x + threadIdx.x;
if(i < N)
{
int x = i % width;
int y = i / width;
double p_im = y * ratioY + minY;
double p_re = x * ratioX + minX;
double z_re = p_re;
double z_im = p_im;
int iteration = 0;
while ((z_re * z_re + z_im * z_im) < 4 && iteration < maxLevel)
{
double tmp_re = z_re * z_re - z_im * z_im + c_re;
double tmp_im = 2 * z_re * z_im + c_im;
z_re = tmp_re;
z_im = tmp_im;
iteration++;
}
a[i] = iteration;
}
}
void calulateFractalCPU(unsigned char *a, int i, double c_re, double c_im, int width, int height, double minX, double maxX, double minY, double maxY, double ratioX, double ratioY, int maxLevel)
{
int x = i % width;
int y = i / width;
double p_im = y * ratioY + minY;
double p_re = x * ratioX + minX;
double z_re = p_re;
double z_im = p_im;
int iteration = 0;
while ((z_re * z_re + z_im * z_im) < 4 && iteration < 99)
{
double tmp_re = z_re * z_re - z_im * z_im + c_re;
double tmp_im = 2 * z_re * z_im + c_im;
z_re = tmp_re;
z_im = tmp_im;
iteration++;
}
a[i] = iteration;
}
int saveFractalToBitmap(unsigned char **colorsArray, unsigned char *bitmap, int width, int height, char *filename)
{
// Bitmap structures to be written to file
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
// Fill BITMAPFILEHEADER structure
memcpy((char *)&bfh.bfType, "BM", 2);
bfh.bfSize = sizeof(bfh) + sizeof(bih) + 3*height*width;
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits = sizeof(bfh) + sizeof(bih);
// Fill BITMAPINFOHEADER structure
bih.biSize = sizeof(bih);
bih.biWidth = width;
bih.biHeight = height;
bih.biPlanes = 1;
bih.biBitCount = 24;
bih.biCompression = BI_RGB; // uncompressed 24-bit RGB
bih.biSizeImage = 0; // can be zero for BI_RGB bitmaps
bih.biXPelsPerMeter = 3780; // 96dpi equivalent
bih.biYPelsPerMeter = 3780;
bih.biClrUsed = 0;
bih.biClrImportant = 0;
// Open bitmap file (binary mode)
FILE *f;
f = fopen(filename, "wb");
if(f == NULL)
return -1;
// Write bitmap file header
fwrite(&bfh, 1, sizeof(bfh), f);
fwrite(&bih, 1, sizeof(bih), f);
// Write bitmap pixel data starting with the
// bottom line of pixels, left hand side
for (int i = 0; i < width * height ; i++)
{
// Write pixel components in BGR order
fputc(colorsArray[bitmap[i]][2], f);
fputc(colorsArray[bitmap[i]][1], f);
fputc(colorsArray[bitmap[i]][0], f);
}
// Close bitmap file
fclose(f);
return 0;
}
int main()
{
unsigned char **colorsArray;
unsigned char *fractalLevelsCPU;
unsigned char *fractalLevelsGPU;
double minX = -1.7;
double maxX = 1.7;
double minY = -1.5;
double maxY = 1.5;
double input_re = -0.79;
double input_im = 0.1463;
int width = 10;
int height = 5;
int N = width * height;
int maxLevel = 100;
size_t levelsArraySize = N * sizeof(unsigned char);
double ratioX = (maxX - minX) / (double) width;
double ratioY = (maxY - minY) / (double) height;
bool gpu = true;
// Allocate memory
colorsArray = (unsigned char**) malloc((maxLevel+1) * sizeof(unsigned char*));
for(int i=0; i<=maxLevel; i++)
{
colorsArray[i] = (unsigned char *) malloc(3 * sizeof(unsigned char));
colorsArray[i][0] = (int) (255.0 * i / maxLevel);
colorsArray[i][1] = (int) (255.0 * i / maxLevel);
colorsArray[i][2] = (int) (255.0 * log((double) i) / log((double) maxLevel));
}
fractalLevelsCPU = (unsigned char*) malloc(levelsArraySize);
cudaMalloc((unsigned char **) &fractalLevelsGPU, levelsArraySize);
cudaMemcpy(fractalLevelsCPU, fractalLevelsGPU, levelsArraySize, cudaMemcpyHostToDevice);
if(gpu)
{
// Run GPU method
calulateFractal <<< 1, N >>> (fractalLevelsGPU, N, input_re, input_im, width, height, minX, maxX, minY, maxY, ratioX, ratioY, maxLevel);
// Copy data from GPU to CPU array
cudaMemcpy(fractalLevelsCPU, fractalLevelsGPU, levelsArraySize, cudaMemcpyDeviceToHost);
}
else
{
// Iterate every element in array and compute level of fractal
for(int i=0; i<N; i++)
{
calulateFractalCPU(fractalLevelsCPU, i, input_re, input_im, width, height, minX, maxX, minY, maxY, ratioX, ratioY, maxLevel);
}
}
// Show results
for(int i=0; i<N; i++)
{
if((i % width) == 0)
printf("\n");
printf("%d\t", fractalLevelsCPU[i]);
}
//saveFractalToBitmap(colorsArray, fractalLevelsCPU, width, height, "frac.bmp");
// Free memory
for(int i=0; i<=maxLevel; i++)
{
free(colorsArray[i]);
}
free(colorsArray);
free(fractalLevelsCPU);
cudaFree(fractalLevelsGPU);
return 0;
}
I've find solution to my problem.
First of all, number of threads per block should be a power of two number.
Also I realized that my GPU has it's limits for number of threads per block and blocks itself.
NVIDIA Utils showed me that I can use max 65536 blocks and 512 threads per block.
Solution:
int threadsPerBlock = 512;
int blocksNumber = N/threadsPerBlock + (N % threadsPerBlock == 0 ? 0:1);
if(blocksNumber > 65536)
return -1;
calulateFractal <<< blocksNumber, threadsPerBlock >>> (fractalLevelsGPU, N, input_re, input_im, width, height, minX, maxX, minY, maxY, ratioX, ratioY, maxLevel);