Frage

I'm writing a program for an assignment I have at school to model the oscillations of a coupled harmonic oscillator (a block connected to a wall by a spring, and another block connected to the first block by a spring). With this my extension I have chosen is to model n blocks connected by n springs! Up to a reasonable amount, I started by trying 3.

When I attempt to compile it it compiles fine and I can run the program for the first part which only requires input. After that it just crashes, giving a bus error. Here is my code, sorry it might seem like a wall!! It begins by taking a number of values from the command like for the positions of the blocks.

#include    <stdlib.h>
#include    <stdio.h>
#include    <math.h>

/* Set variables for the width of the blocks and rest length of the springs*/
#define     w   1.0
#define     R   1.0

/*Define our external function for finding the runge kutta constants*/
double rkutta(double *xpos, double *omeg, double *j,  int delta, int n, int N);

int main(int argc, char *argv[])
{
FILE*   output;
int     tmp, N;
double  *x, *v, *m, *k, *omega, mtmp, ktmp, t, dt, *xstep, *vstep;

/*Find value of number of masses from the command line*/
N = argc - 1;
dt = 0.001;

/*Allocate array memory for each variable required*/
x = malloc(N*sizeof(double));
v = malloc(N*sizeof(double));
m = malloc(N*sizeof(double));
k = malloc(N*sizeof(double));
omega = malloc((2*N - 1)*sizeof(double));

/*Read values for the x position of each mass from command line*/
if(x != NULL && v != NULL && m != NULL && k != NULL && omega !=NULL)
{
    for(tmp=0; tmp<N; tmp++)
    {
        sscanf(argv[tmp+1], "%lf", &x[tmp]);
    }
}
else
{
    printf("***************************\n");
    printf("**Error allocating arrays**\n");
    printf("***************************\n");
}

/*Check there are an appropriate amount of masses,
if so take values for other quantities from user*/
if(N <= 1)
{
    printf("************************************\n");
    printf("**There must be at least 2 masses!**\n");
    printf("************************************\n");
}
else if(N == 2)
{
    for(tmp=0; tmp<N; tmp++)
    {
        printf("Input a value for the velocity of Block %d\n", tmp+1);
        scanf("%lf", &v[tmp]);
    }

    for(tmp=0; tmp<N; tmp++)
    {
        printf("Input a value for the mass of Block %d\n", tmp+1);
        scanf("%lf", &m[tmp]);
    }

    for(tmp=0; tmp<N; tmp++)
    {
        printf("Input a value for the spring constant of Spring %d\n", tmp+1);
        scanf("%lf", &k[tmp]);
    }
}
else
{
    for(tmp=0; tmp<N; tmp++)
    {
        printf("Input a value for the velocity of Mass %d\n", tmp+1);
        scanf("%lf", &v[tmp]);
    }

    printf("Input a value for the mass of each Block\n");
    scanf("%lf", &mtmp);
    for(tmp=0; tmp<N; tmp++)
    {   
        m[tmp] = mtmp;
    }

    printf("Input a value for the spring constant of each Spring\n");
    scanf("%lf", &ktmp);
    for(tmp=0; tmp<N; tmp++)
    {
        k[tmp] = ktmp;
    }   
}   

/*Compute values of each omega*/
for(tmp=0; tmp<(2*N-1); tmp++)
{
    if(tmp % 2)
    {
        omega[tmp] = k[(tmp+1)/2] / m[(tmp-1)/2];
    }
    else
    {
        omega[tmp] = k[tmp/2] / m[tmp/2];
    }
}

/*Define arrays for runge kutta constants*/
double      *a, *b, *c, *d;

/*Calculate the values of the runge kutta constants*/
for(tmp=0; tmp<(2*N); tmp++)
{
    if(tmp < N)
    {
        a[tmp] = v[tmp];
    }
    else
    {
        a[tmp] = rkutta(x, omega, 0, 0, (tmp-N), N);
    }
}
for(tmp=0; tmp<(2*N); tmp++)
{
    if(tmp < N)
    {
        b[tmp] = v[tmp] + 0.5*dt*a[tmp+2];
    }
    else
    {
        b[tmp] = rkutta(x, omega, a, (0.5*dt), (tmp-N), N);
    }
}
for(tmp=0; tmp<(2*N); tmp++)
{
    if(tmp < N)
    {
        c[tmp] = v[tmp] + 0.5*dt*b[tmp+2];
    }
    else
    {
        c[tmp] = rkutta(x, omega, b, (0.5*dt), (tmp-N), N);
    }
}
for(tmp=0; tmp<(2*N); tmp++)
{
    if(tmp < N)
    {
        d[tmp] = v[tmp] + dt*c[tmp+2];
    }
    else
    {
        d[tmp] = rkutta(x, omega, c, dt, (tmp-N), N);
    }
}

/*Open file to output data*/
output = fopen("1209937_proj1.out", "w");

for(t=0; t<=0.1; t=t+dt)
{

    if(output != (FILE*)NULL)
    {
        fprintf(output, "%lf ", t);
        for(tmp=0; tmp<N; tmp++)
        {
            fprintf(output, "%lf ", x[tmp]);
        }
        for(tmp=0; tmp<N; tmp++)
        {
            if(tmp<N-1)
            {
                fprintf(output, "%lf ", v[tmp]);
            }
            else
            {
                fprintf(output, "%lf\n", v[tmp]);
            }
        }
    }
    else
    {
        printf("*********************************\n");
        printf("**Error outputting data to file**\n");
        printf("*********************************\n");
        return(EXIT_FAILURE);
    }

    /*Use runge kutta to find the next value of v and x*/
    for(tmp=0; tmp<N; tmp++)
    {
        xstep[tmp] = x[tmp] + (dt/6)*(a[tmp]+2*b[tmp]+2*c[tmp]+d[tmp]);

        vstep[tmp] = v[tmp] + (dt/6)*(a[tmp+2]+2*b[tmp+2]);
        vstep[tmp] = vstep[tmp] + (dt/6)*(2*c[tmp+2]+d[tmp+2]);

        x[tmp] = xstep[tmp];
        v[tmp] = vstep[tmp];
    }
}

free(x);
free(v);
free(m);
free(k);
free(omega);
fclose(output); 
return(EXIT_SUCCESS);
}

