<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://chemwiki.ch.ic.ac.uk/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Gmallia</id>
	<title>ChemWiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://chemwiki.ch.ic.ac.uk/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Gmallia"/>
	<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/wiki/Special:Contributions/Gmallia"/>
	<updated>2026-05-16T01:30:00Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822109</id>
		<title>Programming a 2D Ising Model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822109"/>
		<updated>2026-05-03T14:25:29Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the Ising Model experiment (aka programming for simple simulations).&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is a core experiment for year 3 students on the Chemistry with Molecular Physics degree.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Programming a 2D Ising Model/ Main page =&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
In this exercise, you are going to use the Python that you learned in the first year to write a code to perform Monte-Carlo simulations of the 2D [http://en.wikipedia.org/wiki/Ising_model Ising model], a set of spins on a lattice which is used to model ferromagnetic behaviour, and also to analyse the results of the simulation to find the heat capacity of the system and the Curie temperature &amp;amp;mdash; the temperature below which the system is able to maintain a spontaneous magnetisation.&lt;br /&gt;
&lt;br /&gt;
A more extensive introduction to the Ising Model will be given in the next page. This page gives some practical information about how the experiment. &lt;br /&gt;
&lt;br /&gt;
==Assessment==&lt;br /&gt;
At the end of this experiment you must submit a report, writing up your findings. Each section of the experiment has a number of tasks that you should complete, labelled &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK&amp;lt;/big&amp;gt;&#039;&#039;&#039;. If this is a mathematical exercise, your report should contain a short summary of the solution. If it is a graphical exercise, you should include the relevant image. Your report should explain briefly what you did in each stage of the experiment, and what your findings were.&lt;br /&gt;
&lt;br /&gt;
The report should be submitted as a PDF file to Turnitin, created with your favourite word processor or LaTeX, and should contain the annotated source code of the Python scripts that your write during the experiment. For clarity, code included in the report should be written in a monospaced font (e.g. Courier), which in LaTeX can be easily achieved by placing your code inside a &amp;lt;code&amp;gt;\texttt{}&amp;lt;/code&amp;gt; command. &#039;&#039;&#039;The code, except where relevant to discussion, can be placed in an appendix.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As well as including relevant source code in your report, you should also submit a bundle with all your scripts and analysis code as a separate Blackboard submission.&lt;br /&gt;
&lt;br /&gt;
===On the use of AI tools===&lt;br /&gt;
The code you write for this experiment is assessed, and as per the [https://bb.imperial.ac.uk/bbcswebdav/pid-3344481-dt-content-rid-21115105_1/xid-21115105_1 department&#039;s guidelines on the use of AI], it is not acceptable to use generative AI tools to write computer code for this assignment.&lt;br /&gt;
&lt;br /&gt;
Writing computer programs yourself enhances your logical thinking and problem solving skills. Using generative AI tools to write your code makes you dumb. Don&#039;t choose to be dumb, don&#039;t use AI to write code for you.&lt;br /&gt;
&lt;br /&gt;
==Getting Help==&lt;br /&gt;
&lt;br /&gt;
The Graduate Teaching Assistants demonstrating this experiment are Fionn Carman and Lei Li. Demonstrators will be available in room 232A at the following times:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Demonstrator timetable&lt;br /&gt;
! !! Monday !! Tuesday !! Wednesday !! Thusrsday !! Friday&lt;br /&gt;
|-&lt;br /&gt;
| Morning || 10:00 - Experiment intro&amp;lt;br /&amp;gt; 10:00-13:00 - Li || 10:00-13:00 - Fionn|| || 10:00-12:00 - João || 10:00-13:00 - Fionn&lt;br /&gt;
|-&lt;br /&gt;
| Afternoon || 14:00-17:00 - Li|| 14:00-17:00 - Fionn|| ||  || 14:00-17:00 - Fionn&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you have questions outside these times, please use the Discussion Board on Blackboard.&lt;br /&gt;
&lt;br /&gt;
João and Giuseppe are the members of academic staff responsible for this experiment. You are welcome to address your questions and comments to them.&lt;br /&gt;
&lt;br /&gt;
==Structure of this Experiment==&lt;br /&gt;
&lt;br /&gt;
This experimental manual has been broken up into a number of subsections. Direct links to each of them may be found below. You should attempt them in order, and you should complete all of them to finish the experiment.&lt;br /&gt;
&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model|Introduction to the Ising model]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Calculating the energy and magnetisation|Calculating the energy and magnetisation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction to Monte Carlo simulation|Introduction to the Monte Carlo simulation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Accelerating the code|Accelerating the code]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of temperature|The effect of temperature]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of system size|The effect of system size]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Determining the heat capacity|Determining the heat capacity]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Locating the Curie temperature|Locating the Curie temperature]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Introduction to the Ising model|1. Introduction to the Ising model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Locating_the_Curie_temperature&amp;diff=822108</id>
		<title>Programming a 2D Ising Model/Locating the Curie temperature</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Locating_the_Curie_temperature&amp;diff=822108"/>
		<updated>2026-05-03T14:08:30Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the eighth (and final) section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Determining the heat capacity|7. Determining the heat capacity]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 8. Locating the Curie temperature =&lt;br /&gt;
You should have seen in the previous section that the heat capacity becomes strongly peaked in the vicinity of the critical temperature and that the peak became increasingly sharply peaked as the system size was increased &amp;amp;mdash; in fact, Onsager proved that in an infinite system the heat capacity should diverge at &#039;&#039;T&#039;&#039; = &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;. In our finite systems, however, not only does the heat capacity not diverge, the Curie temperature changes with system size! This is known as a &#039;&#039;finite size effect&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
It can be shown, however, that the temperature at which the heat capacity has its maximum must scale according to &amp;lt;math&amp;gt;T_{C, L} = \frac{A}{L} + T_{C,\infty}&amp;lt;/math&amp;gt;, where &#039;&#039;T&amp;lt;sub&amp;gt;C,L&amp;lt;/sub&amp;gt;&#039;&#039; is the Curie temperature of an &#039;&#039;L&#039;&#039;&amp;amp;times;&#039;&#039;L&#039;&#039; lattice, &#039;&#039;T&amp;lt;sub&amp;gt;C,&amp;amp;infin;&amp;lt;/sub&amp;gt;&#039;&#039; is the Curie temperature of an infinite lattice, and &#039;&#039;A&#039;&#039; is a constant in which we are not especially interested. This scaling equation comes from expanding in the limit of large &#039;&#039;L&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 8a&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Reference data has been generated for longer simulations than would be possible on the college computers in Python. Each file contains six columns: &#039;&#039;T&#039;&#039;, &#039;&#039;E&#039;&#039;, &#039;&#039;E&#039;&#039;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;, &#039;&#039;M&#039;&#039;, &#039;&#039;M&#039;&#039;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;, &#039;&#039;C&#039;&#039; (NOTE: these final five quantities are normalised per spin, unlike your Python data), and you can read them with the NumPy &amp;lt;code&amp;gt;loadtxt&amp;lt;/code&amp;gt; function as before. For each lattice size, plot the reference data against your data. For &#039;&#039;one&#039;&#039; lattice size, save a SVG or PNG image of this comparison and add it to your report &amp;amp;mdash; add a legend to the graph to label which is which (check if you need a [https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.legend.html reminder about use of legend]).&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Polynomial fitting==&lt;br /&gt;
&lt;br /&gt;
To find the temperature at which the heat capacity and susceptibilities have their maxima, we are going to fit a polynomial to the data in the critical region. NumPy provides the useful [http://docs.scipy.org/doc/numpy/reference/generated/numpy.polyfit.html &amp;lt;code&amp;gt;polyfit&amp;lt;/code&amp;gt;] and [http://docs.scipy.org/doc/numpy/reference/generated/numpy.polyval.html#numpy.polyval &amp;lt;code&amp;gt;polyval&amp;lt;/code&amp;gt;] functions for this purpose. The following code is written for the heat capacities - try to also repeat this for the susceptibility! The usage is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
data = np.loadtxt(&amp;quot;...&amp;quot;) #assume data is now a 2D array containing two columns, T and C&lt;br /&gt;
T = data[:,0] #get the first column&lt;br /&gt;
C = data[:,1] # get the second column&lt;br /&gt;
&lt;br /&gt;
#first we fit the polynomial to the data&lt;br /&gt;
fit = np.polyfit(T, C, 3) # fit a third order polynomial&lt;br /&gt;
&lt;br /&gt;
#now we generate interpolated values of the fitted polynomial over the range of our function&lt;br /&gt;
T_min = np.min(T)&lt;br /&gt;
T_max = np.max(T)&lt;br /&gt;
T_range = np.linspace(T_min, T_max, 1000) #generate 1000 evenly spaced points between T_min and T_max&lt;br /&gt;
fitted_C_values = np.polyval(fit, T_range) # use the fit object to generate the corresponding values of C&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 8b&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Write a script to read the data from a particular file, and plot &#039;&#039;C&#039;&#039; and &#039;&#039;&amp;amp;chi;&#039;&#039; vs &#039;&#039;T&#039;&#039;, as well as a fitted polynomial. Try changing the degree of the polynomial to improve the fit &amp;amp;mdash; in general, it might be difficult to get a good fit! Attach a SVG or PNG image of an example fit to your report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Fitting in a particular temperature range===&lt;br /&gt;
&lt;br /&gt;
Rather than fit to all of the data, we might want to fit in only a particular range. NumPy provides a very powerful way to index arrays based on certain conditions. For example, if we want to extract only those data points which are between a particular &#039;&#039;T&#039;&#039;&amp;lt;sub&amp;gt;min&amp;lt;/sub&amp;gt; and &#039;&#039;T&#039;&#039;&amp;lt;sub&amp;gt;max&amp;lt;/sub&amp;gt;, we can use the following syntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
data = np.loadtxt(&amp;quot;...&amp;quot;) #assume data is now a 2D array containing two columns, T and C&lt;br /&gt;
T = data[:,0] #get the first column&lt;br /&gt;
C = data[:,1] # get the second column&lt;br /&gt;
&lt;br /&gt;
Tmin = 0.5 #for example&lt;br /&gt;
Tmax = 2.0 #for example&lt;br /&gt;
&lt;br /&gt;
selection = np.logical_and(T &amp;gt; Tmin, T &amp;lt; Tmax) #choose only those rows where both conditions are true&lt;br /&gt;
peak_T_values = T[selection]&lt;br /&gt;
peak_C_values = C[selection]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 8c&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Modify your script from the previous section. You should still plot the whole temperature range, but fit the polynomial only to the peak! You should find it easier to get a good fit when restricted to this region.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Finding the peak in C===&lt;br /&gt;
&lt;br /&gt;
Your fitting script should now generate two variables: &amp;lt;code&amp;gt;peak_T_range&amp;lt;/code&amp;gt;, containing 1000 equally spaced temperature values between &#039;&#039;T&#039;&#039;&amp;lt;sub&amp;gt;min&amp;lt;/sub&amp;gt; and &#039;&#039;T&#039;&#039;&amp;lt;sub&amp;gt;max&amp;lt;/sub&amp;gt; (whatever you chose those values to be), and fitted_&#039;&#039;C&#039;&#039;_values, containing the fitted heat capacity at each of those points. Use the NumPy &amp;lt;code&amp;gt;max&amp;lt;/code&amp;gt; function to find the maximum in &#039;&#039;C&#039;&#039;. If you store the maximum value of &#039;&#039;C&#039;&#039; in the variable &amp;lt;code&amp;gt;Cmax&amp;lt;/code&amp;gt;, you can use the following notation to find the corresponding temperature:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Cmax = np.max(...)&lt;br /&gt;
Tmax = peak_T_range[fitted_C_values == Cmax]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 8d&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Find the temperature at which the maximum in &#039;&#039;C&#039;&#039; occurs for each datafile that you were given or generated with Python. Make a text file containing two columns: the lattice side length (2,4,8, etc.), and the temperature at which &#039;&#039;C&#039;&#039; is a maximum. This is your estimate of &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039; for that side length. Make a plot that uses the scaling relation given above to determine &#039;&#039;T&amp;lt;sub&amp;gt;C,&amp;amp;infin;&amp;lt;/sub&amp;gt;&#039;&#039;. By doing a little research, you should be able to find the theoretical exact Curie temperature for the infinite 2D Ising lattice. How does your value compare to this? Are you surprised by how good/bad the agreement is? Attach a SVG or PNG image of this final graph to your report, and discuss briefly what you think the major sources of error are in your estimate.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the eighth (and final) section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Determining the heat capacity|7. Determining the heat capacity]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Locating_the_Curie_temperature&amp;diff=822107</id>
		<title>Programming a 2D Ising Model/Locating the Curie temperature</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Locating_the_Curie_temperature&amp;diff=822107"/>
		<updated>2026-05-03T14:07:39Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the eighth (and final) section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Determining the heat capacity|7. Determining the heat capacity]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 8. Locating the Curie temperature =&lt;br /&gt;
You should have seen in the previous section that the heat capacity becomes strongly peaked in the vicinity of the critical temperature and that the peak became increasingly sharply peaked as the system size was increased &amp;amp;mdash; in fact, Onsager proved that in an infinite system the heat capacity should diverge at &#039;&#039;T&#039;&#039; = &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;. In our finite systems, however, not only does the heat capacity not diverge, the Curie temperature changes with system size! This is known as a &#039;&#039;finite size effect&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
It can be shown, however, that the temperature at which the heat capacity has its maximum must scale according to &amp;lt;math&amp;gt;T_{C, L} = \frac{A}{L} + T_{C,\infty}&amp;lt;/math&amp;gt;, where &#039;&#039;T&amp;lt;sub&amp;gt;C,L&amp;lt;/sub&amp;gt;&#039;&#039; is the Curie temperature of an &#039;&#039;L&#039;&#039;&amp;amp;times;&#039;&#039;L&#039;&#039; lattice, &#039;&#039;T&amp;lt;sub&amp;gt;C,&amp;amp;infin;&amp;lt;/sub&amp;gt;&#039;&#039; is the Curie temperature of an infinite lattice, and &#039;&#039;A&#039;&#039; is a constant in which we are not especially interested. This scaling equation comes from expanding in the limit of large &#039;&#039;L&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 8a&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Reference data has been generated for longer simulations than would be possible on the college computers in Python. Each file contains six columns: &#039;&#039;T&#039;&#039;, &#039;&#039;E&#039;&#039;, &#039;&#039;E&#039;&#039;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;, &#039;&#039;M&#039;&#039;, &#039;&#039;M&#039;&#039;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;, &#039;&#039;C&#039;&#039; (NOTE: these final five quantities are normalised per spin, unlike your Python data), and you can read them with the NumPy &amp;lt;code&amp;gt;loadtxt&amp;lt;/code&amp;gt; function as before. For each lattice size, plot the reference data against your data. For &#039;&#039;one&#039;&#039; lattice size, save a SVG or PNG image of this comparison and add it to your report &amp;amp;mdash; add a legend to the graph to label which is which (check if you need a [https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.legend.html reminder about use of legend]).&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Polynomial fitting==&lt;br /&gt;
&lt;br /&gt;
To find the temperature at which the heat capacity and susceptibilities have their maxima, we are going to fit a polynomial to the data in the critical region. NumPy provides the useful [http://docs.scipy.org/doc/numpy/reference/generated/numpy.polyfit.html &amp;lt;code&amp;gt;polyfit&amp;lt;/code&amp;gt;] and [http://docs.scipy.org/doc/numpy/reference/generated/numpy.polyval.html#numpy.polyval &amp;lt;code&amp;gt;polyval&amp;lt;/code&amp;gt;] functions for this purpose. The following code is written for the heat capacities - try to also repeat this for the susceptibility! The usage is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
data = np.loadtxt(&amp;quot;...&amp;quot;) #assume data is now a 2D array containing two columns, T and C&lt;br /&gt;
T = data[:,0] #get the first column&lt;br /&gt;
C = data[:,1] # get the second column&lt;br /&gt;
&lt;br /&gt;
#first we fit the polynomial to the data&lt;br /&gt;
fit = np.polyfit(T, C, 3) # fit a third order polynomial&lt;br /&gt;
&lt;br /&gt;
#now we generate interpolated values of the fitted polynomial over the range of our function&lt;br /&gt;
T_min = np.min(T)&lt;br /&gt;
T_max = np.max(T)&lt;br /&gt;
T_range = np.linspace(T_min, T_max, 1000) #generate 1000 evenly spaced points between T_min and T_max&lt;br /&gt;
fitted_C_values = np.polyval(fit, T_range) # use the fit object to generate the corresponding values of C&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 8b&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;Write a script to read the data from a particular file, and plot &#039;&#039;C&#039;&#039; and &#039;&#039;&amp;amp;chi;&#039;&#039; vs &#039;&#039;T&#039;&#039;, as well as a fitted polynomial. Try changing the degree of the polynomial to improve the fit &amp;amp;mdash; in general, it might be difficult to get a good fit! Attach a SVG or PNG image of an example fit to your report.&#039;&#039;&#039; ====&lt;br /&gt;
&lt;br /&gt;
===Fitting in a particular temperature range===&lt;br /&gt;
&lt;br /&gt;
Rather than fit to all of the data, we might want to fit in only a particular range. NumPy provides a very powerful way to index arrays based on certain conditions. For example, if we want to extract only those data points which are between a particular &#039;&#039;T&#039;&#039;&amp;lt;sub&amp;gt;min&amp;lt;/sub&amp;gt; and &#039;&#039;T&#039;&#039;&amp;lt;sub&amp;gt;max&amp;lt;/sub&amp;gt;, we can use the following syntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
data = np.loadtxt(&amp;quot;...&amp;quot;) #assume data is now a 2D array containing two columns, T and C&lt;br /&gt;
T = data[:,0] #get the first column&lt;br /&gt;
C = data[:,1] # get the second column&lt;br /&gt;
&lt;br /&gt;
Tmin = 0.5 #for example&lt;br /&gt;
Tmax = 2.0 #for example&lt;br /&gt;
&lt;br /&gt;
selection = np.logical_and(T &amp;gt; Tmin, T &amp;lt; Tmax) #choose only those rows where both conditions are true&lt;br /&gt;
peak_T_values = T[selection]&lt;br /&gt;
peak_C_values = C[selection]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 8c&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Modify your script from the previous section. You should still plot the whole temperature range, but fit the polynomial only to the peak! You should find it easier to get a good fit when restricted to this region.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Finding the peak in C===&lt;br /&gt;
&lt;br /&gt;
Your fitting script should now generate two variables: &amp;lt;code&amp;gt;peak_T_range&amp;lt;/code&amp;gt;, containing 1000 equally spaced temperature values between &#039;&#039;T&#039;&#039;&amp;lt;sub&amp;gt;min&amp;lt;/sub&amp;gt; and &#039;&#039;T&#039;&#039;&amp;lt;sub&amp;gt;max&amp;lt;/sub&amp;gt; (whatever you chose those values to be), and fitted_&#039;&#039;C&#039;&#039;_values, containing the fitted heat capacity at each of those points. Use the NumPy &amp;lt;code&amp;gt;max&amp;lt;/code&amp;gt; function to find the maximum in &#039;&#039;C&#039;&#039;. If you store the maximum value of &#039;&#039;C&#039;&#039; in the variable &amp;lt;code&amp;gt;Cmax&amp;lt;/code&amp;gt;, you can use the following notation to find the corresponding temperature:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Cmax = np.max(...)&lt;br /&gt;
Tmax = peak_T_range[fitted_C_values == Cmax]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 8d&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Find the temperature at which the maximum in &#039;&#039;C&#039;&#039; occurs for each datafile that you were given or generated with Python. Make a text file containing two columns: the lattice side length (2,4,8, etc.), and the temperature at which &#039;&#039;C&#039;&#039; is a maximum. This is your estimate of &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039; for that side length. Make a plot that uses the scaling relation given above to determine &#039;&#039;T&amp;lt;sub&amp;gt;C,&amp;amp;infin;&amp;lt;/sub&amp;gt;&#039;&#039;. By doing a little research, you should be able to find the theoretical exact Curie temperature for the infinite 2D Ising lattice. How does your value compare to this? Are you surprised by how good/bad the agreement is? Attach a SVG or PNG image of this final graph to your report, and discuss briefly what you think the major sources of error are in your estimate.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the eighth (and final) section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Determining the heat capacity|7. Determining the heat capacity]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822106</id>
		<title>Programming a 2D Ising Model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822106"/>
		<updated>2026-05-03T14:04:35Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* Structure of this Experiment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;This is the Ising Model experiment (aka programming for simple simulations).&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;This is a core experiment for year 3 students on the Chemistry with Molecular Physics degree.&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Programming a 2D Ising Model/ Main page =&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
In this exercise, you are going to use the Python that you learned in the first year to write a code to perform Monte-Carlo simulations of the 2D [http://en.wikipedia.org/wiki/Ising_model Ising model], a set of spins on a lattice which is used to model ferromagnetic behaviour, and also to analyse the results of the simulation to find the heat capacity of the system and the Curie temperature &amp;amp;mdash; the temperature below which the system is able to maintain a spontaneous magnetisation.&lt;br /&gt;
&lt;br /&gt;
A more extensive introduction to the Ising Model will be given in the next page. This page gives some practical information about how the experiment. &lt;br /&gt;
&lt;br /&gt;
==Assessment==&lt;br /&gt;
At the end of this experiment you must submit a report, writing up your findings. Each section of the experiment has a number of tasks that you should complete, labelled &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK&amp;lt;/big&amp;gt;&#039;&#039;&#039;. If this is a mathematical exercise, your report should contain a short summary of the solution. If it is a graphical exercise, you should include the relevant image. Your report should explain briefly what you did in each stage of the experiment, and what your findings were.&lt;br /&gt;
&lt;br /&gt;
The report should be submitted as a PDF file to Turnitin, created with your favourite word processor or LaTeX, and should contain the annotated source code of the Python scripts that your write during the experiment. For clarity, code included in the report should be written in a monospaced font (e.g. Courier), which in LaTeX can be easily achieved by placing your code inside a &amp;lt;code&amp;gt;\texttt{}&amp;lt;/code&amp;gt; command. &#039;&#039;&#039;The code, except where relevant to discussion, can be placed in an appendix.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As well as including relevant source code in your report, you should also submit a bundle with all your scripts and analysis code as a separate Blackboard submission.&lt;br /&gt;
&lt;br /&gt;
===On the use of AI tools===&lt;br /&gt;
The code you write for this experiment is assessed, and as per the [https://bb.imperial.ac.uk/bbcswebdav/pid-3344481-dt-content-rid-21115105_1/xid-21115105_1 department&#039;s guidelines on the use of AI], it is not acceptable to use generative AI tools to write computer code for this assignment.&lt;br /&gt;
&lt;br /&gt;
Writing computer programs yourself enhances your logical thinking and problem solving skills. Using generative AI tools to write your code makes you dumb. Don&#039;t choose to be dumb, don&#039;t use AI to write code for you.&lt;br /&gt;
&lt;br /&gt;
==Getting Help==&lt;br /&gt;
&lt;br /&gt;
The Graduate Teaching Assistants demonstrating this experiment are Fionn Carman and Lei Li. Demonstrators will be available in room 232A at the following times:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Demonstrator timetable&lt;br /&gt;
! !! Monday !! Tuesday !! Wednesday !! Thusrsday !! Friday&lt;br /&gt;
|-&lt;br /&gt;
| Morning || 10:00 - Experiment intro&amp;lt;br /&amp;gt; 10:00-13:00 - Li || 10:00-13:00 - Fionn|| || 10:00-12:00 - João || 10:00-13:00 - Fionn&lt;br /&gt;
|-&lt;br /&gt;
| Afternoon || 14:00-17:00 - Li|| 14:00-17:00 - Fionn|| ||  || 14:00-17:00 - Fionn&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you have questions outside these times, please use the Discussion Board on Blackboard.&lt;br /&gt;
&lt;br /&gt;
João and Giuseppe are the members of academic staff responsible for this experiment. You are welcome to address your questions and comments to them.&lt;br /&gt;
&lt;br /&gt;
==Structure of this Experiment==&lt;br /&gt;
&lt;br /&gt;
This experimental manual has been broken up into a number of subsections. Direct links to each of them may be found below. You should attempt them in order, and you should complete all of them to finish the experiment.&lt;br /&gt;
&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model|Introduction to the Ising model]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Calculating the energy and magnetisation|Calculating the energy and magnetisation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction to Monte Carlo simulation|Introduction to the Monte Carlo simulation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Accelerating the code|Accelerating the code]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of temperature|The effect of temperature]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of system size|The effect of system size]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Determining the heat capacity|Determining the heat capacity]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Locating the Curie temperature|Locating the Curie temperature]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Introduction to the Ising model|1. Introduction to the Ising model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822105</id>
		<title>Programming a 2D Ising Model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822105"/>
		<updated>2026-05-03T14:02:53Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;This is the Ising Model experiment (aka programming for simple simulations).&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;This is a core experiment for year 3 students on the Chemistry with Molecular Physics degree.&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Programming a 2D Ising Model/ Main page =&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
In this exercise, you are going to use the Python that you learned in the first year to write a code to perform Monte-Carlo simulations of the 2D [http://en.wikipedia.org/wiki/Ising_model Ising model], a set of spins on a lattice which is used to model ferromagnetic behaviour, and also to analyse the results of the simulation to find the heat capacity of the system and the Curie temperature &amp;amp;mdash; the temperature below which the system is able to maintain a spontaneous magnetisation.&lt;br /&gt;
&lt;br /&gt;
A more extensive introduction to the Ising Model will be given in the next page. This page gives some practical information about how the experiment. &lt;br /&gt;
&lt;br /&gt;
==Assessment==&lt;br /&gt;
At the end of this experiment you must submit a report, writing up your findings. Each section of the experiment has a number of tasks that you should complete, labelled &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK&amp;lt;/big&amp;gt;&#039;&#039;&#039;. If this is a mathematical exercise, your report should contain a short summary of the solution. If it is a graphical exercise, you should include the relevant image. Your report should explain briefly what you did in each stage of the experiment, and what your findings were.&lt;br /&gt;
&lt;br /&gt;
The report should be submitted as a PDF file to Turnitin, created with your favourite word processor or LaTeX, and should contain the annotated source code of the Python scripts that your write during the experiment. For clarity, code included in the report should be written in a monospaced font (e.g. Courier), which in LaTeX can be easily achieved by placing your code inside a &amp;lt;code&amp;gt;\texttt{}&amp;lt;/code&amp;gt; command. &#039;&#039;&#039;The code, except where relevant to discussion, can be placed in an appendix.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As well as including relevant source code in your report, you should also submit a bundle with all your scripts and analysis code as a separate Blackboard submission.&lt;br /&gt;
&lt;br /&gt;
===On the use of AI tools===&lt;br /&gt;
The code you write for this experiment is assessed, and as per the [https://bb.imperial.ac.uk/bbcswebdav/pid-3344481-dt-content-rid-21115105_1/xid-21115105_1 department&#039;s guidelines on the use of AI], it is not acceptable to use generative AI tools to write computer code for this assignment.&lt;br /&gt;
&lt;br /&gt;
Writing computer programs yourself enhances your logical thinking and problem solving skills. Using generative AI tools to write your code makes you dumb. Don&#039;t choose to be dumb, don&#039;t use AI to write code for you.&lt;br /&gt;
&lt;br /&gt;
==Getting Help==&lt;br /&gt;
&lt;br /&gt;
The Graduate Teaching Assistants demonstrating this experiment are Fionn Carman and Lei Li. Demonstrators will be available in room 232A at the following times:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Demonstrator timetable&lt;br /&gt;
! !! Monday !! Tuesday !! Wednesday !! Thusrsday !! Friday&lt;br /&gt;
|-&lt;br /&gt;
| Morning || 10:00 - Experiment intro&amp;lt;br /&amp;gt; 10:00-13:00 - Li || 10:00-13:00 - Fionn|| || 10:00-12:00 - João || 10:00-13:00 - Fionn&lt;br /&gt;
|-&lt;br /&gt;
| Afternoon || 14:00-17:00 - Li|| 14:00-17:00 - Fionn|| ||  || 14:00-17:00 - Fionn&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you have questions outside these times, please use the Discussion Board on Blackboard.&lt;br /&gt;
&lt;br /&gt;
João and Giuseppe are the members of academic staff responsible for this experiment. You are welcome to address your questions and comments to them.&lt;br /&gt;
&lt;br /&gt;
==Structure of this Experiment==&lt;br /&gt;
&lt;br /&gt;
This experimental manual has been broken up into a number of subsections. Direct links to each of them may be found below. You should attempt them in order, and you should complete all of them to finish the experiment.&lt;br /&gt;
&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model|Introduction to the Ising model]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Calculating the energy and magnetisation|Calculating the energy and magnetisation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction to Monte Carlo simulation|Introduction to the Monte Carlo simulation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Accelerating the code|Accelerating the code]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of temperature|The effect of temperature]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of system size|The effect of system size]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Determining the heat capacity|Determining the heat capacity]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Locating the Curie temperature|Locating the Curie temperature]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Next section: [[Programming a 2D Ising Model/Introduction to the Ising model|1. Introduction to the Ising model]]&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822104</id>
		<title>Programming a 2D Ising Model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822104"/>
		<updated>2026-05-03T14:01:40Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;This is the Ising Model experiment (aka programming for simple simulations).&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;This is a core experiment for year 3 students on the Chemistry with Molecular Physics degree.&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Programming a 2D Ising Model/ Main page =&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
In this exercise, you are going to use the Python that you learned in the first year to write a code to perform Monte-Carlo simulations of the 2D [http://en.wikipedia.org/wiki/Ising_model Ising model], a set of spins on a lattice which is used to model ferromagnetic behaviour, and also to analyse the results of the simulation to find the heat capacity of the system and the Curie temperature &amp;amp;mdash; the temperature below which the system is able to maintain a spontaneous magnetisation.&lt;br /&gt;
&lt;br /&gt;
A more extensive introduction to the Ising Model will be given in the next page. This page gives some practical information about how the experiment. &lt;br /&gt;
&lt;br /&gt;
==Assessment==&lt;br /&gt;
At the end of this experiment you must submit a report, writing up your findings. Each section of the experiment has a number of tasks that you should complete, labelled &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK&amp;lt;/big&amp;gt;&#039;&#039;&#039;. If this is a mathematical exercise, your report should contain a short summary of the solution. If it is a graphical exercise, you should include the relevant image. Your report should explain briefly what you did in each stage of the experiment, and what your findings were.&lt;br /&gt;
&lt;br /&gt;
The report should be submitted as a PDF file to Turnitin, created with your favourite word processor or LaTeX, and should contain the annotated source code of the Python scripts that your write during the experiment. For clarity, code included in the report should be written in a monospaced font (e.g. Courier), which in LaTeX can be easily achieved by placing your code inside a &amp;lt;code&amp;gt;\texttt{}&amp;lt;/code&amp;gt; command. &#039;&#039;&#039;The code, except where relevant to discussion, can be placed in an appendix.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As well as including relevant source code in your report, you should also submit a bundle with all your scripts and analysis code as a separate Blackboard submission.&lt;br /&gt;
&lt;br /&gt;
===On the use of AI tools===&lt;br /&gt;
The code you write for this experiment is assessed, and as per the [https://bb.imperial.ac.uk/bbcswebdav/pid-3344481-dt-content-rid-21115105_1/xid-21115105_1 department&#039;s guidelines on the use of AI], it is not acceptable to use generative AI tools to write computer code for this assignment.&lt;br /&gt;
&lt;br /&gt;
Writing computer programs yourself enhances your logical thinking and problem solving skills. Using generative AI tools to write your code makes you dumb. Don&#039;t choose to be dumb, don&#039;t use AI to write code for you.&lt;br /&gt;
&lt;br /&gt;
==Getting Help==&lt;br /&gt;
&lt;br /&gt;
The Graduate Teaching Assistants demonstrating this experiment are Fionn Carman and Lei Li. Demonstrators will be available in room 232A at the following times:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Demonstrator timetable&lt;br /&gt;
! !! Monday !! Tuesday !! Wednesday !! Thusrsday !! Friday&lt;br /&gt;
|-&lt;br /&gt;
| Morning || 10:00 - Experiment intro&amp;lt;br /&amp;gt; 10:00-13:00 - Li || 10:00-13:00 - Fionn|| || 10:00-12:00 - João || 10:00-13:00 - Fionn&lt;br /&gt;
|-&lt;br /&gt;
| Afternoon || 14:00-17:00 - Li|| 14:00-17:00 - Fionn|| ||  || 14:00-17:00 - Fionn&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you have questions outside these times, please use the Discussion Board on Blackboard.&lt;br /&gt;
&lt;br /&gt;
João and Giuseppe are the members of academic staff responsible for this experiment. You are welcome to address your questions and comments to them.&lt;br /&gt;
&lt;br /&gt;
==Structure of this Experiment==&lt;br /&gt;
&lt;br /&gt;
This experimental manual has been broken up into a number of subsections. Direct links to each of them may be found below. You should attempt them in order, and you should complete all of them to finish the experiment.&lt;br /&gt;
&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model|Introduction to the Ising model]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Calculating the energy and magnetisation|Calculating the energy and magnetisation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction to Monte Carlo simulation|Introduction to the Monte Carlo simulation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Accelerating the code|Accelerating the code]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of temperature|The effect of temperature]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of system size|The effect of system size]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Determining the heat capacity|Determining the heat capacity]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Locating the Curie temperature|Locating the Curie temperature]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Next section: [[Programming a 2D Ising Model/Introduction to the Ising model|1. Introduction to the Ising model]]&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Determining_the_heat_capacity&amp;diff=822103</id>
		<title>Programming a 2D Ising Model/Determining the heat capacity</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Determining_the_heat_capacity&amp;diff=822103"/>
		<updated>2026-05-03T14:00:31Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the seventh section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/The effect of system size|6. The effect of system size]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Locating the Curie temperature|8. Locating the Curie temperature]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Calculating the heat capacity==&lt;br /&gt;
&lt;br /&gt;
As we have seen, increasing the temperature above &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039; induces a phase transition &amp;amp;mdash; the magnetisation of the system rapidly drops, but it can be hard to use this information to pinpoint the Curie temperature itself. As well as demonstrating the closed form solution to the partition function that we mentioned in the introduction, Lars Onsager also demonstrated that the heat capacity of the 2D Ising model should become very strongly peaked at the phase transition temperature (in fact, when &#039;&#039;T&#039;&#039; = &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039; exactly, &#039;&#039;C&#039;&#039; diverges).&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 7a&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;By definition, &amp;lt;math&amp;gt;C = \frac{\partial \left\langle E\right\rangle}{\partial T}&amp;lt;/math&amp;gt;. From this, show that &amp;lt;math&amp;gt;C = \frac{\mathrm{Var}[E]}{k_B T^2}&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;\mathrm{Var}[E]&amp;lt;/math&amp;gt; is the variance in &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using this relation, and the data that you generated in the previous sections, you can now determine the heat capacity of your lattice as a function of temperature and system size. in a similar way, we can also define another quantity called the magnetic susceptibility, &#039;&#039;&amp;amp;chi;&#039;&#039;, which depends on the average properties of the order parameter of the system:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\chi = \beta(\left\langle M^2\right\rangle - \left\langle M\right\rangle^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which will behave in a similar way to the heat capacity. Here &amp;lt;math&amp;gt;\beta = \frac{1}{k_BT}&amp;lt;/math&amp;gt; is the inverse of the thermodynamic temperature, often used in statistical thermodynamics. &lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 7b&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Write a Python script to make a plot showing the heat capacity and susceptibility versus temperature for each of your lattice sizes from the previous section. You may need to do some research to recall the connection between the variance of a variable, Var[&#039;&#039;X&#039;&#039;], the mean of its square  &amp;amp;lang;&#039;&#039;X&#039;&#039;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;amp;rang;, and its squared mean &amp;amp;lang;&#039;&#039;X&#039;&#039;&amp;amp;rang;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;. You may find that the data around the peak is very noisy &amp;amp;mdash; this is normal, and is a result of being in the critical region. As before, use the plot controls to save a SVG or PNG image of your plot and attach this to the report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the seventh section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/The effect of system size|6. The effect of system size]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Locating the Curie temperature|8. Locating the Curie temperature]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/The_effect_of_system_size&amp;diff=822102</id>
		<title>Programming a 2D Ising Model/The effect of system size</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/The_effect_of_system_size&amp;diff=822102"/>
		<updated>2026-05-03T13:53:53Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the sixth section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/The effect of temperature|5. The effect of temperature]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Determining the heat capacity|7. Determining the heat capacity]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 6. The effect of system size =&lt;br /&gt;
&lt;br /&gt;
==Scaling the System Size==&lt;br /&gt;
&lt;br /&gt;
Your plots from the previous section showed how the magnetisation and energy vary with temperature, and you should be able to see the onset of the phase transition. In this region, the energetic and entropic driving forces are of almost equal importance, and large fluctuations in the state of the system can take place. In fact, it is a characteristic of phase transitions that fluctuations within a system start to take place over very long ranges. This is a big problem in our simulation &amp;amp;mdash; so far, we only have 64 spins (or &amp;quot;atoms&amp;quot;, if you prefer), so our system may not be big enough for these long ranged fluctuations to be correctly modelled.&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 6&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Repeat the final task of the previous section for the following lattice sizes: 2&amp;amp;times;2, 4&amp;amp;times;4, 8&amp;amp;times;8, 16&amp;amp;times;16, 32&amp;amp;times;32. Make sure that you name each datafile that you produce after the corresponding lattice size! Write a Python script to make a plot showing the energy &#039;&#039;per spin&#039;&#039; versus temperature for each of your lattice sizes. Hint: the NumPy &amp;lt;code&amp;gt;loadtxt&amp;lt;/code&amp;gt; function is the reverse of the &amp;lt;code&amp;gt;savetxt&amp;lt;/code&amp;gt; function, and can be used to read your previously saved files into the script. Repeat this for the magnetisation. As before, use the plot controls to save your an SVG or PNG image of your plot and attach this to the report. How big a lattice do you think is big enough to capture the long range correlations?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the sixth section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/The effect of temperature|5. The effect of temperature]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Determining the heat capacity|7. Determining the heat capacity]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Accelerating_the_code&amp;diff=822101</id>
		<title>Programming a 2D Ising Model/Accelerating the code</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Accelerating_the_code&amp;diff=822101"/>
		<updated>2026-05-03T13:51:45Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* 4. Accelerating the code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the fourth section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/The effect of temperature|5. The effect of temperature]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 4. Accelerating the code =&lt;br /&gt;
So far, your energy() and magnetisation() functions probably use Python loops to go over every spin in your system (and a double loop for the energy). One of the drawbacks of Python&#039;s flexibility is a performance penalty &amp;amp;mdash; though developing code in Python tends to be &lt;br /&gt;
faster than other compiled programming languages, the resulting program is much, much slower.&lt;br /&gt;
&lt;br /&gt;
Fortunately, the NumPy module provides an interface to a number of functions written to give high performance. &lt;br /&gt;
These are written in the C programming language under the hood and take numpy arrays, which are contiguous arrays of a single data type, &lt;br /&gt;
unlike Python lists, which may contain mixes of data types.&lt;br /&gt;
&lt;br /&gt;
In this section, we are going to use these functions to improve the performance of our simulation.&lt;br /&gt;
&lt;br /&gt;
When trying to optimise the performance of something, you should always measure first, rather than making assumptions. Although there are some very obvious candidates in our program, you should always measure properly.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ILtimetrial.py&amp;lt;/code&amp;gt; script measures how fast it takes for 2000 iterations of your code to run.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ILProfiling.py&amp;lt;/code&amp;gt; script is the same, except uses the python standard library package [https://docs.python.org/3/library/profile.html cProfile] to sample what functions are being called and give you information&lt;br /&gt;
about the time spent in each. Analysing the output of the script, you will see that by far the majority of the time is spent in the energy method, followed by the magnetisation one. This makes sense, as each Monte-Carlo step can call the energy function multiple times.&lt;br /&gt;
&lt;br /&gt;
(If you want to profile your code in more detail, please seek advice from a demonstrator.)&lt;br /&gt;
&lt;br /&gt;
In order to improve the performance of this, we need to: &lt;br /&gt;
* Run the energy call fewer times per step.&lt;br /&gt;
* Improve the performance of the energy function.&lt;br /&gt;
&lt;br /&gt;
Fortunately, the NumPy module provides an interface to a number of functions written to give high performance. In this section, we are going to use these functions to improve the performance of our simulation.&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 4a&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Use the script ILtimetrial.py to record how long your &#039;&#039;current&#039;&#039; version of IsingLattice.py takes to perform 2000 Monte Carlo steps. This will vary, depending on what else the computer happens to be doing, so perform repeats and report the error in your average!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 4b&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Look at the documentation for the [http://docs.scipy.org/doc/numpy/reference/generated/numpy.sum.html NumPy &amp;lt;code&amp;gt;sum&amp;lt;/code&amp;gt; function]. You should be able to modify your &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt; function so that it uses this to evaluate M. The energy is a little trickier. Familiarise yourself with the NumPy [http://docs.scipy.org/doc/numpy/reference/generated/numpy.roll.html &amp;lt;code&amp;gt;roll&amp;lt;/code&amp;gt;] and [http://docs.scipy.org/doc/numpy/reference/generated/numpy.multiply.html &amp;lt;code&amp;gt;multiply&amp;lt;/code&amp;gt;] functions, and use these to replace your energy double loop (you will need to call roll and multiply twice!). Add your faster code to the report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 4c&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Use the script ILtimetrial.py to record how long your &#039;&#039;new&#039;&#039; version of IsingLattice.py takes to perform 2000 Monte Carlo steps. This will vary, depending on what else the computer happens to be doing, so perform repeats and report the error in your average! What makes this new version faster?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 4d:&amp;lt;/big&amp;gt;&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Making the code even faster &amp;lt;/big&amp;gt;: Consider trying to make the Monte Carlo step function substantially faster by calculating the difference in energy directly, in a way that avoids looping over the whole lattice. Think back how you answered some of the introduction questions. You can make it so the energy and magnetisation only needs to be calculated explicitly at the beginning of the simulation.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the fourth section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/The effect of temperature|5. The effect of temperature]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_Monte_Carlo_simulation&amp;diff=822100</id>
		<title>Programming a 2D Ising Model/Introduction to Monte Carlo simulation</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_Monte_Carlo_simulation&amp;diff=822100"/>
		<updated>2026-05-03T13:51:06Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* 3. Introduction to Monte Carlo simulation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the third section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Accelerating the code|4. Accelerating the code]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 3. Introduction to Monte Carlo simulation =&lt;br /&gt;
&lt;br /&gt;
==Average Energy and Magnetisation==&lt;br /&gt;
&lt;br /&gt;
Consider again the expressions for the average energy and magnetisation that we gave in the introduction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle M\right\rangle_T = \frac{1}{Z}\sum_\alpha M\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle E\right\rangle_T = \frac{1}{Z}\sum_\alpha E\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Imagine we want to evaluate these at a particular temperature, in a system of 100 spins.&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3a&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;How many configurations are available to a system with 100 spins? To evaluate these expressions, we have to calculate the energy and magnetisation for each of these configurations, then perform the sum. Let&#039;s be very, very, generous, and say that we can analyse 1&amp;amp;times;10&amp;lt;sup&amp;gt;9&amp;lt;/sup&amp;gt; configurations per second with our computer. How long will it take to evaluate a single value of &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;amp;rang;&amp;lt;sub&amp;gt;&#039;&#039;T&#039;&#039;&amp;lt;/sub&amp;gt;?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Clearly, we need to try a cleverer approach.&lt;br /&gt;
&lt;br /&gt;
For the overwhelming majority of the possible configurations, the Boltzmann factor, &amp;lt;math&amp;gt;\exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\}&amp;lt;/math&amp;gt;, will be very small, and that state will contribute very little to the average value. We can save an enormous amount of time, and make this problem tractable, if we only consider the states whose Boltzmann factor is not so vanishingly small. This technique is called &#039;&#039;importance sampling&#039;&#039; &amp;amp;mdash; instead of sampling every point in phase space, we sample only those that the system is likely to occupy.&lt;br /&gt;
&lt;br /&gt;
==Importance Sampling==&lt;br /&gt;
&lt;br /&gt;
This is easily stated, of course, but how can we know which states contribute a lot to the average without actually calculating the energy? So far, we have been imagining generating random states of the system; that is to say, we have been choosing &#039;&#039;&amp;amp;alpha;&#039;&#039; from a uniform distribution in which no arrangement of spins is any more likely to be chosen than any other. If we instead had a method which generated states randomly from the probability distribution &amp;lt;math&amp;gt;\exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\}&amp;lt;/math&amp;gt;, then our problem would be solved. The method which allows us to do this was developed in the 1950s, and is called the [https://doi.org/10.1063/1.1699114 Metropolis Monte Carlo (MMC)] method, or more often simply &amp;quot;Monte Carlo simulation&amp;quot;. This was one of the major breakthroughs of the early days of computational science, and in the year 2000, the IEEE named among the [https://doi.org/10.1109/MCISE.2000.814652 &amp;quot;Top 10 Algorithms of the 20th Century&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
The algorithm is as follows:&lt;br /&gt;
&lt;br /&gt;
# Start from a given configuration of spins, &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039;, with energy &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
# Choose a single spin &#039;&#039;&#039;at random&#039;&#039;&#039;, and &amp;quot;flip&amp;quot; it, to generate a new configuration &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
# Calculate the energy of this new configuration, &#039;&#039;E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
# Calculate the energy difference between the states, &#039;&#039;&amp;amp;Delta;E = E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; - E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
## If the &#039;&#039;&amp;amp;Delta;E &amp;amp;le; 0&#039;&#039; (the spin flipping decreased the energy), then we &#039;&#039;&#039;accept&#039;&#039;&#039; the new configuration.&lt;br /&gt;
##* We set &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = &amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and then &#039;&#039;&#039;go to step 5&#039;&#039;&#039;.&lt;br /&gt;
## If &#039;&#039;&amp;amp;Delta;E &amp;amp;gt; 0&#039;&#039;, the spin flipping increased the energy. By considering the probability of observing the starting and final states, &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039; and &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, it can be shown that the probability for the transition between the two to occur is &amp;lt;math&amp;gt;\exp \left\{-\frac{\Delta E}{k_BT}\right\}&amp;lt;/math&amp;gt;. To ensure that we only accept this kind of spin flip with the correct probability, we use the following procedure:&lt;br /&gt;
### Choose a random number, &#039;&#039;R&#039;&#039;, in the interval [0,1).&lt;br /&gt;
### If &amp;lt;math&amp;gt;R \leq \exp \left\{-\frac{\Delta E}{k_BT}\right\}&amp;lt;/math&amp;gt;, we &#039;&#039;&#039;accept&#039;&#039;&#039; the new configuration.&lt;br /&gt;
###* We set &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = &amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and then &#039;&#039;&#039;go to step 5&#039;&#039;&#039;.&lt;br /&gt;
### If &amp;lt;math&amp;gt;R &amp;gt; \exp \left\{-\frac{\Delta E}{k_BT}\right\}&amp;lt;/math&amp;gt;, we &#039;&#039;&#039;reject&#039;&#039;&#039; the new configuration.&lt;br /&gt;
###* &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039; and &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039; are left unchanged. &#039;&#039;&#039;Go to step 5&#039;&#039;&#039;.&lt;br /&gt;
# Update the running averages of the energy and magnetisation.&lt;br /&gt;
# Monte Carlo &amp;quot;step&amp;quot; complete, &#039;&#039;&#039;return to step 2&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Step 4 is the key to the method. By accepting moves which increase the energy only with a certain probability, we ensure that the sequence of states that we generate is correctly distributed.  A transition which carries a very large energy penalty, &#039;&#039;&amp;amp;Delta;E&#039;&#039; is extremely unlikely to be selected. The use of random numbers in this step is the reason that the method acquired the name &amp;quot;Monte Carlo&amp;quot;, after the casinos located there!&lt;br /&gt;
&lt;br /&gt;
Note, unlike molecular dynamics, each step only moves a single atom. In Monte Carlo simulation, there is the notion of a cycle which is &#039;&#039;N&#039;&#039;&amp;lt;sub&amp;gt;spins&amp;lt;/sub&amp;gt;-steps, so that each spin on average has an attempted flip per cycle.&lt;br /&gt;
&lt;br /&gt;
If you are interested in the mathematical details of why this procedure generates a sequence of states distributed in the correct way, consult the Monte Carlo chapter of [https://library-search.imperial.ac.uk/permalink/f/o1297h/TN_cdi_askewsholts_vlebooks_9780080519982 &amp;quot;Understanding Molecular Simulation&amp;quot;], by Frenkel and Smit, but a discussion of this is not required for the experiment. Chapter 7 of [https://library-search.imperial.ac.uk/permalink/44IMP_INST/mek6kh/alma997227534401591 &amp;quot;Statistical Mechanics: Theory and Molecular Simulation&amp;quot;] by Tuckerman also gives a good description.&lt;br /&gt;
&lt;br /&gt;
==Modifying IsingLattice.py==&lt;br /&gt;
&lt;br /&gt;
Our IsingLattice object contains a stub function, &#039;&#039;&#039;&amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt;&#039;&#039;&#039;, which takes a single argument &amp;amp;mdash; the temperature at which we want to do the cycle. There are also attributes used to calculate the average energy and magnetisation and respective variances: &amp;lt;code&amp;gt;self.E_tally&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;self.E2_tally&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;self.M_tally&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;self.M2_tally&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;self.n_steps&amp;lt;/code&amp;gt;. You should use these values to keep a running sum of all the energies, squared energies, magnetisations, and squared magnetisations that your system has sampled, as well as the number of steps that have been performed. Finally, there is also a function &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt;, that takes no arguments and should return the average energy, squared energy, magnetisation, squared magnetisation and current step, &#039;&#039;&#039;in that order&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3b&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Implement a single step of the above algorithm in the &amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt; function. This function should return the energy of your lattice and the magnetisation at the end of the cycle. Complete the &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt; function. This should return the following quantities whenever it is called: &amp;amp;lang;&#039;&#039;E&#039;&#039;&amp;amp;rang;, &amp;amp;lang;&#039;&#039;E&#039;&#039;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;amp;rang;, &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;amp;rang;, &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;amp;rang;, and &#039;&#039;N&#039;&#039;&amp;lt;sub&amp;gt;steps&amp;lt;/sub&amp;gt;, the number of Monte Carlo steps that have elapsed. Put your code for these functions in the report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note on units:&#039;&#039; In our simulation we will be using an unitless scaled energy &amp;lt;math&amp;gt;\tilde{E}=\frac{E}{J}&amp;lt;/math&amp;gt;, and a unitless scaled temperature &amp;lt;math&amp;gt;\tilde{T}=\frac{k_B T}{J}&amp;lt;/math&amp;gt;, where &#039;&#039;J&#039;&#039; is the interaction energy between spins discussed previously. The use of these scaled quantities in practice means that in the code we can set &#039;&#039;k&amp;lt;sub&amp;gt;B&amp;lt;/sub&amp;gt;&#039;&#039; to numerically equal to 1. Going forward we will drop the &amp;amp;tilde; from the notation of energy and temperature.&lt;br /&gt;
&lt;br /&gt;
You have been provided with a script, &#039;&#039;&#039;ILanim.py&#039;&#039;&#039;, which will use your &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; object to run a Monte Carlo simulation and display the output on the screen in real time. By default, this simulation will run an 8&amp;amp;times;8 lattice at &#039;&#039;T&#039;&#039;=1.0, which is below the critical temperature. You will see a representation of the lattice, and graphs of the energy and magnetisation &#039;&#039;&#039;per spin&#039;&#039;&#039;. When you close the window, the script will use your &#039;&#039;&#039;&amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt;&#039;&#039;&#039; function to print the average energy and magnetisation from the simulation. Note, you should run this script from the command line.&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3c&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;If &#039;&#039;T&#039;&#039; &amp;amp;lt; &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;, do you expect a spontaneous magnetisation (i.e. do you expect &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;amp;rang; &amp;amp;ne; 0)? When the state of the simulation appears to stop changing (when you have reached an equilibrium state), use the controls to export the output to an SVG or PNG file and attach this to your report. You should also include the output from your statistics() function.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the third section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Accelerating the code|4. Accelerating the code]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Accelerating_the_code&amp;diff=822099</id>
		<title>Programming a 2D Ising Model/Accelerating the code</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Accelerating_the_code&amp;diff=822099"/>
		<updated>2026-05-03T13:50:27Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the fourth section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/The effect of temperature|5. The effect of temperature]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 4. Accelerating the code =&lt;br /&gt;
So far, your energy() and magnetisation() functions probably use Python loops to go over every spin in your system (and a double loop for the energy). One of the drawbacks of Python&#039;s flexibility is a performance penalty &amp;amp;mdash; though developing code in Python tends to be &lt;br /&gt;
faster than other compiled programming languages, the resulting program is much, much slower.&lt;br /&gt;
&lt;br /&gt;
Fortunately, the NumPy module provides an interface to a number of functions written to give high performance. &lt;br /&gt;
These are written in the C programming language under the hood and take numpy arrays, which are contiguous arrays of a single data type, &lt;br /&gt;
unlike Python lists, which may contain mixes of data types.&lt;br /&gt;
&lt;br /&gt;
In this section, we are going to use these functions to improve the performance of our simulation.&lt;br /&gt;
&lt;br /&gt;
When trying to optimise the performance of something, you should always measure first, rather than making assumptions. Although there are some very obvious candidates in our program, you should always measure properly.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ILtimetrial.py&amp;lt;/code&amp;gt; script measures how fast it takes for 2000 iterations of your code to run.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ILProfiling.py&amp;lt;/code&amp;gt; script is the same, except uses the python standard library package [https://docs.python.org/3/library/profile.html cProfile] to sample what functions are being called and give you information&lt;br /&gt;
about the time spent in each. Analysing the output of the script, you will see that by far the majority of the time is spent in the energy method, followed by the magnetisation one. This makes sense, as each Monte-Carlo step can call the energy function multiple times.&lt;br /&gt;
&lt;br /&gt;
(If you want to profile your code in more detail, please seek advice from a demonstrator.)&lt;br /&gt;
&lt;br /&gt;
In order to improve the performance of this, we need to: &lt;br /&gt;
* Run the energy call fewer times per step.&lt;br /&gt;
* Improve the performance of the energy function.&lt;br /&gt;
&lt;br /&gt;
Fortunately, the NumPy module provides an interface to a number of functions written to give high performance. In this section, we are going to use these functions to improve the performance of our simulation.&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 4a&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Use the script ILtimetrial.py to record how long your &#039;&#039;current&#039;&#039; version of IsingLattice.py takes to perform 2000 Monte Carlo steps. This will vary, depending on what else the computer happens to be doing, so perform repeats and report the error in your average!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 4b&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Look at the documentation for the [http://docs.scipy.org/doc/numpy/reference/generated/numpy.sum.html NumPy &amp;lt;code&amp;gt;sum&amp;lt;/code&amp;gt; function]. You should be able to modify your &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt; function so that it uses this to evaluate M. The energy is a little trickier. Familiarise yourself with the NumPy [http://docs.scipy.org/doc/numpy/reference/generated/numpy.roll.html &amp;lt;code&amp;gt;roll&amp;lt;/code&amp;gt;] and [http://docs.scipy.org/doc/numpy/reference/generated/numpy.multiply.html &amp;lt;code&amp;gt;multiply&amp;lt;/code&amp;gt;] functions, and use these to replace your energy double loop (you will need to call roll and multiply twice!). Add your faster code to the report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 4c&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Use the script ILtimetrial.py to record how long your &#039;&#039;new&#039;&#039; version of IsingLattice.py takes to perform 2000 Monte Carlo steps. This will vary, depending on what else the computer happens to be doing, so perform repeats and report the error in your average! What makes this new version faster?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;Task 4d:&amp;lt;/big&amp;gt;&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Making the code even faster &amp;lt;/big&amp;gt;: Consider trying to make the Monte Carlo step function substantially faster by calculating the difference in energy directly, in a way that avoids looping over the whole lattice. Think back how you answered some of the introduction questions. You can make it so the energy and magnetisation only needs to be calculated explicitly at the beginning of the simulation.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the fourth section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/The effect of temperature|5. The effect of temperature]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/The_effect_of_temperature&amp;diff=822098</id>
		<title>Programming a 2D Ising Model/The effect of temperature</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/The_effect_of_temperature&amp;diff=822098"/>
		<updated>2026-05-03T13:49:53Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the fifth section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Accelerating the code|4. Accelerating the code]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/The effect of system size|6. The effect of system size]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 5. The effect of temperature =&lt;br /&gt;
We now have enough code to start to investigate the phase behaviour of our model. In the first instance, we are going to make plots of the average energy and magnetisation of the system as a function of temperature, to get an idea of where the change between energetic and entropic domination takes place, but we first have to make a small change to the code that averages the energy and magnetisation.&lt;br /&gt;
&lt;br /&gt;
==Correcting the Averaging Code==&lt;br /&gt;
As you saw in the previous part of the experiment, when we begin from a random configuration, it takes a few Monte Carlo cycles to reach the equilibrium state of the system at a particular temperature. This manifests itself as a relatively sharp drop in the energy of the system in the first few hundred or thousand steps, before the energy starts to fluctuate around a constant value. If we want our average properties to be correct, we should only average in the region where the &#039;&#039;average&#039;&#039; energy and magnetisation are constant.&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 5a&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;The script ILfinalframe.py runs for a given number of cycles at a given temperature, then plots a depiction of the &#039;&#039;final&#039;&#039; lattice state as well as graphs of the energy and magnetisation as a function of cycle number. This is much quicker than animating every frame! Experiment with a few different temperatures and lattice sizes. Approximately how many cycles (remember, a cycle is &#039;&#039;N&#039;&#039;&amp;lt;sub&amp;gt;spins&amp;lt;/sub&amp;gt; steps) are needed for the system to go from its random starting position to the equilibrium state? Modify your &amp;lt;code&amp;gt;__init__()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;montecarlostep()&amp;lt;/code&amp;gt; methods so that the first &#039;&#039;N&#039;&#039; cycles of the simulation are ignored when calculating the averages. Be careful of off-by-one errors. You should state in your report what period you chose to ignore, and include graphs from ILfinalframe.py to illustrate your motivation in choosing this number.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Running over a range of temperatures==&lt;br /&gt;
&lt;br /&gt;
The script ILtemperaturerange.py performs simulations of a given length over a range of temperatures. The temperature range is determined by the parameters given to the &amp;lt;code&amp;gt;np.arange&amp;lt;/code&amp;gt; function near the top of the file. Starting from a uniformly aligned lattice, a simulation of length &amp;lt;code&amp;gt;n_steps&amp;lt;/code&amp;gt; will be performed at temperature &amp;lt;code&amp;gt;T_cold&amp;lt;/code&amp;gt;, and the average energy and magnetisation will be recorded. A new simulation of length &amp;lt;code&amp;gt;n_steps&amp;lt;/code&amp;gt; will then be performed at temperature &amp;lt;code&amp;gt;T_cold + dT&amp;lt;/code&amp;gt;, and so on until all temperatures in the range have been simulated. This results in a NumPy array of five columns: the temperature, then the four statistical quantities: &amp;lt;code&amp;gt;ave_energies&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ave_sqenergies&amp;lt;/code&amp;gt; (squared energies), &amp;lt;code&amp;gt;ave_magnetisations&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ave_sqmagnetisations&amp;lt;/code&amp;gt; (squared magnetisations).&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 5b&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Use ILtemperaturerange.py to plot the average energy and magnetisation for each temperature, &#039;&#039;with error bars&#039;&#039;, for an 8 &amp;amp;times; 8 lattice. Use multiple repeats to calculate these error bars. Use your intuition and results from the script ILfinalframe.py to estimate how many cycles each simulation should be. The temperature range 0.25 to 5.0 is sufficient. Use as many temperature points as you feel necessary to illustrate the behaviour, but do not use a temperature spacing larger than 0.5. The NumPy function &amp;lt;code&amp;gt;savetxt()&amp;lt;/code&amp;gt; stores your array of output data on disk &amp;amp;mdash; you will need it later. Save the file as &#039;&#039;8x8.dat&#039;&#039; so that you know which lattice size it came from.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the fifth section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page:&amp;lt;/span&amp;gt; [[Programming a 2D Ising Model]]&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Accelerating the code|4. Accelerating the code]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/The effect of system size|6. The effect of system size]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822097</id>
		<title>Programming a 2D Ising Model/Calculating the energy and magnetisation</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822097"/>
		<updated>2026-05-03T13:48:51Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* 2. Calculating the energy and magnetisation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Introduction to the Ising model|1. Introduction to the Ising model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 2. Calculating the energy and magnetisation =&lt;br /&gt;
&lt;br /&gt;
==Getting the files for the experiment==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Various scripts have been prepared to assist you with this experiment, and you can obtain them by downloading the files from the Blackboard.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We recommend you open the extracted folder with JupyterLab, which has an integrated terminal where you can run the  simulation scripts.&lt;br /&gt;
&lt;br /&gt;
==Modifying the files==&lt;br /&gt;
&lt;br /&gt;
The file &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; contains a Python class called IsingLattice. This class will be the basis for our model of the system, and is restricted to modelling the two dimensional case. It contains a number of stub methods that you will complete as you work through the experiment.&lt;br /&gt;
&lt;br /&gt;
== A note about Python Classes ==&lt;br /&gt;
The file IsingLattice.py makes use of a Python feature called &#039;&#039;class&#039;&#039;. You should be familiar with the idea that all Python &#039;&#039;objects&#039;&#039; have an associated &#039;&#039;type&#039;&#039; -- you have already encountered objects such as integers, string, lists, and NumPy arrays. Classes allow us to define new types of object. In this case, we define a type called &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
class IsingLattice:&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each class is allowed to have certain attributes and functions (known as methods) associated with it. We can see, for example, that each &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; object has the methods &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt; (the method &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt; will be explained shortly). Each of these methods takes a special first argument called self, which is a variable pointing to the current copy of IsingLattice. To use the new IsingLattice object that we have defined, we use code like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import IsingLattice&lt;br /&gt;
&lt;br /&gt;
il = IsingLattice(5, 5) #create an IsingLattice object with 5 row and 5 columns&lt;br /&gt;
&lt;br /&gt;
energy = il.energy() #call the energy() method of our IsingLattice object&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all attributes and methods belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the &amp;lt;code&amp;gt;montecarlostep()&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the method &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; which is part of the &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;lt;code&amp;gt;self.&amp;lt;/code&amp;gt; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def magnetisation(self):&lt;br /&gt;
    # we have to use self.lattice, because the lattice variable is part of the object, not local to this function&lt;br /&gt;
    for i in self.lattice:&lt;br /&gt;
        ...&lt;br /&gt;
        # we use i, not self.i&lt;br /&gt;
        # we don&#039;t need to access i outside this function &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Have a look at the other files that you have been given to see how this IsingLattice object is used.&lt;br /&gt;
&lt;br /&gt;
== The Constructor ==&lt;br /&gt;
The only method currently filled in is &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt;. This is a special method called a &#039;&#039;constructor&#039;&#039;. Whenever a new IsingLattice object is created, using code like &amp;lt;code&amp;gt;il = IsingLattice(5,5)&amp;lt;/code&amp;gt;, this method is called automatically. It takes two arguments (excluding &amp;quot;self&amp;quot;), which are simply the number of rows and columns that our lattice will have. The attribute &amp;lt;code&amp;gt;self.lattice&amp;lt;/code&amp;gt; is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;code&amp;gt;np.random.choice&amp;lt;/code&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for the function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html numpy.random.choice].&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Complete the functions &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, which should return the energy of the lattice and the total magnetisation, respectively. In the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; function you may assume that &#039;&#039;J&#039;&#039;=1.0 at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which all energies are a multiple of &#039;&#039;J&#039;&#039;, but there will be more information about this in later sections). Do not worry about the efficiency of the code at the moment &amp;amp;mdash; we will address the speed in a later part of the experiment. Paste your code in your report and describe how it works.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Testing the files==&lt;br /&gt;
&lt;br /&gt;
When you have completed the energy() and magnetisation() methods, we need to test that they work correctly.&lt;br /&gt;
We have provided you with a script, &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;, which will create three IsingLattice objects and check their energies and magnetisations, displaying these on a graph. One configuration corresponds to the energy minimum, one to the energy maximum, and one to an intermediate state.&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2b&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Run the ILcheck.py script from the a terminal using the command&#039;&#039;&#039;&amp;lt;pre&amp;gt;python ILcheck.py&amp;lt;/pre&amp;gt;&#039;&#039;&#039;The displayed window has a series of control buttons in the bottom left, one of which will allow you to export the figure as a SVG or PNG image. Save an image of the ILcheck.py output, and include it in your report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are also some unit tests available in the &amp;lt;code&amp;gt;test_energy.py&amp;lt;/code&amp;gt; file. These tests are designed to be run by simply running the [https://docs.pytest.org pytest] command in your terminal,&lt;br /&gt;
&amp;lt;pre&amp;gt;pytest&amp;lt;/pre&amp;gt;&lt;br /&gt;
You should make sure your code passes the tests for the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt; methods at this time. The file contains tests for methods that will only be implemented later on, so some failures are expected for now.&lt;br /&gt;
These sorts of test are useful because they are easier to write and faster to run and can be made to run automatically.&lt;br /&gt;
&lt;br /&gt;
You can also debug and test your program on a Jupyter notebook or IPython console by importing your IsingLattice class, creating one object, and inspecting its properties. If you do this, we recommend that you start your session running the commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%load_ext autoreload&lt;br /&gt;
%autoreload 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will ensure that when you try executing your code, you always run the most recent version (please note this isn&#039;t fool proof and if you find problems you may need to restart the kernel)!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page:&amp;lt;/span&amp;gt; [[Programming a 2D Ising Model]]&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section:  [[Programming a 2D Ising Model/Introduction to the Ising model|1. Introduction to the Ising model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822096</id>
		<title>Programming a 2D Ising Model/Calculating the energy and magnetisation</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822096"/>
		<updated>2026-05-03T13:46:06Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* 2. Calculating the energy and magnetisation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Introduction to the Ising model|1. Introduction to the Ising model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 2. Calculating the energy and magnetisation =&lt;br /&gt;
&lt;br /&gt;
==Getting the files for the experiment==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Various scripts have been prepared to assist you with this experiment, and you can obtain them by downloading the files from the Blackboard.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We recommend you open the extracted folder with JupyterLab, which has an integrated terminal where you can run the  simulation scripts.&lt;br /&gt;
&lt;br /&gt;
==Modifying the files==&lt;br /&gt;
&lt;br /&gt;
The file &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; contains a Python class called IsingLattice. This class will be the basis for our model of the system, and is restricted to modelling the two dimensional case. It contains a number of stub methods that you will complete as you work through the experiment.&lt;br /&gt;
&lt;br /&gt;
===A note about Python Classes===&lt;br /&gt;
&lt;br /&gt;
The file IsingLattice.py makes use of a Python feature called &#039;&#039;class&#039;&#039;. You should be familiar with the idea that all Python &#039;&#039;objects&#039;&#039; have an associated &#039;&#039;type&#039;&#039; -- you have already encountered objects such as integers, string, lists, and NumPy arrays. Classes allow us to define new types of object. In this case, we define a type called &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
class IsingLattice:&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each class is allowed to have certain attributes and functions (known as methods) associated with it. We can see, for example, that each &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; object has the methods &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt; (the method &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt; will be explained shortly). Each of these methods takes a special first argument called self, which is a variable pointing to the current copy of IsingLattice. To use the new IsingLattice object that we have defined, we use code like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import IsingLattice&lt;br /&gt;
&lt;br /&gt;
il = IsingLattice(5, 5) #create an IsingLattice object with 5 row and 5 columns&lt;br /&gt;
&lt;br /&gt;
energy = il.energy() #call the energy() method of our IsingLattice object&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all attributes and methods belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the &amp;lt;code&amp;gt;montecarlostep()&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the method &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; which is part of the &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;lt;code&amp;gt;self.&amp;lt;/code&amp;gt; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def magnetisation(self):&lt;br /&gt;
    # we have to use self.lattice, because the lattice variable is part of the object, not local to this function&lt;br /&gt;
    for i in self.lattice:&lt;br /&gt;
        ...&lt;br /&gt;
        # we use i, not self.i&lt;br /&gt;
        # we don&#039;t need to access i outside this function &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Have a look at the other files that you have been given to see how this IsingLattice object is used.&lt;br /&gt;
&lt;br /&gt;
== The Constructor ==&lt;br /&gt;
The only method currently filled in is &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt;. This is a special method called a &#039;&#039;constructor&#039;&#039;. Whenever a new IsingLattice object is created, using code like &amp;lt;code&amp;gt;il = IsingLattice(5,5)&amp;lt;/code&amp;gt;, this method is called automatically. It takes two arguments (excluding &amp;quot;self&amp;quot;), which are simply the number of rows and columns that our lattice will have. The attribute &amp;lt;code&amp;gt;self.lattice&amp;lt;/code&amp;gt; is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;code&amp;gt;np.random.choice&amp;lt;/code&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for the function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html numpy.random.choice].&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Complete the functions &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, which should return the energy of the lattice and the total magnetisation, respectively. In the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; function you may assume that &#039;&#039;J&#039;&#039;=1.0 at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which all energies are a multiple of &#039;&#039;J&#039;&#039;, but there will be more information about this in later sections). Do not worry about the efficiency of the code at the moment &amp;amp;mdash; we will address the speed in a later part of the experiment. Paste your code in your report and describe how it works.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Testing the files==&lt;br /&gt;
&lt;br /&gt;
When you have completed the energy() and magnetisation() methods, we need to test that they work correctly.&lt;br /&gt;
We have provided you with a script, &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;, which will create three IsingLattice objects and check their energies and magnetisations, displaying these on a graph. One configuration corresponds to the energy minimum, one to the energy maximum, and one to an intermediate state.&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2b&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Run the ILcheck.py script from the a terminal using the command&#039;&#039;&#039;&amp;lt;pre&amp;gt;python ILcheck.py&amp;lt;/pre&amp;gt;&#039;&#039;&#039;The displayed window has a series of control buttons in the bottom left, one of which will allow you to export the figure as a SVG or PNG image. Save an image of the ILcheck.py output, and include it in your report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are also some unit tests available in the &amp;lt;code&amp;gt;test_energy.py&amp;lt;/code&amp;gt; file. These tests are designed to be run by simply running the [https://docs.pytest.org pytest] command in your terminal,&lt;br /&gt;
&amp;lt;pre&amp;gt;pytest&amp;lt;/pre&amp;gt;&lt;br /&gt;
You should make sure your code passes the tests for the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt; methods at this time. The file contains tests for methods that will only be implemented later on, so some failures are expected for now.&lt;br /&gt;
These sorts of test are useful because they are easier to write and faster to run and can be made to run automatically.&lt;br /&gt;
&lt;br /&gt;
You can also debug and test your program on a Jupyter notebook or IPython console by importing your IsingLattice class, creating one object, and inspecting its properties. If you do this, we recommend that you start your session running the commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%load_ext autoreload&lt;br /&gt;
%autoreload 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will ensure that when you try executing your code, you always run the most recent version (please note this isn&#039;t fool proof and if you find problems you may need to restart the kernel)!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page:&amp;lt;/span&amp;gt; [[Programming a 2D Ising Model]]&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section:  [[Programming a 2D Ising Model/Introduction to the Ising model|1. Introduction to the Ising model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822095</id>
		<title>Programming a 2D Ising Model/Calculating the energy and magnetisation</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822095"/>
		<updated>2026-05-03T13:44:56Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* Modifying the files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Introduction to the Ising model|1. Introduction to the Ising model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 2. Calculating the energy and magnetisation =&lt;br /&gt;
&lt;br /&gt;
==Getting the files for the experiment==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Various scripts have been prepared to assist you with this experiment, and you can obtain them by downloading the files from the Blackboard.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We recommend you open the extracted folder with JupyterLab, which has an integrated terminal where you can run the  simulation scripts.&lt;br /&gt;
&lt;br /&gt;
==Modifying the files==&lt;br /&gt;
&lt;br /&gt;
The file &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; contains a Python class called IsingLattice. This class will be the basis for our model of the system, and is restricted to modelling the two dimensional case. It contains a number of stub methods that you will complete as you work through the experiment.&lt;br /&gt;
&lt;br /&gt;
===A note about Python Classes===&lt;br /&gt;
&lt;br /&gt;
The file IsingLattice.py makes use of a Python feature called &#039;&#039;class&#039;&#039;. You should be familiar with the idea that all Python &#039;&#039;objects&#039;&#039; have an associated &#039;&#039;type&#039;&#039; -- you have already encountered objects such as integers, string, lists, and NumPy arrays. Classes allow us to define new types of object. In this case, we define a type called &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
class IsingLattice:&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each class is allowed to have certain attributes and functions (known as methods) associated with it. We can see, for example, that each &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; object has the methods &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt; (the method &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt; will be explained shortly). Each of these methods takes a special first argument called self, which is a variable pointing to the current copy of IsingLattice. To use the new IsingLattice object that we have defined, we use code like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import IsingLattice&lt;br /&gt;
&lt;br /&gt;
il = IsingLattice(5, 5) #create an IsingLattice object with 5 row and 5 columns&lt;br /&gt;
&lt;br /&gt;
energy = il.energy() #call the energy() method of our IsingLattice object&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all attributes and methods belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the &amp;lt;code&amp;gt;montecarlostep()&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the method &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; which is part of the &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;lt;code&amp;gt;self.&amp;lt;/code&amp;gt; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def magnetisation(self):&lt;br /&gt;
    # we have to use self.lattice, because the lattice variable is part of the object, not local to this function&lt;br /&gt;
    for i in self.lattice:&lt;br /&gt;
        ...&lt;br /&gt;
        # we use i, not self.i&lt;br /&gt;
        # we don&#039;t need to access i outside this function &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Have a look at the other files that you have been given to see how this IsingLattice object is used.&lt;br /&gt;
&lt;br /&gt;
===The Constructor===&lt;br /&gt;
&lt;br /&gt;
The only method currently filled in is &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt;. This is a special method called a &#039;&#039;constructor&#039;&#039;. Whenever a new IsingLattice object is created, using code like &amp;lt;code&amp;gt;il = IsingLattice(5,5)&amp;lt;/code&amp;gt;, this method is called automatically. It takes two arguments (excluding &amp;quot;self&amp;quot;), which are simply the number of rows and columns that our lattice will have. The attribute &amp;lt;code&amp;gt;self.lattice&amp;lt;/code&amp;gt; is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;code&amp;gt;np.random.choice&amp;lt;/code&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for the function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html numpy.random.choice].&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Complete the functions &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, which should return the energy of the lattice and the total magnetisation, respectively. In the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; function you may assume that &#039;&#039;J&#039;&#039;=1.0 at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which all energies are a multiple of &#039;&#039;J&#039;&#039;, but there will be more information about this in later sections). Do not worry about the efficiency of the code at the moment &amp;amp;mdash; we will address the speed in a later part of the experiment. Paste your code in your report and describe how it works.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Testing the files==&lt;br /&gt;
&lt;br /&gt;
When you have completed the energy() and magnetisation() methods, we need to test that they work correctly.&lt;br /&gt;
We have provided you with a script, &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;, which will create three IsingLattice objects and check their energies and magnetisations, displaying these on a graph. One configuration corresponds to the energy minimum, one to the energy maximum, and one to an intermediate state.&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2b&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Run the ILcheck.py script from the a terminal using the command&#039;&#039;&#039;&amp;lt;pre&amp;gt;python ILcheck.py&amp;lt;/pre&amp;gt;&#039;&#039;&#039;The displayed window has a series of control buttons in the bottom left, one of which will allow you to export the figure as a SVG or PNG image. Save an image of the ILcheck.py output, and include it in your report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are also some unit tests available in the &amp;lt;code&amp;gt;test_energy.py&amp;lt;/code&amp;gt; file. These tests are designed to be run by simply running the [https://docs.pytest.org pytest] command in your terminal,&lt;br /&gt;
&amp;lt;pre&amp;gt;pytest&amp;lt;/pre&amp;gt;&lt;br /&gt;
You should make sure your code passes the tests for the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt; methods at this time. The file contains tests for methods that will only be implemented later on, so some failures are expected for now.&lt;br /&gt;
These sorts of test are useful because they are easier to write and faster to run and can be made to run automatically.&lt;br /&gt;
&lt;br /&gt;
You can also debug and test your program on a Jupyter notebook or IPython console by importing your IsingLattice class, creating one object, and inspecting its properties. If you do this, we recommend that you start your session running the commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%load_ext autoreload&lt;br /&gt;
%autoreload 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will ensure that when you try executing your code, you always run the most recent version (please note this isn&#039;t fool proof and if you find problems you may need to restart the kernel)!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page:&amp;lt;/span&amp;gt; [[Programming a 2D Ising Model]]&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section:  [[Programming a 2D Ising Model/Introduction to the Ising model|1. Introduction to the Ising model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822094</id>
		<title>Programming a 2D Ising Model/Introduction to the Ising model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822094"/>
		<updated>2026-05-03T13:43:54Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* The Ising model */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 1. Introduction to the Ising model =&lt;br /&gt;
&lt;br /&gt;
== The Ising model ==&lt;br /&gt;
The Ising model is a simple physical model proposed in the 1920s to understand the behaviour of ferromagnets. In most materials, the magnetic dipoles of the atoms have no preferred orientation, and the bulk material has no net magnetic moment. In certain materials, however, there is preferential alignment of the magnetic dipoles along certain directions. These materials, such as iron, exhibit an overall magnetic moment, and are called ferromagnetic.&lt;br /&gt;
&lt;br /&gt;
The phenomenon is based on competition between two physical effects &amp;amp;mdash; energy minimisation and entropy maximisation. On the one hand, parallel alignment of magnetic moments is energetically favourable. On the other hand, aligning the system in this way reduces the entropy.&lt;br /&gt;
&lt;br /&gt;
In the Ising model, we consider a collection of spins, &#039;&#039;s&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;&#039;&#039;, each of which can either have the value &amp;quot;up&amp;quot; (+1) or &amp;quot;down&amp;quot; (-1), arranged on a lattice. In one dimension, this takes the form of a &amp;quot;chain&amp;quot; of adjacent spins, &#039;&#039;s&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039; to &#039;&#039;s&amp;lt;sub&amp;gt;N&amp;lt;/sub&amp;gt;&#039;&#039;. In two dimensions we have a grid of cells, each of which contains one spin. In three dimensions, the system is a cuboid, and so on. The arrangements for 1, 2 and 3 dimensions are illustrated in &#039;&#039;&#039;figure 1&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingSketch.png|300px|thumb|right|&#039;&#039;&#039;Figure 1&#039;&#039;&#039;: Illustration of an Ising lattice in one (N=5), two (N=5&amp;amp;times;5), and three (N=5&amp;amp;times;5&amp;amp;times;5) dimensions. Red cells indicate the &amp;quot;up&amp;quot; spin&amp;quot;, and blue cells indicate the &amp;quot;down&amp;quot; spin.]]&lt;br /&gt;
&lt;br /&gt;
The rules of the model are simple:&lt;br /&gt;
&lt;br /&gt;
* When no magnetic field is applied, the only energetic contribution comes from the interaction between spins in &#039;&#039;adjacent&#039;&#039; lattice cells&lt;br /&gt;
* The total interaction energy is defined as &amp;lt;math&amp;gt;- \frac{1}{2} J \sum_i^N \sum_{j\  \in\  \mathrm{neighbours}\left(i\right)} s_i s_j&amp;lt;/math&amp;gt;, where &#039;&#039;J&#039;&#039; is a constant which controls the strength of interaction and the notation &#039;&#039;j&#039;&#039;&amp;amp;nbsp;&amp;amp;in;&amp;amp;nbsp;neighbours(&#039;&#039;i&#039;&#039;) indicates that spin &#039;&#039;j&#039;&#039; must lie in a lattice cell adjacent to spin &#039;&#039;i&#039;&#039;. The factor of one half is included to make sure that we do not count each spin-spin interaction twice.&lt;br /&gt;
* Periodic boundary conditions are applied. In other words, the &amp;quot;final&amp;quot; spin in a particular direction is considered to be adjacent to the &amp;quot;first&amp;quot; spin in that direction. In &#039;&#039;&#039;figure 2&#039;&#039;&#039;, for example, cell 1 has neighbour interactions with cells 2, 3, 4, and 7, while cell 9 interacts with cells 3, 6, 7, and 8.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingNumberedCell.png|300px|thumb|right|&#039;&#039;&#039;Figure 2&#039;&#039;&#039;: Illustration of a 2D Ising lattice, with numbered cells to indicate the neighbour interactions.]]&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1a&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Show that the lowest possible energy for the Ising model (with &#039;&#039;J&#039;&#039;&amp;amp;gt;0) is &#039;&#039;E&#039;&#039;&amp;amp;nbsp;=&amp;amp;nbsp;-&#039;&#039;DNJ&#039;&#039;, where &#039;&#039;D&#039;&#039; is the number of dimensions and &#039;&#039;N&#039;&#039; is the total number of spins. What is the multiplicity of this state? Calculate its entropy.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Phase Transitions==&lt;br /&gt;
&lt;br /&gt;
The Ising model is interesting because it is one of the simplest physical models to display a phase transition (so long as we are in two dimensions or more). The temperature of the system controls the balance between the energetic driving force, which wants the system to adopt the lowest energy configuration that you imagined in the previous section, and the entropic driving force, which seeks to maximise the number of configurations available to the system.&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1b&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Imagine that the system is in the lowest energy configuration. To move to a different state, one of the spins must spontaneously change direction (&amp;quot;flip&amp;quot;). What is the change in energy if this happens (&#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000)? How much entropy does the system gain by doing so?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
At low temperatures, little thermal energy is available to overcome such energy barriers, and we expect the system to adopt the lowest energy (the energetic driving force will dominate). Under these conditions, we expect a large number of parallel spins, and we can characterise this by considering the total &#039;&#039;magnetisation&#039;&#039; of the system: &amp;lt;math&amp;gt;M = \sum_i s_i&amp;lt;/math&amp;gt;. At higher temperatures, however, enough thermal energy will be available that spins can flip relatively freely. Under these conditions, the entropic driving force should dominate. The transition temperature between the two regimes is called the &#039;&#039;Curie temperature&#039;&#039;, &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;. Below &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;, we observe the highly ordered magnetised phase, while above &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039; a disordered, demagnetised, phase emerges.&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1c&amp;lt;/big&amp;gt;:&#039;&#039;&#039; ====&lt;br /&gt;
&#039;&#039;&#039;Calculate the magnetisation of the 1D and 2D lattices in figure 1. What magnetisation would you expect to observe for an Ising lattice with &#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000 at absolute zero?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We are interested, therefore, in determining the magnetisation &#039;&#039;M&#039;&#039;, and energy &#039;&#039;E&#039;&#039;, of the system as functions of temperature &#039;&#039;T&#039;&#039;. We can write statistical mechanical equations for these quantities:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle M\right\rangle_T = \frac{1}{Z}\sum_\alpha M\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle E\right\rangle_T = \frac{1}{Z}\sum_\alpha E\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &#039;&#039;&amp;amp;alpha;&#039;&#039; is used as a shorthand to represent all spins in the system, and &#039;&#039;Z&#039;&#039; is the partition function,&lt;br /&gt;
&amp;lt;math&amp;gt;Z = \sum_\alpha \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It was discovered relatively quickly after the model was first proposed that the partition function in the one dimensional case can be solved analytically (though doing so is beyond the scope of this experiment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Z\left(T, N\right) = \left[2\cosh\left(\frac{J}{k_BT}\right)\right]^N&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Much later, [http://en.wikipedia.org/wiki/Lars_Onsager Lars Onsager] established that the two dimensional partition function can also be found analytically, though the mathematics is significantly more involved and the resulting expression is correspondingly much more complicated. In dimensions greater than two, no analytical solution is known.&lt;br /&gt;
&lt;br /&gt;
Luckily for us, the problem can instead be tackled by numerical methods, and it is this that will be the focus of the experiment. We will discuss how the equations for &#039;&#039;M&#039;&#039; and &#039;&#039;E&#039;&#039; can be solved, but first we must set up a Python script to model the lattice.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page:  [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822093</id>
		<title>Programming a 2D Ising Model/Introduction to the Ising model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822093"/>
		<updated>2026-05-03T13:42:43Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* The Ising model */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 1. Introduction to the Ising model =&lt;br /&gt;
&lt;br /&gt;
== The Ising model ==&lt;br /&gt;
The Ising model is a simple physical model proposed in the 1920s to understand the behaviour of ferromagnets. In most materials, the magnetic dipoles of the atoms have no preferred orientation, and the bulk material has no net magnetic moment. In certain materials, however, there is preferential alignment of the magnetic dipoles along certain directions. These materials, such as iron, exhibit an overall magnetic moment, and are called ferromagnetic.&lt;br /&gt;
&lt;br /&gt;
The phenomenon is based on competition between two physical effects &amp;amp;mdash; energy minimisation and entropy maximisation. On the one hand, parallel alignment of magnetic moments is energetically favourable. On the other hand, aligning the system in this way reduces the entropy.&lt;br /&gt;
&lt;br /&gt;
In the Ising model, we consider a collection of spins, &#039;&#039;s&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;&#039;&#039;, each of which can either have the value &amp;quot;up&amp;quot; (+1) or &amp;quot;down&amp;quot; (-1), arranged on a lattice. In one dimension, this takes the form of a &amp;quot;chain&amp;quot; of adjacent spins, &#039;&#039;s&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039; to &#039;&#039;s&amp;lt;sub&amp;gt;N&amp;lt;/sub&amp;gt;&#039;&#039;. In two dimensions we have a grid of cells, each of which contains one spin. In three dimensions, the system is a cuboid, and so on. The arrangements for 1, 2 and 3 dimensions are illustrated in &#039;&#039;&#039;figure 1&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingSketch.png|300px|thumb|right|&#039;&#039;&#039;Figure 1&#039;&#039;&#039;: Illustration of an Ising lattice in one (N=5), two (N=5&amp;amp;times;5), and three (N=5&amp;amp;times;5&amp;amp;times;5) dimensions. Red cells indicate the &amp;quot;up&amp;quot; spin&amp;quot;, and blue cells indicate the &amp;quot;down&amp;quot; spin.]]&lt;br /&gt;
&lt;br /&gt;
The rules of the model are simple:&lt;br /&gt;
&lt;br /&gt;
* When no magnetic field is applied, the only energetic contribution comes from the interaction between spins in &#039;&#039;adjacent&#039;&#039; lattice cells&lt;br /&gt;
* The total interaction energy is defined as &amp;lt;math&amp;gt;- \frac{1}{2} J \sum_i^N \sum_{j\  \in\  \mathrm{neighbours}\left(i\right)} s_i s_j&amp;lt;/math&amp;gt;, where &#039;&#039;J&#039;&#039; is a constant which controls the strength of interaction and the notation &#039;&#039;j&#039;&#039;&amp;amp;nbsp;&amp;amp;in;&amp;amp;nbsp;neighbours(&#039;&#039;i&#039;&#039;) indicates that spin &#039;&#039;j&#039;&#039; must lie in a lattice cell adjacent to spin &#039;&#039;i&#039;&#039;. The factor of one half is included to make sure that we do not count each spin-spin interaction twice.&lt;br /&gt;
* Periodic boundary conditions are applied. In other words, the &amp;quot;final&amp;quot; spin in a particular direction is considered to be adjacent to the &amp;quot;first&amp;quot; spin in that direction. In &#039;&#039;&#039;figure 2&#039;&#039;&#039;, for example, cell 1 has neighbour interactions with cells 2, 3, 4, and 7, while cell 9 interacts with cells 3, 6, 7, and 8.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingNumberedCell.png|300px|thumb|right|&#039;&#039;&#039;Figure 2&#039;&#039;&#039;: Illustration of a 2D Ising lattice, with numbered cells to indicate the neighbour interactions.]]&lt;br /&gt;
&lt;br /&gt;
==== &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1a&amp;lt;/big&amp;gt;: Show that the lowest possible energy for the Ising model (with &#039;&#039;J&#039;&#039;&amp;amp;gt;0) is &#039;&#039;E&#039;&#039;&amp;amp;nbsp;=&amp;amp;nbsp;-&#039;&#039;DNJ&#039;&#039;, where &#039;&#039;D&#039;&#039; is the number of dimensions and &#039;&#039;N&#039;&#039; is the total number of spins. What is the multiplicity of this state? Calculate its entropy.&#039;&#039;&#039; ====&lt;br /&gt;
&lt;br /&gt;
==Phase Transitions==&lt;br /&gt;
&lt;br /&gt;
The Ising model is interesting because it is one of the simplest physical models to display a phase transition (so long as we are in two dimensions or more). The temperature of the system controls the balance between the energetic driving force, which wants the system to adopt the lowest energy configuration that you imagined in the previous section, and the entropic driving force, which seeks to maximise the number of configurations available to the system.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1b&amp;lt;/big&amp;gt;: Imagine that the system is in the lowest energy configuration. To move to a different state, one of the spins must spontaneously change direction (&amp;quot;flip&amp;quot;). What is the change in energy if this happens (&#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000)? How much entropy does the system gain by doing so?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
At low temperatures, little thermal energy is available to overcome such energy barriers, and we expect the system to adopt the lowest energy (the energetic driving force will dominate). Under these conditions, we expect a large number of parallel spins, and we can characterise this by considering the total &#039;&#039;magnetisation&#039;&#039; of the system: &amp;lt;math&amp;gt;M = \sum_i s_i&amp;lt;/math&amp;gt;. At higher temperatures, however, enough thermal energy will be available that spins can flip relatively freely. Under these conditions, the entropic driving force should dominate. The transition temperature between the two regimes is called the &#039;&#039;Curie temperature&#039;&#039;, &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;. Below &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;, we observe the highly ordered magnetised phase, while above &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039; a disordered, demagnetised, phase emerges.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1c&amp;lt;/big&amp;gt;: Calculate the magnetisation of the 1D and 2D lattices in figure 1. What magnetisation would you expect to observe for an Ising lattice with &#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000 at absolute zero?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We are interested, therefore, in determining the magnetisation &#039;&#039;M&#039;&#039;, and energy &#039;&#039;E&#039;&#039;, of the system as functions of temperature &#039;&#039;T&#039;&#039;. We can write statistical mechanical equations for these quantities:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle M\right\rangle_T = \frac{1}{Z}\sum_\alpha M\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle E\right\rangle_T = \frac{1}{Z}\sum_\alpha E\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &#039;&#039;&amp;amp;alpha;&#039;&#039; is used as a shorthand to represent all spins in the system, and &#039;&#039;Z&#039;&#039; is the partition function,&lt;br /&gt;
&amp;lt;math&amp;gt;Z = \sum_\alpha \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It was discovered relatively quickly after the model was first proposed that the partition function in the one dimensional case can be solved analytically (though doing so is beyond the scope of this experiment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Z\left(T, N\right) = \left[2\cosh\left(\frac{J}{k_BT}\right)\right]^N&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Much later, [http://en.wikipedia.org/wiki/Lars_Onsager Lars Onsager] established that the two dimensional partition function can also be found analytically, though the mathematics is significantly more involved and the resulting expression is correspondingly much more complicated. In dimensions greater than two, no analytical solution is known.&lt;br /&gt;
&lt;br /&gt;
Luckily for us, the problem can instead be tackled by numerical methods, and it is this that will be the focus of the experiment. We will discuss how the equations for &#039;&#039;M&#039;&#039; and &#039;&#039;E&#039;&#039; can be solved, but first we must set up a Python script to model the lattice.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page:  [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/The_effect_of_temperature&amp;diff=822092</id>
		<title>Programming a 2D Ising Model/The effect of temperature</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/The_effect_of_temperature&amp;diff=822092"/>
		<updated>2026-05-03T13:41:04Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the fifth section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Accelerating the code|4. Accelerating the code]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/The effect of system size|6. The effect of system size]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 5. The effect of temperature =&lt;br /&gt;
We now have enough code to start to investigate the phase behaviour of our model. In the first instance, we are going to make plots of the average energy and magnetisation of the system as a function of temperature, to get an idea of where the change between energetic and entropic domination takes place, but we first have to make a small change to the code that averages the energy and magnetisation.&lt;br /&gt;
&lt;br /&gt;
==Correcting the Averaging Code==&lt;br /&gt;
As you saw in the previous part of the experiment, when we begin from a random configuration, it takes a few Monte Carlo cycles to reach the equilibrium state of the system at a particular temperature. This manifests itself as a relatively sharp drop in the energy of the system in the first few hundred or thousand steps, before the energy starts to fluctuate around a constant value. If we want our average properties to be correct, we should only average in the region where the &#039;&#039;average&#039;&#039; energy and magnetisation are constant.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 5a&amp;lt;/big&amp;gt;: The script ILfinalframe.py runs for a given number of cycles at a given temperature, then plots a depiction of the &#039;&#039;final&#039;&#039; lattice state as well as graphs of the energy and magnetisation as a function of cycle number. This is much quicker than animating every frame! Experiment with a few different temperatures and lattice sizes. Approximately how many cycles (remember, a cycle is &#039;&#039;N&#039;&#039;&amp;lt;sub&amp;gt;spins&amp;lt;/sub&amp;gt; steps) are needed for the system to go from its random starting position to the equilibrium state? Modify your &amp;lt;code&amp;gt;__init__()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;montecarlostep()&amp;lt;/code&amp;gt; methods so that the first &#039;&#039;N&#039;&#039; cycles of the simulation are ignored when calculating the averages. Be careful of off-by-one errors. You should state in your report what period you chose to ignore, and include graphs from ILfinalframe.py to illustrate your motivation in choosing this number.&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Running over a range of temperatures==&lt;br /&gt;
&lt;br /&gt;
The script ILtemperaturerange.py performs simulations of a given length over a range of temperatures. The temperature range is determined by the parameters given to the &amp;lt;code&amp;gt;np.arange&amp;lt;/code&amp;gt; function near the top of the file. Starting from a uniformly aligned lattice, a simulation of length &amp;lt;code&amp;gt;n_steps&amp;lt;/code&amp;gt; will be performed at temperature &amp;lt;code&amp;gt;T_cold&amp;lt;/code&amp;gt;, and the average energy and magnetisation will be recorded. A new simulation of length &amp;lt;code&amp;gt;n_steps&amp;lt;/code&amp;gt; will then be performed at temperature &amp;lt;code&amp;gt;T_cold + dT&amp;lt;/code&amp;gt;, and so on until all temperatures in the range have been simulated. This results in a NumPy array of five columns: the temperature, then the four statistical quantities: &amp;lt;code&amp;gt;ave_energies&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ave_sqenergies&amp;lt;/code&amp;gt; (squared energies), &amp;lt;code&amp;gt;ave_magnetisations&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ave_sqmagnetisations&amp;lt;/code&amp;gt; (squared magnetisations).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 5b&amp;lt;/big&amp;gt;: Use ILtemperaturerange.py to plot the average energy and magnetisation for each temperature, &#039;&#039;with error bars&#039;&#039;, for an 8 &amp;amp;times; 8 lattice. Use multiple repeats to calculate these error bars. Use your intuition and results from the script ILfinalframe.py to estimate how many cycles each simulation should be. The temperature range 0.25 to 5.0 is sufficient. Use as many temperature points as you feel necessary to illustrate the behaviour, but do not use a temperature spacing larger than 0.5. The NumPy function &amp;lt;code&amp;gt;savetxt()&amp;lt;/code&amp;gt; stores your array of output data on disk &amp;amp;mdash; you will need it later. Save the file as &#039;&#039;8x8.dat&#039;&#039; so that you know which lattice size it came from.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the fifth section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page:&amp;lt;/span&amp;gt; [[Programming a 2D Ising Model]]&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Accelerating the code|4. Accelerating the code]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/The effect of system size|6. The effect of system size]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/The_effect_of_temperature&amp;diff=822091</id>
		<title>Programming a 2D Ising Model/The effect of temperature</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/The_effect_of_temperature&amp;diff=822091"/>
		<updated>2026-05-03T13:40:11Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* Running over a range of temperatures */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the fifth section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Accelerating the code|4. Accelerating the code]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/The effect of system size|6. The effect of system size]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We now have enough code to start to investigate the phase behaviour of our model. In the first instance, we are going to make plots of the average energy and magnetisation of the system as a function of temperature, to get an idea of where the change between energetic and entropic domination takes place, but we first have to make a small change to the code that averages the energy and magnetisation.&lt;br /&gt;
&lt;br /&gt;
==Correcting the Averaging Code==&lt;br /&gt;
As you saw in the previous part of the experiment, when we begin from a random configuration, it takes a few Monte Carlo cycles to reach the equilibrium state of the system at a particular temperature. This manifests itself as a relatively sharp drop in the energy of the system in the first few hundred or thousand steps, before the energy starts to fluctuate around a constant value. If we want our average properties to be correct, we should only average in the region where the &#039;&#039;average&#039;&#039; energy and magnetisation are constant.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 5a&amp;lt;/big&amp;gt;: The script ILfinalframe.py runs for a given number of cycles at a given temperature, then plots a depiction of the &#039;&#039;final&#039;&#039; lattice state as well as graphs of the energy and magnetisation as a function of cycle number. This is much quicker than animating every frame! Experiment with a few different temperatures and lattice sizes. Approximately how many cycles (remember, a cycle is &#039;&#039;N&#039;&#039;&amp;lt;sub&amp;gt;spins&amp;lt;/sub&amp;gt; steps) are needed for the system to go from its random starting position to the equilibrium state? Modify your &amp;lt;code&amp;gt;__init__()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;montecarlostep()&amp;lt;/code&amp;gt; methods so that the first &#039;&#039;N&#039;&#039; cycles of the simulation are ignored when calculating the averages. Be careful of off-by-one errors. You should state in your report what period you chose to ignore, and include graphs from ILfinalframe.py to illustrate your motivation in choosing this number.&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Running over a range of temperatures==&lt;br /&gt;
&lt;br /&gt;
The script ILtemperaturerange.py performs simulations of a given length over a range of temperatures. The temperature range is determined by the parameters given to the &amp;lt;code&amp;gt;np.arange&amp;lt;/code&amp;gt; function near the top of the file. Starting from a uniformly aligned lattice, a simulation of length &amp;lt;code&amp;gt;n_steps&amp;lt;/code&amp;gt; will be performed at temperature &amp;lt;code&amp;gt;T_cold&amp;lt;/code&amp;gt;, and the average energy and magnetisation will be recorded. A new simulation of length &amp;lt;code&amp;gt;n_steps&amp;lt;/code&amp;gt; will then be performed at temperature &amp;lt;code&amp;gt;T_cold + dT&amp;lt;/code&amp;gt;, and so on until all temperatures in the range have been simulated. This results in a NumPy array of five columns: the temperature, then the four statistical quantities: &amp;lt;code&amp;gt;ave_energies&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ave_sqenergies&amp;lt;/code&amp;gt; (squared energies), &amp;lt;code&amp;gt;ave_magnetisations&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ave_sqmagnetisations&amp;lt;/code&amp;gt; (squared magnetisations).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 5b&amp;lt;/big&amp;gt;: Use ILtemperaturerange.py to plot the average energy and magnetisation for each temperature, &#039;&#039;with error bars&#039;&#039;, for an 8 &amp;amp;times; 8 lattice. Use multiple repeats to calculate these error bars. Use your intuition and results from the script ILfinalframe.py to estimate how many cycles each simulation should be. The temperature range 0.25 to 5.0 is sufficient. Use as many temperature points as you feel necessary to illustrate the behaviour, but do not use a temperature spacing larger than 0.5. The NumPy function &amp;lt;code&amp;gt;savetxt()&amp;lt;/code&amp;gt; stores your array of output data on disk &amp;amp;mdash; you will need it later. Save the file as &#039;&#039;8x8.dat&#039;&#039; so that you know which lattice size it came from.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the fifth section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page:&amp;lt;/span&amp;gt; [[Programming a 2D Ising Model]]&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Accelerating the code|4. Accelerating the code]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/The effect of system size|6. The effect of system size]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_Monte_Carlo_simulation&amp;diff=822090</id>
		<title>Programming a 2D Ising Model/Introduction to Monte Carlo simulation</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_Monte_Carlo_simulation&amp;diff=822090"/>
		<updated>2026-05-03T13:37:27Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the third section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Accelerating the code|4. Accelerating the code]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 3. Introduction to Monte Carlo simulation =&lt;br /&gt;
&lt;br /&gt;
==Average Energy and Magnetisation==&lt;br /&gt;
&lt;br /&gt;
Consider again the expressions for the average energy and magnetisation that we gave in the introduction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle M\right\rangle_T = \frac{1}{Z}\sum_\alpha M\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle E\right\rangle_T = \frac{1}{Z}\sum_\alpha E\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Imagine we want to evaluate these at a particular temperature, in a system of 100 spins.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3a&amp;lt;/big&amp;gt;: How many configurations are available to a system with 100 spins? To evaluate these expressions, we have to calculate the energy and magnetisation for each of these configurations, then perform the sum. Let&#039;s be very, very, generous, and say that we can analyse 1&amp;amp;times;10&amp;lt;sup&amp;gt;9&amp;lt;/sup&amp;gt; configurations per second with our computer. How long will it take to evaluate a single value of &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;amp;rang;&amp;lt;sub&amp;gt;&#039;&#039;T&#039;&#039;&amp;lt;/sub&amp;gt;?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Clearly, we need to try a cleverer approach.&lt;br /&gt;
&lt;br /&gt;
For the overwhelming majority of the possible configurations, the Boltzmann factor, &amp;lt;math&amp;gt;\exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\}&amp;lt;/math&amp;gt;, will be very small, and that state will contribute very little to the average value. We can save an enormous amount of time, and make this problem tractable, if we only consider the states whose Boltzmann factor is not so vanishingly small. This technique is called &#039;&#039;importance sampling&#039;&#039; &amp;amp;mdash; instead of sampling every point in phase space, we sample only those that the system is likely to occupy.&lt;br /&gt;
&lt;br /&gt;
==Importance Sampling==&lt;br /&gt;
&lt;br /&gt;
This is easily stated, of course, but how can we know which states contribute a lot to the average without actually calculating the energy? So far, we have been imagining generating random states of the system; that is to say, we have been choosing &#039;&#039;&amp;amp;alpha;&#039;&#039; from a uniform distribution in which no arrangement of spins is any more likely to be chosen than any other. If we instead had a method which generated states randomly from the probability distribution &amp;lt;math&amp;gt;\exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\}&amp;lt;/math&amp;gt;, then our problem would be solved. The method which allows us to do this was developed in the 1950s, and is called the [https://doi.org/10.1063/1.1699114 Metropolis Monte Carlo (MMC)] method, or more often simply &amp;quot;Monte Carlo simulation&amp;quot;. This was one of the major breakthroughs of the early days of computational science, and in the year 2000, the IEEE named among the [https://doi.org/10.1109/MCISE.2000.814652 &amp;quot;Top 10 Algorithms of the 20th Century&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
The algorithm is as follows:&lt;br /&gt;
&lt;br /&gt;
# Start from a given configuration of spins, &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039;, with energy &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
# Choose a single spin &#039;&#039;&#039;at random&#039;&#039;&#039;, and &amp;quot;flip&amp;quot; it, to generate a new configuration &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
# Calculate the energy of this new configuration, &#039;&#039;E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
# Calculate the energy difference between the states, &#039;&#039;&amp;amp;Delta;E = E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; - E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
## If the &#039;&#039;&amp;amp;Delta;E &amp;amp;le; 0&#039;&#039; (the spin flipping decreased the energy), then we &#039;&#039;&#039;accept&#039;&#039;&#039; the new configuration.&lt;br /&gt;
##* We set &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = &amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and then &#039;&#039;&#039;go to step 5&#039;&#039;&#039;.&lt;br /&gt;
## If &#039;&#039;&amp;amp;Delta;E &amp;amp;gt; 0&#039;&#039;, the spin flipping increased the energy. By considering the probability of observing the starting and final states, &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039; and &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, it can be shown that the probability for the transition between the two to occur is &amp;lt;math&amp;gt;\exp \left\{-\frac{\Delta E}{k_BT}\right\}&amp;lt;/math&amp;gt;. To ensure that we only accept this kind of spin flip with the correct probability, we use the following procedure:&lt;br /&gt;
### Choose a random number, &#039;&#039;R&#039;&#039;, in the interval [0,1).&lt;br /&gt;
### If &amp;lt;math&amp;gt;R \leq \exp \left\{-\frac{\Delta E}{k_BT}\right\}&amp;lt;/math&amp;gt;, we &#039;&#039;&#039;accept&#039;&#039;&#039; the new configuration.&lt;br /&gt;
###* We set &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = &amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and then &#039;&#039;&#039;go to step 5&#039;&#039;&#039;.&lt;br /&gt;
### If &amp;lt;math&amp;gt;R &amp;gt; \exp \left\{-\frac{\Delta E}{k_BT}\right\}&amp;lt;/math&amp;gt;, we &#039;&#039;&#039;reject&#039;&#039;&#039; the new configuration.&lt;br /&gt;
###* &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039; and &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039; are left unchanged. &#039;&#039;&#039;Go to step 5&#039;&#039;&#039;.&lt;br /&gt;
# Update the running averages of the energy and magnetisation.&lt;br /&gt;
# Monte Carlo &amp;quot;step&amp;quot; complete, &#039;&#039;&#039;return to step 2&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Step 4 is the key to the method. By accepting moves which increase the energy only with a certain probability, we ensure that the sequence of states that we generate is correctly distributed.  A transition which carries a very large energy penalty, &#039;&#039;&amp;amp;Delta;E&#039;&#039; is extremely unlikely to be selected. The use of random numbers in this step is the reason that the method acquired the name &amp;quot;Monte Carlo&amp;quot;, after the casinos located there!&lt;br /&gt;
&lt;br /&gt;
Note, unlike molecular dynamics, each step only moves a single atom. In Monte Carlo simulation, there is the notion of a cycle which is &#039;&#039;N&#039;&#039;&amp;lt;sub&amp;gt;spins&amp;lt;/sub&amp;gt;-steps, so that each spin on average has an attempted flip per cycle.&lt;br /&gt;
&lt;br /&gt;
If you are interested in the mathematical details of why this procedure generates a sequence of states distributed in the correct way, consult the Monte Carlo chapter of [https://library-search.imperial.ac.uk/permalink/f/o1297h/TN_cdi_askewsholts_vlebooks_9780080519982 &amp;quot;Understanding Molecular Simulation&amp;quot;], by Frenkel and Smit, but a discussion of this is not required for the experiment. Chapter 7 of [https://library-search.imperial.ac.uk/permalink/44IMP_INST/mek6kh/alma997227534401591 &amp;quot;Statistical Mechanics: Theory and Molecular Simulation&amp;quot;] by Tuckerman also gives a good description.&lt;br /&gt;
&lt;br /&gt;
==Modifying IsingLattice.py==&lt;br /&gt;
&lt;br /&gt;
Our IsingLattice object contains a stub function, &#039;&#039;&#039;&amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt;&#039;&#039;&#039;, which takes a single argument &amp;amp;mdash; the temperature at which we want to do the cycle. There are also attributes used to calculate the average energy and magnetisation and respective variances: &amp;lt;code&amp;gt;self.E_tally&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;self.E2_tally&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;self.M_tally&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;self.M2_tally&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;self.n_steps&amp;lt;/code&amp;gt;. You should use these values to keep a running sum of all the energies, squared energies, magnetisations, and squared magnetisations that your system has sampled, as well as the number of steps that have been performed. Finally, there is also a function &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt;, that takes no arguments and should return the average energy, squared energy, magnetisation, squared magnetisation and current step, &#039;&#039;&#039;in that order&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3b&amp;lt;/big&amp;gt;: Implement a single step of the above algorithm in the &amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt; function. This function should return the energy of your lattice and the magnetisation at the end of the cycle. Complete the &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt; function. This should return the following quantities whenever it is called: &amp;amp;lang;&#039;&#039;E&#039;&#039;&amp;amp;rang;, &amp;amp;lang;&#039;&#039;E&#039;&#039;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;amp;rang;, &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;amp;rang;, &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;amp;rang;, and &#039;&#039;N&#039;&#039;&amp;lt;sub&amp;gt;steps&amp;lt;/sub&amp;gt;, the number of Monte Carlo steps that have elapsed. Put your code for these functions in the report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note on units:&#039;&#039; In our simulation we will be using an unitless scaled energy &amp;lt;math&amp;gt;\tilde{E}=\frac{E}{J}&amp;lt;/math&amp;gt;, and a unitless scaled temperature &amp;lt;math&amp;gt;\tilde{T}=\frac{k_B T}{J}&amp;lt;/math&amp;gt;, where &#039;&#039;J&#039;&#039; is the interaction energy between spins discussed previously. The use of these scaled quantities in practice means that in the code we can set &#039;&#039;k&amp;lt;sub&amp;gt;B&amp;lt;/sub&amp;gt;&#039;&#039; to numerically equal to 1. Going forward we will drop the &amp;amp;tilde; from the notation of energy and temperature.&lt;br /&gt;
&lt;br /&gt;
You have been provided with a script, &#039;&#039;&#039;ILanim.py&#039;&#039;&#039;, which will use your &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; object to run a Monte Carlo simulation and display the output on the screen in real time. By default, this simulation will run an 8&amp;amp;times;8 lattice at &#039;&#039;T&#039;&#039;=1.0, which is below the critical temperature. You will see a representation of the lattice, and graphs of the energy and magnetisation &#039;&#039;&#039;per spin&#039;&#039;&#039;. When you close the window, the script will use your &#039;&#039;&#039;&amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt;&#039;&#039;&#039; function to print the average energy and magnetisation from the simulation. Note, you should run this script from the command line.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3c&amp;lt;/big&amp;gt;: If &#039;&#039;T&#039;&#039; &amp;amp;lt; &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;, do you expect a spontaneous magnetisation (i.e. do you expect &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;amp;rang; &amp;amp;ne; 0)? When the state of the simulation appears to stop changing (when you have reached an equilibrium state), use the controls to export the output to an SVG or PNG file and attach this to your report. You should also include the output from your statistics() function.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the third section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Accelerating the code|4. Accelerating the code]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822089</id>
		<title>Programming a 2D Ising Model/Calculating the energy and magnetisation</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822089"/>
		<updated>2026-05-03T13:36:45Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Introduction to the Ising model|1. Introduction to the Ising model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 2. Calculating the energy and magnetisation =&lt;br /&gt;
&lt;br /&gt;
==Getting the files for the experiment==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Various scripts have been prepared to assist you with this experiment, and you can obtain them by downloading the files from the Blackboard.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We recommend you open the extracted folder with JupyterLab, which has an integrated terminal where you can run the  simulation scripts.&lt;br /&gt;
&lt;br /&gt;
==Modifying the files==&lt;br /&gt;
&lt;br /&gt;
The file &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; contains a Python class called IsingLattice. This class will be the basis for our model of the system, and is restricted to modelling the two dimensional case. It contains a number of stub methods that you will complete as you work through the experiment.&lt;br /&gt;
&lt;br /&gt;
===A note about Python Classes===&lt;br /&gt;
&lt;br /&gt;
The file IsingLattice.py makes use of a Python feature called &#039;&#039;class&#039;&#039;. You should be familiar with the idea that all Python &#039;&#039;objects&#039;&#039; have an associated &#039;&#039;type&#039;&#039; -- you have already encountered objects such as integers, string, lists, and NumPy arrays. Classes allow us to define new types of object. In this case, we define a type called &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
class IsingLattice:&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each class is allowed to have certain attributes and functions (known as methods) associated with it. We can see, for example, that each &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; object has the methods &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt; (the method &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt; will be explained shortly). Each of these methods takes a special first argument called self, which is a variable pointing to the current copy of IsingLattice. To use the new IsingLattice object that we have defined, we use code like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import IsingLattice&lt;br /&gt;
&lt;br /&gt;
il = IsingLattice(5, 5) #create an IsingLattice object with 5 row and 5 columns&lt;br /&gt;
&lt;br /&gt;
energy = il.energy() #call the energy() method of our IsingLattice object&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all attributes and methods belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the &amp;lt;code&amp;gt;montecarlostep()&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the method &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; which is part of the &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;lt;code&amp;gt;self.&amp;lt;/code&amp;gt; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def magnetisation(self):&lt;br /&gt;
    # we have to use self.lattice, because the lattice variable is part of the object, not local to this function&lt;br /&gt;
    for i in self.lattice:&lt;br /&gt;
        ...&lt;br /&gt;
        # we use i, not self.i&lt;br /&gt;
        # we don&#039;t need to access i outside this function &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Have a look at the other files that you have been given to see how this IsingLattice object is used.&lt;br /&gt;
&lt;br /&gt;
===The Constructor===&lt;br /&gt;
&lt;br /&gt;
The only method currently filled in is &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt;. This is a special method called a &#039;&#039;constructor&#039;&#039;. Whenever a new IsingLattice object is created, using code like &amp;lt;code&amp;gt;il = IsingLattice(5,5)&amp;lt;/code&amp;gt;, this method is called automatically. It takes two arguments (excluding &amp;quot;self&amp;quot;), which are simply the number of rows and columns that our lattice will have. The attribute &amp;lt;code&amp;gt;self.lattice&amp;lt;/code&amp;gt; is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;code&amp;gt;np.random.choice&amp;lt;/code&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for the function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html numpy.random.choice].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, which should return the energy of the lattice and the total magnetisation, respectively. In the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; function you may assume that &#039;&#039;J&#039;&#039;=1.0 at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which all energies are a multiple of &#039;&#039;J&#039;&#039;, but there will be more information about this in later sections). Do not worry about the efficiency of the code at the moment &amp;amp;mdash; we will address the speed in a later part of the experiment. Paste your code in your report and describe how it works.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Testing the files==&lt;br /&gt;
&lt;br /&gt;
When you have completed the energy() and magnetisation() methods, we need to test that they work correctly.&lt;br /&gt;
We have provided you with a script, &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;, which will create three IsingLattice objects and check their energies and magnetisations, displaying these on a graph. One configuration corresponds to the energy minimum, one to the energy maximum, and one to an intermediate state.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2b&amp;lt;/big&amp;gt;: Run the ILcheck.py script from the a terminal using the command&#039;&#039;&#039;&amp;lt;pre&amp;gt;python ILcheck.py&amp;lt;/pre&amp;gt;&#039;&#039;&#039;The displayed window has a series of control buttons in the bottom left, one of which will allow you to export the figure as a SVG or PNG image. Save an image of the ILcheck.py output, and include it in your report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are also some unit tests available in the &amp;lt;code&amp;gt;test_energy.py&amp;lt;/code&amp;gt; file. These tests are designed to be run by simply running the [https://docs.pytest.org pytest] command in your terminal,&lt;br /&gt;
&amp;lt;pre&amp;gt;pytest&amp;lt;/pre&amp;gt;&lt;br /&gt;
You should make sure your code passes the tests for the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt; methods at this time. The file contains tests for methods that will only be implemented later on, so some failures are expected for now.&lt;br /&gt;
These sorts of test are useful because they are easier to write and faster to run and can be made to run automatically.&lt;br /&gt;
&lt;br /&gt;
You can also debug and test your program on a Jupyter notebook or IPython console by importing your IsingLattice class, creating one object, and inspecting its properties. If you do this, we recommend that you start your session running the commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%load_ext autoreload&lt;br /&gt;
%autoreload 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will ensure that when you try executing your code, you always run the most recent version (please note this isn&#039;t fool proof and if you find problems you may need to restart the kernel)!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page:&amp;lt;/span&amp;gt; [[Programming a 2D Ising Model]]&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section:  [[Programming a 2D Ising Model/Introduction to the Ising model|1. Introduction to the Ising model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822088</id>
		<title>Programming a 2D Ising Model/Calculating the energy and magnetisation</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822088"/>
		<updated>2026-05-03T13:36:33Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Introduction to the Ising model|1. Introduction to the Ising model]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 2. Calculating the energy and magnetisation =&lt;br /&gt;
&lt;br /&gt;
==Getting the files for the experiment==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Various scripts have been prepared to assist you with this experiment, and you can obtain them by downloading the files from the Blackboard.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We recommend you open the extracted folder with JupyterLab, which has an integrated terminal where you can run the  simulation scripts.&lt;br /&gt;
&lt;br /&gt;
==Modifying the files==&lt;br /&gt;
&lt;br /&gt;
The file &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; contains a Python class called IsingLattice. This class will be the basis for our model of the system, and is restricted to modelling the two dimensional case. It contains a number of stub methods that you will complete as you work through the experiment.&lt;br /&gt;
&lt;br /&gt;
===A note about Python Classes===&lt;br /&gt;
&lt;br /&gt;
The file IsingLattice.py makes use of a Python feature called &#039;&#039;class&#039;&#039;. You should be familiar with the idea that all Python &#039;&#039;objects&#039;&#039; have an associated &#039;&#039;type&#039;&#039; -- you have already encountered objects such as integers, string, lists, and NumPy arrays. Classes allow us to define new types of object. In this case, we define a type called &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
class IsingLattice:&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each class is allowed to have certain attributes and functions (known as methods) associated with it. We can see, for example, that each &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; object has the methods &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt; (the method &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt; will be explained shortly). Each of these methods takes a special first argument called self, which is a variable pointing to the current copy of IsingLattice. To use the new IsingLattice object that we have defined, we use code like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import IsingLattice&lt;br /&gt;
&lt;br /&gt;
il = IsingLattice(5, 5) #create an IsingLattice object with 5 row and 5 columns&lt;br /&gt;
&lt;br /&gt;
energy = il.energy() #call the energy() method of our IsingLattice object&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all attributes and methods belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the &amp;lt;code&amp;gt;montecarlostep()&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the method &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; which is part of the &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;lt;code&amp;gt;self.&amp;lt;/code&amp;gt; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def magnetisation(self):&lt;br /&gt;
    # we have to use self.lattice, because the lattice variable is part of the object, not local to this function&lt;br /&gt;
    for i in self.lattice:&lt;br /&gt;
        ...&lt;br /&gt;
        # we use i, not self.i&lt;br /&gt;
        # we don&#039;t need to access i outside this function &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Have a look at the other files that you have been given to see how this IsingLattice object is used.&lt;br /&gt;
&lt;br /&gt;
===The Constructor===&lt;br /&gt;
&lt;br /&gt;
The only method currently filled in is &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt;. This is a special method called a &#039;&#039;constructor&#039;&#039;. Whenever a new IsingLattice object is created, using code like &amp;lt;code&amp;gt;il = IsingLattice(5,5)&amp;lt;/code&amp;gt;, this method is called automatically. It takes two arguments (excluding &amp;quot;self&amp;quot;), which are simply the number of rows and columns that our lattice will have. The attribute &amp;lt;code&amp;gt;self.lattice&amp;lt;/code&amp;gt; is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;code&amp;gt;np.random.choice&amp;lt;/code&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for the function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html numpy.random.choice].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, which should return the energy of the lattice and the total magnetisation, respectively. In the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; function you may assume that &#039;&#039;J&#039;&#039;=1.0 at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which all energies are a multiple of &#039;&#039;J&#039;&#039;, but there will be more information about this in later sections). Do not worry about the efficiency of the code at the moment &amp;amp;mdash; we will address the speed in a later part of the experiment. Paste your code in your report and describe how it works.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Testing the files==&lt;br /&gt;
&lt;br /&gt;
When you have completed the energy() and magnetisation() methods, we need to test that they work correctly.&lt;br /&gt;
We have provided you with a script, &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;, which will create three IsingLattice objects and check their energies and magnetisations, displaying these on a graph. One configuration corresponds to the energy minimum, one to the energy maximum, and one to an intermediate state.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2b&amp;lt;/big&amp;gt;: Run the ILcheck.py script from the a terminal using the command&#039;&#039;&#039;&amp;lt;pre&amp;gt;python ILcheck.py&amp;lt;/pre&amp;gt;&#039;&#039;&#039;The displayed window has a series of control buttons in the bottom left, one of which will allow you to export the figure as a SVG or PNG image. Save an image of the ILcheck.py output, and include it in your report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are also some unit tests available in the &amp;lt;code&amp;gt;test_energy.py&amp;lt;/code&amp;gt; file. These tests are designed to be run by simply running the [https://docs.pytest.org pytest] command in your terminal,&lt;br /&gt;
&amp;lt;pre&amp;gt;pytest&amp;lt;/pre&amp;gt;&lt;br /&gt;
You should make sure your code passes the tests for the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt; methods at this time. The file contains tests for methods that will only be implemented later on, so some failures are expected for now.&lt;br /&gt;
These sorts of test are useful because they are easier to write and faster to run and can be made to run automatically.&lt;br /&gt;
&lt;br /&gt;
You can also debug and test your program on a Jupyter notebook or IPython console by importing your IsingLattice class, creating one object, and inspecting its properties. If you do this, we recommend that you start your session running the commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%load_ext autoreload&lt;br /&gt;
%autoreload 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will ensure that when you try executing your code, you always run the most recent version (please note this isn&#039;t fool proof and if you find problems you may need to restart the kernel)!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page:&amp;lt;/span&amp;gt; [[Programming a 2D Ising Model]]&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section:  [[Programming a 2D Ising Model/Introduction to the Ising model|1. Introduction to the Ising model]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822087</id>
		<title>Programming a 2D Ising Model/Introduction to the Ising model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822087"/>
		<updated>2026-05-03T13:35:17Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 1. Introduction to the Ising model =&lt;br /&gt;
&lt;br /&gt;
== The Ising model ==&lt;br /&gt;
The Ising model is a simple physical model proposed in the 1920s to understand the behaviour of ferromagnets. In most materials, the magnetic dipoles of the atoms have no preferred orientation, and the bulk material has no net magnetic moment. In certain materials, however, there is preferential alignment of the magnetic dipoles along certain directions. These materials, such as iron, exhibit an overall magnetic moment, and are called ferromagnetic.&lt;br /&gt;
&lt;br /&gt;
The phenomenon is based on competition between two physical effects &amp;amp;mdash; energy minimisation and entropy maximisation. On the one hand, parallel alignment of magnetic moments is energetically favourable. On the other hand, aligning the system in this way reduces the entropy.&lt;br /&gt;
&lt;br /&gt;
In the Ising model, we consider a collection of spins, &#039;&#039;s&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;&#039;&#039;, each of which can either have the value &amp;quot;up&amp;quot; (+1) or &amp;quot;down&amp;quot; (-1), arranged on a lattice. In one dimension, this takes the form of a &amp;quot;chain&amp;quot; of adjacent spins, &#039;&#039;s&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039; to &#039;&#039;s&amp;lt;sub&amp;gt;N&amp;lt;/sub&amp;gt;&#039;&#039;. In two dimensions we have a grid of cells, each of which contains one spin. In three dimensions, the system is a cuboid, and so on. The arrangements for 1, 2 and 3 dimensions are illustrated in &#039;&#039;&#039;figure 1&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingSketch.png|300px|thumb|right|&#039;&#039;&#039;Figure 1&#039;&#039;&#039;: Illustration of an Ising lattice in one (N=5), two (N=5&amp;amp;times;5), and three (N=5&amp;amp;times;5&amp;amp;times;5) dimensions. Red cells indicate the &amp;quot;up&amp;quot; spin&amp;quot;, and blue cells indicate the &amp;quot;down&amp;quot; spin.]]&lt;br /&gt;
&lt;br /&gt;
The rules of the model are simple:&lt;br /&gt;
&lt;br /&gt;
* When no magnetic field is applied, the only energetic contribution comes from the interaction between spins in &#039;&#039;adjacent&#039;&#039; lattice cells&lt;br /&gt;
* The total interaction energy is defined as &amp;lt;math&amp;gt;- \frac{1}{2} J \sum_i^N \sum_{j\  \in\  \mathrm{neighbours}\left(i\right)} s_i s_j&amp;lt;/math&amp;gt;, where &#039;&#039;J&#039;&#039; is a constant which controls the strength of interaction and the notation &#039;&#039;j&#039;&#039;&amp;amp;nbsp;&amp;amp;in;&amp;amp;nbsp;neighbours(&#039;&#039;i&#039;&#039;) indicates that spin &#039;&#039;j&#039;&#039; must lie in a lattice cell adjacent to spin &#039;&#039;i&#039;&#039;. The factor of one half is included to make sure that we do not count each spin-spin interaction twice.&lt;br /&gt;
* Periodic boundary conditions are applied. In other words, the &amp;quot;final&amp;quot; spin in a particular direction is considered to be adjacent to the &amp;quot;first&amp;quot; spin in that direction. In &#039;&#039;&#039;figure 2&#039;&#039;&#039;, for example, cell 1 has neighbour interactions with cells 2, 3, 4, and 7, while cell 9 interacts with cells 3, 6, 7, and 8.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingNumberedCell.png|300px|thumb|right|&#039;&#039;&#039;Figure 2&#039;&#039;&#039;: Illustration of a 2D Ising lattice, with numbered cells to indicate the neighbour interactions.]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1a&amp;lt;/big&amp;gt;: Show that the lowest possible energy for the Ising model (with &#039;&#039;J&#039;&#039;&amp;amp;gt;0) is &#039;&#039;E&#039;&#039;&amp;amp;nbsp;=&amp;amp;nbsp;-&#039;&#039;DNJ&#039;&#039;, where &#039;&#039;D&#039;&#039; is the number of dimensions and &#039;&#039;N&#039;&#039; is the total number of spins. What is the multiplicity of this state? Calculate its entropy.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Phase Transitions==&lt;br /&gt;
&lt;br /&gt;
The Ising model is interesting because it is one of the simplest physical models to display a phase transition (so long as we are in two dimensions or more). The temperature of the system controls the balance between the energetic driving force, which wants the system to adopt the lowest energy configuration that you imagined in the previous section, and the entropic driving force, which seeks to maximise the number of configurations available to the system.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1b&amp;lt;/big&amp;gt;: Imagine that the system is in the lowest energy configuration. To move to a different state, one of the spins must spontaneously change direction (&amp;quot;flip&amp;quot;). What is the change in energy if this happens (&#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000)? How much entropy does the system gain by doing so?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
At low temperatures, little thermal energy is available to overcome such energy barriers, and we expect the system to adopt the lowest energy (the energetic driving force will dominate). Under these conditions, we expect a large number of parallel spins, and we can characterise this by considering the total &#039;&#039;magnetisation&#039;&#039; of the system: &amp;lt;math&amp;gt;M = \sum_i s_i&amp;lt;/math&amp;gt;. At higher temperatures, however, enough thermal energy will be available that spins can flip relatively freely. Under these conditions, the entropic driving force should dominate. The transition temperature between the two regimes is called the &#039;&#039;Curie temperature&#039;&#039;, &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;. Below &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;, we observe the highly ordered magnetised phase, while above &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039; a disordered, demagnetised, phase emerges.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1c&amp;lt;/big&amp;gt;: Calculate the magnetisation of the 1D and 2D lattices in figure 1. What magnetisation would you expect to observe for an Ising lattice with &#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000 at absolute zero?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We are interested, therefore, in determining the magnetisation &#039;&#039;M&#039;&#039;, and energy &#039;&#039;E&#039;&#039;, of the system as functions of temperature &#039;&#039;T&#039;&#039;. We can write statistical mechanical equations for these quantities:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle M\right\rangle_T = \frac{1}{Z}\sum_\alpha M\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle E\right\rangle_T = \frac{1}{Z}\sum_\alpha E\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &#039;&#039;&amp;amp;alpha;&#039;&#039; is used as a shorthand to represent all spins in the system, and &#039;&#039;Z&#039;&#039; is the partition function,&lt;br /&gt;
&amp;lt;math&amp;gt;Z = \sum_\alpha \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It was discovered relatively quickly after the model was first proposed that the partition function in the one dimensional case can be solved analytically (though doing so is beyond the scope of this experiment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Z\left(T, N\right) = \left[2\cosh\left(\frac{J}{k_BT}\right)\right]^N&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Much later, [http://en.wikipedia.org/wiki/Lars_Onsager Lars Onsager] established that the two dimensional partition function can also be found analytically, though the mathematics is significantly more involved and the resulting expression is correspondingly much more complicated. In dimensions greater than two, no analytical solution is known.&lt;br /&gt;
&lt;br /&gt;
Luckily for us, the problem can instead be tackled by numerical methods, and it is this that will be the focus of the experiment. We will discuss how the equations for &#039;&#039;M&#039;&#039; and &#039;&#039;E&#039;&#039; can be solved, but first we must set up a Python script to model the lattice.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page:  [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Accelerating_the_code&amp;diff=822086</id>
		<title>Programming a 2D Ising Model/Accelerating the code</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Accelerating_the_code&amp;diff=822086"/>
		<updated>2026-05-03T13:34:59Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* 4. Accelerating the code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the fourth section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/The effect of temperature|5. The effect of temperature]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 4. Accelerating the code =&lt;br /&gt;
So far, your energy() and magnetisation() functions probably use Python loops to go over every spin in your system (and a double loop for the energy). One of the drawbacks of Python&#039;s flexibility is a performance penalty &amp;amp;mdash; though developing code in Python tends to be &lt;br /&gt;
faster than other compiled programming languages, the resulting program is much, much slower.&lt;br /&gt;
&lt;br /&gt;
Fortunately, the NumPy module provides an interface to a number of functions written to give high performance. &lt;br /&gt;
These are written in the C programming language under the hood and take numpy arrays, which are contiguous arrays of a single data type, &lt;br /&gt;
unlike Python lists, which may contain mixes of data types.&lt;br /&gt;
&lt;br /&gt;
In this section, we are going to use these functions to improve the performance of our simulation.&lt;br /&gt;
&lt;br /&gt;
When trying to optimise the performance of something, you should always measure first, rather than making assumptions. Although there are some very obvious candidates in our program, you should always measure properly.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ILtimetrial.py&amp;lt;/code&amp;gt; script measures how fast it takes for 2000 iterations of your code to run.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ILProfiling.py&amp;lt;/code&amp;gt; script is the same, except uses the python standard library package [https://docs.python.org/3/library/profile.html cProfile] to sample what functions are being called and give you information&lt;br /&gt;
about the time spent in each. Analysing the output of the script, you will see that by far the majority of the time is spent in the energy method, followed by the magnetisation one. This makes sense, as each Monte-Carlo step can call the energy function multiple times.&lt;br /&gt;
&lt;br /&gt;
(If you want to profile your code in more detail, please seek advice from a demonstrator.)&lt;br /&gt;
&lt;br /&gt;
In order to improve the performance of this, we need to: &lt;br /&gt;
* Run the energy call fewer times per step.&lt;br /&gt;
* Improve the performance of the energy function.&lt;br /&gt;
&lt;br /&gt;
Fortunately, the NumPy module provides an interface to a number of functions written to give high performance. In this section, we are going to use these functions to improve the performance of our simulation.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 4a&amp;lt;/big&amp;gt;: Use the script ILtimetrial.py to record how long your &#039;&#039;current&#039;&#039; version of IsingLattice.py takes to perform 2000 Monte Carlo steps. This will vary, depending on what else the computer happens to be doing, so perform repeats and report the error in your average!&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 4b&amp;lt;/big&amp;gt;: Look at the documentation for the [http://docs.scipy.org/doc/numpy/reference/generated/numpy.sum.html NumPy &amp;lt;code&amp;gt;sum&amp;lt;/code&amp;gt; function]. You should be able to modify your &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt; function so that it uses this to evaluate M. The energy is a little trickier. Familiarise yourself with the NumPy [http://docs.scipy.org/doc/numpy/reference/generated/numpy.roll.html &amp;lt;code&amp;gt;roll&amp;lt;/code&amp;gt;] and [http://docs.scipy.org/doc/numpy/reference/generated/numpy.multiply.html &amp;lt;code&amp;gt;multiply&amp;lt;/code&amp;gt;] functions, and use these to replace your energy double loop (you will need to call roll and multiply twice!). Add your faster code to the report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 4c&amp;lt;/big&amp;gt;: Use the script ILtimetrial.py to record how long your &#039;&#039;new&#039;&#039; version of IsingLattice.py takes to perform 2000 Monte Carlo steps. This will vary, depending on what else the computer happens to be doing, so perform repeats and report the error in your average! What makes this new version faster?&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Task 4d: Making the code even faster &amp;lt;/big&amp;gt;: Consider trying to make the Monte Carlo step function substantially faster by calculating the difference in energy directly, in a way that avoids looping over the whole lattice. Think back how you answered some of the introduction questions. You can make it so the energy and magnetisation only needs to be calculated explicitly at the beginning of the simulation.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the fourth section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/The effect of temperature|5. The effect of temperature]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Accelerating_the_code&amp;diff=822085</id>
		<title>Programming a 2D Ising Model/Accelerating the code</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Accelerating_the_code&amp;diff=822085"/>
		<updated>2026-05-03T13:34:34Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the fourth section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/The effect of temperature|5. The effect of temperature]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 4. Accelerating the code =&lt;br /&gt;
So far, your energy() and magnetisation() functions probably use Python loops to go over every spin in your system (and a double loop for the energy). One of the drawbacks of Python&#039;s flexibility is a performance penalty &amp;amp;mdash; though developing code in Python tends to be &lt;br /&gt;
faster than other compiled programming languages, the resulting program is much, much slower.&lt;br /&gt;
&lt;br /&gt;
Fortunately, the NumPy module provides an interface to a number of functions written to give high performance. &lt;br /&gt;
These are written in the C programming language under the hood and take numpy arrays, which are contiguous arrays of a single data type, &lt;br /&gt;
unlike Python lists, which may contain mixes of data types.&lt;br /&gt;
&lt;br /&gt;
In this section, we are going to use these functions to improve the performance of our simulation.&lt;br /&gt;
&lt;br /&gt;
When trying to optimise the performance of something, you should always measure first, rather than making assumptions. Although there are some very obvious candidates in our program, you should always measure properly.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ILtimetrial.py&amp;lt;/code&amp;gt; script measures how fast it takes for 2000 iterations of your code to run.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ILProfiling.py&amp;lt;/code&amp;gt; script is the same, except uses the python standard library package [https://docs.python.org/3/library/profile.html cProfile] to sample what functions are being called and give you information&lt;br /&gt;
about the time spent in each. Analysing the output of the script, you will see that by far the majority of the time is spent in the energy method, followed by the magnetisation one. This makes sense, as each Monte-Carlo step can call the energy function multiple times.&lt;br /&gt;
&lt;br /&gt;
(If you want to profile your code in more detail, please seek advice from a demonstrator.)&lt;br /&gt;
&lt;br /&gt;
In order to improve the performance of this, we need to: &lt;br /&gt;
* Run the energy call fewer times per step.&lt;br /&gt;
* Improve the performance of the energy function.&lt;br /&gt;
&lt;br /&gt;
Fortunately, the NumPy module provides an interface to a number of functions written to give high performance. In this section, we are going to use these functions to improve the performance of our simulation.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 4a&amp;lt;/big&amp;gt;: Use the script ILtimetrial.py to record how long your &#039;&#039;current&#039;&#039; version of IsingLattice.py takes to perform 2000 Monte Carlo steps. This will vary, depending on what else the computer happens to be doing, so perform repeats and report the error in your average!&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 4b&amp;lt;/big&amp;gt;: Look at the documentation for the [http://docs.scipy.org/doc/numpy/reference/generated/numpy.sum.html NumPy &amp;lt;code&amp;gt;sum&amp;lt;/code&amp;gt; function]. You should be able to modify your &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt; function so that it uses this to evaluate M. The energy is a little trickier. Familiarise yourself with the NumPy [http://docs.scipy.org/doc/numpy/reference/generated/numpy.roll.html &amp;lt;code&amp;gt;roll&amp;lt;/code&amp;gt;] and [http://docs.scipy.org/doc/numpy/reference/generated/numpy.multiply.html &amp;lt;code&amp;gt;multiply&amp;lt;/code&amp;gt;] functions, and use these to replace your energy double loop (you will need to call roll and multiply twice!). Add your faster code to the report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 4c&amp;lt;/big&amp;gt;: Use the script ILtimetrial.py to record how long your &#039;&#039;new&#039;&#039; version of IsingLattice.py takes to perform 2000 Monte Carlo steps. This will vary, depending on what else the computer happens to be doing, so perform repeats and report the error in your average! What makes this new version faster?&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;Task 4d: Making the code even faster &amp;lt;/big&amp;gt;: Consider trying to make the Monte Carlo step function substantially faster by calculating the difference in energy directly, in a way that avoids looping over the whole lattice. Think back how you answered some of the introduction questions. You can make it so the energy and magnetisation only needs to be calculated explicitly at the beginning of the simulation.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the fourth section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/The effect of temperature|5. The effect of temperature]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Accelerating_the_code&amp;diff=822084</id>
		<title>Programming a 2D Ising Model/Accelerating the code</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Accelerating_the_code&amp;diff=822084"/>
		<updated>2026-05-03T13:33:53Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the fourth section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/The effect of temperature|5. The effect of temperature]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 4. Accelerating the code =&lt;br /&gt;
So far, your energy() and magnetisation() functions probably use Python loops to go over every spin in your system (and a double loop for the energy). One of the drawbacks of Python&#039;s flexibility is a performance penalty &amp;amp;mdash; though developing code in Python tends to be &lt;br /&gt;
faster than other compiled programming languages, the resulting program is much, much slower.&lt;br /&gt;
&lt;br /&gt;
Fortunately, the NumPy module provides an interface to a number of functions written to give high performance. &lt;br /&gt;
These are written in the C programming language under the hood and take numpy arrays, which are contiguous arrays of a single data type, &lt;br /&gt;
unlike Python lists, which may contain mixes of data types.&lt;br /&gt;
&lt;br /&gt;
In this section, we are going to use these functions to improve the performance of our simulation.&lt;br /&gt;
&lt;br /&gt;
When trying to optimise the performance of something, you should always measure first, rather than making assumptions. Although there are some very obvious candidates in our program, you should always measure properly.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ILtimetrial.py&amp;lt;/code&amp;gt; script measures how fast it takes for 2000 iterations of your code to run.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ILProfiling.py&amp;lt;/code&amp;gt; script is the same, except uses the python standard library package [https://docs.python.org/3/library/profile.html cProfile] to sample what functions are being called and give you information&lt;br /&gt;
about the time spent in each. Analysing the output of the script, you will see that by far the majority of the time is spent in the energy method, followed by the magnetisation one. This makes sense, as each Monte-Carlo step can call the energy function multiple times.&lt;br /&gt;
&lt;br /&gt;
(If you want to profile your code in more detail, please seek advice from a demonstrator.)&lt;br /&gt;
&lt;br /&gt;
In order to improve the performance of this, we need to: &lt;br /&gt;
* Run the energy call fewer times per step.&lt;br /&gt;
* Improve the performance of the energy function.&lt;br /&gt;
&lt;br /&gt;
Fortunately, the NumPy module provides an interface to a number of functions written to give high performance. In this section, we are going to use these functions to improve the performance of our simulation.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 4a&amp;lt;/big&amp;gt;: Use the script ILtimetrial.py to record how long your &#039;&#039;current&#039;&#039; version of IsingLattice.py takes to perform 2000 Monte Carlo steps. This will vary, depending on what else the computer happens to be doing, so perform repeats and report the error in your average!&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 4b&amp;lt;/big&amp;gt;: Look at the documentation for the [http://docs.scipy.org/doc/numpy/reference/generated/numpy.sum.html NumPy &amp;lt;code&amp;gt;sum&amp;lt;/code&amp;gt; function]. You should be able to modify your &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt; function so that it uses this to evaluate M. The energy is a little trickier. Familiarise yourself with the NumPy [http://docs.scipy.org/doc/numpy/reference/generated/numpy.roll.html &amp;lt;code&amp;gt;roll&amp;lt;/code&amp;gt;] and [http://docs.scipy.org/doc/numpy/reference/generated/numpy.multiply.html &amp;lt;code&amp;gt;multiply&amp;lt;/code&amp;gt;] functions, and use these to replace your energy double loop (you will need to call roll and multiply twice!). Add your faster code to the report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 4c&amp;lt;/big&amp;gt;: Use the script ILtimetrial.py to record how long your &#039;&#039;new&#039;&#039; version of IsingLattice.py takes to perform 2000 Monte Carlo steps. This will vary, depending on what else the computer happens to be doing, so perform repeats and report the error in your average! What makes this new version faster?&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt; Optional: Making the code even faster &amp;lt;/big&amp;gt;: Consider trying to make the Monte Carlo step function substantially faster by calculating the difference in energy directly, in a way that avoids looping over the whole lattice. Think back how you answered some of the introduction questions. You can make it so the energy and magnetisation only needs to be calculated explicitly at the beginning of the simulation.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the fourth section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/The effect of temperature|5. The effect of temperature]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822083</id>
		<title>Programming a 2D Ising Model/Calculating the energy and magnetisation</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822083"/>
		<updated>2026-05-03T13:29:52Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* Testing the files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;You can return to the previous page, [[Programming a 2D Ising Model/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|Introduction to Monte Carlo simulation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 2. Calculating the energy and magnetisation =&lt;br /&gt;
&lt;br /&gt;
==Getting the files for the experiment==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Various scripts have been prepared to assist you with this experiment, and you can obtain them by downloading the files from the Blackboard.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We recommend you open the extracted folder with JupyterLab, which has an integrated terminal where you can run the  simulation scripts.&lt;br /&gt;
&lt;br /&gt;
==Modifying the files==&lt;br /&gt;
&lt;br /&gt;
The file &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; contains a Python class called IsingLattice. This class will be the basis for our model of the system, and is restricted to modelling the two dimensional case. It contains a number of stub methods that you will complete as you work through the experiment.&lt;br /&gt;
&lt;br /&gt;
===A note about Python Classes===&lt;br /&gt;
&lt;br /&gt;
The file IsingLattice.py makes use of a Python feature called &#039;&#039;class&#039;&#039;. You should be familiar with the idea that all Python &#039;&#039;objects&#039;&#039; have an associated &#039;&#039;type&#039;&#039; -- you have already encountered objects such as integers, string, lists, and NumPy arrays. Classes allow us to define new types of object. In this case, we define a type called &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
class IsingLattice:&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each class is allowed to have certain attributes and functions (known as methods) associated with it. We can see, for example, that each &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; object has the methods &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt; (the method &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt; will be explained shortly). Each of these methods takes a special first argument called self, which is a variable pointing to the current copy of IsingLattice. To use the new IsingLattice object that we have defined, we use code like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import IsingLattice&lt;br /&gt;
&lt;br /&gt;
il = IsingLattice(5, 5) #create an IsingLattice object with 5 row and 5 columns&lt;br /&gt;
&lt;br /&gt;
energy = il.energy() #call the energy() method of our IsingLattice object&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all attributes and methods belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the &amp;lt;code&amp;gt;montecarlostep()&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the method &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; which is part of the &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;lt;code&amp;gt;self.&amp;lt;/code&amp;gt; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def magnetisation(self):&lt;br /&gt;
    # we have to use self.lattice, because the lattice variable is part of the object, not local to this function&lt;br /&gt;
    for i in self.lattice:&lt;br /&gt;
        ...&lt;br /&gt;
        # we use i, not self.i&lt;br /&gt;
        # we don&#039;t need to access i outside this function &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Have a look at the other files that you have been given to see how this IsingLattice object is used.&lt;br /&gt;
&lt;br /&gt;
===The Constructor===&lt;br /&gt;
&lt;br /&gt;
The only method currently filled in is &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt;. This is a special method called a &#039;&#039;constructor&#039;&#039;. Whenever a new IsingLattice object is created, using code like &amp;lt;code&amp;gt;il = IsingLattice(5,5)&amp;lt;/code&amp;gt;, this method is called automatically. It takes two arguments (excluding &amp;quot;self&amp;quot;), which are simply the number of rows and columns that our lattice will have. The attribute &amp;lt;code&amp;gt;self.lattice&amp;lt;/code&amp;gt; is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;code&amp;gt;np.random.choice&amp;lt;/code&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for the function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html numpy.random.choice].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, which should return the energy of the lattice and the total magnetisation, respectively. In the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; function you may assume that &#039;&#039;J&#039;&#039;=1.0 at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which all energies are a multiple of &#039;&#039;J&#039;&#039;, but there will be more information about this in later sections). Do not worry about the efficiency of the code at the moment &amp;amp;mdash; we will address the speed in a later part of the experiment. Paste your code in your report and describe how it works.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Testing the files==&lt;br /&gt;
&lt;br /&gt;
When you have completed the energy() and magnetisation() methods, we need to test that they work correctly.&lt;br /&gt;
We have provided you with a script, &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;, which will create three IsingLattice objects and check their energies and magnetisations, displaying these on a graph. One configuration corresponds to the energy minimum, one to the energy maximum, and one to an intermediate state.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2b&amp;lt;/big&amp;gt;: Run the ILcheck.py script from the a terminal using the command&#039;&#039;&#039;&amp;lt;pre&amp;gt;python ILcheck.py&amp;lt;/pre&amp;gt;&#039;&#039;&#039;The displayed window has a series of control buttons in the bottom left, one of which will allow you to export the figure as a SVG or PNG image. Save an image of the ILcheck.py output, and include it in your report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are also some unit tests available in the &amp;lt;code&amp;gt;test_energy.py&amp;lt;/code&amp;gt; file. These tests are designed to be run by simply running the [https://docs.pytest.org pytest] command in your terminal,&lt;br /&gt;
&amp;lt;pre&amp;gt;pytest&amp;lt;/pre&amp;gt;&lt;br /&gt;
You should make sure your code passes the tests for the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt; methods at this time. The file contains tests for methods that will only be implemented later on, so some failures are expected for now.&lt;br /&gt;
These sorts of test are useful because they are easier to write and faster to run and can be made to run automatically.&lt;br /&gt;
&lt;br /&gt;
You can also debug and test your program on a Jupyter notebook or IPython console by importing your IsingLattice class, creating one object, and inspecting its properties. If you do this, we recommend that you start your session running the commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%load_ext autoreload&lt;br /&gt;
%autoreload 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will ensure that when you try executing your code, you always run the most recent version (please note this isn&#039;t fool proof and if you find problems you may need to restart the kernel)!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main Page:&amp;lt;/span&amp;gt; [[Programming a 2D Ising Model]]&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section:  [[Programming a 2D Ising Model/Introduction to the Ising model|1. Introduction to the Ising model]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822082</id>
		<title>Programming a 2D Ising Model/Calculating the energy and magnetisation</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822082"/>
		<updated>2026-05-03T12:39:52Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;You can return to the previous page, [[Programming a 2D Ising Model/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|Introduction to Monte Carlo simulation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 2. Calculating the energy and magnetisation =&lt;br /&gt;
&lt;br /&gt;
==Getting the files for the experiment==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Various scripts have been prepared to assist you with this experiment, and you can obtain them by downloading the files from the Blackboard.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We recommend you open the extracted folder with JupyterLab, which has an integrated terminal where you can run the  simulation scripts.&lt;br /&gt;
&lt;br /&gt;
==Modifying the files==&lt;br /&gt;
&lt;br /&gt;
The file &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; contains a Python class called IsingLattice. This class will be the basis for our model of the system, and is restricted to modelling the two dimensional case. It contains a number of stub methods that you will complete as you work through the experiment.&lt;br /&gt;
&lt;br /&gt;
===A note about Python Classes===&lt;br /&gt;
&lt;br /&gt;
The file IsingLattice.py makes use of a Python feature called &#039;&#039;class&#039;&#039;. You should be familiar with the idea that all Python &#039;&#039;objects&#039;&#039; have an associated &#039;&#039;type&#039;&#039; -- you have already encountered objects such as integers, string, lists, and NumPy arrays. Classes allow us to define new types of object. In this case, we define a type called &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
class IsingLattice:&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each class is allowed to have certain attributes and functions (known as methods) associated with it. We can see, for example, that each &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; object has the methods &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt; (the method &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt; will be explained shortly). Each of these methods takes a special first argument called self, which is a variable pointing to the current copy of IsingLattice. To use the new IsingLattice object that we have defined, we use code like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import IsingLattice&lt;br /&gt;
&lt;br /&gt;
il = IsingLattice(5, 5) #create an IsingLattice object with 5 row and 5 columns&lt;br /&gt;
&lt;br /&gt;
energy = il.energy() #call the energy() method of our IsingLattice object&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all attributes and methods belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the &amp;lt;code&amp;gt;montecarlostep()&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the method &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; which is part of the &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;lt;code&amp;gt;self.&amp;lt;/code&amp;gt; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def magnetisation(self):&lt;br /&gt;
    # we have to use self.lattice, because the lattice variable is part of the object, not local to this function&lt;br /&gt;
    for i in self.lattice:&lt;br /&gt;
        ...&lt;br /&gt;
        # we use i, not self.i&lt;br /&gt;
        # we don&#039;t need to access i outside this function &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Have a look at the other files that you have been given to see how this IsingLattice object is used.&lt;br /&gt;
&lt;br /&gt;
===The Constructor===&lt;br /&gt;
&lt;br /&gt;
The only method currently filled in is &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt;. This is a special method called a &#039;&#039;constructor&#039;&#039;. Whenever a new IsingLattice object is created, using code like &amp;lt;code&amp;gt;il = IsingLattice(5,5)&amp;lt;/code&amp;gt;, this method is called automatically. It takes two arguments (excluding &amp;quot;self&amp;quot;), which are simply the number of rows and columns that our lattice will have. The attribute &amp;lt;code&amp;gt;self.lattice&amp;lt;/code&amp;gt; is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;code&amp;gt;np.random.choice&amp;lt;/code&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for the function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html numpy.random.choice].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, which should return the energy of the lattice and the total magnetisation, respectively. In the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; function you may assume that &#039;&#039;J&#039;&#039;=1.0 at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which all energies are a multiple of &#039;&#039;J&#039;&#039;, but there will be more information about this in later sections). Do not worry about the efficiency of the code at the moment &amp;amp;mdash; we will address the speed in a later part of the experiment. Paste your code in your report and describe how it works.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Testing the files==&lt;br /&gt;
&lt;br /&gt;
When you have completed the energy() and magnetisation() methods, we need to test that they work correctly.&lt;br /&gt;
We have provided you with a script, &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;, which will create three IsingLattice objects and check their energies and magnetisations, displaying these on a graph. One configuration corresponds to the energy minimum, one to the energy maximum, and one to an intermediate state.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2b&amp;lt;/big&amp;gt;: Run the ILcheck.py script from the a terminal using the command&#039;&#039;&#039;&amp;lt;pre&amp;gt;python ILcheck.py&amp;lt;/pre&amp;gt;&#039;&#039;&#039;The displayed window has a series of control buttons in the bottom left, one of which will allow you to export the figure as a SVG or PNG image. Save an image of the ILcheck.py output, and include it in your report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are also some unit tests available in the &amp;lt;code&amp;gt;test_energy.py&amp;lt;/code&amp;gt; file. These tests are designed to be run by simply running the [https://docs.pytest.org pytest] command in your terminal,&lt;br /&gt;
&amp;lt;pre&amp;gt;pytest&amp;lt;/pre&amp;gt;&lt;br /&gt;
You should make sure your code passes the tests for the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt; methods at this time. The file contains tests for methods that will only be implemented later on, so some failures are expected for now.&lt;br /&gt;
These sorts of test are useful because they are easier to write and faster to run and can be made to run automatically.&lt;br /&gt;
&lt;br /&gt;
You can also debug and test your program on a Jupyter notebook or IPython console by importing your IsingLattice class, creating one object, and inspecting its properties. If you do this, we recommend that you start your session running the commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%load_ext autoreload&lt;br /&gt;
%autoreload 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will ensure that when you try executing your code, you always run the most recent version (please note this isn&#039;t fool proof and if you find problems you may need to restart the kernel)!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment. You can return to the previous page, [[Programming a 2D Ising Model/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822081</id>
		<title>Programming a 2D Ising Model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822081"/>
		<updated>2026-05-03T12:37:12Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;This is the Ising Model experiment (aka programming for simple simulations).&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;This is a core experiment for year 3 students on the Chemistry with Molecular Physics degree.&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Programming a 2D Ising Model/ Main page =&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
In this exercise, you are going to use the Python that you learned in the first year to write a code to perform Monte-Carlo simulations of the 2D [http://en.wikipedia.org/wiki/Ising_model Ising model], a set of spins on a lattice which is used to model ferromagnetic behaviour, and also to analyse the results of the simulation to find the heat capacity of the system and the Curie temperature &amp;amp;mdash; the temperature below which the system is able to maintain a spontaneous magnetisation.&lt;br /&gt;
&lt;br /&gt;
A more extensive introduction to the Ising Model will be given in the next page. This page gives some practical information about how the experiment. &lt;br /&gt;
&lt;br /&gt;
==Assessment==&lt;br /&gt;
At the end of this experiment you must submit a report, writing up your findings. Each section of the experiment has a number of tasks that you should complete, labelled &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK&amp;lt;/big&amp;gt;&#039;&#039;&#039;. If this is a mathematical exercise, your report should contain a short summary of the solution. If it is a graphical exercise, you should include the relevant image. Your report should explain briefly what you did in each stage of the experiment, and what your findings were.&lt;br /&gt;
&lt;br /&gt;
The report should be submitted as a PDF file to Turnitin, created with your favourite word processor or LaTeX, and should contain the annotated source code of the Python scripts that your write during the experiment. For clarity, code included in the report should be written in a monospaced font (e.g. Courier), which in LaTeX can be easily achieved by placing your code inside a &amp;lt;code&amp;gt;\texttt{}&amp;lt;/code&amp;gt; command. &#039;&#039;&#039;The code, except where relevant to discussion, can be placed in an appendix.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As well as including relevant source code in your report, you should also submit a bundle with all your scripts and analysis code as a separate Blackboard submission.&lt;br /&gt;
&lt;br /&gt;
===On the use of AI tools===&lt;br /&gt;
The code you write for this experiment is assessed, and as per the [https://bb.imperial.ac.uk/bbcswebdav/pid-3344481-dt-content-rid-21115105_1/xid-21115105_1 department&#039;s guidelines on the use of AI], it is not acceptable to use generative AI tools to write computer code for this assignment.&lt;br /&gt;
&lt;br /&gt;
Writing computer programs yourself enhances your logical thinking and problem solving skills. Using generative AI tools to write your code makes you dumb. Don&#039;t choose to be dumb, don&#039;t use AI to write code for you.&lt;br /&gt;
&lt;br /&gt;
==Getting Help==&lt;br /&gt;
&lt;br /&gt;
The Graduate Teaching Assistants demonstrating this experiment are Fionn Carman and Lei Li. Demonstrators will be available in room 232A at the following times:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Demonstrator timetable&lt;br /&gt;
! !! Monday !! Tuesday !! Wednesday !! Thusrsday !! Friday&lt;br /&gt;
|-&lt;br /&gt;
| Morning || 10:00 - Experiment intro&amp;lt;br /&amp;gt; 10:00-13:00 - Li || 10:00-13:00 - Fionn|| || 10:00-12:00 - João || 10:00-13:00 - Fionn&lt;br /&gt;
|-&lt;br /&gt;
| Afternoon || 14:00-17:00 - Li|| 14:00-17:00 - Fionn|| ||  || 14:00-17:00 - Fionn&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you have questions outside these times, please use the Discussion Board on Blackboard.&lt;br /&gt;
&lt;br /&gt;
João and Giuseppe are the members of academic staff responsible for this experiment. You are welcome to address your questions and comments to them.&lt;br /&gt;
&lt;br /&gt;
==Structure of this Experiment==&lt;br /&gt;
&lt;br /&gt;
This experimental manual has been broken up into a number of subsections. Direct links to each of them may be found below. You should attempt them in order, and you should complete all of them to finish the experiment.&lt;br /&gt;
&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model|Introduction to the Ising model]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Calculating the energy and magnetisation|Calculating the energy and magnetisation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction to Monte Carlo simulation|Introduction to the Monte Carlo simulation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Accelerating the code|Accelerating the code]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of temperature|The effect of temperature]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of system size|The effect of system size]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Determining the heat capacity|Determining the heat capacity]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Locating the Curie temperature|Locating the Curie temperature]]&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822080</id>
		<title>Programming a 2D Ising Model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822080"/>
		<updated>2026-05-03T12:36:49Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;This is the Ising Model experiment (aka programming for simple simulations).&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;This is a core experiment for year 3 students on the Chemistry with Molecular Physics degree.&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Programming a 2D Ising Model =&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
In this exercise, you are going to use the Python that you learned in the first year to write a code to perform Monte-Carlo simulations of the 2D [http://en.wikipedia.org/wiki/Ising_model Ising model], a set of spins on a lattice which is used to model ferromagnetic behaviour, and also to analyse the results of the simulation to find the heat capacity of the system and the Curie temperature &amp;amp;mdash; the temperature below which the system is able to maintain a spontaneous magnetisation.&lt;br /&gt;
&lt;br /&gt;
A more extensive introduction to the Ising Model will be given in the next page. This page gives some practical information about how the experiment. &lt;br /&gt;
&lt;br /&gt;
==Assessment==&lt;br /&gt;
At the end of this experiment you must submit a report, writing up your findings. Each section of the experiment has a number of tasks that you should complete, labelled &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK&amp;lt;/big&amp;gt;&#039;&#039;&#039;. If this is a mathematical exercise, your report should contain a short summary of the solution. If it is a graphical exercise, you should include the relevant image. Your report should explain briefly what you did in each stage of the experiment, and what your findings were.&lt;br /&gt;
&lt;br /&gt;
The report should be submitted as a PDF file to Turnitin, created with your favourite word processor or LaTeX, and should contain the annotated source code of the Python scripts that your write during the experiment. For clarity, code included in the report should be written in a monospaced font (e.g. Courier), which in LaTeX can be easily achieved by placing your code inside a &amp;lt;code&amp;gt;\texttt{}&amp;lt;/code&amp;gt; command. &#039;&#039;&#039;The code, except where relevant to discussion, can be placed in an appendix.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As well as including relevant source code in your report, you should also submit a bundle with all your scripts and analysis code as a separate Blackboard submission.&lt;br /&gt;
&lt;br /&gt;
===On the use of AI tools===&lt;br /&gt;
The code you write for this experiment is assessed, and as per the [https://bb.imperial.ac.uk/bbcswebdav/pid-3344481-dt-content-rid-21115105_1/xid-21115105_1 department&#039;s guidelines on the use of AI], it is not acceptable to use generative AI tools to write computer code for this assignment.&lt;br /&gt;
&lt;br /&gt;
Writing computer programs yourself enhances your logical thinking and problem solving skills. Using generative AI tools to write your code makes you dumb. Don&#039;t choose to be dumb, don&#039;t use AI to write code for you.&lt;br /&gt;
&lt;br /&gt;
==Getting Help==&lt;br /&gt;
&lt;br /&gt;
The Graduate Teaching Assistants demonstrating this experiment are Fionn Carman and Lei Li. Demonstrators will be available in room 232A at the following times:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Demonstrator timetable&lt;br /&gt;
! !! Monday !! Tuesday !! Wednesday !! Thusrsday !! Friday&lt;br /&gt;
|-&lt;br /&gt;
| Morning || 10:00 - Experiment intro&amp;lt;br /&amp;gt; 10:00-13:00 - Li || 10:00-13:00 - Fionn|| || 10:00-12:00 - João || 10:00-13:00 - Fionn&lt;br /&gt;
|-&lt;br /&gt;
| Afternoon || 14:00-17:00 - Li|| 14:00-17:00 - Fionn|| ||  || 14:00-17:00 - Fionn&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you have questions outside these times, please use the Discussion Board on Blackboard.&lt;br /&gt;
&lt;br /&gt;
João and Giuseppe are the members of academic staff responsible for this experiment. You are welcome to address your questions and comments to them.&lt;br /&gt;
&lt;br /&gt;
==Structure of this Experiment==&lt;br /&gt;
&lt;br /&gt;
This experimental manual has been broken up into a number of subsections. Direct links to each of them may be found below. You should attempt them in order, and you should complete all of them to finish the experiment.&lt;br /&gt;
&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model|Introduction to the Ising model]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Calculating the energy and magnetisation|Calculating the energy and magnetisation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction to Monte Carlo simulation|Introduction to the Monte Carlo simulation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Accelerating the code|Accelerating the code]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of temperature|The effect of temperature]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of system size|The effect of system size]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Determining the heat capacity|Determining the heat capacity]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Locating the Curie temperature|Locating the Curie temperature]]&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822079</id>
		<title>Programming a 2D Ising Model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822079"/>
		<updated>2026-05-03T12:36:07Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;This is the Ising Model experiment (aka programming for simple simulations).&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;This is a core experiment for year 3 students on the Chemistry with Molecular Physics degree.&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
In this exercise, you are going to use the Python that you learned in the first year to write a code to perform Monte-Carlo simulations of the 2D [http://en.wikipedia.org/wiki/Ising_model Ising model], a set of spins on a lattice which is used to model ferromagnetic behaviour, and also to analyse the results of the simulation to find the heat capacity of the system and the Curie temperature &amp;amp;mdash; the temperature below which the system is able to maintain a spontaneous magnetisation.&lt;br /&gt;
&lt;br /&gt;
A more extensive introduction to the Ising Model will be given in the next page. This page gives some practical information about how the experiment. &lt;br /&gt;
&lt;br /&gt;
==Assessment==&lt;br /&gt;
At the end of this experiment you must submit a report, writing up your findings. Each section of the experiment has a number of tasks that you should complete, labelled &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK&amp;lt;/big&amp;gt;&#039;&#039;&#039;. If this is a mathematical exercise, your report should contain a short summary of the solution. If it is a graphical exercise, you should include the relevant image. Your report should explain briefly what you did in each stage of the experiment, and what your findings were.&lt;br /&gt;
&lt;br /&gt;
The report should be submitted as a PDF file to Turnitin, created with your favourite word processor or LaTeX, and should contain the annotated source code of the Python scripts that your write during the experiment. For clarity, code included in the report should be written in a monospaced font (e.g. Courier), which in LaTeX can be easily achieved by placing your code inside a &amp;lt;code&amp;gt;\texttt{}&amp;lt;/code&amp;gt; command. &#039;&#039;&#039;The code, except where relevant to discussion, can be placed in an appendix.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As well as including relevant source code in your report, you should also submit a bundle with all your scripts and analysis code as a separate Blackboard submission.&lt;br /&gt;
&lt;br /&gt;
===On the use of AI tools===&lt;br /&gt;
The code you write for this experiment is assessed, and as per the [https://bb.imperial.ac.uk/bbcswebdav/pid-3344481-dt-content-rid-21115105_1/xid-21115105_1 department&#039;s guidelines on the use of AI], it is not acceptable to use generative AI tools to write computer code for this assignment.&lt;br /&gt;
&lt;br /&gt;
Writing computer programs yourself enhances your logical thinking and problem solving skills. Using generative AI tools to write your code makes you dumb. Don&#039;t choose to be dumb, don&#039;t use AI to write code for you.&lt;br /&gt;
&lt;br /&gt;
==Getting Help==&lt;br /&gt;
&lt;br /&gt;
The Graduate Teaching Assistants demonstrating this experiment are Fionn Carman and Lei Li. Demonstrators will be available in room 232A at the following times:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Demonstrator timetable&lt;br /&gt;
! !! Monday !! Tuesday !! Wednesday !! Thusrsday !! Friday&lt;br /&gt;
|-&lt;br /&gt;
| Morning || 10:00 - Experiment intro&amp;lt;br /&amp;gt; 10:00-13:00 - Li || 10:00-13:00 - Fionn|| || 10:00-12:00 - João || 10:00-13:00 - Fionn&lt;br /&gt;
|-&lt;br /&gt;
| Afternoon || 14:00-17:00 - Li|| 14:00-17:00 - Fionn|| ||  || 14:00-17:00 - Fionn&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you have questions outside these times, please use the Discussion Board on Blackboard.&lt;br /&gt;
&lt;br /&gt;
João and Giuseppe are the members of academic staff responsible for this experiment. You are welcome to address your questions and comments to them.&lt;br /&gt;
&lt;br /&gt;
==Structure of this Experiment==&lt;br /&gt;
&lt;br /&gt;
This experimental manual has been broken up into a number of subsections. Direct links to each of them may be found below. You should attempt them in order, and you should complete all of them to finish the experiment.&lt;br /&gt;
&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model|Introduction to the Ising model]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Calculating the energy and magnetisation|Calculating the energy and magnetisation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction to Monte Carlo simulation|Introduction to the Monte Carlo simulation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Accelerating the code|Accelerating the code]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of temperature|The effect of temperature]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of system size|The effect of system size]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Determining the heat capacity|Determining the heat capacity]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Locating the Curie temperature|Locating the Curie temperature]]&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_Monte_Carlo_simulation&amp;diff=822078</id>
		<title>Programming a 2D Ising Model/Introduction to Monte Carlo simulation</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_Monte_Carlo_simulation&amp;diff=822078"/>
		<updated>2026-05-03T12:34:45Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the third section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Accelerating the code|4. Accelerating the code]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 3. Introduction to Monte Carlo simulation =&lt;br /&gt;
