PAOFLOW.hamiltonian.pao_sym#

pao_sym — Crystal symmetry engine for PAO Hamiltonian expansion.

This module implements the full symmetry workflow that expands the PAO Hamiltonian from the irreducible Brillouin zone (IBZ) wedge to the complete uniform k-grid. It is the core symmetry back-end called by pao_hamiltonian() and is MPI-parallel throughout.

Overview#

The workflow exposed by open_grid_wrapper() proceeds in the following stages:

  1. Wigner-D matrices (get_wigner(), get_wigner_so()) — For each space-group rotation, the \(D^{(l)}\) matrices are built via the ZYZ-convention Euler-angle decomposition (mat2eul(), eul2mat(), d_mat_l()) and converted from the quantum-mechanics \(|lm\rangle\) basis to the chemistry real-orbital basis (get_trans(), convert_wigner_d()). Spin–orbit variants (get_wigner_so()) handle half-integer \(j\) channels.

  2. Unitary transformation matrices (build_U_matrix()) — The per-symop block-diagonal \(U\) matrices are assembled from the \(D^{(l)}\) blocks. Atom-permutation phases from symmetry-equivalent Wyckoff sites are folded in via map_equiv_atoms(), get_phase_shifts(), and add_U_wyc(). Time-reversal partners are handled by get_U_TR() and add_U_TR().

  3. IBZ → full-grid expansion (wedge_to_grid()) — For each k-point in the full grid, the symmetry operation and originating IBZ k-point are identified by find_equiv_k(); the corresponding Hamiltonian is transformed as

    \[H(\mathbf{k}') = U(\mathbf{k})\,H(\mathbf{k})\,U^\dagger(\mathbf{k})\]

    with k-dependent phase factors from get_U_k(). Inversion and time-reversal anti-unitarity are applied where required.

  4. Symmetrisation (symmetrize_grid(), symmetrize_grid_nspin2()) — An optional iterative symmetrisation loop averages H(k) over all symmetry-equivalent images and alternates between the original and an upsampled interpolated grid (via zero_pad()) until the maximum symmetry residual falls below symm_thresh.

  5. Time-reversal and Hermiticity enforcement (enforce_t_rev(), enforce_hermaticity()) — Final passes ensure \(H(\mathbf{k}) = H^\dagger(\mathbf{k})\) and \(H(\mathbf{k}) = H^*(-\mathbf{k})\) as required by crystal symmetry.

Entry points#

open_grid_wrapper()

High-level DataController-based interface; unpacks all arrays/attributes and dispatches to open_grid() (nspin=1, with or without SOC) or open_grid_nspin2() (collinear spin-polarised).

Utility functions#

get_full_grid()

Generate a uniform Monkhorst–Pack grid in crystal fractional coordinates.

correct_roundoff()

Zero-out floating-point noise near exact crystallographic values.

LPF() / down_samp()

Low-pass filter and down-sample routines for FFT-based grid interpolation.

get_inv_op()

Build the real-space parity operator \((-1)^l\) acting on the PAO basis.

MPI parallelism#

k-point loops in the expansion and symmetrisation stages are distributed over MPI ranks using scatter_full() and gather_full(). Rank 0 collects and broadcasts the final full-grid Hamiltonian.

Attributes#

Functions#

check(Hksp_s, si_per_k, new_k_ind, orig_k_ind, ...)

LPF(aux, nk1, nk2, nk3, nfft1, nfft2, nfft3)

Pad frequency domain with zeroes, such that any relationship between

down_samp(aux, nk1, nk2, nk3, nfft1, nfft2, nfft3)

Pad frequency domain with zeroes, such that any relationship between

map_equiv_atoms(a_index, map_ind)

get_U_TR(jchia)

add_U_TR(U, sym_TR, jchia)

get_trans()

d_mat_l(AL, BE, GA, l)

get_wigner(symop)

get_wigner_so(symop)

convert_wigner_d(wigner)

eul2mat(ALPHA, BETA, GAMMA)

mat2eul(R)

find_equiv_k(kp, symop, full_grid, sym_TR[, check, ...])

build_U_matrix(wigner, shells)

get_phase_shifts(atom_pos, symop, equiv_atom)

get_U_k(k, shift, a_index, U)

correct_roundoff(arr[, incl_hex, atol])

get_full_grid(nk1, nk2, nk3, o1, o2, o3)

get_inv_op(shells)

enforce_t_rev(Hksp_s, nk1, nk2, nk3, spin_orb, U_inv, ...)

apply_t_rev(Hksp, kp, spin_orb, U_inv, jchia)

enforce_hermaticity(Hksp)

add_U_wyc(U, U_wyc)

wedge_to_grid(Hksp, U, a_index, phase_shifts, kp, ...)

open_grid(Hksp, full_grid, kp, symop, symop_cart, ...)

open_grid_nspin2(Hksp, full_grid, kp, symop, ...)

open_grid_wrapper(data_controller)

Expand the IBZ-wedge k-space arrays in data_controller to the

symmetrize(Hksp, U, a_index, phase_shifts, new_k_ind, ...)

symmetrize_grid(Hksp, U, a_index, phase_shifts, ...)

symmetrize_grid_nspin2(Hksp, U, a_index, phase_shifts, ...)

correct_roundoff_kp(kp, full_grid)

Module Contents#

PAOFLOW.hamiltonian.pao_sym.comm[source]#
PAOFLOW.hamiltonian.pao_sym.rank[source]#
PAOFLOW.hamiltonian.pao_sym.check(Hksp_s, si_per_k, new_k_ind, orig_k_ind, phase_shifts, U, a_index, inv_flag, equiv_atom, kp, symop, fg, isl, sym_TR)[source]#
PAOFLOW.hamiltonian.pao_sym.LPF(aux, nk1, nk2, nk3, nfft1, nfft2, nfft3)[source]#
Pad frequency domain with zeroes, such that any relationship between

aux[k] and aux[N-k] is preserved.

Arguments:

aux (ndarray): unpadded frequency domain data nk1 (int): current size of aux along axis 0 nk2 (int): current size of aux along axis 1 nk3 (int): current size of aux along axis 2 nfft1 (int): number of zeroes to pad axis 0 by nfft1 (int): number of zeroes to pad axis 1 by nfft1 (int): number of zeroes to pad axis 2 by

Returns:

auxp3 (ndarray): padded frequency domain data

PAOFLOW.hamiltonian.pao_sym.down_samp(aux, nk1, nk2, nk3, nfft1, nfft2, nfft3)[source]#
Pad frequency domain with zeroes, such that any relationship between

aux[k] and aux[N-k] is preserved.

Arguments:

aux (ndarray): unpadded frequency domain data nk1 (int): current size of aux along axis 0 nk2 (int): current size of aux along axis 1 nk3 (int): current size of aux along axis 2 nfft1 (int): number of zeroes to pad axis 0 by nfft1 (int): number of zeroes to pad axis 1 by nfft1 (int): number of zeroes to pad axis 2 by

Returns:

auxp3 (ndarray): padded frequency domain data

PAOFLOW.hamiltonian.pao_sym.map_equiv_atoms(a_index, map_ind)[source]#
PAOFLOW.hamiltonian.pao_sym.get_U_TR(jchia)[source]#
PAOFLOW.hamiltonian.pao_sym.add_U_TR(U, sym_TR, jchia)[source]#
PAOFLOW.hamiltonian.pao_sym.get_trans()[source]#
PAOFLOW.hamiltonian.pao_sym.d_mat_l(AL, BE, GA, l)[source]#
PAOFLOW.hamiltonian.pao_sym.get_wigner(symop)[source]#
PAOFLOW.hamiltonian.pao_sym.get_wigner_so(symop)[source]#
PAOFLOW.hamiltonian.pao_sym.convert_wigner_d(wigner)[source]#
PAOFLOW.hamiltonian.pao_sym.eul2mat(ALPHA, BETA, GAMMA)[source]#
PAOFLOW.hamiltonian.pao_sym.mat2eul(R)[source]#
PAOFLOW.hamiltonian.pao_sym.find_equiv_k(kp, symop, full_grid, sym_TR, check=True, include_self=False)[source]#
PAOFLOW.hamiltonian.pao_sym.build_U_matrix(wigner, shells)[source]#
PAOFLOW.hamiltonian.pao_sym.get_phase_shifts(atom_pos, symop, equiv_atom)[source]#
PAOFLOW.hamiltonian.pao_sym.get_U_k(k, shift, a_index, U)[source]#
PAOFLOW.hamiltonian.pao_sym.correct_roundoff(arr, incl_hex=False, atol=1e-08)[source]#
PAOFLOW.hamiltonian.pao_sym.get_full_grid(nk1, nk2, nk3, o1, o2, o3)[source]#
PAOFLOW.hamiltonian.pao_sym.get_inv_op(shells)[source]#
PAOFLOW.hamiltonian.pao_sym.enforce_t_rev(Hksp_s, nk1, nk2, nk3, spin_orb, U_inv, jchia)[source]#
PAOFLOW.hamiltonian.pao_sym.apply_t_rev(Hksp, kp, spin_orb, U_inv, jchia)[source]#
PAOFLOW.hamiltonian.pao_sym.enforce_hermaticity(Hksp)[source]#
PAOFLOW.hamiltonian.pao_sym.add_U_wyc(U, U_wyc)[source]#
PAOFLOW.hamiltonian.pao_sym.wedge_to_grid(Hksp, U, a_index, phase_shifts, kp, new_k_ind, orig_k_ind, si_per_k, inv_flag, U_inv, sym_TR, spin_orb, npool)[source]#
PAOFLOW.hamiltonian.pao_sym.open_grid(Hksp, full_grid, kp, symop, symop_cart, atom_pos, shells, a_index, equiv_atom, nk1, nk2, nk3, o1, o2, o3, spin_orb, sym_TR, jchia, mag_calc, symm_grid, thresh, max_iter, verbose, npool)[source]#
PAOFLOW.hamiltonian.pao_sym.open_grid_nspin2(Hksp, full_grid, kp, symop, symop_cart, atom_pos, shells, a_index, equiv_atom, nk1, nk2, nk3, o1, o2, o3, sym_TR, symm_grid, thresh, max_iter, verbose, npool)[source]#
PAOFLOW.hamiltonian.pao_sym.open_grid_wrapper(data_controller)[source]#

Expand the IBZ-wedge k-space arrays in data_controller to the full Brillouin zone.

Always expands Hks. If Sks is present in data_arrays (i.e. save_overlaps=True / ACBN0 path) it is expanded too, using the same symmetry rotations. Spin-independent operators (such as Sks) are handled by temporarily adding a singleton spin axis.

PAOFLOW.hamiltonian.pao_sym.symmetrize(Hksp, U, a_index, phase_shifts, new_k_ind, orig_k_ind, si_per_k, inv_flag, U_inv, sym_TR, spin_orb, full_grid, reverse=False)[source]#
PAOFLOW.hamiltonian.pao_sym.symmetrize_grid(Hksp, U, a_index, phase_shifts, inv_flag, U_inv, sym_TR, full_grid, jchia, spin_orb, mag_calc, nk1, nk2, nk3, nkl, partial_grid, npool)[source]#
PAOFLOW.hamiltonian.pao_sym.symmetrize_grid_nspin2(Hksp, U, a_index, phase_shifts, inv_flag, U_inv, sym_TR, full_grid, nk1, nk2, nk3, nkl, partial_grid, npool)[source]#
PAOFLOW.hamiltonian.pao_sym.correct_roundoff_kp(kp, full_grid)[source]#