/*Given various quantities find runge kutta values*/
double rkutta(double *xpos, double *omeg, double *j,  int delta, int n, int N)
{
int     temp;
double  result;

result = 0;

for(temp=0; temp<N; temp++)
{
    xpos[temp] = xpos[temp] + delta*j[temp];
}

if(n=0)
{
    result = -omeg[n]*(xpos[n]-R) + omeg[n+1]*(xpos[n+1]-xpos[n]-w-R);
}
else if(n < N-1)
{
    result = -omeg[2*n]*(xpos[n]-xpos[n-1]-w-R); 
    result = result + omeg[(2*n+1)]*(xpos[n+1]-xpos[n]-w-R);
}
else
{
    result = -omeg[(2*n-1)]*(xpos[n]-xpos[n-1]-w-R);
}

return(result);
}

I haven't really done much programming so I'm sorry if it's something obvious. I just want to fix it. The program runs up until after all the data has been put in by the user.

War es hilfreich?

Lösung

Running in the debugger it fails here for me:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400cfb in main (argc=3, argv=0x7fffffffe508) at t.c:116
116             a[tmp] = v[tmp];

Looking at a we find that its un-initialized.

(gdb) p a
$1 = (double *) 0xc2

Looking at your program, we see that you define:

/*Define arrays for runge kutta constants*/
double      *a, *b, *c, *d;  

But you have not defined an array, you've defined an empty pointer and not set it to anything.

Change this to

double a[100], b[100], c[100], d[100] ;

And then the compiler will create memory for those (at least for N up to 50).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top