42 use,
intrinsic :: iso_fortran_env
84 integer :: max_iter_berry
90 type(berry_t),
intent(inout) :: this
91 type(namespace_t),
intent(in) :: namespace
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)
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
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
135 if (.not. space%is_periodic())
then
136 message(1) =
"SCFCalculatePolarization requires a periodic system."
140 if (kpoints%use_symmetries)
then
141 message(1) =
"SCFCalculatePolarization requires the full k-point grid."
142 message(2) =
"Set KPointsUseSymmetries = no."
148 message(1) =
"SCFCalculatePolarization currently requires a Monkhorst-Pack KPointsGrid."
152 if (kpoints%reduced%npoints /= kpoints%full%npoints)
then
153 message(1) =
"SCFCalculatePolarization requires unreduced k-points."
158 if (kpoints%full%nshifts /= 1)
then
159 message(1) =
"SCFCalculatePolarization requires a KPointsGrid with a single shift."
163 if (st%parallel_in_states)
then
168 message(1) =
"SCFCalculatePolarization requires integer occupations."
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)
183 ionic_dipole = ions%latt%fold_into_cell(-ions%dipole())
184 total_dipole = ions%latt%fold_into_cell(electronic_dipole + ionic_dipole)
186 volume = ions%latt%rcell_volume
187 electronic_pol = electronic_dipole / volume
188 ionic_pol = ionic_dipole / volume
189 total_pol = total_dipole / volume
192 do idir = 1, space%periodic_dim
193 pol_quantum(idir) = norm2(ions%latt%rlattice(1:space%dim, idir)) / volume
196 if (st%system_grp%is_root())
then
197 pol_iunit =
io_open(
static_dir//
'polarization', namespace, action=
'write', position=
'asis')
199 electronic_pol, ionic_pol, total_pol, pol_quantum)
217 class(
space_t),
intent(in) :: space
218 class(
mesh_t),
intent(in) :: mesh
222 real(real64),
contiguous,
intent(out) :: berry_phase(:)
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
235 safe_allocate(visited(1:st%nik))
239 do idir = 1, space%periodic_dim
241 have_reference = .false.
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."
250 if (visited(iq)) cycle
255 visited(iq_current) = .
true.
257 gvectors(:, :, idir), iq_current, iq_next, det)
258 string_prod = string_prod * det
260 if (visited(iq_current))
exit
263 if (abs(string_prod) >
m_tiny)
then
264 string_phase = aimag(
log(string_prod))
272 if (have_reference)
then
273 string_phase = string_phase &
276 reference_phase = string_phase
277 have_reference = .
true.
280 berry_phase(idir) = berry_phase(idir) + string_phase
284 berry_phase(idir) = berry_phase(idir) / nstrings
287 safe_deallocate_a(visited)
288 safe_deallocate_a(neighbor)
289 safe_deallocate_a(gvectors)
302 subroutine berry_neighbor_kpoint(namespace, space, mesh, latt, st, neighbor, gvectors, iq, iq_next, det)
304 class(
space_t),
intent(in) :: space
305 class(
mesh_t),
intent(in) :: mesh
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
314 integer :: ik, ik_next, spin, gvector(space%dim), nocc
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)
324 iq_next = (ik_next - 1)*2 + spin
330 det =
berry_overlap_det(st, namespace, space, mesh, latt, nocc, iq, iq_next, gvector)
354 class(
space_t),
intent(in) :: space
356 integer,
allocatable,
intent(out) :: neighbor(:, :)
357 integer,
allocatable,
intent(out) :: gvectors(:, :, :)
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
367 assert(
allocated(kpoints%lk123))
369 npoints = kpoints%full%npoints
373 safe_allocate(lookup(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."
381 if (lookup(key) /= 0)
then
382 message(1) =
"Repeated k-points in the Berry-phase k-point grid."
388 safe_allocate(neighbor(1:npoints, 1:space%periodic_dim))
389 safe_allocate(gvectors(1:space%dim, 1:npoints, 1:space%periodic_dim))
391 do idir = 1, space%periodic_dim
393 dk(idir) =
m_one/kpoints%nik_axis(idir)
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)
401 neighbor(ik, idir) = ik_next
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."
417 safe_deallocate_a(lookup)
424 integer pure function berry_kpoint_key(space, kpoints, label) result(key)
425 class(
space_t),
intent(in) :: space
427 integer,
intent(in) :: label(:)
429 integer :: idir, stride
433 do idir = 1, space%periodic_dim
434 key = key + (label(idir) - 1)*stride
435 stride = stride*kpoints%nik_axis(idir)
445 type(namespace_t),
intent(in) :: namespace
446 type(states_elec_t),
intent(in) :: st
447 integer,
intent(in) :: iq, iq_next
449 integer :: ist, nocc_next
456 if (st%occ(ist, iq) > m_epsilon) nocc = ist
457 if (st%occ(ist, iq_next) > m_epsilon) nocc_next = ist
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)
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(:)
485 complex(real64),
allocatable :: matrix(:, :)
495 safe_allocate(matrix(1:nocc, 1:nocc))
497 det = lalg_determinant(nocc, matrix, preserve_mat=.false.) ** st%smear%el_per_state
498 safe_deallocate_a(matrix)
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(:, :)
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
529 assert(.not. st%parallel_in_states)
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)
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)
545 safe_allocate(dot(1:st%nst, 1:nocc))
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
555 safe_allocate(psi_next(1:mesh%np, 1:st%d%dim, 1:nst_block))
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))
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)
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)
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
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.)
583 call zmesh_batch_dotp_matrix(mesh, st%group%psib(ib, iq), psib_next, dot, reduce = .false.)
587 call psib_next%end(copy = .false.)
590 safe_deallocate_a(psi_next)
594 matrix(1:nocc, 1:nocc) = dot(1:nocc, 1:nocc)
595 safe_deallocate_a(dot)
598 call mesh%allreduce(matrix)
599 if (st%d%kpt%parallel)
call comm_allreduce(st%d%kpt%mpi_grp, matrix)
601 safe_deallocate_a(phase)
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(:)
621 type(unit_t) :: unit_pol, unit_c_m2
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)
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)
637 call messages_info(1+space%periodic_dim, iunit=iunit)
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))
644 call messages_info(1+space%dim, iunit=iunit)
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))
651 call messages_info(1+space%dim, iunit=iunit)
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))
658 call messages_info(1+space%dim, iunit=iunit)
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))
666 call messages_info(1+space%dim, iunit=iunit)
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))
674 call messages_info(1+space%dim, iunit=iunit)
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))
682 call messages_info(1+space%dim, iunit=iunit)
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))
690 call messages_info(1+space%periodic_dim, iunit=iunit)
698 class(space_t),
intent(in) :: space
699 integer,
intent(in) :: iunit
700 real(real64),
contiguous,
intent(in) :: total_pol(:)
702 type(unit_t) :: unit_pol, unit_c_m2
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))
715 call messages_info(1+space%dim, iunit=iunit)
723 class(space_t),
intent(in) :: space
724 type(unit_t),
intent(out) :: unit_pol
725 type(unit_t),
intent(out) :: unit_c_m2
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'
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
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
764 assert(
allocated(hm%vberry))
766 if (st%parallel_in_states)
then
767 call messages_not_implemented(
"Berry phase parallel in states", namespace=namespace)
770 if (st%d%ispin == spinors)
then
771 call messages_not_implemented(
"Berry phase with spinors", namespace=namespace)
773 if (st%d%ispin == spin_polarized)
then
774 call messages_not_implemented(
"Berry phase with spin polarization", namespace=namespace)
779 do iberry = 1, this%max_iter_berry
780 eigensolver%converged = 0
781 call eigensolver%run(namespace, gr, st, hm, space, ext_partners, iter)
784 call berry_potential(st, namespace, space, gr, hm%ions%latt, hm%ep%e_field, hm%vberry)
788 hm%ep%e_field(1:space%periodic_dim), hm%vberry(1:gr%np, 1:hm%d%nspin))
791 call v_ks_calc(ks, namespace, space, hm, st, ions, ext_partners, calc_current=.false.)
795 write(message(1),
'(a,9f12.6)')
'Dipole = ', dipole(1:space%dim)
796 call messages_info(1, namespace=namespace)
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))
804 berry_conv = berry_conv .and. (abs(dipole(idir) - dipole_prev(idir)) < tol)
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
830 integer :: ispin, idir
831 real(real64) :: e_dip(space%dim + 1, st%d%spin_channels), n_dip(space%dim), nquantumpol
835 assert(.not. ions%latt%nonorthogonal)
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))
843 n_dip = ions%dipole()
845 do idir = 1, space%dim
847 if (idir <= space%periodic_dim)
then
848 dipole(idir) = -n_dip(idir) -
berry_dipole(st, ions%namespace, mesh, ions%latt, space, idir)
851 nquantumpol = nint(dipole(idir)/norm2(ions%latt%rlattice(:, idir)))
852 dipole(idir) = dipole(idir) - nquantumpol * norm2(ions%latt%rlattice(:, idir))
856 e_dip(idir + 1, 1) = sum(e_dip(idir + 1, :))
857 dipole(idir) = -n_dip(idir) - e_dip(idir + 1, 1)
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
886 complex(real64) :: det
895 do ik = st%d%kpt%start, st%d%kpt%end
898 if (abs(det) > m_tiny)
then
899 dipole = dipole + aimag(
log(det))
903 dipole = -(norm2(latt%rlattice(:,dir)) / (m_two*m_pi)) * dipole
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
926 integer :: ist, noccst, gvector(3)
933 if (st%occ(ist, ik) > m_epsilon) noccst = ist
938 det =
berry_overlap_det(st, namespace, space, mesh, latt, noccst, ik, ik, gvector)
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(:,:)
963 integer :: ispin, idir, ip
964 complex(real64) :: factor, det, phase_factor
968 if (latt%nonorthogonal)
then
969 call messages_not_implemented(
"Berry phase for non-orthogonal cells", namespace=namespace)
973 call messages_not_implemented(
"Berry phase with k-points", namespace=namespace)
976 pot(1:mesh%np, 1:st%d%nspin) = m_zero
978 do ispin = 1, st%d%nspin
979 do idir = 1, space%periodic_dim
980 if (abs(e_field(idir)) > m_epsilon)
then
983 if (abs(det) > m_epsilon)
then
984 factor = e_field(idir) * (norm2(latt%rlattice(:,idir)) / (m_two*m_pi)) / det
988 write(message(1),*)
"Divide by zero: dir = ", idir,
" Berry-phase determinant = ", det
989 call messages_fatal(1, namespace=namespace)
992 phase_factor = m_two * m_pi * m_zi / norm2(latt%rlattice(:,idir))
995 pot(ip, ispin) = pot(ip, ispin) + &
996 aimag(factor *
exp(phase_factor * mesh%x_t(ip, idir)))
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(:,:)
1022 integer :: ispin, idir
1028 do ispin = 1, st%d%nspin
1029 delta = delta - dmf_dotp(mesh, st%rho(1:mesh%np, ispin), vberry(1:mesh%np, ispin))
1033 do idir = 1, space%periodic_dim
1034 delta = delta -
berry_dipole(st, namespace, mesh, latt, space, idir) * e_field(idir)
double log(double __x) __attribute__((__nothrow__
double exp(double __x) __attribute__((__nothrow__
This module implements common operations on batches of mesh functions.
Berry-phase routines for periodic dipoles, static polarization, and the finite-field electric enthalp...
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.
subroutine berry_polarization_units(space, unit_pol, unit_c_m2)
Polarization unit.
subroutine berry_write_total_polarization_info(space, iunit, total_pol)
Write the total polarization.
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.
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.
subroutine, public berry_write_polarization(namespace, space, mesh, st, ions, kpoints, iunit)
Compute and write the static modern-theory polarization after SCF.
integer pure function berry_kpoint_key(space, kpoints, label)
Flatten a Monkhorst-Pack grid label into a single index.
real(real64) function, public berry_dipole(st, namespace, mesh, latt, space, dir)
Use the single-point Berry-phase method to calculate a periodic dipole.
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.
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.
integer function berry_occupied_states(namespace, st, iq, iq_next)
Return the number of occupied states shared by two neighboring k-points.
subroutine berry_build_kpoint_strings(namespace, space, kpoints, neighbor, gvectors)
Tabulate the k-point strings of a full Monkhorst-Pack grid.
subroutine, public berry_potential(st, namespace, space, mesh, latt, e_field, pot)
Local potential for electric enthalpy of a uniform field.
subroutine, public berry_init(this, namespace)
complex(real64) function berry_phase_det(st, namespace, mesh, latt, space, dir, ik)
Determinant entering the single-point Berry-phase dipole.
subroutine, public calc_dipole(dipole, space, mesh, st, ions)
Calculate the total dipole used by the finite-field Berry machinery.
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.
subroutine berry_polarization_phase(namespace, space, mesh, st, latt, kpoints, berry_phase)
Evaluate Berry phases along each periodic reciprocal-lattice direction.
integer, parameter, public spin_polarized
real(real64), parameter, public m_two
real(real64), parameter, public m_zero
real(real64), parameter, public m_pi
some mathematical constants
real(real64), parameter, public m_tiny
character(len= *), parameter, public static_dir
complex(real64), parameter, public m_z1
real(real64), parameter, public m_one
This module implements the underlying real-space grid.
This module defines classes and functions for interaction partners.
subroutine, public io_close(iunit, grp)
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
integer, parameter, public kpoints_monkh_pack
integer, parameter, public kpoints_path
integer, parameter, public kpoints_user
This module defines functions over batches of mesh functions.
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
subroutine, public messages_not_implemented(feature, namespace)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
subroutine, public phase_build_vector(mesh, np, kvector, conjugate, phase)
tabulate an explicitly supplied reciprocal-vector phase.
logical pure function, public smear_is_semiconducting(this)
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.
This module defines the unit system, used for input and output.
This module is intended to contain simple general-purpose utility functions and procedures.
Parameters controlling the inner Berry-potential SCF loop.
Describes mesh distribution to nodes.
The states_elec_t class contains all electronic wave functions.