pyextal.jaxMultipole

Hansen-Coppens multipole modelling of refined electron structure factors.

The refined Ug of LARBED refinements – per-scan jaxGeo runs, joint jaxJoint runs, or any table – are fitted with an aspherical-atom model: frozen core, valence populations with kappa, and density-normalised multipoles up to hexadecapoles with kappa’, on Slater-type radial functions from an XD data bank (Dirac-Fock or PBE/ZORA). Which multipoles and which U_ij each site may have follows from its site symmetry, worked out from the space group the Bloch engine itself uses.

Usage from Python:

from pyextal.jaxMultipole import Crystal, MultipoleModel, AtomSpec, data, params, fit
crystal = Crystal.from_dat('STO_001.dat')
model = MultipoleModel(crystal, [AtomSpec('Sr1', lmax=-1),
                                 AtomSpec('Ti1', valence=['3d', '4s']),
                                 AtomSpec('O1')])
obs = data.from_scan_runs(h5_files, crystal)
pmap = params.build_parameter_map(model, {'Sr1': dict(kappa=False)})
result = fit.fit(model, obs, pmap)

or from a script, with the full command line (jaxMultipole.cli).

Option 2 of the project – multipole parameters refined directly against LARBED intensities – will build on MultipoleModel.ug, which is differentiable and dtype-agnostic (float32 for the Bloch engine, float64 here).

Importing the package sets the same JAX allocator defaults as jaxGeo (no up-front preallocation of 75% of the GPU), so import it before JAX.

Submodules

Classes

Crystal

Cell, symmetry and sites.

Site

One asymmetric-unit atom.

MultipoleModel

Structure factors of a crystal under a multipole model.

AtomSpec

How one site is modelled.

SiteRefine

Refinement switches for one site.

FitSettings

Everything a jaxMultipole.cli run needs.

Functions

build_parameter_map(model[, refine, neutral, ...])

Assembles the free parameters of a refinement.

Package Contents

class pyextal.jaxMultipole.Crystal

Cell, symmetry and sites.

Variables:
  • cell (np.ndarray) – a, b, c, alpha, beta, gamma.

  • A (np.ndarray) – (3, 3) lattice vectors as columns, Angstrom.

  • ops_W (np.ndarray) – (n, 3, 3) fractional rotations of the full group modulo lattice translations (inversion and centring folded in).

  • ops_w (np.ndarray) – (n, 3) their translations.

  • centro (bool) – The group is centrosymmetric.

  • ops_inv (np.ndarray) – (n,) bool, the operation is one of the inversion-related half the engine adds to its coset representatives ((-W, w)); reflections reached only through these are Friedel mates, linked by conjugation (jaxMultipole.symmetry.link_phase).

  • sites (list[Site]) – Asymmetric unit.

  • kv (float) – Accelerating voltage the Ug refer to, kV.

  • source (str) – Where it came from.

cell: numpy.ndarray
A: numpy.ndarray
ops_W: numpy.ndarray
ops_w: numpy.ndarray
centro: bool
sites: list
kv: float
source: str = ''
ops_inv: numpy.ndarray = None
__post_init__()
property Bstar
property G
property Gstar
property omega
property gamma
property n_ops
s(hkl)

sin(theta)/lambda of reflections (..., 3).

site(label)
cart_rotation(W)

Cartesian matrix of a fractional rotation, A W A^-1, snapped orthogonal.

Rounding in the cell leaves A W A^-1 orthogonal only to the cell’s precision; the nearest orthogonal matrix (polar factor) removes that.

with_kv(kv)

Copy at another voltage (Ug scale with gamma).

classmethod manual(cell, ops, sites, kv, centro=None, source='manual', tol=0.0001, ops_inv=None)

Builds a crystal without the engine.

Parameters:
  • cell (sequence) – a, b, c, alpha, beta, gamma.

  • ops (tuple) – (W, w), the full group modulo lattice translations.

  • sites (list[dict]) – dict(label, xyz, beta, occ=1, element=None).

  • kv (float) – Voltage.

  • centro (bool, optional) – Inferred from the operations when None.

  • ops_inv (array, optional) – Marks the inversion-related half of the operations (see the class attributes); none when omitted.

