Octopus
ps_in_grid.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
22 use atomic_oct_m
23 use debug_oct_m
24 use global_oct_m
25 use, intrinsic :: iso_fortran_env
26 use logrid_oct_m
30
31 implicit none
32
33 private
34 public :: &
44
45 type ps_in_grid_t
46 ! Components are public by default
47 type(logrid_t) :: g
48
49 real(real64) :: zval
50
51 integer :: no_l_channels
52 real(real64), allocatable :: vps(:, :)
53 real(real64), allocatable :: KB(:,:)
54 real(real64), allocatable :: dkbcos(:)
55 real(real64), allocatable, private :: dknorm(:)
56 real(real64), allocatable :: kb_radius(:)
57
58 integer :: so_no_l_channels
59 real(real64), allocatable :: so_vps(:,:)
60 real(real64), allocatable, private :: so_KB(:,:)
61 real(real64), allocatable, private :: so_dkbcos(:)
62 real(real64), allocatable, private :: so_dknorm(:)
63 real(real64), allocatable, private :: so_kb_radius(:)
64
65 real(real64), allocatable :: vlocal(:)
66 real(real64), allocatable :: rphi(:, :,:)
67
68 logical :: core_corrections
69 real(real64), allocatable :: chcore(:)
70
71 end type ps_in_grid_t
72
73contains
74
75 subroutine ps_in_grid_init(ps, flavor, a, b, nrval, no_l, so_no_l)
76 type(ps_in_grid_t), intent(out) :: ps
77 integer, intent(in) :: flavor, nrval
78 real(real64), intent(in) :: a, b
79 integer, intent(in) :: no_l, so_no_l
80
81 push_sub(ps_in_grid_init)
82
83 ! initialize logarithmic grid
84 call logrid_init(ps%g, flavor, a, b, nrval)
85
86 ! copy data
87 ps% no_l_channels = no_l
88 ps%so_no_l_channels = so_no_l
89
90 ! Allocate some stuff
91 safe_allocate(ps%vps (1:ps%g%nrval, 1:no_l))
92 safe_allocate(ps%chcore (1:ps%g%nrval))
93 safe_allocate(ps%vlocal (1:ps%g%nrval))
94
95 safe_allocate(ps%rphi (1:ps%g%nrval, 1:no_l, 1:3))
96 safe_allocate(ps%KB (1:ps%g%nrval, 1:no_l))
97 safe_allocate(ps%dkbcos(1:no_l))
98 safe_allocate(ps%dknorm(1:no_l))
99 safe_allocate(ps%kb_radius(1:no_l+1))
100
101 if (so_no_l > 0) then
102 safe_allocate(ps%so_vps(1:ps%g%nrval, 1:so_no_l))
103 safe_allocate(ps%so_KB (1:ps%g%nrval, 1:so_no_l))
104 safe_allocate(ps%so_dkbcos(1:so_no_l))
105 safe_allocate(ps%so_dknorm(1:so_no_l))
106 safe_allocate(ps%so_kb_radius(1:so_no_l))
107 end if
108
109 pop_sub(ps_in_grid_init)
110 end subroutine ps_in_grid_init
111
112
113 ! ---------------------------------------------------------
114 subroutine ps_in_grid_end(ps)
115 type(ps_in_grid_t), intent(inout) :: ps
116
117 push_sub(ps_in_grid_end)
118
119 safe_deallocate_a(ps%vps)
120 safe_deallocate_a(ps%chcore)
121 safe_deallocate_a(ps%vlocal)
122
123 safe_deallocate_a(ps%rphi)
124 safe_deallocate_a(ps%KB)
125 safe_deallocate_a(ps%dkbcos)
126 safe_deallocate_a(ps%dknorm)
127 safe_deallocate_a(ps%kb_radius)
128
129 if (ps%so_no_l_channels > 0) then
130 safe_deallocate_a(ps%so_vps)
131 safe_deallocate_a(ps%so_KB)
132 safe_deallocate_a(ps%so_dkbcos)
133 safe_deallocate_a(ps%so_dknorm)
134 safe_deallocate_a(ps%so_kb_radius)
135 end if
136
137 call logrid_end(ps%g)
139 pop_sub(ps_in_grid_end)
140 end subroutine ps_in_grid_end
141
143 ! ---------------------------------------------------------
144 subroutine ps_in_grid_vlocal(ps, l_loc, rcore, namespace)
145 type(ps_in_grid_t), intent(inout) :: ps
146 integer, intent(in) :: l_loc
147 real(real64), intent(in) :: rcore
148 type(namespace_t), intent(in) :: namespace
150 integer :: ir
151 real(real64) :: a, b, qtot
152 real(real64), allocatable :: rho(:)
156 if (l_loc >= 0) then
157 ps%vlocal(:) = ps%vps(:, l_loc+1)
159 else if (l_loc == -1) then
160 if (ps%g%flavor /= logrid_psf) then
161 message(1) = "For the moment, Vanderbilt local potentials are only possible with tm grids."
162 call messages_fatal(1, namespace=namespace)
163 end if
164
165 a = 1.82_real64 / rcore
166 b = m_one
167 safe_allocate(rho(1:ps%g%nrval))
169 do ir = 1, ps%g%nrval
170 rho(ir) = exp(-(sinh(a*b*ps%g%rofi(ir)) / sinh(b))**2)
171 rho(ir) = m_four * m_pi * rho(ir) * ps%g%r2ofi(ir)
172 end do
173! do ir =1,2
174 qtot = sum(rho(:)*ps%g%drdi(:))
175 rho(:) = - rho(:)*(ps%zval/qtot)
176
177 call vhrtre(rho, ps%vlocal, ps%g%rofi, ps%g%drdi, ps%g%s, ps%g%nrval, ps%g%a)
178 ps%vlocal(1) = ps%vlocal(2)
179
180 safe_deallocate_a(rho)
181 end if
182
183 pop_sub(ps_in_grid_vlocal)
184 end subroutine ps_in_grid_vlocal
185
186
187 ! ---------------------------------------------------------
190 subroutine ps_in_grid_kb_projectors(ps)
191 type(ps_in_grid_t), intent(inout) :: ps
192
193 integer :: l
194
196
197 do l = 1, ps%no_l_channels
198 ps%KB(2:, l) = (ps%vps(2:, l) - ps%vlocal(2:))*(ps%rphi(2:, l, 1)/ps%g%rofi(2:))*ps%dknorm(l)
199
200 ps%KB(1, l) = first_point_extrapolate(ps%g%rofi, ps%KB(:, l))
201 end do
202
203 do l = 1, ps%so_no_l_channels
204 ps%so_KB(2:, l) = ps%so_vps(2:, l)*(ps%rphi(2:, l, 1)/ps%g%rofi(2:))*ps%dknorm(l)
205
206 ps%so_KB(1, l) = first_point_extrapolate(ps%g%rofi, ps%so_KB(:, l))
207 end do
208
210 end subroutine ps_in_grid_kb_projectors
211
212
213 ! ---------------------------------------------------------
219 subroutine ps_in_grid_kb_cosines(ps, lloc)
220 type(ps_in_grid_t), intent(inout) :: ps
221 integer, intent(in) :: lloc
222
223 integer :: ir, l
224 real(real64) :: dnrm, avgv, vphi
225 real(real64), parameter :: tol = 1.0e-20_real64
226
227 push_sub(ps_in_grid_kb_cosines)
228
229 do l = 1, ps%no_l_channels
230 if (l-1 == lloc) then
231 ps%dkbcos(l) = m_zero
232 ps%dknorm(l) = m_zero
233 cycle
234 end if
235
236 dnrm = m_zero
237 avgv = m_zero
238 do ir = 1, ps%g%nrval
239 vphi = (ps%vps(ir, l) - ps%vlocal(ir))*ps%rphi(ir, l, 1)
240 dnrm = dnrm + vphi*vphi*ps%g%drdi(ir)
241 avgv = avgv + vphi*ps%rphi(ir, l, 1)*ps%g%drdi(ir)
242 end do
243 ps%dkbcos(l) = dnrm/safe_tol(avgv, tol)
244 ps%dknorm(l) = m_one/safe_tol(sqrt(dnrm), tol)
245 end do
246
247 do l = 1, ps%so_no_l_channels
248 dnrm = m_zero
249 avgv = m_zero
250 do ir = 1, ps%g%nrval
251 vphi = ps%so_vps(ir, l)*ps%rphi(ir, l, 1)
252 dnrm = dnrm + vphi*vphi*ps%g%drdi(ir)
253 avgv = avgv + vphi*ps%rphi(ir, l, 1)*ps%g%drdi(ir)
254 end do
255 ps%so_dkbcos(l) = dnrm/safe_tol(avgv, tol)
256 ps%so_dknorm(l) = m_one/safe_tol(sqrt(dnrm), tol)
257 end do
258
259 pop_sub(ps_in_grid_kb_cosines)
260 end subroutine ps_in_grid_kb_cosines
261
262
263 ! ---------------------------------------------------------
264 subroutine ps_in_grid_cutoff_radii(ps, lloc)
265 type(ps_in_grid_t), intent(inout) :: ps
266 integer, intent(in) :: lloc
267
268 integer :: l, ir
269 real(real64) :: dincv, phi
270 real(real64), parameter :: threshold = 1.0e-6_real64
271
273
274 ! local part ....
275 do ir = ps%g%nrval-1, 2, -1
276 dincv = abs(ps%vlocal(ir)*ps%g%rofi(ir) + m_two*ps%zval)
277 if (dincv > threshold) exit
278 end do
279 ps%kb_radius(ps%no_l_channels+1) = ps%g%rofi(ir + 1)
280
281 ! non-local part....
282 do l = 1, ps%no_l_channels
283 if (l-1 == lloc) then
284 ps%kb_radius(l) = m_zero
285 cycle
286 end if
287
288 do ir = ps%g%nrval-1, 2, -1
289 phi = (ps%rphi(ir, l, 1)/ps%g%rofi(ir))*ps%dknorm(l)
290 dincv = abs((ps%vps(ir, l) - ps%vlocal(ir))*phi)
291
292 if (dincv > threshold) exit
293
294 phi = (ps%rphi(ir, l, 1)/ps%g%rofi(ir))*ps%dknorm(l)
295 end do
296
297 ps%kb_radius(l) = ps%g%rofi(ir + 1)
298 end do
299
300 ! now the SO part
301 do l = 1, ps%so_no_l_channels
302 do ir = ps%g%nrval-1, 2, -1
303 phi = (ps%rphi(ir, l, 1)/ps%g%rofi(ir))*ps%so_dknorm(l)
304 dincv = abs((ps%so_vps(ir, l))*phi)
305
306 if (dincv > threshold) exit
307 end do
308
309 ps%so_kb_radius(l) = ps%g%rofi(ir + 1)
310 end do
311
313 end subroutine ps_in_grid_cutoff_radii
314
315
316 ! ---------------------------------------------------------
318 subroutine ps_in_grid_check_rphi(ps, namespace)
319 type(ps_in_grid_t), intent(in) :: ps
320 type(namespace_t), intent(in) :: namespace
321
322 integer :: l
323 real(real64) :: nrm
324
325 push_sub(ps_in_grid_check_rphi)
326
327 ! checking normalization of the wavefunctions
328 do l = 1, ps%no_l_channels
329 nrm = sqrt(sum(ps%g%drdi(:)*ps%rphi(:, l, 1)**2))
330 nrm = abs(nrm - m_one)
331 if (nrm > 1.0e-5_real64) then
332 write(message(1), '(a,i2,a)') "Eigenstate for l = ", l-1, ' is not normalized.'
333 write(message(2), '(a, f12.6,a)') '(abs(1 - norm) = ', nrm, ')'
334 call messages_warning(2, namespace=namespace)
335 end if
336 end do
337
338 pop_sub(ps_in_grid_check_rphi)
339 end subroutine ps_in_grid_check_rphi
340
341 ! ---------------------------------------------------------
342
343 real(real64) function first_point_extrapolate(x, y, high_order) result(y0)
344 real(real64), intent(in) :: x(:)
345 real(real64), intent(in) :: y(:)
346 logical, optional, intent(in) :: high_order
347
348 real(real64) :: x1, x2, x3
349 real(real64) :: y1, y2, y3
350
351 x1 = x(2) - x(1)
352 x2 = x(3) - x(1)
353 x3 = x(4) - x(1)
354 y1 = y(2)
355 y2 = y(3)
356 y3 = y(4)
358 if (optional_default(high_order, .false.)) then
359
360 y0 = y1*x2*x3*(x2 - x3) + y2*x1*x3*(x3 - x1) + y3*x1*x2*(x1 - x2)
361 y0 = y0/((x1 - x2)*(x1 - x3)*(x2 - x3))
362
363 else
364
365 y0 = y1 - (y2 - y1)*x1/(x2 - x1)
366
367 end if
368
369 end function first_point_extrapolate
370
371end module ps_in_grid_oct_m
372
373!! Local Variables:
374!! mode: f90
375!! coding: utf-8
376!! End:
double exp(double __x) __attribute__((__nothrow__
double sqrt(double __x) __attribute__((__nothrow__
double sinh(double __x) __attribute__((__nothrow__
subroutine, public vhrtre(rho, v, r, drdi, srdrdi, nr, a)
VHRTRE CONSTRUCTS THE ELECTROSTATIC POTENTIAL DUE TO A SUPPLIED ! ELECTRON DENSITY....
Definition: atomic.F90:627
real(real64), parameter, public m_two
Definition: global.F90:189
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_pi
some mathematical constants
Definition: global.F90:185
real(real64), parameter, public m_one
Definition: global.F90:188
integer, parameter, public logrid_psf
log grid used in Troullier-Martins code
Definition: logrid.F90:135
subroutine, public logrid_end(grid)
Definition: logrid.F90:213
subroutine, public logrid_init(grid, flavor, aa, bb, nrval)
Definition: logrid.F90:156
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:543
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:420
subroutine, public ps_in_grid_kb_projectors(ps)
KB-projectors kb = (vps - vlocal) |phi> * dknorm.
Definition: ps_in_grid.F90:284
subroutine, public ps_in_grid_end(ps)
Definition: ps_in_grid.F90:208
subroutine, public ps_in_grid_cutoff_radii(ps, lloc)
Definition: ps_in_grid.F90:358
subroutine, public ps_in_grid_init(ps, flavor, a, b, nrval, no_l, so_no_l)
Definition: ps_in_grid.F90:169
subroutine, public ps_in_grid_kb_cosines(ps, lloc)
KB-cosines and KB-norms: dkbcos stores the KB "cosines:" || (v_l - v_local) phi_l ||^2 / < (v_l - v_l...
Definition: ps_in_grid.F90:313
subroutine, public ps_in_grid_vlocal(ps, l_loc, rcore, namespace)
Definition: ps_in_grid.F90:238
real(real64) function, public first_point_extrapolate(x, y, high_order)
Definition: ps_in_grid.F90:437
subroutine, public ps_in_grid_check_rphi(ps, namespace)
checks normalization of the pseudo wavefunctions
Definition: ps_in_grid.F90:412