Υπολογιστικά Mαθηματικά II Ζαφειράκογλου Απόστολος 1 Μελέτη διασπάσεων με τη μέθοδο Monte Carlo Να προσδιοριστεί ο αριθ-µός των πυρήνων του στοιχείου 134 I 53 ως συνάρτηση του χρόνου, αν είναι γνωστό ότι N 0 = 1000 και για t = 0.5min, 1min, 2min. Να γίνει σύγκριση με τα αποτελέσματα της σχέσης N(t) = N 0 e λt. Η ακριβής χρονική στιγμή της διασπάσεως δεν εξαρτάται από κάποιο εξωτερικό αίτιο ή από την παρουσία άλλων σωματιδίων και επομένως είναι ένα τυχαίο γεγονός. Η πιθανότητα διασπάσεως ενός σωματιδίου στη μονάδα του χρόνου είναι σταθερή. Ο νόμος που περιγράφει το πλήθος των σωματιδιών σε οποιαδήποτε χρονική στιγμή είναι: N(t) = N 0 e λt Επειδή διαδικασία της ϱαδιενεργού διασπάσεως είναι ένα τυχαίο γεγονός, και άρα είναι λογικό να επιλέξουμε μία από τις μεθόδους των διαφόρων αλγορίθμων Monte Carlo, για να προσομοιώσουμε το γεγονός. Για να αποφύγουμε τις πολλές εκτελέσεις του προγράμματος με διαφορετικά inputs, απλά έχουμε δημιουργήσει ένα πίνακα και όλα τα αρχικά data, και το πρόγραμμα δίνει 3 output files. Ένα εξωτερικό loop τρέχει τον ίδιο κώδικα για τις διάφορες αρχικές τιμές. Ο αλγόριθμος αναπτύχθηκε σε C++ και παρουσιάζεται παρακάτω: 1 #include <iostream> 2 #include <ctime> 3 #include <stdio.h> 4 #include <cmath> 5 #include <cstdlib> 6 #include <fstream> 7 #include <sstream> 1
ΠΜΣ Υπολογιστικη ς Φυσικη ς 1 Μελε τη διασπα σεων με τη με θοδο Monte Carlo 8 10 9 using namespace std; 11 int n0=1000, nleft, ntime; 12 double t12=53, tmax, lamda, p, ntheory, error, ndt; 13 double dt_ar[3]={0.5, 1, 2}; 14 15 double myrand(double fmin, double fmax) 16 { 17 static unsigned int xseed[3]={time(null),time(null),time( NULL)}; 18 xseed[0]=(1812433253*xseed[0]+1); 19 xseed[1]=(1664525*xseed[1]+1013904223); 20 xseed[2]=(22695477*xseed[2]+1); 21 return (double)xseed[rand()%3]/4294967296.d; 22 } 23 24 25 int main() 26 { 27 ofstream out1, out2; 28 29 cout << "Decay\n N0 = 1000 \t T1/2 = 53 min \n" ; 30 cout << "dt (min) : {0.5, 1, 2}" ; 31 32 33 for(int k=0;k<3;k++) 34 { 35 if(k==0) 36 out1.open("dt_0_5.dat"); 37 if(k==1) 38 out1.open("dt_1.dat"); 39 if(k==2) 40 out1.open("dt_2.dat"); 41 42 lamda=0.693/t12; 43 ndt=floor(1/(lamda*dt_ar[k])); 44 p=lamda*dt_ar[k]; 45 46 double t=0; 47 int i=1, j; 48 nleft=n0; 49 while(i<=ndt) 50 { 2
ΠΜΣ Υπολογιστικη ς Φυσικη ς 1 Μελε τη διασπα σεων με τη με θοδο Monte Carlo 51 t=t+dt_ar[k]; 52 ntime=nleft; 53 j=1; 54 while(j<=ntime) 55 { 56 if(p>=myrand(0,1)) 57 { 58 nleft=nleft 1; 59 } 60 j++; 61 } 62 ntheory = floor(n0*exp( lamda*t)); 63 error=fabs(ntheory nleft)/ntheory; 64 out1 << t << " " << ntheory << " " << nleft << " " << error << endl; 65 i++; 66 } 67 out1.close(); 68 } 69 system("gnuplot p e 'plot \"dt_0_5.dat\" using 1:2 title \"0.5min theory\" with points lc rgb \"#0060ad\" lt 1 lw 1 pt 7 ps.2 \' "); 70 system("gnuplot p e 'plot \"dt_0_5.dat\" using 1:3 title \"0.5min MC\" with points lc rgb \"#0060ad\" lt 1 lw 1 pt 7 ps.2 \' "); 71 72 system("gnuplot p e 'plot \"dt_1.dat\" using 1:2 title \"1min theory\" with points lc rgb \"#0060ad\" lt 1 lw 1 pt 7 ps.2 \' "); 73 system("gnuplot p e 'plot \"dt_1.dat\" using 1:3 title \"1min MC\" with points lc rgb \"#0060ad\" lt 1 lw 1 pt 7 ps.2 \' "); 74 75 system("gnuplot p e 'plot \"dt_2.dat\" using 1:2 title \"2min theory\" with points lc rgb \"#0060ad\" lt 1 lw 1 pt 7 ps.2 \' "); 76 system("gnuplot p e 'plot \"dt_2.dat\" using 1:3 title \"2min MC\" with points lc rgb \"#0060ad\" lt 1 lw 1 pt 7 ps.2 \' "); 77 return 0; 78 } Το πρόγραμμα δίνει 3 output files. Αν σχεδιάσουμε τα διαγράμματα από αυτά τα δεδομένα, έχουμε : 3
ΠΜΣ Υπολογιστικη ς Φυσικη ς 1 Μελε τη διασπα σεων με τη με θοδο Monte Carlo Διάγραμμα 1.1: Monte Carlo (1 min) Διάγραμμα 1.2: Theoritical (0.5 min) 4
ΠΜΣ Υπολογιστικη ς Φυσικη ς 1 Μελε τη διασπα σεων με τη με θοδο Monte Carlo Διάγραμμα 1.3: Monte Carlo (1 min) Διάγραμμα 1.4: Theoritical (1 min) 5
Διάγραμμα 1.5: Monte Carlo (2 min) Διάγραμμα 1.6: Theoritical (2 min) 2 Ising model με τη χρήση Monte Carlo Να τροποποιηθεί το πρόγραµµα prg11_mc_ising ώστε να υπολογίζονται επιπλέον οι τυπικές αποκλίσεις των E, CB, M και χ. Να εκτελεστεί η νέα µορφή του 6
προγράµµατος για διαφορετικά πλήθη µικροκαταστάσεων που δεν χρησιµοποιούνται στους υπολογισµούς και διαπιστώσατε ότι για κάποια τιµή του Nskip οι διασπορές των διαφόρων συλλογών συµφωνούν µεταξύ τους, εφόσον δεν ϐρισκό- µαστε κοντά στο κρίσιµο σηµείο. Το μόντελο Ising είναι ένα από τα πιο γνωστά και πιο εφαρμοσμένα μοντέλα της στατιστικής Φυσικής. Οι λόγοι που το κάνουν τόσο χρήσιμο: i. η καλή ακρίβεια (όχι τόσο από την αριθμητική πλευρά, αλλά από την ποιοτική πλευρά των διαγραμμάτων της συμπεριφοράς των διαφόρων στατιστικών μεγεθών) ii. η εύκολη γενίκευση και τροποποίηση του μοντέλου για 2 και 3 διαστάσεις, και φυσικά σε πιο πολύπλοκες Χαμιλτονιανές iii. ο εύκολος αλγόριθμος (από προγραμματιστική πλευρά) iv. ο μικρός χρόνος εκτέλεσης Το μοντέλο Ising μπορεί να χρησιμοποιηθεί για 1,2 ή ακόμα και 3 διαστάσεις, αν γενικευθεί σωστά. Στο συγκεκριμένο πρόγραμμα, μελετούμε 2D μοντέλο. Το μοντέλο χρησιμοποιεί τη μέθοδο M(RT) 2 για να αποφασίσει αν θα γίνει δεκτή μία αλλαγή στο spin ενός πλεγματικού σημείου, το οποίο βέβαια επηρεάζεται από τους κοντινούς γείτονες. Διάγραμμα 2.1: Πλεγματικό σημείο και κοντινοί γείτονες Το πρόγραμμα που αναπτύχθηκε αποτελεί γενίκευση του κώδικα του διδάσκοντα, σε C++. Για να αποφευχθεί ένας μεγάλος κώδικας που επαναλαμβάνεται κάνοντας τα ίδια πράγματα, και για να μπορούν να αντιμετωπιστούν με ένα εννιαίο τρόπο τα διάφορα στατιστικά, έχουμε προγραμματίσει ρουτίνες που υπολογίζουν τη μέση τιμή και την τυπική απόκλιση σε οποιονδήποτε πίνακα που δέχο- 7
νται ως όρισμα. Για να επιτευχθεί αυτό έγινε χρήση pointers. Αυτό έκανε απλούστερο τον κώδικα και πιο κομψό. 1 #include <iostream> 2 #include <ctime> 3 #include <stdio.h> 4 #include <cmath> 5 #include <cstdlib> 6 #include <fstream> 7 #include <sstream> 8 9 using namespace std; 10 #define N 16 11 #define Nens 100 12 #define Nmicro 100 13 #define Nthermalize 200 14 15 int NmicroSkip; 16 int spin[n][n]; 17 double results[10]; 18 19 double rnd() 20 { 21 static unsigned int xseed[3]={time(null),time(null),time( NULL)}; 22 xseed[0]=(1812433253*xseed[0]+1); 23 xseed[1]=(1664525*xseed[1]+1013904223); 24 xseed[2]=(22695477*xseed[2]+1); 25 return (double)xseed[rand()%3]/4294967296.d; 26 } 27 28 void initspins() 29 { 30 for(int i=0;i<n;i++) 31 { 32 for(int j=0;j<n;j++) 33 { 34 spin[i][j]= 1+2*(int)(0.5+rnd()); 35 } 36 } 37 } 38 39 void initresults(double e, double b) 40 { 41 results[0]=exp( 2*( 4*e+b)); 8
42 results[1]=exp( 2*( 2*e+b)); 43 results[2]=exp( 2*(0*e+b)); 44 results[3]=exp( 2*(2*e+b)); 45 results[4]=exp( 2*(4*e+b)); 46 results[5]=exp(+2*( 4*e+b)); 47 results[6]=exp(+2*( 2*e+b)); 48 results[7]=exp(+2*(0*e+b)); 49 results[8]=exp(+2*(2*e+b)); 50 results[9]=exp(+2*(4*e+b)); 51 } 52 53 double giveresult(int totalspin, int ownspin) 54 { 55 if(ownspin==1) switch(totalspin) 56 { 57 case( 4):return results[0]; 58 case( 2):return results[1]; 59 case(0):return results[2]; 60 case(2):return results[3]; 61 case(4):return results[4]; 62 default:cout<<"error"<<endl; 63 } 64 65 else switch(totalspin) 66 { 67 case( 4):return results[5]; 68 case( 2):return results[6]; 69 case(0):return results[7]; 70 case(2):return results[8]; 71 case(4):return results[9]; 72 default:cout<<"error"<<endl; 73 } 74 return 0; 75 } 76 77 int spinofneigh(int x, int y) 78 { 79 int neighbors=0; 80 int x1=x+1; if(x1==n) x1=0; 81 int x2=x 1; if(x2== 1) x2=n 1; 82 int y1=y+1; if(y1==n) y1=0; 83 int y2=y 1; if(y2== 1) y2=n 1; 84 neighbors+=spin[x1][y]; 85 neighbors+=spin[x2][y]; 9
86 neighbors+=spin[x][y1]; 87 neighbors+=spin[x][y2]; 88 return neighbors; 89 } 90 91 void flip(int times) 92 { 93 for(int i=0;i<times;i++) 94 for(int i=0;i<n;i++) 95 for(int j=0;j<n;j++) 96 { 97 if(giveresult(spinofneigh(i,j),spin[i][j])>rnd()){spin[i][j ]*= 1;} 98 } 99 } 100 101 102 int gettotalspin() 103 { 104 int result=0; 105 for(int i=0;i<n;i++) 106 { 107 for(int j=0;j<n;j++) 108 { 109 result+=spin[i][j]; 110 } 111 } 112 return result; 113 } 114 115 double gete(double e, double b) 116 { 117 int jjsum=0; 118 for(int i=0;i<n;i++) 119 { 120 for(int j=0;j<n;j++) 121 { 122 jjsum+=spinofneigh(i,j)*spin[i][j]; 123 } 124 } 125 return 0.5*e*jjsum b*gettotalspin(); 126 } 127 128 double mean(double *thistable, int NN) 10
129 { 130 double result=0; 131 for(int i=0;i<nn;i++) 132 { 133 result+=thistable[i]/nn; 134 } 135 return result; 136 } 137 138 double variance(double *thistable, int NN) 139 { 140 double result=0; 141 for(int i=0;i<nn;i++) 142 { 143 result+=thistable[i]*thistable[i]/nn; 144 } 145 double average=mean(thistable,nn); 146 147 return result average*average; 148 } 149 150 int main() 151 { 152 double epsilon,beta; 153 double Mens[Nens];double Eens[Nens];double CBens[Nens]; double Xens[Nens]; 154 double savedm[nmicro];double savedm2[nmicro];double savede[ Nmicro];double savede2[nmicro]; 155 156 double E,M,CB,X,Ev,Mv,CBv,Xv; 157 158 cout<<"nmicroskip= "; 159 cin>>nmicroskip; 160 cout<<"beta= "; 161 cin>>beta; 162 163 164 ofstream fout; 165 string filename = "solution.txt"; 166 fout.open(filename.c_str()); 167 cout<<"epsilon\te\t\tm\t\tcb\t\tx"<<endl; 168 169 for (int ie=1;ie<24;ie++) 170 { 11
171 epsilon=ie*0.05; 172 if(ie>8) epsilon=0.44+(ie 11)*0.01; 173 if(ie>13) epsilon=(ie 4)*0.05; 174 initresults(epsilon,beta); 175 for (int iens=0;iens<nens;iens++) 176 { 177 initspins(); 178 flip(nthermalize); 179 180 for(int i=0;i<nmicro;i++) 181 { 182 flip(nmicroskip+1); 183 savedm[i]=fabs(gettotalspin()); 184 savedm2[i]=savedm[i]*savedm[i]; 185 savede[i]=gete(epsilon,beta); 186 savede2[i]=savede[i]*savede[i]; 187 } 188 189 Eens[iens]=mean(savedE,Nmicro); 190 Mens[iens]=mean(savedM,Nmicro); 191 CBens[iens]=mean(savedE2,Nmicro) Eens[iens]*Eens[ iens]; 192 Xens[iens]=mean(savedM2,Nmicro) Mens[iens]*Mens[iens ]; 193 194 } 195 196 E= mean(eens,nens)/(n*n); 197 M=mean(Mens,Nens)/(N*N); 198 CB=mean(CBens,Nens)/(N*N); 199 X=mean(Xens,Nens)/(N*N); 200 Ev=sqrt(variance(Eens,Nens))/pow(N,4); 201 Mv=sqrt(variance(Mens,Nens))/pow(N,4); 202 CBv=sqrt(variance(CBens,Nens))/pow(N,4); 203 Xv=sqrt(variance(Xens,Nens))/pow(N,4); 204 205 cout<<epsilon<<"\t"<<e<<" \t"<<m<<" \t"<<cb<<" \t"<<x<<" \n"; 206 cout<<"sd:\t"<<ev<<" \t"<<mv<<" \t"<<cbv<<" \t"<<xv<<"\n "; 207 208 fout<<epsilon<<"\t"<<e<<"\t"<<m<<"\t"<<cb<<"\t"<<x; 209 fout<<"\t"<<ev<<"\t"<<mv<<"\t"<<cbv<<"\t"<<xv<<endl; 210 } 12
211 fout.close(); 212 system("gnuplot p e 'plot \"solution.txt\" using 0:1 title \"Ev\" with points lc rgb \"#0060ad\" lt 1 lw 1 pt 7 ps.2 \' "); 213 system("gnuplot p e 'plot \"solution.txt\" using 0:2 title \"Mv\" with points lc rgb \"#0060ad\" lt 1 lw 1 pt 7 ps.2 \' "); 214 system("gnuplot p e 'plot \"solution.txt\" using 0:3 title \"CBv\" with points lc rgb \"#0060ad\" lt 1 lw 1 pt 7 ps.2 \' "); 215 system("gnuplot p e 'plot \"solution.txt\" using 0:4 title \"Xv\" with points lc rgb \"#0060ad\" lt 1 lw 1 pt 7 ps.2 \' "); 216 return 0; 217 } Το εκτελέσιμο φαίνεται στη ακόλουθη εικόνα: Διάγραμμα 2.2: Ising Executable Τα δεδομένα αποθηκεύονται σε ένα αρχείο που ονομάζεται solution.txt. Τα διαγράμματα που μπορούν να σχεδιαστούν συμφωνούν με τα αναμενόνα από τη βιβλιογραφεία και είναι τα ακόλουθα: 13
Διάγραμμα 2.3: Διάγραμμα E Διάγραμμα 2.4: Διάγραμμα M 14
Διάγραμμα 2.5: Διάγραμμα X Διάγραμμα 2.6: Διάγραμμα CB Να σημειώσουμε εδώ ότι τα διαγράμματα δημιουργούνται αυτόματα από τον κώδικα της C++, με τη κλήση του εξωτερικού προγράμματος gnuplot. Αυτό γίνεται με την εντολή system. 15