C Segmentation Fault in while loop-cannot resolve issue despite debugging - c

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

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.

Related

Why does the following code run out of memory?

The following code describes 2 harmonic oscillators. They are initially uncoupled and independent and am only looking at one of them, which is a mechanical oscillator. The other oscillator's variables have been declared and forced to 0. I first do 300,000 time iterations and do this for 80 different frequencies of wdm (mechanical drive w).
//find frequency response
int index_A;
double wdm_1;
wdm_1=wm-2*3.142*2e5;
double wdm_2;
wdm_2=wm+2*3.142*2e5;
double wdm_prec=2*3.142*5e3;
index_A=(wdm_2-wdm_1)/wdm_prec;
printf("%d \n", index_A);
However, my code runs till 58 frequencies and gives this error:
Strangely, if I run the code in 2 parts of 40 frequencies each and append the files together, it works fine.
Resonance peak in frequency domain
Also, when I reduce the size of v0 to 3, the code works properly. However, I will need the other variables later.
int j=0;
for (j=0; j<= index_A ; j++){
wdm=wdm_1+j*wdm_prec;
printf("%d \n",j);
v0[0] = 0;
v0[1] = 0;
v0[2] = 0;
v0[3] = 0;
v0[4] = 0;
v0[5] = 0;
v0[6]= wdm;
for (i=0; i< n ; i++){
if (cabs(xa)>=1){
printf("Breaking Loop \n");
break;
}
v1 = rk4vec_ameya_complex_1 ( tau, 7, v0, dtau, rk4vec_f_ameya_complex_1 );
memcpy(v0, v1, 4 * sizeof ( double complex ) );
tau=tau+dtau;
}
fprintf(f1, "%g, %g \n", wdm/(2*3.142), cabs(v1[2]) );
}
printf("Completed");
fclose(f1);
At the end of time iterations, I save the value of the frequency wdm and last value of displacement x=v1[2] in a file and move on to do time iterations with another frequency. Hence, my file contains the frequency response.
fprintf(f1, "%g, %g \n", wdm/(2*3.142), cabs(v1[2]) );
I have used runge kutta (rk4.c) from people.sc.fsu.edu/~jburkardt/c_src/rk4/rk4.html and modified it for complex datatype using
#include <complex.h>
Following is the function runge-kutta-4 has to solve:
/******************************************************************************/
double complex *rk4vec_f_ameya_complex_1 ( double t, int n, double complex u[] )
/******************************************************************************/
{
double complex drive_m;
double complex drive_c;
double x;
double xrf0_1;
double complex *uprime;
uprime = ( double * ) malloc ( 7 * sizeof ( double complex ) );
//Check if memory unavailable
if(uprime==NULL){
printf("No memory available \n");
return 0;
}
///////////////////Second Order////////////////////////
xrf0_1=xrf0*(1-exp(-0.2*t));
drive_m=(xrf0*cexp(I*((u[6]-wm)/gammac)*t)/(2*wm*gammac));
uprime[2]=u[3];
uprime[3]=(wm/gammac)*(drive_m-u[3]*(2*I+2*gammam/wm)-u[2]*(2*I*gammam/gammac));
return uprime;
free(uprime);
}
Kindly suggest any solutions if my usage of malloc() is responsible for running out of memory.
One obvious problem - you free uprime after you have returned from rk4vec_f_ameya_complex_1, I'd expect you to be getting an unreachable code warning. Also as uprime is always the same size why do you use malloc at all? If you just make it an array of size 7 then you won't have issues with malloc and your code will probably run faster.

How to make gaussian package move in numerical simulation of a square barrier in C

