Octopus
wannier_calc.F90
Go to the documentation of this file.
1!! Copyright (C) A Buccheri, J Reimann. 2026
2!!
3!! This Source Code Form is subject to the terms of the Mozilla Public
4!! License, v. 2.0. If a copy of the MPL was not distributed with this
5!! file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
7#include "global.h"
8
11 use, intrinsic :: iso_fortran_env
12
14 use comm_oct_m
15 use debug_oct_m
17 use global_oct_m
18 use io_oct_m
19 use ions_oct_m
22 use mesh_oct_m
25 use mpi_oct_m
31 use space_oct_m
35 use types_oct_m
36 use unit_oct_m
39 use wfs_elec_oct_m, only: wfs_elec_t
41
42 implicit none
43 private
44
45 public :: &
54
60 integer :: l, m, s
61 integer :: radial = 1
62 real(real64) :: site(3)
63 real(real64) :: s_qaxis(3) = [0.0_real64, 0.0_real64, 1.0_real64]
64 real(real64) :: z(3) = [0.0_real64, 0.0_real64, 1.0_real64]
65 real(real64) :: x(3) = [1.0_real64, 0.0_real64, 0.0_real64]
66 real(real64) :: zona = 1.0_real64
67 end type wannier_calc_proj_t
68
69contains
70
75 subroutine wannier_calc_load_restart(namespace, mc, space, st, gr, kpoints, restart_states)
76 type(namespace_t), intent(in) :: namespace
77 type(multicomm_t), intent(in) :: mc
78 class(space_t), intent(inout) :: space
79 type(states_elec_t), intent(inout) :: st
80 class(mesh_t), intent(inout) :: gr
81 type(kpoints_t), intent(inout) :: kpoints
82 integer, optional, intent(in) :: restart_states
83 ! Defaults to ground state
84
85 integer :: restart_states_, ierr, nik, dim, nst
86 type(restart_t) :: restart
87
88 restart_states_ = optional_default(restart_states, restart_gs)
89 if (.not. (restart_states_ == restart_gs .or. restart_states_ == restart_td)) then
90 message(1) = 'Invalid restart_states value; expected RESTART_GS or RESTART_TD.'
91 call messages_fatal(1)
92 end if
93
94 call states_elec_allocate_wfns(st, gr, wfs_type = type_cmplx)
95 call restart%init(namespace, restart_states_, restart_type_load, mc, ierr, gr)
96
97 if (ierr /= 0) then
98 write(message(1),'(a)') 'Error opening restart file'
99 call messages_fatal(1)
100 endif
101
102 call states_elec_look(restart, nik, dim, nst, ierr)
103 if (st%d%ispin == spin_polarized) nik = nik / 2
104 if (dim /= st%d%dim) then
105 write(message(1),'(a)') 'Restart structure not commensurate, since spin dimensions differ.'
106 call messages_fatal(1)
107 else if (nik /= kpoints%reduced%npoints) then
108 write(message(1),'(a)') 'Restart structure not commensurate, since number of k-points differ.'
109 call messages_fatal(1)
110 else if (nst /= st%nst) then
111 write(message(1),'(a)') 'Restart structure not commensurate, since number of states differ.'
112 call messages_fatal(1)
113 end if
114
115 call states_elec_load(restart, namespace, space, st, gr, kpoints, fixed_occ=st%restart_fixed_occ , &
116 ierr=ierr, label = ": wannier90")
117 call restart%end()
118
119 end subroutine wannier_calc_load_restart
120
121 ! TODO: Removed SCDM - Should reintroduce once the code is working
127 subroutine wannier_calc_create_amn(wan_opts, exclude_list, &
128 band_index, space, mesh, latt, st, kpoints, &
129 spin_channel, num_proj, proj_input, projection)
130 type(wannier_opts_t), intent(in) :: wan_opts
131 class(space_t), intent(in) :: space
132 class(mesh_t), intent(in) :: mesh
133 type(lattice_vectors_t), intent(in) :: latt
134 type(states_elec_t), intent(in) :: st
135 type(kpoints_t), intent(in) :: kpoints
136 logical, intent(in) :: exclude_list(:)
137 integer, intent(in) :: band_index(:)
138 integer, intent(in) :: spin_channel
139 integer, intent(in) :: num_proj
140 type(wannier_calc_proj_t), intent(in) :: proj_input(:)
141
142 complex(real64), contiguous, intent(out) :: projection(:, :, :)
143
144 integer :: ist, ik, idim, iw, ip, ik_real, iband, num_kpts
145 real(real64) :: center(3), kpoint(3)
146
147 complex(real64), allocatable :: psi(:,:), phase(:)
148 real(real64), allocatable :: ylm(:)
149 type(orbitalset_t), allocatable :: orbitals(:)
150
152 call profiling_in("W90_AMN")
153
154 if (st%parallel_in_states) then
155 call messages_not_implemented("w90_amn output with states parallelization")
156 end if
158 message(1) = "Info: Computing the projection matrix"
161 assert(num_proj == size(proj_input))
162
163 num_kpts = product(kpoints%nik_axis(1:3))
164
165 ! Precompute orbitals
166 safe_allocate(orbitals(1:num_proj))
167 do iw=1, num_proj
168 call orbitalset_init(orbitals(iw))
169
170 orbitals(iw)%norbs = 1
171 orbitals(iw)%ndim = 1
172 orbitals(iw)%radius = -log(wan_opts%threshold)
173 orbitals(iw)%use_submesh = .false.
174
175 ! cartesian coordinate of orbital center
176 center(1:3) = latt%red_to_cart(proj_input(iw)%site(1:3))
177 call submesh_init(orbitals(iw)%sphere, space, mesh, latt, center, orbitals(iw)%radius)
178
179 ! get dorb as submesh points
180 safe_allocate(ylm(1:orbitals(iw)%sphere%np))
181 ! (this is a routine from pwscf)
182 call ylm_wannier(ylm, proj_input(iw)%l, proj_input(iw)%m, &
183 orbitals(iw)%sphere%r, orbitals(iw)%sphere%rel_x, orbitals(iw)%sphere%np)
184
185 if (proj_input(iw)%radial /= 1) then
186 call messages_not_implemented("oct-wannier90: r/=1 for the radial part")
187 end if
188
189 ! apply radial function
190 do ip = 1, orbitals(iw)%sphere%np
191 ylm(ip) = ylm(ip) * m_two * exp(-orbitals(iw)%sphere%r(ip))
192 end do
193
194 ! NOTE(Alex) One can probably fill directly into zorb, and avoid allocating ylm
195 safe_allocate(orbitals(iw)%zorb(1:orbitals(iw)%sphere%np, 1:1, 1:1))
196 orbitals(iw)%zorb(1:orbitals(iw)%sphere%np, 1, 1) = ylm(1:orbitals(iw)%sphere%np)
197 safe_deallocate_a(ylm)
198
199 safe_allocate(orbitals(iw)%phase(1:orbitals(iw)%sphere%np, st%d%kpt%start:st%d%kpt%end))
200 orbitals(iw)%phase = m_z0
201 safe_allocate(orbitals(iw)%eorb_mesh(1:mesh%np, 1:1, 1:1, st%d%kpt%start:st%d%kpt%end))
202 orbitals(iw)%eorb_mesh = m_z0
203
204 call orbitalset_update_phase(orbitals(iw), space%dim, st%d%kpt, kpoints, st%d%ispin == spin_polarized, &
205 kpt_max = num_kpts)
206 end do
207
208 ! Compute the projections
209 safe_allocate(psi(1:mesh%np, 1:st%d%dim))
210 safe_allocate(phase(1:mesh%np))
211 projection = m_zero
212
213 do ik = 1, num_kpts
214 kpoint(1:space%dim) = kpoints%get_point(ik)
215 do ip = 1, mesh%np
216 phase(ip) = exp(-m_zi * sum(mesh%x(1:space%dim, ip) * kpoint(1:space%dim)))
217 end do
218
219 !For spin-polarized calculations, we select the right k-point
220 if (st%d%ispin == spin_polarized) then
221 ik_real = (ik-1)*2 + spin_channel
222 else
223 ik_real = ik
224 end if
225
226 ! TODO(Alex) ist and iw loops need interchanging to optimise array access
227 do ist = 1, st%nst
228 if (exclude_list(ist)) cycle
229 iband = band_index(ist)
230
231 if(ik_real >= st%d%kpt%start .and. ik_real <= st%d%kpt%end) then
232 call states_elec_get_state(st, mesh, ist, ik_real, psi)
233
234 do idim = 1, st%d%dim
235 do ip = 1, mesh%np
236 psi(ip, idim) = psi(ip, idim)*phase(ip)
237 end do
238 end do
239
240 do iw = 1, num_proj
241 idim = 1
242 if (wan_opts%spinors) idim = wan_opts%spin_proj_component(iw)
243 !At the moment the orbitals do not depend on idim
244 !The idim index for eorb_mesh would be for a spin-resolved orbital like j=1/2
245 projection(iband, iw, ik) = zmf_dotp(mesh, psi(1:mesh%np, idim), &
246 orbitals(iw)%eorb_mesh(1:mesh%np, 1, 1, ik_real), reduce = .false.)
247 end do
248
249 call profiling_in("W90_AMN_REDUCE")
250 call mesh%allreduce(projection(iband, :, ik))
251 call profiling_out("W90_AMN_REDUCE")
252 end if
253
254 if(st%d%kpt%parallel) then
255 call comm_allreduce(st%d%kpt%mpi_grp, projection(iband, :, ik))
256 end if
257
258 end do !ist
259 end do !ik
260
261 safe_deallocate_a(psi)
262 safe_deallocate_a(phase)
263
264 do iw = 1, num_proj
265 call orbitalset_end(orbitals(iw))
266 end do
267 safe_deallocate_a(orbitals)
268
269 call profiling_out("W90_AMN")
270
272
273 end subroutine wannier_calc_create_amn
274
284 subroutine wannier_calc_create_mmn(exclude_list, band_index, mesh, st, ions, &
285 spin_channel, nnlist, nncell, overlap)
286 logical, intent(in) :: exclude_list(:)
287 integer, intent(in) :: band_index(:)
288 class(mesh_t), intent(in) :: mesh
289 type(states_elec_t), target, intent(in) :: st
290 type(ions_t), intent(in) :: ions
291 integer, intent(in) :: spin_channel
292 integer, intent(in) :: nnlist(:,:)
293 integer, intent(in) :: nncell(:,:,:)
294
295 complex(real64), contiguous, intent(out) :: overlap(:, :, :, :)
296
297 integer :: ist, jst, ik, ip, iknn, idim, ibind
298 integer :: ik_oct, iknn_oct, inn
299 integer :: ik_loc
300 integer :: iband, jband, inode, node_fr, node_to
301 real(real64) :: gcart(3)
302 integer :: g(3)
303
304 integer :: nntot, num_kpts
305
306 complex(real64), allocatable :: psim(:,:), psin(:,:), phase(:)
307 type(wfs_elec_t), pointer :: batch
308 type(mpi_request) :: send_req
309
311
312 call profiling_in("W90_MMN")
313
314
315 nntot = size(nnlist, 2)
316 num_kpts = size(nnlist, 1)
317 assert(size(nnlist, 1) == num_kpts)
318 assert(size(nncell, 1) == 3)
319 assert(size(nncell, 2) == num_kpts)
320 assert(size(nncell, 3) == nntot)
321
322 if (st%parallel_in_states) then
323 call messages_not_implemented("w90_mmn output with states parallelization")
324 end if
325
326 message(1) = "Info: Computing the overlap matrix for wannerisation"
327 call messages_info(1)
328
329 overlap = m_zero
330 safe_allocate(psim(1:mesh%np, 1:st%d%dim))
331 safe_allocate(psin(1:mesh%np, 1:st%d%dim))
332 safe_allocate(phase(1:mesh%np))
333
334 if (st%d%kpt%parallel) ik_loc = 0
335
336 ! loop over the pairs specified in the nnk tuple
337 do ik = 1, num_kpts
338 do inn = 1, nntot
339
340 iknn = nnlist(ik, inn)
341 g(1:3) = nncell(:, ik, inn)
342
343 ! For spin-polarized calculations, we select the right k-point
344 if (st%d%ispin == spin_polarized) then
345 ik_oct = (ik-1)*2 + spin_channel
346 iknn_oct = (iknn-1)*2 + spin_channel
347 else
348 ik_oct = ik
349 iknn_oct = iknn
350 end if
351
352 ! If the k-point is local, compute the phase e^{-i G.r}
353 if(ik_oct >= st%d%kpt%start .and. ik_oct <= st%d%kpt%end) then
354 ! Wannier90 treats everything fully periodic
355 ! Conversion is done with the 3D "correct" klattice
356 call kpoints_to_absolute(ions%latt, real(g, real64) , gcart)
357
358 ! Phase that gives u_{n,k+G}(r) from u_{nk}(r)
359 ! Here the minus sign of Octopus cancels with minus sign of the input G
360 ! (ik and iknn correspond in the list to minus the k-points in Octopus)
361 if (any(g /= 0)) then
362 do ip = 1, mesh%np
363 phase(ip) = exp(-m_zi*dot_product(mesh%x(1:3, ip), gcart(1:3)))
364 end do
365 end if
366 end if
367
368 ! Loop over distributed bands
369 do jst = 1, st%nst
370 if (exclude_list(jst)) cycle
371 jband = band_index(jst)
372
373 if (st%d%kpt%parallel) then
374 node_fr = -1
375 node_to = -1
376 do inode = 0, st%d%kpt%mpi_grp%size-1
377 if(iknn_oct >= st%st_kpt_task(inode,3) .and. iknn_oct <= st%st_kpt_task(inode,4)) then
378 node_fr = inode
379 end if
380 if(ik_oct >= st%st_kpt_task(inode,3) .and. ik_oct <= st%st_kpt_task(inode,4)) then
381 node_to = inode
382 end if
383 end do
384 assert(node_fr > -1)
385 assert(node_to > -1)
386 send_req = mpi_request_null
387 ! We have locally the k-point
388 if (state_kpt_is_local(st, jst, iknn_oct)) then
389 call states_elec_get_state(st, mesh, jst, iknn_oct, psin)
390 ! We send it only if we don`t want to use it locally
391 if(node_to /= st%d%kpt%mpi_grp%rank) then
392 call st%d%kpt%mpi_grp%isend(psin, mesh%np*st%d%dim, mpi_double_complex, node_to, send_req)
393 end if
394 end if
395 ! We receive the desired state, only if it is not a local one
396 if(node_to == st%d%kpt%mpi_grp%rank .and. node_to /= node_fr) then
397 call st%d%kpt%mpi_grp%recv(psin, mesh%np*st%d%dim, mpi_double_complex, node_fr)
398 end if
399 if (send_req /= mpi_request_null) then
400 call st%d%kpt%mpi_grp%wait(send_req)
401 end if
402 else
403 call states_elec_get_state(st, mesh, jst, iknn_oct, psin)
404 end if
405
406 if(ik_oct >= st%d%kpt%start .and. ik_oct <= st%d%kpt%end) then
407
408 ! Do not apply the phase if the phase factor is 1
409 if (any(g /= 0)) then
410 do idim = 1, st%d%dim
411 do ip = 1, mesh%np
412 psin(ip, idim) = psin(ip, idim) * phase(ip)
413 end do
414 end do
415 end if
416
417 ! See Eq. (25) in PRB 56, 12847 (1997)
418 ! Loop over local k-points
419 do ist = 1, st%nst
420 if (exclude_list(ist)) cycle
421 iband = band_index(ist)
422
423 batch => st%group%psib(st%group%iblock(ist), ik_oct)
424
425 select case (batch%status())
426 case (batch_not_packed)
427 overlap(iband, jband, inn, ik) = m_z0
428 do idim = 1, st%d%dim
429 ibind = batch%inv_index((/ist, idim/))
430 overlap(iband, jband, inn, ik) = overlap(iband, jband, inn, ik) + &
431 zmf_dotp(mesh, batch%zff_linear(:, ibind), psin(:,idim), reduce = .false.)
432 end do
433 !Not properly done at the moment
435 call states_elec_get_state(st, mesh, ist, ik_oct, psim)
436 overlap(iband, jband, inn, ik) = zmf_dotp(mesh, st%d%dim, psim, psin, reduce = .false.)
437 end select
438 end do !ist
439 end if
440
441 call profiling_in("W90_MMN_REDUCE")
442 call mesh%allreduce(overlap(:, jband, inn, ik))
443 call profiling_out("W90_MMN_REDUCE")
444
445 if(st%d%kpt%parallel) then
446 call comm_allreduce(st%d%kpt%mpi_grp, overlap(:, jband, inn, ik))
447 end if
448 end do !jst
449 end do !inn
450
451 ! This contains a necessary remap: wannier90 only stores the local m_matrix, so it stores
452 ! only the first nk_rank kpoints in the matrix. The following block remaps from the global
453 ! kpoint to the local kpoint
454 if (st%d%kpt%parallel) then
455 if (st%d%ispin == spin_polarized) then
456 ik_oct = (ik-1)*2 + spin_channel
457 else
458 ik_oct = ik
459 end if
460 if (ik_oct >= st%d%kpt%start .and. ik_oct <= st%d%kpt%end) then
461 ik_loc = ik_loc + 1
462 if (ik_loc /= ik) then
463 overlap(:, :, :, ik_loc) = overlap(:, :, :, ik)
464 end if
465 end if
466 end if
467 end do !ik
468
469 safe_deallocate_a(psim)
470 safe_deallocate_a(psin)
471 safe_deallocate_a(phase)
472
473 call profiling_out("W90_MMN")
474
476
477 end subroutine wannier_calc_create_mmn
478
483 subroutine wannier_calc_read_centers(wan_opts, centers)
484 type(wannier_opts_t), intent(in) :: wan_opts
485 real(real64), intent(inout) :: centers(:, :)
486
487 integer :: w90_xyz, iw
488 character(len=2) :: dum
489 logical :: exist
490
492
493 assert(size(centers, 2) == wan_opts%num_wann)
494 assert(size(centers, 1) == 3)
495
496 inquire(file=trim(adjustl(wan_opts%prefix))//'_centres.xyz',exist=exist)
497 if (.not. exist) then
498 message(1) = 'Cannot find the Wannier90 file seedname_centres.xyz.'
499 call messages_fatal(1)
500 end if
501
502 w90_xyz = io_open(trim(adjustl(wan_opts%prefix))//'_centres.xyz', global_namespace, action='read')
503
504 !Skip two lines
505 read(w90_xyz, *)
506 read(w90_xyz, *)
507 do iw = 1, wan_opts%num_wann
508 read(w90_xyz, *) dum, centers(1:3, iw)
509 ! Wannier90 outputs the coordinates in angstrom
510 centers(1:3, iw) = units_to_atomic(unit_angstrom, centers(1:3, iw))
511 end do
512 call io_close(w90_xyz)
513
515 end subroutine wannier_calc_read_centers
516
521 subroutine wannier_calc_read_u_matrices(wan_opts, kpoints, u_matrix, u_dis_matrix)
522 type(wannier_opts_t), intent(in) :: wan_opts
523 type(kpoints_t), intent(in) :: kpoints
524 complex(real64), intent(inout) :: u_matrix(:, :, :)
525 complex(real64), intent(inout) :: u_dis_matrix(:, :, :)
526
527 integer :: w90_u_mat, w90_u_dis, ik, ib, iw, iw2, nik, nwann, nib
528 integer :: num_kpts
529 logical :: exist, have_disentangled
530
531 num_kpts = product(kpoints%nik_axis(1:3))
532
534
535 inquire(file=trim(adjustl(wan_opts%prefix))//'_u.mat',exist=exist)
536 if (.not. exist) then
537 message(1) = 'Cannot find the Wannier90 seedname_u.mat file.'
538 call messages_fatal(1)
539 end if
540 w90_u_mat = io_open(trim(adjustl(wan_opts%prefix))//'_u.mat', global_namespace, action='read')
541
542 !Skip one line
543 read(w90_u_mat, *)
544 !Read num_kpts, num_wann, num_wann for consistency check
545 read(w90_u_mat, *) nik, nwann, nwann
546 if (nik /= num_kpts .or. nwann /= wan_opts%num_wann) then
547 message(1) = "The U matrix has inconsistent shape."
548 call messages_fatal(1)
549 end if
550
551 do ik = 1, num_kpts
552 !Skip one line
553 read(w90_u_mat, *)
554 !Skip one line (k-point coordinate)
555 read(w90_u_mat, *)
556 read(w90_u_mat, '(f15.10,sp,f15.10)') ((u_matrix(iw, iw2, ik), iw=1, wan_opts%num_wann), iw2=1, wan_opts%num_wann)
557 end do
558
559 call io_close(w90_u_mat)
560
561 inquire(file=trim(adjustl(wan_opts%prefix))//'_u_dis.mat',exist=have_disentangled)
562 if (have_disentangled) then
563 ! Read u_dis.mat: dimensions are (w90_num_bands x w90_num_wann) per k-point.
564 ! The band rows follow the compressed, non-excluded band ordering used by
565 ! the rest of the Wannier90 interface (i.e. after applying exclude_bands).
566 w90_u_dis = io_open(trim(adjustl(wan_opts%prefix))//'_u_dis.mat', global_namespace, action='read')
567 !Skip one line
568 read(w90_u_dis, *)
569 !Read num_kpts, num_wann, num_bands for consistency check
570 read(w90_u_dis, *) nik, nwann, nib
571 if (nik /= num_kpts .or. nwann /= wan_opts%num_wann .or. nib /= wan_opts%num_bands) then
572 message(1) = 'The u_dis matrix has inconsistent shape.'
573 call messages_fatal(1)
574 end if
575
576 do ik = 1, num_kpts
577 !Skip one line
578 read(w90_u_dis, *)
579 !Skip one line (k-point coordinate)
580 read(w90_u_dis, *)
581 read(w90_u_dis, '(f15.10,sp,f15.10)') ((u_dis_matrix(ib, iw, ik), ib=1, wan_opts%num_bands), iw=1, wan_opts%num_wann)
582 end do
583
584 call io_close(w90_u_dis)
585
586 ! In case of disentanglement, u_dis matrix needs to be reordered to the correct layout.
587 ! See issue #1465.
588 end if
589
591 end subroutine wannier_calc_read_u_matrices
592
596 subroutine wannier_calc_write_centers(dir, prefix, centers, ions)
597 character(len=*), intent(in) :: dir
598 character(len=*), intent(in) :: prefix
599 real(real64), intent(in) :: centers(:, :)
600 class(ions_t), intent(in) :: ions
601
602 integer :: w90_xyz, iw, ia, ind
603 character(len=512) :: header
604 integer :: date_time(8)
605
607
608 w90_xyz = io_open(trim(adjustl(dir))//'/'//trim(adjustl(prefix))//'_centres.xyz', global_namespace, action='write', die=.false.)
609 if (w90_xyz == -1) then
610 message(1) = 'Unable to open output file '//trim(adjustl(prefix))//'_centres.xyz for writing.'
611 call messages_fatal(1)
612 end if
613
614 ! Get current date and time
615 call date_and_time(values=date_time)
617 write(w90_xyz, '(i6)') size(centers, 2) + ions%natoms
618 write(header, '(a,i4,a1,i2.2,a1,i2.2,a,i2.2,a1,i2.2,a1,i2.2)') &
619 'Wannier centers, written by octopus on ', date_time(1), '/', date_time(2), '/', date_time(3), &
620 ' at ', date_time(5), ':', date_time(6), ':', date_time(7)
621 write (w90_xyz, *) trim(header)
622
623 do iw = 1, size(centers, 2)
624 write(w90_xyz, '("X",6x,3(f14.8,3x))') &
625 (units_from_atomic(unit_angstrom, centers(ind, iw)), ind=1, 3)
626 end do
627 do ia = 1, ions%natoms
628 write(w90_xyz, '(a2,5x,3(f14.8,3x))') trim(ions%atom(ia)%label), &
629 (units_from_atomic(unit_angstrom, ions%pos(ind, ia)), ind=1, 3)
630 end do
631 call io_close(w90_xyz)
632
634
635 end subroutine wannier_calc_write_centers
636
641 subroutine wannier_calc_write_u_matrices(dir, prefix, kpoints, u_matrix, u_dis_matrix)
642 character(len=*), intent(in) :: dir
643 character(len=*), intent(in) :: prefix
644 type(kpoints_t), intent(in) :: kpoints
645 complex(real64), intent(in) :: u_matrix(:, :, :)
646 complex(real64), intent(in) :: u_dis_matrix(:, :, :)
647
648 integer :: w90_u_mat, w90_u_dis
649 logical :: have_disentangled
650 integer :: i, j, nkp, num_wann, num_bands, num_kpts
651 character(len=512) :: header
652 integer :: date_time(8)
653
654 num_kpts = size(u_matrix, 3)
655 num_wann = size(u_matrix, 1)
656 num_bands = size(u_dis_matrix, 1)
657 assert(num_kpts == size(kpoints%reduced%red_point, 2))
658
660
661 ! Get current date and time
662 call date_and_time(values=date_time)
663
664 w90_u_mat = io_open(trim(adjustl(dir))//'/'//trim(adjustl(prefix))//'_u.mat', global_namespace, action='write', die=.false.)
665 if (w90_u_mat == -1) then
666 message(1) = 'Unable to open output file '//trim(adjustl(prefix))//'_u.mat for writing.'
667 call messages_fatal(1)
668 end if
669
670 write(header, '(a,i4,a1,i2.2,a1,i2.2,a,i2.2,a1,i2.2,a1,i2.2)') &
671 'written on ', date_time(1), '/', date_time(2), '/', date_time(3), &
672 ' at ', date_time(5), ':', date_time(6), ':', date_time(7)
673 write (w90_u_mat, *) trim(header)
674 write (w90_u_mat, *) num_kpts, num_wann, num_wann
675
676 do nkp = 1, num_kpts
677 write (w90_u_mat, *)
678 write (w90_u_mat, '(f15.10,sp,f15.10,sp,f15.10)') -kpoints%reduced%red_point(1:3, nkp)
679 write (w90_u_mat, '(f15.10,sp,f15.10)') ((u_matrix(i, j, nkp), i=1, num_wann), j=1, num_wann)
680 end do
681
682 call io_close(w90_u_mat)
683
684 inquire(file=trim(trim(adjustl(prefix))//'_u_dis.mat'),exist=have_disentangled)
685 if (have_disentangled) then
686
687 w90_u_dis = io_open(trim(adjustl(dir))//'/'//trim(adjustl(prefix))//'_u_dis.mat', &
688 global_namespace, action='write', die=.false.)
689 if (w90_u_dis == -1) then
690 message(1) = 'Unable to open output file '//trim(adjustl(prefix))//'_u_dis.mat for writing.'
692 end if
693
694 write (w90_u_dis, *) trim(header)
695 write (w90_u_dis, *) num_kpts, num_wann, num_bands
696 do nkp = 1, num_kpts
697 write (w90_u_dis, *)
698 write (w90_u_dis, '(f15.10,sp,f15.10,sp,f15.10)') -kpoints%reduced%red_point(1:3, nkp)
699 write (w90_u_dis, '(f15.10,sp,f15.10)') ((u_dis_matrix(i, j, nkp), i=1, num_bands), j=1, num_wann)
700 end do
701
702 call io_close(w90_u_dis)
703 end if
704
706
707 end subroutine wannier_calc_write_u_matrices
708
709end module wannier_calc_oct_m
double log(double __x) __attribute__((__nothrow__
double exp(double __x) __attribute__((__nothrow__
This module implements batches of mesh functions.
Definition: batch.F90:135
integer, parameter, public batch_not_packed
functions are stored in CPU memory, unpacked order
Definition: batch.F90:286
integer, parameter, public batch_device_packed
functions are stored in device memory in packed order
Definition: batch.F90:286
integer, parameter, public batch_packed
functions are stored in CPU memory, in transposed (packed) order
Definition: batch.F90:286
integer, parameter, public spin_polarized
real(real64), parameter, public m_two
Definition: global.F90:202
real(real64), parameter, public m_zero
Definition: global.F90:200
complex(real64), parameter, public m_z0
Definition: global.F90:210
complex(real64), parameter, public m_zi
Definition: global.F90:214
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
subroutine, public kpoints_to_absolute(latt, kin, kout)
Definition: kpoints.F90:1137
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1068
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
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 orbitalset_init(this)
Definition: orbitalset.F90:209
subroutine, public orbitalset_end(this)
Definition: orbitalset.F90:235
subroutine, public orbitalset_update_phase(os, dim, kpt, kpoints, spin_polarized, vec_pot, vec_pot_var, kpt_max)
Build the phase correction to the global phase in case the orbital crosses the border of the simulato...
Definition: orbitalset.F90:285
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
integer, parameter, public restart_gs
Definition: restart.F90:156
integer, parameter, public restart_td
Definition: restart.F90:156
integer, parameter, public restart_type_load
Definition: restart.F90:184
logical function, public state_kpt_is_local(st, ist, ik)
check whether a given state (ist, ik) is on the local node
subroutine, public states_elec_allocate_wfns(st, mesh, wfs_type, skip, packed)
Allocates the KS wavefunctions defined within a states_elec_t structure.
subroutine, public states_elec_look(restart, nik, dim, nst, ierr)
Reads the 'states' file in the restart directory, and finds out the nik, dim, and nst contained in it...
This module handles reading and writing restart information for the states_elec_t.
subroutine, public states_elec_load(restart, namespace, space, st, mesh, kpoints, fixed_occ, ierr, iter, lr, lowest_missing, label, verbose, skip)
returns in ierr: <0 => Fatal error, or nothing read =0 => read all wavefunctions >0 => could only rea...
subroutine, public submesh_init(this, space, mesh, latt, center, rc)
Definition: submesh.F90:226
type(type_t), parameter, public type_cmplx
Definition: types.F90:136
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.
Wannier90 related calculations.
subroutine, public wannier_calc_write_centers(dir, prefix, centers, ions)
Write wannier centers to file.
subroutine, public wannier_calc_read_centers(wan_opts, centers)
Read wannier centers.
subroutine, public wannier_calc_create_amn(wan_opts, exclude_list, band_index, space, mesh, latt, st, kpoints, spin_channel, num_proj, proj_input, projection)
Calculation of Wannier90 Projection Matrix.
subroutine, public wannier_calc_write_u_matrices(dir, prefix, kpoints, u_matrix, u_dis_matrix)
Write U and U_dis matrices to file.
subroutine, public wannier_calc_read_u_matrices(wan_opts, kpoints, u_matrix, u_dis_matrix)
Read wannier transformation matrix.
subroutine, public wannier_calc_load_restart(namespace, mc, space, st, gr, kpoints, restart_states)
Load Octopus restart data from disk.
subroutine, public wannier_calc_create_mmn(exclude_list, band_index, mesh, st, ions, spin_channel, nnlist, nncell, overlap)
Kohn-Sham State Overlap Matrix.
Wannier options module.
subroutine, public ylm_wannier(ylm, l, mr, rr, xx, nr)
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.
batches of electronic states
Definition: wfs_elec.F90:141
real(real64) function values(xx)
Definition: test.F90:2147