Octopus
xc_sic.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!! Copyright (C) 2022 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
22module xc_sic_oct_m
23 use debug_oct_m
25 use global_oct_m
26 use grid_oct_m
33 use parser_oct_m
36 use space_oct_m
40 use xc_oct_m
41 use xc_f03_lib_m
42 use xc_oep_oct_m
43
44 implicit none
45
46 private
47 public :: &
48 xc_sic_t, &
53
55 integer, parameter, public :: &
56 SIC_NONE = 1, & !< no self-interaction correction
57 sic_pz_oep = 2, &
58 sic_amaldi = 3, &
59 sic_adsic = 4
60
62 type xc_sic_t
63 private
64 integer, public :: level = sic_none
65 real(real64), public :: amaldi_factor
66 type(xc_oep_t), public :: oep
67 end type xc_sic_t
68
69contains
70
71 ! ---------------------------------------------------------
73 !
74 subroutine xc_sic_init(sic, namespace, gr, st, mc, space)
75 type(xc_sic_t), intent(out) :: sic
76 type(namespace_t), intent(in) :: namespace
77 type(grid_t), intent(inout) :: gr
78 type(states_elec_t), intent(in) :: st
79 type(multicomm_t), intent(in) :: mc
80 class(space_t), intent(in) :: space
81
82
83 push_sub(xc_sic_init)
84
85 !%Variable SICCorrection
86 !%Type integer
87 !%Default sic_none
88 !%Section Hamiltonian::XC
89 !%Description
90 !% This variable controls which form of self-interaction correction to use. Note that
91 !% this correction will be applied to the functional chosen by <tt>XCFunctional</tt>.
92 !%Option sic_none 1
93 !% No self-interaction correction.
94 !%Option sic_pz 2
95 !% Perdew-Zunger SIC, handled by the OEP technique.
96 !% J. P. Perdew and Alex Zunger, Phys. Rev. B 23, 5048 (1981)
97 !% Extension to the spinor case follows Tancogne-Dejean et al., J. Chem. Phys. 159, 224110 (2023)
98 !%Option sic_amaldi 3
99 !% Amaldi correction term. Not implemeneted for spinors.
100 !% E. Fermi and E. Amaldi, Mem. Reale Accad. Italia 6, 119 (1934)
101 !%Option sic_adsic 4
102 !% Average-density SIC.
103 !% C. Legrand <i>et al.</i>, <i>J. Phys. B</i> <b>35</b>, 1115 (2002).
104 !% Extension to the spinor case follows Tancogne-Dejean et al., J. Chem. Phys. 159, 224110 (2023)
105 !%End
106 call parse_variable(namespace, 'SICCorrection', sic_none, sic%level)
107 if (.not. varinfo_valid_option('SICCorrection', sic%level)) call messages_input_error(namespace, 'SICCorrection')
108
109 ! check whether we should introduce the Amaldi SIC correction
110 sic%amaldi_factor = m_one
111 if (sic%level == sic_amaldi) then
112 sic%amaldi_factor = (st%qtot - m_one)/st%qtot
113 if(st%d%ispin == spinors) then
114 call messages_not_implemented("Amaldi SIC with non-collinear spins")
115 end if
116 end if
117
118 if(sic%level == sic_pz_oep) then
119 call xc_oep_init(sic%oep, namespace, gr, st, mc, space, oep_type = oep_type_sic)
120
121 if(st%nik > st%d%spin_channels) then
122 call messages_not_implemented("PZ-SIC with k-points")
123 end if
124 end if
125
126 if (allocated(st%rho_core)) then
127 call messages_not_implemented('SIC with nonlinear core corrections')
128 end if
129
130 if (allocated(st%frozen_rho) .and. (sic%level == sic_pz_oep .or. sic%level == sic_amaldi)) then
131 call messages_not_implemented('PZ-SIC with frozen orbitals')
132 end if
133
134 if (space%is_periodic() .and. sic%level /= sic_none) then
135 call messages_not_implemented("SIC corrections in periodic systems")
136 end if
137
138 pop_sub(xc_sic_init)
139 end subroutine xc_sic_init
140
141 ! ---------------------------------------------------------
143 subroutine xc_sic_end(sic)
144 type(xc_sic_t), intent(inout) :: sic
145
146 if (sic%level == sic_none) return
147
148 push_sub(xc_sic_end)
149
150 if(sic%level == sic_pz_oep) call xc_oep_end(sic%oep)
151
152 pop_sub(xc_sic_end)
153 end subroutine xc_sic_end
154
156 ! ---------------------------------------------------------
157 subroutine xc_sic_write_info(sic, iunit, namespace)
158 type(xc_sic_t), intent(in) :: sic
159 integer, optional, intent(in) :: iunit
160 type(namespace_t), optional, intent(in) :: namespace
161
162 if (sic%level == sic_none) return
163
164 push_sub(xc_sic_write_info)
165
166 call messages_print_var_option('SICCorrection', sic%level, iunit=iunit, namespace=namespace)
168 pop_sub(xc_sic_write_info)
169 end subroutine xc_sic_write_info
170
171 ! ---------------------------------------------------------
188 subroutine xc_sic_calc_adsic(sic, namespace, space, gr, st, hm, xc, density, vxc, ex, ec)
189 type(xc_sic_t), intent(in) :: sic
190 type(namespace_t), intent(in) :: namespace
191 class(space_t), intent(in) :: space
192 type(grid_t), intent(in) :: gr
193 type(states_elec_t), intent(in) :: st
194 type(hamiltonian_elec_t), intent(in) :: hm
195 type(xc_t), intent(inout) :: xc
196 real(real64), contiguous, intent(in) :: density(:,:)
197 real(real64), contiguous, intent(inout) :: vxc(:,:)
198 real(real64), optional, intent(inout) :: ex, ec
199
200 integer :: ispin, ist, ik, ip
201 real(real64), allocatable :: vxc_sic(:,:), vh_sic(:), rho(:, :), qsp(:)
202 real(real64) :: ex_sic, ec_sic
203 real(real64) :: dtot, dpol, vpol
204 real(real64), parameter :: tiny = 1e-12_real64
205 real(real64) :: nup
206
207 push_sub(xc_sic_calc_adsic)
208
209 assert(sic%level == sic_adsic)
210
211 if (st%d%ispin == spinors .and. bitand(xc%family, xc_family_lda) == 0) then
212 call messages_not_implemented('ADSIC with non-collinear spin and GGAs', namespace=namespace)
213 end if
214
215 if (xc_is_not_size_consistent(xc, namespace)) then
216 call messages_not_implemented('ADSIC with size inconsistent functionals', namespace=namespace)
217 end if
218
219 ! We compute here the number of electrons per spin channel
220 safe_allocate(qsp(1:2))
221 qsp = m_zero
222 if( .not. allocated(st%frozen_rho)) then
223 select case (st%d%ispin)
225 do ist = 1, st%nst
226 do ik = 1, st%nik
227 ispin = st%d%get_spin_index(ik)
228 qsp(ispin) = qsp(ispin) + st%occ(ist, ik) * st%kweights(ik)
229 end do
230 end do
231 end select
232 else
233 ! In the case of the frozen density, we can only get the charge from the integral
234 ! of the total density, including valence and frozen density
235 do ispin = 1, st%d%nspin
236 qsp(ispin) = dmf_integrate(gr, density(:, ispin))
237 end do
238 end if
239
240 safe_allocate(vxc_sic(1:gr%np, 1:2))
241 safe_allocate(vh_sic(1:gr%np))
242 safe_allocate(rho(1:gr%np, 1:2))
243 ! We first compute the average xc self-interction error and we substract it
244 select case (st%d%ispin)
246 do ispin = 1, st%d%nspin
247 if (abs(qsp(ispin)) <= m_min_occ) cycle
248
249 rho = m_zero
250 vxc_sic = m_zero
251
252 rho(:, ispin) = density(:, ispin) / qsp(ispin)
253 if(present(ex) .and. present(ec)) then
254 ex_sic = m_zero
255 ec_sic = m_zero
256 ! This needs always to be called for the spin-polarized case
257 call xc_get_vxc(gr, xc, st, hm%kpoints, hm%psolver, namespace, space, &
258 rho, spin_polarized, hm%ions%latt%rcell_volume, vxc_sic, ex = ex_sic, ec = ec_sic)
259 ex = ex - ex_sic * qsp(ispin)
260 ec = ec - ec_sic * qsp(ispin)
261 else
262 ! This needs always to be called for the spin-polarized case
263 call xc_get_vxc(gr, xc, st, hm%kpoints, hm%psolver, namespace, space, &
264 rho, spin_polarized, hm%ions%latt%rcell_volume, vxc_sic)
265 end if
266
267 call lalg_axpy(gr%np, -m_one, vxc_sic(:, ispin), vxc(:, ispin))
268
269 ! We now substract the averaged Hartree self-interaction error
270 ! See Eq. 15 in [Pietezak and Vieira, Theoretical Chemistry Accounts (2021) 140:130]
271 vh_sic = m_zero
272 call dpoisson_solve(hm%psolver, namespace, vh_sic, rho(:, ispin), all_nodes=.false.)
273 call lalg_axpy(gr%np, -m_one, vh_sic, vxc(:, ispin))
274
275 ! Compute the corresponding energy contribution
276 if(present(ex)) then
277 ex = ex - m_half*dmf_dotp(gr, rho(:,ispin), vh_sic) * qsp(ispin)
278 end if
279
280 end do
282 case (spinors)
283 ! Here we only treat the case of LDA. We rotate the average density in the local frame
284 ! And we then compute the SIC correction from it
285 ! This cannot excerce any xc torque, by construction
286 assert(bitand(xc%family, xc_family_lda) /= 0)
287
288 do ispin = 1, 2
289 rho = m_zero
290 vxc_sic = m_zero
291 ! Averaged density in the local frame
292 do ip = 1, gr%np
293 dtot = density(ip, 1) + density(ip, 2)
294 dpol = sqrt((density(ip, 1) - density(ip, 2))**2 + &
295 m_four*(density(ip, 3)**2 + density(ip, 4)**2))
296 if(ispin == 1) then
297 rho(ip, 1) = max(m_half*(dtot + dpol), m_zero)
298 else
299 rho(ip, 2) = max(m_half*(dtot - dpol), m_zero)
300 end if
301 end do
302 nup = dmf_integrate(gr, rho(:,ispin))
303 if (nup <= 1e-14_real64) cycle
304 call lalg_scal(gr%np, m_one/nup, rho(:,ispin))
305
306 ! This needs always to be called for the spin-polarized case
307 if(present(ex) .and. present(ec)) then
308 ex_sic = m_zero
309 ec_sic = m_zero
310 call xc_get_vxc(gr, xc, st, hm%kpoints, hm%psolver, namespace, space, &
311 rho, spin_polarized, hm%ions%latt%rcell_volume, vxc_sic, ex = ex_sic, ec = ec_sic)
312 ex = ex - ex_sic * nup
313 ec = ec - ec_sic * nup
314 else
315 call xc_get_vxc(gr, xc, st, hm%kpoints, hm%psolver, namespace, space, &
316 rho, spin_polarized, hm%ions%latt%rcell_volume, vxc_sic)
317 end if
318
319 ! Select only the potential correspond to this spin channel
320 if(ispin == 2) then
321 vxc_sic(:, 1) = m_zero
322 else
323 vxc_sic(:, 2) = m_zero
324 end if
325
326 vh_sic = m_zero
327 call dpoisson_solve(hm%psolver, namespace, vh_sic, rho(:, ispin), all_nodes=.false.)
328 call lalg_axpy(gr%np, m_one, vh_sic, vxc_sic(:, ispin))
329 ! Compute the corresponding energy contribution
330 if(present(ex)) then
331 ex = ex - m_half*dmf_dotp(gr, rho(:,ispin), vh_sic) * nup
332 end if
333
334 do ip = 1, gr%np
335 dpol = sqrt((density(ip, 1) - density(ip, 2))**2 + &
336 m_four*(density(ip, 3)**2 + density(ip, 4)**2))
337 vpol = (vxc_sic(ip, 1) - vxc_sic(ip, 2))*(density(ip, 1) - density(ip, 2))/(safe_tol(dpol, tiny))
338
339 vxc(ip, 1) = vxc(ip, 1) - m_half*(vxc_sic(ip, 1) + vxc_sic(ip, 2) + vpol)
340 vxc(ip, 2) = vxc(ip, 2) - m_half*(vxc_sic(ip, 1) + vxc_sic(ip, 2) - vpol)
341 vxc(ip, 3) = vxc(ip, 3) - (vxc_sic(ip, 1) - vxc_sic(ip, 2))*density(ip, 3)/(safe_tol(dpol, tiny))
342 vxc(ip, 4) = vxc(ip, 4) - (vxc_sic(ip, 1) - vxc_sic(ip, 2))*density(ip, 4)/(safe_tol(dpol, tiny))
343 end do
344 end do
345
346
347 end select
348
349 safe_deallocate_a(qsp)
350 safe_deallocate_a(vxc_sic)
351 safe_deallocate_a(vh_sic)
352 safe_deallocate_a(rho)
353
354 pop_sub(xc_sic_calc_adsic)
355 end subroutine xc_sic_calc_adsic
356
357end module xc_sic_oct_m
358
359!! Local Variables:
360!! mode: f90
361!! coding: utf-8
362!! End:
constant times a vector plus a vector
Definition: lalg_basic.F90:170
scales a vector by a constant
Definition: lalg_basic.F90:156
double sqrt(double __x) __attribute__((__nothrow__
integer, parameter, public unpolarized
Parameters...
integer, parameter, public spinors
integer, parameter, public spin_polarized
real(real64), parameter, public m_zero
Definition: global.F90:187
real(real64), parameter, public m_four
Definition: global.F90:191
real(real64), parameter, public m_half
Definition: global.F90:193
real(real64), parameter, public m_one
Definition: global.F90:188
real(real64), parameter, public m_min_occ
Minimal occupation that is considered to be non-zero.
Definition: global.F90:210
This module implements the underlying real-space grid.
Definition: grid.F90:117
This module defines various routines, operating on mesh functions.
real(real64) function, public dmf_integrate(mesh, ff, mask, reduce)
Integrate a function on the mesh.
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1125
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:723
This module handles the communicators for the various parallelization strategies.
Definition: multicomm.F90:145
subroutine, public dpoisson_solve(this, namespace, pot, rho, all_nodes, kernel)
Calculates the Poisson equation. Given the density returns the corresponding potential.
Definition: poisson.F90:892
This module handles spin dimensions of the states and the k-point distribution.
Definition: xc.F90:114
real(real64), parameter tiny
Definition: xc.F90:208
subroutine, public xc_get_vxc(gr, xcs, st, kpoints, psolver, namespace, space, rho, ispin, rcell_volume, vxc, ex, ec, deltaxc, vtau, ex_density, ec_density, stress_xc, force_orbitalfree)
Definition: xc.F90:754
logical function, public xc_is_not_size_consistent(xcs, namespace)
Is one of the x or c functional is not size consistent.
Definition: xc.F90:718
subroutine, public xc_oep_end(oep)
Definition: xc_oep.F90:356
subroutine, public xc_oep_init(oep, namespace, gr, st, mc, space, oep_type)
Definition: xc_oep.F90:217
integer, parameter, public oep_type_sic
Definition: xc_oep.F90:184
subroutine, public xc_sic_write_info(sic, iunit, namespace)
Definition: xc_sic.F90:251
integer, parameter, public sic_adsic
Averaged density SIC.
Definition: xc_sic.F90:148
subroutine, public xc_sic_init(sic, namespace, gr, st, mc, space)
initialize the SIC object
Definition: xc_sic.F90:168
subroutine, public xc_sic_end(sic)
finalize the SIC and, if needed, the included OEP
Definition: xc_sic.F90:237
integer, parameter, public sic_pz_oep
Perdew-Zunger SIC (OEP way)
Definition: xc_sic.F90:148
integer, parameter, public sic_amaldi
Amaldi correction term.
Definition: xc_sic.F90:148
subroutine, public xc_sic_calc_adsic(sic, namespace, space, gr, st, hm, xc, density, vxc, ex, ec)
Computes the ADSIC potential and energy.
Definition: xc_sic.F90:282
Description of the grid, containing information on derivatives, stencil, and symmetries.
Definition: grid.F90:168
The states_elec_t class contains all electronic wave functions.
This class contains information about the self-interaction correction.
Definition: xc_sic.F90:155