I am trying to use Gaussian packages to study the transmission probability via Trotter-Suzuki formula and fast Fourier transform (FFT) when confronted with a square barrier, just as done in this Quantum Python article. But I need to realize it using C. In principle, the wave function will remain its shape before the collision with the square barrier. But I found that the wave function becomes flat dramatically with time before colliding with the square barrier. Anybody finds problems in the following codes?
Here, two files - result and psi.txt - are created to store the initial and evolved wave-function. The first two data for each are x coordinates, the probability of the wave function at that x. The third data for each line in file result is the square barrier distribution. The FFT I use is shown in this C program.
#include <stdio.h>
#include <math.h>
#define h_bar 1.0
#define pi 3.1415926535897932385E0
#define m0 1.0
typedef double real;
typedef struct { real Re; real Im; } complex;
extern void fft(complex x[], int N, int flag);
complex complex_product(complex x, real y_power, real y_scale)
{//x*exp(i*y_power)*y_scale
real Re, Im;
Re = (x.Re*cos(y_power)-x.Im*sin(y_power))*y_scale;
Im = (x.Re*sin(y_power)+x.Im*cos(y_power))*y_scale;
x.Re = Re; x.Im = Im;
return x;
}
real potential(real x, real a)
{
return (x<0 || x>=a) ? 0 : 1;
}
void main()
{
int t_steps=20, i, N=pow(2,10), m, n;
complex psi[N];
real x0=-2, p0=1, k0=p0/h_bar, x[N], k[N], V[N];
real sigma=0.5, a=0.1, x_lower=-5, x_upper=5;
real dt=1, dx=(x_upper-x_lower)/N, dk=2*pi/(dx*N);
FILE *file;
file = fopen("result", "w");
//initialize
for (n=0; n<N; n++)
{
x[n] = x_lower+n*dx;
k[n] = k0+(n-N*0.5)*dk;
V[n] = potential(x[n], a);
psi[n].Re = exp(-pow((x[n]-x0)/sigma, 2)/2)*cos(p0*(x[n]-x0)/h_bar);
psi[n].Im = exp(-pow((x[n]-x0)/sigma, 2)/2)*sin(p0*(x[n]-x0)/h_bar);
}
for (m=0; m<N; m++)
fprintf(file, "%g %g %g\n", x[m], psi[m].Re*psi[m].Re+psi[m].Im*psi[m].Im, V[m]);
fclose(file);
for (i=0; i<t_steps; i++)
{
printf("t_steps=%d\n", i);
for (n=0; n<N; n++)
{
psi[n]=complex_product(psi[n], -V[n]*dt/h_bar, 1);
psi[n]=complex_product(psi[n], -k[0]*x[n], dx/sqrt(2*pi));//x--->x_mod
}
fft(psi, N, 1);//psi: x_mod--->k_mod
for (m=0; m<N; m++)
{
psi[m]=complex_product(psi[m], -m*dk*x[0], 1);//k_mod--->k
psi[m]=complex_product(psi[m], -h_bar*k[m]*k[m]*dt/(2*m0), 1./N);
psi[m]=complex_product(psi[m], m*dk*x[0], 1);//k--->k_mod
}
fft(psi, N, -1);
for (n=0; n<N; n++)
psi[n] = complex_product(psi[n], k[0]*x[n], sqrt(2*pi)/dx);//x_mod--->x
}
file = fopen("psi.txt", "w");
for (m=0; m<N; m++)
fprintf(file, "%g %g 0\n", x[m], pow((psi[m]).Re, 2)+pow((psi[m]).Im, 2));
fclose(file);
}
I use the following Python code to plot the initial and final evolved wave functions:
call: `>>> python plot.py result psi.txt`
import matplotlib.pyplot as plt
from sys import argv
for filename in argv[1:]:
print filename
f = open(filename, 'r')
lines = [line.strip(" \n").split(" ") for line in f]
x = [float(line[0]) for line in lines]
y = [float(line[2]) for line in lines]
psi = [float(line[1]) for line in lines]
print "x=%g, max=%g" % (x[psi.index(max(psi))], max(psi))
plt.plot(x, y, x, psi)
#plt.xlim([-1.0e-10, 1.0e-10])
plt.ylim([0, 3])
plt.show()
Your code is almost correct, sans the fact that you are missing the initial/final half-step in the real domain and some unnecessary operations (kmod -> k and back), but the main problem is that your initial conditions are really chosen badly. The time evolution of a Gaussian wavepacket results in the uncertainty spreading out quadratically in time:
Given your choice of particle mass and initial wavepacket width, the term in the braces equals 1 + 4 t2. After one timestep, the wavepacket is already significantly wider than initially and after another timestep becomes wider than the entire simulation box. The periodicity implied by the use of FFT results in spatial and frequency aliasing, which together with the overly large timestep is why your final wavefunction looks that strange.
I would advise that you try to replicate exactly the conditions of the Python program, including the fact that the entire system is in a deep potential well (Vborder -> +oo).
The variable i is uninitialised here:
k[n] = k0+(i-N*0.5)*dk;

The output of ceil() and floor() in C language is odd

