Entry 3119
latex
Submitted by anonymous
on Jan. 31, 2010 at 10:23 a.m.
Language: C. Code size: 6.2 KB.
#include <stdlib.h> #include <stdio.h> #include <math.h> #include <gsl/gsl_rng.h> #include <gsl/gsl_randist.h> #define L 30 //lunghezza massima del loop #define DELTA M_PI //pigreco math.h #define CORSA 100000 //quanti cammini lunghi L voglio fare #define CHUNK_SIZE 1000 #define SIGMA 0.02 inline void soluzione(const double *z,const double *r,double *v); inline void croce(const double *x, const double *y, double *z); inline double punto(const double *x,const double *y); inline void normalizza(double *x); void visualizza_rr(double rr[L][3]){ int i,j; printf("\n\n\n"); for(i=0;i<3;i++){ printf("\n"); for(j=0;j<L;j++) printf("%.4f\t",rr[j][i]); } printf("\n"); } int main(){ const gsl_rng_type *T; //dichiarazione tipo gsl_rng *r; //dichiarazione puntatore generatore gsl_rng_env_setup (); //inizializzazione del generatore prendendo dalla bash le variabili: $ GSL_RNG_TYPE="..." GSL_RNG_SEED=... ./eseguibile se fornite, altrimenti vedi default pag. 204 manuale gsl // -> //in questo caso è ideale chiamare il programma con ad es GSL_RNG_SEED=date +%s ./eseguibile T = gsl_rng_default; //assegnazione tipo generatore r = gsl_rng_alloc (T); //assegnazione generatore tipo T int chunk_size=CHUNK_SIZE; int i, j; double theta, phi, ct, st, cp, sp, tmp3, tmp4; /* scegliamo il primo vettore rr =asse y, il primo piano alfa =piano XY ad ogni passo k, alfa(k) è il piano passante per l'origine, che contiene il vettore rr(k) ed il vettore v(k+1) perpendicolare ad rr(k) ed appartenete ad alfa(k-1) z è l'asse di rotazione di theta; al primo passo se alfa=>XY rr=>asse y allora z=>asse z v giace sugli incroci fra alfa(k) e alfa(k-1) quindi è perpendicolare sia a z(k-1) che ad rr(k-1) chiaramente alfa è determinato da z e viceversa quindi uso solo z */ double tmp1[3]; double tmp2[3]; double z[3]={0,0,1}; double v[3]; double rr[L][3], ss[L][3]; //standard C : nello stack per righe rr[0][0]=0; //il primo vetore non viene mai toccato rr[0][1]=1; rr[0][2]=0; ss[0][0]=0; //il primo vetore non viene mai toccato ss[0][1]=fabs(1.0+gsl_ran_gaussian(r, SIGMA)); ss[0][2]=0; double m[3]; double modulo; FILE *fp; fp=fopen("sequenza_dati.bin","wb"); //in questo file andremo ascrivere ogni sequenza lunga trenta vettori in formato binario if(fp==NULL) return; setvbuf( fp , NULL , _IOFBF , 720 ); //questo dovrebbe forzare la scrittura su file ogno 720 byte che sono la dimensione della variabile rr // cio dovrebbe essere utile usando open MP per evitare di incasinare l'ordine di scrittura sul file for(i=1; i<= CORSA; i++){ for(j=1; j<L; j++){ theta = -DELTA + 2 * DELTA * gsl_rng_uniform(r); //piatto fra -D e D //printf("theta %.3f\t",theta); ct = cos(theta); st = sin(theta); //printf("ct %.5f\t",ct); //printf("st %.5f\t",st); phi = 2 * M_PI * gsl_rng_uniform(r); //piatto fra 0 e 2pi cp=cos(phi); sp=sin(phi); // 4 variabili temporanee per limitare i calcoli ripetuti croce(z,rr[j-1],tmp1); tmp3=punto(z,rr[j-1]); //faccio le 2 rotazioni attorno ad un asse fissato rr[j][0] = rr[j-1][0]*ct + tmp1[0]*st + tmp3 * (1-ct)*z[0]; rr[j][1] = rr[j-1][1]*ct + tmp1[1]*st + tmp3 * (1-ct)*z[1]; rr[j][2] = rr[j-1][2]*ct + tmp1[2]*st + tmp3 * (1-ct)*z[2]; croce(rr[j-1],rr[j],tmp2); tmp4= punto(rr[j],rr[j-1]); rr[j][0] = rr[j][0]*cp + tmp2[0]*sp + tmp4*(1-cp)*rr[j-1][0]; rr[j][1] = rr[j][1]*cp + tmp2[1]*sp + tmp4*(1-cp)*rr[j-1][1]; rr[j][2] = rr[j][2]*cp + tmp2[2]*sp + tmp4*(1-cp)*rr[j-1][2]; //printf("tmp1 %.3f %.3f %.3f \t tmp2 %.3f %.3f %.3f \t tmp3 %.3f \ttmp4 %.3f \t",tmp1[0],tmp1[1],tmp1[2],tmp2[0],tmp2[1],tmp2[2],tmp3,tmp4); //printf("\n"); normalizza(rr[j]); //questa ulteriore rinormalizzazione è fondamentale per controllare l'errore che si propaga //m[0]=gsl_ran_gaussian (r, SIGMA); //m[1]=gsl_ran_gaussian (r, SIGMA); //m[2]=gsl_ran_gaussian (r, SIGMA); //modulo=sqrt(punto(m, m)); modulo=fabs(1+gsl_ran_gaussian (r, SIGMA)); //printf("modulo %.5f\n",modulo); ss[j][0]=rr[j][0]*modulo; ss[j][1]=rr[j][1]*modulo; ss[j][2]=rr[j][2]*modulo; //preparo i nuovi vettori soluzione(z,rr[j-1],v); // v giace sull' incrocio fra i due piani normalizza(v); croce(rr[j-1],v,z); } fwrite(ss,sizeof(double),90,fp); //90 è sizeof(rr)/sizeof(double) //visualizza_rr(ss); } //fine sezione parallela fclose(fp); return 0; } ///////////////////////////////////////////////////////////////////////////////// /*funzione che risolve con il metodo di kramer un sistema 3x3 NON singolare*/ ///////////////////////////////////////////////////////////////////////////////// inline void soluzione(const double *z, const double *r, double *v){ double det_originale = z[0]*(r[1]-r[2]) - z[1]*(r[0]-r[2]) + z[2]*(r[0]-r[1]); v[0] = (z[1]*r[2] - r[1]*z[2]) / det_originale; v[1] = (r[0]*z[2] - z[0]*r[2]) / det_originale; v[2] = (z[0]*r[1] - r[0]*z[1]) / det_originale; } ///////////////////////////////////////////////////////////////////////////////// /*funzione che fa il prodotto a croce di 2 vettori*/ ///////////////////////////////////////////////////////////////////////////////// inline void croce(const double *x, const double *y, double *z){ *z = x[1]*y[2]-y[1]*x[2]; *(z+1) = x[0]*y[2]-y[0]*x[2]; *(z+2) = x[0]*y[1]-y[0]*x[1]; } ///////////////////////////////////////////////////////////////////////////////// /*funzione che restituisce il prodotto scalare*/ ///////////////////////////////////////////////////////////////////////////////// inline double punto(const double *x,const double *y){ return x[0]*y[0] +x[1]*y[1] +x[2]*y[2]; } ///////////////////////////////////////////////////////////////////////////////// /*funzione che normalizza un vettore di lunghezza 3 */ ///////////////////////////////////////////////////////////////////////////////// inline void normalizza(double *x){ double norma=sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]); *x = *x / norma; *(x+1) = *(x+1) / norma; *(x+2) = *(x+2) / norma; }
This snippet took 0.04 seconds to highlight.
Back to the Entry List or Home.