-1

This is the piece of code I have which prints my diffused density matrices to a file after every nth time step of the simulation time given by fdparam_1.t_domain. t and fdparam_1.Dt are variables of the type double. All variables are declared and defined either with user input or with pre-defined values in the code.

Please note that the last time I posted the code for the segmentation fault, I modified the code as per the suggestions and this piece of code below is the modified one, although the operations are obviously the same.

    int main(void)
    {
    int i,j,size,sz;
    double *ux, *vy, *ux0, *vy0, *r, *r0, t, sum, sum1;
    struct fdparam fdparam_1;


    printf("Enter the number of grid points: \t");
    scanf("%d", &fdparam_1.N);

    printf("Enter the maximum number of iterations: \t");
    scanf("%d", &fdparam_1.MAXIT);

    printf("Enter the value for time domain and the time interval: \t");
    scanf("%d\t%d", &fdparam_1.t_domain, &fdparam_1.Del_t);

    printf("Enter the time step, number of molecules: \t \t");
    scanf("%lf\t%lf", &fdparam_1.Dt,  &fdparam_1.dens);

    printf("Enter the volume of the fluid: \t");
    scanf("%lf", &fdparam_1.V);

    printf("Enter the diffusion coefficient and viscosity and angular velocity(in rad/s): \t \t");
    scanf("%lf\t%lf\t%lf",&fdparam_1.diff, &fdparam_1.mu, &fdparam_1.wv);

    size=(fdparam_1.N+2)*(fdparam_1.N+2);

    sz=fdparam_1.t_domain/fdparam_1.Del_t;

    double map[fdparam_1.N+2][fdparam_1.N+2],map_init[fdparam_1.N+2][fdparam_1.N+2],n_calc, time[sz+1];


    r  = (double*) calloc (size,sizeof(double));
    r0 = (double*) calloc (size,sizeof(double));
    ux = (double*) calloc (size,sizeof(double));
    vy = (double*) calloc (size,sizeof(double));
    ux0 = (double*)calloc (size,sizeof(double));
    vy0 = (double*)calloc (size,sizeof(double));

    double vol = fdparam_1.V;
    FILE *fp1[sz+1];

    var_init(fdparam_1.N,r0,ux0,vy0,fdparam_1.dens);

    sum1=r0[0];

    for (i=0;i<=fdparam_1.N+1;i++){
            for (j=0;j<=fdparam_1.N+1;j++){
                    sum1+=r0[(i)+((fdparam_1.N+2)*j)];
            }
    }

    double n_act = sum1*vol;
    printf("Time = %lf \t Initial Nr. of Molecules is: %e \n",t,n_act);

    int l = 0;

    add_source(fdparam_1.N,r,r0,fdparam_1.Dt);

    t=0;
    int k=0;

 while(t<=fdparam_1.t_domain){

            swap(r0,r);
                            density_solve(fdparam_1.N,r,r0,ux0,vy0,fdparam_1.Dt,fdparam_1.diff,fdparam_1.MAXIT);    //uses ux and vy calculated from Navier Stokes in the velocity solver to calculate density
           // creating multiple files to store the density values during the simulation at every Del_t time interval
            if(((int)(t*100))%fdparam_1.t_domain==0){
                    char filename[sz+1];
                    sprintf(filename,"density%d.txt",l);
                    fp1[l]=fopen(filename,"w");
                    for (i=0;i<=fdparam_1.N+1;i++){
                            for (j=0;j<=fdparam_1.N+1;j++){
                                    map[i][j]=r[(i)+(fdparam_1.N+2)*j];
                                    fprintf(fp1[l],"%lf \t",map[i][j]);
                            }
                            fprintf(fp1[l],"\n");
                    }
                    fclose(fp1[l]);
            sum=r[0];
            for (i=0;i<=fdparam_1.N+1;i++){
                    for (j=0;j<=fdparam_1.N+1;j++){
                            sum+=r[(i)+((fdparam_1.N+2)*j)];
                    }
            }
            n_calc=sum*vol;
            printf("Time = %lf \t Calculated Nr. of Molecules = %e \n",t,n_act);
            }
            l++;
            t+=fdparam_1.Dt;
    }

void add_source(int n, double *x, double *s, double dt)
{
    int i, size;
    size = (n+2)*(n+2);
    for (i=0; i<size; i++)
    {
            x[i]+=s[i]; //add source terms to the density
    }
}

I am sorry the code is divided into numerous functions and header files and it is really difficult for me to prepare a minimal working code out of it. The above is my complete main function but here is what is happening now when I run the gdb debugger again without supplying any breakpoint, it seems to be executing the step where it is supposed to print t and n_act because this is the actual expected output which I am supposed to get but I get segmentation fault instead,

Printing source densities now: 
Time = 0.000000      Initial Nr. of Molecules is: 8.820000e+06 
Time = 0.000000      Calculated Nr. of Molecules = 8.820000e+06 
Time = 10.000000     Calculated Nr. of Molecules = 8.820000e+06 
Time = 20.000000     Calculated Nr. of Molecules = 8.820000e+06 

... and so on till Time=1000

  • Repeatedly incrementing a floating point value like that will lead to rounding errors. It would be best to have an integer that you increment, and then calculate `t = int_counter * fdparam_1.Dt;` on each iteration. That will give you maximum accuracy. It is unrelated to your core dump, though. – Jonathan Leffler Jun 18 '15 at 14:36
  • @JonathanLeffler Aah! okay...thanks for that suggestion though. It is nevertheless quite helpful. However, do you have a clue why I might be getting a segmentation fault in the successive iterations? – Sneha Choudhury Jun 18 '15 at 14:39
  • As for debugging; which line of your code triggers the seg fault? The increment of `t` (which seems pretty improbable) or something else? There's really not going to be an easy way to resolve this for us — you have not provided an MCVE ([How to create a Minimal, Complete, and Verifiable Example?](http://stackoverflow.com/help/mcve)). It could be that you have an array access out of control. Actually, all sorts of things are possible. You don't check that the file was opened OK, so it might be that you're trying to write via a null file pointer. – Jonathan Leffler Jun 18 '15 at 14:40
  • Many possibilities. Example, `fopen()` fails, `fprintf()` starts crying.... – Sourav Ghosh Jun 18 '15 at 14:41
  • 1
    run it in GDB again, when it crashes again, use the command `bt` to see the stack trace. That way, you can have some clue in what's going wrong. – vincentleest Jun 18 '15 at 14:41
  • 1
    I suggest that you add some asserts in the various loops to check that the array indexes are in bounds. – Richard Chambers Jun 18 '15 at 14:42
  • Also, for `printf()` using `%f` is recommended for `double`. – Sourav Ghosh Jun 18 '15 at 14:42
  • 1
    @Sneha, this looks suspect to me: `for (i=0;i<=fdparam_1.N+1;i++)`. A typical index goes from 0 to less than something. This has equal, and a +1. What does N represent? – donjuedo Jun 18 '15 at 14:44
  • @JonathanLeffler I tried to increment an integer but it still gives me the same long values of 0.2999....and 0.39999...that didn't seem to work – Sneha Choudhury Jun 18 '15 at 14:45
  • @SnehaChoudhury that will happen as exact floating numbers cant be stored in memory.Read [this](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Sourav Kanta Jun 18 '15 at 14:47
  • @donjuedo N represent the number of grid points which I use to implement the finite difference scheme in computational fluid dynamics. I don't suspect that could be the problem because the statement runs fine elsewhere – Sneha Choudhury Jun 18 '15 at 14:48
  • Find 'What Every Computer Scientist Needs To Know About Floating Point Arithmetic' and read it. A binary floating point number cannot represent most decimal fractions (and specifically not 0.01) exactly. You will get rounding errors. Using the integer arithmetic means that the errors will not accumulate; using floating point arithmetic means they will. – Jonathan Leffler Jun 18 '15 at 14:48
  • Are you using dynamically allocated memory (`malloc()` and friends)? If so, can you run with [`valgrind`](http://www.valgrind.org/)? If you can use it, there's a good chance it will tell you where the error is. – Jonathan Leffler Jun 18 '15 at 14:49
  • @Sneha, it may run fine elsewhere, but that may be just luck. It depends on reading or writing, for one thing. A simple test here could be to allocate extra for that array, and change nothing else. – donjuedo Jun 18 '15 at 14:51
  • I don't think {fopen()} or {fprintf()} fails, because if that happened it would not write the first output file when t=0 but it does write it. So, I doubt that is happening. – Sneha Choudhury Jun 18 '15 at 14:52
  • 1
    Just because you open a file once doesn't mean you'll be able to open a file every time. **Always** check that a file open succeeded before trying to use the file pointer. – Jonathan Leffler Jun 18 '15 at 14:56

1 Answers1

1

Where the issue is:

Based on your previous post, Segmentation fault - Two functions don't run simultaneously, where N is the number of points, it looks like your indexes are going of of bounds.

How to resolve it:

Revise your loop comparisons for i and for j where used for map.

Community
  • 1
  • 1
donjuedo
  • 2,475
  • 18
  • 28
  • 1
    Good tracking down the older question on what is clearly the same program. Note that when the older code does set `size`, it sets it to `size=(fdparam_1.N+2)*(fdparam_1.N+2);` and then uses that to run some `calloc()` operations. Presumably, the problem with defining a bunch of arrays with a dimension of `size` before `size` is given a value has been resolved during the last month or so. – Jonathan Leffler Jun 18 '15 at 14:56
  • This time in the code size is defined before the calloc operations. – Sneha Choudhury Jun 18 '15 at 15:02
  • @donjuedo Okay..now you need to help me understand the issue with `map`...can you please explain what do you mean by allocation of `map` exactly? – Sneha Choudhury Jun 18 '15 at 15:13
  • @Sneha, the updated code in the question shows `map` is allocated as a local variable, and I see the size, too. – donjuedo Jun 18 '15 at 15:15
  • @Sneha, `sz` is smaller than `fdparam_1.t_domain`, because of the division, right? But the while loop iterates to `fdparam_1.t_domain`, and `l` increments each time. It looks like `fp1[l]` could go out of bounds, since `fp1` is only `sz+1`. – donjuedo Jun 18 '15 at 15:19
  • @donjuedo Aah yes, that's right!! then how do I deal with the `l`?? Do you have any suggestions on how I could sort that out? Should I increment `l` inside the if condition statement where I print the output after every nth iteration? – Sneha Choudhury Jun 18 '15 at 15:29
  • @Sneha, since you are opening and closing the file, there is no need to store the fd value longer than that. I would recommend using just one pointer,` fp` and doing away with `l` completely. – donjuedo Jun 18 '15 at 15:34
  • @donjuedo But I want to store different matrices in different files, in the form of different snapshots of my density profile so that in the end I will have density profiles at different times in different files . If I do away with `l` completely, won't it keep overwriting the same file? – Sneha Choudhury Jun 18 '15 at 15:41
  • Sorry, you're right. I missed that embedded in the name. It's OK to keep it for that -- you just won't need it as an index for file pointers. – donjuedo Jun 18 '15 at 15:46
  • @donjuedo I still get the segmentation fault even if I remove `l` as an index for the file pointers – Sneha Choudhury Jun 18 '15 at 16:08
  • @Sneha, while you're at it, please change `char filename[sz+1];` to `char filename[50];` and re-test. – donjuedo Jun 18 '15 at 16:15
  • And did you mean `sum=0;` instead of `sum=r[0];` ? – donjuedo Jun 18 '15 at 16:17
  • @donjuedo Can you explain why I should change the sz+1 to 50? because technically I am supposed to have 100 files if I run the simulation for t=1000 and take the output at intervals of 10. So I will have outputs at t=0,10,20,30....1000. In addition to this, I could do `sum=0` as well but I chose to assign the first element of the `r` i.e. `r[0]` to sum instead. Is that what could be a problem you think? – Sneha Choudhury Jun 18 '15 at 16:39
  • First, there is only one file name variable, and the name length should not depend on sz. With the string literal I see, `density%d.txt`, the name is only going to get to 13, 14, or 15 characters, most likely. 50 is plenty more, so the `sprintf()` call is certain to stay in bounds. The file name will be used for as many files as you wish -- that's not limited. Second, your original code is setting sum to r[0] before the loop, and then the first time in the loops, adding it again (i=0, j=0). I assume you did not intend to add r[0] twice to sum. – donjuedo Jun 18 '15 at 17:16
  • Oh Okay!! Yeah I didn't notice I was adding it twice. Thanks for pointing that out. And also thanks for explaining the change of dimensions for the filename. – Sneha Choudhury Jun 18 '15 at 17:19