11. phaseshifts API
11.1. Package Contents
This chapter covers the main modules of the phaseshifts and provides some API documentation for those wishing to incorporate this package into their own projects.
11.2. Subpackages
- The main sub packages are listed below:
phaseshifts.gui- includes all the necessary files for the graphical user interface.phaseshifts.lib- contains the Fortran libphsh library and the python wrappings.phaseshifts.doc- source documentation for the phaseshifts package.phaseshifts.test- modules for testing the phaseshift package.
11.3. Submodules
11.3.1. phaseshifts.atorb
atorb.py
This module provides a high-level Python interface for generating input files and executing atomic structure calculations using the ‘atorb’ program (part of the Barbieri/Van Hove LEED phase shift package).
The core functionality allows users to: 1. Determine the ground-state electronic configuration of elements. 2. Construct formatted input files for the atorb Fortran solver. 3. Calculate radial charge densities \(\rho(r)\) by solving the
Dirac-Fock (relativistic) or Hartree-Fock (non-relativistic) equations for a free atom.
These charge densities serve as the starting potential for calculating scattering phase shifts in Low-Energy Electron Diffraction (LEED) and photoelectron diffraction experiments.
- See:
http://www.icts.hkbu.edu.hk/surfstructinfo/SurfStrucInfo_files/leed/
- Requires:
f2py (for libphsh fortran wrapper generation)
Note
To generate libphsh fortran wrappers (libphsh.pyd) for your platform then use ‘python setup.py’ in the lib directory of this package to install into your python distribution. Alternatively, use:
f2py -c -m libphsh libphsh.f
Windows users may have to add appropriate compiler switches, e.g.
# 32-bit
f2py -c -m libphsh --fcompiler=gfortran --compiler=mingw-32 libphsh.f
# 64-bit
f2py -c -m libphsh --fcompiler=gfortran --compiler=mingw-64 libphsh.f
- class phaseshifts.atorb.Atorb(ngrid=1000, rel=True, exchange=0.0, relic=0, mixing_SCF=0.05, tolerance=0.0005, xnum=100, ifil=0, **kwargs)[source]
Bases:
objectWrapper for the atorb atomic structure solver.
This class encapsulates the logic for interacting with the Barbieri/Van Hove atorb program. It calculates atomic orbitals and radial charge densities on a logarithmic grid.
The solver numerically integrates the radial Dirac equation (or Schrödinger equation if relativistic effects are disabled) to find the eigenvalues and eigenfunctions of the bound electrons.
Notes
The Breit interaction is neglected, which is a valid approximation for valence states dominating the scattering potential in LEED.
Original author: Eric Shirley
There are nr grid points, and distances are in Bohr radii \(a_0 \simeq 0.539 \mathrm{\AA}\)
\(r(i) = r_{min} \cdot (r_{max} / r_{min})^{(i/n_r)}\), \(i=1,2,3,...n_r-1,n_r\)
The orbitals are stored in phe(), first index goes \(1...n_r\), the second index is the orbital index (\(i...n_{el}\))
Look at the atomic files after printing this out to see everything… Suffice it to say, that the charge density at radius \(r(i)\) in units of electrons per cubic Bohr radius is given by:
\(\sum_{j-1}^{n_el}{occ(j) \cdot phe(i,j)^2 / (4.0\,\pi\,{r(i)^2)}}\)
Think of the phe functions as plotting the radial wave-functions as a function of radius on a logarithmic mesh…
The Dirac equation is solved for the orbitals, whereas their density is treated by setting \(phe(i,j)\) to Dirac’s \(\sqrt{F(i,j)^2 + G(i,j)^2}\) times the sign of \(G(i,j)\)…
So we are doing Dirac-Fock, except that we are not treating exchange exactly, in terms of working with major and minor components of the orbitals, and the phe’s give the CORRECT CHARGE DENSITY…
The above approximation ought to be very small for valence states, so you need not worry about it…
The Breit interaction has been neglected altogether…it should not have a huge effect on the charge density you are concerned with…
- _get_conf_parameters(conf_file='hf.conf')[source]
- Parameters:
- conf_filestr
Path to
*.conffile to read from. If the file does not exist then the function will attempt to readhf.conffrom normal lookup storage locations, including (in order):ATLIBor~/atlib/~/or%USERPROFILE%/~/.phaseshifts/or%APPDATA%/phaseshifts‘./’
- Returns:
- Dictionary of Atorb.gen_input() keyword arguments.
- atlib = '~/atlib/'
- static calculate_Q_density(**kwargs)[source]
Execute the atomic structure calculation to obtain radial charge densities.
This method serves as the primary driver for the ‘atorb’ Fortran routine. It either generates a new input file based on an element symbol or validates an existing input file, then invokes the solver (hartfock) via libphsh.
The solver computes the radial wavefunctions \(\phi_{n,l,j}(r)\) and constructs the total spherical charge density \(\rho(r)\).
- Parameters:
- **kwargsdict, optional
Keyword arguments passed to
gen_input()if element is provided.- elementstr or int
Target element. If provided, an input file is generated on-the-fly.
- inputstr
Path to an existing atorb input file. Ignored if element is provided.
- output_dirstr
Directory where the output file (containing phase shifts or charge densities) should be placed. Defaults to current directory.
- Returns:
- str
Path to the output file containing the calculated atomic charge densities.
- Raises:
- ValueError
If neither element nor input is specified.
- IOError
If the output directory cannot be created or accessed.
Examples
>>> Atorb.calculate_Q_density(input='atorb_C.txt') 18.008635 -33.678535 4.451786 -36.654271 1.569616 -37.283660 0.424129 -37.355634 0.116221 -37.359816 0.047172 -37.360317 0.021939 -37.360435 0.010555 -37.360464 0.005112 -37.360471 0.002486 -37.360473 0.001213 -37.360473 0.000593 -37.360473 0.000290 -37.360474 N L M J S OCC. 1 0 0 -1/2 1 2.0000 -11.493862 2 0 0 -1/2 1 2.0000 -0.788618 2 1 1 -1/2 1 0.6667 -0.133536 2 1 1 -3/2 1 1.3333 -0.133311 TOTAL ENERGY = -37.360474 -1016.638262
>>> Atorb.calculate_Q_density(element='H') 0.500007 -0.343752 0.152392 -0.354939 0.065889 -0.357254 0.028751 -0.357644 0.012732 -0.357703 0.005743 -0.357711 0.002641 -0.357712 0.001236 -0.357713 0.000587 -0.357713 0.000282 -0.357713 N L M J S OCC. 1 0 0 -1/2 1 1.0000 -0.229756 TOTAL ENERGY = -0.357713 -9.733932
- datalib = '~/.phaseshifts'
- property exchange
Returns the exchange correlation value, where 0.0=Hartree-Fock, 1.0=LDA or <float>=-alpha
- gen_conf_file(conf_file='hf.conf')[source]
- Parameters:
- conf_filestr
Filepath for conf output file (default: ‘hf.conf’).
- static gen_input(element, **kwargs)[source]
Generate the input file for the ‘atorb’ atomic structure solver.
This method constructs a formatted input file required by the Barbieri/Van Hove ‘atorb’ program (encapsulated in libphsh). It determines the electronic configuration of the specified element, handles noble gas core expansion, and sets up the radial grid and exchange-correlation parameters for the Dirac-Fock calculation.
- Parameters:
- elementstr or int
The chemical symbol (e.g., ‘Cu’) or atomic number (e.g., 29) of the target element.
- **kwargsdict, optional
Configuration options for the calculation:
- outputstr
Filename for the resulting charge density output (default: ‘at_<symbol>.i’).
- ngridint
Number of points in the logarithmic radial grid (default: 1000). Higher values provide better numerical resolution near the nucleus.
- relint or bool
Relativistic flag (default: 1). 1 (or True): Solve Dirac equations (includes spin-orbit coupling). 0 (or False): Solve non-relativistic Schrödinger equations.
- filenamestr
Filename for the generated input text file (default: ‘atorb_<symbol>.txt’).
- headerstr
Comment line at the top of the input file (default: auto-generated).
- methodstr
Exchange-correlation potential approximation (default: ‘0.d0’ for Hartree-Fock). ‘0.d0’: Hartree-Fock (HF). ‘1.d0’: Local Density Approximation (LDA). ‘-alpha’: X-alpha method (requires providing alpha value).
- relicfloat
Mixing parameter for the self-consistency cycle (default: 0.0).
- mixing_SCFfloat
Mixing parameter for Self-Consistent Field convergence (default: 0.5).
- tolerancefloat
Convergence tolerance for orbital eigenvalues (default: 0.0005 Hartrees).
- echint
Parameter for the exchange potential (default: 100).
- atorb_filestr or IO, optional
Override the destination for the generated input file. Accepts a file path or a file-like object (e.g., StringIO) for buffered writes.
- xnumfloat, optional
Extra numeric parameter used by EEASiSSS input formatting (default: 100).
- ifilint, optional
Flag to read vpert from vvalence. Only used when fmt=’rundgren’ or ‘eeasisss’ (default: 0).
- fmtstr, optional
Format of generated atorb input file; use ‘vht’ for Barbieri/Van Hove or ‘rundgren’/’eeasisss’ for EEASiSSS (default: ‘vht’).
- Returns:
- str
The path to the generated input file.
Notes
The resulting file allows libphsh to solve the radial Dirac equation:
\[H \Psi = E \Psi\]where density functional theory (DFT) or Hartree-Fock approximations define the potential.
- get_conf_parameters(conf_file='hf.conf')[source]
Public wrapper to read Atorb configuration parameters.
- static get_quantum_info(shell)[source]
Parse quantum numbers from a subshell string (e.g., ‘3d6’).
Decomposes a standard spectroscopic notation into the set of quantum numbers required for the radial equation solver. Handles the splitting of shells into spin-orbit coupled states (\(j = l \pm 1/2\)).
- Parameters:
- shellstr
Subshell string, e.g., ‘1s2’, ‘4f14’, ‘3d5’.
- Returns:
- tuple
(n, l, j_list, occ_list)
n (int): Principal quantum number.
l (int): Azimuthal quantum number.
j_list (list[float]): Total angular momentum values \(j\) associated with this shell. For \(l > 0\), this will be [\(l-1/2\), \(l+1/2\)].
occ_list (list[float]): Occupancy for each \(j\) level. Electrons are distributed according to statistical weight (\(2j+1\)).
Examples
>>> Atorb.get_quantum_info('3d6') (3, 2, [1.5, 2.5], [2.4, 3.6])
For a full ‘3d10’ shell:
>>> Atorb.get_quantum_info('3d10') (3, 2, [1.5, 2.5], [4.0, 6.0])
Here, \(n=3\), \(l=2\). The states are \(d_{3/2}\) (occupancy 4) and \(d_{5/2}\) (occupancy 6).
- property mixing_SCF
Returns the self-consisting field value
- property ngrid
Returns the number of points in the radial charge grid
- property rel
Returns boolean value of whether to consider relativistic effects
- property relic
Returns the relic value for calculation
- static replace_core_config(electron_config)[source]
Expand noble gas core abbreviations into full orbital strings.
The atorb solver requires explicit definitions for all orbitals starting from 1s. This function replaces ‘[Ar]’, ‘[Xe]’, etc., with their constituent subshells.
- Parameters:
- electron_configstr
Electronic configuration string, potentially containing noble gas cores (e.g., ‘[Ar] 4s2’).
- Returns:
- str
The fully expanded configuration string.
Examples
>>> Atorb.replace_core_config('[He] 2s1') '1s2 2s1'
- property tolerance
Returns the eigenvalue tolerance
- update_config(conf)[source]
- Parameters:
- confstr or dict
Either filepath to the user-specified
*.conffile containing the atomic charge density calculation parameters or else a dictionary of the keyword arguments to update.
- Raises:
- ValueError if
confis neither a str or dict instance.
- ValueError if
- userhome = '~/hf.conf'
- static validate_input_file(input_path)[source]
Validate a generated or user-supplied atorb input file.
Parses the input file using the phaseshifts.validation.atorb logic to ensure it meets the strict formatting and physical requirements of the solver.
- Parameters:
- input_pathstr
Path to the file to validate.
- Returns:
- AtorbInputModel
Parsed and validated representation of the input file.
- property xnum
Returns xnum value
- class phaseshifts.atorb.EEASiSSSAtorb(ifil=0, **kwargs)[source]
Bases:
Atorb- _get_conf_parameters(conf_file='~/atlib/hf.conf')[source]
- Parameters:
- conf_filestr
Path to
*.conffile to read from. If the file does not exist then the function will attempt to readhf.conffrom normal storage locations, including (in order):ATLIBor~/atlib/~/or%USERPROFILE%/~/.phaseshifts/or%APPDATA%/phaseshifts‘./’
- Returns:
- Dictionary of keyword arguments for
Atorb.gen_input().
- Dictionary of keyword arguments for
- static calculate_Q_density(elements=None, atorb_input='inputA', output_dir=None, **kwargs)[source]
- Parameters:
- elementslist of Element, int or str
Generate atorb input file on the fly. If the list is empty then the function will return an empty list.
- atorb_inputstr, optional
Specifies the path to the atorb input file. If
Nonethen a temporary file will be created.- output_dirstr, optional
Specifies the output directory for the at_*.i file generated. (default: :envar:`$ATLIB` or
~/atlib)- subroutinefunction, optional
Specifies the hartfock function to use (default: eeasisss_hartfock)
Warning
Do not modify the
subroutinevalue without good cause - here be dragons!
- Returns:
- List of filepaths to the calculated atomic charge density files.
Notes
This method implicitly calls
EEASiSSSAtorb.gen_input()for generating a suitable input file for the charge density calculations.For the patient, it may be worth having a initial one-time atomic charge density calculation for every element. This can be done like so:
from phaseshifts.elements import ELEMENTS, SERIES from phaseshifts.atorb import EEASiSSSAtorb # calculate chgden* files for EVERY element # and place them in the default location EEASiSSSAtorb.calculate_Q_density(elements=ELEMENTS)
Note
The above calculation is very useful and can be customised using a user generated
hf.conffile. For more details seeEEASiSSSAtorb.gen_conf_file()Examples
>>> from phaseshifts.elements import ELEMENTS, SERIES >>> from phaseshifts.atorb import EEASiSSSAtorb >>> >>> # generate hartfock input file for InGaAs >>> InGaAs = ['In', 31, 'Arsenic'] >>> input = '~/atlib/InGaAs.hf' >>> EEASiSSSAtorb.calculate_Q_density(elements=InGaAs, >>> atorb_input=input) >>> >>> # generate hartfock input file for all halogens >>> halogens = [e for e in ELEMENTS if SERIES[e.series] == 'Halogens'] >>> input = '$ATLIB/halogens.hf' >>> EEASiSSSAtorb.calculate_Q_density(halogens, atorb_file=input) >>> >>> # do likewise for all non-metals, but using hf.conf file parameters >>> series = 'Nonmetals' >>> non_metals = [e for e in ELEMENTS if SERIES[e.series] == series] >>> input = './nonmetals.hf' >>> EEASiSSSAtorb.calculate_Q_density(non_metals, atorb_file=input)
- gen_conf_file(conf_file='~/atlib/hf.conf')[source]
- Parameters:
- conf_filestr
Filepath for conf output file (default: ‘~/atlib/hf.conf’).
Examples
>>> from phaseshifts.atorb import EEASiSSSAtorb >>> atorb = EEASiSSSAtorb() # create an object instance >>> # create a config file in the default location >>> atorb.gen_conf_file()
- static gen_input(elements=None, atorb_file='inputA', **kwargs)[source]
- Parameters:
- elementslist
List of elements to include in the generated input file. Each element can be either the atomic number, symbol, name or an
phaseshifts.Elementinstance.- outputstr, optional
File string for atomic orbital output (default: ‘at_<symbol>.i’)
- ngridint, optional
Number of points in radial grid (default: 1000)
- relbool, optional
Specify whether to consider relativistic effects (default: True)
- atorb_filestr, optional
Name for generated input file (default: ‘inputA’)
- headerstr, optional
Comment at beginning of input file (default: None)
- methodstr or float, optional
Exchange correlation method using either 0.0=Hartree-Fock, 1.0=LDA, -alpha = float (default: 0.0)
- relicfloat, optional
Relic value for calculation (default: 0)
- mixing_SCFfloat, optional
Self consisting field value (default: 0.5)
- tolerancefloat, optional
Eigenvalue tolerance (default: 0.0005)
- xnumfloat, optional
??? (default: 100)
- ifilint, optional
flag to read
vpertarray fromvvalence- possibly redundant. Only used when fmt=’rundgren’ or ‘eeasisss’ (default: 0)
- Returns:
- Filename of input file once generated or else instance of StringIO
- object containing written input text.
Nonewill be returned if - the method failed to generate the input.
Notes
output can also be a StringIO() object to avoid saving to file.
Examples
>>> from phaseshifts.elements import ELEMENTS, SERIES >>> >>> # generate hartfock input file for InGaAs >>> InGaAs = ['In', 31, 'Arsenic'] >>> EEASiSSS.gen_input(elements=InGaAs, atorb_file='~/atlib/InGaAs.hf') >>> >>> # generate hartfock input file for all halogens >>> halogens = [e for e in ELEMENTS if SERIES[e.series] == 'Halogens'] >>> EEASiSSS.gen_input(halogens, atorb_file='$ATLIB/halogens.hf') >>> >>> # do likewise for all non-metals, but using hf.conf file parameters >>> non_metals = [e for e in ELEMENTS if SERIES[e.series] == 'Nonmetals'] >>> EEASiSSS.gen_input(non_metals, atorb_file='./nonmetals.hf')
- get_conf_parameters(conf_file='~/atlib/hf.conf')[source]
Public wrapper to read EEASiSSS-specific configuration parameters.
- property ifil
Returns flag for reading
vpertarray from filevvalence
- phaseshifts.atorb.eeasisss_hartfock(input_file)[source]
Lightweight wrapper around the EEASiSSS hartfock routine.
The underlying Fortran expects optional log/output arguments; this wrapper matches the single-argument call shape used by
Atorb.calculate_Q_density().
- phaseshifts.atorb.get_electron_config(element_obj)[source]
Extract the electronic configuration string from an element object.
Retrieves the standard ground-state configuration (e.g., ‘[Ar] 4s2 3d10 4p5’) from the backend-specific element object.
- Parameters:
- element_objobject
The element object returned by get_element.
- Returns:
- str
The electronic configuration string.
- phaseshifts.atorb.get_element(element: str, backend: str | None = None) object[source]
Retrieve an element object from the specified chemical data backend.
This function abstracts the details of various chemistry libraries (mendeleev, elementy, periodictable) to provide a unified interface for accessing atomic properties like proton count (Z) and electronic configurations.
- Parameters:
- elementstr or int
The symbol (e.g., ‘Fe’) or atomic number (e.g., 26) of the element.
- backendstr, optional
The preferred backend library to use (‘mendeleev’, ‘elementy’, ‘periodictable’). If None, tries available backends in order.
- Returns:
- object
An object containing element data (attributes vary by backend but usually include protons, symbol, name).
- Raises:
- LookupError
If the element cannot be found in any available backend.
11.3.2. phaseshifts.conphas
conphas.py
Provides a native python version of the conphas (phsh3) FORTRAN program by W. Moritz, which is distributed as part of the SATLEED code (see “Barbieri/Van Hove phase shift calculation package” section) and can be found at: http://www.icts.hkbu.edu.hk/surfstructinfo/SurfStrucInfo_files/ leed/leedpack.html
The Conphas() class also provides a number of convenience functions (see docstrings below).
11.3.2.1. Examples
>>> from os.path import join
>>> from phaseshifts.conphas import Conphas
>>> con = Conphas(output_file=join('testing', 'leedph_py.d'), lmax=10)
>>> con.set_input_files([join('testing', 'ph1')])
>>> con.set_format('cleed')
>>> con.calculate()
- class phaseshifts.conphas.Conphas(input_files=None, output_file=None, formatting=None, lmax=10, v0_params=None, **kwargs)[source]
Bases:
objectClass Conphas
Notes
This work is based on the original conphas (phsh3) FORTRAN program by W. Moritz, which is distributed as part of the SATLEED code (see “Barbieri/Van Hove phase shift calculation package” section) and can be found at: http://www.icts.hkbu.edu.hk/surfstructinfo/SurfStrucInfo_files/ leed/leedpack.html
- __fix_path(file_path)
Fix escaped characters in filepath
- __set_data(data=None)
- _resolve_v0_params()[source]
Resolve Rundgren inner potential parameters for ViPErLEED output.
- Returns:
- tuple(float, float, float, float)
c0-c3 parameters; defaults to ViPErLEED’s documented values if none are provided. Raises a ValueError if an invalid v0_params configuration is supplied.
- _write_viper_output(file_handle, conpha, energy, n_phases)[source]
Write phase shifts in ViPErLEED PHASESHIFTS format.
- Parameters:
- file_handleIO
Open file handle for writing.
- conphalist
Continuous phase shifts per atom/site.
- energylist
Energies in eV as parsed from phasout.
- n_phasesint
Number of energy points to write.
- calculate()[source]
Calculates continuous phase shifts from input file(s).
Examples
>>> con = Conphas(output_file=r'testing/leedph_py.d', lmax=10) >>> con.set_input_files([r'testing/ph1']) >>> con.set_format('cleed') >>> con.calculate() L = 0 jump between 25.0 eV and 30.0 eV; IFAK = -1 L = 1 jump between 65.0 eV and 70.0 eV; IFAK = -1 L = 2 jump between 20.0 eV and 25.0 eV; IFAK = 1 jump between 80.0 eV and 85.0 eV; IFAK = 0 L = 3 L = 4 jump between 275.0 eV and 280.0 eV; IFAK = 1 L = 5 L = 6 L = 7 L = 8 L = 9 L = 10
- load_data(filename)[source]
Load (discontinuous) phase shift data from file
- Parameters:
- filestr
Path to phase shift file.
- Returns:
- tuple: (double, double, int, int, ndarray)
(initial_energy, energy_step, n_phases, lmf, data)
Notes
initial_energy is the starting energy of the phase shifts.
energy_step is the change in energy between consecutive values.
n_phases is the number of phase shifts contained in the file.
lmf is the maximum azimuthal quantum number considered.
data is a (2 x n_phases) array containing the phase shift data.
- read_datafile(filename)[source]
Read in discontinuous phase shift file
- Parameters:
- filenamestr
The path to the discontinuous phase shift file
- set_format(formatting=None)[source]
Set appropriate format from available options
- Parameters:
- formatstr, optional
The format identifier for different packages; can be ‘cleed’, ‘curve’, ‘viperleed’, or None.
11.3.3. phaseshifts.elements
Properties of the chemical elements.
Each chemical element is represented as an object instance. Physicochemical and descriptive properties of the elements are stored as instance attributes.
- Author:
- Version:
2013.03.18
11.3.3.1. Requirements
11.3.3.2. References
11.3.3.3. Examples
>>> from elements import ELEMENTS
>>> len(ELEMENTS)
109
>>> str(ELEMENTS[109])
'Meitnerium'
>>> ele = ELEMENTS['C']
>>> ele.number, ele.symbol, ele.name, ele.eleconfig
(6, 'C', 'Carbon', '[He] 2s2 2p2')
>>> ele.eleconfig_dict
{(1, 's'): 2, (2, 'p'): 2, (2, 's'): 2}
>>> sum(ele.mass for ele in ELEMENTS)
14659.1115599
>>> for ele in ELEMENTS:
... ele.validate()
... ele = eval(repr(ele))