classmethod from_dat(path, labels=None, tol=0.0001)

Snapshots a .dat file through the Bloch engine’s parser.

Parameters:
  • path (path-like) – The crystal file the refinement used.

  • labels (list[str], optional) – Site names; Sr1, Ti1, O1, ... by default.

  • tol (float) – Site-symmetry tolerance, fractional.

Note

bloch_parse resets the engine’s global state and accepts paths of at most 120 characters; a longer absolute path is retried relative to the working directory. No simulation is run, so terminate() is never needed.

class pyextal.jaxMultipole.Site

One asymmetric-unit atom.

Variables:
  • label (str) – Unique name, e.g. 'Sr1', 'O1'.

  • element (str) – Element symbol, 'Sr'.

  • engine_label (str) – The label the engine used ('SR', 'TI4+'), which decides its Cromer-Mann row.

  • xyz (np.ndarray) – Fractional coordinates.

  • occ (float) – Occupancy.

  • beta (np.ndarray) – Engine 6-vector (b11, b22, b33, b12, b13, b23).

  • stab (np.ndarray) – (m, 3, 3) fractional rotations that fix the site.

label: str
element: str
engine_label: str
xyz: numpy.ndarray
occ: float
beta: numpy.ndarray
stab: numpy.ndarray
property order
class pyextal.jaxMultipole.MultipoleModel(crystal, specs=())

Structure factors of a crystal under a multipole model.

Parameters:
  • crystal (Crystal) – The crystal.

  • specs (list[AtomSpec] | dict) – One spec per site, or label -> spec keyword dict; sites without a spec get AtomSpec(site).

crystal
sites = []
layout
_resolve(i, site, spec)
_build_layout()
geometry(hkl)

Everything about a set of reflections that does not depend on p.

Parameters:

hkl (array-like) – (nh, 3) reflections; 000 is not allowed.

Returns:

NumPy arrays: hkl, s, k (bohr^-1), Q (the six ADP quadratic forms per operation), and per site phase (complex, (nh, nops)) and Y (harmonics of the local directions, (nh, nops, (lmax+1)^2)).

Return type:

dict

_beta_matrix()
_site_terms(p, geo, j, dtype)

(f_sph (nh,), f_aniso (nh, nops) | None, T (nh, nops)) of site j.

_crystal_sum(p, geo, electron, static)
ug(p, geo)

Electron structure factors, Angstrom^-2 (complex).

fx(p, geo, static=False)

X-ray structure factors, electrons (complex); static drops the ADPs.

electrons(p)

Electrons in the cell: sum occ * mult * (Pc + sum Pv + P00).

nuclear_charge()
describe()

One line per site: mode, partition, frame, allowed functions.

class pyextal.jaxMultipole.AtomSpec

How one site is modelled.

Variables:
  • site (str) – Site label in the Crystal.

  • mode (str) – 'hc' or 'cm'.

  • bank (str) – XD bank ('RDF_SCM', 'PBE-QZ4P-ZORA' or a path).

  • key (str, optional) – Bank entry; the element by default.

  • valence (list[str], optional) – Valence orbitals (bank default if None).

  • occupations (dict, optional) – Orbital occupation overrides.

  • core_from (str, optional) – Bank entry supplying the core.

  • shells (str) – 'joined' (one Pv for all valence orbitals) or 'separate'.

  • kappa_shared (bool) – One kappa for all valence shells.

  • lmax (int) – Highest deformation order, -1 for none.

  • n_l (tuple, optional) – Radial powers per l; default_n_l if None.

  • zeta (float | sequence, optional) – Deformation exponent (bohr^-1) before kappa’ – one value for every l, or one per l (lmax + 1 values; e.g. VALRAY’s separate alpha_l). Twice the single-zeta exponent of deformation_orbital if None.

  • frame (tuple, optional) – (z, x) direct-lattice directions of the local axes; automatic if None (jaxMultipole.symmetry.local_frame).

