<jupyter_start><jupyter_text>Dynamical Xray Scattering  Setup<jupyter_code>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<jupyter_output><empty_output><jupyter_text>Atom creationInitialize all required atoms using the `Atom` class.<jupyter_code>O = ud.Atom('O')
Ti = ud.Atom('Ti')
Sr = ud.Atom('Sr')
Ru = ud.Atom('Ru')
Pb = ud.Atom('Pb')
Zr = ud.Atom('Zr')<jupyter_output><empty_output><jupyter_text>Unit cell creationCreate all required unit cells using the `UnitCell` class and add `Atom` objects to them.<jupyter_code># c-axis
c_STO_sub = 3.905*u.angstrom
c_SRO = 3.94897*u.angstrom
# sound velocity
sv_SRO = 6.312*u.nm/u.ps
sv_STO = 7.800*u.nm/u.ps

# property dict for SrRuO3
propSRO = {}
propSRO['a_axis'] = c_STO_sub # aAxis
propSRO['b_axis'] = c_STO_sub # bAxis
propSRO['deb_Wal_Fac'] = 0 # Debye-Waller factor
propSRO['sound_vel'] = sv_SRO # sound velocity
propSRO['opt_pen_depth'] = 43.8*u.nm # optical penetration depth
propSRO['therm_cond'] = 5.72*u.W/(u.m *u.K) # heat conductivity
propSRO['lin_therm_exp'] = 1.03e-5 # linear thermal expansion
propSRO['heat_capacity'] = 'lambda T: 455.2 + 0.112*T - 2.1935e6/T**2' # heat capacity [J/kg K]

# create unit cell object
SRO = ud.UnitCell('SRO', 'SRO', c_SRO, **propSRO)
# add atoms to unit cell at relative z-positions
SRO.add_atom(O, 0)
SRO.add_atom(Sr, 0)
SRO.add_atom(O, 0.5)
SRO.add_atom(O, 0.5)
SRO.add_atom(Ru, 0.5)

# property dict for SrTiO3 substrate
propSTOsub = {}
propSTOsub['a_axis'] = c_STO_sub # aAxis
propSTOsub['b_axis'] = c_STO_sub # bAxis
propSTOsub['deb_Wal_Fac'] = 0 # Debye-Waller factor
propSTOsub['sound_vel'] = sv_STO # sound velocity
propSTOsub['opt_pen_depth'] = np.inf*u.nm # optical penetration depth
propSTOsub['therm_cond'] = 12*u.W/(u.m *u.K) # heat conductivity
propSTOsub['lin_therm_exp'] = 1e-5 # linear thermal expansion
propSTOsub['heat_capacity'] = 'lambda T: 733.73 + 0.0248*T - 6.531e6/T**2' # heat capacity [J/kg K]

# create unit cell object
STO_sub = ud.UnitCell('STOsub', 'STOsub', c_STO_sub, **propSTOsub)
# add atoms to unit cell at relative z-positions
STO_sub.add_atom(O, 0)
STO_sub.add_atom(Sr, 0)
STO_sub.add_atom(O, 0.5)
STO_sub.add_atom(O, 0.5)
STO_sub.add_atom(Ti, 0.5)<jupyter_output><empty_output><jupyter_text>Structure creationCreate an actual sample using the `Structure` class and add `UnitCell` objects to it.<jupyter_code>S = ud.Structure('Single Layer')
S.add_sub_structure(SRO, 100) # add 100 layers of SRO to sample
S.add_sub_structure(STO_sub, 1000) # add 1000 layers of STO substrate

substrate = ud.Structure('STO substrate')
substrate.add_sub_structure(STO_sub, 1000000)

S.add_substrate(substrate)

distances, _, _ = S.get_distances_of_unit_cells() # distance vecotor of all unit cells<jupyter_output><empty_output><jupyter_text>Strain map creationSince the `Heat` and `Phonon` simulations are not implemented, yet, the `strain_map` is created by a simple script, which mimics a strain wave traveling into the sample.<jupyter_code>delays = np.r_[-10:50:0.5]*u.ps #  define the delays of the simulations
strain_map = np.zeros([len(delays), S.get_number_of_unit_cells()]) #  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_unit_cells()

