Skip to content

Commit 58e88ab

Browse files
Feat/add curated examples (#103)
* adding curated examples * add spherical cvector creation * Update curated-examples/vsd-basic-freq-scan.py Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> --------- Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
1 parent 7084aeb commit 58e88ab

16 files changed

+1890
-0
lines changed

cmtj/__init__.pyi

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,15 @@ class CVector:
201201
"""Converts the vector to a list."""
202202
...
203203

204+
@staticmethod
205+
def fromSpherical(theta: float, phi: float, r: float = 1.0) -> CVector:
206+
"""Create a vector from spherical coordinates.
207+
:param theta: polar angle in radians
208+
:param phi: azimuthal angle in radians
209+
:param r: radius of the vector
210+
"""
211+
...
212+
204213
def __add__(self, arg0: CVector) -> CVector: ...
205214
def __eq__(self, arg0: CVector) -> bool: ...
206215
def __getitem__(self, arg0: int) -> float: ...
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
"""
2+
Current-Induced Magnetization Switching (CIMS) Hysteresis Simulation
3+
4+
GOAL:
5+
This simulation studies current-induced magnetization switching in spin-orbit torque (SOT)
6+
devices by analyzing hysteresis loops under varying current densities and Oersted field
7+
contributions. The simulation maps the stable magnetization states as a function of
8+
applied current, revealing switching thresholds and stability regions.
9+
10+
CRITICAL SIMULATION MECHANISMS:
11+
1. Spin-Orbit Torque (SOT): Models both damping-like and field-like torque components
12+
arising from spin-orbit coupling in heavy metal/ferromagnet bilayers
13+
2. Current Sweep Protocol: Applies bidirectional current sweeps with step drivers to
14+
map complete hysteresis loops and identify switching thresholds
15+
3. Oersted Field Effects: Includes current-induced Oersted fields that provide additional
16+
torque contributions and can assist or oppose SOT switching
17+
4. Magnetization Dynamics: Solves extended LLG equation including SOT terms using
18+
adaptive time stepping for accurate switching dynamics
19+
5. Stability Analysis: Monitors final magnetization states after current pulses to
20+
determine stable configurations and switching probability
21+
6. Resistance Readout: Uses GMR (Giant Magnetoresistance) model to convert magnetization
22+
states to resistance values for experimental comparison
23+
7. Multi-parameter Sweep: Varies Oersted field scaling to study the interplay between
24+
SOT and Oersted field contributions
25+
26+
The simulation generates current-resistance hysteresis loops that reveal switching
27+
thresholds, coercive currents, and the influence of Oersted fields on switching
28+
efficiency, providing insights for optimizing SOT-based memory devices.
29+
"""
30+
31+
from collections import defaultdict
32+
from cmtj import *
33+
from cmtj.utils import compute_gmr
34+
import numpy as np
35+
import matplotlib.pyplot as plt
36+
from cmtj.utils import TtoAm
37+
from tqdm import tqdm
38+
39+
try:
40+
import scienceplots
41+
except ImportError:
42+
pass
43+
44+
45+
demagTensor = [CVector(0.0, 0.0, 0.0), CVector(0.0, 0.0, 0.0), CVector(0.0, 0.0, 1)]
46+
"""
47+
Compute the current scan.
48+
The facing area is thickness x width
49+
50+
Below, you can change the torque signs!
51+
Depending on the Hfl sign the Oersted field will assist or oppose the SOT switching.
52+
If sign is changed, or one of the torques is removed, adjust the current density accordingly.
53+
"""
54+
sgnHdl = 1
55+
sgnHfl = -1
56+
57+
Hdl = sgnHdl * 0.000371 * TtoAm
58+
Hfl = sgnHfl * 0.000433 * TtoAm
59+
jden1 = 6e10
60+
HDL = Hdl / jden1
61+
HFL = Hfl / jden1
62+
63+
last_N = 100
64+
dt = 6e-9
65+
tstart = 1e-9
66+
67+
tstep = 5e-13
68+
sim_time = 15e-9
69+
70+
71+
t_hm = 6e-9
72+
t_fm = 1.7e-9
73+
Kdir1 = CVector(0, 0, 1.0)
74+
pdir1 = CVector(0.0, 1.0, 0.0)
75+
Ku1 = 0.3e6
76+
Ms = 1.45
77+
alpha = 0.0064
78+
layer_free = Layer.createSOTLayer(
79+
id="free",
80+
mag=CVector(1, 0, 0),
81+
anis=Kdir1,
82+
Ms=Ms,
83+
thickness=t_fm,
84+
cellSurface=0.0,
85+
demagTensor=demagTensor,
86+
damping=alpha,
87+
dampingLikeTorque=HDL,
88+
fieldLikeTorque=HFL,
89+
)
90+
91+
j = Junction([layer_free])
92+
j.setLayerAnisotropyDriver("free", ScalarDriver.getConstantDriver(Ku1))
93+
j.setLayerReferenceLayer("free", pdir1)
94+
95+
96+
j.clearLog()
97+
j.runSimulation(14e-9, tstep, tstep)
98+
m_components = defaultdict(list)
99+
hysteresis_scales = []
100+
Hoescales = np.linspace(0, 2500, 3)
101+
Hoescales = np.concatenate((-Hoescales, Hoescales[1:]))
102+
103+
Hoescales = np.asarray([-1000, -500, -100, 0, 100, 500, 1000])
104+
Hoescales = [1, 0.5, 1e-1, 1e-2, 0, -1e-1, -1]
105+
Hoescales = [1, 0, -1]
106+
107+
"""
108+
Below uncomment for specific cases depending on which, damping-like or field-like, torque is used.
109+
"""
110+
if abs(HDL) and abs(HFL):
111+
i_max = [0.1e12 for _ in range(len(Hoescales))] # both Hdl and Hfl only
112+
elif not abs(HFL) and not abs(HDL):
113+
i_max = [1.0e12 for _ in range(len(Hoescales))] # Hoe only
114+
elif abs(HDL) and not abs(HFL):
115+
i_max = [3e11, 3e11, 1e12, 3e13, 3e13, 3e13, 3e11] # Hdl only
116+
elif abs(HFL) and not abs(HDL):
117+
i_max = [2.0e11 for _ in range(len(Hoescales))] # Hfl only
118+
else:
119+
raise ValueError("Invalid torque configuration")
120+
121+
jscans = []
122+
for i, Hoescale in tqdm(enumerate(Hoescales), total=len(Hoescales)):
123+
v = CVector(0.001, 0.99, 0)
124+
v.normalize()
125+
j.setLayerMagnetisation("free", v)
126+
jscan = np.linspace(-i_max[i], i_max[i], 130)
127+
jscan = np.concatenate([jscan, jscan[::-1][1:]])
128+
129+
jscans.append(jscan)
130+
hysteresis = []
131+
for current in jscan:
132+
j.clearLog()
133+
j.setLayerCurrentDriver("all", stepDriver(0, current, tstart, tstart + dt))
134+
j.setLayerOerstedFieldDriver(
135+
"all",
136+
AxialDriver(
137+
constantDriver(0),
138+
stepDriver(0, Hoescale * current * t_hm / 2, tstart, tstart + dt),
139+
constantDriver(0),
140+
),
141+
)
142+
j.runSimulation(sim_time, tstep, tstep)
143+
log = j.getLog()
144+
m = np.asarray(
145+
[
146+
[log[f"{str_}_mx"], log[f"{str_}_my"], log[f"{str_}_mz"]]
147+
for str_ in ("free",)
148+
]
149+
)
150+
151+
Rstable = compute_gmr(
152+
Rp=100,
153+
Rap=200,
154+
m1=m.squeeze()[:, -last_N:],
155+
m2=np.asarray([[0, 1, 0] for _ in range(last_N)]).transpose(),
156+
).mean()
157+
str_ = "free"
158+
m_x_stable = np.mean(log[f"{str_}_mx"][-last_N:])
159+
m_y_stable = np.mean(log[f"{str_}_my"][-last_N:])
160+
m_z_stable = np.mean(log[f"{str_}_mz"][-last_N:])
161+
m_components["x"].append(m_x_stable)
162+
m_components["y"].append(m_y_stable)
163+
m_components["z"].append(m_z_stable)
164+
hysteresis.append(Rstable)
165+
166+
hysteresis = np.asarray(hysteresis)
167+
168+
hysteresis_scales.append(hysteresis)
169+
170+
171+
with plt.style.context(["nature"]):
172+
fig, ax = plt.subplots(1, 1, dpi=250)
173+
# Set white background
174+
fig.patch.set_facecolor("white")
175+
ax.set_facecolor("white")
176+
# get a color scale
177+
colors = plt.cm.viridis(np.linspace(0, 1, len(hysteresis_scales)))
178+
for i, hysteresis in enumerate(hysteresis_scales):
179+
ax.plot(
180+
jscans[i] * 1e-12,
181+
hysteresis,
182+
label=f"Hoe = {Hoescales[i]}",
183+
color=colors[i],
184+
)
185+
ax.set_xlabel(r"$\mathrm{j}$ ($\mathrm{TA/m^2}$)")
186+
ax.set_ylabel(r"$\mathrm{R}_\mathrm{stable}$ ($\Omega$)")
187+
cbar = plt.colorbar(
188+
plt.cm.ScalarMappable(
189+
norm=plt.Normalize(min(Hoescales), max(Hoescales)), cmap=plt.cm.viridis
190+
),
191+
ax=ax,
192+
label="Hoe",
193+
)
194+
cbar.set_ticks(Hoescales)
195+
ax.set_title(
196+
rf"$H_\mathrm{{ext}} = 0, \alpha = {alpha}, \mu_0 M_\mathrm{{s}} = {Ms} \, \mathrm{{T}}$"
197+
"\n"
198+
rf"$H_\mathrm{{dl}} = {Hdl:.2f} \, \mathrm{{A/m}}, H_\mathrm{{fl}} = {Hfl:.2f} \, \mathrm{{A/m}}$"
199+
"\n"
200+
rf"$t_\mathrm{{fm}} = {t_fm*1e9:.0f}\, \mathrm{{nm}}, j_\mathrm{{den}} = {jden1/1e12:.2f} \, \mathrm{{TA/m^2}}$"
201+
)
202+
fig.savefig(
203+
"./curated-examples/figures/cims-hysteresis.png",
204+
dpi=350,
205+
bbox_inches="tight",
206+
)

0 commit comments

Comments
 (0)