Octopus
berry.F90
Go to the documentation of this file.
1!! Copyright (C) 2010 D. Strubbe
2!! Copyright (C) 2026 N. Tancogne-Dejean
3!!
4!! This program is free software; you can redistribute it and/or modify
5!! it under the terms of the GNU General Public License as published by
6!! the Free Software Foundation; either version 2, or (at your option)
7!! any later version.
8!!
9!! This program is distributed in the hope that it will be useful,
10!! but WITHOUT ANY WARRANTY; without even the implied warranty of
11!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12!! GNU General Public License for more details.
13!!
14!! You should have received a copy of the GNU General Public License
15!! along with this program; if not, write to the Free Software
16!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17!! 02110-1301, USA.
18!!
19
20#include "global.h"
21
30module berry_oct_m
32 use comm_oct_m
33 use debug_oct_m
36 use global_oct_m
37 use grid_oct_m
40 use ions_oct_m
41 use io_oct_m, only: io_open, io_close
42 use, intrinsic :: iso_fortran_env
46 use mesh_oct_m
50 use mpi_oct_m
53 use parser_oct_m
55 use smear_oct_m
56 use space_oct_m
60 use types_oct_m
61 use unit_oct_m
63 use utils_oct_m
64 use v_ks_oct_m
66
67 implicit none
68
69 private
70 public :: &
71 berry_t, &
72 berry_init, &
79
81 type berry_t
82 private
83
84 integer :: max_iter_berry
85 end type berry_t
86contains
87
88 ! ---------------------------------------------------------
89 subroutine berry_init(this, namespace)
90 type(berry_t), intent(inout) :: this
91 type(namespace_t), intent(in) :: namespace
92
93 push_sub(berry_init)
94
95 !%Variable MaximumIterBerry
96 !%Type integer
97 !%Default 10
98 !%Section SCF::Convergence
99 !%Description
100 !% Maximum number of iterations for the Berry potential, within each SCF iteration.
101 !% Only applies if a <tt>StaticElectricField</tt> is applied in a periodic direction.
102 !% The code will move on to the next SCF iteration even if convergence
103 !% has not been achieved. -1 means unlimited.
104 !%End
105 call parse_variable(namespace, 'MaximumIterBerry', 10, this%max_iter_berry)
106 if (this%max_iter_berry < 0) this%max_iter_berry = huge(this%max_iter_berry)
107
108
109 pop_sub(berry_init)
110 end subroutine berry_init
111
112 ! ---------------------------------------------------------
118 subroutine berry_write_polarization(namespace, space, mesh, st, ions, kpoints, iunit)
119 type(namespace_t), intent(in) :: namespace
120 class(space_t), intent(in) :: space
121 class(mesh_t), intent(in) :: mesh
122 type(states_elec_t), intent(in) :: st
123 type(ions_t), intent(in) :: ions
124 type(kpoints_t), intent(in) :: kpoints
125 integer, intent(in) :: iunit
126
127 integer :: idir, pol_iunit
128 real(real64) :: berry_phase(space%dim)
129 real(real64) :: electronic_dipole(space%dim), ionic_dipole(space%dim), total_dipole(space%dim)
130 real(real64) :: electronic_pol(space%dim), ionic_pol(space%dim), total_pol(space%dim)
131 real(real64) :: pol_quantum(space%dim), volume
132
134
135 if (.not. space%is_periodic()) then
136 message(1) = "SCFCalculatePolarization requires a periodic system."
137 call messages_fatal(1, namespace=namespace)
138 end if
139
140 if (kpoints%use_symmetries) then
141 message(1) = "SCFCalculatePolarization requires the full k-point grid."
142 message(2) = "Set KPointsUseSymmetries = no."
143 call messages_fatal(2, namespace=namespace)
144 end if
145
146 if (bitand(kpoints%method, kpoints_monkh_pack) == 0 .or. &
147 bitand(kpoints%method, kpoints_user) /= 0 .or. bitand(kpoints%method, kpoints_path) /= 0) then
148 message(1) = "SCFCalculatePolarization currently requires a Monkhorst-Pack KPointsGrid."
149 call messages_fatal(1, namespace=namespace)
150 end if
151
152 if (kpoints%reduced%npoints /= kpoints%full%npoints) then
153 message(1) = "SCFCalculatePolarization requires unreduced k-points."
154 call messages_fatal(1, namespace=namespace)
155 end if
156
157 ! With more than one shift the grid labels no longer identify a k-point.
158 if (kpoints%full%nshifts /= 1) then
159 message(1) = "SCFCalculatePolarization requires a KPointsGrid with a single shift."
160 call messages_fatal(1, namespace=namespace)
161 end if
162
163 if (st%parallel_in_states) then
164 call messages_not_implemented("SCFCalculatePolarization with states parallelization", namespace=namespace)
165 end if
166
167 if (.not. smear_is_semiconducting(st%smear) .and. .not. st%smear%integral_occs) then
168 message(1) = "SCFCalculatePolarization requires integer occupations."
169 call messages_fatal(1, namespace=namespace)
170 end if
171
172 call berry_polarization_phase(namespace, space, mesh, st, ions%latt, kpoints, berry_phase)
173
174 electronic_dipole = m_zero
175 do idir = 1, space%periodic_dim
176 electronic_dipole(1:space%dim) = electronic_dipole(1:space%dim) &
177 + berry_phase(idir) * ions%latt%rlattice(1:space%dim, idir) / (m_two*m_pi)
178 end do
180 ! ions_dipole() returns P_PROTON_CHARGE * sum_I Z_I R_I, that is minus the
181 ! ionic dipole, following the same convention as in calc_dipole below.
182 ! The result is defined up to a quantum of polarization
183 ionic_dipole = ions%latt%fold_into_cell(-ions%dipole())
184 total_dipole = ions%latt%fold_into_cell(electronic_dipole + ionic_dipole)
185
186 volume = ions%latt%rcell_volume
187 electronic_pol = electronic_dipole / volume
188 ionic_pol = ionic_dipole / volume
189 total_pol = total_dipole / volume
190
191 pol_quantum = m_zero
192 do idir = 1, space%periodic_dim
193 pol_quantum(idir) = norm2(ions%latt%rlattice(1:space%dim, idir)) / volume
194 end do
195
196 if (st%system_grp%is_root()) then
197 pol_iunit = io_open(static_dir//'polarization', namespace, action='write', position='asis')
198 call berry_write_polarization_info(space, pol_iunit, berry_phase, electronic_dipole, ionic_dipole, total_dipole, &
199 electronic_pol, ionic_pol, total_pol, pol_quantum)
200 call io_close(pol_iunit)
201
202 call berry_write_total_polarization_info(space, iunit, total_pol)
203 end if
204
206 end subroutine berry_write_polarization
207
208 ! ---------------------------------------------------------
215 subroutine berry_polarization_phase(namespace, space, mesh, st, latt, kpoints, berry_phase)
216 type(namespace_t), intent(in) :: namespace
217 class(space_t), intent(in) :: space
218 class(mesh_t), intent(in) :: mesh
219 type(states_elec_t), intent(in) :: st
220 type(lattice_vectors_t), intent(in) :: latt
221 type(kpoints_t), intent(in) :: kpoints
222 real(real64), contiguous, intent(out) :: berry_phase(:)
223
224 integer :: idir, iq, iq_current, iq_next, nstrings
225 logical :: have_reference
226 logical, allocatable :: visited(:)
227 integer, allocatable :: neighbor(:, :)
228 integer, allocatable :: gvectors(:, :, :)
229 real(real64) :: string_phase, reference_phase
230 complex(real64) :: string_prod, det
231
233
234 berry_phase = m_zero
235 safe_allocate(visited(1:st%nik))
236
237 call berry_build_kpoint_strings(namespace, space, kpoints, neighbor, gvectors)
238
239 do idir = 1, space%periodic_dim
240 visited = .false.
241 have_reference = .false.
242 reference_phase = m_zero
243 nstrings = kpoints%full%npoints / kpoints%nik_axis(idir)
244 if (nstrings < 1) then
245 message(1) = "Invalid k-point grid for Berry-phase polarization."
246 call messages_fatal(1, namespace=namespace)
247 end if
248
249 do iq = 1, st%nik
250 if (visited(iq)) cycle
251
252 string_prod = m_z1
253 iq_current = iq
254 do
255 visited(iq_current) = .true.
256 call berry_neighbor_kpoint(namespace, space, mesh, latt, st, neighbor(:, idir), &
257 gvectors(:, :, idir), iq_current, iq_next, det)
258 string_prod = string_prod * det
259 iq_current = iq_next
260 if (visited(iq_current)) exit
261 end do
262
263 if (abs(string_prod) > m_tiny) then
264 string_phase = aimag(log(string_prod))
265
266 ! The phase of a string is only defined modulo 2*pi, and the logarithm
267 ! returns it on the principal branch. Averaging those values directly is
268 ! wrong as soon as the strings of a direction straddle the branch cut:
269 ! the average then jumps by a fraction of the polarization quantum when
270 ! the transverse sampling changes. Each string is therefore brought onto
271 ! the branch of the first string of the direction before averaging.
272 if (have_reference) then
273 string_phase = string_phase &
274 + m_two*m_pi*anint((reference_phase - string_phase)/(m_two*m_pi))
275 else
276 reference_phase = string_phase
277 have_reference = .true.
278 end if
279
280 berry_phase(idir) = berry_phase(idir) + string_phase
281 end if
282 end do
283
284 berry_phase(idir) = berry_phase(idir) / nstrings
285 end do
286
287 safe_deallocate_a(visited)
288 safe_deallocate_a(neighbor)
289 safe_deallocate_a(gvectors)
290
292 end subroutine berry_polarization_phase
293
294 ! ---------------------------------------------------------
302 subroutine berry_neighbor_kpoint(namespace, space, mesh, latt, st, neighbor, gvectors, iq, iq_next, det)
303 type(namespace_t), intent(in) :: namespace
304 class(space_t), intent(in) :: space
305 class(mesh_t), intent(in) :: mesh
306 type(lattice_vectors_t), intent(in) :: latt
307 type(states_elec_t), intent(in) :: st
308 integer, contiguous, intent(in) :: neighbor(:)
309 integer, contiguous, intent(in) :: gvectors(:, :)
310 integer, intent(in) :: iq
311 integer, intent(out) :: iq_next
312 complex(real64), intent(out) :: det
313
314 integer :: ik, ik_next, spin, gvector(space%dim), nocc
315
316 push_sub(berry_neighbor_kpoint)
317
318 ik = st%d%get_kpoint_index(iq)
319 spin = st%d%get_spin_index(iq)
320 ik_next = neighbor(ik)
321 gvector(1:space%dim) = gvectors(1:space%dim, ik)
322
323 if (st%d%ispin == spin_polarized) then
324 iq_next = (ik_next - 1)*2 + spin
325 else
326 iq_next = ik_next
327 end if
328
329 nocc = berry_occupied_states(namespace, st, iq, iq_next)
330 det = berry_overlap_det(st, namespace, space, mesh, latt, nocc, iq, iq_next, gvector)
331
332 pop_sub(berry_neighbor_kpoint)
333 end subroutine berry_neighbor_kpoint
334
335 ! ---------------------------------------------------------
352 subroutine berry_build_kpoint_strings(namespace, space, kpoints, neighbor, gvectors)
353 type(namespace_t), intent(in) :: namespace
354 class(space_t), intent(in) :: space
355 type(kpoints_t), intent(in) :: kpoints
356 integer, allocatable, intent(out) :: neighbor(:, :)
357 integer, allocatable, intent(out) :: gvectors(:, :, :)
358
359 integer :: ik, ik_next, idir, jdir, npoints, key
360 integer :: label(space%periodic_dim)
361 integer, allocatable :: lookup(:)
362 real(real64) :: dk(space%dim), residual
363 real(real64), parameter :: tol = 1e-8_real64
364
366
367 assert(allocated(kpoints%lk123))
368
369 npoints = kpoints%full%npoints
370
371 ! Invert the labelling: the label of a k-point gives its position on the
372 ! grid, and this gives back the k-point sitting at a given position.
373 safe_allocate(lookup(1:npoints))
374 lookup = 0
375 do ik = 1, npoints
376 key = berry_kpoint_key(space, kpoints, kpoints%lk123(ik, 1:space%periodic_dim))
377 if (key < 1 .or. key > npoints) then
378 message(1) = "Unable to construct Berry-phase k-point strings from KPointsGrid."
379 call messages_fatal(1, namespace=namespace)
380 end if
381 if (lookup(key) /= 0) then
382 message(1) = "Repeated k-points in the Berry-phase k-point grid."
383 call messages_fatal(1, namespace=namespace)
384 end if
385 lookup(key) = ik
386 end do
387
388 safe_allocate(neighbor(1:npoints, 1:space%periodic_dim))
389 safe_allocate(gvectors(1:space%dim, 1:npoints, 1:space%periodic_dim))
390
391 do idir = 1, space%periodic_dim
392 dk = m_zero
393 dk(idir) = m_one/kpoints%nik_axis(idir)
394
395 do ik = 1, npoints
396 label(1:space%periodic_dim) = kpoints%lk123(ik, 1:space%periodic_dim)
397 label(idir) = label(idir) - 1
398 if (label(idir) < 1) label(idir) = label(idir) + kpoints%nik_axis(idir)
399
400 ik_next = lookup(berry_kpoint_key(space, kpoints, label))
401 neighbor(ik, idir) = ik_next
402
403 ! k - dk and the stored neighbor describe the same state, so they differ
404 ! by a reciprocal-lattice vector, which is an integer in reduced
405 ! coordinates.
406 do jdir = 1, space%dim
407 residual = kpoints%full%red_point(jdir, ik_next) - kpoints%full%red_point(jdir, ik) + dk(jdir)
408 gvectors(jdir, ik, idir) = nint(residual)
409 if (abs(residual - gvectors(jdir, ik, idir)) > tol) then
410 message(1) = "Unable to construct Berry-phase k-point strings from KPointsGrid."
411 call messages_fatal(1, namespace=namespace)
412 end if
413 end do
414 end do
415 end do
416
417 safe_deallocate_a(lookup)
418
420 end subroutine berry_build_kpoint_strings
421
422 ! ---------------------------------------------------------
424 integer pure function berry_kpoint_key(space, kpoints, label) result(key)
425 class(space_t), intent(in) :: space
426 type(kpoints_t), intent(in) :: kpoints
427 integer, intent(in) :: label(:)
428
429 integer :: idir, stride
430
431 key = 1
432 stride = 1
433 do idir = 1, space%periodic_dim
434 key = key + (label(idir) - 1)*stride
435 stride = stride*kpoints%nik_axis(idir)
436 end do
437 end function berry_kpoint_key
438
439 ! ---------------------------------------------------------
444 integer function berry_occupied_states(namespace, st, iq, iq_next) result(nocc)
445 type(namespace_t), intent(in) :: namespace
446 type(states_elec_t), intent(in) :: st
447 integer, intent(in) :: iq, iq_next
448
449 integer :: ist, nocc_next
450
451 push_sub(berry_occupied_states)
452
453 nocc = 0
454 nocc_next = 0
455 do ist = 1, st%nst
456 if (st%occ(ist, iq) > m_epsilon) nocc = ist
457 if (st%occ(ist, iq_next) > m_epsilon) nocc_next = ist
458 end do
459
460 if (nocc /= nocc_next) then
461 message(1) = "Berry-phase polarization requires the same occupied manifold at neighboring k-points."
462 call messages_fatal(1, namespace=namespace)
463 end if
464
465 pop_sub(berry_occupied_states)
466 end function berry_occupied_states
467
468 ! ---------------------------------------------------------
474 complex(real64) function berry_overlap_det(st, namespace, space, mesh, latt, nocc, iq, iq_next, gvector) result(det)
475 type(states_elec_t), intent(in) :: st
476 type(namespace_t), intent(in) :: namespace
477 class(space_t), intent(in) :: space
478 class(mesh_t), intent(in) :: mesh
479 type(lattice_vectors_t), intent(in) :: latt
480 integer, intent(in) :: nocc
481 integer, intent(in) :: iq
482 integer, intent(in) :: iq_next
483 integer, contiguous, intent(in) :: gvector(:)
484
485 complex(real64), allocatable :: matrix(:, :)
486
487 push_sub(berry_overlap_det)
488
489 if (nocc == 0) then
490 det = m_z1
491 pop_sub(berry_overlap_det)
492 return
493 end if
494
495 safe_allocate(matrix(1:nocc, 1:nocc))
496 call berry_overlap_matrix(st, namespace, space, mesh, latt, nocc, iq, iq_next, gvector, matrix)
497 det = lalg_determinant(nocc, matrix, preserve_mat=.false.) ** st%smear%el_per_state
498 safe_deallocate_a(matrix)
499
500 pop_sub(berry_overlap_det)
501 end function berry_overlap_det
502
503 ! ---------------------------------------------------------
509 subroutine berry_overlap_matrix(st, namespace, space, mesh, latt, nocc, iq, iq_next, gvector, matrix)
510 type(states_elec_t), intent(in) :: st
511 type(namespace_t), intent(in) :: namespace
512 class(space_t), intent(in) :: space
513 class(mesh_t), intent(in) :: mesh
514 type(lattice_vectors_t), intent(in) :: latt
515 integer, intent(in) :: nocc
516 integer, intent(in) :: iq
517 integer, intent(in) :: iq_next
518 integer, contiguous, intent(in) :: gvector(:)
519 complex(real64), contiguous, intent(out) :: matrix(:, :)
520
521 integer :: ist, ib, jb, jst_start, jst_end, nst_block, sender
522 logical :: local_iq, local_iq_next
523 real(real64) :: gred(space%dim), gcart(space%dim)
524 complex(real64), allocatable :: psi_next(:, :, :), dot(:, :), phase(:)
525 type(wfs_elec_t) :: psib_next, psib_cur
526
527 push_sub(berry_overlap_matrix)
528
529 assert(.not. st%parallel_in_states)
530
531 matrix = m_z0
532 local_iq = (iq >= st%d%kpt%start .and. iq <= st%d%kpt%end)
533 local_iq_next = (iq_next >= st%d%kpt%start .and. iq_next <= st%d%kpt%end)
534
535 if (any(gvector(1:space%dim) /= 0)) then
536 safe_allocate(phase(1:mesh%np))
537 gred(1:space%dim) = real(gvector(1:space%dim), real64)
538 call kpoints_to_absolute(latt, gred, gcart)
539 call phase_build_vector(mesh, mesh%np, gcart(1:space%dim), .false., phase)
540 end if
541
542 if (local_iq) then
543 ! The result of the batched dot product is indexed by the global state indices
544 ! of the blocks, and the block containing the state nocc may extend beyond it.
545 safe_allocate(dot(1:st%nst, 1:nocc))
546 dot = m_z0
547 end if
548
549 do jb = st%group%block_start, st%group%block_end
550 jst_start = st%group%block_range(jb, 1)
551 if (jst_start > nocc) cycle
552 jst_end = min(st%group%block_range(jb, 2), nocc)
553 nst_block = jst_end - jst_start + 1
554
555 safe_allocate(psi_next(1:mesh%np, 1:st%d%dim, 1:nst_block))
556
557 if (local_iq_next) then
558 do ist = jst_start, jst_end
559 call states_elec_get_state(st, mesh, ist, iq_next, psi_next(:, :, ist - jst_start + 1))
560 end do
561 end if
562 if (st%d%kpt%parallel) then
563 sender = st%d%kpt%process(iq_next)
564 call st%d%kpt%mpi_grp%bcast(psi_next, mesh%np*st%d%dim*nst_block, mpi_double_complex, sender)
565 end if
566
567 if (local_iq) then
568 ! The batch is labeled with iq, not iq_next, as the batches entering the dot product
569 ! below must carry the same k-point index.
570 call wfs_elec_init(psib_next, st%d%dim, jst_start, jst_end, psi_next, iq)
571 if (st%group%psib(st%group%block_start, iq)%is_packed()) call psib_next%do_pack(copy = .true.)
572 if (allocated(phase)) call batch_mul_mf(mesh%np, phase, psib_next, psib_next)
573
574 do ib = st%group%block_start, st%group%block_end
575 if (st%group%block_range(ib, 1) > nocc) cycle
576 if (states_are_real(st)) then
577 ! The phase-shifted states are always complex, so real ground-state
578 ! wavefunctions must be promoted before taking the overlap.
579 call st%group%psib(ib, iq)%copy_to(psib_cur, copy_data = .true., dest_type = type_cmplx)
580 call zmesh_batch_dotp_matrix(mesh, psib_cur, psib_next, dot, reduce = .false.)
581 call psib_cur%end()
582 else
583 call zmesh_batch_dotp_matrix(mesh, st%group%psib(ib, iq), psib_next, dot, reduce = .false.)
584 end if
585 end do
586
587 call psib_next%end(copy = .false.)
588 end if
589
590 safe_deallocate_a(psi_next)
591 end do
592
593 if (local_iq) then
594 matrix(1:nocc, 1:nocc) = dot(1:nocc, 1:nocc)
595 safe_deallocate_a(dot)
596 end if
597
598 call mesh%allreduce(matrix)
599 if (st%d%kpt%parallel) call comm_allreduce(st%d%kpt%mpi_grp, matrix)
600
601 safe_deallocate_a(phase)
602
603 pop_sub(berry_overlap_matrix)
604 end subroutine berry_overlap_matrix
605
606 ! ---------------------------------------------------------
608 subroutine berry_write_polarization_info(space, iunit, berry_phase, electronic_dipole, ionic_dipole, total_dipole, &
609 electronic_pol, ionic_pol, total_pol, pol_quantum)
610 class(space_t), intent(in) :: space
611 integer, intent(in) :: iunit
612 real(real64), contiguous, intent(in) :: berry_phase(:)
613 real(real64), contiguous, intent(in) :: electronic_dipole(:)
614 real(real64), contiguous, intent(in) :: ionic_dipole(:)
615 real(real64), contiguous, intent(in) :: total_dipole(:)
616 real(real64), contiguous, intent(in) :: electronic_pol(:)
617 real(real64), contiguous, intent(in) :: ionic_pol(:)
618 real(real64), contiguous, intent(in) :: total_pol(:)
619 real(real64), contiguous, intent(in) :: pol_quantum(:)
620
621 type(unit_t) :: unit_pol, unit_c_m2
622 integer :: idir
623
625
626 call berry_polarization_units(space, unit_pol, unit_c_m2)
627
628 write(message(1), '(a)') 'Berry-phase polarization:'
629 write(message(2), '(a)') 'Defined modulo the polarization quantum.'
630 write(message(3), '(a)') 'Ionic and total values are reduced to the nearest polarization branch.'
631 call messages_info(3, iunit=iunit)
632
633 write(message(1), '(a)') ' Berry phases [rad]:'
634 do idir = 1, space%periodic_dim
635 write(message(1+idir), '(6x,3a,es18.10)') '<', index2axis(idir), '> = ', berry_phase(idir)
636 end do
637 call messages_info(1+space%periodic_dim, iunit=iunit)
638
639 write(message(1), '(a21,a20)') ' Electronic dipole:', '[' // trim(units_abbrev(units_out%length)) // ']'
640 do idir = 1, space%dim
641 write(message(1+idir), '(6x,3a,es18.10)') '<', index2axis(idir), '> = ', &
642 units_from_atomic(units_out%length, electronic_dipole(idir))
643 end do
644 call messages_info(1+space%dim, iunit=iunit)
645
646 write(message(1), '(a21,a20)') ' Ionic dipole:', '[' // trim(units_abbrev(units_out%length)) // ']'
647 do idir = 1, space%dim
648 write(message(1+idir), '(6x,3a,es18.10)') '<', index2axis(idir), '> = ', &
649 units_from_atomic(units_out%length, ionic_dipole(idir))
650 end do
651 call messages_info(1+space%dim, iunit=iunit)
652
653 write(message(1), '(a21,a20)') ' Total dipole:', '[' // trim(units_abbrev(units_out%length)) // ']'
654 do idir = 1, space%dim
655 write(message(1+idir), '(6x,3a,es18.10)') '<', index2axis(idir), '> = ', &
656 units_from_atomic(units_out%length, total_dipole(idir))
657 end do
658 call messages_info(1+space%dim, iunit=iunit)
659
660 write(message(1), '(a,t35,a,t52,a)') ' Electronic polarization:', &
661 '[' // trim(units_abbrev(unit_pol)) // ']', '[' // trim(units_abbrev(unit_c_m2)) // ']'
662 do idir = 1, space%dim
663 write(message(1+idir), '(6x,3a,t35,es14.5,t52,es14.5)') '<', index2axis(idir), '> = ', &
664 units_from_atomic(unit_pol, electronic_pol(idir)), units_from_atomic(unit_c_m2, electronic_pol(idir))
665 end do
666 call messages_info(1+space%dim, iunit=iunit)
667
668 write(message(1), '(a,t35,a,t52,a)') ' Ionic polarization:', &
669 '[' // trim(units_abbrev(unit_pol)) // ']', '[' // trim(units_abbrev(unit_c_m2)) // ']'
670 do idir = 1, space%dim
671 write(message(1+idir), '(6x,3a,t35,es14.5,t52,es14.5)') '<', index2axis(idir), '> = ', &
672 units_from_atomic(unit_pol, ionic_pol(idir)), units_from_atomic(unit_c_m2, ionic_pol(idir))
673 end do
674 call messages_info(1+space%dim, iunit=iunit)
675
676 write(message(1), '(a,t35,a,t52,a)') ' Total polarization:', &
677 '[' // trim(units_abbrev(unit_pol)) // ']', '[' // trim(units_abbrev(unit_c_m2)) // ']'
678 do idir = 1, space%dim
679 write(message(1+idir), '(6x,3a,t35,es14.5,t52,es14.5)') '<', index2axis(idir), '> = ', &
680 units_from_atomic(unit_pol, total_pol(idir)), units_from_atomic(unit_c_m2, total_pol(idir))
681 end do
682 call messages_info(1+space%dim, iunit=iunit)
683
684 write(message(1), '(a,t30,a,t52,a)') ' Polarization quantum:', &
685 '[' // trim(units_abbrev(unit_pol)) // ']', '[' // trim(units_abbrev(unit_c_m2)) // ']'
686 do idir = 1, space%periodic_dim
687 write(message(1+idir), '(6x,3a,t30,es14.5,t52,es14.5)') '<', index2axis(idir), '> = ', &
688 units_from_atomic(unit_pol, pol_quantum(idir)), units_from_atomic(unit_c_m2, pol_quantum(idir))
689 end do
690 call messages_info(1+space%periodic_dim, iunit=iunit)
691
693 end subroutine berry_write_polarization_info
694
695 ! ---------------------------------------------------------
697 subroutine berry_write_total_polarization_info(space, iunit, total_pol)
698 class(space_t), intent(in) :: space
699 integer, intent(in) :: iunit
700 real(real64), contiguous, intent(in) :: total_pol(:)
701
702 type(unit_t) :: unit_pol, unit_c_m2
703 integer :: idir
704
706
707 call berry_polarization_units(space, unit_pol, unit_c_m2)
708
709 write(message(1), '(a,t30,a,t52,a)') 'Total polarization:', &
710 '[' // trim(units_abbrev(unit_pol)) // ']', '[' // trim(units_abbrev(unit_c_m2)) // ']'
711 do idir = 1, space%dim
712 write(message(1+idir), '(4x,3a,t30,es14.5,t52,es14.5)') '<', index2axis(idir), '> = ', &
713 units_from_atomic(unit_pol, total_pol(idir)), units_from_atomic(unit_c_m2, total_pol(idir))
714 end do
715 call messages_info(1+space%dim, iunit=iunit)
716
719
720 ! ---------------------------------------------------------
722 subroutine berry_polarization_units(space, unit_pol, unit_c_m2)
723 class(space_t), intent(in) :: space
724 type(unit_t), intent(out) :: unit_pol
725 type(unit_t), intent(out) :: unit_c_m2
726
728
729 unit_pol = units_out%length**(1-space%periodic_dim)
730 unit_c_m2%factor = m_one / (1.602176634e-19_real64 / (p_a_b*1.0e-10_real64)**2)
731 unit_c_m2%abbrev = 'C/m^2'
732 unit_c_m2%name = 'coulomb per square meter'
733
735 end subroutine berry_polarization_units
736
737 ! ---------------------------------------------------------
743 subroutine berry_perform_internal_scf(this, namespace, space, eigensolver, gr, st, hm, &
744 iter, ks, ions, ext_partners)
745 type(berry_t), intent(in) :: this
746 type(namespace_t), intent(in) :: namespace
747 type(electron_space_t), intent(in) :: space
748 type(eigensolver_t), intent(inout) :: eigensolver
749 type(grid_t), intent(in) :: gr
750 type(states_elec_t), intent(inout) :: st
751 type(hamiltonian_elec_t), intent(inout) :: hm
752 integer, intent(in) :: iter
753 type(v_ks_t), intent(inout) :: ks
754 type(ions_t), intent(in) :: ions
755 type(partner_list_t), intent(in) :: ext_partners
756
757 integer :: iberry, idir
758 logical :: berry_conv
759 real(real64) :: dipole_prev(space%dim), dipole(space%dim)
760 real(real64), parameter :: tol = 1e-5_real64
761
763
764 assert(allocated(hm%vberry))
765
766 if (st%parallel_in_states) then
767 call messages_not_implemented("Berry phase parallel in states", namespace=namespace)
768 end if
769 ! The Berry potential and dipole are implemented for a single unpolarized k-point only
770 if (st%d%ispin == spinors) then
771 call messages_not_implemented("Berry phase with spinors", namespace=namespace)
772 end if
773 if (st%d%ispin == spin_polarized) then
774 call messages_not_implemented("Berry phase with spin polarization", namespace=namespace)
775 end if
776
777 call calc_dipole(dipole, space, gr, st, ions)
778
779 do iberry = 1, this%max_iter_berry
780 eigensolver%converged = 0
781 call eigensolver%run(namespace, gr, st, hm, space, ext_partners, iter)
782
783 !Calculation of the Berry potential
784 call berry_potential(st, namespace, space, gr, hm%ions%latt, hm%ep%e_field, hm%vberry)
785
786 !Calculation of the corresponding energy
787 hm%energy%berry = berry_energy_correction(st, namespace, space, gr, hm%ions%latt, &
788 hm%ep%e_field(1:space%periodic_dim), hm%vberry(1:gr%np, 1:hm%d%nspin))
789
790 !We recompute the KS potential
791 call v_ks_calc(ks, namespace, space, hm, st, ions, ext_partners, calc_current=.false.)
793 dipole_prev = dipole
794 call calc_dipole(dipole, space, gr, st, ions)
795 write(message(1),'(a,9f12.6)') 'Dipole = ', dipole(1:space%dim)
796 call messages_info(1, namespace=namespace)
797
798 berry_conv = .true.
799 do idir = 1, space%periodic_dim
800 if (abs(dipole_prev(idir)) > 1e-10_real64) then
801 berry_conv = berry_conv .and. (abs(dipole(idir) - dipole_prev(idir)) < tol &
802 .or.(abs((dipole(idir) - dipole_prev(idir)) / dipole_prev(idir)) < tol))
803 else
804 berry_conv = berry_conv .and. (abs(dipole(idir) - dipole_prev(idir)) < tol)
805 end if
806 end do
807
808 if (berry_conv) exit
809 end do
810
812 end subroutine berry_perform_internal_scf
813
814 ! ---------------------------------------------------------
823 subroutine calc_dipole(dipole, space, mesh, st, ions)
824 real(real64), contiguous, intent(out) :: dipole(:)
825 class(space_t), intent(in) :: space
826 class(mesh_t), intent(in) :: mesh
827 type(states_elec_t), intent(in) :: st
828 type(ions_t), intent(in) :: ions
829
830 integer :: ispin, idir
831 real(real64) :: e_dip(space%dim + 1, st%d%spin_channels), n_dip(space%dim), nquantumpol
832
833 push_sub(calc_dipole)
834
835 assert(.not. ions%latt%nonorthogonal)
836
837 dipole(1:space%dim) = m_zero
839 do ispin = 1, st%d%spin_channels
840 call dmf_multipoles(mesh, st%rho(:, ispin), 1, e_dip(:, ispin))
841 end do
842
843 n_dip = ions%dipole()
844
845 do idir = 1, space%dim
846 ! in periodic directions use single-point Berry`s phase calculation
847 if (idir <= space%periodic_dim) then
848 dipole(idir) = -n_dip(idir) - berry_dipole(st, ions%namespace, mesh, ions%latt, space, idir)
849
850 ! use quantum of polarization to reduce to smallest possible magnitude
851 nquantumpol = nint(dipole(idir)/norm2(ions%latt%rlattice(:, idir)))
852 dipole(idir) = dipole(idir) - nquantumpol * norm2(ions%latt%rlattice(:, idir))
853 ! in aperiodic directions use normal dipole formula
854
855 else
856 e_dip(idir + 1, 1) = sum(e_dip(idir + 1, :))
857 dipole(idir) = -n_dip(idir) - e_dip(idir + 1, 1)
858 end if
859 end do
860
861 pop_sub(calc_dipole)
862 end subroutine calc_dipole
863
864
865 ! ---------------------------------------------------------
877 real(real64) function berry_dipole(st, namespace, mesh, latt, space, dir) result(dipole)
878 type(states_elec_t), intent(in) :: st
879 type(namespace_t), intent(in) :: namespace
880 class(mesh_t), intent(in) :: mesh
881 type(lattice_vectors_t), intent(in) :: latt
882 class(space_t), intent(in) :: space
883 integer, intent(in) :: dir
884
885 integer :: ik
886 complex(real64) :: det
887
888 push_sub(berry_dipole)
889
890 !There is a missing reduction here.
891 !However, as we are limited to a single k-point at the moment, this is not a problem.
892 assert(st%nik == 1)
893
894 dipole = m_zero
895 do ik = st%d%kpt%start, st%d%kpt%end ! determinants for different spins and k-points multiply since matrix is block-diagonal
896 det = berry_phase_det(st, namespace, mesh, latt, space, dir, ik)
897 !Check in case det is zero. This should never occur in practical calculations
898 if (abs(det) > m_tiny) then
899 dipole = dipole + aimag(log(det))
900 end if
901 end do
902
903 dipole = -(norm2(latt%rlattice(:,dir)) / (m_two*m_pi)) * dipole
904
905 pop_sub(berry_dipole)
906 end function berry_dipole
907
908
909 ! ---------------------------------------------------------
917 complex(real64) function berry_phase_det(st, namespace, mesh, latt, space, dir, ik) result(det)
918 type(states_elec_t), intent(in) :: st
919 type(namespace_t), intent(in) :: namespace
920 class(mesh_t), intent(in) :: mesh
921 type(lattice_vectors_t), intent(in) :: latt
922 class(space_t), intent(in) :: space
923 integer, intent(in) :: dir
924 integer, intent(in) :: ik
925
926 integer :: ist, noccst, gvector(3)
927
928 push_sub(berry_phase_det)
929
930 ! find how many states are occupied on this k-point. Formalism only works if semiconducting anyway.
931 noccst = 0
932 do ist = 1, st%nst
933 if (st%occ(ist, ik) > m_epsilon) noccst = ist
934 end do
935
936 gvector(:) = 0
937 gvector(dir) = 1
938 det = berry_overlap_det(st, namespace, space, mesh, latt, noccst, ik, ik, gvector)
939
940 pop_sub(berry_phase_det)
941 end function berry_phase_det
942
943
944 ! ---------------------------------------------------------
954 subroutine berry_potential(st, namespace, space, mesh, latt, e_field, pot)
955 type(states_elec_t), intent(in) :: st
956 type(namespace_t), intent(in) :: namespace
957 class(space_t), intent(in) :: space
958 class(mesh_t), intent(in) :: mesh
959 type(lattice_vectors_t), intent(in) :: latt
960 real(real64), contiguous, intent(in) :: e_field(:)
961 real(real64), contiguous, intent(out) :: pot(:,:)
962
963 integer :: ispin, idir, ip
964 complex(real64) :: factor, det, phase_factor
965
966 push_sub(berry_potential)
967
968 if (latt%nonorthogonal) then
969 call messages_not_implemented("Berry phase for non-orthogonal cells", namespace=namespace)
970 end if
971
972 if (st%nik > 1) then
973 call messages_not_implemented("Berry phase with k-points", namespace=namespace)
974 end if
975
976 pot(1:mesh%np, 1:st%d%nspin) = m_zero
977
978 do ispin = 1, st%d%nspin
979 do idir = 1, space%periodic_dim
980 if (abs(e_field(idir)) > m_epsilon) then
981 ! calculate the ip-independent part first
982 det = berry_phase_det(st, namespace, mesh, latt, space, idir, ispin)
983 if (abs(det) > m_epsilon) then
984 factor = e_field(idir) * (norm2(latt%rlattice(:,idir)) / (m_two*m_pi)) / det
985 else
986 ! If det = 0, mu = -infinity, so this condition should never be reached
987 ! if things are working properly.
988 write(message(1),*) "Divide by zero: dir = ", idir, " Berry-phase determinant = ", det
989 call messages_fatal(1, namespace=namespace)
990 end if
991 ! Note: this is only correct for orthogonal cells
992 phase_factor = m_two * m_pi * m_zi / norm2(latt%rlattice(:,idir))
993 !$omp parallel do
994 do ip = 1, mesh%np
995 pot(ip, ispin) = pot(ip, ispin) + &
996 aimag(factor * exp(phase_factor * mesh%x_t(ip, idir)))
997 end do
998 !$omp end parallel do
999 end if
1000 end do
1001 end do
1002
1003 pop_sub(berry_potential)
1004 end subroutine berry_potential
1005
1006
1007 ! ---------------------------------------------------------
1013 real(real64) function berry_energy_correction(st, namespace, space, mesh, latt, e_field, vberry) result(delta)
1014 type(states_elec_t), intent(in) :: st
1015 type(namespace_t), intent(in) :: namespace
1016 class(space_t), intent(in) :: space
1017 class(mesh_t), intent(in) :: mesh
1018 type(lattice_vectors_t), intent(in) :: latt
1019 real(real64), contiguous, intent(in) :: e_field(:)
1020 real(real64), intent(in) :: vberry(:,:)
1021
1022 integer :: ispin, idir
1023
1024 push_sub(berry_energy_correction)
1025
1026 ! first we calculate expectation value of Berry potential, to subtract off
1027 delta = m_zero
1028 do ispin = 1, st%d%nspin
1029 delta = delta - dmf_dotp(mesh, st%rho(1:mesh%np, ispin), vberry(1:mesh%np, ispin))
1030 end do
1031
1032 ! the real energy contribution is -mu.E
1033 do idir = 1, space%periodic_dim
1034 delta = delta - berry_dipole(st, namespace, mesh, latt, space, idir) * e_field(idir)
1035 end do
1036
1038 end function berry_energy_correction
1039
1040end module berry_oct_m
1041
1042!! Local Variables:
1043!! mode: f90
1044!! coding: utf-8
1045!! End:
double log(double __x) __attribute__((__nothrow__
double exp(double __x) __attribute__((__nothrow__
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:118
Berry-phase routines for periodic dipoles, static polarization, and the finite-field electric enthalp...
Definition: berry.F90:125
subroutine berry_write_polarization_info(space, iunit, berry_phase, electronic_dipole, ionic_dipole, total_dipole, electronic_pol, ionic_pol, total_pol, pol_quantum)
Write the static polarization information.
Definition: berry.F90:705
subroutine berry_polarization_units(space, unit_pol, unit_c_m2)
Polarization unit.
Definition: berry.F90:818
subroutine berry_write_total_polarization_info(space, iunit, total_pol)
Write the total polarization.
Definition: berry.F90:793
subroutine, public berry_perform_internal_scf(this, namespace, space, eigensolver, gr, st, hm, iter, ks, ions, ext_partners)
Inner self-consistency loop for a static electric field in periodic systems.
Definition: berry.F90:840
subroutine berry_overlap_matrix(st, namespace, space, mesh, latt, nocc, iq, iq_next, gvector, matrix)
Build the occupied-state overlap matrix for a Berry-phase k-point link.
Definition: berry.F90:605
subroutine, public berry_write_polarization(namespace, space, mesh, st, ions, kpoints, iunit)
Compute and write the static modern-theory polarization after SCF.
Definition: berry.F90:214
integer pure function berry_kpoint_key(space, kpoints, label)
Flatten a Monkhorst-Pack grid label into a single index.
Definition: berry.F90:520
real(real64) function, public berry_dipole(st, namespace, mesh, latt, space, dir)
Use the single-point Berry-phase method to calculate a periodic dipole.
Definition: berry.F90:973
real(real64) function, public berry_energy_correction(st, namespace, space, mesh, latt, e_field, vberry)
Return the Berry electric-enthalpy correction for the active field.
Definition: berry.F90:1109
complex(real64) function berry_overlap_det(st, namespace, space, mesh, latt, nocc, iq, iq_next, gvector)
Determinant of the occupied-manifold overlap matrix for one k-point link.
Definition: berry.F90:570
integer function berry_occupied_states(namespace, st, iq, iq_next)
Return the number of occupied states shared by two neighboring k-points.
Definition: berry.F90:540
subroutine berry_build_kpoint_strings(namespace, space, kpoints, neighbor, gvectors)
Tabulate the k-point strings of a full Monkhorst-Pack grid.
Definition: berry.F90:448
subroutine, public berry_potential(st, namespace, space, mesh, latt, e_field, pot)
Local potential for electric enthalpy of a uniform field.
Definition: berry.F90:1050
subroutine, public berry_init(this, namespace)
Definition: berry.F90:185
complex(real64) function berry_phase_det(st, namespace, mesh, latt, space, dir, ik)
Determinant entering the single-point Berry-phase dipole.
Definition: berry.F90:1013
subroutine, public calc_dipole(dipole, space, mesh, st, ions)
Calculate the total dipole used by the finite-field Berry machinery.
Definition: berry.F90:919
subroutine berry_neighbor_kpoint(namespace, space, mesh, latt, st, neighbor, gvectors, iq, iq_next, det)
Advance one step on a Berry-phase k-string and return the link determinant.
Definition: berry.F90:398
subroutine berry_polarization_phase(namespace, space, mesh, st, latt, kpoints, berry_phase)
Evaluate Berry phases along each periodic reciprocal-lattice direction.
Definition: berry.F90:311
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
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:198
real(real64), parameter, public m_tiny
Definition: global.F90:217
character(len= *), parameter, public static_dir
Definition: global.F90:280
complex(real64), parameter, public m_z1
Definition: global.F90:211
real(real64), parameter, public m_one
Definition: global.F90:201
This module implements the underlying real-space grid.
Definition: grid.F90:119
This module defines classes and functions for interaction partners.
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
integer, parameter, public kpoints_monkh_pack
Definition: kpoints.F90:226
integer, parameter, public kpoints_path
Definition: kpoints.F90:226
integer, parameter, public kpoints_user
Definition: kpoints.F90:226
This module defines functions over batches of mesh functions.
Definition: mesh_batch.F90:118
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 phase_build_vector(mesh, np, kvector, conjugate, phase)
tabulate an explicitly supplied reciprocal-vector phase.
Definition: phase.F90:857
logical pure function, public smear_is_semiconducting(this)
Definition: smear.F90:1044
This module handles spin dimensions of the states and the k-point distribution.
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.
This module is intended to contain simple general-purpose utility functions and procedures.
Definition: utils.F90:120
Parameters controlling the inner Berry-potential SCF loop.
Definition: berry.F90:176
Describes mesh distribution to nodes.
Definition: mesh.F90:187
The states_elec_t class contains all electronic wave functions.
int true(void)