regarding frequency sweep FMR of multilayer structure "MTJ"

136 views
Skip to first unread message

Suman Kumar Maharana

unread,
Oct 15, 2024, 9:20:26 AM10/15/24
to Boris Computational Spintronics
Hi Serban,
                   In tutorial 20, you gave a Python script for simulating frequency sweep FMR of single layer Co/Pt. Can you suggest how to simulate the frequency sweep FMR of MTJ, which consists of multiple layers? 
Thankyou

Serban Lepadatu

unread,
Oct 16, 2024, 1:57:33 AM10/16/24
to Boris Computational Spintronics
Hi,

If you have multiple magnetic layers you can simply save their average magnetization outputs separately. In general they will have different resonance frequencies depending on the geometry and material (e.g. see this publication, where we've used a different method to obtain the noise PSD in an MTJ read-head: https://iopscience.iop.org/article/10.1088/1361-648X/acb2a6/meta).

Kind regards,
Serban

Suman Kumar Maharana

unread,
Oct 17, 2024, 9:08:04 AM10/17/24
to Boris Computational Spintronics
Hi Serban,
                    Thank you for the reply. Can you suggest a script for simulating such a complex structure? I am trying to do it by loading the same simulation file, prepared by doing a hysteresis simulation.  
Thankyou

Serban Lepadatu

unread,
Oct 22, 2024, 4:43:21 AM10/22/24
to Boris Computational Spintronics
Hi,

See below for an example FMR simulation on a perpendicular MTJ stack (AFM/PL/Spacer/RL/Tunnel/FL).
This example extracts the FMR peaks from RL and FL layers.

Regards,
Serban


from NetSocks import NSClient
import matplotlib.pyplot as plt
import numpy as np
import scipy.fftpack
import scipy as sp

ns = NSClient(embedded = False); ns.configure(True)

cuda = 0

############## Magnetic Parameters #############################

damping = 0.1

Ms = 800e3
Ka = 400e3

#Dimensions and cellsizes
L = 10e-9
W = 10e-9
cell_x=5e-9
cell_y=5e-9
cell_z=2e-9
ecell_x = 2.5e-9
ecell_y = 2.5e-9
ecell_z_T = 0.5e-9

RA=0.15*1e-12 #Ohm m2
#NOTE : parallel state RA is RA/2
#       anti-parallel state RA is 3*RA/2

################################################################
############# AFM ##############################################
################################################################

AFM = ns.AntiFerromagnet([-W/2, 0, 0, W/2, L, 6e-9], [cell_x, cell_y, 2*cell_z])
AFM.modules(['demag', 'aniuni', 'exchange', 'Zeeman', 'surfexchange'])
AFM.param.K1_AFM = [100e3, 100e3]
AFM.param.ea1 = [0, 0, 1]
AFM.param.J1 = 1e-3
AFM.setangle(0, 0)

################################################################
############# Pinned Layer #####################################
################################################################

#Add Fe mesh on top of the antiferromagnet
PL = ns.Material('Fe', [-W/2, 0, 6e-9, W/2, L, 10e-9], [cell_x, cell_y, cell_z])
PL.modules(['demag', 'exchange', 'Zeeman', 'aniuni', 'surfexchange'])
PL.param.K1 = Ka
PL.param.ea1 = [0, 0, 1]
PL.param.Ms = Ms
PL.param.J1 = 1e-3
PL.setangle(0, 0)
PL.param.damping = damping

################################################################
############# Reference Layer ##################################
################################################################

RL = ns.Material('Fe', [-W/2, 0, 12e-9, W/2, L, 16e-9], [cell_x, cell_y, cell_z])
RL.modules(['demag', 'exchange', 'Zeeman', 'aniuni', 'surfexchange'])
RL.param.K1 = Ka
RL.param.ea1 = [0, 0, 1]
RL.param.Ms = Ms
RL.param.J1 = -1.5e-3
RL.setangle(180, 0)
RL.param.damping = damping

################################################################
############# Tunnel Barrier ###################################
################################################################

Tunnel = ns.Insulator([-W/2, 0, 16e-9, W/2, L, 17e-9], [ecell_x, ecell_y, ecell_z_T])
Tunnel.modules(['tmr'])
Tunnel.param.RAtmr_p = RA/2        #parallel state RA value
Tunnel.param.RAtmr_ap = 3*RA/2     #anti-parallel state RA value

################################################################
############# Free Layer #######################################
################################################################

FL = ns.Material('Fe', [-W/2, 0, 17e-9, W/2, L, 23e-9], [cell_x, cell_y, cell_z])
FL.modules(['demag', 'exchange', 'Zeeman', 'aniuni', 'surfexchange'])
FL.param.K1 = 0.1*Ka
FL.param.ea1 = [0, 0, 1]
FL.param.Ms = Ms
FL.param.J1 = 1e-4
FL.setangle(0, 0)
FL.param.damping = damping

#####################################################

ns.addmodule('supermesh','sdemag')

ns.cuda(cuda)

#####################################################

def get_fmr_peak(P):
   
    #2D fft
    fourier_data = np.fft.fftshift(np.abs(sp.fftpack.fft(P))**2)
   
    #get value ranges
    freq_len = len(fourier_data)
    freq = sp.fftpack.fftfreq(freq_len, time_step)
   
    #extract result from fourier data in a plottable form
    result = fourier_data[int(freq_len/2):freq_len]
   
    return freq, result

#H0: bias field strength (A/m)
def simulate_fmr_peak(H0):
   
    """Simulate FMR peak for given bias field strength"""
   
    #Bias field (A/m)
    ns.equationconstants('H0', H0)
   
    ns.reset()
    ns.Run()
   
    #Analyse
   
    #get 2D list as position along horizontal, time along vertical
    data = ns.Get_Data_Columns(ns.savedatafile())
    Mx_FL = [row[0]/Ms for row in data]
    Mx_RL = [row[3]/Ms for row in data]
   
    plt.axes(xlabel = 'f (Hz)', ylabel = 'FMR Signal (a.u.)', title = 'Frequency-swept FMR')
    freq, result = get_fmr_peak(Mx_FL)
    plt.plot(freq[0:len(result)], result, '.-', label = 'FL')
    freq, result = get_fmr_peak(Mx_RL)
    plt.plot(freq[0:len(result)], result, '.-', label = 'RL')
    plt.legend()
    plt.show()

########################################    

#FMR peak simulation

H0 = 2.5e5

#relax starting configuration
ns.setode('LLGStatic', 'SDesc')
ns.setfield(H0, 0, 0)
ns.Relax(['mxh', 1e-5])
ns.reset()

#data to save
ns.setsavedata('MTJ_FMR.txt', ['<M>', FL], ['<M>', RL])

#cutoff frequency (Hz)
fc = 25e9
#time step for saving magnetisation (s) : determined by Nyquist criterion from cutoff frequency
time_step = (0.5 / fc)
#total time to simulate; increasing this gives you more frequency points in the transform
total_time = 4000e-12
#Field and excitation field strength
He = 100

#setup sinc pulse using a formula
ns.setstage(['Hequation', 'supermesh'])
ns.editstagevalue(0, 'He * sinc(2*PI*fc*(t-t0)), 0, H0')
ns.editstagestop(0, 'time', total_time)
ns.editdatasave(0, 'time', time_step)

#define the equation constants
#Excitation field (A/m)
ns.equationconstants('He', He)
#f cutoff (Hz)
ns.equationconstants('fc', fc)
#sinc pulse center (s)
ns.equationconstants('t0', total_time / 2)

ns.setode('LLG', 'RK4')
ns.setdt(250e-15)

#Simulate
simulate_fmr_peak(H0)

########################################


Suman Kumar Maharana

unread,
May 6, 2025, 9:33:07 AMMay 6
to Boris Computational Spintronics
Hi Serban,
                  When I run a frequency sweep FMR simulation in BORIS using the code below, I notice that the results vary on repeated simulations for a particular magnetic field. I was expecting consistent results (same resonance frequency for MTJ) across repeated simulations. Could you help me understand why this is happening?  

from NetSocks import NSClient
import matplotlib.pyplot as plt
import numpy as np

import scipy as sp
import os

 

# Initialize NetSocks client
ns = NSClient(embedded=False)
ns.configure(True)

 

cuda = 0

 

############## Magnetic Parameters #############################
Ms = 900e3
damping = 0.02
RA = 0.15 * 1e-12  # Ohm m2

 

################################################################
############# AFM ##############################################
################################################################

 

AFM = ns.AntiFerromagnet([0, 0, -17e-9, 50e-9, 50e-9, 0], [5e-9, 5e-9, 0.520e-9])


AFM.modules(['demag', 'aniuni', 'exchange', 'Zeeman', 'surfexchange'])

AFM.param.K1_AFM = [600e3, 600e3]
AFM.param.ea1 = [1, 0, 0]
AFM.param.J1 = 800e-6
AFM.setangle(90, 0)

 

############# Pinned Layer #####################################
PL = ns.Material('CoFeB', [0, 0, 0, 50e-9, 50e-9, 2.6e-9], [5e-9, 5e-9, 0.520e-9])


PL.modules(['demag', 'exchange', 'Zeeman', 'aniuni', 'surfexchange'])

PL.param.K1 = 1e3


PL.param.ea1 = [0, 0, 1]
PL.param.Ms = Ms

PL.param.grel = 1
PL.param.A = 14e-12
PL.param.J1 = 600e-6
PL.setangle(-90, 0)
PL.param.damping = damping

 

############# Reference Layer ##################################
RL = ns.Material('CoFeB', [0, 0, 3.4e-9, 50e-9, 50e-9, 6e-9], [5e-9, 5e-9, 0.520e-9])


RL.modules(['demag', 'exchange', 'Zeeman', 'aniuni', 'surfexchange'])

RL.param.K1 = 2e3


RL.param.ea1 = [0, 0, 1]
RL.param.Ms = Ms

RL.param.grel = 1
RL.param.A = 14e-12
RL.param.J1 = -450e-6
RL.setangle(-90, 0)
RL.param.damping = damping

 

############# Free Layer #######################################
FL = ns.Material('CoFeB', [0, 0, 6.8e-9, 50e-9, 50e-9, 9.8e-9], [5e-9, 5e-9, 0.520e-9])


FL.modules(['demag', 'exchange', 'Zeeman', 'aniuni', 'surfexchange'])

FL.param.K1 = 2e3


FL.param.ea1 = [0, 0, 1]
FL.param.Ms = Ms

FL.param.grel = 1
FL.param.A = 14e-12
FL.param.J1 = 20e-6
FL.setangle(-90, 0)
FL.param.damping = damping

 

#####################################################
ns.addmodule('supermesh', 'sdemag')
ns.cuda(cuda)
#####################################################

 

def get_fmr_peak(P):

    #2D fft
    fourier_data = np.fft.fftshift(np.abs(sp.fftpack.fft(P))**2)

    #get value ranges
    freq_len = len(fourier_data)
    freq = sp.fftpack.fftfreq(freq_len, time_step)

    #extract result from fourier data in a plottable form
    result = fourier_data[int(freq_len/2):freq_len]

    return freq, result

 

#H0: bias field strength (A/m)
def simulate_fmr_peak(H0):

    """Simulate FMR peak for given bias field strength"""

    #Bias field (A/m)
    ns.equationconstants('H0', H0)

    ns.equationconstants('He', He)
    #f cutoff (Hz)
    ns.equationconstants('fc', fc)
    #sinc pulse center (s)
    ns.equationconstants('t0', total_time / 2)

    ns.reset()
    ns.Run()

    #Analyse

    #get 2D list as position along horizontal, time along vertical
    data = ns.Get_Data_Columns(ns.savedatafile())

    Mx_FL = [row[1]/Ms for row in data]
    Mx_RL = [row[4]/Ms for row in data]
    Mx_PL = [row[7]/Ms for row in data]
    Mx = np.array(Mx_PL) * 0.32098 + np.array(Mx_RL) * 0.32098 + np.array(Mx_FL) * 0.358024



    plt.axes(xlabel = 'f (Hz)', ylabel = 'FMR Signal (a.u.)', title = 'Frequency-swept FMR_H0_{H0}')
    freq, result = get_fmr_peak(Mx)
    plt.plot(freq[0:len(result)], result, '.-', label = 'MTJ')
    xy = []
    xy.append(freq[0:len(result)])
    xy.append(result)

    ns.Save_Data_Columns(f'fmr_temp_H0_{H0}.txt', xy)
    plt.legend()
    plt.show()

########################################    

 

#FMR peak simulation

 

H0 = 71e3

 

#relax starting configuration
ns.setode('LLGStatic', 'SDesc')
ns.setfield(H0, 0, 0)
ns.Relax(['mxh', 1e-5])
ns.reset()
#data to save

ns.setsavedata('MTJ_FMR.txt', ['<M>', FL], ['<M>', RL], ['<M>', PL])

 

#cutoff frequency (Hz)
fc = 20e9


#time step for saving magnetisation (s) : determined by Nyquist criterion from cutoff frequency
time_step = (0.5 / fc)
#total time to simulate; increasing this gives you more frequency points in the transform

total_time = 5000e-12


#Field and excitation field strength
He = 100

#setup sinc pulse using a formula
ns.setstage(['Hequation', 'supermesh'])

ns.editstagevalue(0, 'H0, He * sinc(2*PI*fc*(t-t0)), 0')


ns.editstagestop(0, 'time', total_time)
ns.editdatasave(0, 'time', time_step)

 

#define the equation constants
#Excitation field (A/m)
ns.equationconstants('He', He)
#f cutoff (Hz)
ns.equationconstants('fc', fc)
#sinc pulse center (s)
ns.equationconstants('t0', total_time / 2)

 

ns.setode('LLG', 'RK4')
ns.setdt(250e-15)

 

#Simulate
simulate_fmr_peak(H0)

 

########################################

Serban Lepadatu

unread,
May 7, 2025, 3:59:48 AMMay 7
to Boris Computational Spintronics

Hi,

I ran this twice and got the same plot so not sure how you're getting different results.

One thing I noticed though, you have a very small cellsize along z direction (0.52 nm). You may need to decrease the time-step for such a small cellsize. However, I think it would be good enough to treat the layers as 2D since they are relatively thin.

Regards,
Serban

Suman Kumar Maharana

unread,
May 7, 2025, 9:29:58 AMMay 7
to Boris Computational Spintronics
Hi Serban, 
                     I have also observed that for 500kA/m it shows repetition, but for 600kA/m the data does not look theimage.png same. Also, if  I changed the GPU, it would change. 

Suman Kumar Maharana

unread,
May 9, 2025, 12:09:54 AMMay 9
to Boris Computational Spintronics
Hi Serban,
                   I also noticed that there is so much noise while doing frequency sweep fmr, itimage (1).png should not be there. What can we other possible solutions to get proper FMR spectra?

Serban Lepadatu

unread,
May 9, 2025, 1:35:12 AMMay 9
to Boris Computational Spintronics
Hi,

I suggest this is either because the time-step is too large (see my previous message), or at this larger field switching is generated so you're no longer in an FMR regime.

Kind regards,
Serban

Reply all
Reply to author
Forward
0 new messages