Finish Activity 4

This commit is contained in:
Sylvain Tricot 2025-07-22 16:29:02 +02:00
parent 99bf39a37b
commit 8f5dbf6483
7 changed files with 138 additions and 87 deletions

View File

@ -11,7 +11,13 @@
"tags": []
},
"source": [
"# Activity 4: From single scattering to multiple scattering"
"(ssc2ms)=\n",
"# Activity 4: From single scattering to multiple scattering\n",
"\n",
"In the [previous activity](ssc), we saw that simple single scattering calculations (SSC) can be used to simulate photodiffraction diagrams with good accuracy. The approximation works fine when the emitting atom is very close to the surface.\n",
"However, the SSC approach is no longer suitable for deeper emitter atoms, where multiple scattering effects come into play. In this activity, we will focus on a major consequence of multiple scattering: *the defocusing effect*.\n",
"\n",
"The defocusing effect is presented in the [figure below](Ni-fig1) for a chain of nickel atoms. Although purely illustrative, understanding multiple scattering in atomic chains is fundamental because they are found in many situations, such as in particular directions of a crystal or in molecules of various lengths."
]
},
{
@ -26,17 +32,27 @@
},
"source": [
":::{figure-md} Ni-fig1\n",
"<img src=\"Ni_fig1.png\" alt=\"Ni chain\" width=\"600px\" align=\"center\">\n",
"<img src=\"defocusing_animation.gif\" alt=\"defocusing effect\" width=\"600px\" align=\"center\">\n",
"\n",
"Polar scan of a Ni chain of 2-5 atoms for single and mutliple (5{sup}`th` order) scattering.\n",
"The defocusing effect dur to multiple scattering in an atomic chain of Ni atoms.\n",
":::"
]
},
{
"cell_type": "markdown",
"id": "b1b4c789-e62c-40cc-92a3-053e6a90d315",
"metadata": {},
"source": [
"In 1989, M.-L Xu, J.J. Barton and M.A. Van Hove studied these multiple scattering effects on atomic chains ([see their paper below](defocusing-paper)).\n",
"In the spirit of figure 3 of their paper, we will create 3 atomic chains of Ni atoms (2, 3 and 5 atoms) tilted by 45° and we will compare the intensity of the forward scattering peak for single scattering and for full multiple scattering."
]
},
{
"cell_type": "markdown",
"id": "4988e7d3-2ba3-470f-9676-8116348c30a1",
"metadata": {},
"source": [
"(defocusing-paper)=\n",
":::{seealso}\n",
"based on this paper from M.-L. Xu *et al.*\n",
"[Phys. Rev. B **39** p8275 (1989)](https://doi.org/10.1103/PhysRevB.39.8275) \n",
@ -45,27 +61,97 @@
},
{
"cell_type": "markdown",
"id": "b2aa92f1-3170-47f6-87c2-e7abffcbdb12",
"id": "011ef23b-5a76-410d-8d44-1c4a899e2a23",
"metadata": {},
"source": [
":::{literalinclude} Ni_chain.py\n",
":lineno-match:\n",
"## Polar scans of Ni atomic chains\n",
"\n",
"### Building a chain of atoms\n",
"\n",
"Start by creating a simple chain of 2 Ni atoms: an emitter and a scatterer in the [101] direction.\n",
"\n",
":::{tip}\n",
"Nickel is *fcc* with lattice parameter $a$=3.499 Å. Use the [`Atoms`](https://wiki.fysik.dtu.dk/ase/ase/atoms.html#ase.Atoms) class of `ase` like in the [previous activity](ssc)...\n",
"\n",
":::{admonition} if you need help to start...\n",
":class: dropdown\n",
"\n",
":::{code} python\n",
"from msspec.calculator import MSSPEC\n",
"from ase import Atoms\n",
"\n",
"symbol = ... # The kind of atom for the chain\n",
"a = ... # The distance bewteen 2 atoms\n",
" # in [101] direction\n",
"\n",
"chain = Atoms(..., positions=[...])\n",
"chain.rotate(...)\n",
"chain.edit()\n",
":::\n",
"\n",
":::\n",
"\n",
":::"
]
},
{
"cell_type": "markdown",
"id": "bbd682d1-d142-4ac5-872d-0b57f3deecb9",
"id": "3ed73f46-c12f-452f-a584-00d142f2e133",
"metadata": {},
"source": [
"```{admonition} *Solution...*\n",
":class: tip\n",
":class: dropdown\n",
"Building the 2-atoms chain\n",
"\n",
":::{literalinclude} Ni_chain1.py\n",
":linenos: true\n",
":lines: 1-10\n",
":::\n",
"\n",
":::{figure-md} Ni-fig2\n",
"<img src=\"Ni_2atomsSSC.png\" alt=\"Ni 2 atoms\" width=\"600px\" align=\"center\">\n",
"\n",
"Polar scan of a Ni(3s) chain of 2 atoms for single scattering.\n",
":::\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "5c57f951-bfa7-435e-8e74-b3de11909768",
"metadata": {},
"source": [
"::::{tab-set}\n",
"\n",
":::{tab-item} <i class=\"fa-solid fa-circle-question\"></i> Quiz\n",
"Some questions to answer\n",
"Create an `MSSPEC` calculator with `expansion` algortithm and set the `scattering_order`=1 to compute a polar scan of the Ni(3s) in single scattering. How is varying the height of the peak at 45° (along the chain) if you increase the number of atoms in the chain ?\n",
"\n",
"Repeat the same experiment with `inversion` algorithm for having the full multiple scattering result. What do you observe ?\n",
":::\n",
"\n",
"::::"
]
},
{
"cell_type": "markdown",
"id": "626708d9-c421-4bf0-bd70-f32113360f9c",
"metadata": {},
"source": [
"```{admonition} *Solution...*\n",
":class: tip\n",
":class: dropdown\n",
"\n",
"The peak at 45° is increasing with the number of atoms in the chain for SSC. We observe defocusing of this peak for full multiple scattering calculations (MSC). For the 2-atoms chain, both SSC and MSC give the same result owing to the fact that the emitter has only one scatterer atom and that kinetic energy is high enough to cancel out all backscattering.\n",
"\n",
":::{figure-md} Ni-figX\n",
"<img src=\"Ni_SSCvsMI.jpg\" alt=\"Ni chain\" width=\"600px\" align=\"center\">\n",
"\n",
"Polar scan of a Ni chain of 2-5 atoms for single and full mutliple scattering.\n",
":::\n",
"\n",
"```"
]
}
],
"metadata": {
@ -84,7 +170,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.13"
"version": "3.11.3"
}
},
"nbformat": 4,

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 KiB

