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));
}
Related
I am trying to create some functions to handle vector and matrix operations. The vector sum function works as expected, but the dot product function returns always zeros. What I am doing wrong?
Also, I am not sure if this is the best way to handle the problem. I am creating a script for nonlinear optimization. My idea is to allocate memory for the auxiliary scalars, vectors and matrices that are reused on each iteration. The functions are void type to so I can keep track of all variables created in the program.
#include <stdio.h>
void dot (const double *v_1, const double *v_2, double s_out)
{
s_out = v_1[0] * v_2[0] + v_1[1] * v_2[1];
}
void sum (double *v_1, double *v_2, double *v_out)
{
v_out[0] = v_1[0] + v_2[0];
v_out[1] = v_1[1] + v_2[1];
}
int main ()
{
double *r;
double *t;
r = malloc(sizeof(double)*2);
t = malloc(sizeof(double)*2);
r[0] = 1; r[1] = 2;
double rho_new = 0;
dot (r, r, rho_new);
printf("rho_new = %lf\n", rho_new);
sum (r, r, t);
printf("t = %lf %lf\n", t[0], t[1]);
}
Two options to return value from the function.
#include <stdio.h>
double dot (const double *v_1, const double *v_2)
{
return v_1[0] * v_2[0] + v_1[1] * v_2[1];
}
void sum (double *v_1, double *v_2, double *v_out)
{
v_out[0] = v_1[0] + v_2[0];
v_out[1] = v_1[1] + v_2[1];
}
int main ()
{
double *r;
double *t;
r = malloc(sizeof(double)*2);
t = malloc(sizeof(double)*2);
r[0] = 1; r[1] = 2;
double rho_new = 0;
rho_new = dot(r, r, rho_new);
printf("rho_new = %lf\n", rho_new);
sum (r, r, t);
printf("t = %lf %lf\n", t[0], t[1]);
}
#include <stdio.h>
void dot (const double *v_1, const double *v_2, double *s_out)
{
*s_out = v_1[0] * v_2[0] + v_1[1] * v_2[1];
}
void sum (double *v_1, double *v_2, double *v_out)
{
v_out[0] = v_1[0] + v_2[0];
v_out[1] = v_1[1] + v_2[1];
}
int main ()
{
double *r;
double *t;
r = malloc(sizeof(double)*2);
t = malloc(sizeof(double)*2);
r[0] = 1; r[1] = 2;
double rho_new = 0;
dot (r, r, &rho_new);
printf("rho_new = %lf\n", rho_new);
sum (r, r, t);
printf("t = %lf %lf\n", t[0], t[1]);
}
I'm trying to parallelize my code, but i got errors. I need to calc a Cauchy problem (it's already done) but than i need to parallelize it using OpenMP lib.
I've tried to write some code with OpenMP, but it's not working.
I've created a struct to collect result.
struct Dots {
double par;
double x;
double y;
};
This is my target function with parameter.
int ode_func (double x, const double y[], double f[], void *params)
{
double mu = *(int *)params;
f[0] = x + 2 * y[0] / (1 + mu * mu);
return GSL_SUCCESS;
}
This is the main function. I currently didn't find a way how to create a array of arrays of struct, but this is not the main problem.
void calc_cauchy_problem(struct Dots ArrayOfDots[], double x_start, double x_end, double y_start,
int count) {
int dim = 1;
double x = x_start;
double y[1] = {y_start};
int mu = 5;
int param = 0;
gsl_odeiv2_system sys = {ode_func, NULL, dim, ¶m};
gsl_odeiv2_driver * d = gsl_odeiv2_driver_alloc_y_new (&sys,
gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
int status = 0;
#pragma omp parallel for shared(ArrayOfDots) private(sys, param, d, status)
for (int param = 1; param < mu; param++) {
gsl_odeiv2_system sys = {ode_func, NULL, dim, ¶m};
gsl_odeiv2_driver * d = gsl_odeiv2_driver_alloc_y_new (&sys,
gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
for (int i = 1; i <= count; i++)
{
double xi = x_start + i * (x_end - x_start) / count;
int status = gsl_odeiv2_driver_apply(d, &x, xi, y);
if (status != GSL_SUCCESS)
{
printf ("error, return value=%d\n", status);
break;
}
// ArrayOfDots[i].par = mu;
// ArrayOfDots[i].x = xi;
// ArrayOfDots[i].y = y[0];
}
gsl_odeiv2_driver_free (d);
}
}
The main
int main() {
double x_start = 0;
double x_end = 10;
double y_start = 0;
int count = 10;
struct Dots ArrayOfDots[count];
calc_cauchy_problem(ArrayOfDots, x_start, x_end, y_start, count);
return 0;
}
It's compiled successfully with this gcc main.c -o main -fopenmp -lgsl -std=gnu11 but when i launch it i got error
gsl: driver.c:354: ERROR: integration limits and/or step direction not consistent
Default GSL error handler invoked.
I think that the main problem with this #pragma omp parallel for shared(ArrayOfDots) private(sys, param, d, status) but i have no idea how to rewrite this in the other way.
Thanks for your responses.
UPD:
With Kaveh Vahedipour help my code partially start to work. It means that half of my for cycle start to work.
UPD UPD:
After another investigations i had the following code:
It's compile and run, but i got Process finished with exit code 4 and printf("Elapsed time = %f\n", omp_get_wtime() - start_time); don't print anything.
struct Dots {
double par;
double x;
double y;
};
int ode_func (double x, const double y[], double f[], void *params)
{
double mu = *(int *)params;
f[0] = (x + 2 * y[0]) / (1 + mu * mu);
return GSL_SUCCESS;
}
void calc_cauchy_problem(double x_start, double x_end, double y_start,
int count, int param1, int param2) {
int dim = 1;
double x = x_start;
double y[1] = {y_start};
int param = param1;
int j = 0;
int status = 0;
char filename[10];
#pragma omp parallel for private(param, status, x, y)
for (param = param1; param <= param2; param++) {
struct Dots ArrayOfDots[count];
gsl_odeiv2_system sys = {ode_func, NULL, dim, ¶m};
gsl_odeiv2_driver * d =
gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
for (int i = 1; i <= count; i++) {
double xi = x_start + i * (x_end - x_start) / count;
int status = gsl_odeiv2_driver_apply(d, &x, xi, y);
if (status != GSL_SUCCESS)
{
printf ("error, return value=%d\n", status);
break;
}
ArrayOfDots[i].par = param;
ArrayOfDots[i].x = xi;
ArrayOfDots[i].y = y[0];
}
gsl_odeiv2_driver_free (d);
}
}
int main() {
double start_time = omp_get_wtime();
double x_start = 0;
double x_end = 10;
double y_start = 0;
const int count = 500;
int param1 = 1;
int param2 = 10;
calc_cauchy_problem(x_start, x_end, y_start, count, param1, param2);
printf("Elapsed time = %f\n", omp_get_wtime() - start_time);
return 0;
}
Add x to private loop vars: private(sys, param, d, status, x). Please get back to me, if you still experience issues.
void calc_cauchy_problem(double x_start, double x_end, double y_start,
int count, int param1, int param2) {
int dim = 1;
double x = x_start;
double y[1] = {y_start};
int param = param1;
int j = 0;
int status = 0;
char filename[10];
#pragma omp parallel for private(param, status, x, y)
for (param = param1; param <= param2; param++) {
struct Dots ArrayOfDots[count];
gsl_odeiv2_system sys = {ode_func, NULL, dim, ¶m};
gsl_odeiv2_driver * d =
gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
for (int i = 1; i <= count; i++) {
double xi = x_start + i * (x_end - x_start) / count;
int status = gsl_odeiv2_driver_apply(d, &x, xi, y);
if (status != GSL_SUCCESS)
{
printf ("error, return value=%d\n", status);
break;
}
ArrayOfDots[i].par = param;
ArrayOfDots[i].x = xi;
ArrayOfDots[i].y = y[0];
}
//write_data_to_file(param, count, ArrayOfDots);
for (int i = 0; i < count; ++i) {
printf ("%d: %f, %f, %f\n", omp_get_thread_num(),
ArrayOfDots[i].par, ArrayOfDots[i].x, ArrayOfDots[i].y);
}
gsl_odeiv2_driver_free (d);
}
}
Seems like this version works fine. I think problem was with this struct Dots ArrayOfDots[count]; and when i try to push values to this struct.
ArrayOfDots[i].par = param;
ArrayOfDots[i].x = xi;
ArrayOfDots[i].y = y[0];
Here is the full code.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <omp.h>
// GSL lib includes
#include <gsl/gsl_sf_bessel.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_odeiv2.h>
int ode_func (double x, const double y[], double f[], void *params)
{
double mu = *(int *)params;
f[0] = (x + 2 * y[0]) / (1 + mu * mu);
return GSL_SUCCESS;
}
void calc_cauchy_problem(double x_start, double x_end, double y_start,
int count, int param1, int param2) {
#pragma omp parallel for
for(int param = param1; param < param2; param++) {
gsl_odeiv2_system sys = {ode_func, NULL, 1, ¶m};
gsl_odeiv2_driver * d =
gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rk8pd,
1e-6, 1e-6, 0.0);
int i;
double x = x_start, x1 = x_end;
double y[1] = { y_start };
for (i = 1; i <= count; i++)
{
double xi = i * x1 / count;
int status = gsl_odeiv2_driver_apply (d, &x, xi, y);
if (status != GSL_SUCCESS)
{
printf ("error, return value=%d\n", status);
break;
}
// printf ("%d %d %.5e %.5e\n", omp_get_thread_num(), param, x, y[0]);
}
gsl_odeiv2_driver_free (d);
}
}
int main() {
double start_time = omp_get_wtime();
double x_start = 0;
double x_end = 10;
double y_start = 0;
const int count = 100000;
int param1 = 1;
int param2 = 20;
calc_cauchy_problem(x_start, x_end, y_start, count, param1, param2);
printf("Elapsed time = %f\n", omp_get_wtime() - start_time);
return 0;
}
Really thanks to Kaveh Vahedipour.
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.
I am tyring to make velocity Verlet method, by using C language.
I thought I made it good. However, there pops up 'Segmentation fault(core dumped)' whenever, I increase the size of the vector or array, x and y.
For the size n equal and less than 1e3, it's fine, but at the point of n = 1e4, the program gets error.
Please anybody help me on this.
Thank you.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
double verlet(double t, double x)
{
double E = 0.252;
double B = 0.052;
double a = M_PI/2;
return -sin(x) + E*cos(t) + B*cos(2*t+a);
}
double pverlet(double(*f)(double, double), double dt, double t, double x, double y)
{
return x + dt*( y + (dt/2)*f(t, x));
}
double vverlet(double(*g)(double, double), double dt, double t, double x, double y)
{
return y + (dt/2) * g(t, x);
}
int main(void)
{
int i;
double t;
int n = 1e4;
double ti = 0, tf = 1e5, dt = (tf-ti)/n;
double *x = (double *) malloc(sizeof(double)*n);
double *y = (double *) malloc(sizeof(double)*2*n);
if (x == NULL)
{
printf("error allocating memory!\n");
return 1;
}
if (y == NULL)
{
printf("error allocating memory!\n");
return 1;
}
for (y[0] = 0, i = 1; i <2*n; i++)
{
y[i] = vverlet(verlet, dt, ti + dt*(i-1), x[i-1], y[i-1]);
}
for (x[0] = 0, i = 1; i < n; i++)
{
x[i] = pverlet(verlet, dt, ti + dt*(i-1), x[i-1], y[2*(i-1)]);
}
for (i = 0; i < n; i++)
{
t = ti + dt * i;
printf("%e %e %e\n", t, x[i], y[2*i]);
}
return 0;
free(x);
free(y);
}
for (y[0] = 0, i = 1; i <2*n; i++)
{
y[i] = vverlet(verlet, dt, ti + dt*(i-1), x[i-1], y[i-1]);
}
x is defined from 0 to n-1.
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