Octopus
wannier.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
20#include "global.h"
21
24program wannier
25 use, intrinsic :: iso_fortran_env
26
28 use debug_oct_m
31 use fft_oct_m
32 use global_oct_m
33 use grid_oct_m
34 use io_oct_m
36 use ions_oct_m
38 use mpi_oct_m
42 use parser_oct_m
47 use unit_oct_m
52
53 ! External Wannier 90 library
54 use w90_library
55 use w90_library_extra, only:overlaps
56
57 implicit none
58
59 type(namespace_t) :: namespace
60 type(electrons_t), pointer :: sys
61 type(wannier_opts_t) :: wannier_opts
62 integer, allocatable :: band_index(:)
63
64 type(lib_common_type) :: w90main
65
66 complex(real64), allocatable :: m_matrix(:, :, :, :)
67 complex(real64), allocatable :: u_matrix(:, :, :)
68 complex(real64), allocatable :: u_matrix_opt(:, :, :)
69 real(real64), allocatable :: eigenvals(:,:)
70
71 integer, allocatable :: nnkp(:,:), gkpb(:,:,:)
72 logical, allocatable :: exclude_list(:)
73 integer :: nn, nk_local
74
75 integer :: idir, ik, ist, iband
76
77 integer :: ierr
78 real(real64) :: factor(3)
79
80 ! Initialise all Octopus singletons
81 call global_init()
82 call parser_init()
83 call messages_init()
84 call io_init()
85 namespace = namespace_t("Wannier90Lib", parent = global_namespace)
86 call profiling_init(namespace)
87 call fft_all_init(namespace)
88 call unit_system_init(namespace)
89
90 ! Initialise a system object
91 call calc_mode_par%set_parallelization(p_strategy_states, default = .false.)
92 sys => electrons_t(global_namespace, mpi_world, int(option__calculationmode__dummy, int32))
93
94 if (sys%space%dim /= 3) then ! see issue #1466
95 call messages_not_implemented("oct-wannier90lib: only 3D is supported")
96 end if
97
98 ! Sanity checks
99 if (sys%kpoints%use_symmetries) then
100 message(1) = 'oct-wannier90: k-points symmetries are not allowed'
101 call messages_fatal(1)
102 end if
103 if (sys%kpoints%use_time_reversal) then
104 message(1) = 'oct-wannier90: time-reversal symmetry is not allowed'
105 call messages_fatal(1)
106 end if
107 if (sys%kpoints%reduced%nshifts > 1) then
108 message(1) = 'oct-wannier90: Wannier90 does not allow for multiple shifts of the k-point grid'
109 call messages_fatal(1)
110 end if
111 if (sys%st%d%nspin == 4) then
112 call messages_not_implemented('oct-wannier90: Spinors currently not supported', namespace)
113 end if
114
115 ! "Correct" rlattice/klattice for Wannier90 (3D periodicity assumed here).
116 ! Note: this is how the lattice is scaled in src/utils/wannier90_interface.F90
117 factor = m_one
118 do idir = sys%space%periodic_dim+1, sys%space%dim
119 factor(idir) = m_two * sys%gr%box%bounding_box_l(idir)
120 end do
121 call sys%ions%latt%scale(factor)
122
123 ! Parsing all input related to wannier90
124 call wannier_opts%parse_oct(namespace)
125 call wannier_opts%parse_win()
126
127 ! Initialize wannier90 lib object
128 call wannier90lib_init_w90main(namespace, sys%ions, sys%ions%latt, sys%kpoints, sys%st, &
129 wannier_opts, w90main, stdout, stderr, ierr)
130 if (ierr /= 0) then
131 write(message(1),'(a,i0)') 'Error initializing wannier90 library: ', ierr
132 call messages_fatal(1)
133 end if
134
135 ! Check for consistency of spin polarization
136 if (sys%st%d%ispin /= unpolarized) then
137 call messages_experimental("oct-wannier90 with SpinComponents /= unpolarized")
138 elseif(sys%st%d%ispin == unpolarized .and. w90main%wvfn_read%spin_channel == 2) then
139 w90main%wvfn_read%spin_channel = 1
140 message(1) = "octopus was run with SpinComponents == unpolarized. Ignoring wannier90 spin input variable"
141 call messages_warning(1)
142 end if
143
144 ! Load octopus states
145 call wannier_calc_load_restart(global_namespace, sys%mc, sys%space, sys%st, sys%gr, sys%kpoints, wannier_opts%restart_from)
146
147 ! Update exclude_list and band_index based on wannier90 input from .win file (if any)
148 safe_allocate(exclude_list(1:sys%st%nst))
149 exclude_list = .false.
150 if (allocated(w90main%exclude_bands)) then
151 do iband = 1, size(w90main%exclude_bands)
152 ist = w90main%exclude_bands(iband)
153 exclude_list(ist) = .true.
154 end do
155 end if
156 ! Currently TD Wannier is not supported for exclude_band case
157 if (any(exclude_list)) then
158 call messages_not_implemented('TD Wannier: exclude_bands not supported.')
159 end if
160 safe_allocate(band_index(1:count(.not. exclude_list)))
161 band_index = pack([(ist, ist=1,sys%st%nst)], exclude_list .eqv. .false.)
162
163 ! Initial setup (previously in nnkp file)
164 call w90_get_nn(w90main, nn, stdout, stderr, ierr)
165 safe_allocate(nnkp(1:w90main%num_kpts, 1:nn))
166 safe_allocate(gkpb(1:3, 1:w90main%num_kpts, 1:nn))
167 call w90_get_nnkp(w90main, nnkp, stdout, stderr, ierr)
168 call w90_get_gkpb(w90main, gkpb, stdout, stderr, ierr)
169
170 ! Prepare computation of quantities required by Wannier90
171 ! m_matrix is distributed in k, matching wannier90''s m_matrix_local
172 nk_local = sys%st%d%kpt%nlocal()
173 if (sys%st%d%ispin == spin_polarized) nk_local = nk_local / 2
174 safe_allocate(m_matrix(1:wannier_opts%num_bands, 1:wannier_opts%num_bands, 1:nn, 1:nk_local))
175 safe_allocate(u_matrix_opt(1:wannier_opts%num_bands, 1:wannier_opts%num_wann, 1:w90main%num_kpts))
176 safe_allocate(eigenvals(1:wannier_opts%num_bands, 1:w90main%num_kpts))
177 safe_allocate(u_matrix(1:wannier_opts%num_wann, 1:wannier_opts%num_wann, 1:w90main%num_kpts))
178 call w90_set_m_local(w90main, m_matrix)
179 call w90_set_u_opt(w90main, u_matrix_opt)
180 call w90_set_u_matrix(w90main, u_matrix)
181
182 ! Get eigenvalues from octopus, shape is (num_bands, nk)
183 do ik = 1, w90main%num_kpts
184 do ist = 1, sys%st%nst
185 if (exclude_list(ist)) cycle
186 if (sys%st%d%ispin /= spin_polarized) then
187 eigenvals(band_index(ist), ik) = units_from_atomic(unit_ev, sys%st%eigenval(ist, ik))
188 else
189 eigenvals(band_index(ist), ik) = units_from_atomic(unit_ev, sys%st%eigenval(ist, (ik-1)*2+w90main%wvfn_read%spin_channel))
190 end if
191 end do
192 end do
193 call w90_set_eigval(w90main, eigenvals)
194
195 ! Compute or read quantities required by wannier90
196 if (wannier_opts%calc_overlaps) then
197 call wannier90lib_create_wannier90_mmn(w90main, band_index, sys%gr, sys%st, sys%ions%latt, m_matrix)
198 call wannier90lib_create_wannier90_amn(w90main, wannier_opts, band_index, sys%space, &
199 sys%gr, sys%ions%latt, sys%st, sys%kpoints, u_matrix_opt)
200 ! TODO: Revisit spin-polarised functionality once spin-unpolarised works
201 ! call create_wannier90_spn(sys%gr, sys%st)
202 ! TODO: Add write functions here and remove dump_inputs variable in wannier90
203 else
204 call overlaps(w90main, stdout, stderr, ierr)
205 if (ierr /= 0) then
206 write(message(1), '(a,i0)') 'Error while reading overlaps with wannier90: ', ierr
207 call messages_fatal(1)
208 end if
209 end if
210
211 ! Perform wannierization
212 if (wannier_opts%wannierize) then
213 call w90_disentangle(w90main, stdout, stderr, ierr)
214 if (ierr /= 0) then
215 write(message(1), '(a,i0)') 'Error in w90_disentangle: ', ierr
216 call messages_fatal(1)
217 end if
218 call w90_project_overlap(w90main, stdout, stderr, ierr)
219
221 if (ierr /= 0) then
222 write(message(1), '(a,i0)') 'Error in w90_project_overlap: ', ierr
223 call messages_fatal(1)
224 end if
225 call w90_wannierise(w90main, stdout, stderr, ierr)
226 if (ierr /= 0) then
227 write(message(1), '(a,i0)') 'Error in w90_wannierise: ', ierr
228 call messages_fatal(1)
229 end if
230 ! Avoid plotting from Wannier90
231 w90main%w90_calculation%wannier_plot = .false.
232 ! Output U matrices, hr.dat and more output files for plotting with octopus
233 call w90_plot(w90main, stdout, stderr, ierr)
234 if (ierr /= 0) then
235 write(message(1), '(a,i0)') 'Error in w90_plot: ', ierr
236 call messages_fatal(1)
237 end if
238 end if
239 ! if (wan_opts%plot) then
240 ! Here we generate wannier functions
241 ! Currently this is only meaningful after performing the wannierization
242 ! TODO: Check functionality to read U matrix from file
243 ! generate_wannier_states(space, mesh, ions, st, kpoints)
244 ! TODO: Port function to generate wannier states from old utility
245 ! end if
246
247 ! Free memory of variables in this scope
248 safe_deallocate_a(m_matrix)
249 safe_deallocate_a(u_matrix)
250 safe_deallocate_a(u_matrix_opt)
251 safe_deallocate_a(eigenvals)
252 safe_deallocate_a(exclude_list)
253 safe_deallocate_a(band_index)
254 safe_deallocate_a(nnkp)
255 safe_deallocate_a(gkpb)
256 safe_deallocate_p(sys)
257
258 ! End all singletons
259 call fft_all_end()
260 call io_end()
261 call profiling_end(namespace)
262 call messages_end()
263 call parser_end()
264 call global_end()
265
266end program wannier
This module handles the calculation mode.
type(calc_mode_par_t), public calc_mode_par
Singleton instance of parallel calculation mode.
integer, parameter, public p_strategy_states
parallelization in states
integer, parameter, public unpolarized
Parameters...
integer, parameter, public spin_polarized
Fast Fourier Transform module. This module provides a single interface that works with different FFT ...
Definition: fft.F90:120
subroutine, public fft_all_init(namespace)
initialize the table
Definition: fft.F90:303
subroutine, public fft_all_end()
delete all plans
Definition: fft.F90:418
real(real64), parameter, public m_two
Definition: global.F90:202
subroutine, public global_end()
Finalise parser varinfo file, and MPI.
Definition: global.F90:495
subroutine, public global_init(communicator)
Initialise Octopus.
Definition: global.F90:376
real(real64), parameter, public m_one
Definition: global.F90:201
This module implements the underlying real-space grid.
Definition: grid.F90:119
Definition: io.F90:116
subroutine, public io_init(defaults)
If the argument defaults is present and set to true, then the routine will not try to read anything f...
Definition: io.F90:165
subroutine, public io_end()
Definition: io.F90:271
subroutine, public messages_end()
Definition: messages.F90:273
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1068
subroutine, public messages_init(output_dir)
Definition: messages.F90:220
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_experimental(name, namespace)
Definition: messages.F90:1040
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:338
This module handles the communicators for the various parallelization strategies.
Definition: multicomm.F90:147
type(namespace_t), public global_namespace
Definition: namespace.F90:135
subroutine, public parser_init()
Initialise the Octopus parser.
Definition: parser.F90:410
subroutine, public parser_end()
End the Octopus parser.
Definition: parser.F90:442
subroutine, public profiling_end(namespace)
Definition: profiling.F90:415
subroutine, public profiling_init(namespace)
Create profiling subdirectory.
Definition: profiling.F90:257
This module defines routines to write information about states.
This module handles reading and writing restart information for the states_elec_t.
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.
subroutine, public unit_system_init(namespace)
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, 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_load_restart(namespace, mc, space, st, gr, kpoints, restart_states)
Load Octopus restart data from disk.
Wannier options module.
Class describing the electron system.
Definition: electrons.F90:222
int true(void)
program wannier
Construct maximally-localised Wannier functions through API calls to Wannier90 library.
Definition: wannier.F90:119