<?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=Ac5116</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=Ac5116"/>
	<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/wiki/Special:Contributions/Ac5116"/>
	<updated>2026-05-17T20:43:30Z</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/Introduction_to_the_Ising_model&amp;diff=814790</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=814790"/>
		<updated>2025-03-04T15:26:14Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: Add the general expression of the partition function to avoid confusion.&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, &amp;lt;math&amp;gt;s_i&amp;lt;/math&amp;gt;, 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, &amp;lt;math&amp;gt;s_1&amp;lt;/math&amp;gt; to &amp;lt;math&amp;gt;s_N&amp;lt;/math&amp;gt;. 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=5x5), and three (N=5x5x5) 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 &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt; is a constant which controls the strength of interaction and the notation &amp;lt;math&amp;gt;j\  \in\  \mathrm{neighbours}\left(i\right)&amp;lt;/math&amp;gt; indicates that spin &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; must lie in a lattice cell adjacent to spin &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;. 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 &amp;lt;math&amp;gt;J&amp;gt;0&amp;lt;/math&amp;gt;) is &amp;lt;math&amp;gt;E\ =\ -DNJ&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; is the number of dimensions and &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; 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 (&amp;lt;math&amp;gt;D=3,\ N=1000&amp;lt;/math&amp;gt;)? 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;, &amp;lt;math&amp;gt;T_C&amp;lt;/math&amp;gt;. Below &amp;lt;math&amp;gt;T_C&amp;lt;/math&amp;gt;, we observe the highly ordered magnetised phase, while above &amp;lt;math&amp;gt;T_C&amp;lt;/math&amp;gt; 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 &amp;lt;math&amp;gt;D = 3,\ N=1000&amp;lt;/math&amp;gt; at absolute zero?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We are interested, therefore, in determining the magnetisation &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, and energy &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt;, of the system as functions of temperature &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;. 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 &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; is used as a shorthand to represent all spins in the system, and &amp;lt;math&amp;gt;Z&amp;lt;/math&amp;gt; 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 &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; 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. 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;/div&gt;</summary>
		<author><name>Ac5116</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=814789</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=814789"/>
		<updated>2025-03-03T10:00:49Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: Update hours&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;
