We will cover this task during the lab session, and will use a similar implementation for the main problem, the 2D Ising model.
To keep things simple we pick units so that both \(J\) and \(k_B\) are effectively one. Then the average energy per spin site is \[ \langle E\rangle = - \frac{1}{\text{number of sites}} \frac{1}{2} \sum_{ \begin{array}{c} \text{over all}\\ \text{sites \(i\)} \end{array} } \sum_{ \begin{array}{c} \text{over all}\\ \text{neighbours \(j\)} \end{array} } s_i \cdot s_j \] and the magnetisation per site is \[ \langle M\rangle = \frac{1}{\text{number of sites}} \sum_{ \begin{array}{c} \text{over all}\\ \text{sites \(i\)} \end{array} } s_i \] And the transition probability when flipping to a higher energy state (difference \(\Delta E\)) is \[ p = e^{-\Delta E / T} \]
Implement function
1 2 | |
which returns an 1D array of n elements. The each element are -1/+1 with probability 0.5. So a possible output of init(20) is
1 | |
Implement function
1 2 | |
which displays the model using plt.imshow using optional width and title. So a possible output of show(model, title="time = start") is
Implement function
1 2 | |
which computes the energy per spin site in model due to spin of neighbouring sites. This function should return values in range -1 (for all spin up) to 1 (all spin down).
Implement function
1 2 | |
which computes the bulk magnetisation per spin site in model. This function should return values in range -1 (for all spin down) to 1 (all spin up). (Note the difference with energy.)
Implement function
1 2 3 | |
which performs t_steps Monte Carlo iterations on model. I used the optional parameter debug to print out the usual debug info.
We can now use this function to study the behaviour of the model.
Using code like
1 2 3 4 5 6 7 8 | |
we are able to run a simulation of the same starting state under different conditions.
First when the temperature is low the transition probability limit for a site to flip to a higher state is closer to one so less likely to occur. Hence we expect a trend towards lower energy states
Taking the same initial state:
And re-running simulation for 10,000 steps with \(T=0.1\) we get
So system converges to either state where the spins are aligned.
Re-running same experiment, using same initial state, for high temperature (\(T=5\)) get
So system don't get alignment of spins and at a local level, the prediction of spins is impossible.
So what about temperatues that are not too low nor too high?
Re-running same experiment, using same initial state, for temperature (\(T=1\)) get
We get regions of spin alignment. I think the probability distribution of the size of regions is known but I know that I don't know it. These regions are not fixed and "slowly" change over time.
Rather than looking at the start and end point we can call the function simulate inside a for loop and compute the magnetisation over time, using code like:
1 2 3 4 5 6 7 | |
To examine the effect of temperature we run the following algorithm:
The corresponding code is
1 2 3 4 5 6 7 8 9 10 11 12 | |
and the resulting plot using
1 2 3 4 5 6 | |
This is very noisy and difficult to see, so we need to tweak our algorithm by:
The updated code is
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
and the resulting plot is
This is much better. Now we can see that something fundmental happens around \(T=1\), where the model switches from the low temperature state to the high temperature states. This temperature, \(T=1\), is called the critical temperature. We want to determine the corresponding critical temperature for the 2D model.
The corresponding energy plot is
There are a number of (optional) improvements that can be made to this implementation. In particular
simulate, and not parallelising the flipping of spins. Parallelising the flipping of spins by replacing the element operations in simulate array would result in a huge speedup but would break the Monte Carlo assumption of individual spins occurring and can lead to cyclic effects. There is a fix for this but that is for another day.