Line scans and magnetization-graded waveguides#
In this example, we will model a magnetization-graded waveguide like in Ref. 1. A graduation of saturation magnetization can induce a channeling of certain modes. Different quantities, such as magnetization and mode profiles are investigated using the line scan feature of TetraX.
Sample definition as a waveguide with graded saturation magnetization#
First we create a rectangular waveguide with 200 nm width and 1 nm thickness. The exchange stiffness and gyromagnetic ratio are set to typical values of permalloy.
[1]:
import tetrax as tx
T = 1 # nm
W = 200 # nm
res_W = 1
sample = tx.Sample(
tx.geometries.waveguide.rectangular(
width = W,
thickness = T,
cell_size_width = res_W
),
name="rect_waveguide_graded"
)
sample.material["gamma"] = 185.66e9
sample.material["Aex"] = 9.9e-12
We set a graded magnetization to mimic an ion irradiation of a permalloy waveguide with the highest fluence in the middle. In order to model a graduation of the saturation magnetization, we use the following windowing function which ensures a smooth variation of Msat in space.
[2]:
import numpy as np
def smooth_window(t0, T, tau, A, t):
"""Windowing function with smooth edges.
See, e.g., https://zenodo.org/doi/10.5281/zenodo.4493251
on page 53 for a sketch of the role of the parameters.
Parameters
----------
t0 : float
Shift in time.
T : float
Total width of the window (from zero to zero).
tau : float
Rise/fall time of the window.
A : float
Amplitude.
t : float
Time.
"""
def R(u):
"""
Auxiliary R function that appears in the windowing function c_inf_window.
"""
return np.piecewise(u,[u<=0, u>0],[0, lambda u : np.exp(-1/u)])
def S(u):
"""
Auxiliary S function that appears in the windowing function c_inf_window.
"""
return R(u)/(R(u)+R(1-u))
u = (t - t0)/tau
y = A*S(u)*S(T/tau-u)
return y
Msat_Py = 800e3
Msat_Pyirrad = 400e3
zeta = 100
rise = 25
sample.material["Msat"] = Msat_Py - smooth_window(-zeta/2,zeta,rise,Msat_Pyirrad,sample.xyz.x)
Using the scan_along_curve() method of the sample we can show the magnetization across the width of the waveguide. Note that material["Msat"] itself is a container object, while the array holding the local values is contained in material["Msat"].value. Here, the curve is defined by providing a start and end point.
[3]:
Msat_along_line, line_coords = sample.scan_along_curve(
sample.material["Msat"].value,
curve = ((-W/2,0,0), (W/2,0,0)),
num_points=int(W/res_W),
return_curve=True
)
Setting return_curve=True also returns the coordinates on the curve as a MeshVector. Using this, we can easily plot the scanned saturation as a function of the \(x\) coordinates stored in line_coords.x.
[4]:
from plotly import graph_objects as go
fig = go.Figure()
fig.add_trace(
go.Scatter(
x=line_coords.x,
y=Msat_along_line*1e-3,
mode="lines"
)
)
fig.update_xaxes(title_text="<i>x</i> (nm)", range=(-W/2,W/2))
fig.update_yaxes(title_text="<i>M</i><sub>s</sub> (kA/m)", range=(0,900))
fig.update_layout(
template="simple_white",
height=300,
width=600,
hoverlabel={"bordercolor": "rgba(255,255,255,1)"},
)
fig.show(renderer="notebook") # remove this line when running on your computer
Equilibrium under applied external field#
Let us now apply a transversal field and calculate the equilibrium state.
[5]:
sample.mag = tx.vectorfields.homogeneous(sample.xyz,90,10)
sample.Bext = (300e-3,0,0) # same as sample.external_field
relaxation = tx.experiments.relax(sample,tolerance=1e-11)
Minimizing energy in using 'L-BFGS-B' (tolerance 1e-11) ...
energy length density: -3.828206970046140e-11 J/m, <mag.x> = 1.00, <mag.y> = 0.02, <mag.z> = 0.00
Success!
It is best to visualize the equilibrium again by taking line scans along the transversal direction. Since the length of the magnetization vector changes in space, we will do a scan of both the unitary direction \(\mathbf{m}\) (mag) and the full magnetization \(\mathbf{M}\) (mag_full). To bring them both to the same unit and order of magnitude, we will divide the full magnetization by the average saturation \(\langle M_\mathrm{s}\rangle\) (material["Msat"].average). We can
perform the line scan along the same curve as by before by simply providing the line_coords from above as the curve argument of the scan_along_curve() method.
[6]:
mag_dir_along_line = sample.scan_along_curve(
sample.mag,
curve = line_coords,
num_points=int(W/res_W),
)
mag_full_along_line = sample.scan_along_curve(
sample.mag_full/sample.material["Msat"].average,
curve = line_coords,
num_points=int(W/res_W),
)
We plot the different componets of the two vectors together. We can loop over the components of the MeshVectors mag_full_along_line and mag_dir_along_line by looping over their component_names and component attritubes.
[7]:
fig2 = go.Figure()
colors = [
"#86337A",
"#D16F6B",
"#EAB44F"
]
# Looping over the components of the full (rescaled) magnetization.
for color, comp_name, component in zip(colors,
mag_full_along_line.component_names,
mag_full_along_line.components
):
fig2.add_trace(
go.Scatter(
x=line_coords.x,
y=component,
mode="lines",
name=comp_name,
legendgroup="0",
line=dict(color=color),
legendgrouptitle_text="scaled mag. <b><i>M</i></b>/<<i>M</i><sub>s</sub>>",
)
)
# Looping over the components of the magnetization direction.
for color, comp_name, component in zip(colors,
mag_dir_along_line.component_names,
mag_dir_along_line.components
):
fig2.add_trace(
go.Scatter(
x=line_coords.x,
y=component,
mode="lines",
line=dict(color=color, width=1, dash='dash'),
name=comp_name,
legendgroup="1",
legendgrouptitle_text="direction <b><i>m</i></b>",
)
)
fig2.update_xaxes(title_text="<i>x</i> (nm)", range=(-W/2,W/2))
fig2.update_layout(
template="simple_white",
height=600,
width=600,
hoverlabel={"bordercolor": "rgba(255,255,255,1)"},
)
fig2.show(renderer="notebook") # remove this line when running on your computer