The mark breakdown for the tasks is given below. You will also be assessed on the quality of the code and the report. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Task 1a-c&#039;&#039;&#039;: 6 marks &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Task 2a-b&#039;&#039;&#039;: 10 marks &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Task 3a-c&#039;&#039;&#039;: 12 marks&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Task 4a-c&#039;&#039;&#039;: 10 marks&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Task 5a-b&#039;&#039;&#039;: 12 marks&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Task 6&#039;&#039;&#039;: 10 marks&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Task 7a-b&#039;&#039;&#039;: 10 marks&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Task 8a-d&#039;&#039;&#039;: 20 marks  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Report + Code&#039;&#039;&#039;: 10 marks&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Total:&#039;&#039;&#039; 100 marks&lt;br /&gt;
&lt;br /&gt;
This mark will be divided by 5 and rounded to the nearest integer to obtain a final mark out of 20.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;The deadline for report submission is friday the 14&amp;lt;sup&amp;gt;th&amp;lt;/sup&amp;gt; of March at 18:00.&#039;&#039;&#039;&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>Ac5116</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=814786</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=814786"/>
		<updated>2025-03-02T23:09:37Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: more &amp;lt;code&amp;gt; blocks. Added a note about the origin of the scaling equation.&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. You can return to the previous page, [[Programming a 2D Ising Model/Determining the heat capacity|Determining the heat capacity]], or go back to the [[Programming a 2D Ising Model|Introduction]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&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 &amp;lt;math&amp;gt;T = T_C&amp;lt;/math&amp;gt;. 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 &amp;lt;math&amp;gt;T_{C, L}&amp;lt;/math&amp;gt; is the Curie temperature of an &amp;lt;math&amp;gt;L\times L&amp;lt;/math&amp;gt;lattice, &amp;lt;math&amp;gt;T_{C,\infty}&amp;lt;/math&amp;gt; is the Curie temperature of an infinite lattice, and &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; is a constant in which we are not especially interested. This scaling equation comes from expanding in the limit of large &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 8a&amp;lt;/big&amp;gt;: Reference data has been generated for longer simulations than would be possible on the college computers in Python. Each file contains six columns: &amp;lt;math&amp;gt;T, E, E^2, M, M^2, C&amp;lt;/math&amp;gt; (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;: Write a script to read the data from a particular file, and plot C and &amp;amp;chi; vs T, 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 &amp;lt;math&amp;gt;T_{\mathrm{min}}&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;T_{\mathrm{max}}&amp;lt;/math&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;: 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: peak_T_range, containing 1000 equally spaced temperature values between &amp;lt;math&amp;gt;T_{\mathrm{min}}&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;T_{\mathrm{max}}&amp;lt;/math&amp;gt; (whatever you chose those values to be), and fitted_C_values, containing the fitted heat capacity at each of those points. Use the NumPy max function to find the maximum in C. If you store the maximum value of C in the variable Cmax, 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;: Find the temperature at which the maximum in C occurs for each datafile that you were given or generated with Python. Make a text file containing two colums: the lattice side length (2,4,8, etc.), and the temperature at which C is a maximum. This is your estimate of &amp;lt;math&amp;gt;T_C&amp;lt;/math&amp;gt; for that side length. Make a plot that uses the scaling relation given above to determine &amp;lt;math&amp;gt;T_{C,\infty}&amp;lt;/math&amp;gt;. 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. You can return to the previous page, [[Programming a 2D Ising Model/Determining the heat capacity|Determining the heat capacity]], or go back to the [[Programming a 2D Ising Model|Introduction]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</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=814785</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=814785"/>
		<updated>2025-03-02T23:07:13Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* Calculating the heat capacity */&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. You can return to the previous page, [[Programming a 2D Ising Model/The effect of system size|The effect of system size]], or jump ahead to the next section, [[Programming a 2D Ising Model/Locating the Curie temperature|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 &amp;lt;math&amp;gt;T_C&amp;lt;/math&amp;gt; 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 &amp;lt;math&amp;gt;T = T_C&amp;lt;/math&amp;gt; exactly, &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; diverges).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 7a&amp;lt;/big&amp;gt;: 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, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt;, 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;: 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, &amp;lt;math&amp;gt;\mathrm{Var}[X]&amp;lt;/math&amp;gt;, the mean of its square &amp;lt;math&amp;gt;\left\langle X^2\right\rangle&amp;lt;/math&amp;gt;, and its squared mean &amp;lt;math&amp;gt;\left\langle X\right\rangle^2&amp;lt;/math&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. You can return to the previous page, [[Programming a 2D Ising Model/The effect of system size|The effect of system size]], or jump ahead to the next section, [[Programming a 2D Ising Model/Locating the Curie temperature|Locating the Curie temperature]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</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=814784</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=814784"/>
		<updated>2025-03-02T23:05:23Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: &amp;lt;code&amp;gt; blocks&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. You can return to the previous page, [[Programming a 2D Ising Model/The effect of temperature|The effect of temperature]], or jump ahead to the next section, [[Programming a 2D Ising Model/Determining the heat capacity|Determining the heat capacity]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&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;: 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. You can return to the previous page, [[Programming a 2D Ising Model/The effect of temperature|The effect of temperature]], or jump ahead to the next section, [[Programming a 2D Ising Model/Determining the heat capacity|Determining the heat capacity]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</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=814783</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=814783"/>
		<updated>2025-03-02T23:03:22Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: add code blocks. Warn about off-by-one errors.&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. You can return to the previous page, [[Programming a 2D Ising Model/Accelerating the code|Accelerating the code]], or jump ahead to the next section, [[Programming a 2D Ising Model/The effect of system size|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 &amp;lt;math&amp;gt;N_\mathrm{spins}&amp;lt;/math&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 &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; 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 &#039;&#039;np.arange&#039;&#039; function near the top of the file. Starting from a uniformly aligned lattice, a simulation of length n_steps will be performed at temperature T_cold, and the average energy and magnetisation will be recorded. A new simulation of length n_steps will then be performed at temperature T_cold + dT, 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: ave_energies, ave_sqenergies (squared energies), ave_magnetisations, ave_sqmagnetisations (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 savetxt() 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. You can return to the previous page, [[Programming a 2D Ising Model/Accelerating the code|Accelerating the code]], or jump ahead to the next section, [[Programming a 2D Ising Model/The effect of system size|The effect of system size]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Accelerating_the_code&amp;diff=814782</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=814782"/>
		<updated>2025-03-02T23:01:09Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: typos and grammar&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. You can return to the previous page, [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|Introduction to Monte Carlo simulation]], or jump ahead to the next section, [[Programming a 2D Ising Model/The effect of temperature|The effect of temperature]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&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). &lt;br /&gt;
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;
&#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. You can return to the previous page, [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|Introduction to Monte Carlo simulation]], or jump ahead to the next section, [[Programming a 2D Ising Model/The effect of temperature|The effect of temperature]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Accelerating_the_code&amp;diff=814781</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=814781"/>
		<updated>2025-03-02T23:00:23Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: Highlight where code should be added to the report. Point out difference between profile and timetrial&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. You can return to the previous page, [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|Introduction to Monte Carlo simulation]], or jump ahead to the next section, [[Programming a 2D Ising Model/The effect of temperature|The effect of temperature]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&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). &lt;br /&gt;
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 mesaures 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 ther 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;
&#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. You can return to the previous page, [[Programming a 2D Ising Model/Introduction to Monte Carlo simulation|Introduction to Monte Carlo simulation]], or jump ahead to the next section, [[Programming a 2D Ising Model/The effect of temperature|The effect of temperature]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</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=814780</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=814780"/>
		<updated>2025-03-02T22:56:06Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: Emphasise code adding code to report. Highlight code with &amp;lt;code&amp;gt; blocks. Correct reduced units defnition&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;lt;math&amp;gt;\left\langle M\right\rangle_T&amp;lt;/math&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 &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; 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, &amp;lt;math&amp;gt;\alpha_0&amp;lt;/math&amp;gt;, with energy &amp;lt;math&amp;gt;E_0&amp;lt;/math&amp;gt;.&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 &amp;lt;math&amp;gt;\alpha_1&amp;lt;/math&amp;gt;&lt;br /&gt;
# Calculate the energy of this new configuration, &amp;lt;math&amp;gt;E_1&amp;lt;/math&amp;gt;&lt;br /&gt;
# Calculate the energy difference between the states, &amp;lt;math&amp;gt;\Delta E = E_1 - E_0&amp;lt;/math&amp;gt;&lt;br /&gt;
## If the &amp;lt;math&amp;gt;\Delta E \leq 0&amp;lt;/math&amp;gt; (the spin flipping decreased the energy), then we &#039;&#039;&#039;accept&#039;&#039;&#039; the new configuration.&lt;br /&gt;
##* We set &amp;lt;math&amp;gt;\alpha_0 = \alpha_1&amp;lt;/math&amp;gt;, and &amp;lt;math&amp;gt;E_0 = E_1&amp;lt;/math&amp;gt;, and then &#039;&#039;&#039;go to step 5&#039;&#039;&#039;&lt;br /&gt;
## If &amp;lt;math&amp;gt;\Delta E &amp;gt; 0&amp;lt;/math&amp;gt;, the spin flipping increased the energy. By considering the probability of observing the starting and final states, &amp;lt;math&amp;gt;\alpha_0&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;\alpha_1&amp;lt;/math&amp;gt;, 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, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, in the interval &amp;lt;math&amp;gt;[0,1)&amp;lt;/math&amp;gt;&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 &amp;lt;math&amp;gt;\alpha_0 = \alpha_1&amp;lt;/math&amp;gt;, and &amp;lt;math&amp;gt;E_0 = E_1&amp;lt;/math&amp;gt;, 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;
###* &amp;lt;math&amp;gt;\alpha_0&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;E_0&amp;lt;/math&amp;gt; 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, &amp;lt;math&amp;gt;\Delta E&amp;lt;/math&amp;gt; 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 &amp;lt;math&amp;gt;N_\mathrm{spins}&amp;lt;/math&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. You may assume that the energy returned by your &amp;lt;code&amp;gt;energy()&amp;lt;/code&amp;gt; function is in units of &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt; and the temperature is in units &amp;lt;math&amp;gt;T^* = k_BT/J&amp;lt;/math&amp;gt;! 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;lt;math&amp;gt;&amp;lt;E&amp;gt;, &amp;lt;E^2&amp;gt;, &amp;lt;M&amp;gt;, &amp;lt;M^2&amp;gt;&amp;lt;/math&amp;gt;, and &amp;lt;math&amp;gt;N_\mathrm{steps}&amp;lt;/math&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;
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 &amp;lt;math&amp;gt;T=1.0&amp;lt;/math&amp;gt;, 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 &amp;lt;math&amp;gt;T &amp;lt; T_C&amp;lt;/math&amp;gt;, do you expect a spontaneous magnetisation (i.e. do you expect &amp;lt;math&amp;gt;\left\langle M\right\rangle \neq 0&amp;lt;/math&amp;gt;)? 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 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;/div&gt;</summary>
		<author><name>Ac5116</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=814779</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=814779"/>
		<updated>2025-03-02T22:45:08Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: Added link to the Metropolis Paper&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;lt;math&amp;gt;\left\langle M\right\rangle_T&amp;lt;/math&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 &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; 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, &amp;lt;math&amp;gt;\alpha_0&amp;lt;/math&amp;gt;, with energy &amp;lt;math&amp;gt;E_0&amp;lt;/math&amp;gt;.&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 &amp;lt;math&amp;gt;\alpha_1&amp;lt;/math&amp;gt;&lt;br /&gt;
# Calculate the energy of this new configuration, &amp;lt;math&amp;gt;E_1&amp;lt;/math&amp;gt;&lt;br /&gt;
# Calculate the energy difference between the states, &amp;lt;math&amp;gt;\Delta E = E_1 - E_0&amp;lt;/math&amp;gt;&lt;br /&gt;
## If the &amp;lt;math&amp;gt;\Delta E \leq 0&amp;lt;/math&amp;gt; (the spin flipping decreased the energy), then we &#039;&#039;&#039;accept&#039;&#039;&#039; the new configuration.&lt;br /&gt;
##* We set &amp;lt;math&amp;gt;\alpha_0 = \alpha_1&amp;lt;/math&amp;gt;, and &amp;lt;math&amp;gt;E_0 = E_1&amp;lt;/math&amp;gt;, and then &#039;&#039;&#039;go to step 5&#039;&#039;&#039;&lt;br /&gt;
## If &amp;lt;math&amp;gt;\Delta E &amp;gt; 0&amp;lt;/math&amp;gt;, the spin flipping increased the energy. By considering the probability of observing the starting and final states, &amp;lt;math&amp;gt;\alpha_0&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;\alpha_1&amp;lt;/math&amp;gt;, 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, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, in the interval &amp;lt;math&amp;gt;[0,1)&amp;lt;/math&amp;gt;&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 &amp;lt;math&amp;gt;\alpha_0 = \alpha_1&amp;lt;/math&amp;gt;, and &amp;lt;math&amp;gt;E_0 = E_1&amp;lt;/math&amp;gt;, 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;
###* &amp;lt;math&amp;gt;\alpha_0&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;E_0&amp;lt;/math&amp;gt; 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, &amp;lt;math&amp;gt;\Delta E&amp;lt;/math&amp;gt; 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 &amp;lt;math&amp;gt;N_\mathrm{spins}&amp;lt;/math&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;montecarlostep(T)&#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: &#039;&#039;&#039;self.E_tally&#039;&#039;&#039;, &#039;&#039;&#039;self.E2_tally&#039;&#039;&#039;, &#039;&#039;&#039;self.M_tally&#039;&#039;&#039;, &#039;&#039;&#039;self.M2_tally&#039;&#039;&#039;, and &#039;&#039;&#039;self.n_steps&#039;&#039;&#039;. You should use these values to keep a running sum of all of 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 &#039;&#039;&#039;statistics()&#039;&#039;&#039;, that takes no arguments.&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 montecarlostep(T) function. This function should return the energy of your lattice and the magnetisation at the end of the cycle. You may assume that the energy returned by your energy() function is in units of &amp;lt;math&amp;gt;k_B&amp;lt;/math&amp;gt;! Complete the statistics() function. This should return the following quantities whenever it is called: &amp;lt;math&amp;gt;&amp;lt;E&amp;gt;, &amp;lt;E^2&amp;gt;, &amp;lt;M&amp;gt;, &amp;lt;M^2&amp;gt;&amp;lt;/math&amp;gt;, and the number of Monte Carlo steps that have elapsed.&#039;&#039;&#039;&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 IsingLattice 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 &amp;lt;math&amp;gt;T=1.0&amp;lt;/math&amp;gt;, 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;statistics()&#039;&#039;&#039; function to print the average energy and magnetisation from the simulation.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3c&amp;lt;/big&amp;gt;: If &amp;lt;math&amp;gt;T &amp;lt; T_C&amp;lt;/math&amp;gt;, do you expect a spontaneous magnetisation (i.e. do you expect &amp;lt;math&amp;gt;\left\langle M\right\rangle \neq 0&amp;lt;/math&amp;gt;)? 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 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;/div&gt;</summary>
		<author><name>Ac5116</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=814778</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=814778"/>
		<updated>2025-03-02T22:35:33Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: Emphasise code adding code to report. Highlight code with &amp;lt;code&amp;gt; blocks. Correct reduced units defnition&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;
==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;
To perform some of the analysis tasks later in the experiment, you may want to use a Jupyter notebook. If running commands from a Jupyter notebook or IPython console, you should start the session by 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 you may need to restart the kernel)!&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 &amp;lt;math&amp;gt;J=1.0&amp;lt;/math&amp;gt; at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which all energies are a multiple of &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;, 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. You are welcome to do this yourself &amp;amp;mdash; from JupyterLab you can open an IPython console and simply type  &amp;lt;pre&amp;gt;import IsingLattice&amp;lt;/pre&amp;gt; then create objects of your class with the command &amp;lt;pre&amp;gt;il = IsingLattice.IsingLattice(n_rows, n_columns)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have also 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;
These sorts of test are useful because they are easier to write and faster to run and can be run automatically.&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>Ac5116</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=814683</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=814683"/>
		<updated>2024-03-08T13:26:40Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: &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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Determining the heat capacity|Determining the heat capacity]], or go back to the [[Third year CMP compulsory experiment|Introduction]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&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 &amp;lt;math&amp;gt;T = T_C&amp;lt;/math&amp;gt;. 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 &amp;lt;math&amp;gt;T_{C, L}&amp;lt;/math&amp;gt; is the Curie temperature of an &amp;lt;math&amp;gt;L\times L&amp;lt;/math&amp;gt;lattice, &amp;lt;math&amp;gt;T_{C,\infty}&amp;lt;/math&amp;gt; is the Curie temperature of an infinite lattice, and &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; is a constant in which we are not especially interested.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 8a&amp;lt;/big&amp;gt;: A C++ program has been used to run some much longer simulations than would be possible on the college computers in Python. Each file contains six columns: &amp;lt;math&amp;gt;T, E, E^2, M, M^2, C&amp;lt;/math&amp;gt; (NOTE: these final five quantities are normalised per spin, unlike your Python data), and you can read them with the NumPy loadtxt function as before. For each lattice size, plot the C++ data against your data. For &#039;&#039;one&#039;&#039; lattice size, save a PNG of this comparison and add it to your report &amp;amp;mdash; add a legend to the graph to label which is which. To do this, you will need to pass the label=&amp;quot;...&amp;quot; keyword to the plot function, then call the legend() function of the axis object (documentation [http://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes.legend here]).&#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 polyfit] and [http://docs.scipy.org/doc/numpy/reference/generated/numpy.polyval.html#numpy.polyval polyval] 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;: write a script to read the data from a particular file, and plot C and &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt; vs T, 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 PNG 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 &amp;lt;math&amp;gt;T_{\mathrm{min}}&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;T_{\mathrm{max}}&amp;lt;/math&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;: 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: peak_T_range, containing 1000 equally spaced temperature values between &amp;lt;math&amp;gt;T_{\mathrm{min}}&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;T_{\mathrm{max}}&amp;lt;/math&amp;gt; (whatever you chose those values to be), and fitted_C_values, containing the fitted heat capacity at each of those points. Use the NumPy max function to find the maximum in C. If you store the maximum value of C in the variable Cmax, 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;: find the temperature at which the maximum in C occurs for each datafile that you were given or generated with Python. Make a text file containing two colums: the lattice side length (2,4,8, etc.), and the temperature at which C is a maximum. This is your estimate of &amp;lt;math&amp;gt;T_C&amp;lt;/math&amp;gt; for that side length. Make a plot that uses the scaling relation given above to determine &amp;lt;math&amp;gt;T_{C,\infty}&amp;lt;/math&amp;gt;. By doing a little research online, 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 PNG 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Determining the heat capacity|Determining the heat capacity]], or go back to the [[Third year CMP compulsory experiment|Introduction]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Accelerating_the_code&amp;diff=814682</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=814682"/>
		<updated>2024-03-04T13:09:51Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: &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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to Monte Carlo simulation|Introduction to Monte Carlo simulation]], or jump ahead to the next section, [[Third year CMP compulsory experiment/The effect of temperature|The effect of temperature]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&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). &lt;br /&gt;
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 in C++, 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 C code 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;ILProfiling.py&amp;lt;/code&amp;gt; script 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. The data is outputted into a file which can be visualised with [https://jiffyclub.github.io/snakeviz/ snakeviz].&lt;br /&gt;
&lt;br /&gt;
If you run the script and open the file with snakeviz (you may first need to install it via anaconda),&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
snakeviz ising.prof&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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;
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 sum function]. You should be able to modify your magnetisation() 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 roll] and [http://docs.scipy.org/doc/numpy/reference/generated/numpy.multiply.html multiply] functions, and use these to replace your energy double loop (you will need to call roll and multiply twice!).&#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;
&#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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to Monte Carlo simulation|Introduction to Monte Carlo simulation]], or jump ahead to the next section, [[Third year CMP compulsory experiment/The effect of temperature|The effect of temperature]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</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=814681</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=814681"/>
		<updated>2024-03-04T13:04:12Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* Calculating the heat capacity */&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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/The effect of system size|The effect of system size]], or jump ahead to the next section, [[Third year CMP compulsory experiment/Locating the Curie temperature|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 &amp;lt;math&amp;gt;T_C&amp;lt;/math&amp;gt; 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 &amp;lt;math&amp;gt;T = T_C&amp;lt;/math&amp;gt; exactly, &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; diverges).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 7a&amp;lt;/big&amp;gt;: By definition,&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C = \frac{\partial \left\langle E\right\rangle}{\partial T}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;From this, show that&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C = \frac{\mathrm{Var}[E]}{k_B T^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&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;.)&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, &amp;lt;math&amp;gt;\chi&amp;lt;/math&amp;gt;, 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. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 7b&amp;lt;/big&amp;gt;: 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, &amp;lt;math&amp;gt;\mathrm{Var}[X]&amp;lt;/math&amp;gt;, the mean of its square &amp;lt;math&amp;gt;\left\langle X^2\right\rangle&amp;lt;/math&amp;gt;, and its squared mean &amp;lt;math&amp;gt;\left\langle X\right\rangle^2&amp;lt;/math&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 your a 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/The effect of system size|The effect of system size]], or jump ahead to the next section, [[Third year CMP compulsory experiment/Locating the Curie temperature|Locating the Curie temperature]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</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=814678</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=814678"/>
		<updated>2024-03-03T23:12:19Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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;
==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 Box [https://imperialcollegelondon.box.com/v/ising-lab-files here].&#039;&#039;&#039; If this link is broken you can alternatively try an older(slightly broken) version [https://github.com/niallj/ImperialChem-Year3CMPExpt/archive/master.zip here].&lt;br /&gt;
&lt;br /&gt;
We recommend you open the extracted folder with VSCode. This makes it easy to edit your code and run simulations all in one place.&lt;br /&gt;
&lt;br /&gt;
We recommend that you use Conda Prompt (Windows) or Terminal(Mac/Linux) to run your simulation scripts. This should be available on all the college computers, where you can access it through &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Anaconda (64-bit)&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Conda Prompt&#039;&#039;&#039;. On your own Mac or Linux computer you can simply type &#039;ipython&#039; into the terminal. You are very welcome to use the IPython Notebook, that you were introduced to last year, to perform some of the analysis tasks later in the experiment. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: QTConsole does not work for running the ILanim.py script you run later in the lab. The best solution is to just run the script from the command line using &#039;&#039;&#039;python ILanim.py&#039;&#039;&#039; (if you&#039;re in the directory where files are stored). On a Mac/Linux computer you run this from &#039;&#039;&#039;Terminal&#039;&#039;&#039; or on windows you can use the app &#039;Conda Prompt&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If running commands from a Jupyter Notebook or ipython terminal, you shuold start the session by 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 you may need to restart the console)!&lt;br /&gt;
&lt;br /&gt;
For this section of the experiment, you will need the files &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; and &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;. Extract them from the zip file to a convenient location in your OneDrive drive, then in your terminal or console use cd H:\... to change to the correct directory. &lt;br /&gt;
&lt;br /&gt;
Alternatively, open the folder in VS Code and create a new built-in terminal. Doing so opens the terminal in the correct folder.&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. Open this file in your favourite text editor. 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 functions that you will complete as you work through the experiment.&lt;br /&gt;
&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 that you may not have met before, by defining a &#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 IsingLattice:&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. Lines 5-10 of IsingLattice.py create 5 variables that every object of type IsingLattice has:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
E = 0.0&lt;br /&gt;
&lt;br /&gt;
E2 = 0.0&lt;br /&gt;
&lt;br /&gt;
M = 0.0&lt;br /&gt;
&lt;br /&gt;
M2 = 0.0&lt;br /&gt;
&lt;br /&gt;
n_steps = 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also functions defined, on lines 12, 17, 22, etc. We can see, for example, that each IsingLattice object has the functions energy(), magnetisation(), montecarlostep(T), and statistics() (the function __init__ will be explained shortly). Each of these functions 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() function 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 variables and functions belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the montecarlostep() function:&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 function energy() which is part of the IsingLattice class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;quot;self.&amp;quot; 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 function currently filled in is __init__. This is a special function 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 function 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 self.lattice 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 this function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html here].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions energy() and magnetisation(), which should return the energy of the lattice and the total magnetisation, respectively. In the energy() function you may assume that &amp;lt;math&amp;gt;J=1.0&amp;lt;/math&amp;gt; at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which &amp;lt;math&amp;gt;J=k_B&amp;lt;/math&amp;gt;, 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.&#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() functions, we need to test that they work correctly. You are welcome to do this yourself &amp;amp;mdash; from the IPython Qt console (ensuring that you are in the correct directory), you can simply type  &amp;lt;pre&amp;gt;import IsingLattice&amp;lt;/pre&amp;gt; then create objects of your class with the command &amp;lt;pre&amp;gt;il = IsingLattice.IsingLattice(n_rows, n_columns)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have also 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 VSCode terminal using the command &#039;&#039;&#039;&amp;lt;pre&amp;gt;python ILcheck.py&amp;lt;/pre&amp;gt; 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 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/en/8.0.x/ pytest] command in your terminal,&lt;br /&gt;
&amp;lt;pre&amp;gt;pytest&amp;lt;/pre&amp;gt;&lt;br /&gt;
These sorts of test are useful because they are easier to write and faster to run and can be run automatically.&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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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>Ac5116</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=814677</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=814677"/>
		<updated>2024-03-03T23:07:14Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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;
==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 Box [https://imperialcollegelondon.box.com/v/ising-lab-files here].&#039;&#039;&#039; If this link is broken you can alternatively try an older(slightly broken) version [https://github.com/niallj/ImperialChem-Year3CMPExpt/archive/master.zip here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We recommend that you use Conda Prompt (Windows) or Terminal(Mac/Linux) to do your simulation work. This should be available on all of the college computers, where you can access it through &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Anaconda (64-bit)&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Conda Prompt&#039;&#039;&#039;. On your own Mac or Linux computer you can simply type &#039;ipython&#039; into the terminal. You are very welcome to use the IPython Notebook, that you were introduced to last year, to perform some of the analysis tasks later in the experiment. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: QTConsole does not work for running the ILanim.py script you run later in the lab. The best solution is to just run the script from the command line using &#039;&#039;&#039;python ILanim.py&#039;&#039;&#039; (if you&#039;re in the directory where files are stored). On a Mac/Linux computer you run this from &#039;&#039;&#039;Terminal&#039;&#039;&#039; or on windows you can use the app &#039;Conda Prompt&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using the QTConsole, you should start the session by 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 you may need to restart the console)!&lt;br /&gt;
&lt;br /&gt;
For this section of the experiment, you will need the files &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; and &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;. Extract them from the zip file to a convenient location in your H drive, then in the IPython QTConsole use cd H:\... to move to the correct directory.&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. Open this file in your favourite text editor. 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 functions that you will complete as you work through the experiment.&lt;br /&gt;
&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 that you may not have met before, by defining a &#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 IsingLattice:&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. Lines 5-10 of IsingLattice.py create 5 variables that every object of type IsingLattice has:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
E = 0.0&lt;br /&gt;
&lt;br /&gt;
E2 = 0.0&lt;br /&gt;
&lt;br /&gt;
M = 0.0&lt;br /&gt;
&lt;br /&gt;
M2 = 0.0&lt;br /&gt;
&lt;br /&gt;
n_steps = 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also functions defined, on lines 12, 17, 22, etc. We can see, for example, that each IsingLattice object has the functions energy(), magnetisation(), montecarlostep(T), and statistics() (the function __init__ will be explained shortly). Each of these functions 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() function 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 variables and functions belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the montecarlostep() function:&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 function energy() which is part of the IsingLattice class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;quot;self.&amp;quot; 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 function currently filled in is __init__. This is a special function 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 function 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 self.lattice 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 this function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html here].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions energy() and magnetisation(), which should return the energy of the lattice and the total magnetisation, respectively. In the energy() function you may assume that &amp;lt;math&amp;gt;J=1.0&amp;lt;/math&amp;gt; at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which &amp;lt;math&amp;gt;J=k_B&amp;lt;/math&amp;gt;, 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.&#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() functions, we need to test that they work correctly. You are welcome to do this yourself &amp;amp;mdash; from the IPython Qt console (ensuring that you are in the correct directory), you can simply type  &amp;lt;pre&amp;gt;import IsingLattice&amp;lt;/pre&amp;gt; then create objects of your class with the command &amp;lt;pre&amp;gt;il = IsingLattice.IsingLattice(n_rows, n_columns)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have also 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 VSCode terminal using the command &#039;&#039;&#039;&amp;lt;pre&amp;gt;python ILcheck.py&amp;lt;/pre&amp;gt; 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 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/en/8.0.x/ pytest] command in your terminal,&lt;br /&gt;
&amp;lt;pre&amp;gt;pytest&amp;lt;/pre&amp;gt;&lt;br /&gt;
These sorts of test are useful because they are easier to write and faster to run and can be run automatically.&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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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>Ac5116</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=814676</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=814676"/>
		<updated>2024-03-03T22:58:19Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Accelerating the code|Accelerating the code]], or jump ahead to the next section, [[Third year CMP compulsory experiment/The effect of system size|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. How many cycles (remember a cycle is &amp;lt;math&amp;gt;N_\mathrm{spins}&amp;lt;/math&amp;gt; steps) are &#039;&#039;typically&#039;&#039; needed for the system to go from its random starting position to the equilibrium state? Modify your statistics() and montecarlostep() functions so that the first N cycles of the simulation are ignored when calculating the averages. 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 &#039;&#039;np.arange&#039;&#039; function near the top of the file. Starting from a random lattice, a simulation of length n_steps will be performed at temperature T_cold, and the average energy and magnetisation will be recorded. A new simulation of length n_steps will then be performed at temperature T_cold + dT, 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: ave_energies, ave_sqenergies (squared energies), ave_magnetisations, ave_sqmagnetisations (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 &amp;lt;math&amp;gt;8\times 8&amp;lt;/math&amp;gt; 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 savetxt() 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Accelerating the code|Accelerating the code]], or jump ahead to the next section, [[Third year CMP compulsory experiment/The effect of system size|The effect of system size]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</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=814675</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=814675"/>
		<updated>2024-03-03T22:56:14Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* Correcting the Averaging 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 fifth section of the third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Accelerating the code|Accelerating the code]], or jump ahead to the next section, [[Third year CMP compulsory experiment/The effect of system size|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. How many cycles (remember a cycle is &amp;lt;math&amp;gt;N_\mathrm{spins}&amp;lt;/math&amp;gt; steps) are &#039;&#039;typically&#039;&#039; needed for the system to go from its random starting position to the equilibrium state? Modify your statistics() and montecarlostep() functions so that the first N cycles of the simulation are ignored when calculating the averages. 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 &#039;&#039;np.arange&#039;&#039; function near the top of the file. Starting from a random lattice, a simulation of length n_steps will be performed at temperature T_cold, and the average energy and magnetisation will be recorded. A new simulation of length n_steps will then be performed at temperature T_cold + dT, 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: ave_energies, ave_sqenergies (squared energies), ave_magnetisations, ave_sqmagnetisations (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 &amp;lt;math&amp;gt;8\times 8&amp;lt;/math&amp;gt; lattice. 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 trend, but do not use a temperature spacing larger than 0.5. The NumPy function savetxt() 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Accelerating the code|Accelerating the code]], or jump ahead to the next section, [[Third year CMP compulsory experiment/The effect of system size|The effect of system size]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model/Accelerating_the_code&amp;diff=814674</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=814674"/>
		<updated>2024-03-03T22:51:06Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: Added extra details about why numpy has better performance and extension for delta energy method&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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to Monte Carlo simulation|Introduction to Monte Carlo simulation]], or jump ahead to the next section, [[Third year CMP compulsory experiment/The effect of temperature|The effect of temperature]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&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). &lt;br /&gt;
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 in C++, 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 C code 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;ILProfiling.py&amp;lt;/code&amp;gt; script 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. The data is outputted into a file which can be visualised with [https://jiffyclub.github.io/snakeviz/ snakeviz].&lt;br /&gt;
&lt;br /&gt;
If you run the script and open the file with snakeviz (you may first need to install it via anaconda),&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
snakeviz ising.prof&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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;
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 sum function]. You should be able to modify your magnetisation() 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 roll] and [http://docs.scipy.org/doc/numpy/reference/generated/numpy.multiply.html multiply] functions, and use these to replace your energy double loop (you will need to call roll and multiply twice!).&#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; Extension &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;
&#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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to Monte Carlo simulation|Introduction to Monte Carlo simulation]], or jump ahead to the next section, [[Third year CMP compulsory experiment/The effect of temperature|The effect of temperature]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</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=814673</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=814673"/>
		<updated>2024-03-03T22:43:03Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Calculating the energy and magnetisation|Calculating the energy and magnetisation]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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 &amp;lt;math&amp;gt;1\times 10^9&amp;lt;/math&amp;gt; configurations per second with our computer. How long will it take to evaluate a single value of &amp;lt;math&amp;gt;\left\langle M\right\rangle_T&amp;lt;/math&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 &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; 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 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 it first in its list of the [http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=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, &amp;lt;math&amp;gt;\alpha_0&amp;lt;/math&amp;gt;, with energy &amp;lt;math&amp;gt;E_0&amp;lt;/math&amp;gt;.&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 &amp;lt;math&amp;gt;\alpha_1&amp;lt;/math&amp;gt;&lt;br /&gt;
# Calculate the energy of this new configuration, &amp;lt;math&amp;gt;E_1&amp;lt;/math&amp;gt;&lt;br /&gt;
# Calculate the energy difference between the states, &amp;lt;math&amp;gt;\Delta E = E_1 - E_0&amp;lt;/math&amp;gt;&lt;br /&gt;
## If the &amp;lt;math&amp;gt;\Delta E \leq 0&amp;lt;/math&amp;gt; (the spin flipping decreased the energy), then we &#039;&#039;&#039;accept&#039;&#039;&#039; the new configuration.&lt;br /&gt;
##* We set &amp;lt;math&amp;gt;\alpha_0 = \alpha_1&amp;lt;/math&amp;gt;, and &amp;lt;math&amp;gt;E_0 = E_1&amp;lt;/math&amp;gt;, and then &#039;&#039;&#039;go to step 5&#039;&#039;&#039;&lt;br /&gt;
## If &amp;lt;math&amp;gt;\Delta E &amp;gt; 0&amp;lt;/math&amp;gt;, the spin flipping increased the energy. By considering the probability of observing the starting and final states, &amp;lt;math&amp;gt;\alpha_0&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;\alpha_1&amp;lt;/math&amp;gt;, 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, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, in the interval &amp;lt;math&amp;gt;[0,1)&amp;lt;/math&amp;gt;&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 &amp;lt;math&amp;gt;\alpha_0 = \alpha_1&amp;lt;/math&amp;gt;, and &amp;lt;math&amp;gt;E_0 = E_1&amp;lt;/math&amp;gt;, 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;
###* &amp;lt;math&amp;gt;\alpha_0&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;E_0&amp;lt;/math&amp;gt; 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, &amp;lt;math&amp;gt;\Delta E&amp;lt;/math&amp;gt; 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 &amp;lt;math&amp;gt;N_\mathrm{spins}&amp;lt;/math&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 &amp;quot;Understanding Molecular Simulation&amp;quot;, by Frenkel and Smit, but a discussion of this is not required for the experiment. You can find this as an ebook in the library [https://library-search.imperial.ac.uk/permalink/f/o1297h/TN_cdi_askewsholts_vlebooks_9780080519982 here]. Chapter 7 of &#039;Statistical Mechanics: Theory and Molecular Simulation&#039; 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;montecarlostep(T)&#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 to measure the average energy and magnetisation: &#039;&#039;&#039;self.E&#039;&#039;&#039;, &#039;&#039;&#039;self.E2&#039;&#039;&#039;, &#039;&#039;&#039;self.M&#039;&#039;&#039;, &#039;&#039;&#039;self.M2&#039;&#039;&#039;, and &#039;&#039;&#039;self.n_steps&#039;&#039;&#039;. You should use these values to keep a running sum of all of 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 &#039;&#039;&#039;statistics()&#039;&#039;&#039;, that takes no arguments.&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 montecarlostep(T) function. This function should return the energy of your lattice and the magnetisation at the end of the cycle. You may assume that the energy returned by your energy() function is in units of &amp;lt;math&amp;gt;k_B&amp;lt;/math&amp;gt;! Complete the statistics() function. This should return the following quantities whenever it is called: &amp;lt;math&amp;gt;&amp;lt;E&amp;gt;, &amp;lt;E^2&amp;gt;, &amp;lt;M&amp;gt;, &amp;lt;M^2&amp;gt;&amp;lt;/math&amp;gt;, and the number of Monte Carlo steps that have elapsed.&#039;&#039;&#039;&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 IsingLattice object to run a Monte Carlo simulation and display the output on the screen in real time. By default, this simulation will run an &amp;lt;math&amp;gt;8\times 8&amp;lt;/math&amp;gt; lattice at &amp;lt;math&amp;gt;T=1.0&amp;lt;/math&amp;gt;, 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;statistics()&#039;&#039;&#039; function to print the average energy and magnetisation from the simulation.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3c&amp;lt;/big&amp;gt;: If &amp;lt;math&amp;gt;T &amp;lt; T_C&amp;lt;/math&amp;gt;, do you expect a spontaneous magnetisation (i.e. do you expect &amp;lt;math&amp;gt;\left\langle M\right\rangle \neq 0&amp;lt;/math&amp;gt;)? 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 PNG 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Calculating the energy and magnetisation|Calculating the energy and magnetisation]], or jump ahead to the next section, [[Third year CMP compulsory experiment/Accelerating the code|Accelerating the code]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</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=814672</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=814672"/>
		<updated>2024-03-03T22:41:02Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* A note about Python Classes */&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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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;
==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 Box [https://imperialcollegelondon.box.com/v/ising-lab-files here].&#039;&#039;&#039; If this link is broken you can alternatively try an older(slightly broken) version [https://github.com/niallj/ImperialChem-Year3CMPExpt/archive/master.zip here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We recommend that you use Conda Prompt (Windows) or Terminal(Mac/Linux) to do your simulation work. This should be available on all of the college computers, where you can access it through &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Anaconda (64-bit)&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Conda Prompt&#039;&#039;&#039;. On your own Mac or Linux computer you can simply type &#039;ipython&#039; into the terminal. You are very welcome to use the IPython Notebook, that you were introduced to last year, to perform some of the analysis tasks later in the experiment. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: QTConsole does not work for running the ILanim.py script you run later in the lab. The best solution is to just run the script from the command line using &#039;&#039;&#039;python ILanim.py&#039;&#039;&#039; (if you&#039;re in the directory where files are stored). On a Mac/Linux computer you run this from &#039;&#039;&#039;Terminal&#039;&#039;&#039; or on windows you can use the app &#039;Conda Prompt&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using the QTConsole, you should start the session by 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 you may need to restart the console)!&lt;br /&gt;
&lt;br /&gt;
For this section of the experiment, you will need the files &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; and &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;. Extract them from the zip file to a convenient location in your H drive, then in the IPython QTConsole use cd H:\... to move to the correct directory.&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. Open this file in your favourite text editor. 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 functions that you will complete as you work through the experiment.&lt;br /&gt;
&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 that you may not have met before, by defining a &#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 IsingLattice:&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. Lines 5-10 of IsingLattice.py create 5 variables that every object of type IsingLattice has:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
E = 0.0&lt;br /&gt;
&lt;br /&gt;
E2 = 0.0&lt;br /&gt;
&lt;br /&gt;
M = 0.0&lt;br /&gt;
&lt;br /&gt;
M2 = 0.0&lt;br /&gt;
&lt;br /&gt;
n_steps = 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also functions defined, on lines 12, 17, 22, etc. We can see, for example, that each IsingLattice object has the functions energy(), magnetisation(), montecarlostep(T), and statistics() (the function __init__ will be explained shortly). Each of these functions 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() function 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 variables and functions belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the montecarlostep() function:&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 function energy() which is part of the IsingLattice class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;quot;self.&amp;quot; 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 function currently filled in is __init__. This is a special function 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 function 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 self.lattice 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 this function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html here].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions energy() and magnetisation(), which should return the energy of the lattice and the total magnetisation, respectively. In the energy() function you may assume that &amp;lt;math&amp;gt;J=1.0&amp;lt;/math&amp;gt; at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which &amp;lt;math&amp;gt;J=k_B&amp;lt;/math&amp;gt;, 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.&#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() functions, we need to test that they work correctly. You are welcome to do this yourself &amp;amp;mdash; from the IPython Qt console (ensuring that you are in the correct directory), you can simply type  &amp;lt;pre&amp;gt;import IsingLattice&amp;lt;/pre&amp;gt; then create objects of your class with the command &amp;lt;pre&amp;gt;il = IsingLattice.IsingLattice(n_rows, n_columns)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have also 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 IPython Qt console using the command &#039;&#039;&#039;&amp;lt;pre&amp;gt;%run ILcheck.py&amp;lt;/pre&amp;gt; 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 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/en/8.0.x/ pytest] command in your terminal,&lt;br /&gt;
&amp;lt;pre&amp;gt;pytest&amp;lt;/pre&amp;gt;&lt;br /&gt;
These sorts of test are useful because they are easier to write and faster to run and can be run automatically.&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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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>Ac5116</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=814671</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=814671"/>
		<updated>2024-03-03T22:40:17Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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;
==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 Box [https://imperialcollegelondon.box.com/v/ising-lab-files here].&#039;&#039;&#039; If this link is broken you can alternatively try an older(slightly broken) version [https://github.com/niallj/ImperialChem-Year3CMPExpt/archive/master.zip here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We recommend that you use Conda Prompt (Windows) or Terminal(Mac/Linux) to do your simulation work. This should be available on all of the college computers, where you can access it through &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Anaconda (64-bit)&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Conda Prompt&#039;&#039;&#039;. On your own Mac or Linux computer you can simply type &#039;ipython&#039; into the terminal. You are very welcome to use the IPython Notebook, that you were introduced to last year, to perform some of the analysis tasks later in the experiment. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: QTConsole does not work for running the ILanim.py script you run later in the lab. The best solution is to just run the script from the command line using &#039;&#039;&#039;python ILanim.py&#039;&#039;&#039; (if you&#039;re in the directory where files are stored). On a Mac/Linux computer you run this from &#039;&#039;&#039;Terminal&#039;&#039;&#039; or on windows you can use the app &#039;Conda Prompt&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using the QTConsole, you should start the session by 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 you may need to restart the console)!&lt;br /&gt;
&lt;br /&gt;
For this section of the experiment, you will need the files &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; and &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;. Extract them from the zip file to a convenient location in your H drive, then in the IPython QTConsole use cd H:\... to move to the correct directory.&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. Open this file in your favourite text editor. 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 functions that you will complete as you work through the experiment.&lt;br /&gt;
&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 that you may not have met before, by defining a &#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 IsingLattice:&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. Lines 5-10 of IsingLattice.py create 5 variables that every object of type IsingLattice has:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
E = 0.0&lt;br /&gt;
&lt;br /&gt;
E2 = 0.0&lt;br /&gt;
&lt;br /&gt;
M = 0.0&lt;br /&gt;
&lt;br /&gt;
M2 = 0.0&lt;br /&gt;
&lt;br /&gt;
n_steps = 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also functions defined, on lines 12, 17, 22, etc. We can see, for example, that each IsingLattice object has the functions energy(), magnetisation(), montecarlostep(T), and statistics() (the function __init__ will be explained shortly). Each of these functions 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;code&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() function of our IsingLattice object&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all variables and functions belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the montecarlostep() function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the function energy() which is part of the IsingLattice class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;quot;self.&amp;quot; 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 function currently filled in is __init__. This is a special function 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 function 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 self.lattice 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 this function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html here].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions energy() and magnetisation(), which should return the energy of the lattice and the total magnetisation, respectively. In the energy() function you may assume that &amp;lt;math&amp;gt;J=1.0&amp;lt;/math&amp;gt; at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which &amp;lt;math&amp;gt;J=k_B&amp;lt;/math&amp;gt;, 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.&#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() functions, we need to test that they work correctly. You are welcome to do this yourself &amp;amp;mdash; from the IPython Qt console (ensuring that you are in the correct directory), you can simply type  &amp;lt;pre&amp;gt;import IsingLattice&amp;lt;/pre&amp;gt; then create objects of your class with the command &amp;lt;pre&amp;gt;il = IsingLattice.IsingLattice(n_rows, n_columns)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have also 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 IPython Qt console using the command &#039;&#039;&#039;&amp;lt;pre&amp;gt;%run ILcheck.py&amp;lt;/pre&amp;gt; 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 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/en/8.0.x/ pytest] command in your terminal,&lt;br /&gt;
&amp;lt;pre&amp;gt;pytest&amp;lt;/pre&amp;gt;&lt;br /&gt;
These sorts of test are useful because they are easier to write and faster to run and can be run automatically.&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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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>Ac5116</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=814670</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=814670"/>
		<updated>2024-03-03T22:34:48Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* The Constructor */&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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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;
==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 Box [https://imperialcollegelondon.box.com/v/ising-lab-files here].&#039;&#039;&#039; If this link is broken you can alternatively try an older(slightly broken) version [https://github.com/niallj/ImperialChem-Year3CMPExpt/archive/master.zip here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We recommend that you use Conda Prompt (Windows) or Terminal(Mac/Linux) to do your simulation work. This should be available on all of the college computers, where you can access it through &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Anaconda (64-bit)&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Conda Prompt&#039;&#039;&#039;. On your own Mac or Linux computer you can simply type &#039;ipython&#039; into the terminal. You are very welcome to use the IPython Notebook, that you were introduced to last year, to perform some of the analysis tasks later in the experiment. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: QTConsole does not work for running the ILanim.py script you run later in the lab. The best solution is to just run the script from the command line using &#039;&#039;&#039;python ILanim.py&#039;&#039;&#039; (if you&#039;re in the directory where files are stored). On a Mac/Linux computer you run this from &#039;&#039;&#039;Terminal&#039;&#039;&#039; or on windows you can use the app &#039;Conda Prompt&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using the QTConsole, you should start the session by 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 you may need to restart the console)!&lt;br /&gt;
&lt;br /&gt;
For this section of the experiment, you will need the files &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; and &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;. Extract them from the zip file to a convenient location in your H drive, then in the IPython QTConsole use cd H:\... to move to the correct directory.&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. Open this file in your favourite text editor. 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 functions that you will complete as you work through the experiment.&lt;br /&gt;
&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 that you may not have met before, by defining a &#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 IsingLattice:&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. Lines 5-10 of IsingLattice.py create 5 variables that every object of type IsingLattice has:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
E = 0.0&lt;br /&gt;
&lt;br /&gt;
E2 = 0.0&lt;br /&gt;
&lt;br /&gt;
M = 0.0&lt;br /&gt;
&lt;br /&gt;
M2 = 0.0&lt;br /&gt;
&lt;br /&gt;
n_steps = 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also functions defined, on lines 12, 17, 22, etc. We can see, for example, that each IsingLattice object has the functions energy(), magnetisation(), montecarlostep(T), and statistics() (the function __init__ will be explained shortly). Each of these functions 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;code&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() function of our IsingLattice object&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all variables and functions belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the montecarlostep() function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the function energy() which is part of the IsingLattice class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;quot;self.&amp;quot; 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 function currently filled in is __init__. This is a special function 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 function 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 self.lattice 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 this function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html here].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions energy() and magnetisation(), which should return the energy of the lattice and the total magnetisation, respectively. In the energy() function you may assume that &amp;lt;math&amp;gt;J=1.0&amp;lt;/math&amp;gt; at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which &amp;lt;math&amp;gt;J=k_B&amp;lt;/math&amp;gt;, 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.&#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() functions, we need to test that they work correctly. You are welcome to do this yourself &amp;amp;mdash; from the IPython Qt console (ensuring that you are in the correct directory), you can simply type  &amp;lt;pre&amp;gt;import IsingLattice&amp;lt;/pre&amp;gt; then create objects of your class with the command &amp;lt;pre&amp;gt;il = IsingLattice.IsingLattice(n_rows, n_columns)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have also 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 IPython Qt console using the command &#039;&#039;&#039;&amp;lt;pre&amp;gt;%run ILcheck.py&amp;lt;/pre&amp;gt; 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 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;
&#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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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>Ac5116</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=814669</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=814669"/>
		<updated>2024-03-03T22:33:51Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* A note about Python Classes */&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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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;
==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 Box [https://imperialcollegelondon.box.com/v/ising-lab-files here].&#039;&#039;&#039; If this link is broken you can alternatively try an older(slightly broken) version [https://github.com/niallj/ImperialChem-Year3CMPExpt/archive/master.zip here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We recommend that you use Conda Prompt (Windows) or Terminal(Mac/Linux) to do your simulation work. This should be available on all of the college computers, where you can access it through &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Anaconda (64-bit)&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Conda Prompt&#039;&#039;&#039;. On your own Mac or Linux computer you can simply type &#039;ipython&#039; into the terminal. You are very welcome to use the IPython Notebook, that you were introduced to last year, to perform some of the analysis tasks later in the experiment. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: QTConsole does not work for running the ILanim.py script you run later in the lab. The best solution is to just run the script from the command line using &#039;&#039;&#039;python ILanim.py&#039;&#039;&#039; (if you&#039;re in the directory where files are stored). On a Mac/Linux computer you run this from &#039;&#039;&#039;Terminal&#039;&#039;&#039; or on windows you can use the app &#039;Conda Prompt&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using the QTConsole, you should start the session by 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 you may need to restart the console)!&lt;br /&gt;
&lt;br /&gt;
For this section of the experiment, you will need the files &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; and &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;. Extract them from the zip file to a convenient location in your H drive, then in the IPython QTConsole use cd H:\... to move to the correct directory.&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. Open this file in your favourite text editor. 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 functions that you will complete as you work through the experiment.&lt;br /&gt;
&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 that you may not have met before, by defining a &#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 IsingLattice:&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. Lines 5-10 of IsingLattice.py create 5 variables that every object of type IsingLattice has:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
E = 0.0&lt;br /&gt;
&lt;br /&gt;
E2 = 0.0&lt;br /&gt;
&lt;br /&gt;
M = 0.0&lt;br /&gt;
&lt;br /&gt;
M2 = 0.0&lt;br /&gt;
&lt;br /&gt;
n_steps = 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also functions defined, on lines 12, 17, 22, etc. We can see, for example, that each IsingLattice object has the functions energy(), magnetisation(), montecarlostep(T), and statistics() (the function __init__ will be explained shortly). Each of these functions 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;code&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() function of our IsingLattice object&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all variables and functions belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the montecarlostep() function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the function energy() which is part of the IsingLattice class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;quot;self.&amp;quot; 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 function currently filled in is __init__. This is a special function 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 function 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 self.lattice is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;pre&amp;gt;np.random.choice&amp;lt;/pre&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for this function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html here].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions energy() and magnetisation(), which should return the energy of the lattice and the total magnetisation, respectively. In the energy() function you may assume that &amp;lt;math&amp;gt;J=1.0&amp;lt;/math&amp;gt; at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which &amp;lt;math&amp;gt;J=k_B&amp;lt;/math&amp;gt;, 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.&#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() functions, we need to test that they work correctly. You are welcome to do this yourself &amp;amp;mdash; from the IPython Qt console (ensuring that you are in the correct directory), you can simply type  &amp;lt;pre&amp;gt;import IsingLattice&amp;lt;/pre&amp;gt; then create objects of your class with the command &amp;lt;pre&amp;gt;il = IsingLattice.IsingLattice(n_rows, n_columns)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have also 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 IPython Qt console using the command &#039;&#039;&#039;&amp;lt;pre&amp;gt;%run ILcheck.py&amp;lt;/pre&amp;gt; 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 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;
&#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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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>Ac5116</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=814668</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=814668"/>
		<updated>2024-03-03T22:30:03Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* A note about Python Classes */&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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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;
==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 Box [https://imperialcollegelondon.box.com/v/ising-lab-files here].&#039;&#039;&#039; If this link is broken you can alternatively try an older(slightly broken) version [https://github.com/niallj/ImperialChem-Year3CMPExpt/archive/master.zip here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We recommend that you use Conda Prompt (Windows) or Terminal(Mac/Linux) to do your simulation work. This should be available on all of the college computers, where you can access it through &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Anaconda (64-bit)&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Conda Prompt&#039;&#039;&#039;. On your own Mac or Linux computer you can simply type &#039;ipython&#039; into the terminal. You are very welcome to use the IPython Notebook, that you were introduced to last year, to perform some of the analysis tasks later in the experiment. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: QTConsole does not work for running the ILanim.py script you run later in the lab. The best solution is to just run the script from the command line using &#039;&#039;&#039;python ILanim.py&#039;&#039;&#039; (if you&#039;re in the directory where files are stored). On a Mac/Linux computer you run this from &#039;&#039;&#039;Terminal&#039;&#039;&#039; or on windows you can use the app &#039;Conda Prompt&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using the QTConsole, you should start the session by 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 you may need to restart the console)!&lt;br /&gt;
&lt;br /&gt;
For this section of the experiment, you will need the files &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; and &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;. Extract them from the zip file to a convenient location in your H drive, then in the IPython QTConsole use cd H:\... to move to the correct directory.&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. Open this file in your favourite text editor. 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 functions that you will complete as you work through the experiment.&lt;br /&gt;
&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 that you may not have met before, by defining a &#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 IsingLattice:&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. Lines 5-10 of IsingLattice.py create 5 variables that every object of type IsingLattice has:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
E = 0.0&lt;br /&gt;
&lt;br /&gt;
E2 = 0.0&lt;br /&gt;
&lt;br /&gt;
M = 0.0&lt;br /&gt;
&lt;br /&gt;
M2 = 0.0&lt;br /&gt;
&lt;br /&gt;
n_steps = 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also functions defined, on lines 12, 17, 22, etc. We can see, for example, that each IsingLattice object has the functions energy(), magnetisation(), montecarlostep(T), and statistics() (the function __init__ will be explained shortly). Each of these functions 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;code&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() function of our IsingLattice object&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all variables and functions belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the montecarlostep() function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the function energy() which is part of the IsingLattice class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;quot;self.&amp;quot; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&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;
&lt;br /&gt;
&amp;lt;/code&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 function currently filled in is __init__. This is a special function 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 function 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 self.lattice is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;pre&amp;gt;np.random.choice&amp;lt;/pre&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for this function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html here].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions energy() and magnetisation(), which should return the energy of the lattice and the total magnetisation, respectively. In the energy() function you may assume that &amp;lt;math&amp;gt;J=1.0&amp;lt;/math&amp;gt; at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which &amp;lt;math&amp;gt;J=k_B&amp;lt;/math&amp;gt;, 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.&#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() functions, we need to test that they work correctly. You are welcome to do this yourself &amp;amp;mdash; from the IPython Qt console (ensuring that you are in the correct directory), you can simply type  &amp;lt;pre&amp;gt;import IsingLattice&amp;lt;/pre&amp;gt; then create objects of your class with the command &amp;lt;pre&amp;gt;il = IsingLattice.IsingLattice(n_rows, n_columns)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have also 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 IPython Qt console using the command &#039;&#039;&#039;&amp;lt;pre&amp;gt;%run ILcheck.py&amp;lt;/pre&amp;gt; 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 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;
&#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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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>Ac5116</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=814667</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=814667"/>
		<updated>2024-03-03T22:28:51Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* Importance Sampling */&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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Calculating the energy and magnetisation|Calculating the energy and magnetisation]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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 &amp;lt;math&amp;gt;1\times 10^9&amp;lt;/math&amp;gt; configurations per second with our computer. How long will it take to evaluate a single value of &amp;lt;math&amp;gt;\left\langle M\right\rangle_T&amp;lt;/math&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 &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; 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 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 it first in its list of the [http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=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, &amp;lt;math&amp;gt;\alpha_0&amp;lt;/math&amp;gt;, with energy &amp;lt;math&amp;gt;E_0&amp;lt;/math&amp;gt;.&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 &amp;lt;math&amp;gt;\alpha_1&amp;lt;/math&amp;gt;&lt;br /&gt;
# Calculate the energy of this new configuration, &amp;lt;math&amp;gt;E_1&amp;lt;/math&amp;gt;&lt;br /&gt;
# Calculate the energy difference between the states, &amp;lt;math&amp;gt;\Delta E = E_1 - E_0&amp;lt;/math&amp;gt;&lt;br /&gt;
## If the &amp;lt;math&amp;gt;\Delta E \leq 0&amp;lt;/math&amp;gt; (the spin flipping decreased the energy), then we &#039;&#039;&#039;accept&#039;&#039;&#039; the new configuration.&lt;br /&gt;
##* We set &amp;lt;math&amp;gt;\alpha_0 = \alpha_1&amp;lt;/math&amp;gt;, and &amp;lt;math&amp;gt;E_0 = E_1&amp;lt;/math&amp;gt;, and then &#039;&#039;&#039;go to step 5&#039;&#039;&#039;&lt;br /&gt;
## If &amp;lt;math&amp;gt;\Delta E &amp;gt; 0&amp;lt;/math&amp;gt;, the spin flipping increased the energy. By considering the probability of observing the starting and final states, &amp;lt;math&amp;gt;\alpha_0&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;\alpha_1&amp;lt;/math&amp;gt;, 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, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, in the interval &amp;lt;math&amp;gt;[0,1)&amp;lt;/math&amp;gt;&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 &amp;lt;math&amp;gt;\alpha_0 = \alpha_1&amp;lt;/math&amp;gt;, and &amp;lt;math&amp;gt;E_0 = E_1&amp;lt;/math&amp;gt;, 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;
###* &amp;lt;math&amp;gt;\alpha_0&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;E_0&amp;lt;/math&amp;gt; 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, &amp;lt;math&amp;gt;\Delta E&amp;lt;/math&amp;gt; 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 &amp;lt;math&amp;gt;N_\mathrm{spins}&amp;lt;/math&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 &amp;quot;Understanding Molecular Simulation&amp;quot;, by Frenkel and Smit, but a discussion of this is not required for the experiment. You can find this as an ebook in the library [https://library-search.imperial.ac.uk/permalink/f/o1297h/TN_cdi_askewsholts_vlebooks_9780080519982 here]. Chapter 7 of &#039;Statistical Mechanics: Theory and Molecular Simulation&#039; 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;montecarlocycle(T)&#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 to measure the average energy and magnetisation: &#039;&#039;&#039;self.E&#039;&#039;&#039;, &#039;&#039;&#039;self.E2&#039;&#039;&#039;, &#039;&#039;&#039;self.M&#039;&#039;&#039;, &#039;&#039;&#039;self.M2&#039;&#039;&#039;, and &#039;&#039;&#039;self.n_cycles&#039;&#039;&#039;. You should use these values to keep a running sum of all of the energies, squared energies, magnetisations, and squared magnetisations that your system has sampled, as well as the number of cycles that have been performed. Finally, there is also a function &#039;&#039;&#039;statistics()&#039;&#039;&#039;, that takes no arguments.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3b&amp;lt;/big&amp;gt;: Implement a single cycle of the above algorithm in the montecarlocycle(T) function. This function should return the energy of your lattice and the magnetisation at the end of the cycle. You may assume that the energy returned by your energy() function is in units of &amp;lt;math&amp;gt;k_B&amp;lt;/math&amp;gt;! Complete the statistics() function. This should return the following quantities whenever it is called: &amp;lt;math&amp;gt;&amp;lt;E&amp;gt;, &amp;lt;E^2&amp;gt;, &amp;lt;M&amp;gt;, &amp;lt;M^2&amp;gt;&amp;lt;/math&amp;gt;, and the number of Monte Carlo steps that have elapsed.&#039;&#039;&#039;&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 IsingLattice object to run a Monte Carlo simulation and display the output on the screen in real time. By default, this simulation will run an &amp;lt;math&amp;gt;8\times 8&amp;lt;/math&amp;gt; lattice at &amp;lt;math&amp;gt;T=1.0&amp;lt;/math&amp;gt;, 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;statistics()&#039;&#039;&#039; function to print the average energy and magnetisation from the simulation.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3c&amp;lt;/big&amp;gt;: If &amp;lt;math&amp;gt;T &amp;lt; T_C&amp;lt;/math&amp;gt;, do you expect a spontaneous magnetisation (i.e. do you expect &amp;lt;math&amp;gt;\left\langle M\right\rangle \neq 0&amp;lt;/math&amp;gt;)? 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 PNG 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Calculating the energy and magnetisation|Calculating the energy and magnetisation]], or jump ahead to the next section, [[Third year CMP compulsory experiment/Accelerating the code|Accelerating the code]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</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=814236</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=814236"/>
		<updated>2023-03-13T15:09:50Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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;
==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 Box [https://imperialcollegelondon.box.com/v/ising-lab-files here].&#039;&#039;&#039; If this link is broken you can alternatively try an older(slightly broken) version [https://github.com/niallj/ImperialChem-Year3CMPExpt/archive/master.zip here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We recommend that you use Conda Prompt (Windows) or Terminal(Mac/Linux) to do your simulation work. This should be available on all of the college computers, where you can access it through &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Anaconda (64-bit)&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Conda Prompt&#039;&#039;&#039;. On your own Mac or Linux computer you can simply type &#039;ipython&#039; into the terminal. You are very welcome to use the IPython Notebook, that you were introduced to last year, to perform some of the analysis tasks later in the experiment. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: QTConsole does not work for running the ILanim.py script you run later in the lab. The best solution is to just run the script from the command line using &#039;&#039;&#039;python ILanim.py&#039;&#039;&#039; (if you&#039;re in the directory where files are stored). On a Mac/Linux computer you run this from &#039;&#039;&#039;Terminal&#039;&#039;&#039; or on windows you can use the app &#039;Conda Prompt&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using the QTConsole, you should start the session by 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 you may need to restart the console)!&lt;br /&gt;
&lt;br /&gt;
For this section of the experiment, you will need the files &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; and &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;. Extract them from the zip file to a convenient location in your H drive, then in the IPython QTConsole use cd H:\... to move to the correct directory.&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. Open this file in your favourite text editor. 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 functions that you will complete as you work through the experiment.&lt;br /&gt;
&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 that you may not have met before, by defining a &#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 IsingLattice:&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. Lines 5-10 of IsingLattice.py create 5 variables that every object of type IsingLattice has:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
E = 0.0&lt;br /&gt;
&lt;br /&gt;
E2 = 0.0&lt;br /&gt;
&lt;br /&gt;
M = 0.0&lt;br /&gt;
&lt;br /&gt;
M2 = 0.0&lt;br /&gt;
&lt;br /&gt;
n_cycles = 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also functions defined, on lines 12, 17, 22, etc. We can see, for example, that each IsingLattice object has the functions energy(), magnetisation(), montecarlostep(T), and statistics() (the function __init__ will be explained shortly). Each of these functions 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;code&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() function of our IsingLattice object&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all variables and functions belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the montecarlostep() function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the function energy() which is part of the IsingLattice class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;quot;self.&amp;quot; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&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;
&lt;br /&gt;
&amp;lt;/code&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 function currently filled in is __init__. This is a special function 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 function 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 self.lattice is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;pre&amp;gt;np.random.choice&amp;lt;/pre&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for this function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html here].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions energy() and magnetisation(), which should return the energy of the lattice and the total magnetisation, respectively. In the energy() function you may assume that &amp;lt;math&amp;gt;J=1.0&amp;lt;/math&amp;gt; at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which &amp;lt;math&amp;gt;J=k_B&amp;lt;/math&amp;gt;, 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.&#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() functions, we need to test that they work correctly. You are welcome to do this yourself &amp;amp;mdash; from the IPython Qt console (ensuring that you are in the correct directory), you can simply type  &amp;lt;pre&amp;gt;import IsingLattice&amp;lt;/pre&amp;gt; then create objects of your class with the command &amp;lt;pre&amp;gt;il = IsingLattice.IsingLattice(n_rows, n_columns)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have also 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 IPython Qt console using the command &#039;&#039;&#039;&amp;lt;pre&amp;gt;%run ILcheck.py&amp;lt;/pre&amp;gt; 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 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;
&#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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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>Ac5116</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=814235</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=814235"/>
		<updated>2023-03-13T15:08:36Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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;
==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 Box [https://imperialcollegelondon.box.com/v/ising-lab-files here].&#039;&#039;&#039; If this link is broken you can alternatively try an older(slightly broken) version [https://github.com/niallj/ImperialChem-Year3CMPExpt/archive/master.zip here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We recommend that you use the IPython Qt or the regular ipython console (which you can access via spyder) to do your simulation work. This should be available on all of the college computers, where you can access it through &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Anaconda (64-bit)&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;IPython QTConsole&#039;&#039;&#039;. On your own Mac or Linux computer you can simply type &#039;ipython&#039; into the terminal. You are very welcome to use the IPython Notebook, that you were introduced to last year, to perform some of the analysis tasks later in the experiment. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: QTConsole does not work for running the ILanim.py script you run later in the lab. The best solution is to just run the script from the command line using &#039;&#039;&#039;python ILanim.py&#039;&#039;&#039; (if you&#039;re in the directory where files are stored). On a Mac/Linux computer you run this from &#039;&#039;&#039;Terminal&#039;&#039;&#039; or on windows you can use the app &#039;Conda Prompt&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using the QTConsole, you should start the session by 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 you may need to restart the console)!&lt;br /&gt;
&lt;br /&gt;
For this section of the experiment, you will need the files &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; and &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;. Extract them from the zip file to a convenient location in your H drive, then in the IPython QTConsole use cd H:\... to move to the correct directory.&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. Open this file in your favourite text editor. 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 functions that you will complete as you work through the experiment.&lt;br /&gt;
&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 that you may not have met before, by defining a &#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 IsingLattice:&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. Lines 5-10 of IsingLattice.py create 5 variables that every object of type IsingLattice has:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
E = 0.0&lt;br /&gt;
&lt;br /&gt;
E2 = 0.0&lt;br /&gt;
&lt;br /&gt;
M = 0.0&lt;br /&gt;
&lt;br /&gt;
M2 = 0.0&lt;br /&gt;
&lt;br /&gt;
n_cycles = 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also functions defined, on lines 12, 17, 22, etc. We can see, for example, that each IsingLattice object has the functions energy(), magnetisation(), montecarlostep(T), and statistics() (the function __init__ will be explained shortly). Each of these functions 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;code&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() function of our IsingLattice object&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all variables and functions belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the montecarlostep() function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the function energy() which is part of the IsingLattice class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;quot;self.&amp;quot; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&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;
&lt;br /&gt;
&amp;lt;/code&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 function currently filled in is __init__. This is a special function 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 function 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 self.lattice is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;pre&amp;gt;np.random.choice&amp;lt;/pre&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for this function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html here].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions energy() and magnetisation(), which should return the energy of the lattice and the total magnetisation, respectively. In the energy() function you may assume that &amp;lt;math&amp;gt;J=1.0&amp;lt;/math&amp;gt; at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which &amp;lt;math&amp;gt;J=k_B&amp;lt;/math&amp;gt;, 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.&#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() functions, we need to test that they work correctly. You are welcome to do this yourself &amp;amp;mdash; from the IPython Qt console (ensuring that you are in the correct directory), you can simply type  &amp;lt;pre&amp;gt;import IsingLattice&amp;lt;/pre&amp;gt; then create objects of your class with the command &amp;lt;pre&amp;gt;il = IsingLattice.IsingLattice(n_rows, n_columns)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have also 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 IPython Qt console using the command &#039;&#039;&#039;&amp;lt;pre&amp;gt;%run ILcheck.py&amp;lt;/pre&amp;gt; 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 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;
&#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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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>Ac5116</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Programming_a_2D_Ising_Model&amp;diff=814234</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=814234"/>
		<updated>2023-03-10T15:56:27Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* 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 students on the Chemistry with Molecular Physics degree. If you are not a CMP student, you might be looking for the 3&amp;lt;sup&amp;gt;rd&amp;lt;/sup&amp;gt; year [[Third_year_simulation_experiment|Liquid simulation experiment]].&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
In the first year, you were introduced to [https://www.python.org/ Python], a scripting language which is rapidly becoming the de facto language for everyday scientific programming. Python is an interpreted, rather than compiled language, and is rather more forgiving than older languages such as C or FORTRAN. This reduces the amount of time that we need to spend programming and debugging. The downside to all this is that the execution of a Python program is much slower than a compiled equivalent. As a compromise, we usually let large codes written in a compiled language (usually C/C++) do the hefty numerical work for us, and then use scripting languages like Python to analyse the results.&lt;br /&gt;
&lt;br /&gt;
These large codes for numerical work (you may have already used GAUSSIAN for electronic structure calculations) typically take arcane text files as input, and produce equally arcane text files as output. If, for the sake of example, you run twenty different molecular dynamics simulations, and each of them produces an output file which contains information about the density of the system, then extracting this information by hand would be very tedious (and if you run hundreds or thousands of simulations, virtually impossible), but this sort of task is the thing at which languages like Python really excel.&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;
==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;
&#039;&#039;&#039;YOU MUST SUBMIT YOUR REPORT ON BLACKBOARD BY 12 NOON ON THE WEDNESDAY FOLLOWING THE EXPERIMENT.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;Your report should contain the source code to *any* Python scripts that you write during the experiment, annotated with comments. You can write your report in Word or LaTeX, but you should submit a **single PDF file**.&amp;lt;/span&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The mark breakdown for the tasks is given below. You will also be assessed on the quality of the code and the report. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Task 1a-c&#039;&#039;&#039;: 6 marks &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Task 2a-b&#039;&#039;&#039;: 10 marks &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Task 3a-c&#039;&#039;&#039;: 12 marks&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Task 4a-c&#039;&#039;&#039;: 10 marks&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Task 5a-b&#039;&#039;&#039;: 12 marks&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Task 6&#039;&#039;&#039;: 10 marks&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Task 7a-b&#039;&#039;&#039;: 10 marks&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Task 8a-d&#039;&#039;&#039;: 20 marks  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Report + Code&#039;&#039;&#039;: 10 marks&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Total:&#039;&#039;&#039; 100 marks&lt;br /&gt;
&lt;br /&gt;
This mark will be divided by 5 and rounded to the nearest integer to obtain a final mark out of 20. &lt;br /&gt;
&lt;br /&gt;
For clarity, code included in the report should be written in a monospaced font (e.g. Courier) or a pasted screenshot. The former can be easily achieved in LaTeX 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;
If you wish, you are welcome to do the experiment on your own computer. You will need the [https://www.anaconda.com/products/individual Anaconda] scientific Python distribution (if you are a Windows, Mac or Linux user). You may ask for help with installing this, but it is not part of the experiment &amp;amp;mdash; students who have scientific questions will take priority.&lt;br /&gt;
&lt;br /&gt;
==Getting Help==&lt;br /&gt;
&lt;br /&gt;
The demonstrators for this exercise are Aidan Chapman (aidan.chapman16@imperial.ac.uk) and Jonathan Hedley (jonathan.hedley16@imperial.ac.uk). The assessors will be Aidan Chapman, Jonathan Hedley and Prof. Fernando Bresme. The demonstrators will be available in person between 10-12 and 2-3 pm on Monday and Thursday and 11-12 and 2-4pm on Tuesday and Friday (&#039;&#039;&#039;Note: the experiment does not &amp;quot;run&amp;quot; on Wednesdays&#039;&#039;&#039;). If you have questions outside these times, you are welcome to send them via e-mail.&lt;br /&gt;
&lt;br /&gt;
The member of academic staff responsible for this exercise is Prof. Fernando Bresme (f.bresme@imperial.ac.uk).&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;
# [[Third_year_CMP_compulsory_experiment/Introduction_to_the_Ising_model|Introduction to the Ising model]]&lt;br /&gt;
# [[Third_year_CMP_compulsory_experiment/Calculating the energy and magnetisation|Calculating the energy and magnetisation]]&lt;br /&gt;
# [[Third_year_CMP_compulsory_experiment/Introduction to Monte Carlo simulation|Introduction to the Monte Carlo simulation]]&lt;br /&gt;
# [[Third_year_CMP_compulsory_experiment/Accelerating the code|Accelerating the code]]&lt;br /&gt;
# [[Third_year_CMP_compulsory_experiment/The effect of temperature|The effect of temperature]]&lt;br /&gt;
# [[Third_year_CMP_compulsory_experiment/The effect of system size|The effect of system size]]&lt;br /&gt;
# [[Third_year_CMP_compulsory_experiment/Determining the heat capacity|Determining the heat capacity]]&lt;br /&gt;
# [[Third_year_CMP_compulsory_experiment/Locating the Curie temperature|Locating the Curie temperature]]&lt;/div&gt;</summary>
		<author><name>Ac5116</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Software_Instructions&amp;diff=813834</id>
		<title>Third year simulation experiment/Software Instructions</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Software_Instructions&amp;diff=813834"/>
		<updated>2021-10-22T12:27:28Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
==Running LAMMPS==&lt;br /&gt;
&lt;br /&gt;
===Command line basics ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==VMD==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Reading LAMMPS Log Files==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Installing LAMMPS On Your Own Machine (OPTIONAL)==&lt;br /&gt;
&lt;br /&gt;
==Accessing the  Virtual Machines==&lt;/div&gt;</summary>
		<author><name>Ac5116</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Software_Instructions&amp;diff=813833</id>
		<title>Third year simulation experiment/Software Instructions</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Software_Instructions&amp;diff=813833"/>
		<updated>2021-10-22T12:26:19Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: Created page with &amp;quot;==Running LAMMPS==  ===Command line basics ===   ==VMD==    ==Reading LAMMPS Log Files==   ==Installing LAMMPS On Your Own Machine (OPTIONAL)==&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Running LAMMPS==&lt;br /&gt;
&lt;br /&gt;
===Command line basics ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==VMD==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Reading LAMMPS Log Files==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Installing LAMMPS On Your Own Machine (OPTIONAL)==&lt;/div&gt;</summary>
		<author><name>Ac5116</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Structural_properties_and_the_radial_distribution_function&amp;diff=813827</id>
		<title>Third year simulation experiment/Structural properties and the radial distribution function</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Structural_properties_and_the_radial_distribution_function&amp;diff=813827"/>
		<updated>2021-10-20T13:31:52Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* Simulations in this section */&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 third year simulation experiment. You can return to the previous page, [[Third_year_simulation_experiment/Running_simulations_under_specific_conditions|Running simulations under specific conditions]], or jump ahead to the next section, [[Third year simulation experiment/Dynamical properties and the diffusion coefficient|Dynamical properties and the diffusion coefficient]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We can characterise the structure of systems that we simulate using [http://en.wikipedia.org/wiki/Radial_distribution_function radial distribution functions], which we denote &amp;lt;math&amp;gt;g(r)&amp;lt;/math&amp;gt;. Calculating the RDF for a simulation is very useful &amp;amp;mdash; it can tell us the distances from an atom at which we will find it&#039;s nearest neighbour, second nearest neighbour, and so on; it is also a quantity that can be accessed experimentally, and so provides a good check that the forcefield in our simulation is correctly reproducing the structural features.&lt;br /&gt;
&lt;br /&gt;
In this section, you are going to use VMD to calculate the radial distribution function for the solid, liquid, and vapour phases of the Lennard-Jones fluid.&lt;br /&gt;
&lt;br /&gt;
===Simulations in this section===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;RDF&#039;&#039;&#039; subfolder contains an example input script that you can use to record an atomic trajectory to generate RDFs for the solid, liquid, and vapour phase Lennard Jones systems. Make three copies of that script (one for each phase), and modify the density and temperature parameters to give the phase that you want (a phase diagram for the Lennard-Jones system can be found [http://journals.aps.org/pr/abstract/10.1103/PhysRev.184.151 here]). &amp;lt;big&amp;gt;&#039;&#039;&#039;Note: when simulating the solid, you will need to change the lattice type in the lattice command to fcc, rather than sc. &#039;&#039;&#039;&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 9: perform simulations of the Lennard-Jones system in the three phases. When each is complete, open the trajectories (.dump files) and calculate &amp;lt;math&amp;gt;g(r)&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;4\pi \int g(r) r^{2}\mathrm{d}r&amp;lt;/math&amp;gt;.  See instructions at the end of this page.&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Briefly explain what a Radial Distribution Function is. What is the relationship between the coordination number and RDF? [2] ===&lt;br /&gt;
&lt;br /&gt;
=== Plot the RDFs for the three systems. [2] ===&lt;br /&gt;
&lt;br /&gt;
=== Discuss qualitatively the differences between the three RDFs, and what this tells you about the structure of the system in each phase. [5] ===&lt;br /&gt;
&lt;br /&gt;
=== In the solid case, illustrate which lattice sites the first three peaks correspond to [2]. What is the lattice spacing [1]? What are the coordination number for each of the first three peaks [1]? ===&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 third year simulation experiment. You can return to the previous page, [[Third_year_simulation_experiment/Running simulations under specific conditions|Running simulations under specific conditions]], or jump ahead to the next section, [[Third year simulation experiment/Dynamical properties and the diffusion coefficient|Dynamical properties and the diffusion coefficient]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Calculating &amp;lt;math&amp;gt;g(r)&amp;lt;/math&amp;gt; in VMD===&lt;br /&gt;
&lt;br /&gt;
# Start VMD as before and load the trajectory that you want to analyse.&lt;br /&gt;
# Select &#039;&#039;&#039;Extensions&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Analysis&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Radial Pair Distribution Function g(r)&#039;&#039;&#039;&lt;br /&gt;
# Set &#039;&#039;&#039;Selection 1&#039;&#039;&#039; to &#039;&#039;&#039;all&#039;&#039;&#039; and &#039;&#039;&#039;Selection 2&#039;&#039;&#039; to &#039;&#039;&#039;all&#039;&#039;&#039;&lt;br /&gt;
# Change &#039;&#039;&#039;delta r&#039;&#039;&#039; to &#039;&#039;&#039;0.05&#039;&#039;&#039; &amp;amp;mdash; this is the distance between points in the generated RDF.&lt;br /&gt;
# Ensure that &#039;&#039;&#039;Use PBC&#039;&#039;&#039;, &#039;&#039;&#039;Display g(r)&#039;&#039;&#039;, &#039;&#039;&#039;Display Int(g(r))&#039;&#039;&#039;, and &#039;&#039;&#039;Save to File&#039;&#039;&#039; are checked&lt;br /&gt;
# Click &#039;&#039;&#039;Compute g(r)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
After a short pause while it performs the calculation, VMD will display both the RDF, and its running integral. You will then be prompted to save this data &amp;amp;mdash; choose a location for the file that you will be able to find easily later.&lt;/div&gt;</summary>
		<author><name>Ac5116</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Structural_properties_and_the_radial_distribution_function&amp;diff=813826</id>
		<title>Third year simulation experiment/Structural properties and the radial distribution function</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Structural_properties_and_the_radial_distribution_function&amp;diff=813826"/>
		<updated>2021-10-20T13:29:39Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* Simulations in this section */&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 third year simulation experiment. You can return to the previous page, [[Third_year_simulation_experiment/Running_simulations_under_specific_conditions|Running simulations under specific conditions]], or jump ahead to the next section, [[Third year simulation experiment/Dynamical properties and the diffusion coefficient|Dynamical properties and the diffusion coefficient]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We can characterise the structure of systems that we simulate using [http://en.wikipedia.org/wiki/Radial_distribution_function radial distribution functions], which we denote &amp;lt;math&amp;gt;g(r)&amp;lt;/math&amp;gt;. Calculating the RDF for a simulation is very useful &amp;amp;mdash; it can tell us the distances from an atom at which we will find it&#039;s nearest neighbour, second nearest neighbour, and so on; it is also a quantity that can be accessed experimentally, and so provides a good check that the forcefield in our simulation is correctly reproducing the structural features.&lt;br /&gt;
&lt;br /&gt;
In this section, you are going to use VMD to calculate the radial distribution function for the solid, liquid, and vapour phases of the Lennard-Jones fluid.&lt;br /&gt;
&lt;br /&gt;
===Simulations in this section===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;RDF&#039;&#039;&#039; subfolder contains an example input script that you can use to record an atomic trajectory to generate RDFs for the solid, liquid, and vapour phase Lennard Jones systems. Make three copies of that script (one for each phase), and modify the density and temperature parameters to give the phase that you want (a phase diagram for the Lennard-Jones system can be found [http://journals.aps.org/pr/abstract/10.1103/PhysRev.184.151 here]). &amp;lt;big&amp;gt;&#039;&#039;&#039;Note: when simulating the solid, you will need to change the lattice type in the lattice command to fcc, rather than sc.&#039;&#039;&#039;&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 9: perform simulations of the Lennard-Jones system in the three phases. When each is complete, download the trajectory and calculate &amp;lt;math&amp;gt;g(r)&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;4\pi \int g(r) r^{2}\mathrm{d}r&amp;lt;/math&amp;gt;.  See instructions at the end of this page.&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Briefly explain what a Radial Distribution Function is. What is the relationship between the coordination number and RDF? [2] ===&lt;br /&gt;
&lt;br /&gt;
=== Plot the RDFs for the three systems. [2] ===&lt;br /&gt;
&lt;br /&gt;
=== Discuss qualitatively the differences between the three RDFs, and what this tells you about the structure of the system in each phase. [5] ===&lt;br /&gt;
&lt;br /&gt;
=== In the solid case, illustrate which lattice sites the first three peaks correspond to [2]. What is the lattice spacing [1]? What are the coordination number for each of the first three peaks [1]? ===&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 third year simulation experiment. You can return to the previous page, [[Third_year_simulation_experiment/Running simulations under specific conditions|Running simulations under specific conditions]], or jump ahead to the next section, [[Third year simulation experiment/Dynamical properties and the diffusion coefficient|Dynamical properties and the diffusion coefficient]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Calculating &amp;lt;math&amp;gt;g(r)&amp;lt;/math&amp;gt; in VMD===&lt;br /&gt;
&lt;br /&gt;
# Start VMD as before and load the trajectory that you want to analyse.&lt;br /&gt;
# Select &#039;&#039;&#039;Extensions&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Analysis&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Radial Pair Distribution Function g(r)&#039;&#039;&#039;&lt;br /&gt;
# Set &#039;&#039;&#039;Selection 1&#039;&#039;&#039; to &#039;&#039;&#039;all&#039;&#039;&#039; and &#039;&#039;&#039;Selection 2&#039;&#039;&#039; to &#039;&#039;&#039;all&#039;&#039;&#039;&lt;br /&gt;
# Change &#039;&#039;&#039;delta r&#039;&#039;&#039; to &#039;&#039;&#039;0.05&#039;&#039;&#039; &amp;amp;mdash; this is the distance between points in the generated RDF.&lt;br /&gt;
# Ensure that &#039;&#039;&#039;Use PBC&#039;&#039;&#039;, &#039;&#039;&#039;Display g(r)&#039;&#039;&#039;, &#039;&#039;&#039;Display Int(g(r))&#039;&#039;&#039;, and &#039;&#039;&#039;Save to File&#039;&#039;&#039; are checked&lt;br /&gt;
# Click &#039;&#039;&#039;Compute g(r)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
After a short pause while it performs the calculation, VMD will display both the RDF, and its running integral. You will then be prompted to save this data &amp;amp;mdash; choose a location for the file that you will be able to find easily later.&lt;/div&gt;</summary>
		<author><name>Ac5116</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Running_simulations_under_specific_conditions&amp;diff=813825</id>
		<title>Third year simulation experiment/Running simulations under specific conditions</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Running_simulations_under_specific_conditions&amp;diff=813825"/>
		<updated>2021-10-20T13:19:41Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* Temperature and Pressure Control */&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 third year simulation experiment. You can return to the previous page, [[Third_year_simulation_experiment/Equilibration|Equilibration]], or jump ahead to the next section, [[Third_year_simulation_experiment/Structural_properties_and_the_radial_distribution_function| Structural Properties and the Radial Distribution Functions]].&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;THE FILES THAT YOU NEED FOR THIS SECTION ARE FOUND IN THE &amp;quot;NpT&amp;quot; SUBFOLDER.&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Changing Ensemble==&lt;br /&gt;
&lt;br /&gt;
So far, we have been able to do some simulations in which the number of particles and the volume of the simulation cell are held constant. The energy is also constant (within a certain degree of error, which is introduced by the approximations that we make to do the simulation). If the simulation is a working properly, then the pressure and temperature of the system should also reach a constant &#039;&#039;average&#039;&#039; value (although there will again be fluctuations). In the statistical thermodynamics lectures, you met the concept of ensembles, which are used in statistical mechanics to represent different sorts of experimental conditions. The simulations we have done so far are described by the &#039;&#039;microcanonical&#039;&#039;, or NVE ensemble (the letters represent those thermodynamic quantities which are constant).&lt;br /&gt;
&lt;br /&gt;
As chemists, we often want to understand what happens under particular experimental conditions &amp;amp;mdash; at 298K under 1 atmosphere of pressure, for example. These sorts of conditions are described by different ensembles in statistical mechanics, such as the NVT (&#039;&#039;canonical&#039;&#039;) or NpT (&#039;&#039;isobaric-isothermal&#039;&#039;) ensembles.&lt;br /&gt;
&lt;br /&gt;
In this section, we are going to modify our simulations from the previous section to run under NpT conditions, and sketch an equation of state for our model fluid at atmospheric pressure.&lt;br /&gt;
&lt;br /&gt;
==Temperature and Pressure Control==&lt;br /&gt;
&lt;br /&gt;
The file npt.in can be used to perform a constant temperature/pressure simulation of our model fluid. It starts by melting a simple cubic crystal, just as before, so much of this file will look familiar to you. You will notice a new section near the top, however, called &#039;&#039;&#039;### SPECIFY THE REQUIRED THERMODYNAMIC STATE ###&#039;&#039;&#039;. It contains three &#039;&#039;variables&#039;&#039; &amp;amp;mdash; these are used by the script later on to define the desired temperature, pressure, and timestep. The ellipses need to be replaced by the actual temperature, pressure and timestep that you want to use, so&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
variable T equal 0.5&lt;br /&gt;
variable p equal 1.0&lt;br /&gt;
variable timestep equal 0.75&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
would run a simulation at &amp;lt;math&amp;gt;T=0.5,\  p=1.0,\  \delta t=0.75&amp;lt;/math&amp;gt;. You should remember from the [[Third_year_simulation_experiment/Equilibration|Equilibration]] section that this is a poor choice of timestep!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 8: Choose 5 temperatures (above the critical temperature &amp;lt;math&amp;gt;T^* = 1.5&amp;lt;/math&amp;gt;), and two pressures (you can get a good idea of what a reasonable pressure is in Lennard-Jones units by looking at the average pressure of your simulations from the last section). This gives ten phase points &amp;amp;mdash; five temperatures at each pressure. Create 10 copies of npt.in, and modify each to run a simulation at one of your chosen &amp;lt;math&amp;gt;\left(p, T\right)&amp;lt;/math&amp;gt; points. You should be able to use the results of the previous section to choose a timestep. Run these 10 scripts on the virtual machine. When your simulations have finished, download the log files as before. At the end of the log file, LAMMPS will output the values and errors for the pressure, temperature, and density &amp;lt;math&amp;gt;\left(\frac{N}{V}\right)&amp;lt;/math&amp;gt;. &amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Plot the density as a function of temperature for both pressures that you simulated. Include a line corresponding to the predictions made by the ideal gas law. [3] ===&lt;br /&gt;
&lt;br /&gt;
=== How do your results compare to the ideal gas law? Do deviations increase/decrease with temperature and pressure? Explain. [7] ===&lt;br /&gt;
&lt;br /&gt;
=== Do you expect your simulation results to be in better or worse agreement with the Van der Waals equation of state? Why? [3] ===&lt;br /&gt;
&lt;br /&gt;
===Thermostats and Barostats - controlling the thermodynamic properties===&lt;br /&gt;
The statistical thermodynamics lectures will have introduced you to the &#039;&#039;equipartition theorem&#039;&#039;, which states that, on average, every degree of freedom in a system at equilibrium will have &amp;lt;math&amp;gt;\frac{1}{2}k_B T&amp;lt;/math&amp;gt; of energy. In our system with &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; atoms, each with 3 degrees of freedom, we can write&lt;br /&gt;
&amp;lt;math&amp;gt;E_K = \frac{3}{2} N k_B T&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\frac{1}{2}\sum_i m_i v_i^2 = \frac{3}{2} N k_B T&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At the end of every timestep, we use the left hand side of this equation to calculate the kinetic energy, then divide by &amp;lt;math&amp;gt;\frac{3}{2}Nk_B&amp;lt;/math&amp;gt; to get the &#039;&#039;instantaneous&#039;&#039; temperature &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;. In general, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; will fluctuate, and will be different to our &#039;&#039;target&#039;&#039; temperature, &amp;lt;math&amp;gt;\mathfrak{T}&amp;lt;/math&amp;gt; (this is whatever value we specify in the input script). We can change the temperature by multiplying every velocity by a constant factor, &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* If &amp;lt;math&amp;gt; T &amp;gt; \mathfrak{T} &amp;lt;/math&amp;gt;, then the kinetic energy of the system is too high, and we need to reduce it. &amp;lt;math&amp;gt;\gamma &amp;lt; 1&amp;lt;/math&amp;gt;&lt;br /&gt;
* If &amp;lt;math&amp;gt; T &amp;lt; \mathfrak{T} &amp;lt;/math&amp;gt;, then the kinetic energy of the system is too low, and we need to increase it. &amp;lt;math&amp;gt;\gamma &amp;gt; 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We need to choose a scaling parameter &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt; so that the temperature is correct &amp;lt;math&amp;gt;T = \mathfrak{T}&amp;lt;/math&amp;gt; if we multiply every velocity &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt;. We can write two equations:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;math&amp;gt;\frac{1}{2}\sum_i m_i v_i^2 = \frac{3}{2} N k_B T&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\frac{1}{2}\sum_i m_i \left(\gamma v_i\right)^2 = \frac{3}{2} N k_B \mathfrak{T}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By combining these equations, one can see that &amp;lt;math&amp;gt; \gamma = \sqrt{\frac{\mathfrak{T}}{T}} &amp;lt;/math&amp;gt; (satisfy yourself that this is true!). A target value of &amp;lt;math&amp;gt; \gamma &amp;lt;/math&amp;gt; of 1 is required and thus, dependent on whether it&#039;s larger or smaller than 1 the simulation can target the desired temperature.&lt;br /&gt;
&lt;br /&gt;
Controlling the pressure is a little more involved, but the principle is largely the same: at each timestep, the pressure of the system is calculated; if the pressure is too high, then the simulation box is made a little larger, while if the pressure is too low the box is made smaller. Simulations in which the pressure is controlled are thus in the NpT ensemble &amp;amp;mdash; the volume of the simulation box is not constant!&lt;br /&gt;
&lt;br /&gt;
===Examining the Input Script===&lt;br /&gt;
&lt;br /&gt;
Open one of your input scripts (it doesn&#039;t matter which), and look at the section &#039;&#039;&#039;### BRING SYSTEM TO REQUIRED STATE ###&#039;&#039;&#039;. The line &amp;lt;pre&amp;gt;fix npt all npt temp ${T} ${T} ${tdamp} iso ${p} ${p} ${pdamp}&amp;lt;/pre&amp;gt; is the one responsible for switching on the temperature and pressure control. LAMMPS actually allows us to heat or cool the system over the course of a simulation, if we want to &amp;amp;mdash; this is the reason that the temperature appears twice in this line. The first ${T} is the desired starting temperature, and the second is the desired temperature at the end of the simulation. We want a constant average temperature, so we specify the same value twice. The same goes for the pressure.&lt;br /&gt;
&lt;br /&gt;
Now look at the lines near the end of the file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
### MEASURE SYSTEM STATE ###&lt;br /&gt;
thermo_style custom step etotal temp press density&lt;br /&gt;
variable dens equal density&lt;br /&gt;
variable dens2 equal density*density&lt;br /&gt;
variable temp equal temp&lt;br /&gt;
variable temp2 equal temp*temp&lt;br /&gt;
variable press equal press&lt;br /&gt;
variable press2 equal press*press&lt;br /&gt;
fix aves all ave/time 100 1000 30000 v_dens v_temp v_press v_dens2 v_temp2 v_press2&lt;br /&gt;
run 30000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first command, &#039;&#039;thermo_style&#039;&#039;, controls which thermodynamic properties are recorded, as before. The next lines are used to measure &#039;&#039;average&#039;&#039; thermodynamic properties for the system. To draw our equations of state, we need to know the average temperature, pressure, and density, and the statistical errors in those quantities. The six variable lines link those quantities (and their squared values, needed for the errors), to variable names that we can use in the averaging command, which is the line starting &#039;&#039;fix aves...&#039;&#039;. This command takes a number of input values and averages them every so many timesteps. Exactly how often this happens depends in the values of the three numbers which follow &#039;&#039;ave/time&#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 third year simulation experiment. You can return to the previous page, [[Third_year_simulation_experiment/Equilibration|Equilibration]], or jump ahead to the next section, [[Third year simulation experiment/Structural properties and the radial distribution function|Structural properties and the radial distribution function]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Equilibration&amp;diff=813824</id>
		<title>Third year simulation experiment/Equilibration</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Equilibration&amp;diff=813824"/>
		<updated>2021-10-20T13:17:00Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* Checking equilibration */&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 third year simulation experiment. You can return to the previous page, [[Third_year_simulation_experiment/Introduction_to_molecular_dynamics_simulation|Introduction to molecular dynamics simulation]], or jump ahead to the next section, [[Third year simulation experiment/Running simulations under specific conditions|Running simulations under specific conditions]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
We will be using the LAMMPS program to carry out our molecular dynamics simulations.&lt;br /&gt;
&#039;&#039;&#039;In several places in this section, we will ask you to consult the LAMMPS manual to find out things about how the software works. You can find the manual [https://lammps.sandia.gov/doc/Manual.html here].&#039;&#039;&#039; We appreciate that the format of this document can make it a little hard to navigate, but it is the definitive resource on how different commands in LAMMPS work, and is therefore invaluable. The files you will need for this section can be found in the intro folder downloaded previously.&lt;br /&gt;
&lt;br /&gt;
===Creating the simulation box===&lt;br /&gt;
In the previous section, it was pointed out that before we can start a simulation, we need to know the initial states of all of the atoms in the system. Exactly what information we need about each atom depends on which method of numerical integration we need, but at the very least we need to specify the starting position of each atom. If we wanted to simulate a crystal, this information would be quite easy to come by &amp;amp;mdash; we could just look up the crystal structure, and use that to generate coordinates for however many unit cells we wanted. For this purpose, LAMMPS includes a command which generates crystal lattice structures.&lt;br /&gt;
&lt;br /&gt;
Generating coordinates for atoms in a liquid is more difficult. There is no long range order, so we can&#039;t use a single point of reference to work out the positions of every other atom like we can in a solid. We could generate a random position for each atom. This would certainly create a disordered structure, but causes larger problems when we try to run the simulation.&lt;br /&gt;
&lt;br /&gt;
Instead, we are going to place the atoms on the lattice points of a simple cubic lattice. This, of course, is not a situation in which the system is likely to be found physically. It turns out, though, that if we simulate for enough time we will find that the atoms rearrange themselves into more realistic configurations. We will discuss towards the end of this section exactly what is meant by &amp;quot;enough time&amp;quot;!&lt;br /&gt;
&lt;br /&gt;
Consider the line in the input file &amp;lt;pre&amp;gt;lattice sc 0.8&amp;lt;/pre&amp;gt; This command [https://lammps.sandia.gov/doc/lattice.html (further info)] creates a grid of points forming a simple cubic lattice (one lattice point per unit cell). The parameter &amp;lt;math&amp;gt;0.8&amp;lt;/math&amp;gt; specifies the number density (number of lattice points per unit volume). In a corresponding output file, you will see the line &amp;lt;pre&amp;gt;Lattice spacing in x,y,z = 1.07722 1.07722 1.07722&amp;lt;/pre&amp;gt; This indicates that the distance between the points of this lattice is &amp;lt;math&amp;gt;1.07722&amp;lt;/math&amp;gt; (in reduced units, remember!).&lt;br /&gt;
&lt;br /&gt;
The next lines in the input file are&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
region box block 0 5 0 5 0 5&lt;br /&gt;
create_box 1 box&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The corresponding log file output is &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Created orthogonal box = (0.0000000 0.0000000 0.0000000) to (5.3860867 5.3860867 5.3860867)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The region command [https://lammps.sandia.gov/doc/region.html (further info)] simply defines a geometrical region in space, which we call &amp;quot;box&amp;quot;. In this case, &amp;quot;box&amp;quot; is a cube extending ten lattice spacings from the origin in all three dimensions. The subsequent create_box command [https://lammps.sandia.gov/doc/create_box.html (further info)] tells LAMMPS to use the geometrical region called &amp;quot;box&amp;quot; as a template for the simulation box. The number 1 between &amp;quot;create_box&amp;quot; and &amp;quot;box&amp;quot; indicates that our simulation will contain only one type (species) of atom.&lt;br /&gt;
&lt;br /&gt;
So far we have defined a simulation box which is based around a virtual simple cubic lattice. Our box contains 125 (5x5x5) unit cells of this lattice, and so contains 125 lattice points. We now need to fill our simulation box with atoms. The input command is &amp;lt;pre&amp;gt;create_atoms 1 box&amp;lt;/pre&amp;gt; [https://lammps.sandia.gov/doc/create_atoms.html (further info)] while the log file simply contains an acknowledgement of this &amp;lt;pre&amp;gt;Created 125 atoms&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The create_atoms command has two arguments; the first tells LAMMPS that all of the atoms that we create will be of type 1. Every atom in the simulation has a type &amp;amp;mdash; because we will be simulating a pure fluid, containing only one chemical species, every atom will have the same type. The actual type that we assign to each atom is arbitrary &amp;amp;mdash; type 1 does not, for example, need to correspond to the element with atomic number 1 (hydrogen). If we wanted to simulate water, we might make the hydrogen atoms type 1 and the oxygen atoms type 2. We will specify the physical and chemical properties of each atom type later in the input script.&lt;br /&gt;
&lt;br /&gt;
The remaining data in the log file isn&#039;t very instructive as it stands &amp;amp;mdash; it simply contains a list of the thermodynamic properties of the simulation at certain intervals. In a few sections time, we will plot this data, but for now you can close the log file. Keep the input script open.&lt;br /&gt;
&lt;br /&gt;
===Setting the properties of the atoms===&lt;br /&gt;
&lt;br /&gt;
In addition to their positions, we also need the physical properties of the atoms to be able to perform the simulation. We set these properties on a &#039;per-type&#039; basis, so that every atom of the same type has the same mass and the same interactions.&lt;br /&gt;
&lt;br /&gt;
So far we have created 125 atoms, and we know the starting (&amp;lt;math&amp;gt;t = 0&amp;lt;/math&amp;gt;) position for each of them. We have also set their masses, and told LAMMPS what sort of forces to calculate between them. The final thing we need to specify to completely specify the initial conditions is the velocity of each atom.&lt;br /&gt;
&lt;br /&gt;
Choosing initial velocities for the atoms is a little easier than choosing initial positions. From the statistical thermodynamics lectures, you should know that, at equilibrium, the velocities of atoms in any system must be distributed according to the [http://en.wikipedia.org/wiki/Maxwell%E2%80%93Boltzmann_distribution Maxwell-Boltzmann (MB) distribution]. If we know the masses of the atoms, and we know what temperature we want to simulate, then we can determine the relevant MB distribution function. LAMMPS is able to give every atom a random velocity whilst ensuring that overall the MB distribution is followed. This is the purpose of the line&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
velocity all create 1.5 12345 dist gaussian rot yes mom yes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can see the manual page for this command [http://lammps.sandia.gov/doc/velocity.html here], but the key sections are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;all&#039;&#039;&#039;: the &#039;&#039;group&#039;&#039; of atoms on which the command acts. &#039;&#039;&#039;all&#039;&#039;&#039; simply specifies that we want every atom to have a velocity assigned to it.&lt;br /&gt;
* &#039;&#039;&#039;1.5&#039;&#039;&#039;: the temperature, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, needed to calculate the MB distribution(in reduced units, as always)&lt;br /&gt;
&lt;br /&gt;
===Monitoring thermodynamic properties===&lt;br /&gt;
&lt;br /&gt;
We need to be sure that our simulation is correctly modelling whatever physical system we want to study. It is relatively easy to set up simulations, but how can we be sure that the &amp;quot;results&amp;quot; we get make sense? One of the best ways is to calculate from the simulation things that we can measure in experiment, and see if they agree. For example, we might want to simulate our system at a particular temperature and pressure, and measure the resulting density. If we repeat this over a range of temperatures at the same pressure, we will be able to plot an &#039;&#039;equation of state&#039;&#039;, which we could compare to experimental measurements.&lt;br /&gt;
&lt;br /&gt;
LAMMPS is able to calculate a great deal of thermodynamic information for us (you can see a full list of the properties it is able to calculate [http://lammps.sandia.gov/doc/thermo_style.html here]), but in these first simulations we are only interested in those properties specified in these commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
thermo_style custom time etotal temp press&lt;br /&gt;
thermo 10&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first controls which properties will be printed out in the log file. In this case, we print how much time we have simulated so far (which is &#039;&#039;not&#039;&#039; the same as how long it has taken us to simulate it!), the total energy of the atoms, their temperature, and their pressure. The second line tells LAMMPS to print this information on every 10th timestep.&lt;br /&gt;
&lt;br /&gt;
===Running the simulation===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Look at the lines below.&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
### SPECIFY TIMESTEP ###&lt;br /&gt;
variable timestep equal 0.001&lt;br /&gt;
variable n_steps equal floor(50/${timestep})&lt;br /&gt;
timestep ${timestep}&lt;br /&gt;
&lt;br /&gt;
### RUN SIMULATION ###&lt;br /&gt;
run ${n_steps}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;The second line (starting &amp;quot;variable timestep...&amp;quot;) tells LAMMPS that if it encounters the text ${timestep} on a subsequent line, it should replace it by the value given. In this case, the value ${timestep} is always replaced by 0.001.&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt; It is now time to run your first simulation, submit the input script with the data file in the intro folder of the files you have downloaded Try changing the timestep - what happens when you make the timestep larger?. &amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Visualising the trajectory===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;trajectory files&#039;&#039;&#039; contain the positions of all the atoms in the simulation, recorded at a set interval (for all of these simulations, this was every ten timesteps &amp;amp;mdash; this is controlled by the &#039;&#039;&#039;dump&#039;&#039;&#039; command in the input scripts). We use a programme called [http://www.ks.uiuc.edu/Research/vmd/ &#039;&#039;&#039;VMD&#039;&#039;&#039;] to view these trajectories, which you should find is already installed on both the desktop and laptop computers. You can run VMD from the start menu with &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;University of Illinois&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;VMD&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Loading a Trajectory====&lt;br /&gt;
&lt;br /&gt;
We&#039;ll start by looking at the output of the 0.02 timestep simulation. In the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window, select the menu option &#039;&#039;&#039;File&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;New Molecule&#039;&#039;&#039;. Click the &#039;&#039;&#039;Browse&#039;&#039;&#039; button, then select the relevant trajectory file. In the &#039;&#039;&#039;Determine file type&#039;&#039;&#039; dropdown, select &#039;&#039;&#039;LAMMPS Trajectory&#039;&#039;&#039;. Then click &#039;&#039;&#039;Load&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You will see that the &#039;&#039;&#039;VMD 1.9.1 OpenGL Display&#039;&#039;&#039; window now shows a horrible mess. VMD&#039;s default behaviour is to draw lines between atoms which it thinks might be chemically bonded. Our system doesn&#039;t model chemical bonds, so we want to turn this off. In the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window, select the menu option &#039;&#039;&#039;Graphics&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Representations&#039;&#039;&#039;. This shows a list of &amp;quot;representations&amp;quot; of our atoms. You will see that at the moment, there is a single representation listed, and it is selected. It will have the &#039;&#039;Lines&#039;&#039; style, the &#039;&#039;Name&#039;&#039; colour, and the selection &#039;&#039;all&#039;&#039;. &amp;quot;Selection&amp;quot; simply tells VMD which atoms we want it to draw. We want to show every atom, so the current selection is fine. The &#039;&#039;name&#039;&#039; colouring method just makes VMD give atoms colours according to their specified type. The colour isn&#039;t important to us, so we can leave this be too. The &amp;quot;style&amp;quot; tells VMD what we want it to display for each atom. Change the &#039;&#039;&#039;Drawing Method&#039;&#039;&#039; from &#039;&#039;Lines&#039;&#039; to &#039;&#039;VDW&#039;&#039;. You will see that the mess of lines is replaced by a mess of low resolution, overlapping spheres. Change the &#039;&#039;&#039;Sphere Scale&#039;&#039;&#039; to 0.3, and the &#039;&#039;&#039;Sphere Resolution&#039;&#039;&#039; to 17. The result should look a little smoother. Close the &#039;&#039;&#039;Graphical Representations&#039;&#039;&#039; window. You will notice that in the bottom right of the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window, there is a small play button. Click this, and you will see the animated version of your simulation trajectory.&lt;br /&gt;
&lt;br /&gt;
By clicking and dragging with the mouse, you can rotate the simulation box (though this may be sluggish). At any time, you can reset the view by pressing the equals key.&lt;br /&gt;
&lt;br /&gt;
====Tracking a Single Particle====&lt;br /&gt;
To illustrate the periodic boundary conditions that we are using, we are going to draw almost all of the atoms as points, but we will pick a single atom at random to draw as a sphere. This will make it easy to see how a single atom moves through the box. Reset the display using the equals key, then use the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window controls to pause the trajectory and reset it to the first trajectory (play with the different buttons until you find the one that does this). You should see the perfect cubic lattice. Use the option &#039;&#039;&#039;Display&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Orthographic&#039;&#039;&#039; to change the drawing mode, then rotate the displayed crystal so that you are looking at one vertex (looking down the 111 direction, in crystallographic terms).&lt;br /&gt;
&lt;br /&gt;
Open the &#039;&#039;&#039;Graphical Representations&#039;&#039;&#039; window again. Change the representation style from &#039;&#039;&#039;VDW&#039;&#039;&#039; to points, then click the &#039;&#039;&#039;Create Rep&#039;&#039;&#039; button. This creates a second representation, allowing a subset of the atoms to be drawn in a different way. The &#039;&#039;&#039;Selected Atoms&#039;&#039;&#039; box allows us to choose which atoms this representation applies to. We just want to pick two of them at random &amp;amp;mdash; VMD assigns every atom an index, from 0 to N-1. In our case, there are 125 atoms, so choose two numbers between 0 and 124. Changed the &#039;&#039;&#039;Selected Atoms&#039;&#039;&#039; field to &amp;lt;pre&amp;gt;index i or index j&amp;lt;/pre&amp;gt; where i and j are your chosen numbers, press return, then change the &#039;&#039;&#039;Drawing Method&#039;&#039;&#039; to &#039;&#039;&#039;VDW&#039;&#039;&#039;. You should now see only two atoms represented by spheres, with the rest shown as small points. In the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window, click play. Try rotating the box, and changing the playback speed.&lt;br /&gt;
&lt;br /&gt;
You will see that sometimes one of the spheres seems to change position across the box very rapidly &amp;amp;mdash; this occurs when it reaches one periodic boundary, and is reflected back across the other face. Try playing with some of the other representation types in VMD &amp;amp;mdash; it  is a very powerful package, which is often used to render images of simulated proteins, so many of its options aren&#039;t relevant to our simple system!&lt;br /&gt;
&lt;br /&gt;
===Checking equilibration===&lt;br /&gt;
&lt;br /&gt;
When we first set up a simulation, it is very important to make sure that our system reaches an equilibrium state. We characterise equilibrium by the average values of thermodynamic quantities becoming constant (due to the approximations that we have made, there will always be fluctuations, but the average values will become constant).&lt;br /&gt;
&lt;br /&gt;
In this section, we are going to plot the thermodynamic output of the simulation to see how long it takes to reach the equilibrium state (and indeed, whether this happens at all). Instructions are given below to import data from the LAMMPS log file into Microsoft Excel. Once you have the data in a spreadsheet, you can plot it. If you know how to use some of the other plotting software available on the chemistry computers (like Origin), you are welcome to use it.&lt;br /&gt;
&lt;br /&gt;
# Open a blank Excel workbook&lt;br /&gt;
# Copy the data in the textfile into the first cell&lt;br /&gt;
# With these data highlighted, click the Data tab and &amp;quot;Text to Columns&amp;quot;&lt;br /&gt;
# Click &amp;quot;Delimited&amp;quot;, continue and let it be space delimited&lt;br /&gt;
# Click finish&lt;br /&gt;
You can then export this and data as a .csv and analyse in Python or Excel, as you wish. &lt;br /&gt;
&lt;br /&gt;
Challenge: Can you write a python script or function that extracts this data for a given file automatically?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 7: &amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== What does it mean for a simulation to &amp;quot;reach equilibrium&amp;quot;? Why is this important in terms of sampling from an ensemble using molecular dynamics? [2] ===&lt;br /&gt;
&lt;br /&gt;
=== Plot the energy (potential, kinetic and total), temperature and pressure, against time for the 0.001 timestep experiment [2] ===&lt;br /&gt;
&lt;br /&gt;
=== Does the simulation reach equilibrium? How can you tell? [2] ===&lt;br /&gt;
&lt;br /&gt;
=== Make a single plot which shows the energy vs. time for the timesteps you have simulated [2]. ===&lt;br /&gt;
&lt;br /&gt;
=== Of the timesteps that you used, which timestep will you use for subsequent simulations and why? [6] ===&lt;br /&gt;
&#039;&#039;(Think about what is happening &amp;quot;physically&amp;quot; as you increase/decrease the timestep. Also, what features of each timeseries are indicative of the simulation&#039;s &amp;quot;health&amp;quot;?)&#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 third year simulation experiment. You can return to the previous page, [[Third_year_simulation_experiment/Introduction_to_molecular_dynamics_simulation|Introduction to molecular dynamics simulation]], or jump ahead to the next section, [[Third year simulation experiment/Running simulations under specific conditions|Running simulations under specific conditions]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Equilibration&amp;diff=813823</id>
		<title>Third year simulation experiment/Equilibration</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Equilibration&amp;diff=813823"/>
		<updated>2021-10-20T13:14:42Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* Plot the energy (potential, kinetic and total), temperature and pressure, against time for the 0,001 timestep experiment [2] */&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 third year simulation experiment. You can return to the previous page, [[Third_year_simulation_experiment/Introduction_to_molecular_dynamics_simulation|Introduction to molecular dynamics simulation]], or jump ahead to the next section, [[Third year simulation experiment/Running simulations under specific conditions|Running simulations under specific conditions]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
We will be using the LAMMPS program to carry out our molecular dynamics simulations.&lt;br /&gt;
&#039;&#039;&#039;In several places in this section, we will ask you to consult the LAMMPS manual to find out things about how the software works. You can find the manual [https://lammps.sandia.gov/doc/Manual.html here].&#039;&#039;&#039; We appreciate that the format of this document can make it a little hard to navigate, but it is the definitive resource on how different commands in LAMMPS work, and is therefore invaluable. The files you will need for this section can be found in the intro folder downloaded previously.&lt;br /&gt;
&lt;br /&gt;
===Creating the simulation box===&lt;br /&gt;
In the previous section, it was pointed out that before we can start a simulation, we need to know the initial states of all of the atoms in the system. Exactly what information we need about each atom depends on which method of numerical integration we need, but at the very least we need to specify the starting position of each atom. If we wanted to simulate a crystal, this information would be quite easy to come by &amp;amp;mdash; we could just look up the crystal structure, and use that to generate coordinates for however many unit cells we wanted. For this purpose, LAMMPS includes a command which generates crystal lattice structures.&lt;br /&gt;
&lt;br /&gt;
Generating coordinates for atoms in a liquid is more difficult. There is no long range order, so we can&#039;t use a single point of reference to work out the positions of every other atom like we can in a solid. We could generate a random position for each atom. This would certainly create a disordered structure, but causes larger problems when we try to run the simulation.&lt;br /&gt;
&lt;br /&gt;
Instead, we are going to place the atoms on the lattice points of a simple cubic lattice. This, of course, is not a situation in which the system is likely to be found physically. It turns out, though, that if we simulate for enough time we will find that the atoms rearrange themselves into more realistic configurations. We will discuss towards the end of this section exactly what is meant by &amp;quot;enough time&amp;quot;!&lt;br /&gt;
&lt;br /&gt;
Consider the line in the input file &amp;lt;pre&amp;gt;lattice sc 0.8&amp;lt;/pre&amp;gt; This command [https://lammps.sandia.gov/doc/lattice.html (further info)] creates a grid of points forming a simple cubic lattice (one lattice point per unit cell). The parameter &amp;lt;math&amp;gt;0.8&amp;lt;/math&amp;gt; specifies the number density (number of lattice points per unit volume). In a corresponding output file, you will see the line &amp;lt;pre&amp;gt;Lattice spacing in x,y,z = 1.07722 1.07722 1.07722&amp;lt;/pre&amp;gt; This indicates that the distance between the points of this lattice is &amp;lt;math&amp;gt;1.07722&amp;lt;/math&amp;gt; (in reduced units, remember!).&lt;br /&gt;
&lt;br /&gt;
The next lines in the input file are&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
region box block 0 5 0 5 0 5&lt;br /&gt;
create_box 1 box&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The corresponding log file output is &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Created orthogonal box = (0.0000000 0.0000000 0.0000000) to (5.3860867 5.3860867 5.3860867)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The region command [https://lammps.sandia.gov/doc/region.html (further info)] simply defines a geometrical region in space, which we call &amp;quot;box&amp;quot;. In this case, &amp;quot;box&amp;quot; is a cube extending ten lattice spacings from the origin in all three dimensions. The subsequent create_box command [https://lammps.sandia.gov/doc/create_box.html (further info)] tells LAMMPS to use the geometrical region called &amp;quot;box&amp;quot; as a template for the simulation box. The number 1 between &amp;quot;create_box&amp;quot; and &amp;quot;box&amp;quot; indicates that our simulation will contain only one type (species) of atom.&lt;br /&gt;
&lt;br /&gt;
So far we have defined a simulation box which is based around a virtual simple cubic lattice. Our box contains 125 (5x5x5) unit cells of this lattice, and so contains 125 lattice points. We now need to fill our simulation box with atoms. The input command is &amp;lt;pre&amp;gt;create_atoms 1 box&amp;lt;/pre&amp;gt; [https://lammps.sandia.gov/doc/create_atoms.html (further info)] while the log file simply contains an acknowledgement of this &amp;lt;pre&amp;gt;Created 125 atoms&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The create_atoms command has two arguments; the first tells LAMMPS that all of the atoms that we create will be of type 1. Every atom in the simulation has a type &amp;amp;mdash; because we will be simulating a pure fluid, containing only one chemical species, every atom will have the same type. The actual type that we assign to each atom is arbitrary &amp;amp;mdash; type 1 does not, for example, need to correspond to the element with atomic number 1 (hydrogen). If we wanted to simulate water, we might make the hydrogen atoms type 1 and the oxygen atoms type 2. We will specify the physical and chemical properties of each atom type later in the input script.&lt;br /&gt;
&lt;br /&gt;
The remaining data in the log file isn&#039;t very instructive as it stands &amp;amp;mdash; it simply contains a list of the thermodynamic properties of the simulation at certain intervals. In a few sections time, we will plot this data, but for now you can close the log file. Keep the input script open.&lt;br /&gt;
&lt;br /&gt;
===Setting the properties of the atoms===&lt;br /&gt;
&lt;br /&gt;
In addition to their positions, we also need the physical properties of the atoms to be able to perform the simulation. We set these properties on a &#039;per-type&#039; basis, so that every atom of the same type has the same mass and the same interactions.&lt;br /&gt;
&lt;br /&gt;
So far we have created 125 atoms, and we know the starting (&amp;lt;math&amp;gt;t = 0&amp;lt;/math&amp;gt;) position for each of them. We have also set their masses, and told LAMMPS what sort of forces to calculate between them. The final thing we need to specify to completely specify the initial conditions is the velocity of each atom.&lt;br /&gt;
&lt;br /&gt;
Choosing initial velocities for the atoms is a little easier than choosing initial positions. From the statistical thermodynamics lectures, you should know that, at equilibrium, the velocities of atoms in any system must be distributed according to the [http://en.wikipedia.org/wiki/Maxwell%E2%80%93Boltzmann_distribution Maxwell-Boltzmann (MB) distribution]. If we know the masses of the atoms, and we know what temperature we want to simulate, then we can determine the relevant MB distribution function. LAMMPS is able to give every atom a random velocity whilst ensuring that overall the MB distribution is followed. This is the purpose of the line&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
velocity all create 1.5 12345 dist gaussian rot yes mom yes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can see the manual page for this command [http://lammps.sandia.gov/doc/velocity.html here], but the key sections are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;all&#039;&#039;&#039;: the &#039;&#039;group&#039;&#039; of atoms on which the command acts. &#039;&#039;&#039;all&#039;&#039;&#039; simply specifies that we want every atom to have a velocity assigned to it.&lt;br /&gt;
* &#039;&#039;&#039;1.5&#039;&#039;&#039;: the temperature, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, needed to calculate the MB distribution(in reduced units, as always)&lt;br /&gt;
&lt;br /&gt;
===Monitoring thermodynamic properties===&lt;br /&gt;
&lt;br /&gt;
We need to be sure that our simulation is correctly modelling whatever physical system we want to study. It is relatively easy to set up simulations, but how can we be sure that the &amp;quot;results&amp;quot; we get make sense? One of the best ways is to calculate from the simulation things that we can measure in experiment, and see if they agree. For example, we might want to simulate our system at a particular temperature and pressure, and measure the resulting density. If we repeat this over a range of temperatures at the same pressure, we will be able to plot an &#039;&#039;equation of state&#039;&#039;, which we could compare to experimental measurements.&lt;br /&gt;
&lt;br /&gt;
LAMMPS is able to calculate a great deal of thermodynamic information for us (you can see a full list of the properties it is able to calculate [http://lammps.sandia.gov/doc/thermo_style.html here]), but in these first simulations we are only interested in those properties specified in these commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
thermo_style custom time etotal temp press&lt;br /&gt;
thermo 10&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first controls which properties will be printed out in the log file. In this case, we print how much time we have simulated so far (which is &#039;&#039;not&#039;&#039; the same as how long it has taken us to simulate it!), the total energy of the atoms, their temperature, and their pressure. The second line tells LAMMPS to print this information on every 10th timestep.&lt;br /&gt;
&lt;br /&gt;
===Running the simulation===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Look at the lines below.&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
### SPECIFY TIMESTEP ###&lt;br /&gt;
variable timestep equal 0.001&lt;br /&gt;
variable n_steps equal floor(50/${timestep})&lt;br /&gt;
timestep ${timestep}&lt;br /&gt;
&lt;br /&gt;
### RUN SIMULATION ###&lt;br /&gt;
run ${n_steps}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;The second line (starting &amp;quot;variable timestep...&amp;quot;) tells LAMMPS that if it encounters the text ${timestep} on a subsequent line, it should replace it by the value given. In this case, the value ${timestep} is always replaced by 0.001.&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt; It is now time to run your first simulation, submit the input script with the data file in the intro folder of the files you have downloaded Try changing the timestep - what happens when you make the timestep larger?. &amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Visualising the trajectory===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;trajectory files&#039;&#039;&#039; contain the positions of all the atoms in the simulation, recorded at a set interval (for all of these simulations, this was every ten timesteps &amp;amp;mdash; this is controlled by the &#039;&#039;&#039;dump&#039;&#039;&#039; command in the input scripts). We use a programme called [http://www.ks.uiuc.edu/Research/vmd/ &#039;&#039;&#039;VMD&#039;&#039;&#039;] to view these trajectories, which you should find is already installed on both the desktop and laptop computers. You can run VMD from the start menu with &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;University of Illinois&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;VMD&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Loading a Trajectory====&lt;br /&gt;
&lt;br /&gt;
We&#039;ll start by looking at the output of the 0.02 timestep simulation. In the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window, select the menu option &#039;&#039;&#039;File&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;New Molecule&#039;&#039;&#039;. Click the &#039;&#039;&#039;Browse&#039;&#039;&#039; button, then select the relevant trajectory file. In the &#039;&#039;&#039;Determine file type&#039;&#039;&#039; dropdown, select &#039;&#039;&#039;LAMMPS Trajectory&#039;&#039;&#039;. Then click &#039;&#039;&#039;Load&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You will see that the &#039;&#039;&#039;VMD 1.9.1 OpenGL Display&#039;&#039;&#039; window now shows a horrible mess. VMD&#039;s default behaviour is to draw lines between atoms which it thinks might be chemically bonded. Our system doesn&#039;t model chemical bonds, so we want to turn this off. In the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window, select the menu option &#039;&#039;&#039;Graphics&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Representations&#039;&#039;&#039;. This shows a list of &amp;quot;representations&amp;quot; of our atoms. You will see that at the moment, there is a single representation listed, and it is selected. It will have the &#039;&#039;Lines&#039;&#039; style, the &#039;&#039;Name&#039;&#039; colour, and the selection &#039;&#039;all&#039;&#039;. &amp;quot;Selection&amp;quot; simply tells VMD which atoms we want it to draw. We want to show every atom, so the current selection is fine. The &#039;&#039;name&#039;&#039; colouring method just makes VMD give atoms colours according to their specified type. The colour isn&#039;t important to us, so we can leave this be too. The &amp;quot;style&amp;quot; tells VMD what we want it to display for each atom. Change the &#039;&#039;&#039;Drawing Method&#039;&#039;&#039; from &#039;&#039;Lines&#039;&#039; to &#039;&#039;VDW&#039;&#039;. You will see that the mess of lines is replaced by a mess of low resolution, overlapping spheres. Change the &#039;&#039;&#039;Sphere Scale&#039;&#039;&#039; to 0.3, and the &#039;&#039;&#039;Sphere Resolution&#039;&#039;&#039; to 17. The result should look a little smoother. Close the &#039;&#039;&#039;Graphical Representations&#039;&#039;&#039; window. You will notice that in the bottom right of the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window, there is a small play button. Click this, and you will see the animated version of your simulation trajectory.&lt;br /&gt;
&lt;br /&gt;
By clicking and dragging with the mouse, you can rotate the simulation box (though this may be sluggish). At any time, you can reset the view by pressing the equals key.&lt;br /&gt;
&lt;br /&gt;
====Tracking a Single Particle====&lt;br /&gt;
To illustrate the periodic boundary conditions that we are using, we are going to draw almost all of the atoms as points, but we will pick a single atom at random to draw as a sphere. This will make it easy to see how a single atom moves through the box. Reset the display using the equals key, then use the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window controls to pause the trajectory and reset it to the first trajectory (play with the different buttons until you find the one that does this). You should see the perfect cubic lattice. Use the option &#039;&#039;&#039;Display&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Orthographic&#039;&#039;&#039; to change the drawing mode, then rotate the displayed crystal so that you are looking at one vertex (looking down the 111 direction, in crystallographic terms).&lt;br /&gt;
&lt;br /&gt;
Open the &#039;&#039;&#039;Graphical Representations&#039;&#039;&#039; window again. Change the representation style from &#039;&#039;&#039;VDW&#039;&#039;&#039; to points, then click the &#039;&#039;&#039;Create Rep&#039;&#039;&#039; button. This creates a second representation, allowing a subset of the atoms to be drawn in a different way. The &#039;&#039;&#039;Selected Atoms&#039;&#039;&#039; box allows us to choose which atoms this representation applies to. We just want to pick two of them at random &amp;amp;mdash; VMD assigns every atom an index, from 0 to N-1. In our case, there are 125 atoms, so choose two numbers between 0 and 124. Changed the &#039;&#039;&#039;Selected Atoms&#039;&#039;&#039; field to &amp;lt;pre&amp;gt;index i or index j&amp;lt;/pre&amp;gt; where i and j are your chosen numbers, press return, then change the &#039;&#039;&#039;Drawing Method&#039;&#039;&#039; to &#039;&#039;&#039;VDW&#039;&#039;&#039;. You should now see only two atoms represented by spheres, with the rest shown as small points. In the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window, click play. Try rotating the box, and changing the playback speed.&lt;br /&gt;
&lt;br /&gt;
You will see that sometimes one of the spheres seems to change position across the box very rapidly &amp;amp;mdash; this occurs when it reaches one periodic boundary, and is reflected back across the other face. Try playing with some of the other representation types in VMD &amp;amp;mdash; it  is a very powerful package, which is often used to render images of simulated proteins, so many of its options aren&#039;t relevant to our simple system!&lt;br /&gt;
&lt;br /&gt;
===Checking equilibration===&lt;br /&gt;
&lt;br /&gt;
When we first set up a simulation, it is very important to make sure that our system reaches an equilibrium state. We characterise equilibrium by the average values of thermodynamic quantities becoming constant (due to the approximations that we have made, there will always be fluctuations, but the average values will become constant).&lt;br /&gt;
&lt;br /&gt;
In this section, we are going to plot the thermodynamic output of the simulation to see how long it takes to reach the equilibrium state (and indeed, whether this happens at all). Instructions are given below to import data from the LAMMPS log file into Microsoft Excel. Once you have the data in a spreadsheet, you can plot it. If you know how to use some of the other plotting software available on the chemistry computers (like Origin), you are welcome to use it.&lt;br /&gt;
&lt;br /&gt;
# Open a blank Excel workbook&lt;br /&gt;
# Copy the data in the textfile into the first cell&lt;br /&gt;
# With these data highlighted, click the Data tab and &amp;quot;Text to Columns&amp;quot;&lt;br /&gt;
# Click &amp;quot;Delimited&amp;quot;, continue and let it be space delimited&lt;br /&gt;
# Click finish&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 7: &amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== What does it mean for a simulation to &amp;quot;reach equilibrium&amp;quot;? Why is this important in terms of sampling from an ensemble using molecular dynamics? [2] ===&lt;br /&gt;
&lt;br /&gt;
=== Plot the energy (potential, kinetic and total), temperature and pressure, against time for the 0.001 timestep experiment [2] ===&lt;br /&gt;
&lt;br /&gt;
=== Does the simulation reach equilibrium? How can you tell? [2] ===&lt;br /&gt;
&lt;br /&gt;
=== Make a single plot which shows the energy vs. time for the timesteps you have simulated [2]. ===&lt;br /&gt;
&lt;br /&gt;
=== Of the timesteps that you used, which timestep will you use for subsequent simulations and why? [6] ===&lt;br /&gt;
&#039;&#039;(Think about what is happening &amp;quot;physically&amp;quot; as you increase/decrease the timestep. Also, what features of each timeseries are indicative of the simulation&#039;s &amp;quot;health&amp;quot;?)&#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 third year simulation experiment. You can return to the previous page, [[Third_year_simulation_experiment/Introduction_to_molecular_dynamics_simulation|Introduction to molecular dynamics simulation]], or jump ahead to the next section, [[Third year simulation experiment/Running simulations under specific conditions|Running simulations under specific conditions]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Equilibration&amp;diff=813822</id>
		<title>Third year simulation experiment/Equilibration</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Equilibration&amp;diff=813822"/>
		<updated>2021-10-20T13:10:35Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* Running the 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 third year simulation experiment. You can return to the previous page, [[Third_year_simulation_experiment/Introduction_to_molecular_dynamics_simulation|Introduction to molecular dynamics simulation]], or jump ahead to the next section, [[Third year simulation experiment/Running simulations under specific conditions|Running simulations under specific conditions]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
We will be using the LAMMPS program to carry out our molecular dynamics simulations.&lt;br /&gt;
&#039;&#039;&#039;In several places in this section, we will ask you to consult the LAMMPS manual to find out things about how the software works. You can find the manual [https://lammps.sandia.gov/doc/Manual.html here].&#039;&#039;&#039; We appreciate that the format of this document can make it a little hard to navigate, but it is the definitive resource on how different commands in LAMMPS work, and is therefore invaluable. The files you will need for this section can be found in the intro folder downloaded previously.&lt;br /&gt;
&lt;br /&gt;
===Creating the simulation box===&lt;br /&gt;
In the previous section, it was pointed out that before we can start a simulation, we need to know the initial states of all of the atoms in the system. Exactly what information we need about each atom depends on which method of numerical integration we need, but at the very least we need to specify the starting position of each atom. If we wanted to simulate a crystal, this information would be quite easy to come by &amp;amp;mdash; we could just look up the crystal structure, and use that to generate coordinates for however many unit cells we wanted. For this purpose, LAMMPS includes a command which generates crystal lattice structures.&lt;br /&gt;
&lt;br /&gt;
Generating coordinates for atoms in a liquid is more difficult. There is no long range order, so we can&#039;t use a single point of reference to work out the positions of every other atom like we can in a solid. We could generate a random position for each atom. This would certainly create a disordered structure, but causes larger problems when we try to run the simulation.&lt;br /&gt;
&lt;br /&gt;
Instead, we are going to place the atoms on the lattice points of a simple cubic lattice. This, of course, is not a situation in which the system is likely to be found physically. It turns out, though, that if we simulate for enough time we will find that the atoms rearrange themselves into more realistic configurations. We will discuss towards the end of this section exactly what is meant by &amp;quot;enough time&amp;quot;!&lt;br /&gt;
&lt;br /&gt;
Consider the line in the input file &amp;lt;pre&amp;gt;lattice sc 0.8&amp;lt;/pre&amp;gt; This command [https://lammps.sandia.gov/doc/lattice.html (further info)] creates a grid of points forming a simple cubic lattice (one lattice point per unit cell). The parameter &amp;lt;math&amp;gt;0.8&amp;lt;/math&amp;gt; specifies the number density (number of lattice points per unit volume). In a corresponding output file, you will see the line &amp;lt;pre&amp;gt;Lattice spacing in x,y,z = 1.07722 1.07722 1.07722&amp;lt;/pre&amp;gt; This indicates that the distance between the points of this lattice is &amp;lt;math&amp;gt;1.07722&amp;lt;/math&amp;gt; (in reduced units, remember!).&lt;br /&gt;
&lt;br /&gt;
The next lines in the input file are&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
region box block 0 5 0 5 0 5&lt;br /&gt;
create_box 1 box&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The corresponding log file output is &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Created orthogonal box = (0.0000000 0.0000000 0.0000000) to (5.3860867 5.3860867 5.3860867)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The region command [https://lammps.sandia.gov/doc/region.html (further info)] simply defines a geometrical region in space, which we call &amp;quot;box&amp;quot;. In this case, &amp;quot;box&amp;quot; is a cube extending ten lattice spacings from the origin in all three dimensions. The subsequent create_box command [https://lammps.sandia.gov/doc/create_box.html (further info)] tells LAMMPS to use the geometrical region called &amp;quot;box&amp;quot; as a template for the simulation box. The number 1 between &amp;quot;create_box&amp;quot; and &amp;quot;box&amp;quot; indicates that our simulation will contain only one type (species) of atom.&lt;br /&gt;
&lt;br /&gt;
So far we have defined a simulation box which is based around a virtual simple cubic lattice. Our box contains 125 (5x5x5) unit cells of this lattice, and so contains 125 lattice points. We now need to fill our simulation box with atoms. The input command is &amp;lt;pre&amp;gt;create_atoms 1 box&amp;lt;/pre&amp;gt; [https://lammps.sandia.gov/doc/create_atoms.html (further info)] while the log file simply contains an acknowledgement of this &amp;lt;pre&amp;gt;Created 125 atoms&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The create_atoms command has two arguments; the first tells LAMMPS that all of the atoms that we create will be of type 1. Every atom in the simulation has a type &amp;amp;mdash; because we will be simulating a pure fluid, containing only one chemical species, every atom will have the same type. The actual type that we assign to each atom is arbitrary &amp;amp;mdash; type 1 does not, for example, need to correspond to the element with atomic number 1 (hydrogen). If we wanted to simulate water, we might make the hydrogen atoms type 1 and the oxygen atoms type 2. We will specify the physical and chemical properties of each atom type later in the input script.&lt;br /&gt;
&lt;br /&gt;
The remaining data in the log file isn&#039;t very instructive as it stands &amp;amp;mdash; it simply contains a list of the thermodynamic properties of the simulation at certain intervals. In a few sections time, we will plot this data, but for now you can close the log file. Keep the input script open.&lt;br /&gt;
&lt;br /&gt;
===Setting the properties of the atoms===&lt;br /&gt;
&lt;br /&gt;
In addition to their positions, we also need the physical properties of the atoms to be able to perform the simulation. We set these properties on a &#039;per-type&#039; basis, so that every atom of the same type has the same mass and the same interactions.&lt;br /&gt;
&lt;br /&gt;
So far we have created 125 atoms, and we know the starting (&amp;lt;math&amp;gt;t = 0&amp;lt;/math&amp;gt;) position for each of them. We have also set their masses, and told LAMMPS what sort of forces to calculate between them. The final thing we need to specify to completely specify the initial conditions is the velocity of each atom.&lt;br /&gt;
&lt;br /&gt;
Choosing initial velocities for the atoms is a little easier than choosing initial positions. From the statistical thermodynamics lectures, you should know that, at equilibrium, the velocities of atoms in any system must be distributed according to the [http://en.wikipedia.org/wiki/Maxwell%E2%80%93Boltzmann_distribution Maxwell-Boltzmann (MB) distribution]. If we know the masses of the atoms, and we know what temperature we want to simulate, then we can determine the relevant MB distribution function. LAMMPS is able to give every atom a random velocity whilst ensuring that overall the MB distribution is followed. This is the purpose of the line&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
velocity all create 1.5 12345 dist gaussian rot yes mom yes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can see the manual page for this command [http://lammps.sandia.gov/doc/velocity.html here], but the key sections are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;all&#039;&#039;&#039;: the &#039;&#039;group&#039;&#039; of atoms on which the command acts. &#039;&#039;&#039;all&#039;&#039;&#039; simply specifies that we want every atom to have a velocity assigned to it.&lt;br /&gt;
* &#039;&#039;&#039;1.5&#039;&#039;&#039;: the temperature, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, needed to calculate the MB distribution(in reduced units, as always)&lt;br /&gt;
&lt;br /&gt;
===Monitoring thermodynamic properties===&lt;br /&gt;
&lt;br /&gt;
We need to be sure that our simulation is correctly modelling whatever physical system we want to study. It is relatively easy to set up simulations, but how can we be sure that the &amp;quot;results&amp;quot; we get make sense? One of the best ways is to calculate from the simulation things that we can measure in experiment, and see if they agree. For example, we might want to simulate our system at a particular temperature and pressure, and measure the resulting density. If we repeat this over a range of temperatures at the same pressure, we will be able to plot an &#039;&#039;equation of state&#039;&#039;, which we could compare to experimental measurements.&lt;br /&gt;
&lt;br /&gt;
LAMMPS is able to calculate a great deal of thermodynamic information for us (you can see a full list of the properties it is able to calculate [http://lammps.sandia.gov/doc/thermo_style.html here]), but in these first simulations we are only interested in those properties specified in these commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
thermo_style custom time etotal temp press&lt;br /&gt;
thermo 10&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first controls which properties will be printed out in the log file. In this case, we print how much time we have simulated so far (which is &#039;&#039;not&#039;&#039; the same as how long it has taken us to simulate it!), the total energy of the atoms, their temperature, and their pressure. The second line tells LAMMPS to print this information on every 10th timestep.&lt;br /&gt;
&lt;br /&gt;
===Running the simulation===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Look at the lines below.&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
### SPECIFY TIMESTEP ###&lt;br /&gt;
variable timestep equal 0.001&lt;br /&gt;
variable n_steps equal floor(50/${timestep})&lt;br /&gt;
timestep ${timestep}&lt;br /&gt;
&lt;br /&gt;
### RUN SIMULATION ###&lt;br /&gt;
run ${n_steps}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;The second line (starting &amp;quot;variable timestep...&amp;quot;) tells LAMMPS that if it encounters the text ${timestep} on a subsequent line, it should replace it by the value given. In this case, the value ${timestep} is always replaced by 0.001.&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt; It is now time to run your first simulation, submit the input script with the data file in the intro folder of the files you have downloaded Try changing the timestep - what happens when you make the timestep larger?. &amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Visualising the trajectory===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;trajectory files&#039;&#039;&#039; contain the positions of all the atoms in the simulation, recorded at a set interval (for all of these simulations, this was every ten timesteps &amp;amp;mdash; this is controlled by the &#039;&#039;&#039;dump&#039;&#039;&#039; command in the input scripts). We use a programme called [http://www.ks.uiuc.edu/Research/vmd/ &#039;&#039;&#039;VMD&#039;&#039;&#039;] to view these trajectories, which you should find is already installed on both the desktop and laptop computers. You can run VMD from the start menu with &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;University of Illinois&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;VMD&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Loading a Trajectory====&lt;br /&gt;
&lt;br /&gt;
We&#039;ll start by looking at the output of the 0.02 timestep simulation. In the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window, select the menu option &#039;&#039;&#039;File&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;New Molecule&#039;&#039;&#039;. Click the &#039;&#039;&#039;Browse&#039;&#039;&#039; button, then select the relevant trajectory file. In the &#039;&#039;&#039;Determine file type&#039;&#039;&#039; dropdown, select &#039;&#039;&#039;LAMMPS Trajectory&#039;&#039;&#039;. Then click &#039;&#039;&#039;Load&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You will see that the &#039;&#039;&#039;VMD 1.9.1 OpenGL Display&#039;&#039;&#039; window now shows a horrible mess. VMD&#039;s default behaviour is to draw lines between atoms which it thinks might be chemically bonded. Our system doesn&#039;t model chemical bonds, so we want to turn this off. In the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window, select the menu option &#039;&#039;&#039;Graphics&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Representations&#039;&#039;&#039;. This shows a list of &amp;quot;representations&amp;quot; of our atoms. You will see that at the moment, there is a single representation listed, and it is selected. It will have the &#039;&#039;Lines&#039;&#039; style, the &#039;&#039;Name&#039;&#039; colour, and the selection &#039;&#039;all&#039;&#039;. &amp;quot;Selection&amp;quot; simply tells VMD which atoms we want it to draw. We want to show every atom, so the current selection is fine. The &#039;&#039;name&#039;&#039; colouring method just makes VMD give atoms colours according to their specified type. The colour isn&#039;t important to us, so we can leave this be too. The &amp;quot;style&amp;quot; tells VMD what we want it to display for each atom. Change the &#039;&#039;&#039;Drawing Method&#039;&#039;&#039; from &#039;&#039;Lines&#039;&#039; to &#039;&#039;VDW&#039;&#039;. You will see that the mess of lines is replaced by a mess of low resolution, overlapping spheres. Change the &#039;&#039;&#039;Sphere Scale&#039;&#039;&#039; to 0.3, and the &#039;&#039;&#039;Sphere Resolution&#039;&#039;&#039; to 17. The result should look a little smoother. Close the &#039;&#039;&#039;Graphical Representations&#039;&#039;&#039; window. You will notice that in the bottom right of the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window, there is a small play button. Click this, and you will see the animated version of your simulation trajectory.&lt;br /&gt;
&lt;br /&gt;
By clicking and dragging with the mouse, you can rotate the simulation box (though this may be sluggish). At any time, you can reset the view by pressing the equals key.&lt;br /&gt;
&lt;br /&gt;
====Tracking a Single Particle====&lt;br /&gt;
To illustrate the periodic boundary conditions that we are using, we are going to draw almost all of the atoms as points, but we will pick a single atom at random to draw as a sphere. This will make it easy to see how a single atom moves through the box. Reset the display using the equals key, then use the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window controls to pause the trajectory and reset it to the first trajectory (play with the different buttons until you find the one that does this). You should see the perfect cubic lattice. Use the option &#039;&#039;&#039;Display&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Orthographic&#039;&#039;&#039; to change the drawing mode, then rotate the displayed crystal so that you are looking at one vertex (looking down the 111 direction, in crystallographic terms).&lt;br /&gt;
&lt;br /&gt;
Open the &#039;&#039;&#039;Graphical Representations&#039;&#039;&#039; window again. Change the representation style from &#039;&#039;&#039;VDW&#039;&#039;&#039; to points, then click the &#039;&#039;&#039;Create Rep&#039;&#039;&#039; button. This creates a second representation, allowing a subset of the atoms to be drawn in a different way. The &#039;&#039;&#039;Selected Atoms&#039;&#039;&#039; box allows us to choose which atoms this representation applies to. We just want to pick two of them at random &amp;amp;mdash; VMD assigns every atom an index, from 0 to N-1. In our case, there are 125 atoms, so choose two numbers between 0 and 124. Changed the &#039;&#039;&#039;Selected Atoms&#039;&#039;&#039; field to &amp;lt;pre&amp;gt;index i or index j&amp;lt;/pre&amp;gt; where i and j are your chosen numbers, press return, then change the &#039;&#039;&#039;Drawing Method&#039;&#039;&#039; to &#039;&#039;&#039;VDW&#039;&#039;&#039;. You should now see only two atoms represented by spheres, with the rest shown as small points. In the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window, click play. Try rotating the box, and changing the playback speed.&lt;br /&gt;
&lt;br /&gt;
You will see that sometimes one of the spheres seems to change position across the box very rapidly &amp;amp;mdash; this occurs when it reaches one periodic boundary, and is reflected back across the other face. Try playing with some of the other representation types in VMD &amp;amp;mdash; it  is a very powerful package, which is often used to render images of simulated proteins, so many of its options aren&#039;t relevant to our simple system!&lt;br /&gt;
&lt;br /&gt;
===Checking equilibration===&lt;br /&gt;
&lt;br /&gt;
When we first set up a simulation, it is very important to make sure that our system reaches an equilibrium state. We characterise equilibrium by the average values of thermodynamic quantities becoming constant (due to the approximations that we have made, there will always be fluctuations, but the average values will become constant).&lt;br /&gt;
&lt;br /&gt;
In this section, we are going to plot the thermodynamic output of the simulation to see how long it takes to reach the equilibrium state (and indeed, whether this happens at all). Instructions are given below to import data from the LAMMPS log file into Microsoft Excel. Once you have the data in a spreadsheet, you can plot it. If you know how to use some of the other plotting software available on the chemistry computers (like Origin), you are welcome to use it.&lt;br /&gt;
&lt;br /&gt;
# Open a blank Excel workbook&lt;br /&gt;
# Copy the data in the textfile into the first cell&lt;br /&gt;
# With these data highlighted, click the Data tab and &amp;quot;Text to Columns&amp;quot;&lt;br /&gt;
# Click &amp;quot;Delimited&amp;quot;, continue and let it be space delimited&lt;br /&gt;
# Click finish&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 7: &amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== What does it mean for a simulation to &amp;quot;reach equilibrium&amp;quot;? Why is this important in terms of sampling from an ensemble using molecular dynamics? [2] ===&lt;br /&gt;
&lt;br /&gt;
=== Plot the energy (potential, kinetic and total), temperature and pressure, against time for the 0,001 timestep experiment [2] ===&lt;br /&gt;
&lt;br /&gt;
=== Does the simulation reach equilibrium? How can you tell? [2] ===&lt;br /&gt;
&lt;br /&gt;
=== Make a single plot which shows the energy vs. time for the timesteps you have simulated [2]. ===&lt;br /&gt;
&lt;br /&gt;
=== Of the timesteps that you used, which timestep will you use for subsequent simulations and why? [6] ===&lt;br /&gt;
&#039;&#039;(Think about what is happening &amp;quot;physically&amp;quot; as you increase/decrease the timestep. Also, what features of each timeseries are indicative of the simulation&#039;s &amp;quot;health&amp;quot;?)&#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 third year simulation experiment. You can return to the previous page, [[Third_year_simulation_experiment/Introduction_to_molecular_dynamics_simulation|Introduction to molecular dynamics simulation]], or jump ahead to the next section, [[Third year simulation experiment/Running simulations under specific conditions|Running simulations under specific conditions]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Equilibration&amp;diff=813821</id>
		<title>Third year simulation experiment/Equilibration</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Equilibration&amp;diff=813821"/>
		<updated>2021-10-20T13:08:37Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* Creating the simulation box */&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 third year simulation experiment. You can return to the previous page, [[Third_year_simulation_experiment/Introduction_to_molecular_dynamics_simulation|Introduction to molecular dynamics simulation]], or jump ahead to the next section, [[Third year simulation experiment/Running simulations under specific conditions|Running simulations under specific conditions]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
We will be using the LAMMPS program to carry out our molecular dynamics simulations.&lt;br /&gt;
&#039;&#039;&#039;In several places in this section, we will ask you to consult the LAMMPS manual to find out things about how the software works. You can find the manual [https://lammps.sandia.gov/doc/Manual.html here].&#039;&#039;&#039; We appreciate that the format of this document can make it a little hard to navigate, but it is the definitive resource on how different commands in LAMMPS work, and is therefore invaluable. The files you will need for this section can be found in the intro folder downloaded previously.&lt;br /&gt;
&lt;br /&gt;
===Creating the simulation box===&lt;br /&gt;
In the previous section, it was pointed out that before we can start a simulation, we need to know the initial states of all of the atoms in the system. Exactly what information we need about each atom depends on which method of numerical integration we need, but at the very least we need to specify the starting position of each atom. If we wanted to simulate a crystal, this information would be quite easy to come by &amp;amp;mdash; we could just look up the crystal structure, and use that to generate coordinates for however many unit cells we wanted. For this purpose, LAMMPS includes a command which generates crystal lattice structures.&lt;br /&gt;
&lt;br /&gt;
Generating coordinates for atoms in a liquid is more difficult. There is no long range order, so we can&#039;t use a single point of reference to work out the positions of every other atom like we can in a solid. We could generate a random position for each atom. This would certainly create a disordered structure, but causes larger problems when we try to run the simulation.&lt;br /&gt;
&lt;br /&gt;
Instead, we are going to place the atoms on the lattice points of a simple cubic lattice. This, of course, is not a situation in which the system is likely to be found physically. It turns out, though, that if we simulate for enough time we will find that the atoms rearrange themselves into more realistic configurations. We will discuss towards the end of this section exactly what is meant by &amp;quot;enough time&amp;quot;!&lt;br /&gt;
&lt;br /&gt;
Consider the line in the input file &amp;lt;pre&amp;gt;lattice sc 0.8&amp;lt;/pre&amp;gt; This command [https://lammps.sandia.gov/doc/lattice.html (further info)] creates a grid of points forming a simple cubic lattice (one lattice point per unit cell). The parameter &amp;lt;math&amp;gt;0.8&amp;lt;/math&amp;gt; specifies the number density (number of lattice points per unit volume). In a corresponding output file, you will see the line &amp;lt;pre&amp;gt;Lattice spacing in x,y,z = 1.07722 1.07722 1.07722&amp;lt;/pre&amp;gt; This indicates that the distance between the points of this lattice is &amp;lt;math&amp;gt;1.07722&amp;lt;/math&amp;gt; (in reduced units, remember!).&lt;br /&gt;
&lt;br /&gt;
The next lines in the input file are&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
region box block 0 5 0 5 0 5&lt;br /&gt;
create_box 1 box&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The corresponding log file output is &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Created orthogonal box = (0.0000000 0.0000000 0.0000000) to (5.3860867 5.3860867 5.3860867)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The region command [https://lammps.sandia.gov/doc/region.html (further info)] simply defines a geometrical region in space, which we call &amp;quot;box&amp;quot;. In this case, &amp;quot;box&amp;quot; is a cube extending ten lattice spacings from the origin in all three dimensions. The subsequent create_box command [https://lammps.sandia.gov/doc/create_box.html (further info)] tells LAMMPS to use the geometrical region called &amp;quot;box&amp;quot; as a template for the simulation box. The number 1 between &amp;quot;create_box&amp;quot; and &amp;quot;box&amp;quot; indicates that our simulation will contain only one type (species) of atom.&lt;br /&gt;
&lt;br /&gt;
So far we have defined a simulation box which is based around a virtual simple cubic lattice. Our box contains 125 (5x5x5) unit cells of this lattice, and so contains 125 lattice points. We now need to fill our simulation box with atoms. The input command is &amp;lt;pre&amp;gt;create_atoms 1 box&amp;lt;/pre&amp;gt; [https://lammps.sandia.gov/doc/create_atoms.html (further info)] while the log file simply contains an acknowledgement of this &amp;lt;pre&amp;gt;Created 125 atoms&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The create_atoms command has two arguments; the first tells LAMMPS that all of the atoms that we create will be of type 1. Every atom in the simulation has a type &amp;amp;mdash; because we will be simulating a pure fluid, containing only one chemical species, every atom will have the same type. The actual type that we assign to each atom is arbitrary &amp;amp;mdash; type 1 does not, for example, need to correspond to the element with atomic number 1 (hydrogen). If we wanted to simulate water, we might make the hydrogen atoms type 1 and the oxygen atoms type 2. We will specify the physical and chemical properties of each atom type later in the input script.&lt;br /&gt;
&lt;br /&gt;
The remaining data in the log file isn&#039;t very instructive as it stands &amp;amp;mdash; it simply contains a list of the thermodynamic properties of the simulation at certain intervals. In a few sections time, we will plot this data, but for now you can close the log file. Keep the input script open.&lt;br /&gt;
&lt;br /&gt;
===Setting the properties of the atoms===&lt;br /&gt;
&lt;br /&gt;
In addition to their positions, we also need the physical properties of the atoms to be able to perform the simulation. We set these properties on a &#039;per-type&#039; basis, so that every atom of the same type has the same mass and the same interactions.&lt;br /&gt;
&lt;br /&gt;
So far we have created 125 atoms, and we know the starting (&amp;lt;math&amp;gt;t = 0&amp;lt;/math&amp;gt;) position for each of them. We have also set their masses, and told LAMMPS what sort of forces to calculate between them. The final thing we need to specify to completely specify the initial conditions is the velocity of each atom.&lt;br /&gt;
&lt;br /&gt;
Choosing initial velocities for the atoms is a little easier than choosing initial positions. From the statistical thermodynamics lectures, you should know that, at equilibrium, the velocities of atoms in any system must be distributed according to the [http://en.wikipedia.org/wiki/Maxwell%E2%80%93Boltzmann_distribution Maxwell-Boltzmann (MB) distribution]. If we know the masses of the atoms, and we know what temperature we want to simulate, then we can determine the relevant MB distribution function. LAMMPS is able to give every atom a random velocity whilst ensuring that overall the MB distribution is followed. This is the purpose of the line&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
velocity all create 1.5 12345 dist gaussian rot yes mom yes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can see the manual page for this command [http://lammps.sandia.gov/doc/velocity.html here], but the key sections are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;all&#039;&#039;&#039;: the &#039;&#039;group&#039;&#039; of atoms on which the command acts. &#039;&#039;&#039;all&#039;&#039;&#039; simply specifies that we want every atom to have a velocity assigned to it.&lt;br /&gt;
* &#039;&#039;&#039;1.5&#039;&#039;&#039;: the temperature, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, needed to calculate the MB distribution(in reduced units, as always)&lt;br /&gt;
&lt;br /&gt;
===Monitoring thermodynamic properties===&lt;br /&gt;
&lt;br /&gt;
We need to be sure that our simulation is correctly modelling whatever physical system we want to study. It is relatively easy to set up simulations, but how can we be sure that the &amp;quot;results&amp;quot; we get make sense? One of the best ways is to calculate from the simulation things that we can measure in experiment, and see if they agree. For example, we might want to simulate our system at a particular temperature and pressure, and measure the resulting density. If we repeat this over a range of temperatures at the same pressure, we will be able to plot an &#039;&#039;equation of state&#039;&#039;, which we could compare to experimental measurements.&lt;br /&gt;
&lt;br /&gt;
LAMMPS is able to calculate a great deal of thermodynamic information for us (you can see a full list of the properties it is able to calculate [http://lammps.sandia.gov/doc/thermo_style.html here]), but in these first simulations we are only interested in those properties specified in these commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
thermo_style custom time etotal temp press&lt;br /&gt;
thermo 10&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first controls which properties will be printed out in the log file. In this case, we print how much time we have simulated so far (which is &#039;&#039;not&#039;&#039; the same as how long it has taken us to simulate it!), the total energy of the atoms, their temperature, and their pressure. The second line tells LAMMPS to print this information on every 10th timestep.&lt;br /&gt;
&lt;br /&gt;
===Running the simulation===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Look at the lines below.&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
### SPECIFY TIMESTEP ###&lt;br /&gt;
variable timestep equal 0.001&lt;br /&gt;
variable n_steps equal floor(100/${timestep})&lt;br /&gt;
timestep ${timestep}&lt;br /&gt;
&lt;br /&gt;
### RUN SIMULATION ###&lt;br /&gt;
run ${n_steps}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;The second line (starting &amp;quot;variable timestep...&amp;quot;) tells LAMMPS that if it encounters the text ${timestep} on a subsequent line, it should replace it by the value given. In this case, the value ${timestep} is always replaced by 0.001.&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt; It is now time to run your first simulation, submit the input script with the data file in the intro folder of the files you have downloaded Try changing the timestep - what happens when you make the timestep larger?. &amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Visualising the trajectory===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;trajectory files&#039;&#039;&#039; contain the positions of all the atoms in the simulation, recorded at a set interval (for all of these simulations, this was every ten timesteps &amp;amp;mdash; this is controlled by the &#039;&#039;&#039;dump&#039;&#039;&#039; command in the input scripts). We use a programme called [http://www.ks.uiuc.edu/Research/vmd/ &#039;&#039;&#039;VMD&#039;&#039;&#039;] to view these trajectories, which you should find is already installed on both the desktop and laptop computers. You can run VMD from the start menu with &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;University of Illinois&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;VMD&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Loading a Trajectory====&lt;br /&gt;
&lt;br /&gt;
We&#039;ll start by looking at the output of the 0.02 timestep simulation. In the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window, select the menu option &#039;&#039;&#039;File&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;New Molecule&#039;&#039;&#039;. Click the &#039;&#039;&#039;Browse&#039;&#039;&#039; button, then select the relevant trajectory file. In the &#039;&#039;&#039;Determine file type&#039;&#039;&#039; dropdown, select &#039;&#039;&#039;LAMMPS Trajectory&#039;&#039;&#039;. Then click &#039;&#039;&#039;Load&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You will see that the &#039;&#039;&#039;VMD 1.9.1 OpenGL Display&#039;&#039;&#039; window now shows a horrible mess. VMD&#039;s default behaviour is to draw lines between atoms which it thinks might be chemically bonded. Our system doesn&#039;t model chemical bonds, so we want to turn this off. In the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window, select the menu option &#039;&#039;&#039;Graphics&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Representations&#039;&#039;&#039;. This shows a list of &amp;quot;representations&amp;quot; of our atoms. You will see that at the moment, there is a single representation listed, and it is selected. It will have the &#039;&#039;Lines&#039;&#039; style, the &#039;&#039;Name&#039;&#039; colour, and the selection &#039;&#039;all&#039;&#039;. &amp;quot;Selection&amp;quot; simply tells VMD which atoms we want it to draw. We want to show every atom, so the current selection is fine. The &#039;&#039;name&#039;&#039; colouring method just makes VMD give atoms colours according to their specified type. The colour isn&#039;t important to us, so we can leave this be too. The &amp;quot;style&amp;quot; tells VMD what we want it to display for each atom. Change the &#039;&#039;&#039;Drawing Method&#039;&#039;&#039; from &#039;&#039;Lines&#039;&#039; to &#039;&#039;VDW&#039;&#039;. You will see that the mess of lines is replaced by a mess of low resolution, overlapping spheres. Change the &#039;&#039;&#039;Sphere Scale&#039;&#039;&#039; to 0.3, and the &#039;&#039;&#039;Sphere Resolution&#039;&#039;&#039; to 17. The result should look a little smoother. Close the &#039;&#039;&#039;Graphical Representations&#039;&#039;&#039; window. You will notice that in the bottom right of the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window, there is a small play button. Click this, and you will see the animated version of your simulation trajectory.&lt;br /&gt;
&lt;br /&gt;
By clicking and dragging with the mouse, you can rotate the simulation box (though this may be sluggish). At any time, you can reset the view by pressing the equals key.&lt;br /&gt;
&lt;br /&gt;
====Tracking a Single Particle====&lt;br /&gt;
To illustrate the periodic boundary conditions that we are using, we are going to draw almost all of the atoms as points, but we will pick a single atom at random to draw as a sphere. This will make it easy to see how a single atom moves through the box. Reset the display using the equals key, then use the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window controls to pause the trajectory and reset it to the first trajectory (play with the different buttons until you find the one that does this). You should see the perfect cubic lattice. Use the option &#039;&#039;&#039;Display&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Orthographic&#039;&#039;&#039; to change the drawing mode, then rotate the displayed crystal so that you are looking at one vertex (looking down the 111 direction, in crystallographic terms).&lt;br /&gt;
&lt;br /&gt;
Open the &#039;&#039;&#039;Graphical Representations&#039;&#039;&#039; window again. Change the representation style from &#039;&#039;&#039;VDW&#039;&#039;&#039; to points, then click the &#039;&#039;&#039;Create Rep&#039;&#039;&#039; button. This creates a second representation, allowing a subset of the atoms to be drawn in a different way. The &#039;&#039;&#039;Selected Atoms&#039;&#039;&#039; box allows us to choose which atoms this representation applies to. We just want to pick two of them at random &amp;amp;mdash; VMD assigns every atom an index, from 0 to N-1. In our case, there are 125 atoms, so choose two numbers between 0 and 124. Changed the &#039;&#039;&#039;Selected Atoms&#039;&#039;&#039; field to &amp;lt;pre&amp;gt;index i or index j&amp;lt;/pre&amp;gt; where i and j are your chosen numbers, press return, then change the &#039;&#039;&#039;Drawing Method&#039;&#039;&#039; to &#039;&#039;&#039;VDW&#039;&#039;&#039;. You should now see only two atoms represented by spheres, with the rest shown as small points. In the &#039;&#039;&#039;VMD Main&#039;&#039;&#039; window, click play. Try rotating the box, and changing the playback speed.&lt;br /&gt;
&lt;br /&gt;
You will see that sometimes one of the spheres seems to change position across the box very rapidly &amp;amp;mdash; this occurs when it reaches one periodic boundary, and is reflected back across the other face. Try playing with some of the other representation types in VMD &amp;amp;mdash; it  is a very powerful package, which is often used to render images of simulated proteins, so many of its options aren&#039;t relevant to our simple system!&lt;br /&gt;
&lt;br /&gt;
===Checking equilibration===&lt;br /&gt;
&lt;br /&gt;
When we first set up a simulation, it is very important to make sure that our system reaches an equilibrium state. We characterise equilibrium by the average values of thermodynamic quantities becoming constant (due to the approximations that we have made, there will always be fluctuations, but the average values will become constant).&lt;br /&gt;
&lt;br /&gt;
In this section, we are going to plot the thermodynamic output of the simulation to see how long it takes to reach the equilibrium state (and indeed, whether this happens at all). Instructions are given below to import data from the LAMMPS log file into Microsoft Excel. Once you have the data in a spreadsheet, you can plot it. If you know how to use some of the other plotting software available on the chemistry computers (like Origin), you are welcome to use it.&lt;br /&gt;
&lt;br /&gt;
# Open a blank Excel workbook&lt;br /&gt;
# Copy the data in the textfile into the first cell&lt;br /&gt;
# With these data highlighted, click the Data tab and &amp;quot;Text to Columns&amp;quot;&lt;br /&gt;
# Click &amp;quot;Delimited&amp;quot;, continue and let it be space delimited&lt;br /&gt;
# Click finish&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 7: &amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== What does it mean for a simulation to &amp;quot;reach equilibrium&amp;quot;? Why is this important in terms of sampling from an ensemble using molecular dynamics? [2] ===&lt;br /&gt;
&lt;br /&gt;
=== Plot the energy (potential, kinetic and total), temperature and pressure, against time for the 0,001 timestep experiment [2] ===&lt;br /&gt;
&lt;br /&gt;
=== Does the simulation reach equilibrium? How can you tell? [2] ===&lt;br /&gt;
&lt;br /&gt;
=== Make a single plot which shows the energy vs. time for the timesteps you have simulated [2]. ===&lt;br /&gt;
&lt;br /&gt;
=== Of the timesteps that you used, which timestep will you use for subsequent simulations and why? [6] ===&lt;br /&gt;
&#039;&#039;(Think about what is happening &amp;quot;physically&amp;quot; as you increase/decrease the timestep. Also, what features of each timeseries are indicative of the simulation&#039;s &amp;quot;health&amp;quot;?)&#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 third year simulation experiment. You can return to the previous page, [[Third_year_simulation_experiment/Introduction_to_molecular_dynamics_simulation|Introduction to molecular dynamics simulation]], or jump ahead to the next section, [[Third year simulation experiment/Running simulations under specific conditions|Running simulations under specific conditions]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Files_to_download&amp;diff=813820</id>
		<title>Third year simulation experiment/Files to download</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Files_to_download&amp;diff=813820"/>
		<updated>2021-10-20T13:03:55Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* 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 first section of the third year simulation experiment. You can return to the introduction page, [[Third year simulation experiment]], or jump ahead to the next section, [[Third year simulation experiment/Introduction to molecular dynamics simulation|Introduction to molecular dynamics simulation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
All of the simulations that you run in this experiment are going to be performed in Virtual Machines (VM). Before the beginning of your lab session, you should have received an invitation email to register/connect to the VM. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;The small-scale simulations that we will perform in this experiment should not be too long a few minutes. &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In each section of the exercise, we have tried to provide a number of mathematical and/or research exercises that you should attempt while you are waiting for the simulations in that section to be completed. You can also use this time to write your report on the previous sections!&lt;br /&gt;
&lt;br /&gt;
In this first section, we will teach you how to login to the Virtual Machines and submit an example simulation. While you wait for that example to complete, you can move on to the next section and read about the theory of molecular dynamics simulations&lt;br /&gt;
&lt;br /&gt;
==Connecting to the Virtual Machine==&lt;br /&gt;
&lt;br /&gt;
You will be using a Microsoft Azure Lab Virtual Machine (VM) to access the software needed for the lab.&lt;br /&gt;
&lt;br /&gt;
: 1. You will receive an invitation email, before your session starts, with the subject Register for Lab - IC_Chemistry_UK.&lt;br /&gt;
: 2. Follow the link to &#039;Register for the lab&#039; in the email which will direct you to the Azure Lab Services page.&lt;br /&gt;
: 3. On the web page, you should see a box corresponding to the VM shared with you. In the bottom left, slide the toggle from left to right to start the VM (It may take some time to start running).&lt;br /&gt;
: 4. Once running, at the bottom right of the box, click the computer-style icon next to the three vertical dots.&lt;br /&gt;
A file with the extension rdp will be downloaded: IC_Chemistry_UK.rdp. Follow the instructions for your operating service below to use the file:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Windows&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:: a. Navigate to where the file has downloaded and double click on the file to open.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Linux&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:: a. Open a terminal window and through the terminal, go to the location where the file has downloaded.&lt;br /&gt;
:: b. Type the command: &amp;lt;pre&amp;gt; remmina IC_Chemistry_UK.rdp &amp;lt;/pre&amp;gt; to run the file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Mac&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:: a. Download and install the Microsoft Remote Desktop app for Mac OS.&lt;br /&gt;
:: b. Open the Microsoft Remote Desktop app&lt;br /&gt;
:: c. On the top toolbar bar, click on the cog icon and then select Import from RDP file..&lt;br /&gt;
:: d. Navigate and select the downloaded rdp file.&lt;br /&gt;
:: e. There should now be an &#039;IC_Chemistry_UK&#039; PC showing, double click on this to initialise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: 5. You should be asked to Accept Certificate?, select Yes.&lt;br /&gt;
: 6. You will be asked to Enter authentication credentials:&lt;br /&gt;
:: a. Change the username into &amp;quot;chemistry&amp;quot; by removing &amp;quot;~/&amp;quot;.&lt;br /&gt;
:: b. Enter Imperial2021 as the password.&lt;br /&gt;
The VM should now launch and you will be taken to a Windows desktop where you should be able to see the LAMMPS icon on the desktop. Double click this to launch.&lt;br /&gt;
&lt;br /&gt;
If you have any problems with accessing the VM then let a demonstrator know.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--The simulations that you will perform in this experiment can in principle be performed on a desktop computer. However, these machines can only do a single simulation at a time, and are rather slow. Instead, we are going to run simulations on the college&#039;s supercomputer resources. This offers two large advantages. Firstly, even the longest simulations we will perform should take only a few hours. More importantly, you will be able to perform several simulations at the same time. In fact, to use the HPC service you must add your simulations to a queue of &amp;quot;jobs&amp;quot; that the supercomputer will perform. You can add as many jobs as you like to this queue, and simple come back to collect the results some time later.&lt;br /&gt;
&lt;br /&gt;
To start, go to [http://portal.hpc.imperial.ac.uk the HPC portal login page] (as a reminder you must be on the college VPN or remote desktop). You can login with your normal college credentials. We first need to create a &amp;quot;project&amp;quot; with which your simulations will be associated. Click &#039;&#039;&#039;Projects&#039;&#039;&#039; in the menu on the left hand side, then type a name in the &amp;quot;Add Project&amp;quot; box and click &#039;&#039;&#039;Add&#039;&#039;&#039;. You are free to choose whichever name you like, but a sensible choice might be something such as &amp;quot;ThirdYearSimulationExpt&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Leave the HPC Portal webpage open for now &amp;amp;mdash; we will return to it shortly. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Getting the files for the experiment==&lt;br /&gt;
&lt;br /&gt;
You can download all of the files that you will need for this experiment [https://imperialcollegelondon.box.com/s/mjxn9zxl67y10pgn8wkwlin05hmyqdsn from this address]. You should copy the folder &#039;&#039;&#039;ImperialChem-Year3SimExpt1415-master&#039;&#039;&#039; to a location of your choice. It contains a number of subfolders &amp;amp;mdash; one for each section of the experiment. Every subsequent page of this lab manual will begin with a line telling you which folder contains the necessary files, like this one: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;&#039;&#039;&#039;THE FILES THAT YOU NEED FOR THIS SECTION ARE FOUND IN THE &amp;quot;Intro&amp;quot; SUBFOLDER&#039;&#039;&#039;.&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Have a look in the &#039;&#039;&#039;&amp;quot;Intro&amp;quot;&#039;&#039;&#039; folder now. It contains a file called &#039;&#039;&#039;melt_crystal.in&#039;&#039;&#039;, which you should open with a text editor (like Notepad++ or VSCode which you can find on Software Hub. VSCode is also on the Virtual Machines). This file is called an &amp;quot;input script&amp;quot;, and it controls how the simulation software operates. We will perform all of our simulations with a software package called [http://lammps.sandia.gov LAMMPS]. Over the course of the experiment, you will learn what all of the commands in this file mean. The [https://lammps.sandia.gov/doc/Commands.html LAMMPS manual] contains a lot of valuable information about each of the commands, if you don&#039;t understand one of them or want to look up what some parameter means you can look it up there. To make life easier, we put &amp;quot;further info&amp;quot; links in the wiki. For now, we are going to use this file to run a few trial simulations. &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 third year simulation experiment.  You can return to the introduction page, [[Third year simulation experiment]], or jump ahead to the next section, [[Third year simulation experiment/Introduction to molecular dynamics simulation|Introduction to molecular dynamics simulation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</name></author>
	</entry>
	<entry>
		<id>https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Files_to_download&amp;diff=813819</id>
		<title>Third year simulation experiment/Files to download</title>
		<link rel="alternate" type="text/html" href="https://chemwiki.ch.ic.ac.uk/index.php?title=Third_year_simulation_experiment/Files_to_download&amp;diff=813819"/>
		<updated>2021-10-20T12:51:45Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* 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 first section of the third year simulation experiment. You can return to the introduction page, [[Third year simulation experiment]], or jump ahead to the next section, [[Third year simulation experiment/Introduction to molecular dynamics simulation|Introduction to molecular dynamics simulation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
All of the simulations that you run in this experiment are going to be performed in Virtual Machines (VM). Before the beginning of your lab session, you should have received an invitation email to register/connect to the VM. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;The small-scale simulations that we will perform in this experiment should not be too long a few minutes. &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In each section of the exercise, we have tried to provide a number of mathematical and/or research exercises that you should attempt while you are waiting for the simulations in that section to be completed. You can also use this time to write your report on the previous sections!&lt;br /&gt;
&lt;br /&gt;
In this first section, we will teach you how to login to the Virtual Machines and submit an example simulation. While you wait for that example to complete, you can move on to the next section and read about the theory of molecular dynamics simulations&lt;br /&gt;
&lt;br /&gt;
==Connecting to the Virtual Machine==&lt;br /&gt;
&lt;br /&gt;
You will be using a Microsoft Azure Lab Virtual Machine (VM) to access the software needed for the lab.&lt;br /&gt;
&lt;br /&gt;
: 1. You will receive an invitation email, before your session starts, with the subject Register for Lab - IC_Chemistry_UK.&lt;br /&gt;
: 2. Follow the link to &#039;Register for the lab&#039; in the email which will direct you to the Azure Lab Services page.&lt;br /&gt;
: 3. On the web page, you should see a box corresponding to the VM shared with you. In the bottom left, slide the toggle from left to right to start the VM (It may take some time to start running).&lt;br /&gt;
: 4. Once running, at the bottom right of the box, click the computer-style icon next to the three vertical dots.&lt;br /&gt;
A file with the extension rdp will be downloaded: IC_Chemistry_UK.rdp. Follow the instructions for your operating service below to use the file:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Windows&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:: a. Navigate to where the file has downloaded and double click on the file to open.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Linux&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:: a. Open a terminal window and through the terminal, go to the location where the file has downloaded.&lt;br /&gt;
:: b. Type the command: &amp;lt;pre&amp;gt; remmina IC_Chemistry_UK.rdp &amp;lt;/pre&amp;gt; to run the file.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Mac&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:: a. Download and install the Microsoft Remote Desktop app for Mac OS.&lt;br /&gt;
:: b. Open the Microsoft Remote Desktop app&lt;br /&gt;
:: c. On the top toolbar bar, click on the cog icon and then select Import from RDP file..&lt;br /&gt;
:: d. Navigate and select the downloaded rdp file.&lt;br /&gt;
:: e. There should now be an &#039;IC_Chemistry_UK&#039; PC showing, double click on this to initialise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
: 5. You should be asked to Accept Certificate?, select Yes.&lt;br /&gt;
: 6. You will be asked to Enter authentication credentials:&lt;br /&gt;
:: a. Change the username into &amp;quot;chemistry&amp;quot; by removing &amp;quot;~/&amp;quot;.&lt;br /&gt;
:: b. Enter Imperial2021 as the password.&lt;br /&gt;
The VM should now launch and you will be taken to a Windows desktop where you should be able to see the LAMMPS icon on the desktop. Double click this to launch.&lt;br /&gt;
&lt;br /&gt;
If you have any problems with accessing the VM then let a demonstrator know.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--The simulations that you will perform in this experiment can in principle be performed on a desktop computer. However, these machines can only do a single simulation at a time, and are rather slow. Instead, we are going to run simulations on the college&#039;s supercomputer resources. This offers two large advantages. Firstly, even the longest simulations we will perform should take only a few hours. More importantly, you will be able to perform several simulations at the same time. In fact, to use the HPC service you must add your simulations to a queue of &amp;quot;jobs&amp;quot; that the supercomputer will perform. You can add as many jobs as you like to this queue, and simple come back to collect the results some time later.&lt;br /&gt;
&lt;br /&gt;
To start, go to [http://portal.hpc.imperial.ac.uk the HPC portal login page] (as a reminder you must be on the college VPN or remote desktop). You can login with your normal college credentials. We first need to create a &amp;quot;project&amp;quot; with which your simulations will be associated. Click &#039;&#039;&#039;Projects&#039;&#039;&#039; in the menu on the left hand side, then type a name in the &amp;quot;Add Project&amp;quot; box and click &#039;&#039;&#039;Add&#039;&#039;&#039;. You are free to choose whichever name you like, but a sensible choice might be something such as &amp;quot;ThirdYearSimulationExpt&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Leave the HPC Portal webpage open for now &amp;amp;mdash; we will return to it shortly. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Getting the files for the experiment==&lt;br /&gt;
&lt;br /&gt;
You can download all of the files that you will need for this experiment [https://imperialcollegelondon.box.com/s/mjxn9zxl67y10pgn8wkwlin05hmyqdsn from this address]. You should copy the folder &#039;&#039;&#039;ImperialChem-Year3SimExpt1415-master&#039;&#039;&#039; to a location of your choice. It contains a number of subfolders &amp;amp;mdash; one for each section of the experiment. Every subsequent page of this lab manual will begin with a line telling you which folder contains the necessary files, like this one: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;&#039;&#039;&#039;THE FILES THAT YOU NEED FOR THIS SECTION ARE FOUND IN THE &amp;quot;Intro&amp;quot; SUBFOLDER&#039;&#039;&#039;.&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Have a look in the &#039;&#039;&#039;&amp;quot;Intro&amp;quot;&#039;&#039;&#039; folder now. It contains a file called &#039;&#039;&#039;melt_crystal.in&#039;&#039;&#039;, which you should open with a text editor (like Notepad++ which you can find on your Desktop). This file is called an &amp;quot;input script&amp;quot;, and it controls how the simulation software operates. We will perform all of our simulations with a software package called [http://lammps.sandia.gov LAMMPS]. Over the course of the experiment, you will learn what all of the commands in this file mean. The [https://lammps.sandia.gov/doc/Commands.html LAMMPS manual] contains a lot of valuable information about each of the commands, if you don&#039;t understand one of them or want to look up what some parameter means you can look it up there. To make life easier, we put &amp;quot;further info&amp;quot; links in the wiki. For now, we are going to use this file to run a few trial simulations. &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 third year simulation experiment.  You can return to the introduction page, [[Third year simulation experiment]], or jump ahead to the next section, [[Third year simulation experiment/Introduction to molecular dynamics simulation|Introduction to molecular dynamics simulation]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</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=813570</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=813570"/>
		<updated>2021-02-16T14:54:23Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* Importance Sampling */&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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Calculating the energy and magnetisation|Calculating the energy and magnetisation]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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 &amp;lt;math&amp;gt;1\times 10^9&amp;lt;/math&amp;gt; configurations per second with our computer. How long will it take to evaluate a single value of &amp;lt;math&amp;gt;\left\langle M\right\rangle_T&amp;lt;/math&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 &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; 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 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 it first in its list of the [http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=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, &amp;lt;math&amp;gt;\alpha_0&amp;lt;/math&amp;gt;, with energy &amp;lt;math&amp;gt;E_0&amp;lt;/math&amp;gt;.&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 &amp;lt;math&amp;gt;\alpha_1&amp;lt;/math&amp;gt;&lt;br /&gt;
# Calculate the energy of this new configuration, &amp;lt;math&amp;gt;E_1&amp;lt;/math&amp;gt;&lt;br /&gt;
# Calculate the energy difference between the states, &amp;lt;math&amp;gt;\Delta E = E_1 - E_0&amp;lt;/math&amp;gt;&lt;br /&gt;
## If the &amp;lt;math&amp;gt;\Delta E \leq 0&amp;lt;/math&amp;gt; (the spin flipping decreased the energy), then we &#039;&#039;&#039;accept&#039;&#039;&#039; the new configuration.&lt;br /&gt;
##* We set &amp;lt;math&amp;gt;\alpha_0 = \alpha_1&amp;lt;/math&amp;gt;, and &amp;lt;math&amp;gt;E_0 = E_1&amp;lt;/math&amp;gt;, and then &#039;&#039;&#039;go to step 5&#039;&#039;&#039;&lt;br /&gt;
## If &amp;lt;math&amp;gt;\Delta E &amp;gt; 0&amp;lt;/math&amp;gt;, the spin flipping increased the energy. By considering the probability of observing the starting and final states, &amp;lt;math&amp;gt;\alpha_0&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;\alpha_1&amp;lt;/math&amp;gt;, 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, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, in the interval &amp;lt;math&amp;gt;[0,1)&amp;lt;/math&amp;gt;&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 &amp;lt;math&amp;gt;\alpha_0 = \alpha_1&amp;lt;/math&amp;gt;, and &amp;lt;math&amp;gt;E_0 = E_1&amp;lt;/math&amp;gt;, 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;
###* &amp;lt;math&amp;gt;\alpha_0&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;E_0&amp;lt;/math&amp;gt; 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;cycle&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, &amp;lt;math&amp;gt;\Delta E&amp;lt;/math&amp;gt; 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;
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 &amp;quot;Understanding Molecular Simulation&amp;quot;, by Frenkel and Smit, but a discussion of this is not required for the experiment. You can find this as an ebook in the library [https://library-search.imperial.ac.uk/permalink/f/o1297h/TN_cdi_askewsholts_vlebooks_9780080519982 here]. Chapter 7 of &#039;Statistical Mechanics: Theory and Molecular Simulation&#039; 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;montecarlocycle(T)&#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 to measure the average energy and magnetisation: &#039;&#039;&#039;self.E&#039;&#039;&#039;, &#039;&#039;&#039;self.E2&#039;&#039;&#039;, &#039;&#039;&#039;self.M&#039;&#039;&#039;, &#039;&#039;&#039;self.M2&#039;&#039;&#039;, and &#039;&#039;&#039;self.n_cycles&#039;&#039;&#039;. You should use these values to keep a running sum of all of the energies, squared energies, magnetisations, and squared magnetisations that your system has sampled, as well as the number of cycles that have been performed. Finally, there is also a function &#039;&#039;&#039;statistics()&#039;&#039;&#039;, that takes no arguments.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3b&amp;lt;/big&amp;gt;: Implement a single cycle of the above algorithm in the montecarlocycle(T) function. This function should return the energy of your lattice and the magnetisation at the end of the cycle. You may assume that the energy returned by your energy() function is in units of &amp;lt;math&amp;gt;k_B&amp;lt;/math&amp;gt;! Complete the statistics() function. This should return the following quantities whenever it is called: &amp;lt;math&amp;gt;&amp;lt;E&amp;gt;, &amp;lt;E^2&amp;gt;, &amp;lt;M&amp;gt;, &amp;lt;M^2&amp;gt;&amp;lt;/math&amp;gt;, and the number of Monte Carlo steps that have elapsed.&#039;&#039;&#039;&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 IsingLattice object to run a Monte Carlo simulation and display the output on the screen in real time. By default, this simulation will run an &amp;lt;math&amp;gt;8\times 8&amp;lt;/math&amp;gt; lattice at &amp;lt;math&amp;gt;T=1.0&amp;lt;/math&amp;gt;, 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;statistics()&#039;&#039;&#039; function to print the average energy and magnetisation from the simulation.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 3c&amp;lt;/big&amp;gt;: If &amp;lt;math&amp;gt;T &amp;lt; T_C&amp;lt;/math&amp;gt;, do you expect a spontaneous magnetisation (i.e. do you expect &amp;lt;math&amp;gt;\left\langle M\right\rangle \neq 0&amp;lt;/math&amp;gt;)? 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 PNG 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Calculating the energy and magnetisation|Calculating the energy and magnetisation]], or jump ahead to the next section, [[Third year CMP compulsory experiment/Accelerating the code|Accelerating the code]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</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=813421</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=813421"/>
		<updated>2020-11-26T14:15:36Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* Finding the peak in C */&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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Determining the heat capacity|Determining the heat capacity]], or go back to the [[Third year CMP compulsory experiment|Introduction]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&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 &amp;lt;math&amp;gt;T = T_C&amp;lt;/math&amp;gt;. 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 &amp;lt;math&amp;gt;T_{C, L}&amp;lt;/math&amp;gt; is the Curie temperature of an &amp;lt;math&amp;gt;L\times L&amp;lt;/math&amp;gt;lattice, &amp;lt;math&amp;gt;T_{C,\infty}&amp;lt;/math&amp;gt; is the Curie temperature of an infinite lattice, and &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; is a constant in which we are not especially interested.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 8a&amp;lt;/big&amp;gt;: A C++ program has been used to run some much longer simulations than would be possible on the college computers in Python. You can view its source code [https://github.com/niallj/ducking-avenger/tree/master/Ising here] if you are interested. Each file contains six columns: &amp;lt;math&amp;gt;T, E, E^2, M, M^2, C&amp;lt;/math&amp;gt; (the final five quantities are per spin), and you can read them with the NumPy loadtxt function as before. For each lattice size, plot the C++ data against your data. For &#039;&#039;one&#039;&#039; lattice size, save a PNG of this comparison and add it to your report &amp;amp;mdash; add a legend to the graph to label which is which. To do this, you will need to pass the label=&amp;quot;...&amp;quot; keyword to the plot function, then call the legend() function of the axis object (documentation [http://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes.legend here]).&#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 has its maximum, 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 polyfit] and [http://docs.scipy.org/doc/numpy/reference/generated/numpy.polyval.html#numpy.polyval polyval] functions for this purpose. 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;: write a script to read the data from a particular file, and plot C vs T, 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 PNG 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 &amp;lt;math&amp;gt;T_{\mathrm{min}}&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;T_{\mathrm{max}}&amp;lt;/math&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;: Modify your script from the previous section. You should still plot the whole temperature range, but fit the polynomial only to the peak of the heat capacity! 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: peak_T_range, containing 1000 equally spaced temperature values between &amp;lt;math&amp;gt;T_{\mathrm{min}}&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;T_{\mathrm{max}}&amp;lt;/math&amp;gt; (whatever you chose those values to be), and fitted_C_values, containing the fitted heat capacity at each of those points. Use the NumPy max function to find the maximum in C. If you store the maximum value of C in the variable Cmax, 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;: find the temperature at which the maximum in C occurs for each datafile that you were given or generated with Python. Make a text file containing two colums: the lattice side length (2,4,8, etc.), and the temperature at which C is a maximum. This is your estimate of &amp;lt;math&amp;gt;T_C&amp;lt;/math&amp;gt; for that side length. Make a plot that uses the scaling relation given above to determine &amp;lt;math&amp;gt;T_{C,\infty}&amp;lt;/math&amp;gt;. By doing a little research online, 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 PNG 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Determining the heat capacity|Determining the heat capacity]], or go back to the [[Third year CMP compulsory experiment|Introduction]].&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Ac5116</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=813392</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=813392"/>
		<updated>2020-11-23T11:55:29Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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;
==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 Box [https://imperialcollegelondon.box.com/v/ising-lab-files here].&#039;&#039;&#039; If this link is broken you can alternatively try an older(slightly broken) version [https://github.com/niallj/ImperialChem-Year3CMPExpt/archive/master.zip here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We recommend that you use the IPython Qt or the regular ipython console (which you can access via spyder) to do your simulation work. This should be available on all of the college computers, where you can access it through &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Anaconda (64-bit)&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;IPython QTConsole&#039;&#039;&#039;. On your own Mac or Linux computer you can simply type &#039;ipython&#039; into the terminal. You are very welcome to use the IPython Notebook, that you were introduced to last year, to perform some of the analysis tasks later in the experiment. &lt;br /&gt;
&lt;br /&gt;
NOTE: QTConsole does not work for running the ILanim.py script you run latter in the lab. The best solution is to just run the script from the command line using &#039;&#039;&#039;python ILanim.py&#039;&#039;&#039; (if you&#039;re in the directory where files are stored). On a Mac/Linux computer you run this from &#039;&#039;&#039;Terminal&#039;&#039;&#039; or on windows you can use the app &#039;Conda Prompt&#039;&lt;br /&gt;
&lt;br /&gt;
When using the QTConsole, you should start the session by 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 you may need to restart the console)!&lt;br /&gt;
&lt;br /&gt;
For this section of the experiment, you will need the files &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; and &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;. Extract them from the zip file to a convenient location in your H drive, then in the IPython QTConsole use cd H:\... to move to the correct directory.&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. Open this file in your favourite text editor. 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 functions that you will complete as you work through the experiment.&lt;br /&gt;
&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 that you may not have met before, by defining a &#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 IsingLattice:&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. Lines 5-10 of IsingLattice.py create 5 variables that every object of type IsingLattice has:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
E = 0.0&lt;br /&gt;
&lt;br /&gt;
E2 = 0.0&lt;br /&gt;
&lt;br /&gt;
M = 0.0&lt;br /&gt;
&lt;br /&gt;
M2 = 0.0&lt;br /&gt;
&lt;br /&gt;
n_cycles = 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also functions defined, on lines 12, 17, 22, etc. We can see, for example, that each IsingLattice object has the functions energy(), magnetisation(), montecarlostep(T), and statistics() (the function __init__ will be explained shortly). Each of these functions 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;code&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() function of our IsingLattice object&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all variables and functions belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the montecarlostep() function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the function energy() which is part of the IsingLattice class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;quot;self.&amp;quot; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&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;
&lt;br /&gt;
&amp;lt;/code&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 function currently filled in is __init__. This is a special function 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 function 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 self.lattice is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;pre&amp;gt;np.random.choice&amp;lt;/pre&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for this function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html here].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions energy() and magnetisation(), which should return the energy of the lattice and the total magnetisation, respectively. In the energy() function you may assume that &amp;lt;math&amp;gt;J=1.0&amp;lt;/math&amp;gt; at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which &amp;lt;math&amp;gt;J=k_B&amp;lt;/math&amp;gt;, 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.&#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() functions, we need to test that they work correctly. You are welcome to do this yourself &amp;amp;mdash; from the IPython Qt console (ensuring that you are in the correct directory), you can simply type  &amp;lt;pre&amp;gt;import IsingLattice&amp;lt;/pre&amp;gt; then create objects of your class with the command &amp;lt;pre&amp;gt;il = IsingLattice.IsingLattice(n_rows, n_columns)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have also 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 IPython Qt console using the command &#039;&#039;&#039;&amp;lt;pre&amp;gt;%run ILcheck.py&amp;lt;/pre&amp;gt; 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 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;
&#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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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>Ac5116</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=813389</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=813389"/>
		<updated>2020-11-23T11:13:51Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* 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 third year CMP experiment. You can return to the introduction page, [[Third year CMP compulsory experiment]], 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, &amp;lt;math&amp;gt;s_i&amp;lt;/math&amp;gt;, each of which can either have the value &amp;quot;up&amp;quot; (&amp;lt;math&amp;gt;+1&amp;lt;/math&amp;gt;) or &amp;quot;down&amp;quot; (&amp;lt;math&amp;gt;-1&amp;lt;/math&amp;gt;), arranged on a lattice. In one dimension, this takes the form of a &amp;quot;chain&amp;quot; of adjacent spins, &amp;lt;math&amp;gt;s_1&amp;lt;/math&amp;gt; to &amp;lt;math&amp;gt;s_N&amp;lt;/math&amp;gt;. 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=5x5), and three (N=5x5x5) 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 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 &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt; is a constant which controls the strength of interaction and the notation &amp;lt;math&amp;gt;j\  \in\  \mathrm{neighbours}\left(i\right)&amp;lt;/math&amp;gt; indicates that spin &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; must lie in a lattice cell adjacent to spin &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;. 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 &amp;lt;math&amp;gt;J&amp;gt;0&amp;lt;/math&amp;gt;) is &amp;lt;math&amp;gt;E\ =\ -DNJ&amp;lt;/math&amp;gt;, where &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; is the number of dimensions and &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; 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 (&amp;lt;math&amp;gt;D=3,\ N=1000&amp;lt;/math&amp;gt;)? 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;, &amp;lt;math&amp;gt;T_C&amp;lt;/math&amp;gt;. Below &amp;lt;math&amp;gt;T_C&amp;lt;/math&amp;gt;, we observe the highly ordered magnetised phase, while above &amp;lt;math&amp;gt;T_C&amp;lt;/math&amp;gt; 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 &amp;lt;math&amp;gt;D = 3,\ N=1000&amp;lt;/math&amp;gt; at absolute zero?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We are interested, therefore, in determining the magnetisation &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, and energy &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt;, of the system as functions of temperature &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;. 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 &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; is used as a shorthand to represent all spins in the system, and &amp;lt;math&amp;gt;Z&amp;lt;/math&amp;gt; is the partition function. &#039;&#039;&#039;If you are doing this experiment before the statistical thermodynamics lecture course, you may not have seen expressions of this nature before. If so, please ask or e-mail the demonstrator, who will be happy to give you a brief introduction to the topic.&#039;&#039;&#039; 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 the 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 &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; 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 third year CMP experiment. You can return to the introduction page, [[Third year CMP compulsory experiment]], 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;/div&gt;</summary>
		<author><name>Ac5116</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=813305</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=813305"/>
		<updated>2020-10-26T09:35:34Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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;
==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 Box [https://imperialcollegelondon.box.com/v/ising-lab-files here].&#039;&#039;&#039; If this link is broken you can alternatively try an older(slightly broken) version [https://github.com/niallj/ImperialChem-Year3CMPExpt/archive/master.zip here].&lt;br /&gt;
&lt;br /&gt;
We recommend that you use the IPython Qt console to do your simulation work. This should be available on all of the college computers, where you can access it through &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Anaconda (64-bit)&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;IPython QTConsole&#039;&#039;&#039;. On your own Mac or Linux computer you can simply type &#039;ipython&#039; into the terminal. You are very welcome to use the IPython Notebook, that you were introduced to last year, to perform some of the analysis tasks later in the experiment. When using the QTConsole, you should start the session by 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!&lt;br /&gt;
&lt;br /&gt;
For this section of the experiment, you will need the files &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; and &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;. Extract them from the zip file to a convenient location in your H drive, then in the IPython QTConsole use cd H:\... to move to the correct directory.&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. Open this file in your favourite text editor. 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 functions that you will complete as you work through the experiment.&lt;br /&gt;
&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 that you may not have met before, by defining a &#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 IsingLattice:&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. Lines 5-10 of IsingLattice.py create 5 variables that every object of type IsingLattice has:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
E = 0.0&lt;br /&gt;
&lt;br /&gt;
E2 = 0.0&lt;br /&gt;
&lt;br /&gt;
M = 0.0&lt;br /&gt;
&lt;br /&gt;
M2 = 0.0&lt;br /&gt;
&lt;br /&gt;
n_cycles = 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also functions defined, on lines 12, 17, 22, etc. We can see, for example, that each IsingLattice object has the functions energy(), magnetisation(), montecarlostep(T), and statistics() (the function __init__ will be explained shortly). Each of these functions 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;code&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() function of our IsingLattice object&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all variables and functions belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the montecarlostep() function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the function energy() which is part of the IsingLattice class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;quot;self.&amp;quot; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&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;
&lt;br /&gt;
&amp;lt;/code&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 function currently filled in is __init__. This is a special function 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 function 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 self.lattice is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;pre&amp;gt;np.random.choice&amp;lt;/pre&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for this function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html here].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions energy() and magnetisation(), which should return the energy of the lattice and the total magnetisation, respectively. In the energy() function you may assume that &amp;lt;math&amp;gt;J=1.0&amp;lt;/math&amp;gt; at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which &amp;lt;math&amp;gt;J=k_B&amp;lt;/math&amp;gt;, 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.&#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() functions, we need to test that they work correctly. You are welcome to do this yourself &amp;amp;mdash; from the IPython Qt console (ensuring that you are in the correct directory), you can simply type  &amp;lt;pre&amp;gt;import IsingLattice&amp;lt;/pre&amp;gt; then create objects of your class with the command &amp;lt;pre&amp;gt;il = IsingLattice.IsingLattice(n_rows, n_columns)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have also 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 IPython Qt console using the command &#039;&#039;&#039;&amp;lt;pre&amp;gt;%run ILcheck.py&amp;lt;/pre&amp;gt; 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 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;
&#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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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>Ac5116</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=813277</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=813277"/>
		<updated>2020-10-20T14:16:17Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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;
==Getting the files for the experiment==&lt;br /&gt;
&lt;br /&gt;
Various scripts have been prepared to assist you with this experiment, and you can obtain them by downloading the files from the Box [https://imperialcollegelondon.box.com/v/ising-lab-files here]. If this link is broken you can alternatively try an older(slightly broken) version [https://github.com/niallj/ImperialChem-Year3CMPExpt/archive/master.zip here].&lt;br /&gt;
&lt;br /&gt;
We recommend that you use the IPython Qt console to do your simulation work. This should be available on all of the college computers, where you can access it through &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Anaconda (64-bit)&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;IPython QTConsole&#039;&#039;&#039;. On your own Mac or Linux computer you can simply type &#039;ipython&#039; into the terminal. You are very welcome to use the IPython Notebook, that you were introduced to last year, to perform some of the analysis tasks later in the experiment. When using the QTConsole, you should start the session by 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!&lt;br /&gt;
&lt;br /&gt;
For this section of the experiment, you will need the files &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; and &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;. Extract them from the zip file to a convenient location in your H drive, then in the IPython QTConsole use cd H:\... to move to the correct directory.&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. Open this file in your favourite text editor. 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 functions that you will complete as you work through the experiment.&lt;br /&gt;
&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 that you may not have met before, by defining a &#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 IsingLattice:&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. Lines 5-10 of IsingLattice.py create 5 variables that every object of type IsingLattice has:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
E = 0.0&lt;br /&gt;
&lt;br /&gt;
E2 = 0.0&lt;br /&gt;
&lt;br /&gt;
M = 0.0&lt;br /&gt;
&lt;br /&gt;
M2 = 0.0&lt;br /&gt;
&lt;br /&gt;
n_cycles = 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also functions defined, on lines 12, 17, 22, etc. We can see, for example, that each IsingLattice object has the functions energy(), magnetisation(), montecarlostep(T), and statistics() (the function __init__ will be explained shortly). Each of these functions 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;code&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() function of our IsingLattice object&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all variables and functions belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the montecarlostep() function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the function energy() which is part of the IsingLattice class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;quot;self.&amp;quot; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&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;
&lt;br /&gt;
&amp;lt;/code&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 function currently filled in is __init__. This is a special function 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 function 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 self.lattice is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;pre&amp;gt;np.random.choice&amp;lt;/pre&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for this function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html here].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions energy() and magnetisation(), which should return the energy of the lattice and the total magnetisation, respectively. In the energy() function you may assume that &amp;lt;math&amp;gt;J=1.0&amp;lt;/math&amp;gt; at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which &amp;lt;math&amp;gt;J=k_B&amp;lt;/math&amp;gt;, 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.&#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() functions, we need to test that they work correctly. You are welcome to do this yourself &amp;amp;mdash; from the IPython Qt console (ensuring that you are in the correct directory), you can simply type  &amp;lt;pre&amp;gt;import IsingLattice&amp;lt;/pre&amp;gt; then create objects of your class with the command &amp;lt;pre&amp;gt;il = IsingLattice.IsingLattice(n_rows, n_columns)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have also 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 IPython Qt console using the command &#039;&#039;&#039;&amp;lt;pre&amp;gt;%run ILcheck.py&amp;lt;/pre&amp;gt; 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 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;
&#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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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>Ac5116</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=813276</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=813276"/>
		<updated>2020-10-20T14:15:49Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* 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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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;
==Getting the files for the experiment==&lt;br /&gt;
&lt;br /&gt;
Various scripts have been prepared to assist you with this experiment, and you can obtain them by downloading the files from the Box [https://imperialcollegelondon.box.com/v/ising-lab-files here]. If this link is broken you can alternatively try an older(slightly broken) [here https://github.com/niallj/ImperialChem-Year3CMPExpt/archive/master.zip here].&lt;br /&gt;
&lt;br /&gt;
We recommend that you use the IPython Qt console to do your simulation work. This should be available on all of the college computers, where you can access it through &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Anaconda (64-bit)&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;IPython QTConsole&#039;&#039;&#039;. On your own Mac or Linux computer you can simply type &#039;ipython&#039; into the terminal. You are very welcome to use the IPython Notebook, that you were introduced to last year, to perform some of the analysis tasks later in the experiment. When using the QTConsole, you should start the session by 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!&lt;br /&gt;
&lt;br /&gt;
For this section of the experiment, you will need the files &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; and &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;. Extract them from the zip file to a convenient location in your H drive, then in the IPython QTConsole use cd H:\... to move to the correct directory.&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. Open this file in your favourite text editor. 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 functions that you will complete as you work through the experiment.&lt;br /&gt;
&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 that you may not have met before, by defining a &#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 IsingLattice:&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. Lines 5-10 of IsingLattice.py create 5 variables that every object of type IsingLattice has:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
E = 0.0&lt;br /&gt;
&lt;br /&gt;
E2 = 0.0&lt;br /&gt;
&lt;br /&gt;
M = 0.0&lt;br /&gt;
&lt;br /&gt;
M2 = 0.0&lt;br /&gt;
&lt;br /&gt;
n_cycles = 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also functions defined, on lines 12, 17, 22, etc. We can see, for example, that each IsingLattice object has the functions energy(), magnetisation(), montecarlostep(T), and statistics() (the function __init__ will be explained shortly). Each of these functions 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;code&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() function of our IsingLattice object&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all variables and functions belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the montecarlostep() function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the function energy() which is part of the IsingLattice class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;quot;self.&amp;quot; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&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;
&lt;br /&gt;
&amp;lt;/code&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 function currently filled in is __init__. This is a special function 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 function 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 self.lattice is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;pre&amp;gt;np.random.choice&amp;lt;/pre&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for this function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html here].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions energy() and magnetisation(), which should return the energy of the lattice and the total magnetisation, respectively. In the energy() function you may assume that &amp;lt;math&amp;gt;J=1.0&amp;lt;/math&amp;gt; at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which &amp;lt;math&amp;gt;J=k_B&amp;lt;/math&amp;gt;, 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.&#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() functions, we need to test that they work correctly. You are welcome to do this yourself &amp;amp;mdash; from the IPython Qt console (ensuring that you are in the correct directory), you can simply type  &amp;lt;pre&amp;gt;import IsingLattice&amp;lt;/pre&amp;gt; then create objects of your class with the command &amp;lt;pre&amp;gt;il = IsingLattice.IsingLattice(n_rows, n_columns)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have also 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 IPython Qt console using the command &#039;&#039;&#039;&amp;lt;pre&amp;gt;%run ILcheck.py&amp;lt;/pre&amp;gt; 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 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;
&#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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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>Ac5116</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=813275</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=813275"/>
		<updated>2020-10-20T13:03:35Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* A note about Python Classes */&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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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;
==Getting the files for the experiment==&lt;br /&gt;
&lt;br /&gt;
Various scripts have been prepared to assist you with this experiment, and you can obtain them by downloading the file [https://github.com/niallj/ImperialChem-Year3CMPExpt/archive/master.zip here].&lt;br /&gt;
&lt;br /&gt;
We recommend that you use the IPython Qt console to do your simulation work. This should be available on all of the college computers, where you can access it through &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Anaconda (64-bit)&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;IPython QTConsole&#039;&#039;&#039;. On your own Mac or Linux computer you can simply type &#039;ipython&#039; into the terminal. You are very welcome to use the IPython Notebook, that you were introduced to last year, to perform some of the analysis tasks later in the experiment. When using the QTConsole, you should start the session by 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!&lt;br /&gt;
&lt;br /&gt;
For this section of the experiment, you will need the files &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; and &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;. Extract them from the zip file to a convenient location in your H drive, then in the IPython QTConsole use cd H:\... to move to the correct directory.&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. Open this file in your favourite text editor. 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 functions that you will complete as you work through the experiment.&lt;br /&gt;
&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 that you may not have met before, by defining a &#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 IsingLattice:&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. Lines 5-10 of IsingLattice.py create 5 variables that every object of type IsingLattice has:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
E = 0.0&lt;br /&gt;
&lt;br /&gt;
E2 = 0.0&lt;br /&gt;
&lt;br /&gt;
M = 0.0&lt;br /&gt;
&lt;br /&gt;
M2 = 0.0&lt;br /&gt;
&lt;br /&gt;
n_cycles = 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also functions defined, on lines 12, 17, 22, etc. We can see, for example, that each IsingLattice object has the functions energy(), magnetisation(), montecarlostep(T), and statistics() (the function __init__ will be explained shortly). Each of these functions 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;code&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() function of our IsingLattice object&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all variables and functions belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the montecarlostep() function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the function energy() which is part of the IsingLattice class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;quot;self.&amp;quot; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&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;
&lt;br /&gt;
&amp;lt;/code&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 function currently filled in is __init__. This is a special function 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 function 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 self.lattice is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;pre&amp;gt;np.random.choice&amp;lt;/pre&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for this function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html here].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions energy() and magnetisation(), which should return the energy of the lattice and the total magnetisation, respectively. In the energy() function you may assume that &amp;lt;math&amp;gt;J=1.0&amp;lt;/math&amp;gt; at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which &amp;lt;math&amp;gt;J=k_B&amp;lt;/math&amp;gt;, 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.&#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() functions, we need to test that they work correctly. You are welcome to do this yourself &amp;amp;mdash; from the IPython Qt console (ensuring that you are in the correct directory), you can simply type  &amp;lt;pre&amp;gt;import IsingLattice&amp;lt;/pre&amp;gt; then create objects of your class with the command &amp;lt;pre&amp;gt;il = IsingLattice.IsingLattice(n_rows, n_columns)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have also 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 IPython Qt console using the command &#039;&#039;&#039;&amp;lt;pre&amp;gt;%run ILcheck.py&amp;lt;/pre&amp;gt; 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 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;
&#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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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>Ac5116</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=813274</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=813274"/>
		<updated>2020-10-20T13:03:11Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* A note about Python Classes */&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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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;
==Getting the files for the experiment==&lt;br /&gt;
&lt;br /&gt;
Various scripts have been prepared to assist you with this experiment, and you can obtain them by downloading the file [https://github.com/niallj/ImperialChem-Year3CMPExpt/archive/master.zip here].&lt;br /&gt;
&lt;br /&gt;
We recommend that you use the IPython Qt console to do your simulation work. This should be available on all of the college computers, where you can access it through &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Anaconda (64-bit)&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;IPython QTConsole&#039;&#039;&#039;. On your own Mac or Linux computer you can simply type &#039;ipython&#039; into the terminal. You are very welcome to use the IPython Notebook, that you were introduced to last year, to perform some of the analysis tasks later in the experiment. When using the QTConsole, you should start the session by 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!&lt;br /&gt;
&lt;br /&gt;
For this section of the experiment, you will need the files &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; and &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;. Extract them from the zip file to a convenient location in your H drive, then in the IPython QTConsole use cd H:\... to move to the correct directory.&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. Open this file in your favourite text editor. 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 functions that you will complete as you work through the experiment.&lt;br /&gt;
&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 that you may not have met before, by defining a &#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 IsingLattice:&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. Lines 5-10 of IsingLattice.py create 5 variables that every object of type IsingLattice has:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
E = 0.0&lt;br /&gt;
&lt;br /&gt;
E2 = 0.0&lt;br /&gt;
&lt;br /&gt;
M = 0.0&lt;br /&gt;
&lt;br /&gt;
M2 = 0.0&lt;br /&gt;
&lt;br /&gt;
n_cycles = 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also functions defined, on lines 12, 17, 22, etc. We can see, for example, that each IsingLattice object has the functions energy(), magnetisation(), montecarlostep(T), and statistics() (the function __init__ will be explained shortly). Each of these functions 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;code&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() function of our IsingLattice object&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all variables and functions belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the montecarlostep() function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the function energy() which is part of the IsingLattice class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;quot;self.&amp;quot; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&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;/code&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 function currently filled in is __init__. This is a special function 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 function 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 self.lattice is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;pre&amp;gt;np.random.choice&amp;lt;/pre&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for this function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html here].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions energy() and magnetisation(), which should return the energy of the lattice and the total magnetisation, respectively. In the energy() function you may assume that &amp;lt;math&amp;gt;J=1.0&amp;lt;/math&amp;gt; at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which &amp;lt;math&amp;gt;J=k_B&amp;lt;/math&amp;gt;, 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.&#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() functions, we need to test that they work correctly. You are welcome to do this yourself &amp;amp;mdash; from the IPython Qt console (ensuring that you are in the correct directory), you can simply type  &amp;lt;pre&amp;gt;import IsingLattice&amp;lt;/pre&amp;gt; then create objects of your class with the command &amp;lt;pre&amp;gt;il = IsingLattice.IsingLattice(n_rows, n_columns)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have also 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 IPython Qt console using the command &#039;&#039;&#039;&amp;lt;pre&amp;gt;%run ILcheck.py&amp;lt;/pre&amp;gt; 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 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;
&#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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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>Ac5116</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=813273</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=813273"/>
		<updated>2020-10-20T13:02:26Z</updated>

		<summary type="html">&lt;p&gt;Ac5116: /* The Constructor */&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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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;
==Getting the files for the experiment==&lt;br /&gt;
&lt;br /&gt;
Various scripts have been prepared to assist you with this experiment, and you can obtain them by downloading the file [https://github.com/niallj/ImperialChem-Year3CMPExpt/archive/master.zip here].&lt;br /&gt;
&lt;br /&gt;
We recommend that you use the IPython Qt console to do your simulation work. This should be available on all of the college computers, where you can access it through &#039;&#039;&#039;Start&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;All Programs&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Anaconda (64-bit)&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;IPython QTConsole&#039;&#039;&#039;. On your own Mac or Linux computer you can simply type &#039;ipython&#039; into the terminal. You are very welcome to use the IPython Notebook, that you were introduced to last year, to perform some of the analysis tasks later in the experiment. When using the QTConsole, you should start the session by 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!&lt;br /&gt;
&lt;br /&gt;
For this section of the experiment, you will need the files &#039;&#039;&#039;IsingLattice.py&#039;&#039;&#039; and &#039;&#039;&#039;ILcheck.py&#039;&#039;&#039;. Extract them from the zip file to a convenient location in your H drive, then in the IPython QTConsole use cd H:\... to move to the correct directory.&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. Open this file in your favourite text editor. 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 functions that you will complete as you work through the experiment.&lt;br /&gt;
&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 that you may not have met before, by defining a &#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 IsingLattice:&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. Lines 5-10 of IsingLattice.py create 5 variables that every object of type IsingLattice has:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
E = 0.0&lt;br /&gt;
&lt;br /&gt;
E2 = 0.0&lt;br /&gt;
&lt;br /&gt;
M = 0.0&lt;br /&gt;
&lt;br /&gt;
M2 = 0.0&lt;br /&gt;
&lt;br /&gt;
n_cycles = 0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also functions defined, on lines 12, 17, 22, etc. We can see, for example, that each IsingLattice object has the functions energy(), magnetisation(), montecarlostep(T), and statistics() (the function __init__ will be explained shortly). Each of these functions 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;code&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() function of our IsingLattice object&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When writing code &amp;quot;within&amp;quot; the class definition, all variables and functions belonging to the class must be accessed using the &amp;quot;self.&amp;quot; notation. You can see an example of this in the montecarlostep() function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
energy = self.energy()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line creates a variable called energy which contains whatever value was returned by the function energy() which is part of the IsingLattice class. If you just want to define a local variable instead, like an iterator in a loop, the &amp;quot;self.&amp;quot; notation is not required.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&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;/code&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 function currently filled in is __init__. This is a special function 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 function 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 self.lattice is then created, which is a NumPy array with the requested number of rows and columns. The function &amp;lt;pre&amp;gt;np.random.choice&amp;lt;/pre&amp;gt; is used to create a random collection of spins for our initial configuration. You can see the documentation for this function [https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html here].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;big&amp;gt;TASK 2a&amp;lt;/big&amp;gt;: complete the functions energy() and magnetisation(), which should return the energy of the lattice and the total magnetisation, respectively. In the energy() function you may assume that &amp;lt;math&amp;gt;J=1.0&amp;lt;/math&amp;gt; at all times (in fact, we are working in &#039;&#039;reduced units&#039;&#039; in which &amp;lt;math&amp;gt;J=k_B&amp;lt;/math&amp;gt;, 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.&#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() functions, we need to test that they work correctly. You are welcome to do this yourself &amp;amp;mdash; from the IPython Qt console (ensuring that you are in the correct directory), you can simply type  &amp;lt;pre&amp;gt;import IsingLattice&amp;lt;/pre&amp;gt; then create objects of your class with the command &amp;lt;pre&amp;gt;il = IsingLattice.IsingLattice(n_rows, n_columns)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We have also 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 IPython Qt console using the command &#039;&#039;&#039;&amp;lt;pre&amp;gt;%run ILcheck.py&amp;lt;/pre&amp;gt; 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 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;
&#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 third year CMP experiment. You can return to the previous page, [[Third_year_CMP_compulsory_experiment/Introduction to the Ising model|Introduction to the Ising model]], or jump ahead to the next section, [[Third year CMP compulsory experiment/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>Ac5116</name></author>
	</entry>
</feed>