8 USE ieee_arithmetic,
ONLY: ieee_quiet_nan,&
10 USE iso_fortran_env,
ONLY: output_unit
18 COMPLEX(KIND=dp) :: table(6, 3), group_chars(6), metric(2, 2), coeff(4, 4), phase(2), tmp(4)
19 REAL(kind=
dp) :: error, energy_error, energies(4)
20 INTEGER :: multiplicities(3), status, counts(2), odd(8), ebr(2, 8), a, k, sign, strong, weak(3), z4, io_unit
21 LOGICAL :: signed_atomic, nonnegative_atomic
25 table(:, 1) = cmplx([1, 1, 1, 1, 1, 1], 0,
dp)
26 table(:, 2) = cmplx([1, 1, 1, -1, -1, -1], 0,
dp)
27 table(:, 3) = cmplx([2, -1, -1, 0, 0, 0], 0,
dp)
28 group_chars = table(:, 1) + 2*table(:, 3)
30 IF (status /= 0 .OR. any(multiplicities /= [1, 0, 2])) error stop
'C3v decomposition failed'
31 group_chars(2) = group_chars(2) + 0.1_dp
33 IF (status == 0) error stop
'Invalid character accepted'
34 metric = cmplx(0, 0,
dp)
37 coeff = cmplx(0, 0,
dp)
38 coeff(1, 1) = sqrt(0.5_dp)
39 coeff(2, 2) = sqrt(2.0_dp)
40 coeff(3, 3) = sqrt(0.5_dp)
41 coeff(4, 4) = sqrt(2.0_dp)
42 phase = cmplx([1, -1], 0,
dp)
45 1.e-9_dp, 1.e-9_dp, counts, error, energy_error, status)
46 IF (status /= 0 .OR. any(counts /= [2, 2])) error stop
'Metric/spinor parity failed'
48 coeff(:, 1) = (tmp + cmplx(0, 1,
dp)*coeff(:, 2))/sqrt(2.0_dp)
49 coeff(:, 2) = (cmplx(0, 1,
dp)*tmp + coeff(:, 2))/sqrt(2.0_dp)
51 1.e-9_dp, 1.e-9_dp, counts, error, energy_error, status)
52 IF (status /= 0 .OR. any(counts /= [2, 2])) error stop
'Degenerate-gauge parity failed'
54 1.e-9_dp, 1.e-9_dp, counts, error, energy_error, status)
55 IF (status == 0) error stop
'Nonclosed parity subspace accepted'
57 1.e-9_dp, 1.e-9_dp, counts, error, energy_error, status)
58 IF (status == 0) error stop
'Broken physical time reversal accepted'
61 1.e-9_dp, 1.e-9_dp, counts, error, energy_error, status)
62 IF (status == 0) error stop
'Noncommuting eigenspace accepted'
64 metric = cmplx(0.2_dp, 0,
dp)
67 coeff(:2, 1) = cmplx([1.0_dp, 1.0_dp]/sqrt(2.4_dp), 0,
dp)
68 coeff(:2, 2) = cmplx([1.0_dp, -1.0_dp]/sqrt(1.6_dp), 0,
dp)
69 phase = cmplx(1, 0,
dp)
71 1.e-9_dp, 1.e-9_dp, counts, error, energy_error, status)
72 IF (status /= 0 .OR. any(counts /= [1, 1])) error stop
'Scalar two-site inversion failed'
74 1.e-9_dp, 1.e-9_dp, counts, error, energy_error, status)
75 IF (status /= 0 .OR. any(counts /= [0, 1])) error stop
'Zone-boundary inversion phase failed'
76 metric(1, 2) = cmplx(0.2_dp, 0.01_dp,
dp)
78 1.e-9_dp, 1.e-9_dp, counts, error, energy_error, status)
79 IF (status == 0) error stop
'Invalid metric accepted'
80 metric(1, 2) = cmplx(ieee_value(0.0_dp, ieee_quiet_nan), 0,
dp)
82 1.e-9_dp, 1.e-9_dp, counts, error, energy_error, status)
83 IF (status == 0) error stop
'Nonfinite metric accepted'
87 odd(k + 1) = (1 - sign*(-1)**popcnt(iand(a, k)))/2
90 IF (status /= 0 .OR. strong /= 0 .OR. any(weak /= 0) .OR. z4 /= 0) error stop
'Atomic indicator failed'
92 IF (status /= 0 .OR. .NOT. nonnegative_atomic .OR. .NOT. signed_atomic) error stop
'Atomic EBR failed'
93 IF (sum(ebr) /= 1) error stop
'EBR rank failed'
99 IF (status /= 0 .OR. strong /= 1 .OR. z4 /= 1) error stop
'Strong index failed'
101 IF (status /= 0 .OR. signed_atomic .OR. nonnegative_atomic) error stop
'Stable obstruction missed'
104 IF (status /= 0 .OR. strong /= 0 .OR. z4 /= 2) error stop
'Inversion Z4=2 missed'
107 IF (status /= 0 .OR. .NOT. signed_atomic .OR. nonnegative_atomic) error stop
'Signed-only EBR missed'
110 IF (status == 0) error stop
'Invalid multiplicity accepted'
113 WRITE (io_unit, *)
'Native characters, parity, inversion indicators and EBR tests passed.'
121 INTEGER,
INTENT(IN) :: dimension
123 INTEGER :: code, digit, i, ierr, indicator, indices(3), j, n, nu, x, y, &
124 values(2**DIMENSION), signatures(2**DIMENSION, 2**(DIMENSION + 1)), &
125 reconstructed(2**DIMENSION), coefficients(2, 2**DIMENSION)
126 LOGICAL :: indicators_zero, nonnegative_ok, possible(0:3**(2**DIMENSION) - 1), signed_ok
131 signatures(i + 1, 2*x + 1) = (1 - (-1)**popcnt(iand(x, i)))/2
132 signatures(i + 1, 2*x + 2) = 1 - signatures(i + 1, 2*x + 1)
138 code = sum((signatures(:, x) + signatures(:, y))*[(3**i, i=0, n - 1)])
139 possible(code) = .true.
142 DO code = 0, 3**n - 1
145 values(i) = mod(digit, 3)
149 IF (ierr /= 0 .OR. (nonnegative_ok .NEQV. possible(code))) error stop
'Enumerated EBR mismatch'
151 IF (ierr /= 0) error stop
'Enumerated indicator failure'
152 indicators_zero = nu == 0
153 IF (dimension == 3) indicators_zero = indicator == 0 .AND. all(indices == 0)
154 IF (signed_ok .NEQV. indicators_zero) error stop
'Indicator/atomic-lattice mismatch'
155 IF (.NOT. nonnegative_ok) cycle
158 reconstructed = reconstructed + coefficients(1, j)*signatures(:, 2*j - 1) + &
159 coefficients(2, j)*signatures(:, 2*j)
161 IF (any(reconstructed /= values) .OR. sum(coefficients) /= 2) error stop
'EBR reconstruction failed'
Defines the basic variable types.
integer, parameter, public dp
Native character decomposition and metric-aware inversion representations.
subroutine, public inversion_representation(metric, coeff, mapping, phase, energies, check_tr, tolerance, energy_tolerance, counts, error, energy_error, status, diagnostics)
Inversion irreps of an isolated scalar or spinor eigenspace in an AO metric.
subroutine, public character_multiplicities(character, table, multiplicities, tolerance, status)
Decompose a character against a complete unitary character table.
Exact inversion-subgroup EBR and symmetry-indicator analysis (spinful TR).
subroutine, public inversion_indicators(odd, pairs, dimension, strong, weak, z4, status)
Fu–Kane indices and inversion indicator with an explicit sign convention.
subroutine, public inversion_ebr_signature(odd, pairs, signed_atomic, nonnegative_atomic, coefficients, status)
Exact signed/nonnegative EBR-signature test for the inversion subgroup.
program topology_symmetry_unittest
subroutine exhaustive_signatures(dimension)
Compare the exact solver against independent enumeration of rank-two atomic sums.