pyextal.jaxMultipole ==================== .. py:module:: pyextal.jaxMultipole .. autoapi-nested-parse:: 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 ---------- .. toctree:: :maxdepth: 1 /autoapi/pyextal/jaxMultipole/bank/index /autoapi/pyextal/jaxMultipole/cli/index /autoapi/pyextal/jaxMultipole/constants/index /autoapi/pyextal/jaxMultipole/crystal/index /autoapi/pyextal/jaxMultipole/data/index /autoapi/pyextal/jaxMultipole/fit/index /autoapi/pyextal/jaxMultipole/harmonics/index /autoapi/pyextal/jaxMultipole/intensity/index /autoapi/pyextal/jaxMultipole/maps/index /autoapi/pyextal/jaxMultipole/model/index /autoapi/pyextal/jaxMultipole/params/index /autoapi/pyextal/jaxMultipole/plotting/index /autoapi/pyextal/jaxMultipole/protocol/index /autoapi/pyextal/jaxMultipole/radial/index /autoapi/pyextal/jaxMultipole/report/index /autoapi/pyextal/jaxMultipole/settings/index /autoapi/pyextal/jaxMultipole/symmetry/index /autoapi/pyextal/jaxMultipole/wien2k/index Classes ------- .. autoapisummary:: pyextal.jaxMultipole.Crystal pyextal.jaxMultipole.Site pyextal.jaxMultipole.MultipoleModel pyextal.jaxMultipole.AtomSpec pyextal.jaxMultipole.SiteRefine pyextal.jaxMultipole.FitSettings Functions --------- .. autoapisummary:: pyextal.jaxMultipole.build_parameter_map Package Contents ---------------- .. py:class:: Crystal Cell, symmetry and sites. :ivar cell: ``a, b, c, alpha, beta, gamma``. :vartype cell: np.ndarray :ivar A: (3, 3) lattice vectors as columns, Angstrom. :vartype A: np.ndarray :ivar ops_W: ``(n, 3, 3)`` fractional rotations of the full group modulo lattice translations (inversion and centring folded in). :vartype ops_W: np.ndarray :ivar ops_w: ``(n, 3)`` their translations. :vartype ops_w: np.ndarray :ivar centro: The group is centrosymmetric. :vartype centro: bool :ivar ops_inv: ``(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`). :vartype ops_inv: np.ndarray :ivar sites: Asymmetric unit. :vartype sites: list[Site] :ivar kv: Accelerating voltage the Ug refer to, kV. :vartype kv: float :ivar source: Where it came from. :vartype source: str .. py:attribute:: cell :type: numpy.ndarray .. py:attribute:: A :type: numpy.ndarray .. py:attribute:: ops_W :type: numpy.ndarray .. py:attribute:: ops_w :type: numpy.ndarray .. py:attribute:: centro :type: bool .. py:attribute:: sites :type: list .. py:attribute:: kv :type: float .. py:attribute:: source :type: str :value: '' .. py:attribute:: ops_inv :type: numpy.ndarray :value: None .. py:method:: __post_init__() .. py:property:: Bstar .. py:property:: G .. py:property:: Gstar .. py:property:: omega .. py:property:: gamma .. py:property:: n_ops .. py:method:: s(hkl) ``sin(theta)/lambda`` of reflections ``(..., 3)``. .. py:method:: site(label) .. py:method:: 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. .. py:method:: with_kv(kv) Copy at another voltage (Ug scale with gamma). .. py:method:: manual(cell, ops, sites, kv, centro=None, source='manual', tol=0.0001, ops_inv=None) :classmethod: Builds a crystal without the engine. :param cell: ``a, b, c, alpha, beta, gamma``. :type cell: sequence :param ops: ``(W, w)``, the full group modulo lattice translations. :type ops: tuple :param sites: ``dict(label, xyz, beta, occ=1, element=None)``. :type sites: list[dict] :param kv: Voltage. :type kv: float :param centro: Inferred from the operations when None. :type centro: bool, optional :param ops_inv: Marks the inversion-related half of the operations (see the class attributes); none when omitted. :type ops_inv: array, optional .. py:method:: from_dat(path, labels=None, tol=0.0001) :classmethod: Snapshots a ``.dat`` file through the Bloch engine's parser. :param path: The crystal file the refinement used. :type path: path-like :param labels: Site names; ``Sr1, Ti1, O1, ...`` by default. :type labels: list[str], optional :param tol: Site-symmetry tolerance, fractional. :type tol: float .. 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. .. py:class:: Site One asymmetric-unit atom. :ivar label: Unique name, e.g. ``'Sr1'``, ``'O1'``. :vartype label: str :ivar element: Element symbol, ``'Sr'``. :vartype element: str :ivar engine_label: The label the engine used (``'SR'``, ``'TI4+'``), which decides its Cromer-Mann row. :vartype engine_label: str :ivar xyz: Fractional coordinates. :vartype xyz: np.ndarray :ivar occ: Occupancy. :vartype occ: float :ivar beta: Engine 6-vector ``(b11, b22, b33, b12, b13, b23)``. :vartype beta: np.ndarray :ivar stab: ``(m, 3, 3)`` fractional rotations that fix the site. :vartype stab: np.ndarray .. py:attribute:: label :type: str .. py:attribute:: element :type: str .. py:attribute:: engine_label :type: str .. py:attribute:: xyz :type: numpy.ndarray .. py:attribute:: occ :type: float .. py:attribute:: beta :type: numpy.ndarray .. py:attribute:: stab :type: numpy.ndarray .. py:property:: order .. py:class:: MultipoleModel(crystal, specs=()) Structure factors of a crystal under a multipole model. :param crystal: The crystal. :type crystal: Crystal :param specs: One spec per site, or ``label -> spec`` keyword dict; sites without a spec get ``AtomSpec(site)``. :type specs: list[AtomSpec] | dict .. py:attribute:: crystal .. py:attribute:: sites :value: [] .. py:attribute:: layout .. py:method:: _resolve(i, site, spec) .. py:method:: _build_layout() .. py:method:: geometry(hkl) Everything about a set of reflections that does not depend on ``p``. :param hkl: ``(nh, 3)`` reflections; ``000`` is not allowed. :type hkl: array-like :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)``). :rtype: dict .. py:method:: _beta_matrix() .. py:method:: _site_terms(p, geo, j, dtype) ``(f_sph (nh,), f_aniso (nh, nops) | None, T (nh, nops))`` of site j. .. py:method:: _crystal_sum(p, geo, electron, static) .. py:method:: ug(p, geo) Electron structure factors, Angstrom^-2 (complex). .. py:method:: fx(p, geo, static=False) X-ray structure factors, electrons (complex); ``static`` drops the ADPs. .. py:method:: electrons(p) Electrons in the cell: ``sum occ * mult * (Pc + sum Pv + P00)``. .. py:method:: nuclear_charge() .. py:method:: describe() One line per site: mode, partition, frame, allowed functions. .. py:class:: AtomSpec How one site is modelled. :ivar site: Site label in the `Crystal`. :vartype site: str :ivar mode: ``'hc'`` or ``'cm'``. :vartype mode: str :ivar bank: XD bank (``'RDF_SCM'``, ``'PBE-QZ4P-ZORA'`` or a path). :vartype bank: str :ivar key: Bank entry; the element by default. :vartype key: str, optional :ivar valence: Valence orbitals (bank default if None). :vartype valence: list[str], optional :ivar occupations: Orbital occupation overrides. :vartype occupations: dict, optional :ivar core_from: Bank entry supplying the core. :vartype core_from: str, optional :ivar shells: ``'joined'`` (one Pv for all valence orbitals) or ``'separate'``. :vartype shells: str :ivar kappa_shared: One kappa for all valence shells. :vartype kappa_shared: bool :ivar lmax: Highest deformation order, -1 for none. :vartype lmax: int :ivar n_l: Radial powers per l; `default_n_l` if None. :vartype n_l: tuple, optional :ivar zeta: 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. :vartype zeta: float | sequence, optional :ivar frame: ``(z, x)`` direct-lattice directions of the local axes; automatic if None (`jaxMultipole.symmetry.local_frame`). :vartype frame: tuple, optional .. py:attribute:: site :type: str .. py:attribute:: mode :type: str :value: 'hc' .. py:attribute:: bank :type: str :value: 'RDF_SCM' .. py:attribute:: key :type: str :value: None .. py:attribute:: valence :type: list :value: None .. py:attribute:: occupations :type: dict :value: None .. py:attribute:: core_from :type: str :value: None .. py:attribute:: shells :type: str :value: 'joined' .. py:attribute:: kappa_shared :type: bool :value: True .. py:attribute:: lmax :type: int :value: 4 .. py:attribute:: n_l :type: tuple :value: None .. py:attribute:: zeta :type: object :value: None .. py:attribute:: frame :type: tuple :value: None .. py:class:: SiteRefine Refinement switches for one site. :ivar Pv: Refine the valence population(s); a list of names (``['Pv_3d']``) refines only those shells. :vartype Pv: bool | list :ivar kappa: Refine kappa. :vartype kappa: bool :ivar kappa_p: Refine kappa'. :vartype kappa_p: bool :ivar multipoles: ``'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. :vartype multipoles: str | list :ivar U: Refine the symmetry-allowed U_ij. :vartype U: bool :ivar dpop: Refine the d shell as eg / t2g orbital populations (cubic sites only; replaces that shell's Pv and the l = 4 function). :vartype dpop: bool .. py:attribute:: Pv :type: bool :value: True .. py:attribute:: kappa :type: bool :value: True .. py:attribute:: kappa_p :type: bool :value: False .. py:attribute:: multipoles :type: object :value: 'allowed' .. py:attribute:: U :type: bool :value: True .. py:attribute:: dpop :type: bool :value: False .. py:function:: build_parameter_map(model, refine=None, neutral=True, dependent=None, start=None) Assembles the free parameters of a refinement. :param model: The model. :type model: MultipoleModel :param refine: ``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. :type refine: dict, optional :param neutral: Enforce electroneutrality. :type neutral: bool :param dependent: The population to eliminate, e.g. ``'O1.Pv'``; the last refined one by default. :type dependent: str, optional :param start: Physical starting values overriding the model's ``p0`` (``{'O1.Pv': 6.4, 'Ti1.kappa': 1.02}``). :type start: dict, optional :returns: ParameterMap .. py:class:: FitSettings Everything a `jaxMultipole.cli` run needs. :ivar dat: Crystal ``.dat`` (cell, atoms, space group, voltage). :vartype dat: str :ivar h5: Dataset HDF5 files, or glob patterns, for the per-scan runs. :vartype h5: list :ivar notes: Notes prefix selecting the runs (``'geo'``: per-scan). :vartype notes: str :ivar run: ``'latest'`` or a run key. :vartype run: str :ivar method: ``'robust'`` or ``'mean'`` aggregation (`data.from_scan_runs`). :vartype method: str :ivar clip: Robust rejection threshold, sigma. :vartype clip: float :ivar sigma: ``'std'`` or ``'sem'``. :vartype sigma: str :ivar min_n: Minimum measurements per family. :vartype min_n: int :ivar floor: ``(absolute, relative)`` sigma floor. :vartype floor: tuple :ivar joint_json: Take central values from this joint run, sigmas from the scans. :vartype joint_json: str, optional :ivar tables: Extra data, ``dict(path=..., kind='xray')``. :vartype tables: list[dict] :ivar exclude: Families to leave out, as ``[h, k, l]``. :vartype exclude: list :ivar smax: Leave out reflections beyond this s. :vartype smax: float, optional :ivar sites: ``label -> AtomSpec`` keyword dict. :vartype sites: dict :ivar fix_kappa: Sites whose kappa is never refined. :vartype fix_kappa: list[str] :ivar ladder: ``[(name, {label: SiteRefine kwargs})]``; `default_ladder` when None. :vartype ladder: list, optional :ivar ladder_kappa_p: Append a kappa' step to the default ladder. :vartype ladder_kappa_p: bool :ivar restraints: ``dict(name='Ti1.kappa_p', target=1, sigma=0.05)``. :vartype restraints: list[dict] :ivar start: Physical starting values, ``{'O1.Pv': 6.5}``. :vartype start: dict :ivar dependent: Population eliminated by electroneutrality. :vartype dependent: str, optional :ivar out: Output prefix (``.json``, ``.txt``, maps). :vartype out: str :ivar maps: Deformation-density planes: ``dict(name, origin, u, v, extent=(-2, 2, -2, 2), n=121)`` in fractional / lattice units. :vartype maps: list[dict] .. py:attribute:: dat :type: str :value: None .. py:attribute:: h5 :type: list :value: [] .. py:attribute:: notes :type: str :value: 'geo' .. py:attribute:: run :type: str :value: 'latest' .. py:attribute:: method :type: str :value: 'robust' .. py:attribute:: clip :type: float :value: 4.0 .. py:attribute:: sigma :type: str :value: 'std' .. py:attribute:: min_n :type: int :value: 3 .. py:attribute:: floor :type: tuple :value: (2e-05, 0.0) .. py:attribute:: joint_json :type: str :value: None .. py:attribute:: tables :type: list :value: [] .. py:attribute:: exclude :type: list :value: [] .. py:attribute:: smax :type: float :value: None .. py:attribute:: sites :type: dict .. py:attribute:: fix_kappa :type: list :value: [] .. py:attribute:: ladder :type: list :value: None .. py:attribute:: ladder_kappa_p :type: bool :value: False .. py:attribute:: restraints :type: list :value: [] .. py:attribute:: start :type: dict .. py:attribute:: dependent :type: str :value: None .. py:attribute:: out :type: str :value: 'multipole_fit' .. py:attribute:: maps :type: list :value: []