---
jupytext:
  formats: ipynb,md:myst
  text_representation:
    extension: .md
    format_name: myst
    format_version: 0.13
    jupytext_version: 1.17.2
kernelspec:
  display_name: Python 3 (ipykernel)
  language: python
  name: python3
---

# Snakes

+++

This example shows how we can simulate the snakes described in {cite}`Penty2025`:

[“Controllable gliders in a nanomagnetic metamaterial.” Nature Communications 16, 2025.](https://doi.org/10.1038/s41467-025-62515-1)

+++

We start by creating a model of a 30x30 pinwheel ASI

```{code-cell} ipython3
from flatspin.model import PinwheelSpinIceDiamond
import numpy as np
params = dict(
    size=(30, 30),
    use_opencl=1,
    spin_angle=-45,
    spin_axis=0,
    alpha=0.0013,
    hc=0.2,
    sw_b=0.38,
    sw_c=1,
    sw_beta=1.3,
    sw_gamma=3.6,
)
model = PinwheelSpinIceDiamond(**params)
# Define drawing style
style = dict(style="stadium", width=.25, scale=1.3)
```

We can make a convenience function which allows us to easily draw snakes at different positions in the ASI

```{code-cell} ipython3
def init_snake(model, length, pos):
    G = model.grid()
    y, x = pos

    grid_inds = [(y, x+i) for i in range(2*length)]
    grid_inds += [(y+1, x+i+1) for i in range(2*length)]
    spin_inds = [G.point_index(gi) for gi in grid_inds]
    spin_inds = np.concatenate(spin_inds)
    model.spin[spin_inds] = 1
```

```{code-cell} ipython3
# polarize then draw some snakes
model.polarize(-1)

init_snake(model, 6, (15, 24)) # Leftwards snake
init_snake(model, 6, (30, 24)) # Rightwards snake
init_snake(model, 6, (45, 24)) # Leftwards snake

model.plot(**style);
```

To get the snake moving we need to use Astroid Clocking.

We can use the flatspin PulseTrain Encoder to create a sequence of global fields to apply

```{code-cell} ipython3
# Set up clock fields and encoder
from flatspin.encoder import PulseTrain

H_AB = 0.0765
H_ab = 0.072

pulses={
    "A": (H_AB,  22),    # (field strength, angle)
    "a": (H_ab, 180+22),
    "B": (H_AB, -22),
    "b": (H_ab, 180-22)
}

encoder = PulseTrain(pulses=pulses)
```

```{code-cell} ipython3
from flatspin.plotting import animate_spins
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from IPython.display import HTML

sequence = "ABab" * 14
h_ext = encoder(list(sequence))
spins = [model.spin.copy()]
for h_ext_i in h_ext:
    model.set_h_ext(h_ext_i)
    model.relax()
    spins.append(model.spin.copy())

labels = ["init"] + list(sequence)
anim = animate_spins(model, spins, labels, highlight_flips=True, fps=5, **style)
plt.close() # Only show the animation

HTML(anim.to_jshtml())
```
