86 CHARACTER(LEN=*),
INTENT(IN) :: path
87 LOGICAL,
INTENT(IN) :: physical
89 CHARACTER(LEN=256) ::
header
90 CHARACTER(LEN=default_path_length),
ALLOCATABLE :: files(:)
91 INTEGER :: input, store, stat, dim, rank, nvertex, nframe, nat, vertex, axis, mu, nu, p, i, j, na, nb, nbase,
idx, record_size
92 INTEGER,
ALLOCATABLE :: shape(:), extended(:), index(:), next(:), zero(:), points(:), permutation(:, :)
93 LOGICAL,
ALLOCATABLE :: checked(:)
94 REAL(kind=
dp),
ALLOCATABLE :: offsets(:), directions(:, :)
95 REAL(kind=
dp) :: origin(3), ka(3), kb(3), tol_metric, tol_gap, tol_sv, phase_limit, minimum, local_min, &
96 max_metric, min_gap, err, gap,
value, contribution, max_phase, local_phase, seam_error, &
97 valence_max, conduction_min, energy_shift, compensation, y, t
98 COMPLEX(KIND=dp),
ALLOCATABLE :: raw(:, :), link(:, :), sewing(:, :), u(:, :, :), pqs(:, :, :)
100 LOGICAL :: common_reference, prefix
101 INTEGER(KIND=int64) :: total
103 CALL open_file(path, unit_number=input, file_status=
'OLD', file_action=
'READ')
104 READ (input,
'(A)', iostat=stat)
header
107 IF (trim(
header) /=
'CP2K_PHASON_MESH 1')
THEN
108 cpabort(
'Expected CP2K_PHASON_MESH 1')
111 IF (trim(
header) /=
'CP2K_TOPOLOGY_LINKS 1')
THEN
112 cpabort(
'Expected CP2K_TOPOLOGY_LINKS 1')
115 READ (input, *, iostat=stat) dim, rank
117 IF ((dim /= 2 .AND. dim /= 4) .OR. rank < 1)
THEN
118 cpabort(
'Invalid mesh dimension or rank')
120 ALLOCATE (shape(dim), extended(dim), index(dim), next(dim), zero(dim))
121 READ (input, *, iostat=stat) shape
123 IF (any(shape < 3))
THEN
124 cpabort(
'At least three samples per mesh axis are required')
128 IF (total > int(huge(1), int64)/int(shape(axis) + 1, int64))
THEN
129 cpabort(
'Mesh index overflow')
131 total = total*int(shape(axis) + 1, int64)
133 extended(:) = shape + 1
134 nvertex = product(shape)
136 report%dimension = dim
138 report%shape(1:dim) = shape
139 READ (input, *, iostat=stat) tol_metric, tol_gap, tol_sv, phase_limit
141 IF (.NOT. all(ieee_is_finite([tol_metric, tol_gap, tol_sv, phase_limit])))
THEN
142 cpabort(
'Nonfinite tolerances')
144 IF (min(tol_metric, tol_gap, tol_sv, phase_limit) <= 0.0_dp .OR. max(tol_metric, tol_sv) >= 1.0_dp .OR. &
145 phase_limit >= acos(-1.0_dp))
THEN
146 cpabort(
'Invalid mesh tolerances')
148 ALLOCATE (raw(rank, rank), link(rank, rank), sewing(rank, rank), u(rank, rank, 4), pqs(rank, rank, dim*(dim - 1)/2))
150 OPEN (newunit=store, status=
'SCRATCH', access=
'STREAM', form=
'UNFORMATTED', iostat=stat)
152 INQUIRE (iolength=record_size) link
153 minimum = huge(1.0_dp)
155 min_gap = huge(1.0_dp)
157 valence_max = -huge(1.0_dp)
158 conduction_min = huge(1.0_dp)
159 common_reference = .false.
162 ALLOCATE (a, b, base)
163 ALLOCATE (files(nframe), points(nframe), offsets(nframe), checked(nframe), directions(3, dim))
165 READ (input, *, iostat=stat) origin
167 IF (.NOT. all(ieee_is_finite(origin)))
THEN
168 cpabort(
'Nonfinite mesh origin')
171 READ (input, *, iostat=stat) directions(:, axis)
174 IF (.NOT. all(ieee_is_finite(directions)))
THEN
175 cpabort(
'Nonfinite reciprocal periods')
177 IF (maxval(abs(directions - anint(directions))) > 1.e-10_dp)
THEN
178 cpabort(
'Noninteger reciprocal periods')
180 READ (input, *, iostat=stat) nat, common_reference
183 cpabort(
'Invalid mesh atom count')
185 ALLOCATE (permutation(nat, dim))
187 READ (input, *, iostat=stat) permutation(:, axis)
189 IF (any(permutation(:, axis) < 1) .OR. any(permutation(:, axis) > nat))
THEN
190 cpabort(
'Invalid seam permutation')
193 IF (count(permutation(:, axis) ==
idx) /= 1)
THEN
194 cpabort(
'Non-bijective seam map')
200 IF (any(permutation(permutation(:, mu), nu) /= permutation(permutation(:, nu), mu)))
THEN
201 cpabort(
'The declared torus atom permutations do not commute')
206 READ (input, *, iostat=stat) files(
idx), points(
idx), offsets(
idx)
208 IF (points(
idx) < 1 .OR. .NOT. ieee_is_finite(offsets(
idx)))
THEN
209 cpabort(
'Invalid frame record')
213 report%origin(:) = origin
214 report%directions(:, 1:dim) = directions
215 report%first_file = files(1)
216 report%point = points(1)
218 DO vertex = 1, nvertex
219 CALL unflat(vertex, shape, index)
221 na =
flat(index, extended)
223 ka(:) = origin + matmul(directions, real(index,
dp)/real(shape,
dp))
228 next(axis) = next(axis) + 1
229 nb =
flat(next, extended)
231 kb(:) = origin + matmul(directions, real(next,
dp)/real(shape,
dp))
233 IF (next(axis) == shape(axis))
THEN
236 nbase =
flat(zero, extended)
237 CALL frame(nbase, base)
241 link(:, :) = matmul(conjg(transpose(sewing)), sewing)
245 err = maxval(abs(link))
246 seam_error = max(seam_error, err)
247 IF (err > tol_metric)
THEN
248 cpabort(
'Endpoint selected subspaces do not close')
250 CALL polar_link(sewing, link, local_min, stat, tol_sv)
252 cpabort(
'Invalid endpoint sewing link')
254 raw(:, :) = matmul(raw, link)
259 READ (input, *, iostat=stat) ka(1:2)
261 raw(i, j) = cmplx(ka(1), ka(2),
dp)
265 CALL polar_link(raw, link, local_min, stat, tol_sv)
267 cpabort(
'Singular/nonfinite mesh link; refine or check the subspace')
269 minimum = min(minimum, local_min)
270 WRITE (store, iostat=stat) link
275 READ (input,
'(A)', iostat=stat)
header
277 IF (stat /= 0 .OR. len_trim(
header) /= 0)
THEN
278 cpabort(
'Unexpected trailing mesh data')
283 compensation = 0.0_dp
285 DO vertex = 1, nvertex
286 CALL unflat(vertex, shape, index)
291 CALL read_link(vertex, mu, u(:, :, 1))
293 next(mu) = mod(next(mu) + 1, shape(mu))
294 CALL read_link(
flat(next, shape), nu, u(:, :, 2))
296 next(nu) = mod(next(nu) + 1, shape(nu))
297 CALL read_link(
flat(next, shape), mu, u(:, :, 3))
298 CALL read_link(vertex, nu, u(:, :, 4))
299 CALL link_plaquette(u(:, :, 1), u(:, :, 2), u(:, :, 3), u(:, :, 4), pqs(:, :, p))
304 cpabort(
'Unresolved/nonunitary plaquette; refine the mesh')
306 max_phase = max(max_phase, local_phase)
307 y = contribution - compensation
309 compensation = (t -
value) - y
314 WRITE (output_unit,
'(A,I0)')
'PARAMETER_DIMENSION ', dim
315 WRITE (output_unit,
'(A,*(I0,1X))')
'MESH ', shape
316 WRITE (output_unit,
'(A,ES26.17)')
'CHERN_RAW ',
value
317 WRITE (output_unit,
'(A,ES26.17)')
'MINIMUM_LINK_SINGULAR_VALUE ', minimum
318 WRITE (output_unit,
'(A,ES26.17)')
'MAXIMUM_PLAQUETTE_PHASE ', max_phase
320 WRITE (output_unit,
'(A,ES26.17)')
'MAXIMUM_METRIC_ERROR ', max_metric
321 WRITE (output_unit,
'(A,ES26.17)')
'MAXIMUM_SEAM_ERROR ', seam_error
322 WRITE (output_unit,
'(A,ES26.17)')
'MINIMUM_DIRECT_GAP_HA ', min_gap
323 IF (common_reference .AND. prefix)
THEN
324 WRITE (output_unit,
'(A,ES26.17)')
'SAMPLED_INDIRECT_GAP_HA ', conduction_min - valence_max
326 WRITE (output_unit,
'(A)')
'INDIRECT_GAP_NOT_EVALUATED: no asserted common energy reference or not a lowest-band prefix'
329 WRITE (output_unit,
'(A)')
'MESH_CONVERGENCE_NOT_ESTABLISHED: repeat on finer meshes; retain unrounded C2 values.'
336 SUBROUTINE frame(number, state)
337 INTEGER,
INTENT(IN) :: number
342 CALL read_snapshot(trim(files(number)), points(number), state)
343 IF (state%rank /= rank .OR.
SIZE(state%atoms) /= nat)
THEN
344 cpabort(
'Frame rank/atom count differs from manifest')
346 IF (.NOT. checked(number))
THEN
348 max_metric = max(max_metric, err)
349 min_gap = min(min_gap, gap)
350 checked(number) = .true.
352 IF (state%bands(iband) /= iband) prefix = .false.
354 IF (rank >=
SIZE(state%energies)) prefix = .false.
356 energy_shift = offsets(number)
357 valence_max = max(valence_max, state%energies(rank) + energy_shift)
358 conduction_min = min(conduction_min, state%energies(rank + 1) + energy_shift)
368 SUBROUTINE read_link(vertex_index, direction, matrix)
369 INTEGER,
INTENT(IN) :: vertex_index, direction
370 COMPLEX(KIND=dp),
INTENT(OUT) :: matrix(:, :)
372 INTEGER(KIND=int64) :: position
374 position = (int(vertex_index - 1, int64)*int(dim, int64) + int(direction - 1, int64))*int(record_size, int64) + 1_int64
375 READ (store, pos=position, iostat=stat) matrix
377 END SUBROUTINE read_link