-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path2D_Ising_Code2.py
More file actions
130 lines (96 loc) · 3.68 KB
/
2D_Ising_Code2.py
File metadata and controls
130 lines (96 loc) · 3.68 KB
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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Nov 20 15:13:50 2024
@author: vwitch
"""
import numpy as np
import random
import matplotlib.pyplot as plt
class IsingModel:
def __init__(self, size, temperature, field=0):
self.size = size
self.temperature = temperature
self.field = field
self.lattice = np.random.choice([-1, 1], size=(size, size))
def energy(self):
"""Calculate the total energy of the current state."""
energy = 0
for i in range(self.size):
for j in range(self.size):
spin = self.lattice[i, j]
neighbors = self.lattice[(i+1)%self.size, j] + self.lattice[i, (j+1)%self.size] + \
self.lattice[(i-1)%self.size, j] + self.lattice[i, (j-1)%self.size]
energy += -spin * neighbors
return energy / 2 - self.field * np.sum(self.lattice)
def magnetization(self):
"""Calculate the total magnetization of the current state."""
return np.sum(self.lattice)
def metropolis_step(self, sweep='random'):
"""Perform one Metropolis step."""
if sweep == 'random':
for _ in range(self.size**2):
i = random.randint(0, self.size-1)
j = random.randint(0, self.size-1)
self._attempt_flip(i, j)
elif sweep == 'sequential':
for i in range(self.size):
for j in range(self.size):
self._attempt_flip(i, j)
def _attempt_flip(self, i, j):
"""Attempt to flip a spin at position (i, j)."""
spin = self.lattice[i, j]
neighbors = (self.lattice[(i+1) % self.size, j] + self.lattice[(i-1) % self.size, j] +
self.lattice[i, (j+1) % self.size] + self.lattice[i, (j-1) % self.size])
delta_energy = 2 * spin * (neighbors + float(self.field))
if delta_energy < 0 or random.random() < np.exp(-delta_energy / self.temperature):
self.lattice[i, j] *= -1
def simulate(self, steps):
"""Simulate the Ising model for a given number of steps."""
for _ in range(steps):
self.metropolis_step()
def calculate_properties(size, temperatures, steps):
magnetizations = []
energies = []
susceptibilities = []
heat_capacities = []
for T in temperatures:
model = IsingModel(size, T)
model.simulate(steps)
magnetizations.append(model.magnetization() / (size * size))
energies.append(model.energy() / (size * size))
magnetizations = np.array(magnetizations)
energies = np.array(energies)
susceptibilities = np.gradient(magnetizations, temperatures)
heat_capacities = np.gradient(energies, temperatures)
return magnetizations, energies, susceptibilities, heat_capacities
# Parameters
size = 10
temperatures = np.linspace(1.0, 4.0, 50)
steps = 1000
# Calculate properties
magnetizations, energies, susceptibilities, heat_capacities = calculate_properties(size, temperatures, steps)
# Plotting
plt.figure(figsize=(12, 8))
plt.subplot(2, 2, 1)
plt.plot(temperatures, magnetizations, label='Magnetization')
plt.xlabel('Temperature')
plt.ylabel('Magnetization')
plt.legend()
plt.subplot(2, 2, 2)
plt.plot(temperatures, energies, label='Energy')
plt.xlabel('Temperature')
plt.ylabel('Energy')
plt.legend()
plt.subplot(2, 2, 3)
plt.plot(temperatures, susceptibilities, label='Magnetic Susceptibility')
plt.xlabel('Temperature')
plt.ylabel('Susceptibility')
plt.legend()
plt.subplot(2, 2, 4)
plt.plot(temperatures, heat_capacities, label='Heat Capacity')
plt.xlabel('Temperature')
plt.ylabel('Heat Capacity')
plt.legend()
plt.tight_layout()
plt.show()