(git:f2099e5)
Loading...
Searching...
No Matches
topology_symmetry.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief Native character decomposition and metric-aware inversion representations.
10! **************************************************************************************************
12 USE ieee_arithmetic, ONLY: ieee_is_finite
13 USE kinds, ONLY: dp
14
15 IMPLICIT NONE
16 PRIVATE
18CONTAINS
19
20! **************************************************************************************************
21!> \brief Decompose a character against a complete unitary character table.
22!> \param CHARACTER One character per group element (not per conjugacy class)
23!> \param table Characters, group element first and irrep second; identity first
24!> \param multiplicities Nonnegative integer multiplicities, invalid unless status=0
25!> \param tolerance Absolute numerical tolerance
26!> \param status Zero on success, negative for invalid/incomplete/nonintegral data
27!> \note All projective irreps must use the same factor system. This kernel does not
28!> infer a space group or certify the supplied character table's provenance.
29! **************************************************************************************************
30 SUBROUTINE character_multiplicities(CHARACTER, table, multiplicities, tolerance, status)
31 COMPLEX(KIND=dp), INTENT(IN) :: character(:), table(:, :)
32 INTEGER, INTENT(OUT) :: multiplicities(:)
33 REAL(kind=dp), INTENT(IN) :: tolerance
34 INTEGER, INTENT(OUT) :: status
35
36 COMPLEX(KIND=dp) :: value
37 INTEGER :: dimension, i, j, nirrep, order, total
38
39 status = -1
40 multiplicities = -1
41 order = SIZE(character)
42 nirrep = SIZE(table, 2)
43 IF (order < 1 .OR. order > 1024 .OR. nirrep < 1 .OR. SIZE(table, 1) /= order) RETURN
44 IF (SIZE(multiplicities) /= nirrep .OR. tolerance <= 0.0_dp) RETURN
45 IF (.NOT. ieee_is_finite(tolerance)) RETURN
46 IF (.NOT. all(ieee_is_finite(real(CHARACTER, dp)))) return
47 IF (.NOT. all(ieee_is_finite(aimag(character)))) RETURN
48 IF (.NOT. all(ieee_is_finite(real(table, dp)))) RETURN
49 IF (.NOT. all(ieee_is_finite(aimag(table)))) RETURN
50 IF (maxval(abs(table)) > real(order, dp) + tolerance) RETURN
51 IF (maxval(abs(character)) > 1.e6_dp) RETURN
52 total = 0
53 DO i = 1, nirrep
54 dimension = nint(real(table(1, i), dp))
55 IF (dimension < 1 .OR. dimension > order) RETURN
56 IF (abs(table(1, i) - dimension) > tolerance) RETURN
57 total = total + dimension**2
58 IF (total > order) RETURN
59 DO j = 1, nirrep
60 value = sum(conjg(table(:, i))*table(:, j))/real(order, dp)
61 IF (i == j) value = value - 1.0_dp
62 IF (abs(value) > tolerance) RETURN
63 END DO
64 END DO
65 IF (total /= order) RETURN
66 status = -2
67 DO i = 1, nirrep
68 value = sum(conjg(table(:, i))*character)/real(order, dp)
69 j = nint(real(value, dp))
70 IF (j < 0 .OR. abs(value - j) > tolerance) RETURN
71 multiplicities(i) = j
72 END DO
73 IF (maxval(abs(matmul(table, cmplx(multiplicities, 0, dp)) - character)) > tolerance) RETURN
74 status = 0
75 END SUBROUTINE character_multiplicities
76
77! **************************************************************************************************
78!> \brief Inversion irreps of an isolated scalar or spinor eigenspace in an AO metric.
79!> \param metric Scalar AO overlap at a TRIM
80!> \param coeff Selected coefficients, spinor components stacked by AO
81!> \param mapping Target AO index under inversion
82!> \param phase Source-AO multiplier, including orbital parity and lattice phase
83!> \param energies Selected eigenvalues in Hartree
84!> \param check_tr Check physical spinful time reversal as well as inversion
85!> \param tolerance Dimensionless metric/subspace/character tolerance
86!> \param energy_tolerance Eigenvalue-commutator tolerance in Hartree
87!> \param counts Multiplicities of even/odd inversion irreps, counting states not pairs
88!> \param error Largest dimensionless residual
89!> \param energy_error Largest projected symmetry/eigenvalue commutator
90!> \param status Zero on success; invalid output for nonzero status
91!> \param diagnostics Optional metric, normalization, inversion and time-reversal residuals
92! **************************************************************************************************
93 SUBROUTINE inversion_representation(metric, coeff, mapping, phase, energies, check_tr, &
94 tolerance, energy_tolerance, counts, error, energy_error, status, diagnostics)
95 COMPLEX(KIND=dp), INTENT(IN) :: metric(:, :), coeff(:, :)
96 INTEGER, INTENT(IN) :: mapping(:)
97 COMPLEX(KIND=dp), INTENT(IN) :: phase(:)
98 REAL(kind=dp), INTENT(IN) :: energies(:)
99 LOGICAL, INTENT(IN) :: check_tr
100 REAL(kind=dp), INTENT(IN) :: tolerance, energy_tolerance
101 INTEGER, INTENT(OUT) :: counts(2)
102 REAL(kind=dp), INTENT(OUT) :: error, energy_error
103 INTEGER, INTENT(OUT) :: status
104 REAL(kind=dp), INTENT(OUT), OPTIONAL :: diagnostics(4)
105
106 COMPLEX(KIND=dp) :: characters(2), table(2, 2)
107 COMPLEX(KIND=dp), ALLOCATABLE :: pc(:, :), projected(:, :), sc(:, :), &
108 trc(:, :), work(:, :)
109 INTEGER :: first, i, j, last, nao, nspin, rank, s
110 REAL(kind=dp) :: metric_scale
111
112 status = -1
113 counts = -1
114 error = huge(1.0_dp)
115 energy_error = huge(1.0_dp)
116 IF (PRESENT(diagnostics)) diagnostics = huge(1.0_dp)
117 nao = SIZE(metric, 1)
118 rank = SIZE(coeff, 2)
119 IF (nao < 1 .OR. rank < 1 .OR. SIZE(metric, 2) /= nao) RETURN
120 IF (mod(SIZE(coeff, 1), nao) /= 0) RETURN
121 nspin = SIZE(coeff, 1)/nao
122 IF (nspin < 1 .OR. nspin > 2) RETURN
123 IF (check_tr .AND. (nspin /= 2 .OR. mod(rank, 2) /= 0)) RETURN
124 IF (SIZE(mapping) /= nao .OR. SIZE(phase) /= nao .OR. SIZE(energies) /= rank) RETURN
125 IF (tolerance <= 0.0_dp .OR. energy_tolerance <= 0.0_dp) RETURN
126 IF (.NOT. ieee_is_finite(tolerance) .OR. .NOT. ieee_is_finite(energy_tolerance)) RETURN
127 IF (.NOT. all(ieee_is_finite(real(metric, dp))) .OR. .NOT. all(ieee_is_finite(aimag(metric)))) RETURN
128 IF (.NOT. all(ieee_is_finite(real(coeff, dp))) .OR. .NOT. all(ieee_is_finite(aimag(coeff)))) RETURN
129 IF (.NOT. all(ieee_is_finite(real(phase, dp))) .OR. .NOT. all(ieee_is_finite(aimag(phase)))) RETURN
130 IF (.NOT. all(ieee_is_finite(energies))) RETURN
131 IF (any(mapping < 1) .OR. any(mapping > nao)) RETURN
132 IF (any(abs(abs(phase) - 1.0_dp) > tolerance)) RETURN
133 DO i = 1, nao
134 IF (mapping(mapping(i)) /= i) RETURN
135 IF (abs(phase(i)*phase(mapping(i)) - 1.0_dp) > tolerance) RETURN
136 END DO
137 metric_scale = max(1.0_dp, maxval(abs(metric)))
138 error = maxval(abs(metric - conjg(transpose(metric))))/metric_scale
139 DO j = 1, nao
140 DO i = 1, nao
141 error = max(error, abs(conjg(phase(i))*metric(mapping(i), mapping(j))*phase(j) - metric(i, j))/ &
142 metric_scale)
143 END DO
144 END DO
145 IF (PRESENT(diagnostics)) diagnostics(1) = error
146 ALLOCATE (sc(nao*nspin, rank), pc(nao*nspin, rank), projected(rank, rank), work(rank, rank))
147 DO s = 1, nspin
148 first = (s - 1)*nao
149 last = s*nao
150 sc(first + 1:last, :) = matmul(metric, coeff(first + 1:last, :))
151 DO i = 1, nao
152 pc(first + mapping(i), :) = phase(i)*coeff(first + i, :)
153 END DO
154 END DO
155 work(:, :) = matmul(conjg(transpose(coeff)), sc)
156 DO i = 1, rank
157 work(i, i) = work(i, i) - 1.0_dp
158 END DO
159 error = max(error, maxval(abs(work)))
160 IF (PRESENT(diagnostics)) diagnostics(2) = maxval(abs(work))
161 projected(:, :) = matmul(conjg(transpose(sc)), pc)
162 IF (.NOT. all(ieee_is_finite(real(projected, dp)))) RETURN
163 IF (.NOT. all(ieee_is_finite(aimag(projected)))) RETURN
164 work(:, :) = matmul(conjg(transpose(projected)), projected)
165 DO i = 1, rank
166 work(i, i) = work(i, i) - 1.0_dp
167 END DO
168 error = max(error, maxval(abs(work)), maxval(abs(projected - conjg(transpose(projected)))))
169 IF (PRESENT(diagnostics)) diagnostics(3) = max(maxval(abs(work)), &
170 maxval(abs(projected - conjg(transpose(projected)))))
171 IF (PRESENT(diagnostics)) THEN
172 IF (.NOT. check_tr) diagnostics(4) = 0.0_dp
173 END IF
174 energy_error = 0.0_dp
175 DO j = 1, rank
176 DO i = 1, rank
177 energy_error = max(energy_error, abs(projected(i, j)*(energies(i) - energies(j))))
178 END DO
179 END DO
180 characters(1) = cmplx(rank, 0, dp)
181 characters(2) = cmplx(0, 0, dp)
182 DO i = 1, rank
183 characters(2) = characters(2) + projected(i, i)
184 END DO
185 table(:, 1) = cmplx([1, 1], 0, dp)
186 table(:, 2) = cmplx([1, -1], 0, dp)
187 CALL character_multiplicities(characters, table, counts, tolerance*rank, status)
188 IF (status /= 0) RETURN
189 status = -3
190 IF (check_tr) THEN
191 ! In a real Gaussian Bloch basis at a TRIM, Theta=(i sigma_y) K.
192 error = max(error, maxval(abs(aimag(metric)))/max(1.0_dp, maxval(abs(metric))))
193 ALLOCATE (trc(2*nao, rank))
194 trc(:nao, :) = conjg(coeff(nao + 1:, :))
195 trc(nao + 1:, :) = -conjg(coeff(:nao, :))
196 projected(:, :) = matmul(conjg(transpose(sc)), trc)
197 work(:, :) = matmul(conjg(transpose(projected)), projected)
198 DO i = 1, rank
199 work(i, i) = work(i, i) - 1.0_dp
200 END DO
201 error = max(error, maxval(abs(work)), maxval(abs(projected + transpose(projected))))
202 IF (PRESENT(diagnostics)) diagnostics(4) = max(maxval(abs(work)), &
203 maxval(abs(projected + transpose(projected))))
204 DO j = 1, rank
205 DO i = 1, rank
206 energy_error = max(energy_error, abs(projected(i, j)*(energies(i) - energies(j))))
207 END DO
208 END DO
209 IF (any(mod(counts, 2) /= 0)) RETURN
210 END IF
211 IF (.NOT. ieee_is_finite(error) .OR. .NOT. ieee_is_finite(energy_error)) RETURN
212 IF (error > tolerance .OR. energy_error > energy_tolerance) RETURN
213 status = 0
214 END SUBROUTINE inversion_representation
215END MODULE topology_symmetry
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
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.