46 complex(real64),
allocatable,
public :: charge(:, :, :)
47 complex(real64),
allocatable :: sum_ideal(:,:)
48 complex(real64),
allocatable :: delta(:,:)
56 type(born_charges_t),
intent(out) :: this
57 type(namespace_t),
intent(in) :: namespace
58 integer,
intent(in) :: natoms
59 real(real64),
intent(in) :: val_charge
60 real(real64),
intent(in) :: qtot
61 integer,
intent(in) :: dim
67 safe_allocate(this%charge(1:dim, 1:dim, 1:natoms))
68 safe_allocate(this%sum_ideal(1:dim, 1:dim))
69 safe_allocate(this%delta(1:dim, 1:dim))
70 this%charge(1:dim, 1:dim, 1:natoms) =
m_zero
71 this%delta(1:dim, 1:dim) =
m_zero
75 this%sum_ideal(idir, idir) = -(val_charge + qtot)
96 type(born_charges_t),
intent(inout) :: this
100 safe_deallocate_a(this%charge)
101 safe_deallocate_a(this%sum_ideal)
102 safe_deallocate_a(this%delta)
111 type(born_charges_t),
intent(inout) :: this
112 integer,
intent(in) :: natoms
113 integer,
intent(in) :: dim
115 complex(real64) :: born_sum(dim, dim)
123 born_sum = born_sum + this%charge(:, :, iatom)
126 this%delta = (born_sum - this%sum_ideal) / natoms
128 if (this%correct)
then
130 this%charge(:, :, iatom) = this%charge(:, :, iatom) - this%delta
138 subroutine born_output_charges(this, atom, charge, natoms, namespace, dim, dirname, write_real)
141 real(real64),
intent(in) :: charge(:)
142 integer,
intent(in) :: natoms
144 integer,
intent(in) :: dim
145 character(len=*),
intent(in) :: dirname
146 logical,
intent(in) :: write_real
150 real(real64) :: phase(dim, dim)
157 iunit =
io_open(trim(dirname)//
'/born_charges', namespace, action=
'write')
158 write(iunit,
'(a)')
'# (Frequency-dependent) Born effective charge tensors'
159 if (.not. write_real)
write(iunit,
'(a)')
'# Real and imaginary parts'
161 write(iunit,
'(a,i5,a,a5,a,f10.4)')
'Index: ', iatom,
' Label: ', trim(atom(iatom)%species%get_label()), &
162 ' Ionic charge: ', charge(iatom)
164 if (.not. write_real)
write(iunit,
'(a)')
'Real:'
167 if (.not. write_real)
then
168 write(iunit,
'(a)')
'Imaginary:'
175 if (.not. write_real)
then
176 write(iunit,
'(a)')
'# Magnitude and phase'
178 write(iunit,
'(a,i5,a,a5,a,f10.4)')
'Index: ', iatom,
' Label: ', trim(atom(iatom)%species%get_label()), &
179 ' Ionic charge: ', charge(iatom)
181 write(iunit,
'(a)')
'Magnitude:'
184 write(iunit,
'(a)')
'Phase:'
186 where (abs(this%charge(:, :, iatom)) >
m_epsilon)
187 phase =
atan2(aimag(this%charge(:, :, iatom)), real(this%charge(:, :, iatom), real64))
196 write(iunit,
'(a)')
'# Discrepancy of Born effective charges from acoustic sum rule before correction, per atom'
197 if (.not. write_real)
write(iunit,
'(a)')
'Real:'
199 if (.not. write_real)
then
200 write(iunit,
'(a)')
'Imaginary:'
double atan2(double __y, double __x) __attribute__((__nothrow__
subroutine, public born_charges_end(this)
subroutine, public born_output_charges(this, atom, charge, natoms, namespace, dim, dirname, write_real)
subroutine, public born_charges_init(this, namespace, natoms, val_charge, qtot, dim)
subroutine correct_born_charges(this, natoms, dim)
The sum over atoms of a given tensor component of the born charges should be Z delta_ij to satisfy th...
real(real64), parameter, public m_zero
real(real64), parameter, public m_epsilon
subroutine, public io_close(iunit, grp)
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
logical function mpi_grp_is_root(grp)
Is the current MPI process of grpcomm, root.
type(mpi_grp_t), public mpi_world
This module defines the unit system, used for input and output.
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.
subroutine, public output_tensor(tensor, ndim, unit, write_average, iunit, namespace)