site: str
mode: str = 'hc'
bank: str = 'RDF_SCM'
key: str = None
valence: list = None
occupations: dict = None
core_from: str = None
shells: str = 'joined'
kappa_shared: bool = True
lmax: int = 4
n_l: tuple = None
zeta: object = None
frame: tuple = None
class pyextal.jaxMultipole.SiteRefine

Refinement switches for one site.

Variables:
  • Pv (bool | list) – Refine the valence population(s); a list of names (['Pv_3d']) refines only those shells.

  • kappa (bool) – Refine kappa.

  • kappa_p (bool) – Refine kappa’.

  • multipoles (str | list) – 'allowed' for every symmetry-allowed function with 1 <= l <= lmax of the spec, [] for none, or a list of leading labels (['P20', 'P40']) to pick from the allowed ones. P00 is only refined when named explicitly.

  • U (bool) – Refine the symmetry-allowed U_ij.

  • dpop (bool) – Refine the d shell as eg / t2g orbital populations (cubic sites only; replaces that shell’s Pv and the l = 4 function).

Pv: bool = True
kappa: bool = True
kappa_p: bool = False
multipoles: object = 'allowed'
U: bool = True
dpop: bool = False
pyextal.jaxMultipole.build_parameter_map(model, refine=None, neutral=True, dependent=None, start=None)

Assembles the free parameters of a refinement.

Parameters:
  • model (MultipoleModel) – The model.

  • refine (dict, optional) – site label -> SiteRefine (or a dict of its fields). Sites not listed get SiteRefine() – everything allowed, except kappa’ – while 'cm' sites refine their ADPs only.

  • neutral (bool) – Enforce electroneutrality.

  • dependent (str, optional) – The population to eliminate, e.g. 'O1.Pv'; the last refined one by default.

  • start (dict, optional) – Physical starting values overriding the model’s p0 ({'O1.Pv': 6.4, 'Ti1.kappa': 1.02}).

Returns:

ParameterMap

class pyextal.jaxMultipole.FitSettings

Everything a jaxMultipole.cli run needs.

Variables:
  • dat (str) – Crystal .dat (cell, atoms, space group, voltage).

  • h5 (list) – Dataset HDF5 files, or glob patterns, for the per-scan runs.

  • notes (str) – Notes prefix selecting the runs ('geo': per-scan).

  • run (str) – 'latest' or a run key.

  • method (str) – 'robust' or 'mean' aggregation (data.from_scan_runs).

  • clip (float) – Robust rejection threshold, sigma.

  • sigma (str) – 'std' or 'sem'.

  • min_n (int) – Minimum measurements per family.

  • floor (tuple) – (absolute, relative) sigma floor.

  • joint_json (str, optional) – Take central values from this joint run, sigmas from the scans.

  • tables (list[dict]) – Extra data, dict(path=..., kind='xray').

  • exclude (list) – Families to leave out, as [h, k, l].

  • smax (float, optional) – Leave out reflections beyond this s.

  • sites (dict) – label -> AtomSpec keyword dict.

  • fix_kappa (list[str]) – Sites whose kappa is never refined.

  • ladder (list, optional) – [(name, {label: SiteRefine kwargs})]; default_ladder when None.

  • ladder_kappa_p (bool) – Append a kappa’ step to the default ladder.

  • restraints (list[dict]) – dict(name='Ti1.kappa_p', target=1, sigma=0.05).

  • start (dict) – Physical starting values, {'O1.Pv': 6.5}.

  • dependent (str, optional) – Population eliminated by electroneutrality.

  • out (str) – Output prefix (<out>.json, <out>.txt, maps).

  • maps (list[dict]) – Deformation-density planes: dict(name, origin, u, v, extent=(-2, 2, -2, 2), n=121) in fractional / lattice units.

dat: str = None
h5: list = []
notes: str = 'geo'
run: str = 'latest'
method: str = 'robust'
clip: float = 4.0
sigma: str = 'std'
min_n: int = 3
floor: tuple = (2e-05, 0.0)
joint_json: str = None
tables: list = []
exclude: list = []
smax: float = None
sites: dict
fix_kappa: list = []
ladder: list = None
ladder_kappa_p: bool = False
restraints: list = []
start: dict
dependent: str = None
out: str = 'multipole_fit'
maps: list = []