So now that we have our function for calculating the energy, according to this formula here, we can
calculate it really for every configuration and we can just call this function whenever we slightly
change this configuration of the magnetic moments, and it will update the energy immediately.
So we know if the energy decreases or increases, this means now we are ready to implement the actual
Monte Carlo algorithm.
And I was teasing this already to you.
This is basically just a loop over several metropolis steps.
So I think this lecture is really the most important one because here you really learn the core feature
of the Monte Carlo.
So I was reading this already briefly to you, but here it's in detail.
So what happens is at first we will randomly select a magnetic moment.
So right now we have a grid of 40 times 40 more moons, so 1600.
So we will generate two random indices between zero and 40 and then select a single one of these.
For example, this one.
And then we go to the second step, which will be this particular moment is reoriented along just some
random direction.
So as an as in the beginning, we will once again generate a random and Delphi and the random angle
Fita.
And then we will just change the orientation of this moment completely and we will do this randomly.
And what's very important is we must still store the old orientation for now, because now we will calculate
the new energy and we will compare the energy with the old energy.
So with the new moment and the old moment, and now we must use an if statement and if the energy is
decreased by those random change, then the change of the magnetic moment is accepted.
So we accept it and we can just delete the old magnetic moment and when the energy is increased.
This is considered a bat metropolis step, so we will just ignore it and we will restore the old magnetic
moment.
OK, so we know from this algorithm that two things can happen.
Either the energy is decreased, which is good, then the magnetization is updated or the magnetic moments
are updated, or we try to change it and we see the energy is increasing.
And then basically nothing happens because the old Sputnik moment is just restored.
So let's go ahead and implement this.
So we implement a single step.
And since we will add later on more energy terms here, I will call this function here step exchange
so that we know that we only consider the exchange interaction for now.
So as an argument, we only need the magnetization and we begin with the first step here.
A random magnetic moment is selected.
That's of course, pretty similar to what we have done previously.
First of all, we just generate two indices X and Y and P Dot Random Dot brand.
And since it's an integer, we write around it and when we write length, then it will be an integer
between zero and thirty nine in our case.
Then we do the same thing for why, because it must be a different random number.
And now we can write an energy old is equal to.
And now we could, of course, just write energy exchange magnetization.
So we could do this, as I said.
But it turns out that this is not really the ideal thing to do.
I will come back to this later.
We will change this later on.
It would work, but it's pretty slow to do it that way.
So now we come to the second step.
So this would be first and this would be second.
And this is exactly as we did previously.
So I can scroll up.
We will load these random values here.
So here in this case, we were generating an array of 40 times 40 random angles.
And here we only need a single one.
So basically, we can just say, delete all of this stuff and do it like this.
So now we have just a single random value phi and a single random all your theta.
And now we generate the magnetization.
So this we can also do as we did before.
And we can say magnetization.
And now we must specify which of these moments we will change because we will not randomly recreate
the whole era.
We would just change a single one of them and we will address here the moment x y zero.
So the moment with the coordinates x, y and zero and this will be the X, Y and Z coordinates, according
to the X, Y and Z coordinates, according to our two angles random fi and random Fita that we have
just randomly generated.
So one more thing that is really important that I didn't wrote explicitly here, but you see we had
to calculate our old energy and likewise we have to store our old magnetic moment.
So I will write here, save mark.
Is equal to and p dot array.
And then the magnetization.
X my zero.
So basically, we take this one, we store it in a different variable save mark.
And now you may wonder, why don't you just write the following Why don't you just write safe markers
equal to magnetization?
And to be fair to you, this is what I did in the beginning, but I noticed it doesn't work.
And this is because of some pointer issue.
So if I would ride it like this, then it would assign the same pointer to save mark as this one or
the same idea.
I saw the same ID in the storage.
And what happens then when we change this value here?
So basically, once we run this line of code, it also changes the safe mark variable.
This is exactly what we don't want.
We don't want to overwrite to save Mach variable.
We want to have it as an independent variable.
We want the right and pitot array of this.
Then it saves it as an independent variable.
So this was a bit surprising to me, to be fair, but it makes sense because this is how Python works
with the IDs and the pointer, you could say.
So let me right here.
Just as a reminder problem with the IDs save macro.
This would lead to.
Save mark will be changed once.
This change in the next line.
OK, so that's just a comment.
All right, so what we have now is we have the old energy.
We have the old magnetic moment saved and we have generated a new magnetization, a new magnetic magnetic
moment at at this particular point in space.
Now we can calculate the new energy.
So that's pretty easy.
We just write energy new is equal to and then we can just copy this because we have updated Mac.
So this will now be our new magnetization.
So as I said, this would work, but it's pretty slow.
So we will change this in a few minutes.
But let's continue for now, because now comes the if statement, the fourth part where we must compare
the energies.
So as I said, if and then rewrite if the energy new is smaller than the energy old, then do the following.
So we in this case accept the change and we update the energy and we can write basically energy
change.
Or we could say we will.
We will come to this in a second because you are on to do something special.
So I will write your energy just to remind us that we have to do something here still.
So just comment this and.
If this is not true, then we will use ours.
This would mean we decline and restore hold moment.
And we would then say magnetization.
I have the position X-Y Zero is equal to our safe mark magnetization or the magnetic moment that we
have saved previously.
OK.
And then we basically return the compact to magnetization.
We could say, OK, so the thing is now in the next step, we will loop over this many, many times,
maybe one million times.
And you see, we calculate here the energy once we calculate it here another time and we do this one
million times.
And the thing is, it takes a lot of time to do this, especially if the array or if the number of moments
that we consider is very large.
And it doesn't really make sense to do this because in each of these steps, we only change one single
magnetic moment.
And if you look at it here, we just change one particular moment, and the only energy terms that are
affected are the ones interacting with the four neighbors.
So why should we calculate the energy of the whole remaining thing over and over again?
This loses us so much time and slows down our coat so much.
So at this point, I think it makes much more sense to not calculate the energy every time, but to
calculate the change of the energy every time.
So we will only store here the energy that corresponds to this particular moment that we will change
and the interaction with the neighbors.
So let me show you how this works.
So we will store here energy old and now we will not store total energy, but we will only store the
contribution.
This is why I programmed this here in these two individual functions, so we can now say the old energy
would be energy exchange contribution.
And to be honest, or maybe this is a bit difficult now, but you see, we have here.
Where is it?
Sorry.
Here it is, the sum over Paris.
So, for example, one moment interacts with its right neighbor, but then in the sum, there is also
determined occluded where the right neighbor interacts with the left neighbor again.
So basically, all of these terms occur twice.
So this is why when we change one particular moment, it will not just be the four terms with the neighbors,
but also determine where the neighbors interact with the moment itself.
And this will, of course, just give us a factor of two.
So the old energy we should actually may be called as energy or will change, but let's let's leave
it at that is energy exchange contribution times two.
And here the same thing, of course, two times energy exchange.
And that's it.
OK, so now we compare the energies, this is all fine, and now the only thing that we have to do is
we have to see how this the energy change, so we write energy.
Change is equal to energy.
New minus energy.
Old.
Because here we accept the change and we update the energy.
So we have to write this.
And here in this case, we have to say energy
change is equal to zero.
And then we must return not only the magnetization, but we must also return to change of the energy.
So the thing is we could now even increase the speed of the code even further, because you see in every
step we calculate here the old energy.
And then we calculate the new energy.
And then in the next step, we should already know what the new energy is, but we calculated once again.
So we could save this by adding here another parameter, which is basically the current energy that
is given here.
But I think this would now be maybe a bit too much and a bit too much optimization.
This would increase our speed of the code by a factor of two, which is, of course, nice, and we
could do this later on to improve the code, but it's not really necessary here.
What was really necessary or what was really, really useful, was using these contributions only because
this really, really increases the speed of our code, because now the energy calculation will just
contain for four terms here.
And then when we calculate the whole thing, it would contain so, so many terms, it would contain
four times the number of moments in our sample.
So this would make our code especially slow if we would consider very, very large samples.
So I think this change was really worth it for the other change is nice, but not really necessary.
OK, so let's see if it worked because it was quite a lot of code here.
I think it wasn't really that difficult because it's just what written what's written down here, but
still could happen that I made some error.
So let's see.
We just right step exchange magnetization and it gives him that role, of course.
So where's the error?
Oh, yeah, of course here.
So you see, the error messages are pretty good in Python.
So it says the function energy exchange contribution that we call here misses two required positional
arguments, which are called X and Y.
And of course, this is because I have changed it.
First, I wanted to calculate only the total energy, but now I only want to calculate the contribution.
So we need the other two arguments here.
So we just write X come away and here as well.
So let's try again and we have another error.
Energy exchange takes one positional argument, but three were given, I think, yeah, I missed here.
The update for the contribution?
OK.
And this time it worked.
Nice.
OK, so we have no more output of stuff exchange Mac, which are these two values, so we could now
write zero, which would be the updated magnetization or one which would be the change of the of the
energy.
So you see, in this case, the change is zero.
This is probably because we generated a change that increased the energy, so we declined it.
So here it would give us zero.
And if we repeat this, OK, yeah, you see, now the energy decreased by zero point six five.
Let's do it again.
Zero declined, except that negative energy, except that negative energy, except the negative energy
and so on.
So you see the energy change either zero.
This is when it's declined or it's negative where it's accepted, but it will never be positive.
OK, so now this was the most difficult part.
We have implemented the metropolis step.
Now we can run the Monte-Carlo, which is really not, not much left to do.
We will just loop over the metropolis up and then see how will this configuration change and how it
will turn into a fairer mechanism.