(git:26ffdda)
Loading...
Searching...
No Matches
wannier90_nnkpts.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 Read explicit Wannier90 overlap connections, including nonuniform closed loops.
10! **************************************************************************************************
12 USE cp_files, ONLY: close_file,&
14 USE ieee_arithmetic, ONLY: ieee_is_finite
15 USE kinds, ONLY: dp
17#include "./base/base_uses.f90"
18
19 IMPLICIT NONE
20 PRIVATE
21 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'wannier90_nnkpts'
22 ! Absolute file-format tolerances: Angstrom and reciprocal Angstrom, respectively.
23 REAL(KIND=dp), PARAMETER :: real_lattice_tol = 1.e-6_dp, recip_lattice_tol = 1.e-6_dp
24 PUBLIC :: read_wannier90_nnkpts
25CONTAINS
26
27! **************************************************************************************************
28!> \brief Read and validate the cell, points, and directed connections of an nnkp file.
29!> \param filename input file
30!> \param real_lattice direct lattice vectors as columns, in Angstrom
31!> \param recip_lattice reciprocal lattice vectors as columns, in inverse Angstrom (including 2*pi)
32!> \param kpt fractional k-points, without coordinate wrapping
33!> \param nnlist target point for each directed connection
34!> \param nncell reciprocal lattice translation for each connection
35! **************************************************************************************************
36 SUBROUTINE read_wannier90_nnkpts(filename, real_lattice, recip_lattice, kpt, nnlist, nncell)
37 CHARACTER(len=*), INTENT(IN) :: filename
38 REAL(kind=dp), INTENT(IN) :: real_lattice(3, 3), recip_lattice(3, 3)
39 REAL(kind=dp), ALLOCATABLE, INTENT(OUT) :: kpt(:, :)
40 INTEGER, ALLOCATABLE, INTENT(OUT) :: nnlist(:, :), nncell(:, :, :)
41
42 CHARACTER(len=1024) :: line
43 CHARACTER(len=64) :: block, marker
44 INTEGER :: i, ios, j, n, nexclude, nneigh, origin, &
45 shift(3), TARGET, unit
46 INTEGER, ALLOCATABLE :: counts(:)
47 LOGICAL :: have_real, have_recip
48 REAL(kind=dp) :: lattice(3, 3)
49
50 have_real = .false.
51 have_recip = .false.
52 CALL open_file(filename, unit_number=unit, file_status="OLD", file_action="READ")
53 DO
54 CALL next_line(unit, line, ios)
55 IF (ios < 0) EXIT
56 IF (ios /= 0) cpabort("NNKP_FILE: read error.")
57 marker = ""
58 block = ""
59 READ (line, *, iostat=ios) marker, block
60 IF (ios /= 0) cycle
61 CALL lowercase(marker)
62 CALL lowercase(block)
63 IF (marker /= "begin") cycle
64 SELECT CASE (trim(block))
65 CASE ("real_lattice", "recip_lattice")
66 DO i = 1, 3
67 CALL required_line(unit, line)
68 READ (line, *, iostat=ios) lattice(:, i)
69 IF (ios /= 0) cpabort("NNKP_FILE: invalid lattice vector.")
70 END DO
71 IF (.NOT. all(ieee_is_finite(lattice))) cpabort("NNKP_FILE: nonfinite lattice.")
72 IF (block == "real_lattice") THEN
73 IF (have_real) cpabort("NNKP_FILE: duplicate real_lattice block.")
74 IF (maxval(abs(lattice - real_lattice)) > real_lattice_tol) THEN
75 cpabort("NNKP_FILE: real lattice differs from the CP2K cell (Angstrom).")
76 END IF
77 have_real = .true.
78 ELSE
79 IF (have_recip) cpabort("NNKP_FILE: duplicate recip_lattice block.")
80 IF (maxval(abs(lattice - recip_lattice)) > recip_lattice_tol) THEN
81 cpabort("NNKP_FILE: reciprocal lattice differs from the CP2K cell.")
82 END IF
83 have_recip = .true.
84 END IF
85 CALL end_block(unit, block)
86 CASE ("kpoints")
87 IF (ALLOCATED(kpt)) cpabort("NNKP_FILE: duplicate kpoints block.")
88 CALL required_line(unit, line)
89 READ (line, *, iostat=ios) n
90 IF (ios /= 0) cpabort("NNKP_FILE: invalid point count.")
91 IF (n < 1) cpabort("NNKP_FILE: point count must be positive.")
92 ALLOCATE (kpt(3, n))
93 DO i = 1, n
94 CALL required_line(unit, line)
95 READ (line, *, iostat=ios) kpt(:, i)
96 IF (ios /= 0) cpabort("NNKP_FILE: invalid k-point.")
97 END DO
98 IF (.NOT. all(ieee_is_finite(kpt))) cpabort("NNKP_FILE: nonfinite k-point.")
99 CALL end_block(unit, block)
100 CASE ("nnkpts")
101 IF (.NOT. ALLOCATED(kpt)) cpabort("NNKP_FILE: kpoints must precede nnkpts.")
102 IF (ALLOCATED(nnlist)) cpabort("NNKP_FILE: duplicate nnkpts block.")
103 CALL required_line(unit, line)
104 READ (line, *, iostat=ios) nneigh
105 IF (ios /= 0) cpabort("NNKP_FILE: invalid neighbour count.")
106 IF (nneigh < 1) cpabort("NNKP_FILE: neighbour count must be positive.")
107 n = SIZE(kpt, 2)
108 ALLOCATE (nnlist(n, nneigh), nncell(3, n, nneigh), counts(n))
109 counts = 0
110 DO i = 1, n*nneigh
111 CALL required_line(unit, line)
112 READ (line, *, iostat=ios) origin, TARGET, shift
113 IF (ios /= 0) cpabort("NNKP_FILE: invalid connection.")
114 IF (min(origin, TARGET) < 1 .OR. max(origin, TARGET) > n) THEN
115 cpabort("NNKP_FILE: connection point index out of range.")
116 END IF
117 IF (counts(origin) == nneigh) cpabort("NNKP_FILE: too many neighbours for a point.")
118 DO j = 1, counts(origin)
119 IF (nnlist(origin, j) == TARGET .AND. all(nncell(:, origin, j) == shift)) THEN
120 cpabort("NNKP_FILE: duplicate connection.")
121 END IF
122 END DO
123 counts(origin) = counts(origin) + 1
124 nnlist(origin, counts(origin)) = TARGET
125 nncell(:, origin, counts(origin)) = shift
126 END DO
127 IF (any(counts /= nneigh)) cpabort("NNKP_FILE: missing connections.")
128 DEALLOCATE (counts)
129 CALL end_block(unit, block)
130 CASE ("exclude_bands")
131 CALL required_line(unit, line)
132 READ (line, *, iostat=ios) nexclude
133 IF (ios /= 0) cpabort("NNKP_FILE: invalid exclude_bands count.")
134 IF (nexclude /= 0) cpabort("NNKP_FILE: specify band exclusions using CP2K EXCLUDE_BANDS.")
135 CALL end_block(unit, block)
136 CASE DEFAULT
137 ! Skip projections and other Wannier90 blocks not required for overlaps.
138 DO
139 CALL required_line(unit, line)
140 marker = ""
141 READ (line, *, iostat=ios) marker
142 IF (ios /= 0) cpabort("NNKP_FILE: invalid line in unused block.")
143 CALL lowercase(marker)
144 IF (marker == "end") EXIT
145 END DO
146 END SELECT
147 END DO
148 CALL close_file(unit)
149 IF (.NOT. have_real .OR. .NOT. have_recip) cpabort("NNKP_FILE: missing lattice blocks.")
150 IF (.NOT. ALLOCATED(kpt) .OR. .NOT. ALLOCATED(nnlist)) THEN
151 cpabort("NNKP_FILE: missing kpoints or nnkpts block.")
152 END IF
153 END SUBROUTINE read_wannier90_nnkpts
154
155! **************************************************************************************************
156!> \brief Read a nonempty line, removing comments.
157!> \param unit input unit
158!> \param line resulting line
159!> \param ios IO status
160! **************************************************************************************************
161 SUBROUTINE next_line(unit, line, ios)
162 INTEGER, INTENT(IN) :: unit
163 CHARACTER(len=*), INTENT(OUT) :: line
164 INTEGER, INTENT(OUT) :: ios
165
166 INTEGER :: i
167
168 DO
169 READ (unit, '(A)', iostat=ios) line
170 IF (ios /= 0) RETURN
171 i = scan(line, "!#")
172 IF (i > 0) line(i:) = ""
173 line = adjustl(line)
174 IF (len_trim(line) > 0) RETURN
175 END DO
176 END SUBROUTINE next_line
177
178! **************************************************************************************************
179!> \brief Read a required nonempty line.
180!> \param unit input unit
181!> \param line resulting line
182! **************************************************************************************************
183 SUBROUTINE required_line(unit, line)
184 INTEGER, INTENT(IN) :: unit
185 CHARACTER(len=*), INTENT(OUT) :: line
186
187 INTEGER :: ios
188
189 CALL next_line(unit, line, ios)
190 IF (ios /= 0) cpabort("NNKP_FILE: unexpected end of file or read error.")
191 END SUBROUTINE required_line
192
193! **************************************************************************************************
194!> \brief Check a block terminator.
195!> \param unit input unit
196!> \param block expected block name
197! **************************************************************************************************
198 SUBROUTINE end_block(unit, block)
199 INTEGER, INTENT(IN) :: unit
200 CHARACTER(len=*), INTENT(IN) :: block
201
202 CHARACTER(len=1024) :: line
203 CHARACTER(len=64) :: marker, name
204 INTEGER :: ios
205
206 CALL required_line(unit, line)
207 READ (line, *, iostat=ios) marker, name
208 IF (ios /= 0) cpabort("NNKP_FILE: missing block terminator.")
209 CALL lowercase(marker)
210 CALL lowercase(name)
211 IF (marker /= "end" .OR. name /= block) cpabort("NNKP_FILE: incorrect block terminator.")
212 END SUBROUTINE end_block
213
214END MODULE wannier90_nnkpts
Utility routines to open and close files. Tracking of preconnections.
Definition cp_files.F:16
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
Definition cp_files.F:311
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
Definition cp_files.F:122
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Utilities for string manipulations.
elemental subroutine, public lowercase(string)
Convert all upper case characters in a string to lower case.
Read explicit Wannier90 overlap connections, including nonuniform closed loops.
subroutine, public read_wannier90_nnkpts(filename, real_lattice, recip_lattice, kpt, nnlist, nncell)
Read and validate the cell, points, and directed connections of an nnkp file.