&lt;br /&gt;
==Average Energy and Magnetisation==&lt;br /&gt;
&lt;br /&gt;
Consider again the expressions for the average energy and magnetisation that we gave in the introduction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle M\right\rangle_T = \frac{1}{Z}\sum_\alpha M\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle E\right\rangle_T = \frac{1}{Z}\sum_\alpha E\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Imagine we want to evaluate these at a particular temperature, in a system of 100 spins.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3a&amp;lt;/big&amp;gt;: How many configurations are available to a system with 100 spins? To evaluate these expressions, we have to calculate the energy and magnetisation for each of these configurations, then perform the sum. Let&#039;s be very, very, generous, and say that we can analyse 1&amp;amp;times;10&amp;lt;sup&amp;gt;9&amp;lt;/sup&amp;gt; configurations per second with our computer. How long will it take to evaluate a single value of &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;amp;rang;&amp;lt;sub&amp;gt;&#039;&#039;T&#039;&#039;&amp;lt;/sub&amp;gt;?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Clearly, we need to try a cleverer approach.&lt;br /&gt;
&lt;br /&gt;
For the overwhelming majority of the possible configurations, the Boltzmann factor, &amp;lt;math&amp;gt;\exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\}&amp;lt;/math&amp;gt;, will be very small, and that state will contribute very little to the average value. We can save an enormous amount of time, and make this problem tractable, if we only consider the states whose Boltzmann factor is not so vanishingly small. This technique is called &#039;&#039;importance sampling&#039;&#039; &amp;amp;mdash; instead of sampling every point in phase space, we sample only those that the system is likely to occupy.&lt;br /&gt;
&lt;br /&gt;
==Importance Sampling==&lt;br /&gt;
&lt;br /&gt;
This is easily stated, of course, but how can we know which states contribute a lot to the average without actually calculating the energy? So far, we have been imagining generating random states of the system; that is to say, we have been choosing &#039;&#039;&amp;amp;alpha;&#039;&#039; from a uniform distribution in which no arrangement of spins is any more likely to be chosen than any other. If we instead had a method which generated states randomly from the probability distribution &amp;lt;math&amp;gt;\exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\}&amp;lt;/math&amp;gt;, then our problem would be solved. The method which allows us to do this was developed in the 1950s, and is called the [https://doi.org/10.1063/1.1699114 Metropolis Monte Carlo (MMC)] method, or more often simply &amp;quot;Monte Carlo simulation&amp;quot;. This was one of the major breakthroughs of the early days of computational science, and in the year 2000, the IEEE named among the [https://doi.org/10.1109/MCISE.2000.814652 &amp;quot;Top 10 Algorithms of the 20th Century&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
The algorithm is as follows:&lt;br /&gt;
&lt;br /&gt;
# Start from a given configuration of spins, &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039;, with energy &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
# Choose a single spin &#039;&#039;&#039;at random&#039;&#039;&#039;, and &amp;quot;flip&amp;quot; it, to generate a new configuration &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
# Calculate the energy of this new configuration, &#039;&#039;E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
# Calculate the energy difference between the states, &#039;&#039;&amp;amp;Delta;E = E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; - E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
## If the &#039;&#039;&amp;amp;Delta;E &amp;amp;le; 0&#039;&#039; (the spin flipping decreased the energy), then we &#039;&#039;&#039;accept&#039;&#039;&#039; the new configuration.&lt;br /&gt;
##* We set &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = &amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and then &#039;&#039;&#039;go to step 5&#039;&#039;&#039;.&lt;br /&gt;
## If &#039;&#039;&amp;amp;Delta;E &amp;amp;gt; 0&#039;&#039;, the spin flipping increased the energy. By considering the probability of observing the starting and final states, &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039; and &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, it can be shown that the probability for the transition between the two to occur is &amp;lt;math&amp;gt;\exp \left\{-\frac{\Delta E}{k_BT}\right\}&amp;lt;/math&amp;gt;. To ensure that we only accept this kind of spin flip with the correct probability, we use the following procedure:&lt;br /&gt;
### Choose a random number, &#039;&#039;R&#039;&#039;, in the interval [0,1).&lt;br /&gt;
### If &amp;lt;math&amp;gt;R \leq \exp \left\{-\frac{\Delta E}{k_BT}\right\}&amp;lt;/math&amp;gt;, we &#039;&#039;&#039;accept&#039;&#039;&#039; the new configuration.&lt;br /&gt;
###* We set &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = &amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and then &#039;&#039;&#039;go to step 5&#039;&#039;&#039;.&lt;br /&gt;
### If &amp;lt;math&amp;gt;R &amp;gt; \exp \left\{-\frac{\Delta E}{k_BT}\right\}&amp;lt;/math&amp;gt;, we &#039;&#039;&#039;reject&#039;&#039;&#039; the new configuration.&lt;br /&gt;
###* &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039; and &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039; are left unchanged. &#039;&#039;&#039;Go to step 5&#039;&#039;&#039;.&lt;br /&gt;
# Update the running averages of the energy and magnetisation.&lt;br /&gt;
# Monte Carlo &amp;quot;step&amp;quot; complete, &#039;&#039;&#039;return to step 2&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Step 4 is the key to the method. By accepting moves which increase the energy only with a certain probability, we ensure that the sequence of states that we generate is correctly distributed.  A transition which carries a very large energy penalty, &#039;&#039;&amp;amp;Delta;E&#039;&#039; is extremely unlikely to be selected. The use of random numbers in this step is the reason that the method acquired the name &amp;quot;Monte Carlo&amp;quot;, after the casinos located there!&lt;br /&gt;
&lt;br /&gt;
Note, unlike molecular dynamics, each step only moves a single atom. In Monte Carlo simulation, there is the notion of a cycle which is &#039;&#039;N&#039;&#039;&amp;lt;sub&amp;gt;spins&amp;lt;/sub&amp;gt;-steps, so that each spin on average has an attempted flip per cycle.&lt;br /&gt;
&lt;br /&gt;
If you are interested in the mathematical details of why this procedure generates a sequence of states distributed in the correct way, consult the Monte Carlo chapter of [https://library-search.imperial.ac.uk/permalink/f/o1297h/TN_cdi_askewsholts_vlebooks_9780080519982 &amp;quot;Understanding Molecular Simulation&amp;quot;], by Frenkel and Smit, but a discussion of this is not required for the experiment. Chapter 7 of [https://library-search.imperial.ac.uk/permalink/44IMP_INST/mek6kh/alma997227534401591 &amp;quot;Statistical Mechanics: Theory and Molecular Simulation&amp;quot;] by Tuckerman also gives a good description.&lt;br /&gt;
&lt;br /&gt;
==Modifying IsingLattice.py==&lt;br /&gt;
&lt;br /&gt;
Our IsingLattice object contains a stub function, &#039;&#039;&#039;&amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt;&#039;&#039;&#039;, which takes a single argument &amp;amp;mdash; the temperature at which we want to do the cycle. There are also attributes used to calculate the average energy and magnetisation and respective variances: &amp;lt;code&amp;gt;self.E_tally&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;self.E2_tally&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;self.M_tally&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;self.M2_tally&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;self.n_steps&amp;lt;/code&amp;gt;. You should use these values to keep a running sum of all the energies, squared energies, magnetisations, and squared magnetisations that your system has sampled, as well as the number of steps that have been performed. Finally, there is also a function &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt;, that takes no arguments and should return the average energy, squared energy, magnetisation, squared magnetisation and current step, &#039;&#039;&#039;in that order&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3b&amp;lt;/big&amp;gt;: Implement a single step of the above algorithm in the &amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt; function. This function should return the energy of your lattice and the magnetisation at the end of the cycle. Complete the &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt; function. This should return the following quantities whenever it is called: &amp;amp;lang;&#039;&#039;E&#039;&#039;&amp;amp;rang;, &amp;amp;lang;&#039;&#039;E&#039;&#039;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;amp;rang;, &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;amp;rang;, &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;amp;rang;, and &#039;&#039;N&#039;&#039;&amp;lt;sub&amp;gt;steps&amp;lt;/sub&amp;gt;, the number of Monte Carlo steps that have elapsed. Put your code for these functions in the report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note on units:&#039;&#039; In our simulation we will be using an unitless scaled energy &amp;lt;math&amp;gt;\tilde{E}=\frac{E}{J}&amp;lt;/math&amp;gt;, and a unitless scaled temperature &amp;lt;math&amp;gt;\tilde{T}=\frac{k_B T}{J}&amp;lt;/math&amp;gt;, where &#039;&#039;J&#039;&#039; is the interaction energy between spins discussed previously. The use of these scaled quantities in practice means that in the code we can set &#039;&#039;k&amp;lt;sub&amp;gt;B&amp;lt;/sub&amp;gt;&#039;&#039; to numerically equal to 1. Going forward we will drop the &amp;amp;tilde; from the notation of energy and temperature.&lt;br /&gt;
&lt;br /&gt;
You have been provided with a script, &#039;&#039;&#039;ILanim.py&#039;&#039;&#039;, which will use your &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; object to run a Monte Carlo simulation and display the output on the screen in real time. By default, this simulation will run an 8&amp;amp;times;8 lattice at &#039;&#039;T&#039;&#039;=1.0, which is below the critical temperature. You will see a representation of the lattice, and graphs of the energy and magnetisation &#039;&#039;&#039;per spin&#039;&#039;&#039;. When you close the window, the script will use your &#039;&#039;&#039;&amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt;&#039;&#039;&#039; function to print the average energy and magnetisation from the simulation. Note, you should run this script from the command line.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3c&amp;lt;/big&amp;gt;: If &#039;&#039;T&#039;&#039; &amp;amp;lt; &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;, do you expect a spontaneous magnetisation (i.e. do you expect &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;amp;rang; &amp;amp;ne; 0)? When the state of the simulation appears to stop changing (when you have reached an equilibrium state), use the controls to export the output to an SVG or PNG file and attach this to your report. You should also include the output from your statistics() function.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the third section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Accelerating the code|4. Accelerating the code]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_Monte_Carlo_simulation&amp;diff=822077</id>
		<title>Programming a 2D Ising Model/Introduction to Monte Carlo simulation</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_Monte_Carlo_simulation&amp;diff=822077"/>
		<updated>2026-05-03T12:32:35Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* Modifying IsingLattice.py */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the third section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Accelerating the code|4. Accelerating the code]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
