views:

186

answers:

3

I don't understand why this would give me a seg fault. Any ideas?

This is the function that returns the signal to stop the program (plus the other function that is called within this):

double bisect(double A0,double A1,double Sol[N],double tol,double c)
{
  double Amid,shot;

  while (A1-A0 > tol) {
    Amid = 0.5*(A0+A1);

    shot = shoot(Sol, Amid, c);

    if (shot==2.*Pi) {
      return Amid;
    }

    if (shot > 2.*Pi){
      A1 = Amid;
    }
    else if (shot < 2.*Pi){
      A0 = Amid;
    }
  }

  return 0.5*(A1+A0);
}

double shoot(double Sol[N],double A,double c)
{
  int i,j;

  /*Initial Conditions*/
  for (i=0;i<buff;i++)
    {
      Sol[i] = 0.;
    }
  for (i=buff+l;i<N;i++)
    {
      Sol[i] = 2.*Pi;
    }
  Sol[buff]= 0;
  Sol[buff+1]= A*exp(sqrt(1+3*c)*dx);


  for (i=buff+2;i<buff+l;i++)
    {
      Sol[i] = (dx*dx)*( sin(Sol[i-1]) + c*sin(3.*(Sol[i-1])) )
 - Sol[i-2] + 2.*Sol[i-1];
    }

  return Sol[i-1];
}

The values buff, l, N are defined using a #define statement. l = 401, buff = 50, N = 2000

Here is the full code:

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

#define w 10    /*characteristic width of a soliton*/
#define dx 0.05 /*distance between lattice sites*/
#define s (2*w)/dx  /*size of soliton shape*/
#define l (int)(s+1)   /*array length for soliton*/
#define N (int)2000    /*length of field array--lattice sites*/
#define Pi (double)4*atan(1)
#define buff (int)50


double shoot(double Sol[N],double A,double c);
double bisect(double A0,double A1,double Sol[N],double tol,double c);
void super_pos(double antiSol[N],double Sol[N],double phi[][N]);
void vel_ver(double phi[][N],double v,double c,int tsteps,double dt);



int main(int argc, char **argv)
{
  double c,Sol[N],antiSol[N],A,A0,A1,tol,v,dt;
  int  tsteps,i;
  FILE *fp1,*fp2,*fp3;

  fp1 = fopen("soliton.dat","w");
  fp2 = fopen("final-phi.dat","w");
  fp3 = fopen("energy.dat","w");
  printf("Please input the number of time steps:");
  scanf("%d",&tsteps);
  printf("Also, enter the time step size:");
  scanf("%lf",&dt);
  do{
    printf("Please input the parameter c in the interval [-1/3,1]:");
    scanf("%lf",&c);}
  while(c < (-1./3.) || c > 1.);
  printf("Please input the inital speed of eiter soliton:");
  scanf("%lf",&v);

  double phi[tsteps+1][N];

  tol = 0.0000001;
  A0 = 0.;
  A1 = 2.*Pi;
  A = bisect(A0,A1,Sol,tol,c);
  shoot(Sol,A,c);
  for (i=0;i<N;i++)
    {
      fprintf(fp1,"%d\t",i);
      fprintf(fp1,"%lf\n",Sol[i]);
    }
  fclose(fp1);
  super_pos(antiSol,Sol,phi);
  /*vel_ver(phi,v,c,tsteps,dt);
  for (i=0;i<N;i++){
    fprintf(fp2,"%d\t",i);
    fprintf(fp2,"%lf\n",phi[tsteps][i]);
    }*/


}


double shoot(double Sol[N],double A,double c)
{
  int i,j;

  /*Initial Conditions*/
  for (i=0;i<buff;i++)
    {
      Sol[i] = 0.;
    }
  for (i=buff+l;i<N;i++)
    {
      Sol[i] = 2.*Pi;
    }
  Sol[buff]= 0;
  Sol[buff+1]= A*exp(sqrt(1+3*c)*dx);


  for (i=buff+2;i<buff+l;i++)
    {
      Sol[i] = (dx*dx)*( sin(Sol[i-1]) + c*sin(3.*(Sol[i-1])) )
    - Sol[i-2] + 2.*Sol[i-1];
    }

  return Sol[i-1];
}


double bisect(double A0,double A1,double Sol[N],double tol,double c)
{
  double Amid,shot;

  while (A1-A0 > tol) {
    Amid = 0.5*(A0+A1);

    shot = shoot(Sol, Amid, c);

    if (shot==2.*Pi) {
      return Amid;
    }

    if (shot > 2.*Pi){
      A1 = Amid;
    }
    else if (shot < 2.*Pi){
      A0 = Amid;
    }
  }

  return 0.5*(A1+A0);
}


