Advertisement
Guest User

Culo

a guest
Oct 31st, 2014
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.49 KB | None | 0 0
  1. /*
  2.    Metropolis Monte Carlo simulation of a 2D Ising system
  3.  
  4.    Cameron F. Abrams
  5.  
  6.    Written for the course CHE 800-002, Molecular Simulation
  7.    Spring 0304
  8.  
  9.    compile using "gcc -o ising ising.c -lm -lgsl"
  10.    (assumes the GNU Scientific Library is installed)
  11.  
  12.    runs as "./ising -L <sidelength(20)> -T <temperature(1.0)> \
  13.                     -nc <numcycles(1e6)> -fs <samplefreq(100)> \
  14.             -s <seed(?)>"
  15.  
  16.    For example, to run a 20x20 system at T = 0.5 for 1e7 cycles
  17.    sampling every 100 cycles, the command looks like
  18.            
  19.           ./ising -L 20 -T 0.5 -nc 1e7 -fs 100
  20.    
  21.    The default values are shown in parentheses above.
  22.  
  23.    You must have the GNU Scientific Library installed; see
  24.    the coursenotes to learn how to do this.
  25.  
  26.    The Hamiltonian is
  27.  
  28.    H = -J sum_<ij> s_i * s_j,
  29.  
  30.    where "sum_<ij>" is the sum over all unique
  31.    nearest neighbor pairs, s_i = +/- 1, and J
  32.    is an arbitrary "coupling" parameter having
  33.    units of energy.  We work in a unit system
  34.    where energy is measured in units of J and
  35.    temperature is nondimensionalized as (k_B*T)/J.
  36.  
  37.    Drexel University, Department of Chemical Engineering
  38.    Philadelphia
  39.    (c) 2004
  40. */
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <math.h>
  44. //#include <gsl/gsl_rng.h>
  45.  
  46. //Computa el cambio de energía debido al giro del spin i,j,
  47. //que corresponde a la energía asociada a los primeros vecinos
  48. //No computa diagonales
  49. int E( int * F, int L, int i, int j)
  50. {
  51.     //(i - 1) < 0 ? L - 1 : i - 1 es una expresión que da L - 1 si (i - 1) < 0
  52.     //es decir se fue de la grilla (condiciones periodicas). Si no da (i - 1).
  53.     //La energía la
  54.     return -2 * F[i*L+j] * (F[((i - 1) < 0 ? L*(L - 1) : L*(i - 1))+ j + F[((i+1) % L)*L+j] +
  55.               F[i*L + ((j-1) < 0 ? L - 1 : j - 1)] + F[i*L+((j + 1) % L)]);
  56. }
  57.  
  58. //Función que mide la magnetización y la energía por sitio
  59. //No devuelve nada, se pasa los valores de magnetización m y energía e
  60. void sampleo(int *F, int L, double *m, double *e)
  61. {
  62.     int i,j;
  63.     *m=0.0;
  64.     *e=0.0;
  65.     for (i = 0; i < L; i++)
  66.     {
  67.         for (j = 0; j < L; j++)
  68.         {
  69.             *m += (double)F[i*L+j];
  70.             //Como sumo sobre todos los índices, con calcular la energía con los vecinos "posteriores"
  71.             //es suficiente
  72.             *e -= (double) (F[i*L+j])*(F[i*L+(j+1)% L]+F[((i+1)%L)*L+j]);
  73.         }
  74.     }
  75.     *m /= (L*L);
  76.     *e /= (L*L);
  77. }
  78.  
  79. /* Randomly assigns all spins */
  80. void init(int *F, int L)
  81. {
  82.   int i,j;
  83.   /* Visit each position (i,j) in the lattice */
  84.   for (i=0; i<L; i++)
  85.   {
  86.     for (j=0; j<L; j++)
  87.     {
  88.         //Número entero al azar entre -1 y 1
  89.         F[i*L+j]= (int) rand() % 2 - 1;
  90.         if (F[i*L+j] == 0)
  91.         {
  92.             F[i*L+j] = 1;
  93.         }
  94.     }
  95.   }
  96. }
  97.  
  98. int main(int argc, char * argv[])
  99. {
  100.     //Parámetros de sistema
  101.     int L = 20; //Tamaño de la red
  102.     int N = L*L; //Cantidad de spines
  103.     double beta = 1.0; //Temperatura adimensional  beta = J/(k*T)
  104.  
  105.     //Parametro de corrida
  106.     int nIter = 2000000; //Pasos de MC, cada uno tiene N cambios de spin
  107.     int nTerm = 1000000; //Pasos hasta termalizar
  108.     int fSamp = 1000;  //Cantidad de pasos entre mediciones
  109.  
  110.     //Variables internas de cálculo
  111.     int nSamp = 0; //Número de muestras, para obtener el promedio de mag y energia
  112.     int de;   //Delta de energía
  113.     double p; //Factor de aceptación
  114.     double r; //Número aleatorio, para comprar con la aceptación
  115.     int i,j,a,c;  //Contadores
  116.  
  117.     //Observables
  118.     double m = 0.0, msum=0.0;    //Magentización
  119.     double e=0.0, esum=0.0;    //Energía
  120.  
  121.   //Obtencion de parámetros
  122.     for (i=1;i<argc;i++)
  123.     {
  124.         if (!strcmp(argv[i],"-L"))
  125.         {
  126.             L = atoi(argv[++i]);
  127.         }
  128.         else if (!strcmp(argv[i],"-T"))
  129.         {
  130.             beta = atof(argv[++i]);
  131.         }
  132.         else if (!strcmp(argv[i],"-N"))
  133.         {
  134.             nIter = atoi(argv[++i]);
  135.         }
  136.         else if (!strcmp(argv[i],"-fs"))
  137.         {
  138.             fSamp = atoi(argv[++i]);
  139.         }
  140.         //else if (!strcmp(argv[i],"-s")) Seed = (unsigned long)atoi(argv[++i]);
  141.     }
  142.     //Toma del tiempo desde el epoch una semilla para el PRNG
  143.     srand(time(NULL));
  144.     int F[L][L];  //Red
  145.     // Corrida de MC
  146.     for (c = 0; c < nIter; c++)
  147.     {
  148.         //Por cada paso de MC hace N giros de spin
  149.         for (a = 0;a < N;a++)
  150.         {
  151.             i = (int)rand() % L;
  152.             j = (int)rand() % L;
  153.             de = E(F,L,i,j); //Delta de Enegía al posiblemente cambiar el estado
  154.             p = exp(de*beta); //Probabilidad de aceptación
  155.             r = rand() % 1; //Número aleatorio entre 0 y 1
  156.             if (p > r)
  157.             {   //Acepta cambio -> lo invierte
  158.                 F[i][j] *= -1;
  159.             }
  160.         }
  161.         /* Sample and accumulate averages */
  162.         if ((c % fSamp) == 0 && c > nTerm)
  163.         {
  164.             sampleo(F, L, &m, &e);
  165.             //fprintf(stdout,"%i %.5le %.5le\n", c, s, e);
  166.             //fflush(stdout);
  167.             msum += m;
  168.             esum+=e;
  169.             nSamp++;
  170.         }
  171.     }
  172.     //sprintf(str, "\n%.5lf %.5lf %.5lf\n", beta, ssum/nSamp, esum/nSamp);
  173.     printf("%.5lf %.5lf %.5lf \n", beta, msum/nSamp, esum/nSamp);
  174.     //fputs(str,fp);
  175.     //fclose(fp);
  176.     //fprintf(stdout,"# The average magnetization is %.5lf\n",ssum/nSamp);
  177.     //fprintf(stdout,"# The average energy per spin is %.5lf\n",esum/nSamp);
  178.     //fprintf(stdout,"# Program ends.\n");
  179. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement