Components
Building blocks of metadata: operator kinds, sources, sparsity patterns, basis sets, spherical-harmonics conventions, spins, and k-points.
Source
Quoll.AbstractSource — Type
AbstractSourceAbstract supertype for format sources. Concrete subtypes (e.g. CanonicalSource, DeepHSource, FHIaimsSource) carry format-specific configuration such as the default SH convention and data layout. Used to dispatch format-specific methods throughout the pipeline.
Quoll.namedtuple — Method
namedtuple(source::AbstractSource)Convert a source's fields to a NamedTuple. Useful for forwarding source properties as keyword arguments.
OperatorKind
Quoll.OperatorKind — Type
OperatorKind{K}Identifies an operator by its kind symbol K (e.g. :Hamiltonian, :Overlap) and a set of tags stored in an unordered dictionary. Tags are key-value pairs of Symbols that distinguish variants — for example source=:ref or spin=:up. Tag order does not affect equality.
Convenience aliases: Hamiltonian = OperatorKind{:Hamiltonian}, Overlap = OperatorKind{:Overlap}.
Examples
kind = Hamiltonian(; source=:ref) # reference Hamiltonian
kind = Hamiltonian(; source=:pred, spin=:soc) # predicted SOC HamiltonianQuoll.allows_symmetry — Method
allows_symmetry(operatorkinds)
allows_symmetry(operatorkind::OperatorKind)Check whether k-point symmetry reduction is valid. Returns false if any operator has a non-trivial spin tag (:up, :down, :soc), since spin-polarised operators generally break the spatial symmetry used for k-point reduction.
Quoll.get_operator_groups — Method
get_operator_groups(op_list; op_filter=op->true, excluded_keys=nothing)Group a list of OperatorKinds by tag equality. Returns a vector of vectors, where each inner vector contains kinds that share identical tags (after filtering). Use op_filter to restrict which kinds are considered and excluded_keys to ignore specific tags during grouping.
Quoll.get_tags — Method
get_tags(kind; excluded_keys=nothing)Return the tag dictionary of an OperatorKind. If excluded_keys is provided, those keys are filtered out from the result.
Quoll.statictuple — Method
statictuple(kind::OperatorKind)Convert an OperatorKind into a tuple of Val-wrapped symbols, sorted by tag key. Used for type-stable dispatch on operator kind in format-specific methods (e.g. file name lookup).
SHConvention
Quoll.SHConvention — Type
SHConvention{lmax,T}Spherical harmonics ordering/phase convention, expressed as a transformation from the wiki (reference) ordering to a target format. For each angular momentum l, stores:
orders— permutation vector mapping wiki index → format index.shifts— precomputed index shifts for applying the permutation to a full basis.phases— sign factors (±1) applied after reordering.
Two conventions can be composed with ∘ and inverted with inv. Use isidentity to check if a convention is a no-op.
Quoll.convert_speciesdict_shconv — Method
convert_speciesdict_shconv(dict, basis, shconv)Return a deep copy of dict with per-species vectors permuted according to the SH convention. The permutation is computed from basis (via precompute_orders) and is purely positional — it depends only on the subblock l-structure, not on the current m ordering — so shconv must be the transformation from basis's current convention to the target (the target directly when basis is wiki-ordered, or the delta target ∘ inv(current) otherwise). The in-place variant convert_speciesdict_shconv! modifies dict directly.
Quoll.isidentity — Method
isidentity(shconv::SHConvention) -> BoolReturn true if the convention is a no-op (identity ordering with all-positive phases).
Quoll.precompute_orders — Method
precompute_orders(basis, shconv) -> ImmutableDictPrecompute per-species permutation vectors for the full basis set under the given SH convention. Unlike get_order (which operates within a single angular-momentum subblock), these are global indices into the species' basis.
Quoll.precompute_shifts — Method
precompute_shifts(basis, shconv) -> ImmutableDictPrecompute per-species index shift vectors for applying the SH convention to a full basis set.
Quoll.precompute_shphases — Method
precompute_shphases(basis, shconv, Val(D)=Val(1), T=Float64)Precompute per-species sign phase vectors (±1) for the SH convention. When D=1, returns a per-species dictionary of vectors. When D=2, returns a per-species-pair dictionary of outer-product phase matrices (used for matrix-valued data).
Quoll.precompute_signed_perm_matrices — Method
precompute_signed_perm_matrices(basis, shconv, T=Float64)Compute per-species signed permutation matrices for the SH convention. An SH conversion of a matrix M_{z₁z₂} can be performed as P_{z₁} * M_{z₁z₂} * P_{z₂}ᵀ.
Basis
Quoll.BasisMetadata — Type
BasisMetadata{E}Metadata for a single basis function: chemical species z, principal quantum number n, angular momentum l, magnetic quantum number m (always in wiki SH convention), and optional extras (e.g. degeneracy labels). Two BasisMetadata are equal if all fields match; they share_subblock if everything except m matches.
Quoll.BasisSetMetadata — Type
BasisSetMetadata{B,A}A basis set. Contains a basis dictionary mapping each ChemicalSpecies to its vector of BasisMetadata entries, and an atom2species vector mapping atom indices to species.
Quoll.cast_basisset — Method
cast_basisset(out_basisset, in_basisset) -> BasisSetMetadataReturn a copy of out_basisset whose principal quantum numbers n and extras have been taken from in_basisset, matched subblock by subblock.
This is a metadata re-labelling, not a conversion. It assumes out_basisset and in_basisset describe the same physical basis set and differ only in how much metadata each format preserved (e.g. DeepH dumps lose the true n and the orbital-type extras that FHI-aims keeps). Subblock i of out_basisset unconditionally receives the n and extras of subblock i of in_basisset. If the two basis sets are not in fact the same, or if their subblocks are ordered differently, the transferred metadata is silently wrong.
Preserved from out_basisset: z, l, m, the ordering of the basis functions (and hence its spherical harmonics convention) and atom2species.
extras are merged, not overwritten: out_basisset's entries are kept — except :dgen, which is dropped because it labels a degeneracy of the n being replaced — and in_basisset's entries, including its :dgen, are laid on top. A key present in both with differing values is taken from in_basisset and warned about, since it suggests the two basis sets are not really the same.
Throws ArgumentError if the two are structurally incompatible: differing species, atom2species, number of subblocks, subblock angular momenta, or subblock m values.
See also same_basisset, convert_basisset_shconv.
Quoll.compatible_extras — Method
compatible_extras(extras1, extras2) -> BoolReturn true if two extras payloads do not contradict each other: every key present in both must map to equal values. Keys present in only one of them are allowed, and nothing (no extras) is compatible with anything.
Quoll.convert_basisset_shconv — Method
convert_basisset_shconv(basisset, shconv) -> BasisSetMetadataReorder each species' basis functions by the positional permutation of shconv, applied per angular momentum subblock. The reordering is purely positional — it depends only on the subblock l-structure, not on the current m ordering — so shconv must be the transformation from the input basis's current convention to the target. Pass the target convention directly when the input is wiki-ordered (as the format loaders do), or the delta target ∘ inv(current) when the input is already in some convention (as convert_metadata_basic does).
Quoll.get_angular_momenta — Method
get_angular_momenta(basis) -> Vector{Int}Return the angular momentum l of each subblock's representative basis function.
Quoll.get_atom2basis — Method
get_atom2basis(basisset) -> Vector{UnitRange{Int}}Return the global basis function index range for each atom.
Quoll.get_atom2nbasis — Method
get_atom2nbasis(basisset) -> Vector{Int}Return the number of basis functions per atom.
Quoll.get_atom2offset — Method
get_atom2offset(basisset) -> Vector{Int}Return the cumulative basis function offset for each atom (number of basis functions belonging to atoms with lower index).
Quoll.get_basis2atom — Method
get_basis2atom(basisset) -> Vector{Int}Return the atom index for each global basis function index.
Quoll.get_dense_subbasis_mask — Method
get_dense_subbasis_mask(basisset, subbasis; inverted=false) -> BitVector
get_dense_subbasis_mask(basisset, subbasis_masks) -> BitVectorFlatten per-species subbasis masks into a single BitVector over all atoms (following atom2species ordering), suitable for indexing into dense matrices.
Quoll.get_indices_in_subblock — Method
get_indices_in_subblock(basisset::BasisSetMetadata)
get_indices_in_subblock(basis_z::AbstractVector{<:BasisMetadata})Return the 1-based position of each basis function within its subblock. Unlike m, this reflects the actual ordering after SH convention reordering.
Quoll.get_species2nbasis — Method
get_species2nbasis(basisset) -> ImmutableDict{ChemicalSpecies, Int}Return the number of basis functions per chemical species.
Quoll.get_subbasis_masks — Method
get_subbasis_masks(basisset, subbasis; inverted=false) -> Dictionary{ChemicalSpecies, BitVector}Compute per-species boolean masks indicating which basis functions belong to subbasis. If inverted=true, the masks select the complement (i.e. everything not in subbasis).
Quoll.get_subblock_ranges — Method
get_subblock_ranges(basisset::BasisSetMetadata)
get_subblock_ranges(basis_z::AbstractVector{<:BasisMetadata})Return contiguous index ranges for each angular momentum subblock. The BasisSetMetadata form returns a Dictionary{ChemicalSpecies, Vector{UnitRange{Int}}}. It is assumed that all basis functions belonging to a sublock are next to each other.
Quoll.is_arbitrary_degeneracy — Method
is_arbitrary_degeneracy(basisset) -> Bool
is_arbitrary_degeneracy(basis_z) -> BoolCheck whether any species has multiple subblocks sharing the same (n, l) quantum numbers.
Quoll.lift_arbitrary_degeneracy — Method
lift_arbitrary_degeneracy(basis)
lift_arbitrary_degeneracy(basis_z)When multiple subblocks share the same (z, n, l) (arbitrary degeneracy), add a :dgen label to the extras field of each basis function to distinguish them.
Quoll.reduce_basisset — Method
reduce_basisset(basisset, subbasis; inverted=false) -> BasisSetMetadata
reduce_basisset(basisset, subbasis_masks) -> BasisSetMetadataReturn a new BasisSetMetadata containing only the basis functions selected by subbasis (a vector of BasisMetadata to keep). If inverted=true, keep the complement instead. The second form accepts precomputed per-species BitVector masks.
Quoll.same_basisset — Method
same_basisset(bs1::BasisSetMetadata, bs2::BasisSetMetadata) -> BoolReturn true if bs1 and bs2 describe the same set of basis functions, allowing:
- a difference in the ordering of the magnetic quantum numbers
mwithin each angular momentum subblock (legitimate when the two basis sets use different spherical harmonics conventions), and extrasentries present on one side but not the other (legitimate aftercast_basisset, which may leave the result carrying more extras than its source). Keys present in both must agree — seecompatible_extras.
z, n, l and m must match exactly, as must atom2species, the species, and — per species — the subblock structure.
Via share_subblock, extras also decide where subblock boundaries fall, and each basis set is decomposed independently. An extras key present on only one side can therefore split a subblock the other side keeps merged, in which case the subblock structures differ and this returns false even though every basis function is extras-compatible. This needs unlifted arbitrary degeneracy to arise (see lift_arbitrary_degeneracy), and cast_basisset rejects such pairs up front, so it is rare in practice.
Quoll.share_subblock — Method
share_subblock(b1::BasisMetadata, b2::BasisMetadata) -> BoolReturn true if b1 and b2 belong to the same angular momentum subblock (same species, n, l, and extras — only m may differ).
Spin
Quoll.Spin — Type
SpinEnum with values ⬆ (+1) and ⬇ (−1) representing spin-up and spin-down channels.
Quoll.SpinsMetadata — Type
SpinsMetadata{S}Per-species spin assignment for each basis function.
Fields:
spins::S— species-keyed dictionary mapping each species to a vector ofSpinvalues (one per basis function). For SOC, each species' vector is doubled.soc::Bool—trueif this represents spin-orbit coupling (basis doubled per species).
Quoll.SpinsMetadata — Method
SpinsMetadata(source, kind, basisset)Construct SpinsMetadata from an operator kind's :spin tag. Dispatches on the spin tag value (:up, :down, :soc) to build the appropriate per-species spin vectors.
Quoll.convert_spins_shconv — Method
convert_spins_shconv(spins, basisset, shconv)Reorder spin vectors to match a new SH convention, preserving the spin-basis correspondence.
Quoll.convert_spins_source — Function
convert_spins_source(in_spins, out_basisset, in_source, out_source)Make final changes due to the source change (e.g. reorder up and down spins if the two sources don't agree). This often might leave the spins unchanged.
Quoll.reduce_spins — Method
reduce_spins(spins, basisset, subbasis; inverted=false)Restrict spin metadata to a sub-basis, keeping only the spin entries corresponding to the retained basis functions.
Sparsity
Quoll.AbstractSparsity — Type
AbstractSparsityAbstract supertype for all sparsity patterns. All concrete subtypes store a hermitian flag (accessible via op_hermicity) and, for real-space types, an images vector of lattice translation vectors.
Quoll.BlockRealSparsity — Type
BlockRealSparsityReal-space sparsity resolved per atom pair. ij2images maps each atom pair (i, j) to the lattice translations R for which that block is retained, and images is the union of all such translations. This is the sparsity of the canonical block-real operator format and the layout its data follows.
When hermitian is true, only j ≥ i atom pairs are stored (off-site partners follow by Hermitian conjugation), while on-site pairs keep every image (both R and -R). See SubBlockRealSparsity for the finer, angular-momentum-subblock-resolved variant.
Quoll.SubBlockRealSparsity — Type
SubBlockRealSparsityReal-space sparsity resolved down to angular momentum subblocks. On top of the atom-pair image lists of BlockRealSparsity (ij2images, which still describes the atom-pair level and the data layout), ij2isbjsb2images maps each atom pair (i, j) to a dictionary keyed by subblock index pairs (isb, jsb), each holding the images for which that particular subblock pair is within its own cutoff. Every basis function of a subblock shares one cutoff, so a subblock is the finest resolution of this pattern.
Subblock indices count the angular momentum subblocks of the atom's species in basis set order, i.e. they index into get_subblock_ranges(basisset)[z]: isb indexes the subblocks of atom i and jsb those of atom j.
Hermicity follows the same convention as BlockRealSparsity: only j ≥ i atom pairs are stored, and on-site pairs keep every image (both R and -R). In addition, on-site pairs only store jsb ≥ isb subblock pairs; the remaining ones follow from (jsb, isb) at -R. No information is lost, because the interatomic distance does not depend on the subblock, which makes the on-site subblock pattern symmetric in (isb, jsb).
Build one with build_sparsity from per-subblock radii (one cutoff vector per species) or from a BasisSetMetadata carrying :radius extras.
Quoll.build_sparsity — Method
build_sparsity(::Type{S}, atoms, radii; hermitian=false)
build_sparsity(::Type{S}, atoms, basisset; hermitian=false)Build a sparsity pattern of type S from an atomic system and interaction radii. Constructs a neighbour list — whose cutoff is derived from radii via get_maxedges and get_nlist_cut — and retains pairs within the sum of their radii.
radii may be:
- per-species: a dictionary of one scalar cutoff per
ChemicalSpecies. Builds an atom-pair resolved pattern, e.g. aBlockRealSparsity. - per-subblock: a dictionary of one cutoff vector per species (one entry per angular momentum subblock, in basis set order; see
get_subblock_radii). Required to build a subblock resolvedSubBlockRealSparsity; per-species scalar radii cannot convey how many subblocks a species has and are rejected for that type.
The basisset form reads per-subblock radii off the basis functions' :radius extras and forwards to the radii form — a convenience for callers that keep cutoffs on the basis set rather than passing them separately. Radii without units are assumed to be in Å.
Quoll.convert_sparsity — Method
convert_sparsity(::Type{Sₒᵤₜ}, in_sparsity, basisset; hermitian=false)Convert a sparsity pattern to type Sₒᵤₜ, optionally changing hermicity. When input and output types match, only the hermicity is adjusted. Cross-type conversions (e.g. CSCRealSparsity → BlockRealSparsity, BlockRealSparsity → DenseRecipSparsity) are also supported.
Quoll.get_iglobal2ilocal — Method
get_iglobal2ilocal(sparsity::BlockRealSparsity)Return per-pair index maps from global image indices to local image indices in ij2images.
Quoll.get_subblock_radii — Method
get_subblock_radii(basisset) -> Dictionary{ChemicalSpecies,Vector}
get_subblock_radii(basis_z) -> VectorReturn the interaction radius of every angular momentum subblock, read from the :radius entry of the extras field of its basis functions. Radii are given per subblock because all basis functions of a subblock share one radius — share_subblock compares extras, so a differing radius would place the basis functions in different subblocks to begin with.
Values may be numbers (optionally with units) or Symbols / strings parsed as Float64; those without units are assumed to be in Å. Throws an ArgumentError if a subblock carries no :radius.
K-points
Quoll.KGrid — Type
KGrid{T,W}Container for an irreducible k-point grid with integration weights.
Fields:
kpoints::T— collection of irreducible k-point coordinate vectors (fractional).weights::W— integration weights summing to 1.time_reversal::Bool— whether time-reversal symmetry was used to reduce the grid.crystal_symmetry::Bool— whether crystal point-group symmetry was used to reduce the grid.
Quoll.KGridSymmetry — Type
KGridSymmetry{TimeReversal,Crystal}Holy-trait singleton encoding which symmetries were used to reduce a k-point grid. The two Bool type parameters (time-reversal and crystal point-group symmetry) are independent and can both be active. It is used to select the correct contraction in the inverse Fourier transform, where the way the full real-space matrix is reconstructed from irreducible k-points depends on the reduction symmetry. See grid_symmetry.
Quoll.construct_kgrid — Method
construct_kgrid(atoms; density, mesh, shift, time_reversal, crystal_symmetry, symprec)Build an irreducible k-point grid for the given atomic system using Spglib.
Returns a KGrid with irreducible k-points and integration weights. The grid is reduced using the requested symmetries and validated by checking that all reducible k-points can be regenerated. Falls back to no symmetries if validation fails.
The function works only for periodic, or fully non-periodic systems (in which case a gamma point is returned).
The implementation is inspired by DFTK.jl.
Keyword arguments
density=nothing— reciprocal-space density (points per Å⁻¹ per axis). Ignored ifmeshis given.mesh=nothing— explicit Monkhorst–Pack grid dimensions[n₁, n₂, n₃]. Takes priority overdensity.shift=falses(3)— half-grid shift per axis (trueshifts by half a grid spacing).time_reversal=false— exploit time-reversal symmetry (k ↔ −k) to further reduce the grid.crystal_symmetry=false— exploit crystal point-group symmetry to reduce the grid.symprec=1e-5— symmetry detection tolerance (Å) passed to Spglib.
Quoll.grid_symmetry — Method
grid_symmetry(kgrid::KGrid) -> KGridSymmetryMap a KGrid's reduction flags to the corresponding KGridSymmetry trait singleton.
Quoll.normalize_kpoint_coordinate — Method
normalize_kpoint_coordinate(k)Wrap fractional k-point coordinates into the range [-0.5, 0.5). Accepts a scalar or vector.
Quoll.precompute_phases — Method
precompute_phases(kpoints, images) -> Matrix{ComplexF64}Compute Bloch phase factors $e^{2πi \mathbf{T} \cdot \mathbf{k}}$ for all image–k-point pairs. Returns a (nimages, nkpoints) matrix.