Transversal hysteresis of rectangular waveguide#

In this notebook, we calculate a hysteresis loop with the static field applied along the transversal/width (here: \(x\)) direction of a rectangular waveguide.

First, we create the sample and set the material parameters to permalloy.

[1]:
import tetrax as tx
import numpy as np

sample = tx.Sample(
    tx.geometries.waveguide.rectangular(
        width=500,
        thickness=20,
        cell_size_width=5,
        cell_size_thickness=5
    ),
    name="hysteresis_rect_WG_500nmx20nm"
)


sample.material = tx.materials.permalloy

Equilibrium in a field loop#

First, we construct a field range from -300 to 300 mT in both directions. For each value of the external field, we relax the system to its equilibrium and obtain the average magnetization in the cross-section of the waveguide using the average() method of the sample. Since energy minimization using the relax() function is not the most reliable and tends to fail some points, we use dynamic relaxation using relax_dynamic() in these situations to minimize the total torque in the system instead. Note that the following cell can take a while depending on the number of field steps and the size of the used mesh.

[2]:
static_field_range = np.concatenate((np.linspace(-.3, .3 , 70), np.linspace(.3, -.3 , 70))) # in Tesla

average_magnetization = []

sample.mag = tx.vectorfields.homogeneous(sample.xyz, 60.0, 0.0)


for i, B in enumerate(static_field_range):

    # We reinitialize the sample magnetization at an oblique angle at each field step.

    sample.external_field = (B, 0, 0.005)

    # In general, we use energy minimization to calculate the equilibrium state.
    relaxation = tx.experiments.relax(
        sample,
        verbose=False,                  # surpress verbose console output
        set_initial_on_failure=False,    # store last step even on failure
        tolerance=1e-12,
    )

    # Should energy minimization fail to achieve the desired accuracy, we
    # Continue with dynamic relaxation (based on the overdamped LLG).
    if not relaxation.was_success:
        print("Relaxing with LLG ...  ", end="\r")
        tx.experiments.relax_dynamic(
            sample,
            verbose=False,
            tolerance=1e-10
        )

    # storing the average magnetization in a list
    average_magnetization.append(sample.average(sample.mag))

    print(f"B = {int(B*1e3)} mT ({(i+1)/len(static_field_range)*100:.1f}%) done.", end="\r")
B = -300 mT (100.0%) done. (s), dm/dt = 18471.97532071007 [Hz], <mag.x> = -1.00, <mag.y> = 0.00, <mag.z> = 0.033

Plotting the results#

We can plot the obtained average magnetization as a function of the applied field using plotly.

[3]:
from plotly import graph_objects as go

fig = go.Figure()

fig.add_trace(
            go.Scatter(
                x=static_field_range*1e3,
                y=np.asarray(average_magnetization)[:, 0],
                mode="lines",
                line = dict(color="#86337A"),
                name = "<i>m</i><sub>x</sub>",
            )
)

fig.add_trace(
            go.Scatter(
                x=static_field_range*1e3,
                y=np.asarray(average_magnetization)[:, 1],
                mode="lines",
                line = dict(color="#D16F6B"),
                name = "<i>m</i><sub>y</sub>",
            )
)

fig.add_trace(
            go.Scatter(
                x=static_field_range*1e3,
                y=np.asarray(average_magnetization)[:, 2],
                mode="lines",
                line = dict(color="#EAB44F"),
                name = "<i>m</i><sub>z</sub>",
            )
)

fig.update_xaxes(title_text="External field <i>B</i><sub>x</sub> (mT)", exponentformat="power")
fig.update_yaxes(title_text="Normalized magnetization", exponentformat="power")



fig.update_layout(
        template="simple_white",
        height=600,
        width=600,
        hoverlabel={"bordercolor": "rgba(255,255,255,1)"},
    )

fig.show(renderer="notebook") # Remove the renderer argument when running on your computer.

See also#