Update Activity 8

This commit is contained in:
Sylvain Tricot 2025-07-16 17:21:11 +02:00
parent d00c537f30
commit 6996ac97fc
8 changed files with 341 additions and 5 deletions

View File

@ -9,12 +9,85 @@
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1df76138-c957-4da2-bcc8-ec977c209b81",
"cell_type": "markdown",
"id": "394b0c02-f28e-4074-86e5-9dfdf0447adb",
"metadata": {},
"outputs": [],
"source": []
"source": [
"intro"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "5a4036dc-d087-419f-9a44-749a8b313d5c",
"metadata": {},
"source": [
"(aln-paper)=\n",
":::{seealso}\n",
"based on this paper from V. Lebedev *et al.*\n",
"[J. Cryst. Growth. **207(4)** p266-72 (1999)](https://doi.org/10.1016/S0022-0248(99)00375-9)\n",
":::"
]
},
{
"cell_type": "markdown",
"id": "fc1cf08e-77ba-49ea-99a9-8a7bac7c98c7",
"metadata": {},
"source": [
":::{figure-md} AlN-fig1\n",
"<img src=\"fig1.jpg\" alt=\"AlN growth\" width=\"600px\" align=\"center\">\n",
"\n",
"legend\n",
":::"
]
},
{
"cell_type": "markdown",
"id": "fc180c7b-eb23-47c6-8d18-e092bc777843",
"metadata": {},
"source": [
":::{figure-md} AlN-fig2\n",
"<img src=\"fig2.jpg\" alt=\"AlN crystal direction\" width=\"600px\" align=\"center\">\n",
"\n",
"legend\n",
":::"
]
},
{
"cell_type": "markdown",
"id": "86c20245-abca-4587-bccf-90e0fb09f73c",
"metadata": {},
"source": [
":::{figure-md} AlN-fig3\n",
"<img src=\"fig3.jpg\" alt=\"AlN XPD\" width=\"400px\" align=\"center\">\n",
"\n",
"legend\n",
":::"
]
},
{
"cell_type": "markdown",
"id": "8a3a48ef-196f-435a-b342-3a73e62160f8",
"metadata": {},
"source": [
":::{figure-md} AlN-fig4\n",
"<img src=\"fig4.jpg\" alt=\"AlN number of clusters\" width=\"600px\" align=\"center\">\n",
"\n",
"legend\n",
":::"
]
},
{
"cell_type": "markdown",
"id": "abc64fdb-5895-4112-a987-66b3420d78eb",
"metadata": {},
"source": [
":::{figure-md} AlN-fig5\n",
"<img src=\"fig5.jpg\" alt=\"AlN results\" width=\"600px\" align=\"center\">\n",
"\n",
"legend\n",
":::"
]
}
],
"metadata": {

View File

@ -0,0 +1,131 @@
#!/usr/bin/env python
# coding: utf8
from ase.build import bulk
import numpy as np
from msspec.calculator import MSSPEC, XRaySource
from msspec.utils import hemispherical_cluster, get_atom_index
def create_clusters(nplanes=6):
def get_AlN_tags_planes(side, emitter):
AlN = # AlN is a Wurtzite crystal with a=3.11 and c=4.975 angstroms # <= HERE
[atom.set('tag', i) for i, atom in enumerate(AlN)]
if side == 'Al':
AlN.rotate([0,0,1],[0,0,-1])
Al_planes = range(0, nplanes, 2)
N_planes = range(1, nplanes, 2)
else:
N_planes = range(0, nplanes, 2)
Al_planes = range(1, nplanes, 2)
if emitter == 'Al':
tags = [0, 2]
planes = Al_planes
else:
tags = [1, 3]
planes = N_planes
return AlN, tags, planes
clusters = []
for side in ('Al', 'N'):
for emitter in ('Al', 'N'):
AlN, tags, planes = get_AlN_tags_planes(side, emitter)
for emitter_tag in tags:
for emitter_plane in planes:
cluster = # hemis…, construct the cluster here with # <= HERE
# 2 planes below the emitter
cluster.absorber = get_atom_index(cluster, 0, 0, 0)
cluster.info.update({
'emitter_plane': emitter_plane,
'emitter_tag' : emitter_tag,
'emitter' : emitter,
'side' : side,
})
clusters.append(cluster)
print("Added cluster {}-side, emitter {}(tag {:d}) in "
"plane #{:d}".format(side, emitter, emitter_tag,
emitter_plane))
return clusters
def compute(clusters, theta=np.arange(-20., 80., 1.), phi=0.):
data = None
for ic, cluster in enumerate(clusters):
# Retrieve info from cluster object
side = cluster.info['side']
emitter = cluster.info['emitter']
plane = cluster.info['emitter_plane']
tag = cluster.info['emitter_tag']
# Set the level and the kinetic energy
if emitter == 'Al':
level = ##### # <= HERE
ke = ##### # <= HERE
elif emitter == 'N':
level = ##### # <= HERE
ke = ##### # <= HERE
calc = # Create a calculator using the RA series expansion algorithm # <= HERE
calc.source_parameters.energy = ##### # <= HERE
calc.source_parameters.theta = ##### # <= HERE
calc.detector_parameters.angular_acceptance = ##### # <= HERE
calc.detector_parameters.average_sampling = 'medium'
calc.calculation_parameters.scattering_order = max(1, min(4, plane))
calc.calculation_parameters.path_filtering = 'forward_scattering'
calc.calculation_parameters.off_cone_events = 1
[a.set('forward_angle', 30.) for a in cluster]
calc.set_atoms(cluster)
data = calc.get_theta_scan(level=level, theta=theta, phi=phi,
kinetic_energy=ke, data=data)
dset = data[-1]
dset.title = "\'{}\' side - {}({}) tag #{:d}, plane #{:d}".format(
side, emitter, level, tag, plane)
return data
def analysis(data):
tmp_data = {}
for dset in data:
info = dset.get_cluster().info
side = info['side']
emitter = info['emitter']
try:
key = '{}_{}'.format(side, emitter)
tmp_data[key] += dset.cross_section
except KeyError:
tmp_data[key] = dset.cross_section.copy()
tmp_data['theta'] = dset.theta.copy()
tmp_data['Al_side'] = tmp_data['Al_Al'] / tmp_data['Al_N']
tmp_data['N_side'] = tmp_data['N_Al'] / tmp_data['N_N']
# now add all columns
substrate_dset = data.add_dset('Total substrate signal')
substrate_dset.add_columns(**tmp_data)
view = substrate_dset.add_view('Ratios',
title=r'Al(2p)/N(1s) ratios on both polar '
r'sides of AlN in the (10$\bar{1}$0) '
r'azimuthal plane',
xlabel=r'$\Theta (\degree$)',
ylabel='Intenisty ratio')
view.select('theta', 'Al_side', legend='Al side',
where="theta >= 0 and theta <=70")
view.select('theta', 'N_side', legend='N side',
where="theta >= 0 and theta <=70")
view.set_plot_options(autoscale=True)
return data
clusters = create_clusters()
data = compute(clusters)
data = analysis(data)
data.view()

View File

@ -0,0 +1,132 @@
#!/usr/bin/env python
# coding: utf8
from ase.build import bulk
import numpy as np
from msspec.calculator import MSSPEC, XRaySource
from msspec.utils import hemispherical_cluster, get_atom_index
def create_clusters(nplanes=6):
def get_AlN_tags_planes(side, emitter):
AlN = bulk('AlN', crystalstructure='wurtzite', a=3.11, c=4.975)
[atom.set('tag', i) for i, atom in enumerate(AlN)]
if side == 'Al':
AlN.rotate([0,0,1],[0,0,-1])
Al_planes = range(0, nplanes, 2)
N_planes = range(1, nplanes, 2)
else:
N_planes = range(0, nplanes, 2)
Al_planes = range(1, nplanes, 2)
if emitter == 'Al':
tags = [0, 2]
planes = Al_planes
else:
tags = [1, 3]
planes = N_planes
return AlN, tags, planes
clusters = []
for side in ('Al', 'N'):
for emitter in ('Al', 'N'):
AlN, tags, planes = get_AlN_tags_planes(side, emitter)
for emitter_tag in tags:
for emitter_plane in planes:
cluster = hemispherical_cluster(AlN,
emitter_tag=emitter_tag,
emitter_plane=emitter_plane,
planes=emitter_plane+2)
cluster.absorber = get_atom_index(cluster, 0, 0, 0)
cluster.info.update({
'emitter_plane': emitter_plane,
'emitter_tag' : emitter_tag,
'emitter' : emitter,
'side' : side,
})
clusters.append(cluster)
print("Added cluster {}-side, emitter {}(tag {:d}) in "
"plane #{:d}".format(side, emitter, emitter_tag,
emitter_plane))
return clusters
def compute(clusters, theta=np.arange(-20., 80., 1.), phi=0.):
data = None
for ic, cluster in enumerate(clusters):
# Retrieve info from cluster object
side = cluster.info['side']
emitter = cluster.info['emitter']
plane = cluster.info['emitter_plane']
tag = cluster.info['emitter_tag']
# Set the level and the kinetic energy
if emitter == 'Al':
level = '2p'
ke = 1407.
elif emitter == 'N':
level = '1s'
ke = 1083.
calc = MSSPEC(spectroscopy='PED', algorithm='expansion')
calc.source_parameters.energy = XRaySource.AL_KALPHA
calc.source_parameters.theta = -35
calc.detector_parameters.angular_acceptance = 4.
calc.detector_parameters.average_sampling = 'medium'
calc.calculation_parameters.scattering_order = max(1, min(4, plane))
calc.calculation_parameters.path_filtering = 'forward_scattering'
calc.calculation_parameters.off_cone_events = 1
[a.set('forward_angle', 30.) for a in cluster]
calc.set_atoms(cluster)
data = calc.get_theta_scan(level=level, theta=theta, phi=phi,
kinetic_energy=ke, data=data)
dset = data[-1]
dset.title = "\'{}\' side - {}({}) tag #{:d}, plane #{:d}".format(
side, emitter, level, tag, plane)
return data
def analysis(data):
tmp_data = {}
for dset in data:
info = dset.get_cluster().info
side = info['side']
emitter = info['emitter']
try:
key = '{}_{}'.format(side, emitter)
tmp_data[key] += dset.cross_section
except KeyError:
tmp_data[key] = dset.cross_section.copy()
tmp_data['theta'] = dset.theta.copy()
tmp_data['Al_side'] = tmp_data['Al_Al'] / tmp_data['Al_N']
tmp_data['N_side'] = tmp_data['N_Al'] / tmp_data['N_N']
# now add all columns
substrate_dset = data.add_dset('Total substrate signal')
substrate_dset.add_columns(**tmp_data)
view = substrate_dset.add_view('Ratios',
title=r'Al(2p)/N(1s) ratios on both polar '
r'sides of AlN in the (10$\bar{1}$0) '
r'azimuthal plane',
xlabel=r'$\Theta (\degree$)',
ylabel='Intenisty ratio')
view.select('theta', 'Al_side', legend='Al side',
where="theta >= 0 and theta <=70")
view.select('theta', 'N_side', legend='N side',
where="theta >= 0 and theta <=70")
view.set_plot_options(autoscale=True)
return data
clusters = create_clusters()
data = compute(clusters)
data = analysis(data)
data.view()

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 KiB