Octopus
wannier90lib_interface.F90
Go to the documentation of this file.
1!! Copyright (C) 2026 A. Buccheri, J. Reimann
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
25
27 use debug_oct_m
29 use global_oct_m
30 use ions_oct_m, only: ions_t
31 use io_oct_m, only: io_open, io_close
32 use kpoints_oct_m, only: kpoints_t
34 use mesh_oct_m, only: mesh_t
38 use space_oct_m, only: space_t
43 only: &
48
49 ! External library
50 ! Wannier90 lib type and routines are not dressed with the preprocessor guard as they
51 ! are limited to this scope, and this module should only get included in compilation
52 ! if Wannier90 lib is linked to
53 use w90_library
54
55 implicit none
56 private
57 public :: wannier90lib_init_w90main, &
62
63contains
64
70 subroutine wannier90lib_init_w90main(namespace, ions, latt, kpoints, st, &
71 inp_options, w90main, stdout, stderr, ierr)
72 type(namespace_t), intent(in) :: namespace
73 type(ions_t), intent(in) :: ions
74 type(lattice_vectors_t), intent(in) :: latt ! will differ from ions%latt by 2*L for non-periodic systems
75 type(kpoints_t), intent(in) :: kpoints
76 type(states_elec_t), intent(in) :: st
77 type(wannier_opts_t), intent(in) :: inp_options
78 type(lib_common_type), intent(inout) :: w90main
79 integer, intent(inout) :: stdout, stderr, ierr
80
81 integer, allocatable :: distk(:)
82 integer :: ik, iq, nk
83
85
86 ! Set required options
87 ! Note: num_bands does not include excluded bands!
88 ! The order is nst > num_bands > num_wann
89 ! TODO: Correctly handle this depending on inputs
90 ! TODO: Distinguish everywhere between nst and num_bands
91 call w90_set_option(w90main, 'kpoints', -kpoints%reduced%red_point(1:3,:)) ! minus sign for wrong octopus convention
92 call w90_set_option(w90main, 'mp_grid', kpoints%nik_axis(1:3))
93 call w90_set_option(w90main, 'num_bands', inp_options%num_bands)
94 call w90_set_option(w90main, 'num_wann', inp_options%num_wann)
95 call w90_set_option(w90main, 'unit_cell_cart', units_from_atomic(unit_angstrom, latt%rlattice(1:3,:)))
96
97 nk = kpoints%full%npoints
98 safe_allocate(distk(1:nk))
99 if (st%d%kpt%parallel) then
100 ! pass octopus communicator to wannier90 library
101 call w90_set_comm(w90main, st%d%kpt%mpi_grp%comm%MPI_VAL)
102 ! Feed kpoint distribution to wannier90 library
103 distk = -1
104 ! (k, spin)
105 do iq = 1, st%nik
106 ! k-only
107 ik = st%d%get_kpoint_index(iq)
108 if (distk(ik) == -1) then
109 distk(ik) = st%d%kpt%process(iq)
110 else if (distk(ik) /= st%d%kpt%process(iq)) then
111 message(1) = 'Error: Wannier90 k-point parallelization: same k-point' // &
112 'assigned to different nodes.'
113 call messages_fatal(1, namespace=namespace)
114 end if
115 end do
116 else
117 ! octopus default communicator is not acceptable in that case
118 call w90_set_comm(w90main, st%system_grp%comm%MPI_VAL)
119 ! No parallelization, assign all k-points to node 0
120 distk = 0
121 endif
122 call w90_set_option(w90main, 'distk', distk)
123 safe_deallocate_a(distk)
124
125 ! Set atom data for projection parsing
126 call wannier90lib_set_atom_data(w90main, ions, latt)
127
128 ! Parse projections from input file
129 call wannier90lib_set_projections(w90main, inp_options)
130
131 ! Option to dump files
132 if (inp_options%dump_inputs) then
133 call w90_set_option(w90main, "dump_inputs", .true.)
134 end if
135
136 ! Initialize library type with seedname
137 call w90_input_setopt(w90main, inp_options%prefix, stdout, stderr, ierr)
138
139 ! Read optional options from file
140 ! Note: Mandatory options are only read from octopus input.
141 ! If any mandatory options are set in `.win`, they will be ignored triggering a warning.
142 call wannier90lib_warn_inputs(inp_options)
143 call w90_input_reader(w90main, stdout, stderr, ierr)
144 if (ierr /= 0) then
145 write(message(1), '(a,i0)') 'Error in w90_input_reader: ', ierr
146 call messages_fatal(1)
147 end if
148
150 end subroutine wannier90lib_init_w90main
151
152
158 subroutine wannier90lib_set_atom_data(w90main, ions, latt)
159 type(lib_common_type), intent(inout) :: w90main
160 type(ions_t), intent(in) :: ions
161 type(lattice_vectors_t), intent(in) :: latt ! will differ from ions%latt by 2*L for non-periodic systems
162
163 integer :: ia, n_atoms
164 real(real64), allocatable :: atom_pos_frac(:,:)
165 character(len=2), allocatable :: atom_labels(:)
166
168
169 n_atoms = ions%natoms
170
171 ! Allocate arrays for atom data
172 safe_allocate(atom_pos_frac(1:3, 1:n_atoms))
173 safe_allocate(atom_labels(1:n_atoms))
174
175 ! Extract atomic positions and labels from ions
176 do ia = 1, n_atoms
177 ! Get Cartesian positions from octopus
178 ! Convert to fractional (reduced) coordinates for wannier90
179 atom_pos_frac(1:3, ia) = latt%cart_to_red(ions%pos(1:3, ia))
180 ! Get atomic labels
181 atom_labels(ia) = trim(ions%atom(ia)%label)
182 end do
183
184 ! Set atom positions in fractional coordinates
185 call w90_set_option(w90main, 'atoms_frac', atom_pos_frac)
186 ! Set symbols
187 call w90_set_option(w90main, 'symbols', atom_labels)
188
189 safe_deallocate_a(atom_pos_frac)
190 safe_deallocate_a(atom_labels)
191
193 end subroutine wannier90lib_set_atom_data
194
195
200 subroutine wannier90lib_set_projections(w90main, inp_options)
201 type(lib_common_type), intent(inout) :: w90main
202 type(wannier_opts_t), intent(in) :: inp_options
203
204 character(len=80) :: filename, line
205 integer :: w90_win, io
206 logical :: exist
207
209
210 ! Correctly handle projections by parsing them from .win file
211 filename = trim(adjustl(inp_options%prefix)) //'.win'
212
213 message(1) = "oct-wannier90: Parsing projections from "//filename
214 call messages_info(1)
215
216 inquire(file=filename,exist=exist)
217 if (.not. exist) then
218 message(1) = 'oct-wannier90: Cannot find specified Wannier90 win file.'
219 call messages_fatal(1)
220 end if
221
222 ! read projections and set them in w90main
223 w90_win = io_open(trim(filename), action='read')
224 do
225 read(w90_win, '(A)', iostat=io) line
226 if (is_iostat_end(io)) exit
227
228 if (trim(line) == 'begin projections') then
229 do
230 read(w90_win, '(A)') line
231 if (trim(line) == 'end projections') exit
232 call w90_set_option(w90main, 'projections', trim(line))
233 end do
234 end if
235 end do
236 call io_close(w90_win)
237
239 end subroutine wannier90lib_set_projections
240
245 subroutine wannier90lib_initialize_matrix_data(w90main, u_matrix, &
246 u_dis_matrix, m_matrix, centers)
247 type(lib_common_type), intent(inout) :: w90main
248 complex(real64), contiguous, intent(inout) :: u_matrix(:, :, :)
249 complex(real64), contiguous, intent(inout) :: u_dis_matrix(:, :, :)
250 complex(real64), contiguous, intent(inout) :: m_matrix(:, :, :, :)
251 real(real64), contiguous, intent(in) :: centers(:, :)
252
254
255 call w90_set_u_matrix(w90main, u_matrix)
256 call w90_set_u_opt(w90main, u_dis_matrix)
257 call w90_set_m_local(w90main, m_matrix)
258 w90main%wannier_data%centres = centers
259
261
263
269 subroutine wannier90lib_warn_inputs(inp_options)
270 type(wannier_opts_t), intent(in) :: inp_options
271
272 character(len=80) :: filename, line, dummy, dummy1
273 integer :: w90_win, io
274 logical :: exist
275
277
278 filename = trim(adjustl(inp_options%prefix)) //'.win'
279
280 message(1) = "oct-wannier90: Parsing "//filename
281 call messages_info(1)
282
283 inquire(file=filename,exist=exist)
284 if (.not. exist) then
285 message(1) = 'oct-wannier90: Cannot find specified Wannier90 win file.'
286 call messages_fatal(1)
287 end if
288
289 ! warn which options are not considered from .win file
290 w90_win = io_open(trim(filename), action='read')
291 do
292 read(w90_win, '(A)', iostat=io) line
293 if (is_iostat_end(io)) exit
294
295 if (trim(line) == 'begin kpoints') then
296 message(1) = 'oct-wannier90: Warning: kpoints specified in .win file' // &
297 ' are ignored. Using kpoints from octopus input instead.'
298 call messages_warning(1)
299 else if (trim(line) == 'begin atoms_frac') then
300 message(1) = 'oct-wannier90: Warning: atomic positions specified in .win file' // &
301 ' are ignored. Using positions from octopus input instead.'
302 call messages_warning(1)
303 else if (trim(line) == 'begin unit_cell_cart') then
304 message(1) = 'oct-wannier90: Warning: unit cell vectors specified in .win file' // &
305 ' are ignored. Using unit cell vectors from octopus input instead.'
306 call messages_warning(1)
307 end if
308 if (index(line, '=') <= 0) then
309 read(line, *, iostat=io) dummy, dummy1
310 if(dummy == 'mp_grid') then
311 message(1) = 'oct-wannier90: Warning: mp_grid specified in .win file' // &
312 ' is ignored. Using k-point mesh from octopus input instead.'
313 call messages_warning(1)
314 end if
315 end if
316 end do
317 call io_close(w90_win)
318
320 end subroutine wannier90lib_warn_inputs
321
325 subroutine wannier90lib_create_wannier90_amn(w90main, inp_options, &
326 band_index, space, mesh, latt, st, kpoints, projection)
327 type(lib_common_type), intent(in) :: w90main
328 type(wannier_opts_t), intent(in) :: inp_options
329 class(space_t), intent(in) :: space
330 class(mesh_t), intent(in) :: mesh
331 type(lattice_vectors_t), intent(in) :: latt
332 type(states_elec_t), intent(in) :: st
333 type(kpoints_t), intent(in) :: kpoints
334 integer, contiguous, intent(in) :: band_index(:)
335
336 complex(real64), contiguous, intent(out) :: projection(:, :, :)
337 type(wannier_calc_proj_t), allocatable :: proj_input_oct(:)
338
339 integer :: iw
342 call profiling_in("W90_AMN")
343
344 ! Note: in w90main, proj_input contains the projections from input file,
345 ! proj contains the projections that are actually used in wannier90
346 ! We use proj_input since that is also what is written to file in -pp mode
347
348
349 safe_allocate(proj_input_oct(1:w90main%num_proj))
350 do iw = 1, w90main%num_proj
351 proj_input_oct(iw)%l = w90main%proj_input(iw)%l
352 proj_input_oct(iw)%m = w90main%proj_input(iw)%m
353 proj_input_oct(iw)%s = w90main%proj_input(iw)%s
354 proj_input_oct(iw)%radial = w90main%proj_input(iw)%radial
355 proj_input_oct(iw)%site = w90main%proj_input(iw)%site
356 proj_input_oct(iw)%s_qaxis = w90main%proj_input(iw)%s_qaxis
357 proj_input_oct(iw)%z = w90main%proj_input(iw)%z
358 proj_input_oct(iw)%x = w90main%proj_input(iw)%x
359 proj_input_oct(iw)%zona = w90main%proj_input(iw)%zona
360 end do
361
362 call wannier_calc_create_amn(inp_options, &
363 band_index, space, mesh, latt, st, kpoints, &
364 w90main%wvfn_read%spin_channel, w90main%num_proj, &
365 proj_input_oct, projection)
366
367 safe_deallocate_a(proj_input_oct)
368
369 call profiling_out("W90_AMN")
370
372
374
378 subroutine wannier90lib_create_wannier90_mmn(w90main, band_index, mesh, st, latt, overlap)
379 type(lib_common_type), intent(in) :: w90main
380 integer, contiguous, intent(in) :: band_index(:)
381 class(mesh_t), intent(in) :: mesh
382 type(states_elec_t), target, intent(in) :: st
383 type(lattice_vectors_t), intent(in) :: latt ! will differ from ions%latt by 2*L for non-periodic systems
384
385 complex(real64), contiguous, intent(out) :: overlap(:, :, :, :)
386
388
389 call wannier_calc_create_mmn(band_index, &
390 mesh, st, latt, w90main%wvfn_read%spin_channel, &
391 w90main%kmesh_info%nnlist, w90main%kmesh_info%nncell, &
392 overlap)
393
395
397
402 subroutine wannier90lib_wannierization(w90main, gr, space, st, latt, kpoints, options, band_index, &
403 m_matrix, u_matrix_opt, last_u_matrix, warm_start)
404 type(lib_common_type), intent(inout) :: w90main
405 class(mesh_t), intent(in) :: gr
406 class(space_t), intent(in) :: space
407 type(states_elec_t), intent(in) :: st
408 type(lattice_vectors_t), intent(in) :: latt ! will differ from ions%latt by 2*L for non-periodic systems
409 type(kpoints_t), intent(in) :: kpoints
410 type(wannier_opts_t), intent(in) :: options
411 integer, contiguous, intent(in) :: band_index(:)
412 complex(real64), contiguous, intent(inout) :: m_matrix(:, :, :, :)
413 complex(real64), contiguous, intent(inout) :: u_matrix_opt(:, :, :)
414 complex(real64), contiguous, intent(in) :: last_u_matrix(:, :, :)
415 logical, optional, intent(in) :: warm_start
416
417 integer :: ierr
418 integer :: null_stdout
419 logical :: warm_start_
422
423 warm_start_ = .true.
424 if (present(warm_start)) warm_start_ = warm_start
425
426 ! Calls to libwannier90 produce output on every call. We suppress this output here
427 null_stdout = io_open('/dev/null', action='write', die=.false.)
428
429 ! Compute quantities required by wannier90
430 ! m matrix is always needed, as the overlaps change with time
431 call wannier90lib_create_wannier90_mmn(w90main, band_index, gr, st, latt, m_matrix)
432
433 ! Perform wannierization
434 if (.not. warm_start_) then
435 ! Cold start: initialize U from AMN projections
436 call wannier90lib_create_wannier90_amn(w90main, options, band_index, space, &
437 gr, latt, st, kpoints, u_matrix_opt)
438 else
439 ! Warm start: initialize U from previous wannierization result
440 u_matrix_opt(:, :, :) = last_u_matrix(:, :, :)
441 end if
442 ! Not needed for now, since num_bands \= num_wann is not yet supported
443 ! call w90_disentangle(w90main, null_stdout, stderr, ierr)
444 ! if (ierr /= 0) then
445 ! write(message(1), '(a,i0)') 'Error in w90_disentangle: ', ierr
446 ! call messages_fatal(1)
447 ! end if
448 call w90_project_overlap(w90main, null_stdout, stderr, ierr)
449 if (ierr /= 0) then
450 write(message(1), '(a,i0)') 'Error in w90_project_overlap: ', ierr
451 call messages_fatal(1)
452 end if
453 call w90_wannierise(w90main, null_stdout, stderr, ierr)
454 if (ierr /= 0) then
455 write(message(1), '(a,i0)') 'Error in w90_wannierise: ', ierr
456 call messages_fatal(1)
457 end if
458
459 call io_close(null_stdout)
460
462 end subroutine wannier90lib_wannierization
463
integer, parameter, public spin_polarized
Definition: io.F90:116
subroutine, public io_close(iunit, grp)
Definition: io.F90:467
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:402
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:525
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:631
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:554
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:134
This module defines the unit system, used for input and output.
type(unit_t), public unit_angstrom
For XYZ files.
type(unit_t), public unit_ev
For output energies in eV.
Interface module to Wannier 90 library.
subroutine, public wannier90lib_create_wannier90_mmn(w90main, band_index, mesh, st, latt, overlap)
Kohn-Sham State Overlap Matrix.
subroutine, public wannier90lib_create_wannier90_amn(w90main, inp_options, band_index, space, mesh, latt, st, kpoints, projection)
Calculate wannier90 Projection Matrix.
subroutine wannier90lib_set_atom_data(w90main, ions, latt)
Set atom data in wannier90 library.
subroutine, public wannier90lib_wannierization(w90main, gr, space, st, latt, kpoints, options, band_index, m_matrix, u_matrix_opt, last_u_matrix, warm_start)
Full wannierization.
subroutine, public wannier90lib_initialize_matrix_data(w90main, u_matrix, u_dis_matrix, m_matrix, centers)
Associate w90main object with matrix data.
subroutine wannier90lib_set_projections(w90main, inp_options)
Parse projections.
subroutine wannier90lib_warn_inputs(inp_options)
Check for options in .win file.
subroutine, public wannier90lib_init_w90main(namespace, ions, latt, kpoints, st, inp_options, w90main, stdout, stderr, ierr)
Initialize wannier90 library data.
Wannier90 related calculations.
subroutine, public wannier_calc_create_amn(wan_opts, band_index, space, mesh, latt, st, kpoints, spin_channel, num_proj, proj_input, projection)
Calculation of Wannier90 Projection Matrix.
subroutine, public wannier_calc_create_mmn(band_index, mesh, st, latt, spin_channel, nnlist, nncell, overlap)
Kohn-Sham State Overlap Matrix.
Wannier options module.
Describes mesh distribution to nodes.
Definition: mesh.F90:187
The states_elec_t class contains all electronic wave functions.
Mocks the projection type from wannier90.
Wannier related options.
int true(void)