I am doing my homework to realize a C programe and during my work there is one step that I need to get the interger part of the double type numbers. So I choose ceil() or floor() in to realize this. But the output is unpredictable and far from expected.
The whole program is the following :
/*
************************************************************************
Includes
************************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <gsl/gsl_rng.h>
#include <time.h>
#include <math.h>
/* Solvent Particle Propersities*/
typedef struct
{
double vx,vy,rx,ry ; /* velocity AND position */
double cell; /* index of grid */
}solvent_p;
/* Cell Propersities*/
typedef struct
{
double vcm_x,vcm_y ; /* center of mass velocity */
int number; /* number of solvent in the cell */
double roation_angle; /* roation_angle of the cell */
}cell_p;
/* periodic boundary condition judging and adjusting fuction PBC */
void PBC(solvent_p *sol)
{
double L = 20.0; // box size 20
if(sol->rx >20) sol->rx=sol->rx-L;
if(sol->rx < 0) sol->rx=sol->rx+L;
if(sol->ry >20) sol->ry=sol->ry-L;
if(sol->ry < 0) sol->ry=sol->ry+L;
}
int main(int argc, char **argv)
{
// Randome setup generates random numbers from GSL functions
const gsl_rng_type * T;
gsl_rng * r;
T = gsl_rng_default;
gsl_rng_default_seed = ((unsigned long)(time(NULL))); //设seed值为当前时间
r = gsl_rng_alloc (T);
solvent_p solvent[4000];
int i,j,k,index=0;
cell_p grid[400];
double alpha=90.0; //roation angle
/* Iniinitializing solvent
* All vx=0
* half vy = sqrt(3) and half vy=-sqrt(3) to make momentum zero and another requirement is the overall energy is 6000 equals energy of temperature=1 with 4000 solvent 3NkT/2 ,assuming mass of solvent = 1 ,which is all a test quantity
* rx and ry are random number generated by GSL library
* cell=20*(ry+rx) is an index of which cell the solvent is in
*/
for(i=0;i<=3999;i++)
{
solvent[i].vx=0.0;
if(i<=1999)
solvent[i].vy=sqrt(3);
else
solvent[i].vy=-sqrt(3);
solvent[i].rx =20.0 * gsl_rng_uniform_pos(r);
solvent[i].ry =20.0 * gsl_rng_uniform_pos(r);
//printf("%f \t %f \n",solvent[i].rx,solvent[i].ry);
solvent[i].cell=20*(floor(solvent[i].ry))+floor(solvent[i].rx)+1;
}
// grid setting up
for (i=0;i<=399;i++)
{
grid[i].vcm_x=0;
grid[i].vcm_y=0;
grid[i].number=0;
grid[i].roation_angle=0.0;
}
/* Begining Simulation Work
*
* Fist process is preparing the system to equilibrium for 10000 processes
*
* the whole process involving two steps steaming and collision and the two steps are conducted one by one in our simulation
* time duration for steaming is 0.1 which is assigned for Molecular Dynamics and time duration for collision is ignored
*
*
*/
for(i=0;i<=9999;i++)
{
double temp;
double delta_t_MD=0.1; //time step
temp=gsl_rng_uniform_pos(r);
double rand_rx = (temp < 0.5) ? temp : ((-1) * temp ); // randomshift rx;
temp=gsl_rng_uniform_pos(r);
double rand_ry = (temp < 0.5) ? temp : ((-1) * temp ); // randomshift ry
//steaming
for(j=0;j<=3999;j++)
{
//printf("%d \n",j);
printf("1 :%d \t %f \t %f \n",j,solvent[j].rx,solvent[j].ry);
solvent[j].rx=solvent[j].rx+solvent[j].vx * delta_t_MD;
solvent[j].ry=solvent[j].ry+solvent[j].vy * delta_t_MD;
printf("2: %d \t %f \t %f \n",j,solvent[j].rx,solvent[j].ry);
//randomshift
solvent[j].rx=solvent[j].rx+rand_rx;
solvent[j].ry=solvent[j].ry+rand_ry;
printf("3: %d \t %f \t %f \n",j,solvent[j].rx,solvent[j].ry);
// periodic boundary condition
PBC(&solvent[j]);
printf("4: %d \t %f \t %f \n",j,solvent[j].rx,solvent[j].ry);
solvent[j].cell=20*(ceil(solvent[j].ry)-1)+ceil(solvent[j].rx);
printf("5: %d \t %f \t %f \t %f \t %f \n",j,solvent[j].rx,solvent[j].ry,ceil(solvent[j].rx),ceil(solvent[j].ry));
index = (int)(solvent[j].cell);
//printf("%d \t %d \t %f \t %f \t %f \n",j,index,solvent[j].cell,ceil(solvent[j].rx),ceil(solvent[j].ry));
if ((index>=0) &&(index<=400))
{
grid[index].vcm_x=grid[index].vcm_x+solvent[i].vx;
grid[index].vcm_y=grid[index].vcm_y+solvent[i].vy;
grid[index].number=grid[index].number+1;
}
}
// caculating vcm
for (k=0;k<=399;k++)
{
if (grid[k].number >= 1)
{
grid[k].vcm_x=grid[k].vcm_x/grid[k].number;
grid[k].vcm_y=grid[k].vcm_y/grid[k].number;
}
double temp;
temp=gsl_rng_uniform_pos(r);
grid[k].roation_angle = (temp < 0.5) ? alpha : ((-1) * alpha );
}
//collsion
}
gsl_rng_free (r); // free RNG
return 0;
}
Sorry it is some extent long so I did not put in first.And something did not finished but the program framework is set up.
my programe is like this:
printf("4: %d \t %f \t %f \n",j,solvent[j].rx,solvent[i].ry);
solvent[j].cell=20*(floor(solvent[j].ry))+floor(solvent[j].rx)+1;
printf("5: %d \t %f \t %f \t %f \t %f \n",j,solvent[j].rx,solvent[i].ry,floor(solvent[j].rx),floor(solvent[j].ry));
And although something as I wanted something more is wrong and below is I choose some parts of the output:
4: 3993 3.851240 17.047031
5: 3993 3.851240 17.047031 3.000000 9.000000
although floor(solvent[j].rx) is right but floor(solvent[j].ry) is totally wrong.
And the final result of my program is
Segmentation fault (core dumped)
------------------
(program exited with code: 139)
How to fix this one? Is there anything I use was wrong?
And to further test the problem I tried ceil() function in and the program and result is like this
program:
printf("4: %d \t %f \t %f \n",j,solvent[j].rx,solvent[i].ry);
solvent[j].cell=20*(ceil(solvent[j].ry)-1)+ceil(solvent[j].rx);
printf("5: %d \t %f \t %f \t %f \t %f \n",j,solvent[j].rx,solvent[i].ry,ceil(solvent[j].rx),ceil(solvent[j].ry));
result:
2: 3999 14.571205 2.837654
4: 3999 14.571205 2.837654
5: 3999 14.571205 2.837654 15.000000 15.000000
So use the nearest output as an example to illustrate my desire result is:
a= 14.571205, ceil(a)=15.00
b= 2.837654 , ceil(b)=3.00 not the 15.000 in the output
And the problem worsening is that when I just use a and b to test ceil() everything seems perfect:
program:
#include <stdio.h>
#include <math.h>
int main()
{
double a= 14.571205;
double b= 2.837654 ;
printf("%f \t %f \n",ceil(a),ceil(b));
return 0;
}
output:
15.000000 3.000000
I am using GCC in Linux Ubuntu.
==============================================================================
The problem has been solved.
The real fatal problem is here
if ((index>=0) &&(index<=400))
{
grid[index].vcm_x=grid[index].vcm_x+solvent[i].vx;
grid[index].vcm_y=grid[index].vcm_y+solvent[i].vy;
grid[index].number=grid[index].number+1;
}
}
Both solvent[i].vy and solvent[i].vx should be changed i for j.
Just as #Jon and #Blckknght #Eric Lippert have pointed out.
And I obvious get in the wrong trap and mislead #ouah and #Blckknght and In fact, the output sentences do have problem but they do not caused the prorame to crash only the out of boundary will do that.
Thank you ALL!
And I do like to share Eric Lippert 's comment which is powerful and insightful:
More generally, the problem you have is called "select isn't broken" by experienced programmers. That is, you have done something completely wrong, you cannot figure out what you did wrong, and so you conclude that a piece of basic, easy infrastructure written by experts and tested extensively is wrong. I assure you, floor and ceil do exactly what they are supposed to do. They are not wrong. The problem lies somewhere in your code, not in the standard library. – Eric Lippert
Your array is declared as:
solvent_p solvent[4000];
but you have this loop:
for(i=0;i<=9999;i++)
with this function call inside:
printf("1 :%d \t %f \t %f \n",j,solvent[j].rx,solvent[i].ry);
which means you are accessing out-of-bounds array elements.
EDIT:
OP test case has been edited to fix the out-of-bound accesses.
My second suggestion is to check index value (which is used to index grid array) never exceeds the number of elements of grid array after this assignment: index = (int)(solvent[j].cell).
I'm pretty sure the issue is with the indexes you're using. In the statement in question:
printf("5: %d \t %f \t %f \t %f \t %f \n",j,solvent[j].rx,solvent[i].ry,floor(solvent[j].rx),floor(solvent[j].ry));
you are printing the ry value of solvent[i] but the floor of the ry value of solvent[j]. I suspect that you want to be using the same index in both places (though I'm not sure which index you want).

Calculating the Power spectral density

I am trying to get the PSD of a real data set by making use of fftw3 library
To test I wrote a small program as shown below ,that generates the a signal which follows sinusoidal function
#include <stdio.h>
#include <math.h>
#define PI 3.14
int main (){
double value= 0.0;
float frequency = 5;
int i = 0 ;
double time = 0.0;
FILE* outputFile = NULL;
outputFile = fopen("sinvalues","wb+");
if(outputFile==NULL){
printf(" couldn't open the file \n");
return -1;
}
for (i = 0; i<=5000;i++){
value = sin(2*PI*frequency*zeit);
fwrite(&value,sizeof(double),1,outputFile);
zeit += (1.0/frequency);
}
fclose(outputFile);
return 0;
}
Now I'm reading the output file of above program and trying to calculate its PSD like as shown below
#include <stdio.h>
#include <fftw3.h>
#include <complex.h>
#include <stdlib.h>
#include <math.h>
#define PI 3.14
int main (){
FILE* inp = NULL;
FILE* oup = NULL;
double* value;// = 0.0;
double* result;
double spectr = 0.0 ;
int windowsSize =512;
double power_spectrum = 0.0;
fftw_plan plan;
int index=0,i ,k;
double multiplier =0.0;
inp = fopen("1","rb");
oup = fopen("psd","wb+");
value=(double*)malloc(sizeof(double)*windowsSize);
result = (double*)malloc(sizeof(double)*(windowsSize)); // what is the length that I have to choose here ?
plan =fftw_plan_r2r_1d(windowsSize,value,result,FFTW_R2HC,FFTW_ESTIMATE);
while(!feof(inp)){
index =fread(value,sizeof(double),windowsSize,inp);
// zero padding
if( index != windowsSize){
for(i=index;i<windowsSize;i++){
value[i] = 0.0;
}
}
// windowing Hann
for (i=0; i<windowsSize; i++){
multiplier = 0.5*(1-cos(2*PI*i/(windowsSize-1)));
value[i] *= multiplier;
}
fftw_execute(plan);
for(i = 0;i<(windowsSize/2 +1) ;i++){ //why only tell the half size of the window
power_spectrum = result[i]*result[i] +result[windowsSize/2 +1 -i]*result[windowsSize/2 +1 -i];
printf("%lf \t\t\t %d \n",power_spectrum,i);
fprintf(oup," %lf \n ",power_spectrum);
}
}
fclose(oup);
fclose(inp);
return 0;
}
Iam not sure about the correctness of the way I am doing this, but below are the results i have obtained:
Can any one help me in tracing the errors of the above approach
Thanks in advance
*UPDATE
after hartmut answer I'vve edited the code but still got the same result :
and the input data look like :
UPDATE
after increasing the sample frequencyand a windows size of 2048 here is what I've got :
UPDATE
after using the ADD-ON here how the result looks like using the window :
You combine the wrong output values to power spectrum lines. There are windowsSize / 2 + 1 real values at the beginning of result and windowsSize / 2 - 1 imaginary values at the end in reverse order. This is because the imaginary components of the first (0Hz) and last (Nyquist frequency) spectral lines are 0.
int spectrum_lines = windowsSize / 2 + 1;
power_spectrum = (double *)malloc( sizeof(double) * spectrum_lines );
power_spectrum[0] = result[0] * result[0];
for ( i = 1 ; i < windowsSize / 2 ; i++ )
power_spectrum[i] = result[i]*result[i] + result[windowsSize-i]*result[windowsSize-i];
power_spectrum[i] = result[i] * result[i];
And there is a minor mistake: You should apply the window function only to the input signal and not to the zero-padding part.
ADD-ON:
Your test program generates 5001 samples of a sinusoid signal and then you read and analyse the first 512 samples of this signal. The result of this is that you analyse only a fraction of a period. Due to the hard cut-off of the signal it contains a wide spectrum of energy with almost unpredictable energy levels, because you not even use PI but only 3.41 which is not precise enough to do any predictable calculation.
You need to guarantee that an integer number of periods is exactly fitting into your analysis window of 512 samples. Therefore, you should change this in your test signal creation program to have exactly numberOfPeriods periods in your test signal (e.g. numberOfPeriods=1 means that one period of the sinoid has a period of exactly 512 samples, 2 => 256, 3 => 512/3, 4 => 128, ...). This way, you are able to generate energy at a specific spectral line. Keep in mind that windowSize must have the same value in both programs because different sizes make this effort useless.
#define PI 3.141592653589793 // This has to be absolutely exact!
int windowSize = 512; // Total number of created samples in the test signal
int numberOfPeriods = 64; // Total number of sinoid periods in the test signal
for ( n = 0 ; n < windowSize ; ++n ) {
value = sin( (2 * PI * numberOfPeriods * n) / windowSize );
fwrite( &value, sizeof(double), 1, outputFile );
}
Some remarks to your expected output function.
Your input is a function with pure real values.
The result of a DFT has complex values.
So you have to declare the variable out not as double but as fftw_complex *out.
In general the number of dft input values is the same as the number of output values.
However, the output spectrum of a dft contains the complex amplitudes for positive
frequencies as well as for negative frequencies.
In the special case for pure real input, the amplitudes of the positive frequencies are
conjugated complex values of the amplitudes of the negative frequencies.
For that, only the frequencies of the positive spectrum are calculated,
which means that the number of the complex output values is the half of
the number of real input values.
If your input is a simple sinewave, the spectrum contains only a single frequency component.
This is true for 10, 100, 1000 or even more input samples.
All other values are zero. So it doesn't make any sense to work with a huge number of input values.
If the input data set contains a single period, the complex output value is
contained in out[1].
If the If the input data set contains M complete periods, in your case 5,
so the result is stored in out[5]
I did some modifications on your code. To make some facts more clear.
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <complex.h>
#include "fftw3.h"
int performDFT(int nbrOfInputSamples, char *fileName)
{
int nbrOfOutputSamples;
double *in;
fftw_complex *out;
fftw_plan p;
// In the case of pure real input data,
// the output values of the positive frequencies and the negative frequencies
// are conjugated complex values.
// This means, that there no need for calculating both.
// If you have the complex values for the positive frequencies,
// you can calculate the values of the negative frequencies just by
// changing the sign of the value's imaginary part
// So the number of complex output values ( amplitudes of frequency components)
// are the half of the number of the real input values ( amplitutes in time domain):
nbrOfOutputSamples = ceil(nbrOfInputSamples/2.0);
// Create a plan for a 1D DFT with real input and complex output
in = (double*) fftw_malloc(sizeof(double) * nbrOfInputSamples);
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * nbrOfOutputSamples);
p = fftw_plan_dft_r2c_1d(nbrOfInputSamples, in, out, FFTW_ESTIMATE);
// Read data from input file to input array
FILE* inputFile = NULL;
inputFile = fopen(fileName,"r");
if(inputFile==NULL){
fprintf(stdout,"couldn't open the file %s\n", fileName);
return -1;
}
double value;
int idx = 0;
while(!feof(inputFile)){
fscanf(inputFile, "%lf", &value);
in[idx++] = value;
}
fclose(inputFile);
// Perform the dft
fftw_execute(p);
// Print output results
char outputFileName[] = "dftvalues.txt";
FILE* outputFile = NULL;
outputFile = fopen(outputFileName,"w+");
if(outputFile==NULL){
fprintf(stdout,"couldn't open the file %s\n", outputFileName);
return -1;
}
double realVal;
double imagVal;
double powVal;
double absVal;
fprintf(stdout, " Frequency Real Imag Abs Power\n");
for (idx=0; idx<nbrOfOutputSamples; idx++) {
realVal = out[idx][0]/nbrOfInputSamples; // Ideed nbrOfInputSamples is correct!
imagVal = out[idx][1]/nbrOfInputSamples; // Ideed nbrOfInputSamples is correct!
powVal = 2*(realVal*realVal + imagVal*imagVal);
absVal = sqrt(powVal/2);
if (idx == 0) {
powVal /=2;
}
fprintf(outputFile, "%10i %10.4lf %10.4lf %10.4lf %10.4lf\n", idx, realVal, imagVal, absVal, powVal);
fprintf(stdout, "%10i %10.4lf %10.4lf %10.4lf %10.4lf\n", idx, realVal, imagVal, absVal, powVal);
// The total signal power of a frequency is the sum of the power of the posive and the negative frequency line.
// Because only the positive spectrum is calculated, the power is multiplied by two.
// However, there is only one single line in the prectrum for DC.
// This means, the DC value must not be doubled.
}
fclose(outputFile);
// Clean up
fftw_destroy_plan(p);
fftw_free(in); fftw_free(out);
return 0;
}
int main(int argc, const char * argv[]) {
// Set basic parameters
float timeIntervall = 1.0; // in seconds
int nbrOfSamples = 50; // number of Samples per time intervall, so the unit is S/s
double timeStep = timeIntervall/nbrOfSamples; // in seconds
float frequency = 5; // frequency in Hz
// The period time of the signal is 1/5Hz = 0.2s
// The number of samples per period is: nbrOfSamples/frequency = (50S/s)/5Hz = 10S
// The number of periods per time intervall is: frequency*timeIntervall = 5Hz*1.0s = (5/s)*1.0s = 5
// Open file for writing signal values
char fileName[] = "sinvalues.txt";
FILE* outputFile = NULL;
outputFile = fopen(fileName,"w+");
if(outputFile==NULL){
fprintf(stdout,"couldn't open the file %s\n", fileName);
return -1;
}
// Calculate signal values and write them to file
double time;
double value;
double dcValue = 0.2;
int idx = 0;
fprintf(stdout, " SampleNbr Signal value\n");
for (time = 0; time<=timeIntervall; time += timeStep){
value = sin(2*M_PI*frequency*time) + dcValue;
fprintf(outputFile, "%lf\n",value);
fprintf(stdout, "%10i %15.5f\n",idx++, value);
}
fclose(outputFile);
performDFT(nbrOfSamples, fileName);
return 0;
}
If the input of a dft is pure real, the output is complex in any case.
So you have to use the plan r2c (RealToComplex).
If the signal is sin(2*pi*f*t), starting at t=0, the spectrum contains a single frequency line
at f, which is pure imaginary.
If the sign has an offset in phase, like sin(2*pi*f*t+phi) the single line's value is complex.
If your sampling frequency is fs, the range of the output spectrum is -fs/2 ... +fs/2.
The real parts of the positive and negative frequencies are the same.
The imaginary parts of the positive and negative frequencies have opposite signs.
This is called conjugated complex.
If you have the complex values of the positive spectrum you can calculate the values of the
negative spectrum by changing the sign of the imaginary parts.
For this reason there is no need to compute both, the positive and the negative sprectrum.
One sideband holds all information.
Therefore the number of output samples in the plan r2c is the half+1 of the number
of input samples.
To get the power of a frequency, you have to consider the positive frequency as well
as the negative frequency. However, the plan r2c delivers only the right positive half
of the spectrum. So you have to double the power of the positive side to get the total power.
By the way, the documentation of the fftw3 package describes the usage of plans quite well.
You should invest the time to go over the manual.
I'm not sure what your question is. Your results seem reasonable, with the information provided.
As you must know, the PSD is the Fourier transform of the autocorrelation function. With sine wave inputs, your AC function will be periodic, therefore the PSD will have tones, like you've plotted.
My 'answer' is really some thought starters on debugging. It would be easier for all involved if we could post equations. You probably know that there's a signal processing section on SE these days.
First, you should give us a plot of your AC function. The inverse FT of the PSD you've shown will be a linear combination of periodic tones.
Second, try removing the window, just make it a box or skip the step if you can.
Third, try replacing the DFT with the FFT (I only skimmed the fftw3 library docs, maybe this is an option).
Lastly, trying inputting white noise. You can use a Bernoulli dist, or just a Gaussian dist. The AC will be a delta function, although the sample AC will not. This should give you a (sample) white PSD distribution.
I hope these suggestions help.

Kalman Filter implementation - what could be wrong

I am sorry for being this tedious but I reviewed my code several times with the help of a dozen of articles but still my KF doesn't work. By "doesn't work" I mean that the estimates by KF are wrong. Here is a nice paste of Real, Noised and KF estimated positions (just a small chunk).
My example is the same as in every tutorial I've found - I have a state vector of position and velocity. Position is in meters and represents vertical position in air. My real world case is skydiving (with parachute). In my sample generated data I've assumed we start at 3000m and the velocity is 10m/s.
P.S.: I am pretty sure matrix computations are OK - there must be an error with the logic.
Here I generate data:
void generateData(float** inData, float** noisedData, int x, int y){
inData[0][0]= 3000; //start position
inData[1][0]= -10; // 10m/s velocity; minus because we assume it's falling
noisedData[0][0]= 2998;
noisedData[1][0]= -10;
for(int i=1; i<x; i++){
inData[0][i]= inData[0][i-1] + inData[1][i-1];
inData[1][i]= inData[1][i-1]; //the velocity doesn't change for simplicity's sake
noisedData[0][i]=inData[0][i]+(rand()%6-3); //we add noise to real measurement
noisedData[1][i]=inData[1][i]; //velocity has no noise
}
}
And this is my implementation (matrices initialization is based on Wikipedia Kalman example):
int main(int argc, char** argv) {
srand(time(NULL));
float** inData = createMatrix(100,2); //2 rows, 100 columns
float** noisedData = createMatrix(100,2);
float** estData = createMatrix(100,2);
generateData(inData, noisedData, 100, 2);
float sampleRate=0.1; //10hz
float** A=createMatrix(2,2);
A[0][0]=1;
A[0][1]=sampleRate;
A[1][0]=0;
A[1][1]=1;
float** B=createMatrix(1,2);
B[0][0]=pow(sampleRate,2)/2;
B[1][0]=sampleRate;
float** C=createMatrix(2,1);
C[0][0]=1; //we measure only position
C[0][1]=0;
float u=1.0; //acceleration magnitude
float accel_noise=0.2; //acceleration noise
float measure_noise=1.5; //1.5 m standard deviation
float R=pow(measure_noise,2); //measure covariance
float** Q=createMatrix(2,2); //process covariance
Q[0][0]=pow(accel_noise,2)*(pow(sampleRate,4)/4);
Q[0][1]=pow(accel_noise,2)*(pow(sampleRate,3)/2);
Q[1][0]=pow(accel_noise,2)*(pow(sampleRate,3)/2);
Q[1][1]=pow(accel_noise,2)*pow(sampleRate,2);
float** P=createMatrix(2,2); //covariance update
P[0][0]=0;
P[0][1]=0;
P[1][0]=0;
P[1][1]=0;
float** P_est=createMatrix(2,2);
P_est[0][0]=P[0][0];
P_est[0][1]=P[0][1];
P_est[1][0]=P[1][0];
P_est[1][1]=P[1][1];
float** K=createMatrix(1,2); //Kalman gain
float** X_est=createMatrix(1,2); //our estimated state
X_est[0][0]=3000; X_est[1][0]=10;
// !! KALMAN ALGORITHM START !! //
for(int i=0; i<100; i++)
{
float** temp;
float** temp2;
float** temp3;
float** C_trans=matrixTranspose(C,2,1);
temp=matrixMultiply(P_est,C_trans,2,2,1,2); //2x1
temp2=matrixMultiply(C,P_est,2,1,2,2); //1x2
temp3=matrixMultiply(temp2,C_trans,2,1,1,2); //1x1
temp3[0][0]+=R;
K[0][0]=temp[0][0]/temp3[0][0]; // 1. KALMAN GAIN
K[1][0]=temp[1][0]/temp3[0][0];
temp=matrixMultiply(C,X_est,2,1,1,2);
float diff=noisedData[0][i]-temp[0][0]; //diff between meas and est
X_est[0][0]=X_est[0][0]+(K[0][0]*diff); // 2. ESTIMATION CORRECTION
X_est[1][0]=X_est[1][0]+(K[1][0]*diff);
temp=createMatrix(2,2);
temp[0][0]=1; temp[0][1]=0; temp[1][0]=0; temp[1][1]=1;
temp2=matrixMultiply(K,C,1,2,2,1);
temp3=matrixSub(temp,temp2,2,2,2,2);
P=matrixMultiply(temp3,P_est,2,2,2,2); // 3. COVARIANCE UPDATE
temp=matrixMultiply(A,X_est,2,2,1,2);
X_est[0][0]=temp[0][0]+B[0][0]*u;
X_est[1][0]=temp[1][0]+B[1][0]*u; // 4. PREDICT NEXT STATE
temp=matrixMultiply(A,P,2,2,2,2);
float** A_inv=getInverse(A,2);
temp2=matrixMultiply(temp,A_inv,2,2,2,2);
P_est=matrixAdd(temp2,Q,2,2,2,2); // 5. PREDICT NEXT COVARIANCE
estData[0][i]=X_est[0][0]; //just saving here for later to write out
estData[1][i]=X_est[1][0];
}
for(int i=0; i<100; i++) printf("%4.2f : %4.2f : %4.2f \n", inData[0][i], noisedData[0][i], estData[0][i]); // just writing out
return (EXIT_SUCCESS);
}
It looks like you are assuming a rigid body model for the problem. If that is the case, then for the problem you are solving, I would not put in the input u when you do the process update to predict the next state. Maybe I am missing something but the input u does not play any role in generating the data.
Let me put it another way, setting u to +1 looks like your model is assuming that the body should move in the +x direction because there is an input in that direction, but the measurement is telling it to go the other way. So if you put a lot of weight on the measurements, it's going to go in the -ve direction, but if you put a lot of weight on the model, it should go in the +ve direction. Anyway, based on the data generated, I don't see a reason for setting u to anything but zero.
Another thing, your sampling rate is 0.1 Hz, But when you generate data, you are assuming it's one second, since every sample, the position is changed by -10 meters per second.
Here is a matlab/octave implementation.
l = 1000;
Ts = 0.1;
y = 3000; %measurement to be fed to KF
v = -10; % METERS PER SECOND
t = [y(1);v]; % truth for checking if its working
for i=2:l
y(i) = y(i-1) + (v)*Ts;
t(:,i) = [y(i);v]; % copy to truth vector
y(i) = y(i) + randn; % noise it up
end
%%%%% Let the filtering begin!
% Define dynamics
A = [1, Ts; 0, 1];
B = [0;0];
C = [1,0];
% Steady State Kalman Gain computed for R = 0.1, Q = [0,0;0,0.1]
K = [0.44166;0.79889];
x_est_post = [3000;0];
for i=2:l
x_est_pre = A*x_est_post(:,i-1); % Process update! That is our estimate in case no measurement comes in.
%%% OMG A MEASUREMENT!
x_est_post(:,i) = x_est_pre + K*(-x_est_pre(1)+y(i));
end
You are doing a lot of weird array indexing.
float** A=createMatrix(2,2);
A[0][0]=1;
A[0][3]=sampleRate;
A[1][0]=0;
A[1][4]=1;
What is the expected outcome of indexing outside of the bounds of the array?

Resources