|
| 1 | +--- |
| 2 | +jupytext: |
| 3 | + formats: md:myst |
| 4 | + text_representation: |
| 5 | + extension: .md |
| 6 | + format_name: myst |
| 7 | +kernelspec: |
| 8 | + display_name: Python 3 |
| 9 | + language: python |
| 10 | + name: python3 |
| 11 | +--- |
| 12 | + |
1 | 13 | ## Monte Carlo Simulation of the 1D Ising Model |
2 | 14 |
|
3 | 15 | In this exercise, you'll implement a Monte Carlo simulation of a 1D Ising model with 4 spins and periodic boundary conditions. We'll build this up in steps, eventually calculating the mean magnetisation as a function of temperature. |
@@ -45,14 +57,69 @@ Implement a single MC step that: |
45 | 57 | 2. Calculates $\Delta E$ for flipping this spin. |
46 | 58 | 3. Accepts/rejects the flip using the Metropolis criterion. |
47 | 59 |
|
48 | | -One way that you can select a random element from a numpy array is using `np.random.randint()`, which generates random integers from a specified range. By setting that range to the length of an array, you can use the result to pick a random array element. |
| 60 | +#### Python Hints |
| 61 | + |
| 62 | +**1.** One way that you can select a random element from a numpy array is using `np.random.randint()`, which generates random integers from a specified range. By setting that range to the length of an array, you can use the result to pick a random array element. |
49 | 63 |
|
50 | 64 | ```python |
51 | 65 | my_array = np.array(['a', 'b', 'c', 'd']) # create an length-4 array |
52 | 66 | random_index = np.random.randint(len(my_array)) # generate a random integer between 0 and 3 |
53 | 67 | print(my_array[random_index]) # print the corresponding array element |
54 | 68 | ``` |
55 | 69 |
|
| 70 | +**2.** Remember that a spin flip corresponds to changing a spin from $+1$ to $-1$, or from $-1$ to $+1$. In both cases, this corresponds to multiplying that element of your spin-state array by $-1$. |
| 71 | + |
| 72 | +**3.** Creating copies of numpy arrays requires care: |
| 73 | + |
| 74 | +```{code-cell} python |
| 75 | +import numpy as np |
| 76 | +
|
| 77 | +original_array = np.array(['a', 'b', 'c']) |
| 78 | +copied_array = original_array |
| 79 | +copied_array[0] = 'z' |
| 80 | +
|
| 81 | +print(f'original array: {original_array}') |
| 82 | +print(f'copied array: {copied_array}') |
| 83 | +``` |
| 84 | + |
| 85 | +Changing the first element in `copied_array` changed `original_array` too. Why does this happen? |
| 86 | + |
| 87 | +The assignment `copied_array = original_array` does not create a new array. Instead, both it creates a new variable name that points at the _same_ data in memory. Because `original_array` and `copied_array` both point to the same data, any changes to one array appear to be mirrored by the other array. |
| 88 | + |
| 89 | +For a true copy, use the `copy()` method: |
| 90 | + |
| 91 | +```{code-cell} python |
| 92 | +original_array = np.array(['a', 'b', 'c']) |
| 93 | +copied_array = original_array.copy() # Create a true copy |
| 94 | +copied_array[0] = 'z' |
| 95 | +
|
| 96 | +print(f'original array: {original_array}') |
| 97 | +print(f'copied array: {copied_array}') |
| 98 | +``` |
| 99 | + |
| 100 | +For the Ising model, you'll need to: |
| 101 | +1. Try flipping a spin |
| 102 | +2. Calculate the energy change |
| 103 | +3. Accept the flip or keep the previous state |
| 104 | + |
| 105 | +Without `copy()`, you can run into trouble: |
| 106 | + |
| 107 | +```{code-cell} python |
| 108 | +# Problem: both variables point to same data |
| 109 | +spins = np.ones(4) |
| 110 | +new_spins = spins # Seems like we are copying the spin state, but we are not |
| 111 | +new_spins[0] *= -1 # Flip a spin |
| 112 | +print(f'proposed move: {new_spins}') |
| 113 | +print(f'old spins: {spins}') # Changed too! |
| 114 | +
|
| 115 | +# Solution: make a true copy |
| 116 | +spins = np.ones(4) |
| 117 | +new_spins = spins.copy() |
| 118 | +new_spins[0] *= -1 |
| 119 | +print(f'proposed move: {new_spins}') |
| 120 | +print(f'old spins: {spins}') # Stays unchanged |
| 121 | +``` |
| 122 | + |
56 | 123 | ### Part 3: Magnetisation |
57 | 124 |
|
58 | 125 | The magnetisation is simply the sum of the spins. Implement a function to calculate the absolute magnetisation per spin. Your function should take a single numpy array describing the spin-state as the argument. |
|
0 commit comments