# Superferromagnetism in pinwheel ASI#

Here we demonstrate how we used flatspin to replicate the reversal process of pinwheel ASI, as presented by .

“Superferromagnetism and Domain-Wall Topologies in Artificial ‘Pinwheel’ Spin Ice.” ACS Nano 13, no. 2 (January 15, 2019): 2213–22.

A key finding is that when pinwheel ASI is subject to an external field, the angle of the field controls the nature of the reversal process:

1. When the angle is small (equally aligned to both sublattices), reversal happens in a single avalanche.

2. When the angle is large (more aligned to one sublattice), reversal happens in a two-step process where one sublattice switches completely before the other.

Previous attempts at capturing this behavior in a dipole model have proven unfruitful.

The flatspin results are discussed in more detail in our paper .

## Small angles: 0° and -6°#

Fig. 1 and Fig. 2 show the hysteresis loop and snapshots of pinwheel ASI when the angle of the exterernal field is small ($$\theta=0^\circ$$ and $$\theta=-6^\circ$$).

Key features:

• Reversal starts at small number of nucleation points, typically close to the edge

• Reversal progresses by domain growth through domain wall movement perpendicular to the direction of the field.

• Reversal is somewhat more ordered for -6° as opposed to 0°.

## Large angles: 30°#

Fig. 3 shows the hysteresis loop and snapshots of pinwheel ASI when the angle of the exterernal field $$\theta$$ is large.

Key features:

• Reversal process quite different because field now aligned with easy axis of one sublattice

• Ratchetcing behavior yielding a stepped hysteresis loop

• Magnetization constrained to move along 45 degree lines

• Diagonal stripe patterns

## Size and geometry#

Fig. 4 shows a TEM image of the ASI system, where we can deduce the size, shape and lattice spacing:

In addition, there are some more details from the text :

Here, we investigate the behavior of a diamond- edge permalloy (Ni 80 Fe 20 ) pinwheel array of two interleaved collinear 25 × 25 sublattices as shown in the in-focus TEM image in the upper half of Figure 1.

Each individual nanomagnetic island is 10 nm thick, 470 nm long, and 170 nm wide, with a center-to- center separation between nearest-neighbor islands of 420 nm, as shown the top right inset to Figure 1.

Note that their geometry differs from the default pinwheel geometry in flatspin:

1. The angles of the first row is -45° (counter-clockwise), as opposed to 45° (clockwise).

2. They use “asymmetric pinwheel edges”

## flatspin parameters#

We determine simulation parameters based on details from the original paper, mumax simulations for the astroid parameters, as well as some guesswork.

### Geometry#

From Fig. 4 and the text:

• Size: 25x25

• Edges: asymmetric

• Spin angle: -45° (counter-clockwise)

• Lattice spacing: ~594 nm

• From Fig. 4, NN distance is 420 nm. That gives a corresponding flatspin lattice spacing of 2 * 420 * cos(45) ~= 594 nm.

### External field#

• Field angle: -6°, 0° and 30°

• From Fig. 4, their zero angle is straight up, whereas in flatspin zero is towards the right.

• Correspoinding flatspin angles are hence 96°, 90° and 60°, respectively.

• In the following, we refer to flatspin angles using $$\phi$$ (phi), i.e., $$\phi=90-\theta$$

• Field strength: approx +/- 300 Oe = +/- 30 mT (from Fig. 3)

### Switching parameters#

Parameters for switching were estimated from mumax simulations of a single 470x170x10 nm island, subject to an external field at different angles.

• Coercive field $$h_k$$ = 0.098

• $$b$$ = 0.28

• $$c$$ = 1.0

• $$\beta$$ = 4.8

• $$\gamma$$ = 3.0

We now calculate all the flatspin parameters, and instantiate the model.

from flatspin.model import *
from flatspin.data import *
from flatspin.plotting import plot_vectors, montage_fig
from flatspin.vertices import find_vertices, vertex_pos, vertex_mag

size = (25, 25)
edge = "asymmetric"
spin_angle = -45

# Calculate alpha
Msat = 860e3
nw = 470e-9 # width
nh = 170e-9 # height
nt = 10e-9 # thickness
a = 594e-9 # lattice spacing

M = Msat*nw*nh*nt
mu0 = 1.2566370614e-6
alpha = mu0*M/(4*np.pi*a**3)
alpha = np.round(alpha, 5)

# From hysteresis-470x170x10-roundrect100-sweep-phi-li
hc = 0.098
sw_b = 0.28
sw_beta = 4.8
sw_gamma = 3.0

# Guess disorder
disorder = 0.05

params = dict(
size=size, edge=edge, spin_angle=spin_angle, lattice_spacing=1,
hc=hc, alpha=alpha, disorder=disorder,
switching='sw', sw_b=sw_b, sw_beta=sw_beta, sw_gamma=sw_gamma,
random_seed=random_seed, use_opencl=1,
)


### Visual sanity check#

Let’s quickly verify that the resulting flatspin geometry matches the paper (Fig. 4).

