-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathising.f90
180 lines (144 loc) · 5.14 KB
/
ising.f90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
program ising
use ziggurat
implicit none
logical :: es, ms
integer :: seed, i, j, k, L, s, pv, M, dM, pasos, n_write, aceptados
real(8) :: Jx, E, dE, x,r, prob, Temp, E_avg, E2_avg, M_avg, M2_avg, B !, p_vec(2)
integer, allocatable :: a(:,:)
Jx = 1.0
![NO TOCAR] Inicializa generador de número random
inquire(file='seed.dat',exist=es)
if(es) then
open(unit=10,file='seed.dat',status='old')
read(10,*) seed
close(10)
! print *," * Leyendo semilla de archivo seed.dat"
else
seed = 24583490
end if
call zigset(seed)
![FIN NO TOCAR]
! Leer variables del archivo input.dat
open(unit=11,file='input.dat',action='read',status='old')
read(11,*)
read(11,*) L, pasos, Temp, B
close(11)
n_write = L*L
!n_write = 1
allocate(a(0:L+1, 0:L+1))
! Chequear si existe matriz.dat, y cargarla como configuracion inicial
inquire(file='matriz.dat',exist=ms)
if(ms) then
! print *," * Leyendo configuracion inicial de matriz.dat"
open(unit=12,file='matriz.dat',status='old')
read(12,*) a(1:L, 1:L)
close(12)
else
! Si no hay matriz inicial, inicializar con 1 y -1 aleatorios
! print *," * Inicializando configuracion aleatoria"
do j = 1, L
do i = 1, L
x = uni()
if (x < 0.5 ) then
a(i,j) = 1
else
a(i,j) = -1
end if
end do
end do
end if
! Condiciones periodicas de contorno
call cpc()
! Calcular la energia y magnetizacion de la matriz
E=0.0
M=0
do j = 1, L
do i = 1, L
s = a(i,j)
pv = a(i+1,j)+a(i,j+1)+a(i-1,j)+a(i,j-1)
E = E - Jx * s * pv - 2 * B * s ! Sumo dos veces la parte de campo magnetico porque al final divido por 2
M = M + s
end do
end do
! Cuento 2 veces las energias
E = E/2
! Inicializo acumuladores para calcular promedios
E_avg = E
E2_avg = E*E
M_avg = dble(M)
M2_avg = dble(M*M)
! Algoritmo Metropolis
! Archivo para grabar los datos de E y M
open(unit=13,file='output.dat',action='write',status='replace')
aceptados = 0
do k = 1, pasos
i = floor(1 + uni()*L)
j = floor(1 + uni()*L)
s = a(i, j)
pv = a(i+1,j)+a(i,j+1)+a(i-1,j)+a(i,j-1)
dE = 2*s*pv*Jx + 2*B*s
dM = -2*s
if (dE <= 0) then
a(i, j) = -s
aceptados = aceptados + 1
else
r = uni()
prob = exp(-dE/Temp)
if (r < prob) then
a(i, j) = -s
aceptados = aceptados + 1
else
dE = 0
dM = 0
end if
end if
! Condiciones periodicas de contorno
call cpc()
! Calculo la nueva energia y magnetizacion, y actualizo los acumuladores
E = E + dE
M = M + dM
M_avg = M_avg + M
M2_avg = M2_avg + M*M
E_avg = E_avg + E
E2_avg = E2_avg + E*E
! Grabo 1 dato de E y M cada n_write iteraciones
if (mod(k,n_write)==0) then
write(13,*) E, M
end if
end do
close(13)
! Divido por el numero de pasos
E_avg = E_avg / (pasos + 1)
E2_avg = E2_avg / (pasos + 1)
M_avg = M_avg / (pasos + 1)
M2_avg = M2_avg / (pasos + 1)
! Guardo los promedios en un archivo, y la fraccion de pasos aceptados
open(unit=14,file='averages.dat',action='write',status='replace')
write(14,*) 'E E2 M M2 Aceptados'
write(14, *) E_avg, E2_avg, M_avg, M2_avg, dble(aceptados)/dble(pasos)
close(14)
! Guardar la ultima matriz en un archivo
open(unit=12,file='matriz.dat',action='write',status='replace')
do i= 1, L
do j = 1, L
write(12,'(I3)', advance='NO') a(i,j)
end do
write(12,*)
end do
close(12)
![No TOCAR]
! Escribir la última semilla para continuar con la cadena de numeros aleatorios
open(unit=10,file='seed.dat',status='unknown')
seed = shr3()
write(10,*) seed
close(10)
![FIN no Tocar]
contains
! Rutina que implementa las condiciones periodicas de contorno
subroutine cpc()
a(0,:) = a(L,:)
a(L+1,:) = a(1,:)
a(:,0) = a(:, L)
a(:,L+1) = a(:, 1)
end subroutine
end program ising