==Average Energy and Magnetisation==&lt;br /&gt;
&lt;br /&gt;
Consider again the expressions for the average energy and magnetisation that we gave in the introduction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle M\right\rangle_T = \frac{1}{Z}\sum_\alpha M\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle E\right\rangle_T = \frac{1}{Z}\sum_\alpha E\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Imagine we want to evaluate these at a particular temperature, in a system of 100 spins.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3a&amp;lt;/big&amp;gt;: How many configurations are available to a system with 100 spins? To evaluate these expressions, we have to calculate the energy and magnetisation for each of these configurations, then perform the sum. Let&#039;s be very, very, generous, and say that we can analyse 1&amp;amp;times;10&amp;lt;sup&amp;gt;9&amp;lt;/sup&amp;gt; configurations per second with our computer. How long will it take to evaluate a single value of &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;amp;rang;&amp;lt;sub&amp;gt;&#039;&#039;T&#039;&#039;&amp;lt;/sub&amp;gt;?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Clearly, we need to try a cleverer approach.&lt;br /&gt;
&lt;br /&gt;
For the overwhelming majority of the possible configurations, the Boltzmann factor, &amp;lt;math&amp;gt;\exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\}&amp;lt;/math&amp;gt;, will be very small, and that state will contribute very little to the average value. We can save an enormous amount of time, and make this problem tractable, if we only consider the states whose Boltzmann factor is not so vanishingly small. This technique is called &#039;&#039;importance sampling&#039;&#039; &amp;amp;mdash; instead of sampling every point in phase space, we sample only those that the system is likely to occupy.&lt;br /&gt;
&lt;br /&gt;
==Importance Sampling==&lt;br /&gt;
&lt;br /&gt;
This is easily stated, of course, but how can we know which states contribute a lot to the average without actually calculating the energy? So far, we have been imagining generating random states of the system; that is to say, we have been choosing &#039;&#039;&amp;amp;alpha;&#039;&#039; from a uniform distribution in which no arrangement of spins is any more likely to be chosen than any other. If we instead had a method which generated states randomly from the probability distribution &amp;lt;math&amp;gt;\exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\}&amp;lt;/math&amp;gt;, then our problem would be solved. The method which allows us to do this was developed in the 1950s, and is called the [https://doi.org/10.1063/1.1699114 Metropolis Monte Carlo (MMC)] method, or more often simply &amp;quot;Monte Carlo simulation&amp;quot;. This was one of the major breakthroughs of the early days of computational science, and in the year 2000, the IEEE named among the [https://doi.org/10.1109/MCISE.2000.814652 &amp;quot;Top 10 Algorithms of the 20th Century&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
The algorithm is as follows:&lt;br /&gt;
&lt;br /&gt;
# Start from a given configuration of spins, &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039;, with energy &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
# Choose a single spin &#039;&#039;&#039;at random&#039;&#039;&#039;, and &amp;quot;flip&amp;quot; it, to generate a new configuration &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
# Calculate the energy of this new configuration, &#039;&#039;E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
# Calculate the energy difference between the states, &#039;&#039;&amp;amp;Delta;E = E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; - E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
## If the &#039;&#039;&amp;amp;Delta;E &amp;amp;le; 0&#039;&#039; (the spin flipping decreased the energy), then we &#039;&#039;&#039;accept&#039;&#039;&#039; the new configuration.&lt;br /&gt;
##* We set &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = &amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and then &#039;&#039;&#039;go to step 5&#039;&#039;&#039;.&lt;br /&gt;
## If &#039;&#039;&amp;amp;Delta;E &amp;amp;gt; 0&#039;&#039;, the spin flipping increased the energy. By considering the probability of observing the starting and final states, &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039; and &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, it can be shown that the probability for the transition between the two to occur is &amp;lt;math&amp;gt;\exp \left\{-\frac{\Delta E}{k_BT}\right\}&amp;lt;/math&amp;gt;. To ensure that we only accept this kind of spin flip with the correct probability, we use the following procedure:&lt;br /&gt;
### Choose a random number, &#039;&#039;R&#039;&#039;, in the interval [0,1).&lt;br /&gt;
### If &amp;lt;math&amp;gt;R \leq \exp \left\{-\frac{\Delta E}{k_BT}\right\}&amp;lt;/math&amp;gt;, we &#039;&#039;&#039;accept&#039;&#039;&#039; the new configuration.&lt;br /&gt;
###* We set &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = &amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and then &#039;&#039;&#039;go to step 5&#039;&#039;&#039;.&lt;br /&gt;
### If &amp;lt;math&amp;gt;R &amp;gt; \exp \left\{-\frac{\Delta E}{k_BT}\right\}&amp;lt;/math&amp;gt;, we &#039;&#039;&#039;reject&#039;&#039;&#039; the new configuration.&lt;br /&gt;
###* &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039; and &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039; are left unchanged. &#039;&#039;&#039;Go to step 5&#039;&#039;&#039;.&lt;br /&gt;
# Update the running averages of the energy and magnetisation.&lt;br /&gt;
# Monte Carlo &amp;quot;step&amp;quot; complete, &#039;&#039;&#039;return to step 2&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Step 4 is the key to the method. By accepting moves which increase the energy only with a certain probability, we ensure that the sequence of states that we generate is correctly distributed.  A transition which carries a very large energy penalty, &#039;&#039;&amp;amp;Delta;E&#039;&#039; is extremely unlikely to be selected. The use of random numbers in this step is the reason that the method acquired the name &amp;quot;Monte Carlo&amp;quot;, after the casinos located there!&lt;br /&gt;
&lt;br /&gt;
Note, unlike molecular dynamics, each step only moves a single atom. In Monte Carlo simulation, there is the notion of a cycle which is &#039;&#039;N&#039;&#039;&amp;lt;sub&amp;gt;spins&amp;lt;/sub&amp;gt;-steps, so that each spin on average has an attempted flip per cycle.&lt;br /&gt;
&lt;br /&gt;
If you are interested in the mathematical details of why this procedure generates a sequence of states distributed in the correct way, consult the Monte Carlo chapter of [https://library-search.imperial.ac.uk/permalink/f/o1297h/TN_cdi_askewsholts_vlebooks_9780080519982 &amp;quot;Understanding Molecular Simulation&amp;quot;], by Frenkel and Smit, but a discussion of this is not required for the experiment. Chapter 7 of [https://library-search.imperial.ac.uk/permalink/44IMP_INST/mek6kh/alma997227534401591 &amp;quot;Statistical Mechanics: Theory and Molecular Simulation&amp;quot;] by Tuckerman also gives a good description.&lt;br /&gt;
&lt;br /&gt;
==Modifying IsingLattice.py==&lt;br /&gt;
&lt;br /&gt;
Our IsingLattice object contains a stub function, &#039;&#039;&#039;&amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt;&#039;&#039;&#039;, which takes a single argument &amp;amp;mdash; the temperature at which we want to do the cycle. There are also attributes used to calculate the average energy and magnetisation and respective variances: &amp;lt;code&amp;gt;self.E_tally&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;self.E2_tally&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;self.M_tally&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;self.M2_tally&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;self.n_steps&amp;lt;/code&amp;gt;. You should use these values to keep a running sum of all the energies, squared energies, magnetisations, and squared magnetisations that your system has sampled, as well as the number of steps that have been performed. Finally, there is also a function &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt;, that takes no arguments and should return the average energy, squared energy, magnetisation, squared magnetisation and current step, &#039;&#039;&#039;in that order&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3b&amp;lt;/big&amp;gt;: Implement a single step of the above algorithm in the &amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt; function. This function should return the energy of your lattice and the magnetisation at the end of the cycle. Complete the &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt; function. This should return the following quantities whenever it is called: &amp;amp;lang;&#039;&#039;E&#039;&#039;&amp;amp;rang;, &amp;amp;lang;&#039;&#039;E&#039;&#039;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;amp;rang;, &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;amp;rang;, &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;amp;rang;, and &#039;&#039;N&#039;&#039;&amp;lt;sub&amp;gt;steps&amp;lt;/sub&amp;gt;, the number of Monte Carlo steps that have elapsed. Put your code for these functions in the report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note on units:&#039;&#039; In our simulation we will be using an unitless scaled energy &amp;lt;math&amp;gt;\tilde{E}=\frac{E}{J}&amp;lt;/math&amp;gt;, and a unitless scaled temperature &amp;lt;math&amp;gt;\tilde{T}=\frac{k_B T}{J}&amp;lt;/math&amp;gt;, where &#039;&#039;J&#039;&#039; is the interaction energy between spins discussed previously. The use of these scaled quantities in practice means that in the code we can set &#039;&#039;k&amp;lt;sub&amp;gt;B&amp;lt;/sub&amp;gt;&#039;&#039; to numerically equal to 1. Going forward we will drop the &amp;amp;tilde; from the notation of energy and temperature.&lt;br /&gt;
&lt;br /&gt;
You have been provided with a script, &#039;&#039;&#039;ILanim.py&#039;&#039;&#039;, which will use your &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; object to run a Monte Carlo simulation and display the output on the screen in real time. By default, this simulation will run an 8&amp;amp;times;8 lattice at &#039;&#039;T&#039;&#039;=1.0, which is below the critical temperature. You will see a representation of the lattice, and graphs of the energy and magnetisation &#039;&#039;&#039;per spin&#039;&#039;&#039;. When you close the window, the script will use your &#039;&#039;&#039;&amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt;&#039;&#039;&#039; function to print the average energy and magnetisation from the simulation. Note, you should run this script from the command line.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3c&amp;lt;/big&amp;gt;: If &#039;&#039;T&#039;&#039; &amp;amp;lt; &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;, do you expect a spontaneous magnetisation (i.e. do you expect &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;amp;rang; &amp;amp;ne; 0)? When the state of the simulation appears to stop changing (when you have reached an equilibrium state), use the controls to export the output to an SVG or PNG file and attach this to your report. You should also include the output from your statistics() function.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the third section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Accelerating the code|4. Accelerating the code]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822076</id>
		<title>Programming a 2D Ising Model/Introduction to the Ising model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822076"/>
		<updated>2026-05-03T11:36:42Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page: [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 1. Introduction to the Ising model =&lt;br /&gt;
&lt;br /&gt;
== The Ising model ==&lt;br /&gt;
The Ising model is a simple physical model proposed in the 1920s to understand the behaviour of ferromagnets. In most materials, the magnetic dipoles of the atoms have no preferred orientation, and the bulk material has no net magnetic moment. In certain materials, however, there is preferential alignment of the magnetic dipoles along certain directions. These materials, such as iron, exhibit an overall magnetic moment, and are called ferromagnetic.&lt;br /&gt;
&lt;br /&gt;
The phenomenon is based on competition between two physical effects &amp;amp;mdash; energy minimisation and entropy maximisation. On the one hand, parallel alignment of magnetic moments is energetically favourable. On the other hand, aligning the system in this way reduces the entropy.&lt;br /&gt;
&lt;br /&gt;
In the Ising model, we consider a collection of spins, &#039;&#039;s&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;&#039;&#039;, each of which can either have the value &amp;quot;up&amp;quot; (+1) or &amp;quot;down&amp;quot; (-1), arranged on a lattice. In one dimension, this takes the form of a &amp;quot;chain&amp;quot; of adjacent spins, &#039;&#039;s&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039; to &#039;&#039;s&amp;lt;sub&amp;gt;N&amp;lt;/sub&amp;gt;&#039;&#039;. In two dimensions we have a grid of cells, each of which contains one spin. In three dimensions, the system is a cuboid, and so on. The arrangements for 1, 2 and 3 dimensions are illustrated in &#039;&#039;&#039;figure 1&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingSketch.png|300px|thumb|right|&#039;&#039;&#039;Figure 1&#039;&#039;&#039;: Illustration of an Ising lattice in one (N=5), two (N=5&amp;amp;times;5), and three (N=5&amp;amp;times;5&amp;amp;times;5) dimensions. Red cells indicate the &amp;quot;up&amp;quot; spin&amp;quot;, and blue cells indicate the &amp;quot;down&amp;quot; spin.]]&lt;br /&gt;
&lt;br /&gt;
The rules of the model are simple:&lt;br /&gt;
&lt;br /&gt;
* When no magnetic field is applied, the only energetic contribution comes from the interaction between spins in &#039;&#039;adjacent&#039;&#039; lattice cells&lt;br /&gt;
* The total interaction energy is defined as &amp;lt;math&amp;gt;- \frac{1}{2} J \sum_i^N \sum_{j\  \in\  \mathrm{neighbours}\left(i\right)} s_i s_j&amp;lt;/math&amp;gt;, where &#039;&#039;J&#039;&#039; is a constant which controls the strength of interaction and the notation &#039;&#039;j&#039;&#039;&amp;amp;nbsp;&amp;amp;in;&amp;amp;nbsp;neighbours(&#039;&#039;i&#039;&#039;) indicates that spin &#039;&#039;j&#039;&#039; must lie in a lattice cell adjacent to spin &#039;&#039;i&#039;&#039;. The factor of one half is included to make sure that we do not count each spin-spin interaction twice.&lt;br /&gt;
* Periodic boundary conditions are applied. In other words, the &amp;quot;final&amp;quot; spin in a particular direction is considered to be adjacent to the &amp;quot;first&amp;quot; spin in that direction. In &#039;&#039;&#039;figure 2&#039;&#039;&#039;, for example, cell 1 has neighbour interactions with cells 2, 3, 4, and 7, while cell 9 interacts with cells 3, 6, 7, and 8.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingNumberedCell.png|300px|thumb|right|&#039;&#039;&#039;Figure 2&#039;&#039;&#039;: Illustration of a 2D Ising lattice, with numbered cells to indicate the neighbour interactions.]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1a&amp;lt;/big&amp;gt;: Show that the lowest possible energy for the Ising model (with &#039;&#039;J&#039;&#039;&amp;amp;gt;0) is &#039;&#039;E&#039;&#039;&amp;amp;nbsp;=&amp;amp;nbsp;-&#039;&#039;DNJ&#039;&#039;, where &#039;&#039;D&#039;&#039; is the number of dimensions and &#039;&#039;N&#039;&#039; is the total number of spins. What is the multiplicity of this state? Calculate its entropy.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Phase Transitions==&lt;br /&gt;
&lt;br /&gt;
The Ising model is interesting because it is one of the simplest physical models to display a phase transition (so long as we are in two dimensions or more). The temperature of the system controls the balance between the energetic driving force, which wants the system to adopt the lowest energy configuration that you imagined in the previous section, and the entropic driving force, which seeks to maximise the number of configurations available to the system.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1b&amp;lt;/big&amp;gt;: Imagine that the system is in the lowest energy configuration. To move to a different state, one of the spins must spontaneously change direction (&amp;quot;flip&amp;quot;). What is the change in energy if this happens (&#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000)? How much entropy does the system gain by doing so?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
At low temperatures, little thermal energy is available to overcome such energy barriers, and we expect the system to adopt the lowest energy (the energetic driving force will dominate). Under these conditions, we expect a large number of parallel spins, and we can characterise this by considering the total &#039;&#039;magnetisation&#039;&#039; of the system: &amp;lt;math&amp;gt;M = \sum_i s_i&amp;lt;/math&amp;gt;. At higher temperatures, however, enough thermal energy will be available that spins can flip relatively freely. Under these conditions, the entropic driving force should dominate. The transition temperature between the two regimes is called the &#039;&#039;Curie temperature&#039;&#039;, &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;. Below &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;, we observe the highly ordered magnetised phase, while above &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039; a disordered, demagnetised, phase emerges.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1c&amp;lt;/big&amp;gt;: Calculate the magnetisation of the 1D and 2D lattices in figure 1. What magnetisation would you expect to observe for an Ising lattice with &#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000 at absolute zero?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We are interested, therefore, in determining the magnetisation &#039;&#039;M&#039;&#039;, and energy &#039;&#039;E&#039;&#039;, of the system as functions of temperature &#039;&#039;T&#039;&#039;. We can write statistical mechanical equations for these quantities:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle M\right\rangle_T = \frac{1}{Z}\sum_\alpha M\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle E\right\rangle_T = \frac{1}{Z}\sum_\alpha E\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &#039;&#039;&amp;amp;alpha;&#039;&#039; is used as a shorthand to represent all spins in the system, and &#039;&#039;Z&#039;&#039; is the partition function,&lt;br /&gt;
&amp;lt;math&amp;gt;Z = \sum_\alpha \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It was discovered relatively quickly after the model was first proposed that the partition function in the one dimensional case can be solved analytically (though doing so is beyond the scope of this experiment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Z\left(T, N\right) = \left[2\cosh\left(\frac{J}{k_BT}\right)\right]^N&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Much later, [http://en.wikipedia.org/wiki/Lars_Onsager Lars Onsager] established that the two dimensional partition function can also be found analytically, though the mathematics is significantly more involved and the resulting expression is correspondingly much more complicated. In dimensions greater than two, no analytical solution is known.&lt;br /&gt;
&lt;br /&gt;
Luckily for us, the problem can instead be tackled by numerical methods, and it is this that will be the focus of the experiment. We will discuss how the equations for &#039;&#039;M&#039;&#039; and &#039;&#039;E&#039;&#039; can be solved, but first we must set up a Python script to model the lattice.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page:  [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_Monte_Carlo_simulation&amp;diff=822075</id>
		<title>Programming a 2D Ising Model/Introduction to Monte Carlo simulation</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_Monte_Carlo_simulation&amp;diff=822075"/>
		<updated>2026-05-03T11:34:56Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* Modifying IsingLattice.py */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the third section of the Ising model experiment. You can return to the previous page, [[Programming a 2D Ising Model/Calculating the energy and magnetisation|Calculating the energy and magnetisation]], or jump ahead to the next section, [[Programming a 2D Ising Model/Accelerating the code|Accelerating the code]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
==Average Energy and Magnetisation==&lt;br /&gt;
&lt;br /&gt;
Consider again the expressions for the average energy and magnetisation that we gave in the introduction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle M\right\rangle_T = \frac{1}{Z}\sum_\alpha M\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle E\right\rangle_T = \frac{1}{Z}\sum_\alpha E\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Imagine we want to evaluate these at a particular temperature, in a system of 100 spins.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3a&amp;lt;/big&amp;gt;: How many configurations are available to a system with 100 spins? To evaluate these expressions, we have to calculate the energy and magnetisation for each of these configurations, then perform the sum. Let&#039;s be very, very, generous, and say that we can analyse 1&amp;amp;times;10&amp;lt;sup&amp;gt;9&amp;lt;/sup&amp;gt; configurations per second with our computer. How long will it take to evaluate a single value of &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;amp;rang;&amp;lt;sub&amp;gt;&#039;&#039;T&#039;&#039;&amp;lt;/sub&amp;gt;?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Clearly, we need to try a cleverer approach.&lt;br /&gt;
&lt;br /&gt;
For the overwhelming majority of the possible configurations, the Boltzmann factor, &amp;lt;math&amp;gt;\exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\}&amp;lt;/math&amp;gt;, will be very small, and that state will contribute very little to the average value. We can save an enormous amount of time, and make this problem tractable, if we only consider the states whose Boltzmann factor is not so vanishingly small. This technique is called &#039;&#039;importance sampling&#039;&#039; &amp;amp;mdash; instead of sampling every point in phase space, we sample only those that the system is likely to occupy.&lt;br /&gt;
&lt;br /&gt;
==Importance Sampling==&lt;br /&gt;
&lt;br /&gt;
This is easily stated, of course, but how can we know which states contribute a lot to the average without actually calculating the energy? So far, we have been imagining generating random states of the system; that is to say, we have been choosing &#039;&#039;&amp;amp;alpha;&#039;&#039; from a uniform distribution in which no arrangement of spins is any more likely to be chosen than any other. If we instead had a method which generated states randomly from the probability distribution &amp;lt;math&amp;gt;\exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\}&amp;lt;/math&amp;gt;, then our problem would be solved. The method which allows us to do this was developed in the 1950s, and is called the [https://doi.org/10.1063/1.1699114 Metropolis Monte Carlo (MMC)] method, or more often simply &amp;quot;Monte Carlo simulation&amp;quot;. This was one of the major breakthroughs of the early days of computational science, and in the year 2000, the IEEE named among the [https://doi.org/10.1109/MCISE.2000.814652 &amp;quot;Top 10 Algorithms of the 20th Century&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
The algorithm is as follows:&lt;br /&gt;
&lt;br /&gt;
# Start from a given configuration of spins, &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039;, with energy &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
# Choose a single spin &#039;&#039;&#039;at random&#039;&#039;&#039;, and &amp;quot;flip&amp;quot; it, to generate a new configuration &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
# Calculate the energy of this new configuration, &#039;&#039;E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
# Calculate the energy difference between the states, &#039;&#039;&amp;amp;Delta;E = E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; - E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039;.&lt;br /&gt;
## If the &#039;&#039;&amp;amp;Delta;E &amp;amp;le; 0&#039;&#039; (the spin flipping decreased the energy), then we &#039;&#039;&#039;accept&#039;&#039;&#039; the new configuration.&lt;br /&gt;
##* We set &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = &amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and then &#039;&#039;&#039;go to step 5&#039;&#039;&#039;.&lt;br /&gt;
## If &#039;&#039;&amp;amp;Delta;E &amp;amp;gt; 0&#039;&#039;, the spin flipping increased the energy. By considering the probability of observing the starting and final states, &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039; and &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, it can be shown that the probability for the transition between the two to occur is &amp;lt;math&amp;gt;\exp \left\{-\frac{\Delta E}{k_BT}\right\}&amp;lt;/math&amp;gt;. To ensure that we only accept this kind of spin flip with the correct probability, we use the following procedure:&lt;br /&gt;
### Choose a random number, &#039;&#039;R&#039;&#039;, in the interval [0,1).&lt;br /&gt;
### If &amp;lt;math&amp;gt;R \leq \exp \left\{-\frac{\Delta E}{k_BT}\right\}&amp;lt;/math&amp;gt;, we &#039;&#039;&#039;accept&#039;&#039;&#039; the new configuration.&lt;br /&gt;
###* We set &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = &amp;amp;alpha;&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; = E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039;, and then &#039;&#039;&#039;go to step 5&#039;&#039;&#039;.&lt;br /&gt;
### If &amp;lt;math&amp;gt;R &amp;gt; \exp \left\{-\frac{\Delta E}{k_BT}\right\}&amp;lt;/math&amp;gt;, we &#039;&#039;&#039;reject&#039;&#039;&#039; the new configuration.&lt;br /&gt;
###* &#039;&#039;&amp;amp;alpha;&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039; and &#039;&#039;E&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;&#039;&#039; are left unchanged. &#039;&#039;&#039;Go to step 5&#039;&#039;&#039;.&lt;br /&gt;
# Update the running averages of the energy and magnetisation.&lt;br /&gt;
# Monte Carlo &amp;quot;step&amp;quot; complete, &#039;&#039;&#039;return to step 2&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Step 4 is the key to the method. By accepting moves which increase the energy only with a certain probability, we ensure that the sequence of states that we generate is correctly distributed.  A transition which carries a very large energy penalty, &#039;&#039;&amp;amp;Delta;E&#039;&#039; is extremely unlikely to be selected. The use of random numbers in this step is the reason that the method acquired the name &amp;quot;Monte Carlo&amp;quot;, after the casinos located there!&lt;br /&gt;
&lt;br /&gt;
Note, unlike molecular dynamics, each step only moves a single atom. In Monte Carlo simulation, there is the notion of a cycle which is &#039;&#039;N&#039;&#039;&amp;lt;sub&amp;gt;spins&amp;lt;/sub&amp;gt;-steps, so that each spin on average has an attempted flip per cycle.&lt;br /&gt;
&lt;br /&gt;
If you are interested in the mathematical details of why this procedure generates a sequence of states distributed in the correct way, consult the Monte Carlo chapter of [https://library-search.imperial.ac.uk/permalink/f/o1297h/TN_cdi_askewsholts_vlebooks_9780080519982 &amp;quot;Understanding Molecular Simulation&amp;quot;], by Frenkel and Smit, but a discussion of this is not required for the experiment. Chapter 7 of [https://library-search.imperial.ac.uk/permalink/44IMP_INST/mek6kh/alma997227534401591 &amp;quot;Statistical Mechanics: Theory and Molecular Simulation&amp;quot;] by Tuckerman also gives a good description.&lt;br /&gt;
&lt;br /&gt;
==Modifying IsingLattice.py==&lt;br /&gt;
&lt;br /&gt;
Our IsingLattice object contains a stub function, &#039;&#039;&#039;&amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt;&#039;&#039;&#039;, which takes a single argument &amp;amp;mdash; the temperature at which we want to do the cycle. There are also attributes used to calculate the average energy and magnetisation and respective variances: &amp;lt;code&amp;gt;self.E_tally&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;self.E2_tally&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;self.M_tally&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;self.M2_tally&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;self.n_steps&amp;lt;/code&amp;gt;. You should use these values to keep a running sum of all the energies, squared energies, magnetisations, and squared magnetisations that your system has sampled, as well as the number of steps that have been performed. Finally, there is also a function &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt;, that takes no arguments and should return the average energy, squared energy, magnetisation, squared magnetisation and current step, &#039;&#039;&#039;in that order&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3b&amp;lt;/big&amp;gt;: Implement a single step of the above algorithm in the &amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt; function. This function should return the energy of your lattice and the magnetisation at the end of the cycle. Complete the &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt; function. This should return the following quantities whenever it is called: &amp;amp;lang;&#039;&#039;E&#039;&#039;&amp;amp;rang;, &amp;amp;lang;&#039;&#039;E&#039;&#039;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;amp;rang;, &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;amp;rang;, &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&amp;amp;rang;, and &#039;&#039;N&#039;&#039;&amp;lt;sub&amp;gt;steps&amp;lt;/sub&amp;gt;, the number of Monte Carlo steps that have elapsed. Put your code for these functions in the report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note on units:&#039;&#039; In our simulation we will be using an unitless scaled energy &amp;lt;math&amp;gt;\tilde{E}=\frac{E}{J}&amp;lt;/math&amp;gt;, and a unitless scaled temperature &amp;lt;math&amp;gt;\tilde{T}=\frac{k_B T}{J}&amp;lt;/math&amp;gt;, where &#039;&#039;J&#039;&#039; is the interaction energy between spins discussed previously. The use of these scaled quantities in practice means that in the code we can set &#039;&#039;k&amp;lt;sub&amp;gt;B&amp;lt;/sub&amp;gt;&#039;&#039; to numerically equal to 1. Going forward we will drop the &amp;amp;tilde; from the notation of energy and temperature.&lt;br /&gt;
&lt;br /&gt;
You have been provided with a script, &#039;&#039;&#039;ILanim.py&#039;&#039;&#039;, which will use your &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; object to run a Monte Carlo simulation and display the output on the screen in real time. By default, this simulation will run an 8&amp;amp;times;8 lattice at &#039;&#039;T&#039;&#039;=1.0, which is below the critical temperature. You will see a representation of the lattice, and graphs of the energy and magnetisation &#039;&#039;&#039;per spin&#039;&#039;&#039;. When you close the window, the script will use your &#039;&#039;&#039;&amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt;&#039;&#039;&#039; function to print the average energy and magnetisation from the simulation. Note, you should run this script from the command line.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3c&amp;lt;/big&amp;gt;: If &#039;&#039;T&#039;&#039; &amp;amp;lt; &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;, do you expect a spontaneous magnetisation (i.e. do you expect &amp;amp;lang;&#039;&#039;M&#039;&#039;&amp;amp;rang; &amp;amp;ne; 0)? When the state of the simulation appears to stop changing (when you have reached an equilibrium state), use the controls to export the output to an SVG or PNG file and attach this to your report. You should also include the output from your statistics() function.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the third section of the Ising model experiment. You can return to the previous page, [[Programming a 2D Ising Model/Calculating the energy and magnetisation|Calculating the energy and magnetisation]], or jump ahead to the&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Accelerating the code|4. Accelerating the code]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822074</id>
		<title>Programming a 2D Ising Model/Introduction to the Ising model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822074"/>
		<updated>2026-05-03T11:33:53Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* Phase Transitions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment. You can return to the [[Programming_a_2D_Ising_Model|introduction page]], or jump ahead to the next section, [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 1. Introduction to the Ising model =&lt;br /&gt;
&lt;br /&gt;
== The Ising model ==&lt;br /&gt;
The Ising model is a simple physical model proposed in the 1920s to understand the behaviour of ferromagnets. In most materials, the magnetic dipoles of the atoms have no preferred orientation, and the bulk material has no net magnetic moment. In certain materials, however, there is preferential alignment of the magnetic dipoles along certain directions. These materials, such as iron, exhibit an overall magnetic moment, and are called ferromagnetic.&lt;br /&gt;
&lt;br /&gt;
The phenomenon is based on competition between two physical effects &amp;amp;mdash; energy minimisation and entropy maximisation. On the one hand, parallel alignment of magnetic moments is energetically favourable. On the other hand, aligning the system in this way reduces the entropy.&lt;br /&gt;
&lt;br /&gt;
In the Ising model, we consider a collection of spins, &#039;&#039;s&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;&#039;&#039;, each of which can either have the value &amp;quot;up&amp;quot; (+1) or &amp;quot;down&amp;quot; (-1), arranged on a lattice. In one dimension, this takes the form of a &amp;quot;chain&amp;quot; of adjacent spins, &#039;&#039;s&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039; to &#039;&#039;s&amp;lt;sub&amp;gt;N&amp;lt;/sub&amp;gt;&#039;&#039;. In two dimensions we have a grid of cells, each of which contains one spin. In three dimensions, the system is a cuboid, and so on. The arrangements for 1, 2 and 3 dimensions are illustrated in &#039;&#039;&#039;figure 1&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingSketch.png|300px|thumb|right|&#039;&#039;&#039;Figure 1&#039;&#039;&#039;: Illustration of an Ising lattice in one (N=5), two (N=5&amp;amp;times;5), and three (N=5&amp;amp;times;5&amp;amp;times;5) dimensions. Red cells indicate the &amp;quot;up&amp;quot; spin&amp;quot;, and blue cells indicate the &amp;quot;down&amp;quot; spin.]]&lt;br /&gt;
&lt;br /&gt;
The rules of the model are simple:&lt;br /&gt;
&lt;br /&gt;
* When no magnetic field is applied, the only energetic contribution comes from the interaction between spins in &#039;&#039;adjacent&#039;&#039; lattice cells&lt;br /&gt;
* The total interaction energy is defined as &amp;lt;math&amp;gt;- \frac{1}{2} J \sum_i^N \sum_{j\  \in\  \mathrm{neighbours}\left(i\right)} s_i s_j&amp;lt;/math&amp;gt;, where &#039;&#039;J&#039;&#039; is a constant which controls the strength of interaction and the notation &#039;&#039;j&#039;&#039;&amp;amp;nbsp;&amp;amp;in;&amp;amp;nbsp;neighbours(&#039;&#039;i&#039;&#039;) indicates that spin &#039;&#039;j&#039;&#039; must lie in a lattice cell adjacent to spin &#039;&#039;i&#039;&#039;. The factor of one half is included to make sure that we do not count each spin-spin interaction twice.&lt;br /&gt;
* Periodic boundary conditions are applied. In other words, the &amp;quot;final&amp;quot; spin in a particular direction is considered to be adjacent to the &amp;quot;first&amp;quot; spin in that direction. In &#039;&#039;&#039;figure 2&#039;&#039;&#039;, for example, cell 1 has neighbour interactions with cells 2, 3, 4, and 7, while cell 9 interacts with cells 3, 6, 7, and 8.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingNumberedCell.png|300px|thumb|right|&#039;&#039;&#039;Figure 2&#039;&#039;&#039;: Illustration of a 2D Ising lattice, with numbered cells to indicate the neighbour interactions.]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1a&amp;lt;/big&amp;gt;: Show that the lowest possible energy for the Ising model (with &#039;&#039;J&#039;&#039;&amp;amp;gt;0) is &#039;&#039;E&#039;&#039;&amp;amp;nbsp;=&amp;amp;nbsp;-&#039;&#039;DNJ&#039;&#039;, where &#039;&#039;D&#039;&#039; is the number of dimensions and &#039;&#039;N&#039;&#039; is the total number of spins. What is the multiplicity of this state? Calculate its entropy.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Phase Transitions==&lt;br /&gt;
&lt;br /&gt;
The Ising model is interesting because it is one of the simplest physical models to display a phase transition (so long as we are in two dimensions or more). The temperature of the system controls the balance between the energetic driving force, which wants the system to adopt the lowest energy configuration that you imagined in the previous section, and the entropic driving force, which seeks to maximise the number of configurations available to the system.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1b&amp;lt;/big&amp;gt;: Imagine that the system is in the lowest energy configuration. To move to a different state, one of the spins must spontaneously change direction (&amp;quot;flip&amp;quot;). What is the change in energy if this happens (&#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000)? How much entropy does the system gain by doing so?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
At low temperatures, little thermal energy is available to overcome such energy barriers, and we expect the system to adopt the lowest energy (the energetic driving force will dominate). Under these conditions, we expect a large number of parallel spins, and we can characterise this by considering the total &#039;&#039;magnetisation&#039;&#039; of the system: &amp;lt;math&amp;gt;M = \sum_i s_i&amp;lt;/math&amp;gt;. At higher temperatures, however, enough thermal energy will be available that spins can flip relatively freely. Under these conditions, the entropic driving force should dominate. The transition temperature between the two regimes is called the &#039;&#039;Curie temperature&#039;&#039;, &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;. Below &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;, we observe the highly ordered magnetised phase, while above &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039; a disordered, demagnetised, phase emerges.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1c&amp;lt;/big&amp;gt;: Calculate the magnetisation of the 1D and 2D lattices in figure 1. What magnetisation would you expect to observe for an Ising lattice with &#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000 at absolute zero?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We are interested, therefore, in determining the magnetisation &#039;&#039;M&#039;&#039;, and energy &#039;&#039;E&#039;&#039;, of the system as functions of temperature &#039;&#039;T&#039;&#039;. We can write statistical mechanical equations for these quantities:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle M\right\rangle_T = \frac{1}{Z}\sum_\alpha M\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle E\right\rangle_T = \frac{1}{Z}\sum_\alpha E\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &#039;&#039;&amp;amp;alpha;&#039;&#039; is used as a shorthand to represent all spins in the system, and &#039;&#039;Z&#039;&#039; is the partition function,&lt;br /&gt;
&amp;lt;math&amp;gt;Z = \sum_\alpha \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It was discovered relatively quickly after the model was first proposed that the partition function in the one dimensional case can be solved analytically (though doing so is beyond the scope of this experiment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Z\left(T, N\right) = \left[2\cosh\left(\frac{J}{k_BT}\right)\right]^N&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Much later, [http://en.wikipedia.org/wiki/Lars_Onsager Lars Onsager] established that the two dimensional partition function can also be found analytically, though the mathematics is significantly more involved and the resulting expression is correspondingly much more complicated. In dimensions greater than two, no analytical solution is known.&lt;br /&gt;
&lt;br /&gt;
Luckily for us, the problem can instead be tackled by numerical methods, and it is this that will be the focus of the experiment. We will discuss how the equations for &#039;&#039;M&#039;&#039; and &#039;&#039;E&#039;&#039; can be solved, but first we must set up a Python script to model the lattice.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Main page:  [[Programming a 2D Ising Model]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822073</id>
		<title>Programming a 2D Ising Model/Calculating the energy and magnetisation</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822073"/>
		<updated>2026-05-03T11:32:00Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* Testing the files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment. You can return to the previous page, [[Programming a 2D Ising Model/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|Introduction to Monte Carlo simulation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 2. Calculating the energy and magnetisation =&lt;br /&gt;
&lt;br /&gt;
==Getting the files for the experiment==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Various scripts have been prepared to assist you with this experiment, and you can obtain them by downloading the files from the Blackboard.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We recommend you open the extracted folder with JupyterLab, which has an integrated terminal where you can run the  simulation scripts.&lt;br /&gt;
&lt;br /&gt;
==Modifying the files==&lt;br /&gt;
&lt;br /&gt;
The file &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; contains a Python class called IsingLattice. This class will be the basis for our model of the system, and is restricted to modelling the two dimensional case. It contains a number of stub methods that you will complete as you work through the experiment.&lt;br /&gt;
&lt;br /&gt;
===A note about Python Classes===&lt;br /&gt;
&lt;br /&gt;
The file IsingLattice.py makes use of a Python feature called &#039;&#039;class&#039;&#039;. You should be familiar with the idea that all Python &#039;&#039;objects&#039;&#039; have an associated &#039;&#039;type&#039;&#039; -- you have already encountered objects such as integers, string, lists, and NumPy arrays. Classes allow us to define new types of object. In this case, we define a type called &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
class IsingLattice:&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each class is allowed to have certain attributes and functions (known as methods) associated with it. We can see, for example, that each &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; object has the methods &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt; (the method &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt; will be explained shortly). Each of these methods takes a special first argument called self, which is a variable pointing to the current copy of IsingLattice. To use the new IsingLattice object that we have defined, we use code like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import IsingLattice&lt;br /&gt;
&lt;br /&gt;
il = IsingLattice(5, 5) #create an IsingLattice object with 5 row and 5 columns&lt;br /&gt;
&lt;br /&gt;
energy = il.energy() #call the energy() method of our IsingLattice object&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all attributes and methods belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the &amp;lt;code&amp;gt;montecarlostep()&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the method &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; which is part of the &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;lt;code&amp;gt;self.&amp;lt;/code&amp;gt; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def magnetisation(self):&lt;br /&gt;
    # we have to use self.lattice, because the lattice variable is part of the object, not local to this function&lt;br /&gt;
    for i in self.lattice:&lt;br /&gt;
        ...&lt;br /&gt;
        # we use i, not self.i&lt;br /&gt;
        # we don&#039;t need to access i outside this function &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Have a look at the other files that you have been given to see how this IsingLattice object is used.&lt;br /&gt;
&lt;br /&gt;
===The Constructor===&lt;br /&gt;
&lt;br /&gt;
The only method currently filled in is &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt;. This is a special method called a &#039;&#039;constructor&#039;&#039;. Whenever a new IsingLattice object is created, using code like &amp;lt;code&amp;gt;il = IsingLattice(5,5)&amp;lt;/code&amp;gt;, this method is called automatically. It takes two arguments (excluding &amp;quot;self&amp;quot;), which are simply the number of rows and columns that our lattice will have. The attribute &amp;lt;code&amp;gt;self.lattice&amp;lt;/code&amp;gt; is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;code&amp;gt;np.random.choice&amp;lt;/code&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for the function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html numpy.random.choice].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, which should return the energy of the lattice and the total magnetisation, respectively. In the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; function you may assume that &#039;&#039;J&#039;&#039;=1.0 at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which all energies are a multiple of &#039;&#039;J&#039;&#039;, but there will be more information about this in later sections). Do not worry about the efficiency of the code at the moment &amp;amp;mdash; we will address the speed in a later part of the experiment. Paste your code in your report and describe how it works.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Testing the files==&lt;br /&gt;
&lt;br /&gt;
When you have completed the energy() and magnetisation() methods, we need to test that they work correctly.&lt;br /&gt;
We have provided you with a script, &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;, which will create three IsingLattice objects and check their energies and magnetisations, displaying these on a graph. One configuration corresponds to the energy minimum, one to the energy maximum, and one to an intermediate state.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2b&amp;lt;/big&amp;gt;: Run the ILcheck.py script from the a terminal using the command&#039;&#039;&#039;&amp;lt;pre&amp;gt;python ILcheck.py&amp;lt;/pre&amp;gt;&#039;&#039;&#039;The displayed window has a series of control buttons in the bottom left, one of which will allow you to export the figure as a SVG or PNG image. Save an image of the ILcheck.py output, and include it in your report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are also some unit tests available in the &amp;lt;code&amp;gt;test_energy.py&amp;lt;/code&amp;gt; file. These tests are designed to be run by simply running the [https://docs.pytest.org pytest] command in your terminal,&lt;br /&gt;
&amp;lt;pre&amp;gt;pytest&amp;lt;/pre&amp;gt;&lt;br /&gt;
You should make sure your code passes the tests for the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt; methods at this time. The file contains tests for methods that will only be implemented later on, so some failures are expected for now.&lt;br /&gt;
These sorts of test are useful because they are easier to write and faster to run and can be made to run automatically.&lt;br /&gt;
&lt;br /&gt;
You can also debug and test your program on a Jupyter notebook or IPython console by importing your IsingLattice class, creating one object, and inspecting its properties. If you do this, we recommend that you start your session running the commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%load_ext autoreload&lt;br /&gt;
%autoreload 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will ensure that when you try executing your code, you always run the most recent version (please note this isn&#039;t fool proof and if you find problems you may need to restart the kernel)!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment. You can return to the previous page, [[Programming a 2D Ising Model/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|3. Introduction to Monte Carlo simulation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822072</id>
		<title>Programming a 2D Ising Model/Calculating the energy and magnetisation</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822072"/>
		<updated>2026-05-03T11:31:42Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* Testing the files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment. You can return to the previous page, [[Programming a 2D Ising Model/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|Introduction to Monte Carlo simulation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 2. Calculating the energy and magnetisation =&lt;br /&gt;
&lt;br /&gt;
==Getting the files for the experiment==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Various scripts have been prepared to assist you with this experiment, and you can obtain them by downloading the files from the Blackboard.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We recommend you open the extracted folder with JupyterLab, which has an integrated terminal where you can run the  simulation scripts.&lt;br /&gt;
&lt;br /&gt;
==Modifying the files==&lt;br /&gt;
&lt;br /&gt;
The file &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; contains a Python class called IsingLattice. This class will be the basis for our model of the system, and is restricted to modelling the two dimensional case. It contains a number of stub methods that you will complete as you work through the experiment.&lt;br /&gt;
&lt;br /&gt;
===A note about Python Classes===&lt;br /&gt;
&lt;br /&gt;
The file IsingLattice.py makes use of a Python feature called &#039;&#039;class&#039;&#039;. You should be familiar with the idea that all Python &#039;&#039;objects&#039;&#039; have an associated &#039;&#039;type&#039;&#039; -- you have already encountered objects such as integers, string, lists, and NumPy arrays. Classes allow us to define new types of object. In this case, we define a type called &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
class IsingLattice:&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each class is allowed to have certain attributes and functions (known as methods) associated with it. We can see, for example, that each &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; object has the methods &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt; (the method &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt; will be explained shortly). Each of these methods takes a special first argument called self, which is a variable pointing to the current copy of IsingLattice. To use the new IsingLattice object that we have defined, we use code like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import IsingLattice&lt;br /&gt;
&lt;br /&gt;
il = IsingLattice(5, 5) #create an IsingLattice object with 5 row and 5 columns&lt;br /&gt;
&lt;br /&gt;
energy = il.energy() #call the energy() method of our IsingLattice object&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all attributes and methods belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the &amp;lt;code&amp;gt;montecarlostep()&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the method &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; which is part of the &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;lt;code&amp;gt;self.&amp;lt;/code&amp;gt; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def magnetisation(self):&lt;br /&gt;
    # we have to use self.lattice, because the lattice variable is part of the object, not local to this function&lt;br /&gt;
    for i in self.lattice:&lt;br /&gt;
        ...&lt;br /&gt;
        # we use i, not self.i&lt;br /&gt;
        # we don&#039;t need to access i outside this function &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Have a look at the other files that you have been given to see how this IsingLattice object is used.&lt;br /&gt;
&lt;br /&gt;
===The Constructor===&lt;br /&gt;
&lt;br /&gt;
The only method currently filled in is &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt;. This is a special method called a &#039;&#039;constructor&#039;&#039;. Whenever a new IsingLattice object is created, using code like &amp;lt;code&amp;gt;il = IsingLattice(5,5)&amp;lt;/code&amp;gt;, this method is called automatically. It takes two arguments (excluding &amp;quot;self&amp;quot;), which are simply the number of rows and columns that our lattice will have. The attribute &amp;lt;code&amp;gt;self.lattice&amp;lt;/code&amp;gt; is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;code&amp;gt;np.random.choice&amp;lt;/code&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for the function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html numpy.random.choice].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, which should return the energy of the lattice and the total magnetisation, respectively. In the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; function you may assume that &#039;&#039;J&#039;&#039;=1.0 at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which all energies are a multiple of &#039;&#039;J&#039;&#039;, but there will be more information about this in later sections). Do not worry about the efficiency of the code at the moment &amp;amp;mdash; we will address the speed in a later part of the experiment. Paste your code in your report and describe how it works.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Testing the files==&lt;br /&gt;
&lt;br /&gt;
When you have completed the energy() and magnetisation() methods, we need to test that they work correctly.&lt;br /&gt;
We have provided you with a script, &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;, which will create three IsingLattice objects and check their energies and magnetisations, displaying these on a graph. One configuration corresponds to the energy minimum, one to the energy maximum, and one to an intermediate state.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2b&amp;lt;/big&amp;gt;: Run the ILcheck.py script from the a terminal using the command&#039;&#039;&#039;&amp;lt;pre&amp;gt;python ILcheck.py&amp;lt;/pre&amp;gt;&#039;&#039;&#039;The displayed window has a series of control buttons in the bottom left, one of which will allow you to export the figure as a SVG or PNG image. Save an image of the ILcheck.py output, and include it in your report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are also some unit tests available in the &amp;lt;code&amp;gt;test_energy.py&amp;lt;/code&amp;gt; file. These tests are designed to be run by simply running the [https://docs.pytest.org pytest] command in your terminal,&lt;br /&gt;
&amp;lt;pre&amp;gt;pytest&amp;lt;/pre&amp;gt;&lt;br /&gt;
You should make sure your code passes the tests for the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt; methods at this time. The file contains tests for methods that will only be implemented later on, so some failures are expected for now.&lt;br /&gt;
These sorts of test are useful because they are easier to write and faster to run and can be made to run automatically.&lt;br /&gt;
&lt;br /&gt;
You can also debug and test your program on a Jupyter notebook or IPython console by importing your IsingLattice class, creating one object, and inspecting its properties. If you do this, we recommend that you start your session running the commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%load_ext autoreload&lt;br /&gt;
%autoreload 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will ensure that when you try executing your code, you always run the most recent version (please note this isn&#039;t fool proof and if you find problems you may need to restart the kernel)!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment. You can return to the previous page, [[Programming a 2D Ising Model/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|2. Introduction to Monte Carlo simulation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822071</id>
		<title>Programming a 2D Ising Model/Introduction to the Ising model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822071"/>
		<updated>2026-05-03T09:31:28Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* 1. Introduction to the Ising model */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment. You can return to the [[Programming_a_2D_Ising_Model|introduction page]], or jump ahead to the next section, [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 1. Introduction to the Ising model =&lt;br /&gt;
&lt;br /&gt;
== The Ising model ==&lt;br /&gt;
The Ising model is a simple physical model proposed in the 1920s to understand the behaviour of ferromagnets. In most materials, the magnetic dipoles of the atoms have no preferred orientation, and the bulk material has no net magnetic moment. In certain materials, however, there is preferential alignment of the magnetic dipoles along certain directions. These materials, such as iron, exhibit an overall magnetic moment, and are called ferromagnetic.&lt;br /&gt;
&lt;br /&gt;
The phenomenon is based on competition between two physical effects &amp;amp;mdash; energy minimisation and entropy maximisation. On the one hand, parallel alignment of magnetic moments is energetically favourable. On the other hand, aligning the system in this way reduces the entropy.&lt;br /&gt;
&lt;br /&gt;
In the Ising model, we consider a collection of spins, &#039;&#039;s&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;&#039;&#039;, each of which can either have the value &amp;quot;up&amp;quot; (+1) or &amp;quot;down&amp;quot; (-1), arranged on a lattice. In one dimension, this takes the form of a &amp;quot;chain&amp;quot; of adjacent spins, &#039;&#039;s&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039; to &#039;&#039;s&amp;lt;sub&amp;gt;N&amp;lt;/sub&amp;gt;&#039;&#039;. In two dimensions we have a grid of cells, each of which contains one spin. In three dimensions, the system is a cuboid, and so on. The arrangements for 1, 2 and 3 dimensions are illustrated in &#039;&#039;&#039;figure 1&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingSketch.png|300px|thumb|right|&#039;&#039;&#039;Figure 1&#039;&#039;&#039;: Illustration of an Ising lattice in one (N=5), two (N=5&amp;amp;times;5), and three (N=5&amp;amp;times;5&amp;amp;times;5) dimensions. Red cells indicate the &amp;quot;up&amp;quot; spin&amp;quot;, and blue cells indicate the &amp;quot;down&amp;quot; spin.]]&lt;br /&gt;
&lt;br /&gt;
The rules of the model are simple:&lt;br /&gt;
&lt;br /&gt;
* When no magnetic field is applied, the only energetic contribution comes from the interaction between spins in &#039;&#039;adjacent&#039;&#039; lattice cells&lt;br /&gt;
* The total interaction energy is defined as &amp;lt;math&amp;gt;- \frac{1}{2} J \sum_i^N \sum_{j\  \in\  \mathrm{neighbours}\left(i\right)} s_i s_j&amp;lt;/math&amp;gt;, where &#039;&#039;J&#039;&#039; is a constant which controls the strength of interaction and the notation &#039;&#039;j&#039;&#039;&amp;amp;nbsp;&amp;amp;in;&amp;amp;nbsp;neighbours(&#039;&#039;i&#039;&#039;) indicates that spin &#039;&#039;j&#039;&#039; must lie in a lattice cell adjacent to spin &#039;&#039;i&#039;&#039;. The factor of one half is included to make sure that we do not count each spin-spin interaction twice.&lt;br /&gt;
* Periodic boundary conditions are applied. In other words, the &amp;quot;final&amp;quot; spin in a particular direction is considered to be adjacent to the &amp;quot;first&amp;quot; spin in that direction. In &#039;&#039;&#039;figure 2&#039;&#039;&#039;, for example, cell 1 has neighbour interactions with cells 2, 3, 4, and 7, while cell 9 interacts with cells 3, 6, 7, and 8.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingNumberedCell.png|300px|thumb|right|&#039;&#039;&#039;Figure 2&#039;&#039;&#039;: Illustration of a 2D Ising lattice, with numbered cells to indicate the neighbour interactions.]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1a&amp;lt;/big&amp;gt;: Show that the lowest possible energy for the Ising model (with &#039;&#039;J&#039;&#039;&amp;amp;gt;0) is &#039;&#039;E&#039;&#039;&amp;amp;nbsp;=&amp;amp;nbsp;-&#039;&#039;DNJ&#039;&#039;, where &#039;&#039;D&#039;&#039; is the number of dimensions and &#039;&#039;N&#039;&#039; is the total number of spins. What is the multiplicity of this state? Calculate its entropy.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Phase Transitions==&lt;br /&gt;
&lt;br /&gt;
The Ising model is interesting because it is one of the simplest physical models to display a phase transition (so long as we are in two dimensions or more). The temperature of the system controls the balance between the energetic driving force, which wants the system to adopt the lowest energy configuration that you imagined in the previous section, and the entropic driving force, which seeks to maximise the number of configurations available to the system.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1b&amp;lt;/big&amp;gt;: Imagine that the system is in the lowest energy configuration. To move to a different state, one of the spins must spontaneously change direction (&amp;quot;flip&amp;quot;). What is the change in energy if this happens (&#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000)? How much entropy does the system gain by doing so?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
At low temperatures, little thermal energy is available to overcome such energy barriers, and we expect the system to adopt the lowest energy (the energetic driving force will dominate). Under these conditions, we expect a large number of parallel spins, and we can characterise this by considering the total &#039;&#039;magnetisation&#039;&#039; of the system: &amp;lt;math&amp;gt;M = \sum_i s_i&amp;lt;/math&amp;gt;. At higher temperatures, however, enough thermal energy will be available that spins can flip relatively freely. Under these conditions, the entropic driving force should dominate. The transition temperature between the two regimes is called the &#039;&#039;Curie temperature&#039;&#039;, &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;. Below &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;, we observe the highly ordered magnetised phase, while above &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039; a disordered, demagnetised, phase emerges.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1c&amp;lt;/big&amp;gt;: Calculate the magnetisation of the 1D and 2D lattices in figure 1. What magnetisation would you expect to observe for an Ising lattice with &#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000 at absolute zero?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We are interested, therefore, in determining the magnetisation &#039;&#039;M&#039;&#039;, and energy &#039;&#039;E&#039;&#039;, of the system as functions of temperature &#039;&#039;T&#039;&#039;. We can write statistical mechanical equations for these quantities:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle M\right\rangle_T = \frac{1}{Z}\sum_\alpha M\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle E\right\rangle_T = \frac{1}{Z}\sum_\alpha E\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &#039;&#039;&amp;amp;alpha;&#039;&#039; is used as a shorthand to represent all spins in the system, and &#039;&#039;Z&#039;&#039; is the partition function,&lt;br /&gt;
&amp;lt;math&amp;gt;Z = \sum_\alpha \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It was discovered relatively quickly after the model was first proposed that the partition function in the one dimensional case can be solved analytically (though doing so is beyond the scope of this experiment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Z\left(T, N\right) = \left[2\cosh\left(\frac{J}{k_BT}\right)\right]^N&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Much later, [http://en.wikipedia.org/wiki/Lars_Onsager Lars Onsager] established that the two dimensional partition function can also be found analytically, though the mathematics is significantly more involved and the resulting expression is correspondingly much more complicated. In dimensions greater than two, no analytical solution is known.&lt;br /&gt;
&lt;br /&gt;
Luckily for us, the problem can instead be tackled by numerical methods, and it is this that will be the focus of the experiment. We will discuss how the equations for &#039;&#039;M&#039;&#039; and &#039;&#039;E&#039;&#039; can be solved, but first we must set up a Python script to model the lattice.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section:  [[Programming_a_2D_Ising_Model|Introduction page]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822070</id>
		<title>Programming a 2D Ising Model/Calculating the energy and magnetisation</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Calculating_the_energy_and_magnetisation&amp;diff=822070"/>
		<updated>2026-05-03T09:30:18Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* Getting the files for the experiment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment. You can return to the previous page, [[Programming a 2D Ising Model/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|Introduction to Monte Carlo simulation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 2. Calculating the energy and magnetisation =&lt;br /&gt;
&lt;br /&gt;
==Getting the files for the experiment==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Various scripts have been prepared to assist you with this experiment, and you can obtain them by downloading the files from the Blackboard.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We recommend you open the extracted folder with JupyterLab, which has an integrated terminal where you can run the  simulation scripts.&lt;br /&gt;
&lt;br /&gt;
==Modifying the files==&lt;br /&gt;
&lt;br /&gt;
The file &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; contains a Python class called IsingLattice. This class will be the basis for our model of the system, and is restricted to modelling the two dimensional case. It contains a number of stub methods that you will complete as you work through the experiment.&lt;br /&gt;
&lt;br /&gt;
===A note about Python Classes===&lt;br /&gt;
&lt;br /&gt;
The file IsingLattice.py makes use of a Python feature called &#039;&#039;class&#039;&#039;. You should be familiar with the idea that all Python &#039;&#039;objects&#039;&#039; have an associated &#039;&#039;type&#039;&#039; -- you have already encountered objects such as integers, string, lists, and NumPy arrays. Classes allow us to define new types of object. In this case, we define a type called &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
class IsingLattice:&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each class is allowed to have certain attributes and functions (known as methods) associated with it. We can see, for example, that each &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; object has the methods &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;montecarlostep(T)&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;statistics()&amp;lt;/code&amp;gt; (the method &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt; will be explained shortly). Each of these methods takes a special first argument called self, which is a variable pointing to the current copy of IsingLattice. To use the new IsingLattice object that we have defined, we use code like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import IsingLattice&lt;br /&gt;
&lt;br /&gt;
il = IsingLattice(5, 5) #create an IsingLattice object with 5 row and 5 columns&lt;br /&gt;
&lt;br /&gt;
energy = il.energy() #call the energy() method of our IsingLattice object&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all attributes and methods belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the &amp;lt;code&amp;gt;montecarlostep()&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the method &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; which is part of the &amp;lt;code&amp;gt;IsingLattice&amp;lt;/code&amp;gt; class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;lt;code&amp;gt;self.&amp;lt;/code&amp;gt; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def magnetisation(self):&lt;br /&gt;
    # we have to use self.lattice, because the lattice variable is part of the object, not local to this function&lt;br /&gt;
    for i in self.lattice:&lt;br /&gt;
        ...&lt;br /&gt;
        # we use i, not self.i&lt;br /&gt;
        # we don&#039;t need to access i outside this function &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Have a look at the other files that you have been given to see how this IsingLattice object is used.&lt;br /&gt;
&lt;br /&gt;
===The Constructor===&lt;br /&gt;
&lt;br /&gt;
The only method currently filled in is &amp;lt;code&amp;gt;__init__&amp;lt;/code&amp;gt;. This is a special method called a &#039;&#039;constructor&#039;&#039;. Whenever a new IsingLattice object is created, using code like &amp;lt;code&amp;gt;il = IsingLattice(5,5)&amp;lt;/code&amp;gt;, this method is called automatically. It takes two arguments (excluding &amp;quot;self&amp;quot;), which are simply the number of rows and columns that our lattice will have. The attribute &amp;lt;code&amp;gt;self.lattice&amp;lt;/code&amp;gt; is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;code&amp;gt;np.random.choice&amp;lt;/code&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for the function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html numpy.random.choice].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt;, which should return the energy of the lattice and the total magnetisation, respectively. In the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; function you may assume that &#039;&#039;J&#039;&#039;=1.0 at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which all energies are a multiple of &#039;&#039;J&#039;&#039;, but there will be more information about this in later sections). Do not worry about the efficiency of the code at the moment &amp;amp;mdash; we will address the speed in a later part of the experiment. Paste your code in your report and describe how it works.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Testing the files==&lt;br /&gt;
&lt;br /&gt;
When you have completed the energy() and magnetisation() methods, we need to test that they work correctly.&lt;br /&gt;
We have provided you with a script, &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;, which will create three IsingLattice objects and check their energies and magnetisations, displaying these on a graph. One configuration corresponds to the energy minimum, one to the energy maximum, and one to an intermediate state.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2b&amp;lt;/big&amp;gt;: Run the ILcheck.py script from the a terminal using the command&#039;&#039;&#039;&amp;lt;pre&amp;gt;python ILcheck.py&amp;lt;/pre&amp;gt;&#039;&#039;&#039;The displayed window has a series of control buttons in the bottom left, one of which will allow you to export the figure as a SVG or PNG image. Save an image of the ILcheck.py output, and include it in your report.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are also some unit tests available in the &amp;lt;code&amp;gt;test_energy.py&amp;lt;/code&amp;gt; file. These tests are designed to be run by simply running the [https://docs.pytest.org pytest] command in your terminal,&lt;br /&gt;
&amp;lt;pre&amp;gt;pytest&amp;lt;/pre&amp;gt;&lt;br /&gt;
You should make sure your code passes the tests for the &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;magnetisation()&amp;lt;/code&amp;gt; methods at this time. The file contains tests for methods that will only be implemented later on, so some failures are expected for now.&lt;br /&gt;
These sorts of test are useful because they are easier to write and faster to run and can be made to run automatically.&lt;br /&gt;
&lt;br /&gt;
You can also debug and test your program on a Jupyter notebook or IPython console by importing your IsingLattice class, creating one object, and inspecting its properties. If you do this, we recommend that you start your session running the commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%load_ext autoreload&lt;br /&gt;
%autoreload 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will ensure that when you try executing your code, you always run the most recent version (please note this isn&#039;t fool proof and if you find problems you may need to restart the kernel)!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the second section of the Ising model experiment. You can return to the previous page, [[Programming a 2D Ising Model/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|Introduction to Monte Carlo simulation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822069</id>
		<title>Programming a 2D Ising Model/Introduction to the Ising model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822069"/>
		<updated>2026-05-03T09:27:20Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* 1. The Ising model */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment. You can return to the [[Programming_a_2D_Ising_Model|introduction page]], or jump ahead to the next section, [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 1. Introduction to the Ising model =&lt;br /&gt;
The Ising model is a simple physical model proposed in the 1920s to understand the behaviour of ferromagnets. In most materials, the magnetic dipoles of the atoms have no preferred orientation, and the bulk material has no net magnetic moment. In certain materials, however, there is preferential alignment of the magnetic dipoles along certain directions. These materials, such as iron, exhibit an overall magnetic moment, and are called ferromagnetic.&lt;br /&gt;
&lt;br /&gt;
The phenomenon is based on competition between two physical effects &amp;amp;mdash; energy minimisation and entropy maximisation. On the one hand, parallel alignment of magnetic moments is energetically favourable. On the other hand, aligning the system in this way reduces the entropy.&lt;br /&gt;
&lt;br /&gt;
In the Ising model, we consider a collection of spins, &#039;&#039;s&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;&#039;&#039;, each of which can either have the value &amp;quot;up&amp;quot; (+1) or &amp;quot;down&amp;quot; (-1), arranged on a lattice. In one dimension, this takes the form of a &amp;quot;chain&amp;quot; of adjacent spins, &#039;&#039;s&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039; to &#039;&#039;s&amp;lt;sub&amp;gt;N&amp;lt;/sub&amp;gt;&#039;&#039;. In two dimensions we have a grid of cells, each of which contains one spin. In three dimensions, the system is a cuboid, and so on. The arrangements for 1, 2 and 3 dimensions are illustrated in &#039;&#039;&#039;figure 1&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingSketch.png|300px|thumb|right|&#039;&#039;&#039;Figure 1&#039;&#039;&#039;: Illustration of an Ising lattice in one (N=5), two (N=5&amp;amp;times;5), and three (N=5&amp;amp;times;5&amp;amp;times;5) dimensions. Red cells indicate the &amp;quot;up&amp;quot; spin&amp;quot;, and blue cells indicate the &amp;quot;down&amp;quot; spin.]]&lt;br /&gt;
&lt;br /&gt;
The rules of the model are simple:&lt;br /&gt;
&lt;br /&gt;
* When no magnetic field is applied, the only energetic contribution comes from the interaction between spins in &#039;&#039;adjacent&#039;&#039; lattice cells&lt;br /&gt;
* The total interaction energy is defined as &amp;lt;math&amp;gt;- \frac{1}{2} J \sum_i^N \sum_{j\  \in\  \mathrm{neighbours}\left(i\right)} s_i s_j&amp;lt;/math&amp;gt;, where &#039;&#039;J&#039;&#039; is a constant which controls the strength of interaction and the notation &#039;&#039;j&#039;&#039;&amp;amp;nbsp;&amp;amp;in;&amp;amp;nbsp;neighbours(&#039;&#039;i&#039;&#039;) indicates that spin &#039;&#039;j&#039;&#039; must lie in a lattice cell adjacent to spin &#039;&#039;i&#039;&#039;. The factor of one half is included to make sure that we do not count each spin-spin interaction twice.&lt;br /&gt;
* Periodic boundary conditions are applied. In other words, the &amp;quot;final&amp;quot; spin in a particular direction is considered to be adjacent to the &amp;quot;first&amp;quot; spin in that direction. In &#039;&#039;&#039;figure 2&#039;&#039;&#039;, for example, cell 1 has neighbour interactions with cells 2, 3, 4, and 7, while cell 9 interacts with cells 3, 6, 7, and 8.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingNumberedCell.png|300px|thumb|right|&#039;&#039;&#039;Figure 2&#039;&#039;&#039;: Illustration of a 2D Ising lattice, with numbered cells to indicate the neighbour interactions.]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1a&amp;lt;/big&amp;gt;: Show that the lowest possible energy for the Ising model (with &#039;&#039;J&#039;&#039;&amp;amp;gt;0) is &#039;&#039;E&#039;&#039;&amp;amp;nbsp;=&amp;amp;nbsp;-&#039;&#039;DNJ&#039;&#039;, where &#039;&#039;D&#039;&#039; is the number of dimensions and &#039;&#039;N&#039;&#039; is the total number of spins. What is the multiplicity of this state? Calculate its entropy.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Phase Transitions==&lt;br /&gt;
&lt;br /&gt;
The Ising model is interesting because it is one of the simplest physical models to display a phase transition (so long as we are in two dimensions or more). The temperature of the system controls the balance between the energetic driving force, which wants the system to adopt the lowest energy configuration that you imagined in the previous section, and the entropic driving force, which seeks to maximise the number of configurations available to the system.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1b&amp;lt;/big&amp;gt;: Imagine that the system is in the lowest energy configuration. To move to a different state, one of the spins must spontaneously change direction (&amp;quot;flip&amp;quot;). What is the change in energy if this happens (&#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000)? How much entropy does the system gain by doing so?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
At low temperatures, little thermal energy is available to overcome such energy barriers, and we expect the system to adopt the lowest energy (the energetic driving force will dominate). Under these conditions, we expect a large number of parallel spins, and we can characterise this by considering the total &#039;&#039;magnetisation&#039;&#039; of the system: &amp;lt;math&amp;gt;M = \sum_i s_i&amp;lt;/math&amp;gt;. At higher temperatures, however, enough thermal energy will be available that spins can flip relatively freely. Under these conditions, the entropic driving force should dominate. The transition temperature between the two regimes is called the &#039;&#039;Curie temperature&#039;&#039;, &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;. Below &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;, we observe the highly ordered magnetised phase, while above &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039; a disordered, demagnetised, phase emerges.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1c&amp;lt;/big&amp;gt;: Calculate the magnetisation of the 1D and 2D lattices in figure 1. What magnetisation would you expect to observe for an Ising lattice with &#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000 at absolute zero?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We are interested, therefore, in determining the magnetisation &#039;&#039;M&#039;&#039;, and energy &#039;&#039;E&#039;&#039;, of the system as functions of temperature &#039;&#039;T&#039;&#039;. We can write statistical mechanical equations for these quantities:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle M\right\rangle_T = \frac{1}{Z}\sum_\alpha M\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle E\right\rangle_T = \frac{1}{Z}\sum_\alpha E\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &#039;&#039;&amp;amp;alpha;&#039;&#039; is used as a shorthand to represent all spins in the system, and &#039;&#039;Z&#039;&#039; is the partition function,&lt;br /&gt;
&amp;lt;math&amp;gt;Z = \sum_\alpha \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It was discovered relatively quickly after the model was first proposed that the partition function in the one dimensional case can be solved analytically (though doing so is beyond the scope of this experiment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Z\left(T, N\right) = \left[2\cosh\left(\frac{J}{k_BT}\right)\right]^N&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Much later, [http://en.wikipedia.org/wiki/Lars_Onsager Lars Onsager] established that the two dimensional partition function can also be found analytically, though the mathematics is significantly more involved and the resulting expression is correspondingly much more complicated. In dimensions greater than two, no analytical solution is known.&lt;br /&gt;
&lt;br /&gt;
Luckily for us, the problem can instead be tackled by numerical methods, and it is this that will be the focus of the experiment. We will discuss how the equations for &#039;&#039;M&#039;&#039; and &#039;&#039;E&#039;&#039; can be solved, but first we must set up a Python script to model the lattice.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section:  [[Programming_a_2D_Ising_Model|Introduction page]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822068</id>
		<title>Programming a 2D Ising Model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822068"/>
		<updated>2026-05-03T09:27:04Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* Structure of this Experiment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;This is the Ising Model experiment (aka programming for simple simulations). This is a core experiment for year 3 students on the Chemistry with Molecular Physics degree.&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
In this exercise, you are going to use the Python that you learned in the first year to write a code to perform Monte-Carlo simulations of the 2D [http://en.wikipedia.org/wiki/Ising_model Ising model], a set of spins on a lattice which is used to model ferromagnetic behaviour, and also to analyse the results of the simulation to find the heat capacity of the system and the Curie temperature &amp;amp;mdash; the temperature below which the system is able to maintain a spontaneous magnetisation.&lt;br /&gt;
&lt;br /&gt;
A more extensive introduction to the Ising Model will be given in the next page. This page gives some practical information about how the experiment. &lt;br /&gt;
&lt;br /&gt;
==Assessment==&lt;br /&gt;
At the end of this experiment you must submit a report, writing up your findings. Each section of the experiment has a number of tasks that you should complete, labelled &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK&amp;lt;/big&amp;gt;&#039;&#039;&#039;. If this is a mathematical exercise, your report should contain a short summary of the solution. If it is a graphical exercise, you should include the relevant image. Your report should explain briefly what you did in each stage of the experiment, and what your findings were.&lt;br /&gt;
&lt;br /&gt;
The report should be submitted as a PDF file to Turnitin, created with your favourite word processor or LaTeX, and should contain the annotated source code of the Python scripts that your write during the experiment. For clarity, code included in the report should be written in a monospaced font (e.g. Courier), which in LaTeX can be easily achieved by placing your code inside a &amp;lt;code&amp;gt;\texttt{}&amp;lt;/code&amp;gt; command. &#039;&#039;&#039;The code, except where relevant to discussion, can be placed in an appendix.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As well as including relevant source code in your report, you should also submit a bundle with all your scripts and analysis code as a separate Blackboard submission.&lt;br /&gt;
&lt;br /&gt;
===On the use of AI tools===&lt;br /&gt;
The code you write for this experiment is assessed, and as per the [https://bb.imperial.ac.uk/bbcswebdav/pid-3344481-dt-content-rid-21115105_1/xid-21115105_1 department&#039;s guidelines on the use of AI], it is not acceptable to use generative AI tools to write computer code for this assignment.&lt;br /&gt;
&lt;br /&gt;
Writing computer programs yourself enhances your logical thinking and problem solving skills. Using generative AI tools to write your code makes you dumb. Don&#039;t choose to be dumb, don&#039;t use AI to write code for you.&lt;br /&gt;
&lt;br /&gt;
==Getting Help==&lt;br /&gt;
&lt;br /&gt;
The Graduate Teaching Assistants demonstrating this experiment are Fionn Carman and Lei Li. Demonstrators will be available in room 232A at the following times:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Demonstrator timetable&lt;br /&gt;
! !! Monday !! Tuesday !! Wednesday !! Thusrsday !! Friday&lt;br /&gt;
|-&lt;br /&gt;
| Morning || 10:00 - Experiment intro&amp;lt;br /&amp;gt; 10:00-13:00 - Li || 10:00-13:00 - Fionn|| || 10:00-12:00 - João || 10:00-13:00 - Fionn&lt;br /&gt;
|-&lt;br /&gt;
| Afternoon || 14:00-17:00 - Li|| 14:00-17:00 - Fionn|| ||  || 14:00-17:00 - Fionn&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you have questions outside these times, please use the Discussion Board on Blackboard.&lt;br /&gt;
&lt;br /&gt;
João and Giuseppe are the members of academic staff responsible for this experiment. You are welcome to address your questions and comments to them.&lt;br /&gt;
&lt;br /&gt;
==Structure of this Experiment==&lt;br /&gt;
&lt;br /&gt;
This experimental manual has been broken up into a number of subsections. Direct links to each of them may be found below. You should attempt them in order, and you should complete all of them to finish the experiment.&lt;br /&gt;
&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model|Introduction to the Ising model]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Calculating the energy and magnetisation|Calculating the energy and magnetisation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction to Monte Carlo simulation|Introduction to the Monte Carlo simulation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Accelerating the code|Accelerating the code]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of temperature|The effect of temperature]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of system size|The effect of system size]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Determining the heat capacity|Determining the heat capacity]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Locating the Curie temperature|Locating the Curie temperature]]&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822067</id>
		<title>Programming a 2D Ising Model/Introduction to the Ising model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822067"/>
		<updated>2026-05-03T09:25:35Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* Phase Transitions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment. You can return to the [[Programming_a_2D_Ising_Model|introduction page]], or jump ahead to the next section, [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= 1. The Ising model =&lt;br /&gt;
The Ising model is a simple physical model proposed in the 1920s to understand the behaviour of ferromagnets. In most materials, the magnetic dipoles of the atoms have no preferred orientation, and the bulk material has no net magnetic moment. In certain materials, however, there is preferential alignment of the magnetic dipoles along certain directions. These materials, such as iron, exhibit an overall magnetic moment, and are called ferromagnetic.&lt;br /&gt;
&lt;br /&gt;
The phenomenon is based on competition between two physical effects &amp;amp;mdash; energy minimisation and entropy maximisation. On the one hand, parallel alignment of magnetic moments is energetically favourable. On the other hand, aligning the system in this way reduces the entropy.&lt;br /&gt;
&lt;br /&gt;
In the Ising model, we consider a collection of spins, &#039;&#039;s&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;&#039;&#039;, each of which can either have the value &amp;quot;up&amp;quot; (+1) or &amp;quot;down&amp;quot; (-1), arranged on a lattice. In one dimension, this takes the form of a &amp;quot;chain&amp;quot; of adjacent spins, &#039;&#039;s&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039; to &#039;&#039;s&amp;lt;sub&amp;gt;N&amp;lt;/sub&amp;gt;&#039;&#039;. In two dimensions we have a grid of cells, each of which contains one spin. In three dimensions, the system is a cuboid, and so on. The arrangements for 1, 2 and 3 dimensions are illustrated in &#039;&#039;&#039;figure 1&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingSketch.png|300px|thumb|right|&#039;&#039;&#039;Figure 1&#039;&#039;&#039;: Illustration of an Ising lattice in one (N=5), two (N=5&amp;amp;times;5), and three (N=5&amp;amp;times;5&amp;amp;times;5) dimensions. Red cells indicate the &amp;quot;up&amp;quot; spin&amp;quot;, and blue cells indicate the &amp;quot;down&amp;quot; spin.]]&lt;br /&gt;
&lt;br /&gt;
The rules of the model are simple:&lt;br /&gt;
&lt;br /&gt;
* When no magnetic field is applied, the only energetic contribution comes from the interaction between spins in &#039;&#039;adjacent&#039;&#039; lattice cells&lt;br /&gt;
* The total interaction energy is defined as &amp;lt;math&amp;gt;- \frac{1}{2} J \sum_i^N \sum_{j\  \in\  \mathrm{neighbours}\left(i\right)} s_i s_j&amp;lt;/math&amp;gt;, where &#039;&#039;J&#039;&#039; is a constant which controls the strength of interaction and the notation &#039;&#039;j&#039;&#039;&amp;amp;nbsp;&amp;amp;in;&amp;amp;nbsp;neighbours(&#039;&#039;i&#039;&#039;) indicates that spin &#039;&#039;j&#039;&#039; must lie in a lattice cell adjacent to spin &#039;&#039;i&#039;&#039;. The factor of one half is included to make sure that we do not count each spin-spin interaction twice.&lt;br /&gt;
* Periodic boundary conditions are applied. In other words, the &amp;quot;final&amp;quot; spin in a particular direction is considered to be adjacent to the &amp;quot;first&amp;quot; spin in that direction. In &#039;&#039;&#039;figure 2&#039;&#039;&#039;, for example, cell 1 has neighbour interactions with cells 2, 3, 4, and 7, while cell 9 interacts with cells 3, 6, 7, and 8.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingNumberedCell.png|300px|thumb|right|&#039;&#039;&#039;Figure 2&#039;&#039;&#039;: Illustration of a 2D Ising lattice, with numbered cells to indicate the neighbour interactions.]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1a&amp;lt;/big&amp;gt;: Show that the lowest possible energy for the Ising model (with &#039;&#039;J&#039;&#039;&amp;amp;gt;0) is &#039;&#039;E&#039;&#039;&amp;amp;nbsp;=&amp;amp;nbsp;-&#039;&#039;DNJ&#039;&#039;, where &#039;&#039;D&#039;&#039; is the number of dimensions and &#039;&#039;N&#039;&#039; is the total number of spins. What is the multiplicity of this state? Calculate its entropy.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Phase Transitions==&lt;br /&gt;
&lt;br /&gt;
The Ising model is interesting because it is one of the simplest physical models to display a phase transition (so long as we are in two dimensions or more). The temperature of the system controls the balance between the energetic driving force, which wants the system to adopt the lowest energy configuration that you imagined in the previous section, and the entropic driving force, which seeks to maximise the number of configurations available to the system.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1b&amp;lt;/big&amp;gt;: Imagine that the system is in the lowest energy configuration. To move to a different state, one of the spins must spontaneously change direction (&amp;quot;flip&amp;quot;). What is the change in energy if this happens (&#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000)? How much entropy does the system gain by doing so?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
At low temperatures, little thermal energy is available to overcome such energy barriers, and we expect the system to adopt the lowest energy (the energetic driving force will dominate). Under these conditions, we expect a large number of parallel spins, and we can characterise this by considering the total &#039;&#039;magnetisation&#039;&#039; of the system: &amp;lt;math&amp;gt;M = \sum_i s_i&amp;lt;/math&amp;gt;. At higher temperatures, however, enough thermal energy will be available that spins can flip relatively freely. Under these conditions, the entropic driving force should dominate. The transition temperature between the two regimes is called the &#039;&#039;Curie temperature&#039;&#039;, &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;. Below &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;, we observe the highly ordered magnetised phase, while above &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039; a disordered, demagnetised, phase emerges.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1c&amp;lt;/big&amp;gt;: Calculate the magnetisation of the 1D and 2D lattices in figure 1. What magnetisation would you expect to observe for an Ising lattice with &#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000 at absolute zero?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We are interested, therefore, in determining the magnetisation &#039;&#039;M&#039;&#039;, and energy &#039;&#039;E&#039;&#039;, of the system as functions of temperature &#039;&#039;T&#039;&#039;. We can write statistical mechanical equations for these quantities:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle M\right\rangle_T = \frac{1}{Z}\sum_\alpha M\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle E\right\rangle_T = \frac{1}{Z}\sum_\alpha E\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &#039;&#039;&amp;amp;alpha;&#039;&#039; is used as a shorthand to represent all spins in the system, and &#039;&#039;Z&#039;&#039; is the partition function,&lt;br /&gt;
&amp;lt;math&amp;gt;Z = \sum_\alpha \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It was discovered relatively quickly after the model was first proposed that the partition function in the one dimensional case can be solved analytically (though doing so is beyond the scope of this experiment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Z\left(T, N\right) = \left[2\cosh\left(\frac{J}{k_BT}\right)\right]^N&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Much later, [http://en.wikipedia.org/wiki/Lars_Onsager Lars Onsager] established that the two dimensional partition function can also be found analytically, though the mathematics is significantly more involved and the resulting expression is correspondingly much more complicated. In dimensions greater than two, no analytical solution is known.&lt;br /&gt;
&lt;br /&gt;
Luckily for us, the problem can instead be tackled by numerical methods, and it is this that will be the focus of the experiment. We will discuss how the equations for &#039;&#039;M&#039;&#039; and &#039;&#039;E&#039;&#039; can be solved, but first we must set up a Python script to model the lattice.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section:  [[Programming_a_2D_Ising_Model|Introduction page]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822066</id>
		<title>Programming a 2D Ising Model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822066"/>
		<updated>2026-05-03T09:23:34Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* Structure of this Experiment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;This is the Ising Model experiment (aka programming for simple simulations). This is a core experiment for year 3 students on the Chemistry with Molecular Physics degree.&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
In this exercise, you are going to use the Python that you learned in the first year to write a code to perform Monte-Carlo simulations of the 2D [http://en.wikipedia.org/wiki/Ising_model Ising model], a set of spins on a lattice which is used to model ferromagnetic behaviour, and also to analyse the results of the simulation to find the heat capacity of the system and the Curie temperature &amp;amp;mdash; the temperature below which the system is able to maintain a spontaneous magnetisation.&lt;br /&gt;
&lt;br /&gt;
A more extensive introduction to the Ising Model will be given in the next page. This page gives some practical information about how the experiment. &lt;br /&gt;
&lt;br /&gt;
==Assessment==&lt;br /&gt;
At the end of this experiment you must submit a report, writing up your findings. Each section of the experiment has a number of tasks that you should complete, labelled &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK&amp;lt;/big&amp;gt;&#039;&#039;&#039;. If this is a mathematical exercise, your report should contain a short summary of the solution. If it is a graphical exercise, you should include the relevant image. Your report should explain briefly what you did in each stage of the experiment, and what your findings were.&lt;br /&gt;
&lt;br /&gt;
The report should be submitted as a PDF file to Turnitin, created with your favourite word processor or LaTeX, and should contain the annotated source code of the Python scripts that your write during the experiment. For clarity, code included in the report should be written in a monospaced font (e.g. Courier), which in LaTeX can be easily achieved by placing your code inside a &amp;lt;code&amp;gt;\texttt{}&amp;lt;/code&amp;gt; command. &#039;&#039;&#039;The code, except where relevant to discussion, can be placed in an appendix.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As well as including relevant source code in your report, you should also submit a bundle with all your scripts and analysis code as a separate Blackboard submission.&lt;br /&gt;
&lt;br /&gt;
===On the use of AI tools===&lt;br /&gt;
The code you write for this experiment is assessed, and as per the [https://bb.imperial.ac.uk/bbcswebdav/pid-3344481-dt-content-rid-21115105_1/xid-21115105_1 department&#039;s guidelines on the use of AI], it is not acceptable to use generative AI tools to write computer code for this assignment.&lt;br /&gt;
&lt;br /&gt;
Writing computer programs yourself enhances your logical thinking and problem solving skills. Using generative AI tools to write your code makes you dumb. Don&#039;t choose to be dumb, don&#039;t use AI to write code for you.&lt;br /&gt;
&lt;br /&gt;
==Getting Help==&lt;br /&gt;
&lt;br /&gt;
The Graduate Teaching Assistants demonstrating this experiment are Fionn Carman and Lei Li. Demonstrators will be available in room 232A at the following times:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Demonstrator timetable&lt;br /&gt;
! !! Monday !! Tuesday !! Wednesday !! Thusrsday !! Friday&lt;br /&gt;
|-&lt;br /&gt;
| Morning || 10:00 - Experiment intro&amp;lt;br /&amp;gt; 10:00-13:00 - Li || 10:00-13:00 - Fionn|| || 10:00-12:00 - João || 10:00-13:00 - Fionn&lt;br /&gt;
|-&lt;br /&gt;
| Afternoon || 14:00-17:00 - Li|| 14:00-17:00 - Fionn|| ||  || 14:00-17:00 - Fionn&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you have questions outside these times, please use the Discussion Board on Blackboard.&lt;br /&gt;
&lt;br /&gt;
João and Giuseppe are the members of academic staff responsible for this experiment. You are welcome to address your questions and comments to them.&lt;br /&gt;
&lt;br /&gt;
==Structure of this Experiment==&lt;br /&gt;
&lt;br /&gt;
This experimental manual has been broken up into a number of subsections. Direct links to each of them may be found below. You should attempt them in order, and you should complete all of them to finish the experiment.&lt;br /&gt;
&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model|The Ising model]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Calculating the energy and magnetisation|Calculating the energy and magnetisation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction to Monte Carlo simulation|Introduction to the Monte Carlo simulation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Accelerating the code|Accelerating the code]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of temperature|The effect of temperature]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of system size|The effect of system size]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Determining the heat capacity|Determining the heat capacity]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Locating the Curie temperature|Locating the Curie temperature]]&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822065</id>
		<title>Programming a 2D Ising Model/Introduction to the Ising model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822065"/>
		<updated>2026-05-03T09:23:07Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* The Ising model */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment. You can return to the [[Programming_a_2D_Ising_Model|introduction page]], or jump ahead to the next section, [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==1. The Ising model==&lt;br /&gt;
The Ising model is a simple physical model proposed in the 1920s to understand the behaviour of ferromagnets. In most materials, the magnetic dipoles of the atoms have no preferred orientation, and the bulk material has no net magnetic moment. In certain materials, however, there is preferential alignment of the magnetic dipoles along certain directions. These materials, such as iron, exhibit an overall magnetic moment, and are called ferromagnetic.&lt;br /&gt;
&lt;br /&gt;
The phenomenon is based on competition between two physical effects &amp;amp;mdash; energy minimisation and entropy maximisation. On the one hand, parallel alignment of magnetic moments is energetically favourable. On the other hand, aligning the system in this way reduces the entropy.&lt;br /&gt;
&lt;br /&gt;
In the Ising model, we consider a collection of spins, &#039;&#039;s&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;&#039;&#039;, each of which can either have the value &amp;quot;up&amp;quot; (+1) or &amp;quot;down&amp;quot; (-1), arranged on a lattice. In one dimension, this takes the form of a &amp;quot;chain&amp;quot; of adjacent spins, &#039;&#039;s&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039; to &#039;&#039;s&amp;lt;sub&amp;gt;N&amp;lt;/sub&amp;gt;&#039;&#039;. In two dimensions we have a grid of cells, each of which contains one spin. In three dimensions, the system is a cuboid, and so on. The arrangements for 1, 2 and 3 dimensions are illustrated in &#039;&#039;&#039;figure 1&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingSketch.png|300px|thumb|right|&#039;&#039;&#039;Figure 1&#039;&#039;&#039;: Illustration of an Ising lattice in one (N=5), two (N=5&amp;amp;times;5), and three (N=5&amp;amp;times;5&amp;amp;times;5) dimensions. Red cells indicate the &amp;quot;up&amp;quot; spin&amp;quot;, and blue cells indicate the &amp;quot;down&amp;quot; spin.]]&lt;br /&gt;
&lt;br /&gt;
The rules of the model are simple:&lt;br /&gt;
&lt;br /&gt;
* When no magnetic field is applied, the only energetic contribution comes from the interaction between spins in &#039;&#039;adjacent&#039;&#039; lattice cells&lt;br /&gt;
* The total interaction energy is defined as &amp;lt;math&amp;gt;- \frac{1}{2} J \sum_i^N \sum_{j\  \in\  \mathrm{neighbours}\left(i\right)} s_i s_j&amp;lt;/math&amp;gt;, where &#039;&#039;J&#039;&#039; is a constant which controls the strength of interaction and the notation &#039;&#039;j&#039;&#039;&amp;amp;nbsp;&amp;amp;in;&amp;amp;nbsp;neighbours(&#039;&#039;i&#039;&#039;) indicates that spin &#039;&#039;j&#039;&#039; must lie in a lattice cell adjacent to spin &#039;&#039;i&#039;&#039;. The factor of one half is included to make sure that we do not count each spin-spin interaction twice.&lt;br /&gt;
* Periodic boundary conditions are applied. In other words, the &amp;quot;final&amp;quot; spin in a particular direction is considered to be adjacent to the &amp;quot;first&amp;quot; spin in that direction. In &#039;&#039;&#039;figure 2&#039;&#039;&#039;, for example, cell 1 has neighbour interactions with cells 2, 3, 4, and 7, while cell 9 interacts with cells 3, 6, 7, and 8.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingNumberedCell.png|300px|thumb|right|&#039;&#039;&#039;Figure 2&#039;&#039;&#039;: Illustration of a 2D Ising lattice, with numbered cells to indicate the neighbour interactions.]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1a&amp;lt;/big&amp;gt;: Show that the lowest possible energy for the Ising model (with &#039;&#039;J&#039;&#039;&amp;amp;gt;0) is &#039;&#039;E&#039;&#039;&amp;amp;nbsp;=&amp;amp;nbsp;-&#039;&#039;DNJ&#039;&#039;, where &#039;&#039;D&#039;&#039; is the number of dimensions and &#039;&#039;N&#039;&#039; is the total number of spins. What is the multiplicity of this state? Calculate its entropy.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Phase Transitions==&lt;br /&gt;
&lt;br /&gt;
The Ising model is interesting because it is one of the simplest physical models to display a phase transition (so long as we are in two dimensions or more). The temperature of the system controls the balance between the energetic driving force, which wants the system to adopt the lowest energy configuration that you imagined in the previous section, and the entropic driving force, which seeks to maximise the number of configurations available to the system.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1b&amp;lt;/big&amp;gt;: Imagine that the system is in the lowest energy configuration. To move to a different state, one of the spins must spontaneously change direction (&amp;quot;flip&amp;quot;). What is the change in energy if this happens (&#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000)? How much entropy does the system gain by doing so?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
At low temperatures, little thermal energy is available to overcome such energy barriers, and we expect the system to adopt the lowest energy (the energetic driving force will dominate). Under these conditions, we expect a large number of parallel spins, and we can characterise this by considering the total &#039;&#039;magnetisation&#039;&#039; of the system: &amp;lt;math&amp;gt;M = \sum_i s_i&amp;lt;/math&amp;gt;. At higher temperatures, however, enough thermal energy will be available that spins can flip relatively freely. Under these conditions, the entropic driving force should dominate. The transition temperature between the two regimes is called the &#039;&#039;Curie temperature&#039;&#039;, &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;. Below &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;, we observe the highly ordered magnetised phase, while above &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039; a disordered, demagnetised, phase emerges.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1c&amp;lt;/big&amp;gt;: Calculate the magnetisation of the 1D and 2D lattices in figure 1. What magnetisation would you expect to observe for an Ising lattice with &#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000 at absolute zero?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We are interested, therefore, in determining the magnetisation &#039;&#039;M&#039;&#039;, and energy &#039;&#039;E&#039;&#039;, of the system as functions of temperature &#039;&#039;T&#039;&#039;. We can write statistical mechanical equations for these quantities:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle M\right\rangle_T = \frac{1}{Z}\sum_\alpha M\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle E\right\rangle_T = \frac{1}{Z}\sum_\alpha E\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &#039;&#039;&amp;amp;alpha;&#039;&#039; is used as a shorthand to represent all spins in the system, and &#039;&#039;Z&#039;&#039; is the partition function,&lt;br /&gt;
&amp;lt;math&amp;gt;Z = \sum_\alpha \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It was discovered relatively quickly after the model was first proposed that the partition function in the one dimensional case can be solved analytically (though doing so is beyond the scope of this experiment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Z\left(T, N\right) = \left[2\cosh\left(\frac{J}{k_BT}\right)\right]^N&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Much later, [http://en.wikipedia.org/wiki/Lars_Onsager Lars Onsager] established that the two dimensional partition function can also be found analytically, though the mathematics is significantly more involved and the resulting expression is correspondingly much more complicated. In dimensions greater than two, no analytical solution is known.&lt;br /&gt;
&lt;br /&gt;
Luckily for us, the problem can instead be tackled by numerical methods, and it is this that will be the focus of the experiment. We will discuss how the equations for &#039;&#039;M&#039;&#039; and &#039;&#039;E&#039;&#039; can be solved, but first we must set up a Python script to model the lattice.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section:  [[Programming_a_2D_Ising_Model|Introduction page]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822064</id>
		<title>Programming a 2D Ising Model/Introduction to the Ising model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822064"/>
		<updated>2026-05-03T09:22:52Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* The model */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment. You can return to the [[Programming_a_2D_Ising_Model|introduction page]], or jump ahead to the next section, [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==The Ising model==&lt;br /&gt;
The Ising model is a simple physical model proposed in the 1920s to understand the behaviour of ferromagnets. In most materials, the magnetic dipoles of the atoms have no preferred orientation, and the bulk material has no net magnetic moment. In certain materials, however, there is preferential alignment of the magnetic dipoles along certain directions. These materials, such as iron, exhibit an overall magnetic moment, and are called ferromagnetic.&lt;br /&gt;
&lt;br /&gt;
The phenomenon is based on competition between two physical effects &amp;amp;mdash; energy minimisation and entropy maximisation. On the one hand, parallel alignment of magnetic moments is energetically favourable. On the other hand, aligning the system in this way reduces the entropy.&lt;br /&gt;
&lt;br /&gt;
In the Ising model, we consider a collection of spins, &#039;&#039;s&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;&#039;&#039;, each of which can either have the value &amp;quot;up&amp;quot; (+1) or &amp;quot;down&amp;quot; (-1), arranged on a lattice. In one dimension, this takes the form of a &amp;quot;chain&amp;quot; of adjacent spins, &#039;&#039;s&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039; to &#039;&#039;s&amp;lt;sub&amp;gt;N&amp;lt;/sub&amp;gt;&#039;&#039;. In two dimensions we have a grid of cells, each of which contains one spin. In three dimensions, the system is a cuboid, and so on. The arrangements for 1, 2 and 3 dimensions are illustrated in &#039;&#039;&#039;figure 1&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingSketch.png|300px|thumb|right|&#039;&#039;&#039;Figure 1&#039;&#039;&#039;: Illustration of an Ising lattice in one (N=5), two (N=5&amp;amp;times;5), and three (N=5&amp;amp;times;5&amp;amp;times;5) dimensions. Red cells indicate the &amp;quot;up&amp;quot; spin&amp;quot;, and blue cells indicate the &amp;quot;down&amp;quot; spin.]]&lt;br /&gt;
&lt;br /&gt;
The rules of the model are simple:&lt;br /&gt;
&lt;br /&gt;
* When no magnetic field is applied, the only energetic contribution comes from the interaction between spins in &#039;&#039;adjacent&#039;&#039; lattice cells&lt;br /&gt;
* The total interaction energy is defined as &amp;lt;math&amp;gt;- \frac{1}{2} J \sum_i^N \sum_{j\  \in\  \mathrm{neighbours}\left(i\right)} s_i s_j&amp;lt;/math&amp;gt;, where &#039;&#039;J&#039;&#039; is a constant which controls the strength of interaction and the notation &#039;&#039;j&#039;&#039;&amp;amp;nbsp;&amp;amp;in;&amp;amp;nbsp;neighbours(&#039;&#039;i&#039;&#039;) indicates that spin &#039;&#039;j&#039;&#039; must lie in a lattice cell adjacent to spin &#039;&#039;i&#039;&#039;. The factor of one half is included to make sure that we do not count each spin-spin interaction twice.&lt;br /&gt;
* Periodic boundary conditions are applied. In other words, the &amp;quot;final&amp;quot; spin in a particular direction is considered to be adjacent to the &amp;quot;first&amp;quot; spin in that direction. In &#039;&#039;&#039;figure 2&#039;&#039;&#039;, for example, cell 1 has neighbour interactions with cells 2, 3, 4, and 7, while cell 9 interacts with cells 3, 6, 7, and 8.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingNumberedCell.png|300px|thumb|right|&#039;&#039;&#039;Figure 2&#039;&#039;&#039;: Illustration of a 2D Ising lattice, with numbered cells to indicate the neighbour interactions.]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1a&amp;lt;/big&amp;gt;: Show that the lowest possible energy for the Ising model (with &#039;&#039;J&#039;&#039;&amp;amp;gt;0) is &#039;&#039;E&#039;&#039;&amp;amp;nbsp;=&amp;amp;nbsp;-&#039;&#039;DNJ&#039;&#039;, where &#039;&#039;D&#039;&#039; is the number of dimensions and &#039;&#039;N&#039;&#039; is the total number of spins. What is the multiplicity of this state? Calculate its entropy.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Phase Transitions==&lt;br /&gt;
&lt;br /&gt;
The Ising model is interesting because it is one of the simplest physical models to display a phase transition (so long as we are in two dimensions or more). The temperature of the system controls the balance between the energetic driving force, which wants the system to adopt the lowest energy configuration that you imagined in the previous section, and the entropic driving force, which seeks to maximise the number of configurations available to the system.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1b&amp;lt;/big&amp;gt;: Imagine that the system is in the lowest energy configuration. To move to a different state, one of the spins must spontaneously change direction (&amp;quot;flip&amp;quot;). What is the change in energy if this happens (&#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000)? How much entropy does the system gain by doing so?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
At low temperatures, little thermal energy is available to overcome such energy barriers, and we expect the system to adopt the lowest energy (the energetic driving force will dominate). Under these conditions, we expect a large number of parallel spins, and we can characterise this by considering the total &#039;&#039;magnetisation&#039;&#039; of the system: &amp;lt;math&amp;gt;M = \sum_i s_i&amp;lt;/math&amp;gt;. At higher temperatures, however, enough thermal energy will be available that spins can flip relatively freely. Under these conditions, the entropic driving force should dominate. The transition temperature between the two regimes is called the &#039;&#039;Curie temperature&#039;&#039;, &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;. Below &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;, we observe the highly ordered magnetised phase, while above &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039; a disordered, demagnetised, phase emerges.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1c&amp;lt;/big&amp;gt;: Calculate the magnetisation of the 1D and 2D lattices in figure 1. What magnetisation would you expect to observe for an Ising lattice with &#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000 at absolute zero?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We are interested, therefore, in determining the magnetisation &#039;&#039;M&#039;&#039;, and energy &#039;&#039;E&#039;&#039;, of the system as functions of temperature &#039;&#039;T&#039;&#039;. We can write statistical mechanical equations for these quantities:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle M\right\rangle_T = \frac{1}{Z}\sum_\alpha M\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle E\right\rangle_T = \frac{1}{Z}\sum_\alpha E\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &#039;&#039;&amp;amp;alpha;&#039;&#039; is used as a shorthand to represent all spins in the system, and &#039;&#039;Z&#039;&#039; is the partition function,&lt;br /&gt;
&amp;lt;math&amp;gt;Z = \sum_\alpha \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It was discovered relatively quickly after the model was first proposed that the partition function in the one dimensional case can be solved analytically (though doing so is beyond the scope of this experiment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Z\left(T, N\right) = \left[2\cosh\left(\frac{J}{k_BT}\right)\right]^N&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Much later, [http://en.wikipedia.org/wiki/Lars_Onsager Lars Onsager] established that the two dimensional partition function can also be found analytically, though the mathematics is significantly more involved and the resulting expression is correspondingly much more complicated. In dimensions greater than two, no analytical solution is known.&lt;br /&gt;
&lt;br /&gt;
Luckily for us, the problem can instead be tackled by numerical methods, and it is this that will be the focus of the experiment. We will discuss how the equations for &#039;&#039;M&#039;&#039; and &#039;&#039;E&#039;&#039; can be solved, but first we must set up a Python script to model the lattice.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section:  [[Programming_a_2D_Ising_Model|Introduction page]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822063</id>
		<title>Programming a 2D Ising Model/Introduction to the Ising model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822063"/>
		<updated>2026-05-03T09:21:57Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* Phase Transitions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment. You can return to the [[Programming_a_2D_Ising_Model|introduction page]], or jump ahead to the next section, [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==The model==&lt;br /&gt;
The Ising model is a simple physical model proposed in the 1920s to understand the behaviour of ferromagnets. In most materials, the magnetic dipoles of the atoms have no preferred orientation, and the bulk material has no net magnetic moment. In certain materials, however, there is preferential alignment of the magnetic dipoles along certain directions. These materials, such as iron, exhibit an overall magnetic moment, and are called ferromagnetic.&lt;br /&gt;
&lt;br /&gt;
The phenomenon is based on competition between two physical effects &amp;amp;mdash; energy minimisation and entropy maximisation. On the one hand, parallel alignment of magnetic moments is energetically favourable. On the other hand, aligning the system in this way reduces the entropy.&lt;br /&gt;
&lt;br /&gt;
In the Ising model, we consider a collection of spins, &#039;&#039;s&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;&#039;&#039;, each of which can either have the value &amp;quot;up&amp;quot; (+1) or &amp;quot;down&amp;quot; (-1), arranged on a lattice. In one dimension, this takes the form of a &amp;quot;chain&amp;quot; of adjacent spins, &#039;&#039;s&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039; to &#039;&#039;s&amp;lt;sub&amp;gt;N&amp;lt;/sub&amp;gt;&#039;&#039;. In two dimensions we have a grid of cells, each of which contains one spin. In three dimensions, the system is a cuboid, and so on. The arrangements for 1, 2 and 3 dimensions are illustrated in &#039;&#039;&#039;figure 1&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingSketch.png|300px|thumb|right|&#039;&#039;&#039;Figure 1&#039;&#039;&#039;: Illustration of an Ising lattice in one (N=5), two (N=5&amp;amp;times;5), and three (N=5&amp;amp;times;5&amp;amp;times;5) dimensions. Red cells indicate the &amp;quot;up&amp;quot; spin&amp;quot;, and blue cells indicate the &amp;quot;down&amp;quot; spin.]]&lt;br /&gt;
&lt;br /&gt;
The rules of the model are simple:&lt;br /&gt;
&lt;br /&gt;
* When no magnetic field is applied, the only energetic contribution comes from the interaction between spins in &#039;&#039;adjacent&#039;&#039; lattice cells&lt;br /&gt;
* The total interaction energy is defined as &amp;lt;math&amp;gt;- \frac{1}{2} J \sum_i^N \sum_{j\  \in\  \mathrm{neighbours}\left(i\right)} s_i s_j&amp;lt;/math&amp;gt;, where &#039;&#039;J&#039;&#039; is a constant which controls the strength of interaction and the notation &#039;&#039;j&#039;&#039;&amp;amp;nbsp;&amp;amp;in;&amp;amp;nbsp;neighbours(&#039;&#039;i&#039;&#039;) indicates that spin &#039;&#039;j&#039;&#039; must lie in a lattice cell adjacent to spin &#039;&#039;i&#039;&#039;. The factor of one half is included to make sure that we do not count each spin-spin interaction twice.&lt;br /&gt;
* Periodic boundary conditions are applied. In other words, the &amp;quot;final&amp;quot; spin in a particular direction is considered to be adjacent to the &amp;quot;first&amp;quot; spin in that direction. In &#039;&#039;&#039;figure 2&#039;&#039;&#039;, for example, cell 1 has neighbour interactions with cells 2, 3, 4, and 7, while cell 9 interacts with cells 3, 6, 7, and 8.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingNumberedCell.png|300px|thumb|right|&#039;&#039;&#039;Figure 2&#039;&#039;&#039;: Illustration of a 2D Ising lattice, with numbered cells to indicate the neighbour interactions.]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1a&amp;lt;/big&amp;gt;: Show that the lowest possible energy for the Ising model (with &#039;&#039;J&#039;&#039;&amp;amp;gt;0) is &#039;&#039;E&#039;&#039;&amp;amp;nbsp;=&amp;amp;nbsp;-&#039;&#039;DNJ&#039;&#039;, where &#039;&#039;D&#039;&#039; is the number of dimensions and &#039;&#039;N&#039;&#039; is the total number of spins. What is the multiplicity of this state? Calculate its entropy.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Phase Transitions==&lt;br /&gt;
&lt;br /&gt;
The Ising model is interesting because it is one of the simplest physical models to display a phase transition (so long as we are in two dimensions or more). The temperature of the system controls the balance between the energetic driving force, which wants the system to adopt the lowest energy configuration that you imagined in the previous section, and the entropic driving force, which seeks to maximise the number of configurations available to the system.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1b&amp;lt;/big&amp;gt;: Imagine that the system is in the lowest energy configuration. To move to a different state, one of the spins must spontaneously change direction (&amp;quot;flip&amp;quot;). What is the change in energy if this happens (&#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000)? How much entropy does the system gain by doing so?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
At low temperatures, little thermal energy is available to overcome such energy barriers, and we expect the system to adopt the lowest energy (the energetic driving force will dominate). Under these conditions, we expect a large number of parallel spins, and we can characterise this by considering the total &#039;&#039;magnetisation&#039;&#039; of the system: &amp;lt;math&amp;gt;M = \sum_i s_i&amp;lt;/math&amp;gt;. At higher temperatures, however, enough thermal energy will be available that spins can flip relatively freely. Under these conditions, the entropic driving force should dominate. The transition temperature between the two regimes is called the &#039;&#039;Curie temperature&#039;&#039;, &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;. Below &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;, we observe the highly ordered magnetised phase, while above &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039; a disordered, demagnetised, phase emerges.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1c&amp;lt;/big&amp;gt;: Calculate the magnetisation of the 1D and 2D lattices in figure 1. What magnetisation would you expect to observe for an Ising lattice with &#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000 at absolute zero?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We are interested, therefore, in determining the magnetisation &#039;&#039;M&#039;&#039;, and energy &#039;&#039;E&#039;&#039;, of the system as functions of temperature &#039;&#039;T&#039;&#039;. We can write statistical mechanical equations for these quantities:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle M\right\rangle_T = \frac{1}{Z}\sum_\alpha M\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle E\right\rangle_T = \frac{1}{Z}\sum_\alpha E\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &#039;&#039;&amp;amp;alpha;&#039;&#039; is used as a shorthand to represent all spins in the system, and &#039;&#039;Z&#039;&#039; is the partition function,&lt;br /&gt;
&amp;lt;math&amp;gt;Z = \sum_\alpha \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It was discovered relatively quickly after the model was first proposed that the partition function in the one dimensional case can be solved analytically (though doing so is beyond the scope of this experiment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Z\left(T, N\right) = \left[2\cosh\left(\frac{J}{k_BT}\right)\right]^N&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Much later, [http://en.wikipedia.org/wiki/Lars_Onsager Lars Onsager] established that the two dimensional partition function can also be found analytically, though the mathematics is significantly more involved and the resulting expression is correspondingly much more complicated. In dimensions greater than two, no analytical solution is known.&lt;br /&gt;
&lt;br /&gt;
Luckily for us, the problem can instead be tackled by numerical methods, and it is this that will be the focus of the experiment. We will discuss how the equations for &#039;&#039;M&#039;&#039; and &#039;&#039;E&#039;&#039; can be solved, but first we must set up a Python script to model the lattice.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section:  [[Programming_a_2D_Ising_Model|Introduction page]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|2. Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822062</id>
		<title>Programming a 2D Ising Model/Introduction to the Ising model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model&amp;diff=822062"/>
		<updated>2026-05-03T09:19:04Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* Phase Transitions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment. You can return to the [[Programming_a_2D_Ising_Model|introduction page]], or jump ahead to the next section, [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==The model==&lt;br /&gt;
The Ising model is a simple physical model proposed in the 1920s to understand the behaviour of ferromagnets. In most materials, the magnetic dipoles of the atoms have no preferred orientation, and the bulk material has no net magnetic moment. In certain materials, however, there is preferential alignment of the magnetic dipoles along certain directions. These materials, such as iron, exhibit an overall magnetic moment, and are called ferromagnetic.&lt;br /&gt;
&lt;br /&gt;
The phenomenon is based on competition between two physical effects &amp;amp;mdash; energy minimisation and entropy maximisation. On the one hand, parallel alignment of magnetic moments is energetically favourable. On the other hand, aligning the system in this way reduces the entropy.&lt;br /&gt;
&lt;br /&gt;
In the Ising model, we consider a collection of spins, &#039;&#039;s&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;&#039;&#039;, each of which can either have the value &amp;quot;up&amp;quot; (+1) or &amp;quot;down&amp;quot; (-1), arranged on a lattice. In one dimension, this takes the form of a &amp;quot;chain&amp;quot; of adjacent spins, &#039;&#039;s&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&#039;&#039; to &#039;&#039;s&amp;lt;sub&amp;gt;N&amp;lt;/sub&amp;gt;&#039;&#039;. In two dimensions we have a grid of cells, each of which contains one spin. In three dimensions, the system is a cuboid, and so on. The arrangements for 1, 2 and 3 dimensions are illustrated in &#039;&#039;&#039;figure 1&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingSketch.png|300px|thumb|right|&#039;&#039;&#039;Figure 1&#039;&#039;&#039;: Illustration of an Ising lattice in one (N=5), two (N=5&amp;amp;times;5), and three (N=5&amp;amp;times;5&amp;amp;times;5) dimensions. Red cells indicate the &amp;quot;up&amp;quot; spin&amp;quot;, and blue cells indicate the &amp;quot;down&amp;quot; spin.]]&lt;br /&gt;
&lt;br /&gt;
The rules of the model are simple:&lt;br /&gt;
&lt;br /&gt;
* When no magnetic field is applied, the only energetic contribution comes from the interaction between spins in &#039;&#039;adjacent&#039;&#039; lattice cells&lt;br /&gt;
* The total interaction energy is defined as &amp;lt;math&amp;gt;- \frac{1}{2} J \sum_i^N \sum_{j\  \in\  \mathrm{neighbours}\left(i\right)} s_i s_j&amp;lt;/math&amp;gt;, where &#039;&#039;J&#039;&#039; is a constant which controls the strength of interaction and the notation &#039;&#039;j&#039;&#039;&amp;amp;nbsp;&amp;amp;in;&amp;amp;nbsp;neighbours(&#039;&#039;i&#039;&#039;) indicates that spin &#039;&#039;j&#039;&#039; must lie in a lattice cell adjacent to spin &#039;&#039;i&#039;&#039;. The factor of one half is included to make sure that we do not count each spin-spin interaction twice.&lt;br /&gt;
* Periodic boundary conditions are applied. In other words, the &amp;quot;final&amp;quot; spin in a particular direction is considered to be adjacent to the &amp;quot;first&amp;quot; spin in that direction. In &#039;&#039;&#039;figure 2&#039;&#039;&#039;, for example, cell 1 has neighbour interactions with cells 2, 3, 4, and 7, while cell 9 interacts with cells 3, 6, 7, and 8.&lt;br /&gt;
&lt;br /&gt;
[[File:ThirdYearCMPExpt-IsingNumberedCell.png|300px|thumb|right|&#039;&#039;&#039;Figure 2&#039;&#039;&#039;: Illustration of a 2D Ising lattice, with numbered cells to indicate the neighbour interactions.]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1a&amp;lt;/big&amp;gt;: Show that the lowest possible energy for the Ising model (with &#039;&#039;J&#039;&#039;&amp;amp;gt;0) is &#039;&#039;E&#039;&#039;&amp;amp;nbsp;=&amp;amp;nbsp;-&#039;&#039;DNJ&#039;&#039;, where &#039;&#039;D&#039;&#039; is the number of dimensions and &#039;&#039;N&#039;&#039; is the total number of spins. What is the multiplicity of this state? Calculate its entropy.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Phase Transitions==&lt;br /&gt;
&lt;br /&gt;
The Ising model is interesting because it is one of the simplest physical models to display a phase transition (so long as we are in two dimensions or more). The temperature of the system controls the balance between the energetic driving force, which wants the system to adopt the lowest energy configuration that you imagined in the previous section, and the entropic driving force, which seeks to maximise the number of configurations available to the system.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1b&amp;lt;/big&amp;gt;: Imagine that the system is in the lowest energy configuration. To move to a different state, one of the spins must spontaneously change direction (&amp;quot;flip&amp;quot;). What is the change in energy if this happens (&#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000)? How much entropy does the system gain by doing so?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
At low temperatures, little thermal energy is available to overcome such energy barriers, and we expect the system to adopt the lowest energy (the energetic driving force will dominate). Under these conditions, we expect a large number of parallel spins, and we can characterise this by considering the total &#039;&#039;magnetisation&#039;&#039; of the system: &amp;lt;math&amp;gt;M = \sum_i s_i&amp;lt;/math&amp;gt;. At higher temperatures, however, enough thermal energy will be available that spins can flip relatively freely. Under these conditions, the entropic driving force should dominate. The transition temperature between the two regimes is called the &#039;&#039;Curie temperature&#039;&#039;, &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;. Below &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039;, we observe the highly ordered magnetised phase, while above &#039;&#039;T&amp;lt;sub&amp;gt;C&amp;lt;/sub&amp;gt;&#039;&#039; a disordered, demagnetised, phase emerges.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 1c&amp;lt;/big&amp;gt;: Calculate the magnetisation of the 1D and 2D lattices in figure 1. What magnetisation would you expect to observe for an Ising lattice with &#039;&#039;D&#039;&#039;=3, &#039;&#039;N&#039;&#039;=1000 at absolute zero?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We are interested, therefore, in determining the magnetisation &#039;&#039;M&#039;&#039;, and energy &#039;&#039;E&#039;&#039;, of the system as functions of temperature &#039;&#039;T&#039;&#039;. We can write statistical mechanical equations for these quantities:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle M\right\rangle_T = \frac{1}{Z}\sum_\alpha M\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\left\langle E\right\rangle_T = \frac{1}{Z}\sum_\alpha E\left(\alpha\right) \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &#039;&#039;&amp;amp;alpha;&#039;&#039; is used as a shorthand to represent all spins in the system, and &#039;&#039;Z&#039;&#039; is the partition function,&lt;br /&gt;
&amp;lt;math&amp;gt;Z = \sum_\alpha \exp \left\{-\frac{E\left(\alpha\right)}{k_BT}\right\} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It was discovered relatively quickly after the model was first proposed that the partition function in the one dimensional case can be solved analytically (though doing so is beyond the scope of this experiment):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Z\left(T, N\right) = \left[2\cosh\left(\frac{J}{k_BT}\right)\right]^N&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Much later, [http://en.wikipedia.org/wiki/Lars_Onsager Lars Onsager] established that the two dimensional partition function can also be found analytically, though the mathematics is significantly more involved and the resulting expression is correspondingly much more complicated. In dimensions greater than two, no analytical solution is known.&lt;br /&gt;
&lt;br /&gt;
Luckily for us, the problem can instead be tackled by numerical methods, and it is this that will be the focus of the experiment. We will discuss how the equations for &#039;&#039;M&#039;&#039; and &#039;&#039;E&#039;&#039; can be solved, but first we must set up a Python script to model the lattice.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;This is the first section of the Ising model experiment.&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Previous section:  [[Programming_a_2D_Ising_Model|Introduction page]]&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:blue; &amp;quot;&amp;gt;Next section: [[Third year CMP compulsory experiment/Calculating the energy and magnetisation|Calculating the energy and magnetisation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822024</id>
		<title>Programming a 2D Ising Model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822024"/>
		<updated>2026-02-12T12:20:11Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* Getting Help */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;This is the Ising Model experiment (aka programming for simple simulations). This is a core experiment for year 3 students on the Chemistry with Molecular Physics degree.&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
In this exercise, you are going to use the Python that you learned in the first year to write a code to perform Monte-Carlo simulations of the 2D [http://en.wikipedia.org/wiki/Ising_model Ising model], a set of spins on a lattice which is used to model ferromagnetic behaviour, and also to analyse the results of the simulation to find the heat capacity of the system and the Curie temperature &amp;amp;mdash; the temperature below which the system is able to maintain a spontaneous magnetisation.&lt;br /&gt;
&lt;br /&gt;
A more extensive introduction to the Ising Model will be given in the next page. This page gives some practical information about how the experiment. &lt;br /&gt;
&lt;br /&gt;
==Assessment==&lt;br /&gt;
&lt;br /&gt;
At the end of this experiment you must submit a report, writing up your findings. Each section of the experiment has a number of tasks that you should complete, labelled &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK&amp;lt;/big&amp;gt;&#039;&#039;&#039;. If this is a mathematical exercise, your report should contain a short summary of the solution. If it is a graphical exercise, you should include the relevant image. Your report should explain briefly what you did in each stage of the experiment, and what your findings were.&lt;br /&gt;
&lt;br /&gt;
The report should be submitted as a PDF file to Turnitin, created with your favourite word processor or LaTeX, and should contain the annotated source code of the Python scripts that your write during the experiment. For clarity, code included in the report should be written in a monospaced font (e.g. Courier), which in LaTeX can be easily achieved by placing your code inside a &amp;lt;code&amp;gt;\texttt{}&amp;lt;/code&amp;gt; command. &#039;&#039;&#039;The code, except where relevant to discussion, can be placed in an appendix.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As well as including relevant source code in your report, you should also submit a bundle with all your scripts and analysis code as a separate Blackboard submission.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===On the use of AI tools===&lt;br /&gt;
&lt;br /&gt;
The code you write for this experiment is assessed, and as per the [https://bb.imperial.ac.uk/bbcswebdav/pid-3344481-dt-content-rid-21115105_1/xid-21115105_1 department&#039;s guidelines on the use of AI], it is not acceptable to use generative AI tools to write computer code for this assignment.&lt;br /&gt;
&lt;br /&gt;
Writing computer programs yourself enhances your logical thinking and problem solving skills. Using generative AI tools to write your code makes you dumb. Don&#039;t choose to be dumb, don&#039;t use AI to write code for you.&lt;br /&gt;
&lt;br /&gt;
==Getting Help==&lt;br /&gt;
&lt;br /&gt;
The Graduate Teaching Assistants demonstrating this experiment are Fionn Carman and Lei Li. Demonstrators will be available in room 232A at the following times:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Demonstrator timetable&lt;br /&gt;
! !! Monday !! Tuesday !! Wednesday !! Thusrsday !! Friday&lt;br /&gt;
|-&lt;br /&gt;
| Morning || 10:00 - Experiment intro&amp;lt;br /&amp;gt; 10:00-13:00 - Fionn and Aidan || 10:00-13:00 - Ayse and Aidan|| || 10:00-13:00 - Fionn || 10:00-13:00 - Ayse and Aidan&lt;br /&gt;
|-&lt;br /&gt;
| Afternoon || 14:00-17:00 - Fionn|| 14:00-17:00 - Ayse  and Aidan|| || 14:00-16:00 - Fionn and Aidan || 14:00-17:00 - Ayse&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you have questions outside these times, please use the Discussion Board on Blackboard.&lt;br /&gt;
&lt;br /&gt;
João and Giuseppe are the members of academic staff responsible for this experiment. You are welcome to address your questions and comments to them.&lt;br /&gt;
&lt;br /&gt;
==Structure of this Experiment==&lt;br /&gt;
&lt;br /&gt;
This experimental manual has been broken up into a number of subsections. Direct links to each of them may be found below. You should attempt them in order, and you should complete all of them to finish the experiment.&lt;br /&gt;
&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model|Introduction to the Ising model]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Calculating the energy and magnetisation|Calculating the energy and magnetisation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction to Monte Carlo simulation|Introduction to the Monte Carlo simulation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Accelerating the code|Accelerating the code]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of temperature|The effect of temperature]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of system size|The effect of system size]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Determining the heat capacity|Determining the heat capacity]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Locating the Curie temperature|Locating the Curie temperature]]&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822023</id>
		<title>Programming a 2D Ising Model</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=822023"/>
		<updated>2026-02-12T12:19:45Z</updated>

		<summary type="html">&lt;p&gt;Gmallia: /* Assessment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;&amp;lt;big&amp;gt;This is the Ising Model experiment (aka programming for simple simulations). This is a core experiment for year 3 students on the Chemistry with Molecular Physics degree.&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
In this exercise, you are going to use the Python that you learned in the first year to write a code to perform Monte-Carlo simulations of the 2D [http://en.wikipedia.org/wiki/Ising_model Ising model], a set of spins on a lattice which is used to model ferromagnetic behaviour, and also to analyse the results of the simulation to find the heat capacity of the system and the Curie temperature &amp;amp;mdash; the temperature below which the system is able to maintain a spontaneous magnetisation.&lt;br /&gt;
&lt;br /&gt;
A more extensive introduction to the Ising Model will be given in the next page. This page gives some practical information about how the experiment. &lt;br /&gt;
&lt;br /&gt;
==Assessment==&lt;br /&gt;
&lt;br /&gt;
At the end of this experiment you must submit a report, writing up your findings. Each section of the experiment has a number of tasks that you should complete, labelled &#039;&#039;&#039;&amp;lt;big&amp;gt;TASK&amp;lt;/big&amp;gt;&#039;&#039;&#039;. If this is a mathematical exercise, your report should contain a short summary of the solution. If it is a graphical exercise, you should include the relevant image. Your report should explain briefly what you did in each stage of the experiment, and what your findings were.&lt;br /&gt;
&lt;br /&gt;
The report should be submitted as a PDF file to Turnitin, created with your favourite word processor or LaTeX, and should contain the annotated source code of the Python scripts that your write during the experiment. For clarity, code included in the report should be written in a monospaced font (e.g. Courier), which in LaTeX can be easily achieved by placing your code inside a &amp;lt;code&amp;gt;\texttt{}&amp;lt;/code&amp;gt; command. &#039;&#039;&#039;The code, except where relevant to discussion, can be placed in an appendix.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As well as including relevant source code in your report, you should also submit a bundle with all your scripts and analysis code as a separate Blackboard submission.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===On the use of AI tools===&lt;br /&gt;
&lt;br /&gt;
The code you write for this experiment is assessed, and as per the [https://bb.imperial.ac.uk/bbcswebdav/pid-3344481-dt-content-rid-21115105_1/xid-21115105_1 department&#039;s guidelines on the use of AI], it is not acceptable to use generative AI tools to write computer code for this assignment.&lt;br /&gt;
&lt;br /&gt;
Writing computer programs yourself enhances your logical thinking and problem solving skills. Using generative AI tools to write your code makes you dumb. Don&#039;t choose to be dumb, don&#039;t use AI to write code for you.&lt;br /&gt;
&lt;br /&gt;
==Getting Help==&lt;br /&gt;
&lt;br /&gt;
The Graduate Teaching Assistants demonstrating this experiment are Fionn Carman, Ayse Halkseven and Aidan Chapman. Demonstrators will be available in room 232A at the following times:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Demonstrator timetable&lt;br /&gt;
! !! Monday !! Tuesday !! Wednesday !! Thusrsday !! Friday&lt;br /&gt;
|-&lt;br /&gt;
| Morning || 10:00 - Experiment intro&amp;lt;br /&amp;gt; 10:00-13:00 - Fionn and Aidan || 10:00-13:00 - Ayse and Aidan|| || 10:00-13:00 - Fionn || 10:00-13:00 - Ayse and Aidan&lt;br /&gt;
|-&lt;br /&gt;
| Afternoon || 14:00-17:00 - Fionn|| 14:00-17:00 - Ayse  and Aidan|| || 14:00-16:00 - Fionn and Aidan || 14:00-17:00 - Ayse&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you have questions outside these times, please use the Discussion Board on Blackboard.&lt;br /&gt;
&lt;br /&gt;
João and Giuseppe are the members of academic staff responsible for this experiment. You are welcome to address your questions and comments to them.&lt;br /&gt;
&lt;br /&gt;
==Structure of this Experiment==&lt;br /&gt;
&lt;br /&gt;
This experimental manual has been broken up into a number of subsections. Direct links to each of them may be found below. You should attempt them in order, and you should complete all of them to finish the experiment.&lt;br /&gt;
&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction_to_the_Ising_model|Introduction to the Ising model]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Calculating the energy and magnetisation|Calculating the energy and magnetisation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Introduction to Monte Carlo simulation|Introduction to the Monte Carlo simulation]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Accelerating the code|Accelerating the code]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of temperature|The effect of temperature]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/The effect of system size|The effect of system size]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Determining the heat capacity|Determining the heat capacity]]&lt;br /&gt;
# [[Programming_a_2D_Ising_Model/Locating the Curie temperature|Locating the Curie temperature]]&lt;/div&gt;</summary>
		<author><name>Gmallia</name></author>
	</entry>
</feed>