View File

@ -1,78 +0,0 @@
# coding: utf-8
# import all we need and start by msspec
from msspec.calculator import MSSPEC
# we will build a simple atomic chain
from ase import Atom, Atoms
# we need some numpy functions
import numpy as np
symbol = 'Ni' # The kind of atom for the chain
orders = (1, 5) # We will run the calculation for single scattering
# and multiple scattering (5th diffusion order)
chain_lengths = (2,3,5) # We will run the calculation for differnt lengths
# of the atomic chain
a = 3.499 * np.sqrt(2)/2 # The distance bewteen 2 atoms
# Define an empty variable to store all the results
all_data = None
# 2 for nested loops over the chain length and the order of diffusion
for chain_length in chain_lengths:
for order in orders:
# We build the atomic chain by
# 1- stacking each atom one by one along the z axis
chain = Atoms([Atom(symbol, position = (0., 0., i*a)) for i in
range(chain_length)])
# 2- rotating the chain by 45 degrees with respect to the y axis
#chain.rotate('y', np.radians(45.))
chain.rotate(45., 'y')
# 3- setting a custom Muffin-tin radius of 1.5 angstroms for all
# atoms (needed if you want to enlarge the distance between
# the atoms while keeping the radius constant)
#[atom.set('mt_radius', 1.5) for atom in chain]
# 4- defining the absorber to be the first atom in the chain at
# x = y = z = 0
chain.absorber = 0
# We define a new PED calculator
calc = MSSPEC(spectroscopy = 'PED')
calc.set_atoms(chain)
# Here is how to tweak the scattering order
calc.calculation_parameters.scattering_order = order
# This line below is where we actually run the calculation
all_data = calc.get_theta_scan(level='3s', #kinetic_energy=1000.,
theta=np.arange(0., 80.), data=all_data)
# OPTIONAL, to improve the display of the data we will change the dataset
# default title as well as the plot title
t = "order {:d}, n = {:d}".format(order, chain_length) # A useful title
dset = all_data[-1] # get the last dataset
dset.title = t # change its title
# get its last view (there is only one defined for each dataset)
v = dset.views()[-1]
v.set_plot_options(title=t) # change the title of the figure
# OPTIONAL, set the same scale for all plots
# 1. iterate over all computed cross_sections to find the absolute minimum and
# maximum of the data
min_cs = max_cs = 0
for dset in all_data:
min_cs = min(min_cs, np.min(dset.cross_section))
max_cs = max(max_cs, np.max(dset.cross_section))
# 2. for each view in each dataset, change the scale accordingly
for dset in all_data:
v = dset.views()[-1]
v.set_plot_options(ylim=[min_cs, max_cs])
# Pop up the graphical window
all_data.view()
# You can end your script with the line below to remove the temporary
# folder needed for the calculation
calc.shutdown()

View File

@ -0,0 +1,19 @@
from msspec.calculator import MSSPEC
from ase import Atoms
import numpy as np
symbol = 'Ni' # The kind of atom for the chain
a = 3.499 * np.sqrt(2)/2 # The distance bewteen 2 atoms
# in [101] direction
chain = Atoms(symbol*2, positions=[(0,0,0), (0,0,a)])
chain.rotate(45, 'y')
calc = MSSPEC(spectroscopy='PED', algorithm='expansion')
calc.calculation_parameters.scattering_order = 1
chain.emitter = 0
calc.set_atoms(chain)
data = calc.get_theta_scan(level='3s', theta=np.arange(0,80,0.5))
data.view()

View File

@ -0,0 +1,24 @@
from msspec.calculator import MSSPEC
from ase import Atoms
import numpy as np
symbol = 'Ni' # The kind of atom for the chain
a = 3.499 * np.sqrt(2)/2 # The distance bewteen 2 atoms
# in [101] direction
chain = Atoms(symbol)
data = None
for i in range(1,5):
atom = Atoms(symbol, [[0,0,i*a]])
atom.rotate('y', 45)
chain += atom
calc = MSSPEC(spectroscopy='PED', algorithm='inversion')
calc.calculation_parameters.scattering_order = 1
chain.emitter = 0
calc.set_atoms(chain)
data = calc.get_theta_scan(level='3s', theta=np.arange(0,80,0.5), data=data)
data[-1].views[0].set_plot_options(ylim=[0,0.045])
data.view()

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB