I have a problem with entering a function (in C), it will give a segmentation fault when I try to enter calc_uq() from the function dynamical_matrix(). When I try to compile it, it will still print check5, but it will give a segmentation fault before printing checkA.
This problem only occurs to me with I choose a large amount of timesteps (steps=100000), for steps=75000 it still works.
Below is part of my code, the main function, the dynamical_matrix() function and the calc_uq() function.
I hope someone can help me with this problem.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <stdbool.h>
#include <complex.h>
#define MAX 1000 //max aantal deeltjes
#define NDIM 3
#define npart 108
#define steps 100000
#define kint 1
//d is distance squared
int s=20000; //calculations start at time = s.
double pi=3.14159265359;
double radius=0.5;
double r2[npart][NDIM];
double r[steps][npart][NDIM], R[steps][npart][NDIM], RC[steps][npart][NDIM]; //r is with periodic boundary, R without, RC = R-CoM
double CoM[steps][NDIM];
double box;
double mean[npart][NDIM];
double complex uq[steps][NDIM];
double complex Dq[3][3];
double ui[steps][npart][NDIM];
double sqrtN,beta=1;
double k[3];
main()
{
int i,p,t=0;
readparts();
init_random_seed();
sqrtN=sqrt(npart);
k[0]=1*(2*pi/box)*(kint);
k[1]=0*(2*pi/box)*(kint);
k[2]=0*(2*pi/box)*(kint);
for(i=0;i<npart;i++)
{
r[t][i][0]=r2[i][0];
r[t][i][1]=r2[i][1];
r[t][i][2]=r2[i][2];
}
t++;
writedata();
for(p=1;p<steps*100;p++)
{
random_particle_displacement();
if(p%100==0)
{
for(i=0;i<npart;i++)
{
r[t][i][0]=r2[i][0];
r[t][i][1]=r2[i][1];
r[t][i][2]=r2[i][2];
}
if((t+1)%1000==0){printf("t=%d\n",(t+1));}
t++;
}
if(p%1000==0){writedata();}
}
printf("check1\n");
dynamical_matrix();
print_Dq();
print_R72();
print_uq();
}
calc_uq()
{
printf("checkA\n");
double complex arg[npart];
double complex sum[steps][NDIM];
int i,t;
printf("check6\n");
for(i=0;i<npart;i++)
{
arg[i]=I * ( k[0]*mean[i][0] + k[1]*mean[i][1] + k[2]*mean[i][2] );
printf("arg[%d]=%fI\tmean[%d][0]=%f\tmean[%d][1]=%f\tmean[%d][2]=%f\n",i,cimag(arg[i]),i,mean[i][0],i,mean[i][1],i,mean[i][2]);
}
printf("check7\n");
for(t=0;t<steps;t++)
{
sum[t][0]=0;
sum[t][1]=0;
sum[t][2]=0;
for(i=0;i<npart;i++) //calculate the Fourier sum.
{
ui[t][i][0]=RC[t][i][0]-mean[i][0]; //calculate the displacement from its mean position
ui[t][i][1]=RC[t][i][1]-mean[i][1];
ui[t][i][2]=RC[t][i][2]-mean[i][2];
sum[t][0]+=cexp(arg[i])*ui[t][i][0];
sum[t][1]+=cexp(arg[i])*ui[t][i][1];
sum[t][2]+=cexp(arg[i])*ui[t][i][2];
}
uq[t][0] = sum[t][0]/sqrtN; //uq at timestep t
uq[t][1] = sum[t][1]/sqrtN;
uq[t][2] = sum[t][2]/sqrtN;
}
printf("check8\n");
}
dynamical_matrix()
{
printf("check2\n");
double complex uquq[steps][NDIM];
double complex uquqmean[3][3];
printf("check3\n");
int i,j,t;
calc_R();
calc_CoM();
calc_RC();
printf("check4\n");
for(i=0;i<npart;i++)
{
calc_mean_pos(i);
}
printf("check5\n");
calc_uq();
//calculate <uq*.uq>
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
uquqmean[i][j]=calc_uquqmean(i,j);
Dq[i][j]=1/(beta*uquqmean[i][j]);
}
}
Related
I want to collect polar coordinate values by converting them to Cartesian values in C.
But I'm getting wrong values at 12°:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
int main()
{
int desire=1;
int wind[desire];
for (int i = 0; i < desire; i++)
{
printf("\nEnter degree of wind:");
scanf("%d",&wind[i]);
}
double complex sum=0;
for (int i = 0; i < desire; i++)
{
sum=cos(wind[i])+ sin(wind[i]) * I;
}
double convert(double radian);
printf("\n %.2f %.2fi",creal(sum),cimag(sum));
double r =hypot(creal(sum),cimag(sum));
double angle= convert(atanf(creal(sum)/cimag(sum))) ;
printf("\n %.2f %.2f",r,angle);
return 0;
}
returning completely wrong sine(imaginary value)
0.84 -0.54i
1.00 -57.55
It should print0.97 +0.20i not 0.84 -0.54i.
What is wrong?
The convert function:
#include <math.h>
#include "convert.h"
double convert(double radian)
{
return(radian * (180/M_PI));
}
Per 7.12.4.6 The sin functions (bolding mine):
The sin functions compute the sine of x (measured in radians).
cos() is similar.
You're entering 12 radians.
I'm trying to implement polynomials in C but Im having an issue with arrays and setting values. Im bad at C, please explain why this is happening: I run this, it says that p.coefs[1] is 0.0 instead of 3.0 as intended.
#include <stdio.h>
#include <assert.h>
int main()
{
#define MAX_DEG 10
typedef struct Polynomial Polynomial;
struct Polynomial {
int deg;
double coefs[MAX_DEG];
};
Polynomial ply_create(int deg) {
assert(deg >= 0 && deg <= MAX_DEG);
Polynomial poly;
poly.deg = deg;
return poly;
}
void ply_set_coef(Polynomial poly, int i, double val) {
poly.coefs[i] = val;
}
Polynomial p = ply_create(1);
p.coefs[0] = 1.0;
ply_set_coef(p, 1, 3.0);
printf("p.coefs[0] is %f and p.coefs[1] is %f", p.coefs[0], p.coefs[1]);
return 0;
}
I was previously using malloc and made p.coefs a pointer to a double. In this case I did not have any problem.
I am using the trapezium rule to calculate the integral of a function between 0 and infinity. I can calculate the value of the integral for a given value of N, and now I am trying to loop N from two to a given value but it will not work. It keeps calculating the value of the integral for when N is 2 and repeating instead of the new value of N. The problem is in the for loop in main() I think.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
double f(double x) {
double a;
a =1/((1+x)*pow(x,0.5));
return a;}
double tra(double upper, double lower, int N) {
double sum, step, integral,lowest;
step=(upper-lower)/(N-1);
lower=lower+step;
if(lower==0) {
lowest=DBL_EPSILON;}
else {
lowest=lower;}
while(lower<upper) {
sum=sum+f(lower);
lower=lower+step;}
integral=step*(sum+(f(upper)/2)+(f(lowest)/2));
sum=0;
return integral;}
main() {
int N;
double upper=DBL_EPSILON*2, lower=0, total=0;
for(N=2;N<20000;N+=100) { /*Here im trying to loop N so that the integral is calculated for increasing values of N*/
while(upper<FLT_MAX) {
total=total+tra(upper, lower, N);
lower=upper;
upper=upper*2;}
printf("Integral is %.10f\n", total);
}
}
I suggest you move the variable initialisation to within the for loop like this:
int main(void) {
int N;
double upper, lower, total;
for(N=2;N<20000;N+=100) {
upper = DBL_EPSILON*2;
lower = 0;
total = 0;
while(upper<FLT_MAX) {
total=total+tra(upper, lower, N);
lower=upper;
upper=upper*2;
}
printf("Integral is %.10f\n", total);
}
return 0;
}
I wrote a C code that I would like to parallelize using OpenMP (I am a beginner and I have just a few days to solve this task); let's start from the main: first of all I have initialized 6 vectors (Vx,Vy,Vz,thetap,phip,theta); then there is a for loop that cycles over Nmax; inside of this loop I allocate some memory for the structure I have defined at the very top of the code; the structure is called coll_CPU and increases its size every cycle; then I pick some of the values from the vectors I have mentioned before and I place them into the structure; so at this point my structure coll_CPU is filled with Ncoll elements; during this process I used some of the functions declared outside of the main (these functions are random number generators). Now comes the important part: in my serial code I use a for loop to pass every single element of the structure to a function called collisionCPU (this function just gets the inputs and multiplies them by 2); My goal is to parallelize this loop so that each of my CPUs gives its contribution to do this operation and speed up the process.
Here are the codes:
main.c
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <memory.h>
#include <string.h>
#include <time.h>
#include <omp.h>
#define pi2 6.283185307
#define pi 3.141592654
#define IMUL(a,b) __mul24(a,b)
typedef struct {
int seme;
} iniran;
typedef struct{
int jp1;
int jp2;
float kx;
float ky;
float kz;
float vAx;
float vAy;
float vAz;
float vBx;
float vBy;
float vBz;
float tetaAp;
float phiAp;
float tetaA;
float tetaBp;
float phiBp;
float tetaB;
float kAx;
float kAy;
float kAz;
float kBx;
float kBy;
float kBz;
int caso;
} stato_struct;
stato_struct *coll_CPU=0;
unsigned int timer;
#include "DSMC_kernel_float.c"
//=============================================================
float min(float *a, float*b){
if(*a<*b){
return *a;
}
else{
return *b;
}
}
//=============================================================
float max(float *a, float*b){
if(*a>*b){
return *a;
}
else{
return *b;
}
}
//=============================================================
float rf(int *idum){
static int iff=0;
static int inext, inextp, ma[55];
int mj, mk;
int i, k, ii;
float ret_val;
if (*idum<0 || iff==0) {
iff=1;
mj=161803398 - abs(*idum);
mj %= 1000000000;
ma[54]=mj;
mk=1;
for (i=1; i<=54; ++i){
ii=(i*21)%55;
ma[ii-1]=mk;
mk=mj-mk;
if (mk<0) {
mk += 1000000000;
}
mj= ma[ii-1];
}
for(k=1; k<=4; ++k) {
for(i=1; i<=55; ++i){
ma[i-1] -= ma[(i+30)%55];
if (ma[i-1]<0){
ma[i-1] += 1000000000;
}
}
}
inext=0;
inextp=31;
*idum=1;
}
++inext;
if (inext==56){
inext=1;
}
++inextp;
if (inextp==56){
inextp=1;
}
mj=ma[inext-1]-ma[inextp-1];
if (mj<0){
mj += 1000000000;
}
ma[inext-1]=mj;
ret_val=mj*1.0000000000000001e-9;
return ret_val;
}
//============================================================
int genk(float *kx, float *ky, float *kz, int *p2seme){
// float sqrtf(float), sinf(float), cosf(float);
extern float rf(int *);
static float phi;
*kx=rf(p2seme) * 2. -1.f;
*ky= sqrtf(1. - *kx * *kx);
phi=pi2*rf(p2seme);
*kz=*ky * sinf(phi);
*ky *= cosf(phi);
return 0;
}
//==============================================================
int main(void){
float msec_kernel;
int Np=10000, Nmax=512;
int id,jp,jcoll,Ncoll,jp1, jp2, ind;
float Vx[Np],Vy[Np],Vz[Np],teta[Np],tetap[Np],phip[Np];
float kx, ky, kz, Vrx, Vry, Vrz, scalprod, fk;
float kAx, kAy, kAz, kBx, kBy, kBz;
iniran1.seme=7593;
for(jp=1;jp<=Np;jp++){
if(jp<=Np/2){
Vx[jp-1]=2.5;
Vy[jp-1]=0;
Vz[jp-1]=0;
tetap[jp-1]=0;
phip[jp-1]=0;
teta[jp-1]=0;
}
for (Ncoll=1;Ncoll<=Nmax;Ncoll += 10){
coll_CPU=(stato_struct*) malloc(Ncoll*sizeof(stato_struct));
jcoll=0;
while (jcoll<Ncoll){
jp1=1+floorf(Np*rf(&iniran1.seme));
jp2=1+floorf(Np*rf(&iniran1.seme));
genk(&kx,&ky,&kz,&iniran1.seme);
Vrx=Vx[jp2-1]-Vx[jp1-1];
Vry=Vy[jp2-1]-Vy[jp1-1];
Vrz=Vz[jp2-1]-Vz[jp1-1];
scalprod=Vrx*kx+Vry*ky+Vrz*kz;
if (scalprod<0) {
genk(&kAx,&kAy,&kAz,&iniran1.seme);
genk(&kBx,&kBy,&kBz,&iniran1.seme);
coll_CPU[jcoll].jp1= jp1;
coll_CPU[jcoll].jp2=jp2;
coll_CPU[jcoll].kx=kx;
coll_CPU[jcoll].ky=ky;
coll_CPU[jcoll].kz=kz;
coll_CPU[jcoll].vAx=Vx[jp1-1];
coll_CPU[jcoll].vAy=Vy[jp1-1];
coll_CPU[jcoll].vAz=Vz[jp1-1];
coll_CPU[jcoll].vBx=Vx[jp2-1];
coll_CPU[jcoll].vBy=Vy[jp2-1];
coll_CPU[jcoll].vBz=Vz[jp2-1];
coll_CPU[jcoll].tetaAp=tetap[jp1-1];
coll_CPU[jcoll].phiAp=phip[jp1-1];
coll_CPU[jcoll].tetaA=teta[jp1-1];
coll_CPU[jcoll].tetaBp=tetap[jp2-1];
coll_CPU[jcoll].phiBp=phip[jp2-1];
coll_CPU[jcoll].tetaB=teta[jp2-1];
coll_CPU[jcoll].kAx=kAx;
coll_CPU[jcoll].kAy=kAy;
coll_CPU[jcoll].kAz=kAz;
coll_CPU[jcoll].kBx=kBx;
coll_CPU[jcoll].kBy=kBy;
coll_CPU[jcoll].kBz=kBz;
coll_CPU[jcoll].caso=1;
jcoll++;
}
}
clock_t t;
t = clock();
#pragma omp parallel for private(id) //HERE IS WHERE I TRIED TO DO THE PARALLELIZATION BUT WITH NO SUCCESS. WHAT DO I HAVE TO TYPE INSTEAD???
for(id=0;id<Nmax;id++){
CollisioniCPU(coll_CPU,id);
}
t = clock() - t;
msec_kernel = ((float)t*1000)/CLOCKS_PER_SEC;
printf("Tempo esecuzione kernel:%e s\n",msec_kernel*1e-03);
for (ind=0;ind<Ncoll;ind++){
if (coll_CPU[ind].caso==4)
Ncoll_eff++;
else if (coll_CPU[ind].caso==0)
Ncoll_div++;
else
Ncoll_dim++;
}
free(coll_CPU);
}
return 0;
}
DSMC_kernel_float.c
void CollisioniCPU(stato_struct *coll_CPU, int id){
float vettA[6], vettB[6];
vettA[0]=coll_CPU[id].vAx;
vettA[1]=coll_CPU[id].vAy;
vettA[2]=coll_CPU[id].vAz;
vettA[3]=coll_CPU[id].tetaAp;
vettA[4]=coll_CPU[id].phiAp;
vettA[5]=coll_CPU[id].tetaA;
vettB[0]=coll_CPU[id].vBx;
vettB[1]=coll_CPU[id].vBy;
vettB[2]=coll_CPU[id].vBz;
vettB[3]=coll_CPU[id].tetaBp;
vettB[4]=coll_CPU[id].phiBp;
vettB[5]=coll_CPU[id].tetaB;
coll_CPU[id].vAx=2*vettA[0];
coll_CPU[id].vAy=2*vettA[1];
coll_CPU[id].vAz=2*vettA[2];
coll_CPU[id].tetaAp=2*vettA[3];
coll_CPU[id].phiAp=2*vettA[4];
coll_CPU[id].tetaA=2*vettA[5];
coll_CPU[id].vBx=2*vettB[0];
coll_CPU[id].vBy=2*vettB[1];
coll_CPU[id].vBz=2*vettB[2];
coll_CPU[id].tetaBp=2*vettB[3];
coll_CPU[id].phiBp=2*vettB[4];
coll_CPU[id].tetaB=2*vettB[5];
}
In order to compile the program I type this line on the terminal: gcc -fopenmp time_analysis.c -o time_analysis -lm fallowed by export OMP_NUM_THREADS=1; however once I run the executable I get this error message:
Error in `./time_analysis': double free or corruption (!prev): 0x00000000009602c0 ***
Aborted
What does this error mean? what I have done wrong in the main function when I tried to parallelize the for loop? and most important: what should I type instead in order to make my code go on parallel? please help me out if you can because I seriously have no time to study OpenMP from scratch and I need to get this job done right away.
Changing the inner loop as follows should bring you one step further.
#pragma omp parallel for private(id)
for(id=0;id<Ncoll;id++){
CollisioniCPU(coll_CPU,id);
}
Your OpenMP line seems okay, but I doubt that it will lead to significant improvements in runtime. You should optimize the surrounding code as well. Allocating the memory once outside of your loops would be a good start.
By the way, is there any reason for this verbose coding style and not using a more compact and readable version as this one?
void CollisioniCPU(stato_struct *coll_CPU, int id) {
stato_struct *ptr = coll_CPU + id;
ptr->vAx *= 2;
ptr->vAy *= 2;
ptr->vAz *= 2;
ptr->tetaAp *= 2;
ptr->phiAp *= 2;
ptr->tetaA *= 2;
ptr->vBx *= 2;
ptr->vBy *= 2;
ptr->vBz *= 2;
ptr->tetaBp *= 2;
ptr->phiBp *= 2;
ptr->tetaB *= 2;
}
Im trying to make a program that calculates out a math equation, Im getting stuck on how i generate a random number from 0.00 to 1.00 and store it in a variable a.
this is my code so far, im stuck to how now take that number and store it for future use. I need to store that random number in a, and hten use it in a loop, and then generate a new random number and use it in the 2nd cycle of the loop.
EDIT
this is what i have been working on now, it is suppose to calculate the number of times a random number is inside the area, count it, and then devide by the number of times run, but im not getting any output
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
void initrand(void)
{
srand(time(0));
}
float randfloat(void)
{
return rand()/(float)RAND_MAX;
}
int main(void)
{
int n = 10;
float x;
float y;
float pi = 3.1415;
float rootxy;
initrand();
int z = 0;
int inside = 0;
x = randfloat();
y = randfloat();
float area = 0.25 * pi;
float calculatedpi;
rootxy = sqrt(pow(x,2) + (pow(y,2)));
while (z < n){
if (rootxy > area) {
inside++;
z++;
}
else{
return 0;
}
calculatedpi = (inside/n);
}
printf("%f", calculatedpi);
}
There are a few issues with your code:
You shouldn't use nested functions. Some compilers support them as an extension but it's not standard. Define randfloat and initrand outside main
The function initrand does too little. Why not call srand((time(0)); from main ?
Your initrand function is declared as returning a double but it doesn't return anything (and the way it's named it shouldn't). If you need to use such a function, why not make it return void ?
You should rarely use float. Why not use double ?
That said, you can do this to store that random value:
double randdouble()
{
return rand()/((double)RAND_MAX + 1);
}
int main()
{
double x = randdouble();
/* ... */
}
I think you want something like this:
#include <stdlib.h>
#include <time.h>
void initrand(void)
{
srand(time(0));
}
float randfloat(void)
{
return rand()/(float)RAND_MAX;
}
int main(void)
{
initrand();
float a = randfloat();
return 0;
}
You can't nest functions like in some other languages.
You had non-matching parentheses in the initrand function.
I fixed the declarations of your functions, use void when there are no parameters, initrand doesn't return anything.
Your division by RAND_MAX+1 was a little messed up. Simply divide by RAND_MAX and the result will be in the closed interval [0,1]. And the syntax for the conversion to float was not quite right.
If you want to get random double numbers in a specified range you can use this function
// Return a random double from a to b
double randomDouble(double a, double b)
{
return = ( rand() / ( (double)RAND_MAX + 1.0))
* (b - a) + a;
}