# Quickstart

## Contents

# Quickstart#

This page gives a whirlwind introduction to flatspin. Make sure you have installed flatspin before you continue.

The best way to get familiar with flatspin, is to play with the simulator in an interactive Python environment. This guide is written as a Jupyter notebook, which you can download and run yourself. Just click the download link from the top of this page.

Let’s get started!

## The flatspin model#

The main object in flatspin is the model.
Each model class defines a spin ice *geometry*, which specifies the positions and angles of the spins.
The `SquareSpinIceClosed`

class, for instance, creates a square spin ice geometry (with “closed” edges):

```
from flatspin.model import SquareSpinIceClosed
model = SquareSpinIceClosed()
model.plot();
```

A list of available model classes can be found in the user guide. Custom geometries may be created by extending flatspin.

## Model parameters#

Properties of the model can be changed through *parameters*, which are passed as keyword arguments to the model class. For instance, we may change the `size`

parameter to create a larger spin ice:

```
model = SquareSpinIceClosed(size=(10,5))
print(f"10x5 square ASI has", model.spin_count, "spins")
model.plot();
```

```
10x5 square ASI has 115 spins
```

Note that `size`

is geometry-specific: for `SquareSpinIceClosed`

, the size specifies the number of columns (rows) of horizontal (vertical) magnets.
For `KagomeSpinIce`

, the size denotes the number of hexagonal units:

```
from flatspin.model import KagomeSpinIce
model = KagomeSpinIce(size=(10,5))
print(f"10x5 kagome ASI has", model.spin_count, "spins")
model.plot();
```

```
10x5 kagome ASI has 179 spins
```

Other important parameters include `alpha`

(the coupling strength), `hc`

(the coercive field), `disorder`

(random variations in the coercive fields) and `temperature`

(absolute temperature in Kelvin). For a list of available parameters, see `SpinIce`

.

## Running the model#

The primary method for interacting with the model is the *external field*. We set the external field with `set_h_ext()`

.

```
model = SquareSpinIceClosed()
model.set_h_ext([-0.058, -0.058])
```

Next we run the model by calling `relax()`

, which will flip all spins until equilibrium is reached, i.e., until there are no more flippable spins. `relax()`

returns the number of spins that were flipped.

```
flips = model.relax()
print(flips, "spins flipped")
model.plot();
```

```
23 spins flipped
```

We may also flip only a single spin at a time by calling `step()`

. For each call to `step()`

, the spin with the highest “switching energy” will be flipped, and the method returns `True`

. If there are no flippable spins, `step()`

returns `False`

. Below we use `step()`

to create an animation of the relaxation process.

```
from matplotlib.animation import FuncAnimation
from IPython.display import HTML
# Reset system back to the polarized state
model.polarize()
fig, ax = plt.subplots()
def do_steps():
yield model
while model.step():
yield model
def animate(model):
model.plot(ax=ax, replace=True)
anim = FuncAnimation(fig, animate, frames=do_steps(), interval=200, blit=False)
plt.close() # Only show the animation
HTML(anim.to_jshtml())
```

## Hysteresis loops#

Often we are interested in some average quantity of the ensemble, such as the total magnetization.

A hysteresis loop is a plot of the total magnetization, projected along the direction of the external field. Below we gradually increase the strength `H`

of the external field, applied at some angle `phi`

, and record the total magnetization for each field value `H`

. We also enable GPU acceleration to speed up the simulation with `use_opencl=True`

.

```
model = SquareSpinIceClosed(size=(10,10), use_opencl=True)
# H decreases linearly from 0.1 to -0.1, then back to 0.1
H = np.linspace(0.1, -0.1, 500)
H = np.concatenate([H, -H])
# Angle of the external field
phi = np.deg2rad(45)
h_dir = np.array([np.cos(phi), np.sin(phi)])
M_H = []
for h in H:
model.set_h_ext(h * h_dir)
model.relax()
# Magnetization projected along field direction
m = model.total_magnetization().dot(h_dir)
M_H.append(m)
plt.plot(H, M_H)
plt.xlabel("H [T]")
plt.ylabel(r"M_H [a.u.]");
```

And here is an animation of the hysteresis loop, where only changes to the state are shown:

```
# Reset system back to the polarized state
model.polarize()
fig, ax = plt.subplots()
def do_hysteresis():
yield model
for h in H:
model.set_h_ext(h * h_dir)
if model.relax():
# Only show frames where any spins flipped
yield model
def animate(model):
h = model.h_ext[0].dot(h_dir)
ax.set_title(f'H = {h:g}')
model.plot(ax=ax, replace=True)
anim = FuncAnimation(fig, animate, frames=do_hysteresis(), interval=200, blit=False)
plt.close() # Only show the animation
HTML(anim.to_jshtml())
```