In [ ]:
import udkm1Dsim as ud
u = ud.u # import the pint unit registry from udkm1Dsim
import scipy.constants as constants
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
u.setup_matplotlib() # use matplotlib with pint units
In [ ]:
Fe = ud.Atom('Fe')
Cr = ud.Atom('Cr')
Si = ud.Atom('Si')
In [ ]:
# c-axis
c_Fe = 2.86*u.angstrom
c_Cr = 2.91*u.angstrom
c_Si = 5*u.angstrom
# we only care basic properties for now
propFe = {}
propFe['a_axis'] = c_Fe # aAxis
propFe['b_axis'] = c_Fe # bAxis
Fe_uc = ud.UnitCell('Fe', 'Fe', c_Fe, **propFe)
Fe_uc.add_atom(Fe, 0)
Fe_uc.add_atom(Fe, 0.5)
propCr = {}
propCr['a_axis'] = c_Cr # aAxis
propCr['b_axis'] = c_Cr # bAxis
Cr_uc = ud.UnitCell('Cr', 'Cr', c_Cr, **propCr)
Cr_uc.add_atom(Cr, 0)
Cr_uc.add_atom(Cr, 0.5)
propSi = {}
propSi['a_axis'] = c_Si # aAxis
propSi['b_axis'] = c_Si # bAxis
Si_uc = ud.UnitCell('Si', 'Si', c_Si, **propSi)
Si_uc.add_atom(Si, 0)
In [ ]:
N_Fe = 5
N_Cr = 4
S = ud.Structure('Super Lattice')
DL = ud.Structure('Double Layer Fe+Cr')
DL.add_sub_structure(Fe_uc, N_Fe)
DL.add_sub_structure(Cr_uc, N_Cr)
S.add_sub_structure(DL, 20)
# add Si substrate
substrate = ud.Structure('Si substrate')
substrate.add_sub_structure(Si_uc, 1000)
S.add_substrate(substrate)
distances, _, _ = S.get_distances_of_layers() # distance vecotor of all layers
In [ ]:
delays = np.r_[-10:30:1]*u.ps # define the delays of the simulations
strain_map = np.zeros([len(delays), S.get_number_of_layers()]) # allocate size of the strain_map
for i, delay in enumerate(delays):
factor = 10
width = 100
if delay > 0:
end = int(delay.magnitude * factor)
start = end - width
if start < 0: start = 0
if end < 0: end = 0
strain_map[i, start:end] = 0.005
# strain_vectors are a subset of the strain_map and are required to speed up the xray simulations
strain_vectors = [np.array(np.linspace(np.min(strain_map), np.max(strain_map), 100))]*S.get_number_of_unique_layers()
# plot the artifical strain_map
plt.figure()
plt.contourf(distances, delays, strain_map)
plt.title('Strain Map')
plt.colorbar()
plt.show()
In [ ]:
force_recalc = True # always recalculate results and do not consider cached results
mag = ud.XrayDynMag(S, force_recalc)
mag.disp_messages = True # enable displaying messages from within the simulations
mag.save_data = False # do not save results for caching
In [ ]:
mag.energy = np.r_[600, 710]*u.eV # set two photon energies
mag.qz = np.r_[0.01:5:0.01]/u.nm # qz range
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.figure()
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}'.format(mag.energy[0]), alpha=0.5)
plt.semilogy(mag.qz[1, :], R_hom[1, :], label='{}'.format(mag.energy[1]), alpha=0.5)
plt.ylabel('Reflectivity')
plt.legend()
plt.show()
In [ ]:
FWHM = 0.01/1e-10 # Angstrom
sigma = FWHM /2.3548
handle = lambda x: np.exp(-((x)/sigma)**2/2)
y_conv = mag.conv_with_function(R_hom[0,:], mag._qz[0,:], handle)
plt.figure()
plt.semilogy(mag.qz[0,:], R_hom[0,:], label='{}'.format(mag.energy[0]))
plt.semilogy(mag.qz[0,:], y_conv, label='{} convoluted'.format(mag.energy[0]))
plt.ylabel('Reflectivity')
plt.legend()
plt.show()
In [ ]:
mag.energy = np.r_[680:750:0.01]*u.eV # set the energy range
mag.qz = np.r_[2.5]/u.nm # qz range
R_hom= mag.homogeneous_reflectivity() # this is the actual calculation
plt.figure()
plt.plot(mag.energy, R_hom[:, 0])
plt.ylabel('Reflectivity')
plt.show()
In [ ]:
%%time
mag.energy = np.r_[600, 710]*u.eV # set two photon energies
mag.qz = np.r_[0.1:5:0.1]/u.nm # qz range
R_seq = mag.inhomogeneous_reflectivity(strain_map, strain_vectors)
In [ ]:
for i, energy in enumerate(mag.energy):
plt.figure()
plt.contourf(mag.qz[i,:], delays, np.log10(R_seq[:, i, :]), levels=100)
plt.title('{:0.1f} eV'.format(energy.magnitude))
plt.show()
Parallelization needs still to be implemented, but will work similarly as with XrayDyn.
You need to install the udkm1Dsim
with the parallel
option which essentially add the Dask package to the requirements:
> pip install udkm1Dsim[parallel]
You can also install/add Dask manually, e.g. via pip:
> pip install dask
Please refer to the Dask documentation for more details on parallel computing in Python.
In [ ]:
mag.energy = np.r_[710]*u.eV # set two photon energies
mag.qz = np.r_[0.01:5:0.01]/u.nm # qz range
plt.figure()
mag.set_polarization(3, 3)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: sigma -> sigma'.format(mag.energy[0]), alpha=0.5)
mag.set_polarization(3, 4)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: sigma -> pi'.format(mag.energy[0]), alpha=0.5)
plt.ylabel('Reflectivity')
plt.title('non-magnetic sample: sigma')
plt.legend()
plt.show()
In [ ]:
mag.energy = np.r_[710]*u.eV # set two photon energies
mag.qz = np.r_[0.01:5:0.01]/u.nm # qz range
plt.figure()
mag.set_polarization(4, 4)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: pi -> pi'.format(mag.energy[0]), alpha=0.5)
mag.set_polarization(4, 3)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: pi -> sigma'.format(mag.energy[0]), alpha=0.5)
plt.ylabel('Reflectivity')
plt.title('non-magnetic sample: pi')
plt.legend()
plt.show()
In [ ]:
# Fe atom with magnetization in-plane to the left
Fe_left = ud.Atom('Fe', mag_amplitude=1, mag_phi=90*u.deg, mag_gamma=90*u.deg, id='Fe left')
# Fe atom with magnetization in-plane to the right
Fe_right = ud.Atom('Fe', mag_amplitude=1, mag_phi=90*u.deg, mag_gamma=270*u.deg, id='Fe right')
# Fe unit cell with left in-plane magnetization
Fe_uc_left = ud.UnitCell('Fe_left', 'Fe', c_Fe, **propFe)
Fe_uc_left.add_atom(Fe_left, 0)
Fe_uc_left.add_atom(Fe_left, 0.5)
# Fe unit cell with right in-plane magnetization
Fe_uc_right = ud.UnitCell('Fe_right', 'Fe', c_Fe, **propFe)
Fe_uc_right.add_atom(Fe_right, 0)
Fe_uc_right.add_atom(Fe_right, 0.5)
In [ ]:
N_Fe = 5
N_Cr = 4
SFM = ud.Structure('FM Super Lattice')
DLFM = ud.Structure('FM Double Layer Fe+Cr')
DLFM.add_sub_structure(Fe_uc_left, N_Fe)
DLFM.add_sub_structure(Cr_uc, N_Cr)
SFM.add_sub_structure(DLFM, 20)
# add Si substrate
SFM.add_substrate(substrate)
distances, _, _ = SFM.get_distances_of_layers() # distance vecotor of all unit cells
mag.S = SFM # replace the sample in the current simulation
In [ ]:
mag.energy = np.r_[710]*u.eV # set two photon energies
mag.qz = np.r_[0.01:5:0.01]/u.nm # qz range
plt.figure()
mag.set_polarization(3, 3)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: sigma -> sigma'.format(mag.energy[0]), alpha=0.5)
mag.set_polarization(3, 4)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: sigma -> pi'.format(mag.energy[0]), alpha=0.5)
plt.ylabel('Reflectivity')
plt.title('FM sample: sigma')
plt.legend()
plt.show()
In [ ]:
mag.energy = np.r_[710]*u.eV # set two photon energies
mag.qz = np.r_[0.01:5:0.01]/u.nm # qz range
plt.figure()
mag.set_polarization(4, 4)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: pi -> pi'.format(mag.energy[0]), alpha=0.5)
mag.set_polarization(4, 3)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: pi -> sigma'.format(mag.energy[0]), alpha=0.5)
plt.ylabel('Reflectivity')
plt.title('FM sample: pi')
plt.legend()
plt.show()
In [ ]:
mag.energy = np.r_[710]*u.eV # set two photon energies
mag.qz = np.r_[0.01:5:0.01]/u.nm # qz range
plt.figure()
mag.set_polarization(1, 0)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: circ +'.format(mag.energy[0]), alpha=0.5)
mag.set_polarization(2, 0)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: circ -'.format(mag.energy[0]), alpha=0.5)
plt.ylabel('Reflectivity')
plt.title('FM sample: circular')
plt.legend()
plt.show()
Same again with the non-magnetic sample
In [ ]:
mag.S = S # change again to the inital sample
mag.energy = np.r_[710]*u.eV # set two photon energies
mag.qz = np.r_[0.01:5:0.01]/u.nm # qz range
plt.figure()
mag.set_polarization(1, 0)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: circ +'.format(mag.energy[0]), alpha=0.5)
mag.set_polarization(2, 0)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: circ -'.format(mag.energy[0]), alpha=0.5)
plt.ylabel('Reflectivity')
plt.title('FM sample: circular')
plt.legend()
plt.show()
In [ ]:
N_Fe = 5
N_Cr = 4
SAFM = ud.Structure('AFM Super Lattice')
DLAFM = ud.Structure('AFM Double Layer Fe+Cr')
DLAFM.add_sub_structure(Fe_uc_left, N_Fe)
DLAFM.add_sub_structure(Cr_uc, N_Cr)
DLAFM.add_sub_structure(Fe_uc_right, N_Fe)
DLAFM.add_sub_structure(Cr_uc, N_Cr)
SAFM.add_sub_structure(DLAFM, 10)
# add Si substrate
SAFM.add_substrate(substrate)
distances, _, _ = SAFM.get_distances_of_layers() # distance vecotor of all unit cells
mag.S = SAFM # replace the sample in the current simulation
In [ ]:
mag.energy = np.r_[710]*u.eV # set two photon energies
mag.qz = np.r_[0.01:5:0.01]/u.nm # qz range
plt.figure()
mag.set_polarization(3, 0)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: sigma -> unpolarized'.format(mag.energy[0]), alpha=0.5)
mag.set_polarization(3, 3)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: sigma -> sigma'.format(mag.energy[0]), alpha=0.5)
mag.set_polarization(3, 4)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: sigma -> pi'.format(mag.energy[0]), alpha=0.5)
plt.ylabel('Reflectivity')
plt.title('AFM sample: sigma')
plt.legend()
plt.show()
In [ ]:
mag.energy = np.r_[710]*u.eV # set two photon energies
mag.qz = np.r_[0.01:5:0.01]/u.nm # qz range
plt.figure()
mag.set_polarization(4, 0)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: pi -> unpolarized'.format(mag.energy[0]), alpha=0.5)
mag.set_polarization(4, 4)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: pi -> pi'.format(mag.energy[0]), alpha=0.5)
mag.set_polarization(4, 3)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: pi -> sigma'.format(mag.energy[0]), alpha=0.5)
plt.ylabel('Reflectivity')
plt.title('AFM sample: pi')
plt.legend()
plt.show()
In [ ]:
mag.energy = np.r_[710]*u.eV # set two photon energies
mag.qz = np.r_[0.01:5:0.01]/u.nm # qz range
plt.figure()
mag.set_polarization(1, 0)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: circ +'.format(mag.energy[0]), alpha=0.5)
mag.set_polarization(2, 0)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: circ -'.format(mag.energy[0]), alpha=0.5)
plt.ylabel('Reflectivity')
plt.title('AFM sample: circular')
plt.legend()
plt.show()
In [ ]:
mag.energy = np.r_[680:750]*u.eV # set two photon energies
mag.qz = np.r_[0.01:5:0.01]/u.nm # qz range
mag.set_polarization(3, 0)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.figure()
plt.figure(figsize=[12,12])
plt.contourf(mag.qz[0,:], mag.energy, np.log10(R_hom[:, :]), levels=100)
plt.colorbar()
plt.ylabel('Reflectivity')
plt.title('AFM sample: circular')
plt.show()
In [ ]:
N_Fe = 5
N_Cr = 4
amAFM = ud.Structure('amorphous AFM Super Lattice')
amDLAFM = ud.Structure('amourphous AFM Double Layer Fe+Cr')
amFeLeftLay = ud.AmorphousLayer('Fe_left_amorphous', "Fe left amorphous", Fe_uc.c_axis*N_Fe, Fe_uc.density, atom=Fe_left)
amFeRightLay = ud.AmorphousLayer('Fe_right_amorphous', "Fe right amorphous", Fe_uc.c_axis*N_Fe, Fe_uc.density, atom=Fe_right)
amCrLay = ud.AmorphousLayer('Cr_amorphous', "Cr amorphous", Cr_uc.c_axis * N_Cr, Cr_uc.density, atom=Cr)
amDLAFM.add_sub_structure(amFeLeftLay)
amDLAFM.add_sub_structure(amCrLay)
amDLAFM.add_sub_structure(amFeRightLay)
amDLAFM.add_sub_structure(amCrLay)
amAFM.add_sub_structure(amDLAFM, 10)
In [ ]:
# add Si substrate
amAFM.add_substrate(substrate)
distances, _, _ = amAFM.get_distances_of_layers() # distance vecotor of all unit cells
mag.S = amAFM # replace the sample in the current simulation
In [ ]:
mag.energy = np.r_[710]*u.eV # set two photon energies
mag.qz = np.r_[0.01:5:0.01]/u.nm # qz range
plt.figure()
mag.set_polarization(3, 0)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: sigma -> unpolarized'.format(mag.energy[0]), alpha=0.5)
mag.set_polarization(3, 3)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: sigma -> sigma'.format(mag.energy[0]), alpha=0.5)
mag.set_polarization(3, 4)
R_hom = mag.homogeneous_reflectivity() # this is the actual calculation
plt.semilogy(mag.qz[0, :], R_hom[0, :], label='{}: sigma -> pi'.format(mag.energy[0]), alpha=0.5)
plt.ylabel('Reflectivity')
plt.title('AFM sample: sigma')
plt.legend()
plt.show()