# plot the artifical strain_map
plt.figure()
plt.contourf(distances, delays, strain_map)
plt.title('Strain Map')
plt.colorbar()
plt.show()<jupyter_output><empty_output><jupyter_text>Initialize dynamical Xray simulationCreate a dynamical Xray simulation using the `XrayDyn` class and add a `Structure` object as sample.Also set the photon energy and $q_z$ range for the actual simulations.<jupyter_code>force_recalc = True #  always recalculate results and do not consider cached results
dyn = ud.XrayDyn(S, force_recalc)
dyn.disp_messages = True #  enable displaying messages from within the simulations
dyn.save_data = False #  do not save results for caching<jupyter_output><empty_output><jupyter_text>Homogeneous Xray simulationFor the case of homogeneously strained samples, the dynamical Xray scattering simulations can be greatly simplyfied, which saves a lot of computational time.  $q_z$-scan<jupyter_code>dyn.energy = np.r_[5000, 8047]*u.eV #  set two photon energies
dyn.qz = np.r_[3:3.5:0.001]/u.angstrom #  qz range

R_hom, A = dyn.homogeneous_reflectivity() #  this is the actual calculation

plt.figure()
plt.semilogy(dyn.qz[0, :], R_hom[0, :], label='{}'.format(dyn.energy[0]), alpha=0.5)
plt.semilogy(dyn.qz[1, :], R_hom[1, :], label='{}'.format(dyn.energy[1]), alpha=0.5)
plt.ylabel('Reflectivity')
plt.legend()
plt.show()<jupyter_output><empty_output><jupyter_text>Post-ProcessingSimple convolution of the results with an arbitrary function handle.<jupyter_code>FWHM = 0.01/1e-10 # Angstrom
sigma = FWHM /2.3548
        
handle = lambda x: np.exp(-((x)/sigma)**2/2)
y_conv = dyn.conv_with_function(R_hom[0,:], dyn._qz[0,:], handle)

plt.figure()
plt.semilogy(dyn.qz[0,:], R_hom[0,:], label='{}'.format(dyn.energy[0]))
plt.semilogy(dyn.qz[0,:], y_conv, label='{} convoluted'.format(dyn.energy[0]))
plt.ylabel('Reflectivity')
plt.legend()
plt.show()<jupyter_output><empty_output><jupyter_text>Energy-scan<jupyter_code>dyn.energy = np.r_[2000:10000]*u.eV #  set two photon energies
dyn.qz = np.r_[1]/u.angstrom # qz range

R_hom, A = dyn.homogeneous_reflectivity() #  this is the actual calculation

plt.figure()
plt.plot(dyn.energy, R_hom[:, 0])
plt.ylabel('Reflectivity')
plt.show()<jupyter_output><empty_output><jupyter_text>Sequential dynamical Xray simulationDo a time-resolved xray scatting simulation for the above defined `strain_map` without parallelization.<jupyter_code>%%time
dyn.energy = np.r_[5000, 8047]*u.eV #  set two photon energies
dyn.qz = np.r_[3:3.5:0.001]/u.angstrom #  qz range

R_seq = dyn.inhomogeneous_reflectivity(strain_map, strain_vectors, calc_type='sequential')<jupyter_output><empty_output><jupyter_text>Sequential Results<jupyter_code>for i, energy in enumerate(dyn.energy):
    plt.figure()
    plt.contourf(dyn.qz[i,:], delays, np.log10(R_seq[:, i, :]), levels=100)
    plt.title('{:0.1f} eV'.format(energy.magnitude))
    plt.show()<jupyter_output><empty_output><jupyter_text>Parallel dynamical Xray scatteringYou 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](https://docs.dask.org/en/latest/) for more details on parallel computing in Python.<jupyter_code>try:
    from dask.distributed import Client
    client = Client()
    client

    R_par = dyn.inhomogeneous_reflectivity(strain_map, strain_vectors, calc_type='parallel', dask_client=client)

    for i, energy in enumerate(dyn.energy):
        plt.figure()
        plt.contourf(dyn.qz[i,:], delays, np.log10(R_par[:, i, :]), levels=100)
        plt.title('{:0.1f} eV'.format(energy.magnitude))
        plt.show()
except:
    pass<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13249211356466878, 'fraction_numerical': 0.028391167192429023, 'mean_word_length': 5.448305084745763, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 52, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '94707', 'license': 'MIT', 'n_tokens_mistral': 3011, 'n_tokens_neox': 2802, 'n_words': 668, 'path': 'docs/source/examples/dynamical_xray.ipynb', 'repo_name': 'AleksUDKM/udkm1Dsim-1', 'size': '7608'}