model = PinwheelSpinIceDiamond(**params)
model.plot()
plt.axis('off');


### Pinwheel units (vertices)#

In the paper they consider the magnetization of the “pinwheel units”, similar to vertices from other geometries.

Vertices in pinwheel are a bit different from square. Let’s compare them.

plt.subplot(121)
plt.axis('off')
prms = dict(params)
del prms['spin_angle']
prms.update(size=(4,4))
sq = SquareSpinIceClosed(**prms)
sq.randomize()
sq.plot()
sq.plot_vertices()

plt.subplot(122)
plt.axis('off')
prms = dict(params)
prms.update(size=(4,4))
pw = PinwheelSpinIceDiamond(**prms)
pw.randomize()
pw.plot()
pw.plot_vertices();


## Visuals#

Here we attempt to replicate the visualization of the pinwheel units, as detailed in Figure S9 (d) from :

# Color map for the magnetization arrows
clist = list('ckkbbkkggkkrrkkc')
clist = ['#00da00' if c == 'g' else c for c in clist]
clist = ['#0800da' if c == 'b' else c for c in clist]
clist = ['#ed0912' if c == 'r' else c for c in clist]
clist = ['#00ccff' if c == 'c' else c for c in clist]

cmap = matplotlib.colors.ListedColormap(clist)
cmap(np.arange(0,1.01,0.125))[:,:3]
plt.figure(figsize=(4, .5))
plt.gca().get_yaxis().set_visible(False)
plt.grid(False)
plt.xticks(np.arange(0,360,45));

# Try the color map
model.randomize()
plt.subplot(121)
plt.axis('off')
model.plot()

plt.subplot(122)
plt.axis('off')

# Plot vertex magnetization, with added markers for Type I and IV vertices (zero net magnetization)
def plot_vertices(model, markersize=80, ax=None, **kwargs):
# Find type I and IV vertices
vertices = model.vertices()
vertex_types = np.array([model.vertex_type(v) for v in vertices])
type1, = np.nonzero(vertex_types == 1)
type4, = np.nonzero(vertex_types == 4)
spin4 = np.array([model.spin[vertices[v]] for v in type4])
type4a = type4[[s[0] == 1 for s in spin4]]
type4b = type4[[s[0] == -1 for s in spin4]]

if ax is None:
ax = plt.gca()

# Plot vertex magnetization
a1 = model.plot_vertex_mag(
ax=ax, **kwargs)

# Add markers for Type I and IV vertices
XY = vertex_pos(model.pos, vertices)
a2 = ax.scatter(XY[type1, 0], XY[type1, 1],
c='black', marker='x', s=markersize, lw=0.05*markersize)
a3 = ax.scatter(XY[type4a, 0], XY[type4a, 1],
c='red', marker='o', s=markersize, edgecolors='none')
a4 = ax.scatter(XY[type4b, 0], XY[type4b, 1],
c='blue', marker='o', s=markersize, edgecolors='none')
return [a1, a2, a3, a4]

# Test plot_vertices (small system)
plot_vertices(pw)

# Full state in background
pw.plot(alpha=0.2)
plt.axis('off');

plot_vertices(model, 10)
plt.axis('off');


## Reversal curves#

We are now ready to simulate the reversal process in flatspin. In the code below, we apply an external field at an angle phi. The amplitude of the field is gradually increased from -H to H, and then decreased from H to -H. For each field value, we record the state of the system when one or more spins flipped. In other words, we only record changes in state.

def run_reversal(model, phi, H=0.03, timesteps=101):
triangle = -sawtooth(np.linspace(0, 2*np.pi, timesteps), 0.5)

H = H * triangle

spin = []
time = []

model.polarize()
for i, h_ext_i in enumerate(h_ext):
model.set_h_ext(h_ext_i)
steps = model.relax()
if i == 0 or steps > 0:
# Store only state when there were spin flips
time.append(i)
spin.append(model.spin.copy())

result = {
'phi': phi,
'H': H,
'time': time,
'spin': spin,
}

return result

# Run reversal curves for phi=60 (corresponds to theta=30 in the paper)
result60 = run_reversal(model, 60)


### Reversal animation#

Animate the state of the system during the different stages of reversal. Note that we only show frames where there have been spin flips.

def animate_reversal(model, phi, H, time, spin):
fig, ax = plt.subplots()
fig.subplots_adjust(left=0, right=1, bottom=0.0, top=.9, wspace=0, hspace=0)

def animate(i):
t = time[i]
model.set_spin(spin[i])
ax.cla()
ax.set_axis_off()
ax.set_title(rf"H={H[t]:g} $\theta={90-phi}\degree$")
plot_vertices(model, markersize=10, ax=ax)

anim = FuncAnimation(
fig, animate, init_func=lambda: None,
frames=len(time), interval=100, blit=False
)
plt.close() # Only show the animation
return HTML(anim.to_jshtml())


### Animation: 30°#

The animation below shows the full reversal for $$\theta=30^\circ$$. Compare with Fig. 3.

animate_reversal(model, **result60)