33 use,
intrinsic :: iso_fortran_env
73 integer,
intent(in) :: nst
74 type(states_elec_t),
intent(in) :: st
75 class(space_t),
intent(in) :: space
76 type(kpoints_t),
intent(in) :: kpoints
77 real(real64),
optional,
intent(in) :: error(:,:)
78 integer,
optional,
intent(in) :: st_start
79 logical,
optional,
intent(in) :: compact
80 integer,
optional,
intent(in) :: iunit
81 type(namespace_t),
optional,
intent(in) :: namespace
83 integer :: ik, ikk, ist, ns, is, idir, st_start_, iflat, iqn, homo_index, not_printed
84 logical :: print_eigenval
85 real(real64) :: kpoint(space%dim), max_error
86 character(len=120) :: tmp_str(max(space%dim, 3)), cspin
88 real(real64),
allocatable :: flat_eigenval(:)
89 integer,
allocatable :: flat_indices(:, :)
90 integer,
parameter :: print_range = 8
95 if (
present(st_start)) st_start_ = st_start
107 if (st%d%nspin == 2) ns = 2
112 if (st%d%ispin ==
spinors)
then
113 write(
message(1),
'(a4,1x,a5,1x,a12,1x,a12,2x,a4,4x,a4,4x,a4)') &
114 '#st',
' Spin',
' Eigenvalue',
'Occupation ',
'<Sx>',
'<Sy>',
'<Sz>'
116 write(
message(1),
'(a4,1x,a5,1x,a12,4x,a12)') &
117 '#st',
' Spin',
' Eigenvalue',
'Occupation'
119 if (
present(error))
then
124 do ik = 1, st%nik, ns
125 if (space%is_periodic())
then
126 ikk = st%d%get_kpoint_index(ik)
127 kpoint(1:space%dim) = kpoints%get_point(ikk, absolute_coordinates = .false.)
128 write(
message(1),
'(a,i8,a)')
'#k =', ikk,
', k = ('
129 do idir = 1, space%dim
130 write(tmp_str(1),
'(f10.6)') kpoint(idir)
138 do ist = st_start_, nst
140 if (is == 0) cspin =
'up'
141 if (is == 1) cspin =
'dn'
144 write(tmp_str(1),
'(i4,3x,a2)') ist, trim(cspin)
145 if (st%d%ispin ==
spinors)
then
146 write(tmp_str(2),
'(1x,f12.6,5x,f5.2,3x,3f8.4)') &
148 if (
present(error))
write(tmp_str(3),
'(a3,es8.1,a1)')
' (', error(ist, ik),
')'
150 write(tmp_str(2),
'(1x,f12.6,3x,f12.6)') &
152 if (
present(error))
write(tmp_str(3),
'(a7,es8.1,a1)')
' (', error(ist, ik+is),
')'
154 if (
present(error))
then
155 message(1) = trim(tmp_str(1))//trim(tmp_str(2))//trim(tmp_str(3))
157 message(1) = trim(tmp_str(1))//trim(tmp_str(2))
168 safe_allocate(flat_eigenval(1:st%nik*nst))
169 safe_allocate(flat_indices(1:2, 1:st%nik*nst))
175 flat_eigenval(iflat) = st%eigenval(ist, iqn)
176 flat_indices(1:2, iflat) = (/iqn, ist/)
182 call sort(flat_eigenval, flat_indices(:, :))
184 homo_index = st%nik*nst
185 do iflat = 1, st%nik*nst
186 iqn = flat_indices(1, iflat)
187 ist = flat_indices(2, iflat)
188 if (abs(st%occ(ist, iqn)) < 0.1_real64)
then
189 homo_index = iflat - 1
194 tmp_str(1) =
'# State'
196 if (space%is_periodic()) tmp_str(1) = trim(tmp_str(1))//
' KPoint'
198 if (st%d%ispin ==
spin_polarized) tmp_str(1) = trim(tmp_str(1))//
' Spin'
202 tmp_str(1) = trim(tmp_str(1))//
' Occupation'
204 if (st%d%ispin ==
spinors)
then
205 tmp_str(1) = trim(tmp_str(1))//
' <Sx> <Sy> <Sz>'
208 if (
present(error)) tmp_str(1) = trim(tmp_str(1))//
' Error'
214 max_error = 0.0_real64
215 do iflat = 1, st%nik*nst
216 iqn = flat_indices(1, iflat)
217 ist = flat_indices(2, iflat)
218 ik = st%d%get_kpoint_index(iqn)
219 is = st%d%get_spin_index(iqn)
221 print_eigenval = iflat <= print_range
222 print_eigenval = print_eigenval .or. st%nik*nst - iflat < print_range
223 print_eigenval = print_eigenval .or. abs(iflat - homo_index) <= print_range
225 if (print_eigenval)
then
227 if (not_printed > 0)
then
233 if (
present(error))
then
243 max_error = 0.0_real64
247 write(tmp_str(1),
'(i7)') ist
249 if (space%is_periodic())
then
250 write(tmp_str(1),
'(2a,i7)') trim(tmp_str(1)),
' ', ik
254 if (is == 1) cspin =
' up'
255 if (is == 2) cspin =
' dn'
256 write(tmp_str(1),
'(2a,a5)') trim(tmp_str(1)),
' ', cspin
266 write(tmp_str(1),
'(2a,f11.6)') trim(tmp_str(1)),
' ', st%occ(ist, iqn)
268 if (st%d%ispin ==
spinors)
then
269 write(tmp_str(1),
'(2a,3f9.4)') trim(tmp_str(1)),
' ', st%spin(1:3, ist, iqn)
272 if (
present(error))
then
273 write(tmp_str(1),
'(2a,es8.1,a)') trim(tmp_str(1)),
' (', error(ist, iqn),
')'
281 not_printed = not_printed + 1
283 if (
present(error))
then
284 max_error = max(max_error, error(ist, iqn))
293 safe_deallocate_a(flat_indices)
294 safe_deallocate_a(flat_eigenval)
306 integer,
parameter :: ndiv = 70, height = 10
307 integer :: histogram(1:ndiv), iev, ien, iline, ife
308 real(real64) :: dhistogram(1:ndiv)
309 character(len=ndiv) :: line
310 real(real64) :: emin, emax, de, maxhist
314 emin = flat_eigenval(1)
315 emax = flat_eigenval(st%nik*nst)
316 de = (emax - emin)/(ndiv -
m_one)
323 ife = nint((st%smear%e_fermi - emin)/de) + 1
327 do iev = 1, st%nik*nst
328 ien = nint((flat_eigenval(iev) - emin)/de) + 1
331 dhistogram(ien) = dhistogram(ien) + st%kweights(flat_indices(1, iev))*kpoints%full%npoints
335 maxhist = maxval(dhistogram)
337 histogram(ien) = nint(dhistogram(ien)*height/maxhist)
346 do iline = height, 1, -1
348 if (histogram(ien) >= iline)
then
372 integer,
intent(in) :: iunit
374 class(
space_t),
intent(in) :: space
378 real(real64) :: homo, lumo, egdir, egindir
379 integer :: homok, lumok, egdirk
390 if (ceiling(st%qtot/st%smear%el_per_state) == st%nst)
then
404 if (abs(st%kweights(ik)) <
m_epsilon) cycle
406 if (st%occ(ist, ik) >
m_epsilon .and. st%eigenval(ist, ik) > homo)
then
407 homo = st%eigenval(ist, ik)
411 if (st%occ(ist+1, ik) <=
m_epsilon .and. st%eigenval(ist+1, ik) < lumo)
then
412 lumo = st%eigenval(ist+1, ik)
417 .and. (st%eigenval(ist+1, ik) - st%eigenval(ist, ik)) < egdir)
then
418 egdir = (st%eigenval(ist+1, ik) - st%eigenval(ist, ik))
426 if (lumok == -1 .or. egdir <=
m_epsilon)
then
427 write(
message(1),
'(a)')
'The system seems to have no gap.'
430 write(
message(1),
'(a,i5,a,f7.4,a)')
'Direct gap at ik=', egdirk,
' of ', &
432 write(
message(2),
'(a,i5,a,i5,a,f7.4,a)')
'Indirect gap between ik=', homok,
' and ik=', lumok, &
448 character(len=*),
intent(in) :: dir
450 class(
space_t),
intent(in) :: space
451 class(
mesh_t),
intent(in) :: mesh
455 integer :: ncols, icoord, ist, ik, tpa_initialst, tpa_initialk
458 real(real64),
allocatable :: ff(:)
459 complex(real64),
allocatable :: cff(:)
460 real(real64),
allocatable :: osc(:)
461 real(real64) :: transition_energy, osc_strength, dsf
463 logical :: use_qvector
464 real(real64),
allocatable :: qvector(:), psi_initial(:, :), psi_ist(:, :)
468 use_qvector = .false.
482 if (tpa_initialst == -1)
then
485 call messages_write(
'No orbital with half-occupancy found. TPA output is not written.')
509 if (
parse_block(namespace,
'MomentumTransfer', blk) == 0)
then
514 if (ncols /= space%dim)
then
517 call messages_write(
'Inconsistent size of momentum-transfer vector. It will not be used in the TPA calculation.')
524 safe_allocate(qvector(1:space%dim))
526 do icoord = 1, space%dim
537 safe_allocate(ff(1:mesh%np))
538 if (use_qvector)
then
539 safe_allocate(cff(1:mesh%np))
541 safe_allocate(osc(1:space%dim))
547 iunit =
io_open(trim(dir)//
'/'//trim(
'tpa_xas'), namespace, action=
'write')
550 if (use_qvector)
then
551 write (
message(1),
'(a1,a30,3(es14.5,1x),a1)')
'#',
' momentum-transfer vector : (', &
553 select case (space%dim)
555 write(
message(2),
'(a1,4(a15,1x))')
'#',
'E' ,
'<x>',
'<f>',
'S(q,omega)'
557 write(
message(2),
'(a1,5(a15,1x))')
'#',
'E' ,
'<x>',
'<y>',
'<f>',
'S(q,omega)'
559 write(
message(2),
'(a1,6(a15,1x))')
'#',
'E' ,
'<x>',
'<y>',
'<z>',
'<f>',
'S(q,omega)'
563 select case (space%dim)
565 write(
message(1),
'(a1,3(a15,1x))')
'#',
'E' ,
'<x>',
'<f>'
567 write(
message(1),
'(a1,4(a15,1x))')
'#',
'E' ,
'<x>',
'<y>',
'<f>'
569 write(
message(1),
'(a1,5(a15,1x))')
'#',
'E' ,
'<x>',
'<y>',
'<z>',
'<f>'
576 safe_allocate(psi_initial(1:mesh%np, 1:st%d%dim))
577 safe_allocate(psi_ist(1:mesh%np, 1:st%d%dim))
587 if (abs(st%occ(ist,tpa_initialk)) <
m_min_occ)
then
590 transition_energy = st%eigenval(ist, tpa_initialk) - st%eigenval(tpa_initialst, tpa_initialk)
593 do icoord = 1, space%dim
595 ff(1:mesh%np) = psi_initial(1:mesh%np, 1)*mesh%x(1:mesh%np, icoord)* &
596 psi_ist(1:mesh%np, 1)
598 osc_strength = osc_strength +
m_two/real(space%dim, real64) *transition_energy*abs(osc(icoord))**2
603 if (use_qvector)
then
605 cff(1:mesh%np) = psi_initial(1:mesh%np, 1)*psi_ist(1:mesh%np, 1)
607 do icoord = 1, space%dim
608 cff(1:mesh%np) = cff(1:mesh%np)*
exp(
m_zi*mesh%x(1:mesh%np, icoord)*qvector(icoord))
617 if (use_qvector)
then
637 safe_deallocate_a(psi_initial)
638 safe_deallocate_a(psi_ist)
640 safe_deallocate_a(ff)
641 if (use_qvector)
then
642 safe_deallocate_a(cff)
644 safe_deallocate_a(osc)
645 if (use_qvector)
then
646 safe_deallocate_a(qvector)
658 phase, vec_pot, vec_pot_var)
659 character(len=*),
intent(in) :: dir
661 integer,
intent(in) :: nst
663 type(
ions_t),
target,
intent(in) :: ions
664 class(
mesh_t),
intent(in) :: mesh
666 type(
phase_t),
intent(in) :: phase
667 real(real64),
optional,
allocatable,
intent(in) :: vec_pot(:)
668 real(real64),
optional,
allocatable,
intent(in) :: vec_pot_var(:, :)
671 integer :: idir, ist, ik, ns, is,npath
672 integer,
allocatable :: iunit(:)
673 real(real64) :: red_kpoint(mesh%box%dim)
674 character(len=80) :: filename
676 logical :: projection
677 integer :: ii, ll, mm, nn, work, norb, work2
678 integer :: ia, iorb, idim, maxnorb
679 real(real64),
allocatable :: dpsi(:,:), ddot(:,:)
680 complex(real64),
allocatable :: zpsi(:,:), zdot(:,:)
681 real(real64),
allocatable :: weight(:,:,:,:,:)
689 if (st%d%nspin == 2) ns = 2
699 call parse_variable(namespace,
'BandStructureComputeProjections', .false., projection)
703 safe_allocate(iunit(0:ns-1))
707 write(filename,
'(a,i1.1,a)')
'bandstructure-sp', is+1
709 write(filename,
'(a)')
'bandstructure'
711 iunit(is) =
io_open(trim(dir)//
'/'//trim(filename), namespace, action=
'write')
714 write(iunit(is),
'(a)',advance=
'no')
'# coord. '
715 do idir = 1, mesh%box%dim
716 write(iunit(is),
'(3a)',advance=
'no')
'k',
index2axis(idir),
' '
718 if (.not. projection)
then
719 write(iunit(is),
'(a,i6,3a)')
'(red. coord.), bands:', nst,
' [', trim(
units_abbrev(
units_out%energy)),
']'
721 write(iunit(is),
'(a,i6,3a)',advance=
'no')
'(red. coord.), bands:', nst,
' [', trim(
units_abbrev(
units_out%energy)),
'] '
722 do ia = 1, ions%natoms
726 write(iunit(is),
'(a, i3.3,a,i1.1,a)',advance=
'no')
'w(at=',ia,
',os=',norb,
') '
729 write(iunit(is),
'(a)')
''
734 npath = kpoints%nkpt_in_path()*ns
741 safe_allocate(dpsi(1:mesh%np, 1:st%d%dim))
743 safe_allocate(zpsi(1:mesh%np, 1:st%d%dim))
747 do ia = 1, ions%natoms
751 safe_allocate(weight(1:st%nik,1:st%nst, 1:maxnorb, 1:
max_l, 1:ions%natoms))
752 weight(1:st%nik,1:st%nst, 1:maxnorb, 1:
max_l, 1:ions%natoms) =
m_zero
754 do ia = 1, ions%natoms
765 do iorb = 1, ions%atom(ia)%species%get_niwfs()
766 call ions%atom(ia)%species%get_iwf_ilm(iorb, 1, ii, ll, mm)
767 call ions%atom(ia)%species%get_iwf_n(iorb, 1, nn)
778 os%use_submesh = .false.
779 os%spec => ions%atom(ia)%species
781 do iorb = 1, os%norbs
785 ions%atom(ia)%species, mesh, os%sphere, os%ii, os%ll, os%jj, &
786 os, iorb, os%radius, os%ndim, use_mesh=.not.os%use_submesh, &
790 ions%atom(ia)%species, mesh, os%sphere, os%ii, os%ll, os%jj, &
791 os, iorb, os%radius, os%ndim, use_mesh=.not.os%use_submesh, &
796 if (phase%is_allocated())
then
798 safe_allocate(os%phase(1:os%sphere%np, st%d%kpt%start:st%d%kpt%end))
800 if (.not. os%use_submesh)
then
801 safe_allocate(os%eorb_mesh(1:mesh%np, 1:os%norbs, 1:os%ndim, st%d%kpt%start:st%d%kpt%end))
802 os%eorb_mesh(:,:,:,:) =
m_zero
804 safe_allocate(os%eorb_submesh(1:os%sphere%np, 1:os%ndim, 1:os%norbs, st%d%kpt%start:st%d%kpt%end))
805 os%eorb_submesh(:,:,:,:) =
m_zero
808 vec_pot, vec_pot_var)
812 safe_allocate(ddot(1:st%d%dim,1:os%norbs))
814 safe_allocate(zdot(1:st%d%dim,1:os%norbs))
817 do ist = st%st_start, st%st_end
818 do ik = st%d%kpt%start, st%d%kpt%end
819 if (ik < st%nik - npath + 1) cycle
823 do iorb = 1, os%norbs
824 do idim = 1, st%d%dim
825 weight(ik,ist,iorb,norb,ia) = weight(ik,ist,iorb,norb,ia) + abs(ddot(idim,iorb))**2
830 if (phase%is_allocated())
then
832 call phase%apply_to_single(zpsi, mesh%np, st%d%dim, ik, .false.)
835 zdot(1:st%d%dim,1:os%norbs))
836 do iorb = 1, os%norbs
837 do idim = 1, st%d%dim
838 weight(ik,ist,iorb,norb,ia) = weight(ik,ist,iorb,norb,ia) + abs(zdot(idim,iorb))**2
845 safe_deallocate_a(ddot)
846 safe_deallocate_a(zdot)
851 if (st%parallel_in_states .or. st%d%kpt%parallel)
then
856 safe_deallocate_a(dpsi)
857 safe_deallocate_a(zpsi)
863 do ik = st%nik-npath+1, st%nik, ns
865 red_kpoint(1:mesh%box%dim) = kpoints%get_point(st%d%get_kpoint_index(ik + is), absolute_coordinates=.false.)
866 write(iunit(is),
'(1x)',advance=
'no')
867 if (st%nik > npath)
then
869 st%d%get_kpoint_index(ik + is)-st%d%get_kpoint_index(st%nik -npath))
872 st%d%get_kpoint_index(ik + is))
874 do idir = 1, mesh%box%dim
875 write(iunit(is),
'(f14.8)',advance=
'no') red_kpoint(idir)
881 do ia = 1, ions%natoms
887 write(iunit(is),
'(es15.8)',advance=
'no') weight(ik+is,ist,iorb,norb,ia)
896 write(iunit(is),
'(a)')
906 safe_deallocate_a(weight)
909 safe_deallocate_a(iunit)
This is the common interface to a sorting routine. It performs the shell algorithm,...
double exp(double __x) __attribute__((__nothrow__
integer, parameter, public max_l
subroutine, public zget_atomic_orbital(namespace, space, latt, pos, species, mesh, sm, ii, ll, jj, os, orbind, radius, d_dim, use_mesh, normalize, index_shift)
This routine returns the atomic orbital basis – provided by the pseudopotential structure in geo.
real(real64) function, public atomic_orbital_get_radius(species, mesh, iorb, ispin, truncation, threshold)
subroutine, public dget_atomic_orbital(namespace, space, latt, pos, species, mesh, sm, ii, ll, jj, os, orbind, radius, d_dim, use_mesh, normalize, index_shift)
This routine returns the atomic orbital basis – provided by the pseudopotential structure in geo.
integer, parameter, public unpolarized
Parameters...
integer, parameter, public spinors
integer, parameter, public spin_polarized
real(real64), parameter, public m_two
real(real64), parameter, public m_huge
real(real64), parameter, public m_zero
complex(real64), parameter, public m_zi
real(real64), parameter, public m_epsilon
real(real64), parameter, public m_half
real(real64), parameter, public m_one
real(real64), parameter, public m_min_occ
Minimal occupation that is considered to be non-zero.
This module implements the underlying real-space grid.
subroutine, public io_close(iunit, grp)
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
real(real64) pure function, public kpoints_get_path_coord(this, ind)
This module defines various routines, operating on mesh functions.
complex(real64) function, public zmf_integrate(mesh, ff, mask, reduce)
Integrate a function on the mesh.
real(real64) function, public dmf_integrate(mesh, ff, mask, reduce)
Integrate a function on the mesh.
This module defines the meshes, which are used in Octopus.
subroutine, public messages_warning(no_lines, all_nodes, namespace)
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
subroutine, public messages_new_line()
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
logical function mpi_grp_is_root(grp)
Is the current MPI process of grpcomm, root.
type(mpi_grp_t), public mpi_world
subroutine, public orbitalset_init(this)
subroutine, public orbitalset_end(this)
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...
subroutine, public dorbitalset_get_coefficients(os, ndim, psi, ik, has_phase, dot, reduce)
subroutine, public zorbitalset_get_coefficients(os, ndim, psi, ik, has_phase, dot, reduce)
integer function, public orbitalset_utils_count(species, iselect)
integer function, public parse_block(namespace, name, blk, check_varinfo_)
subroutine, public smear_write_info(this, namespace, iunit)
integer, parameter, public smear_semiconductor
This module is intended to contain "only mathematical" functions and procedures.
pure logical function, public states_are_real(st)
This module handles spin dimensions of the states and the k-point distribution.
This module defines routines to write information about states.
subroutine, public states_elec_write_tpa(dir, namespace, space, mesh, st)
calculate the transition potential and write to a file
subroutine, public states_elec_write_eigenvalues(nst, st, space, kpoints, error, st_start, compact, iunit, namespace)
write the eigenvalues for some states to a file.
subroutine, public states_elec_write_gaps(iunit, st, space)
calculate gaps and write to a file.
subroutine, public states_elec_write_bandstructure(dir, namespace, nst, st, ions, mesh, kpoints, phase, vec_pot, vec_pot_var)
calculate and write the bandstructure
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
character(len=20) pure function, public units_abbrev(this)
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
type(unit_system_t), public units_inp
the units systems for reading and writing
type(unit_t), public unit_one
some special units required for particular quantities
This module is intended to contain simple general-purpose utility functions and procedures.
character pure function, public index2axis(idir)
Describes mesh distribution to nodes.
A container for the phase.
The states_elec_t class contains all electronic wave functions.