void super_pos(double antiSol[N],double Sol[N],double phi[][N])
{
  int i;

  /*for (i=0;i<N;i++)
    {
    phi[i]=0;
    }

  for (i=buffer+s;i<1950-s;i++)
    {
      phi[i]=2*Pi;
      }*/

  for (i=0;i<N;i++)
    {
      antiSol[i] = Sol[N-i];
    }

  /*for (i=0;i<s+1;i++)
    {
      phi[buffer+j] = Sol[j];
      phi[1549+j] = antiSol[j];
      }*/

  for (i=0;i<N;i++)
    {
      phi[0][i] = antiSol[i] + Sol[i] - 2.*Pi;
    }

}

/* This funciton will set the 2nd input array to the derivative at the time t, for all points x in the lattice */
void deriv2(double phi[][N],double DphiDx2[][N],int t)
{
  //double SolDer2[s+1];
  int x;
  for (x=0;x<N;x++)
    {
      DphiDx2[t][x] = (phi[buff+x+1][t] + phi[buff+x-1][t] - 2.*phi[x][t])/(dx*dx);
    }

  /*for (i=0;i<N;i++)
    {
      ptr[i] = &SolDer2[i];
      }*/

  //return DphiDx2[x];
  }




void vel_ver(double phi[][N],double v,double c,int tsteps,double dt)
{
  int t,x;
  double d1,d2,dp,DphiDx1[tsteps+1][N],DphiDx2[tsteps+1][N],dpdt[tsteps+1][N],p[tsteps+1][N];

  for (t=0;t<tsteps;t++){
    if (t==0){
      for (x=0;x<N;x++){//inital conditions
    deriv2(phi,DphiDx2,t);
    dpdt[t][x] = DphiDx2[t][x] - sin(phi[t][x]) - sin(3.*phi[t][x]);
    DphiDx1[t][x] = (phi[t][x+1] - phi[t][x])/dx;
    p[t][x] = -v*DphiDx1[t][x];
      }
    }
    for (x=0;x<N;x++){//velocity-verlet
      phi[t+1][x] = phi[t][x] + dt*p[t][x] + (dt*dt/2)*dpdt[t][x];
      p[t+1][x] = p[t][x] + (dt/2)*dpdt[t][x];
      deriv2(phi,DphiDx2,t+1);
      dpdt[t][x] = DphiDx2[t][x] - sin(phi[t+1][x]) - sin(3.*phi[t+1][x]);
      p[t+1][x] += (dt/2)*dpdt[t+1][x];
    }
  }  
}

So, this really isn't due to my overwriting the end of the Sol array. I've commented out both functions that I suspected of causing the problem (bisect or shoot) and inserted a print function. Two things happen. When I have code like below:

double A,Pi,B,c;

c=0;
Pi = 4.*atan(1.);
A = Pi;
B = 1./4.;
printf("%lf",B);
B = shoot(Sol,A,c);
printf("%lf",B);

I get a segfault from the function, shoot. However, if I take away the shoot function so that I have:

double A,Pi,B,c;

c=0;
Pi = 4.*atan(1.);
A = Pi;
B = 1./4.;
printf("%lf",B);

it gives me a segfault at the printf... Why!?

A: 

Perhaps you are writing past the end of the Sol array?

I suggest that you start by using a debugger such as gdb to figure out what line is causing the segmentation fault.

Justin Ethier
I know what line--or at least in my calling code. I used ddd and the signal is at line 45 my code w/ main, which is the line where I call bisect. And Sol has a size much bigger than buff+l and i only do a loop with N once and I've checked and double checked that my i is < N... is there a way in a debugger to determine where in the function the problem is coming from?
A: 

Personally, I think using #define for those constants makes your function less reusable. Why not pass those in? At least that way users of your function know what's needed by looking at the function.

I see magic numbers in lots of places. I don't care for this method much at all.

duffymo
sure, certainly. i'm opposed to magic numbers myself. I'm just trying to get this running first. I'll put the rest of the code up though
-1 this should've been a comment
Earlz
A: 

So, this has been resolved. The problem was with memory. I was using several arrays of GREAT size phi[tsteps+1][N] (N=2000) and the like. When tsteps came in from user (my own) input it was on the order of 20,000. So, the memory overload caused the program to crash runtime. Thanks for all the suggestions, you all.