Octopus
zora.F90
Go to the documentation of this file.
1!! Copyright (C) 2023 L. Konecny, M. Lueders
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
23module zora_oct_m
24
25 use batch_oct_m
27 use debug_oct_m
29 use epot_oct_m
30 use global_oct_m
31 use grid_oct_m
33 use mesh_oct_m
39
40 implicit none
41
42 private
43 public :: zora_t
44
45 integer, parameter, public :: &
46 ZORA_NONE = 0, & !< no ZORA
49
51 !
52 type :: zora_t
53 private
54
55 real(real64), allocatable :: pot(:,:)
56 real(real64), allocatable :: grad_pot(:,:,:)
57 ! !! \f$ \nabla ( \frac{c^2}{2c^2 - V} ) \f$
58 real(real64), allocatable :: soc(:,:,:)
59 ! !! \f$ {\rm zora\%pref} * (\sigma \times {\nabla V}) \cdot p \f$
60
61 real(real64) :: so_strength = m_zero
62 real(real64) :: mass = m_zero
63
64 integer :: zora_level = zora_none
65
66 contains
67 procedure :: update => zora_update
68 procedure :: dapply_batch => dzora_apply_batch
69 procedure :: zapply_batch => zzora_apply_batch
70 final :: zora_finalize
71 end type
72
73 interface zora_t
74 procedure zora_constructor
75 end interface zora_t
76
77contains
78
82 !
83 function zora_constructor(namespace, der, st_d, ep, mass) result(this)
84 type(namespace_t), intent(in) :: namespace
85 type(derivatives_t), intent(in) :: der
86 type(states_elec_dim_t), intent(in) :: st_d
87 type(epot_t), intent(in) :: ep
88 real(real64), intent(in) :: mass
89 class(zora_t), pointer :: this
90
91 push_sub(zora_constructor)
92 safe_allocate(this)
93
94
95 this%so_strength = ep%so_strength
96 this%mass = mass
97
98 select case (ep%reltype)
100 this%zora_level = zora_scalar_relativistic
102 this%zora_level = zora_fully_relativistic
103 case default
104 this%zora_level = zora_none
105 pop_sub(zora_constructor)
106 return
107 end select
108
109 if (der%dim /= 3) then
110 call messages_not_implemented("ZORA for dimensions /= 3", namespace)
111 end if
112
113 safe_allocate(this%pot(1:der%mesh%np_part, 1:st_d%nspin))
114 safe_allocate(this%grad_pot(1:der%mesh%np, 1:st_d%nspin, 1:der%dim))
115
116 if(this%zora_level == zora_fully_relativistic) then
117
118 assert(st_d%nspin == 4)
119 safe_allocate(this%soc(1:der%mesh%np, 1:st_d%nspin, 1:der%dim))
120
121 end if
122
123 pop_sub(zora_constructor)
124 end function zora_constructor
125
126
128 subroutine zora_finalize(this)
129 type(zora_t), intent(inout) :: this
130
131 push_sub(zora_finalize)
132
133 safe_deallocate_a(this%pot)
134 safe_deallocate_a(this%grad_pot)
135 safe_deallocate_a(this%soc)
136
137 pop_sub(zora_finalize)
138 end subroutine zora_finalize
139
160 subroutine zora_update(this, der, potential)
161 class(zora_t), intent(inout) :: this
162 class(derivatives_t), intent(in) :: der
163 real(real64), contiguous, intent(in) :: potential(:, :)
165 real(real64), allocatable :: zora_scpot(:), grad_pot(:,:)
166 real(real64) :: prefactor, two_c2
167
168 integer :: ip, idir
169 integer :: nspin
170
171 push_sub(zora_update)
172
173 if (this%zora_level == zora_none) then
174 pop_sub(zora_update)
175 return
176 end if
177
178 nspin = size(this%pot, dim=2)
179 two_c2 = m_two * p_c**2
180
181 ! We need to copy the potential to an array, allocated to np_part for the application of the derivatives.
182
183 safe_allocate( zora_scpot(1:der%mesh%np_part) )
184 safe_allocate( grad_pot(1:der%mesh%np_part, 1:der%dim) )
185
186 ! Only channel 1 is read: the caller passes the ionic plus external potential, before
187 ! add_vhxc() and before the Zeeman term, so V is spin independent by construction (see
188 ! hamiltonian_elec_update_pot). The ZORA prefactor is therefore a scalar in spin space:
189 ! channel 2 below is a copy, and the spinor off-diagonal channels 3 and 4 vanish.
190 !$omp parallel private(ip)
191 !$omp do simd schedule(static)
192 do ip = 1, der%mesh%np
193 ! zora_scpot = V
194 zora_scpot(ip) = potential(ip, 1)
195 ! zora_pot = \frac{c^2}{2 m c^2 - V}
196 ! included extra factor of 2 because of -1/2 in kinetic energy
197 this%pot(ip,1) = two_c2 / (this%mass * two_c2 - zora_scpot(ip) )
198 end do
199 !$omp end do simd
200
201 if (nspin > 1) then
202 !$omp do simd schedule(static)
203 do ip = 1, der%mesh%np
204 this%pot(ip,2) = this%pot(ip,1)
205 end do
206 !$omp end do simd
207 end if
208 if (nspin > 2) then
209 !$omp do simd schedule(static)
210 do ip = 1, der%mesh%np
211 this%pot(ip,3) = m_zero
212 this%pot(ip,4) = m_zero
213 end do
214 !$omp end do simd
215 end if
216 !$omp end parallel
217
218 ! zora_grad_pot = grad( \frac{c^2}{2 m c^2 - V} )
219
220 call dderivatives_grad(der, this%pot(:,1), grad_pot)
221
222 do idir=1, der%dim
223 !$omp parallel private(ip)
224 !$omp do simd schedule(static)
225 do ip = 1, der%mesh%np
226 this%grad_pot(ip, 1, idir)= grad_pot(ip,idir)
227 end do
228 !$omp end do simd
229
230 if (nspin > 1) then
231 !$omp do simd schedule(static)
232 do ip = 1, der%mesh%np
233 this%grad_pot(ip, 2, idir)= grad_pot(ip,idir)
234 end do
235 !$omp end do simd
236 end if
237
238 if (nspin > 2) then
239 !$omp do simd schedule(static)
240 do ip = 1, der%mesh%np
241 this%grad_pot(ip, 3, idir)= m_zero
242 this%grad_pot(ip, 4, idir)= m_zero
243 end do
244 !$omp end do simd
245 end if
246 !$omp end parallel
247
248 end do
249
250 ! spin-orbit relativistic ZORA contribution
251 if (this%zora_level == zora_fully_relativistic) then
253 end if
254
255 safe_deallocate_a( zora_scpot )
256 safe_deallocate_a( grad_pot )
257
258 pop_sub(zora_update)
259
260 contains
261
267
269
270 real(real64), allocatable :: grad_v(:,:)
271
273
274 safe_allocate(grad_v(1:der%mesh%np, 1:der%dim))
275
276
277 ! gradient of potenial, only consider scalar potential
278 call dderivatives_grad(der, zora_scpot(:), grad_v(:,:))
279
280 !$omp parallel private(ip, prefactor)
281 !$omp do simd schedule(static)
282 do ip = 1, der%mesh%np
283
284 ! added extra factor of 2 because of -1/2 in the gradient
285 prefactor = this%so_strength * two_c2 / (this%mass*two_c2 - zora_scpot(ip))**2
286
287 grad_v(ip, 1) = grad_v(ip, 1) * prefactor
288 grad_v(ip, 2) = grad_v(ip, 2) * prefactor
289 grad_v(ip, 3) = grad_v(ip, 3) * prefactor
290
291 ! sigma \times zora_grad_v
292 ! four-component vector has elements ( up-up, down-down, Re(up-down), Im(up-down) )
293 this%soc(ip, 1, 1) = -grad_v(ip, 2)
294 this%soc(ip, 2, 1) = grad_v(ip, 2)
295 this%soc(ip, 3, 1) = m_zero
296 this%soc(ip, 4, 1) = -grad_v(ip, 3)
297
298 this%soc(ip, 1, 2) = grad_v(ip, 1)
299 this%soc(ip, 2, 2) = -grad_v(ip, 1)
300 this%soc(ip, 3, 2) = -grad_v(ip, 3)
301 this%soc(ip, 4, 2) = m_zero
302
303 this%soc(ip, 1, 3) = m_zero
304 this%soc(ip, 2, 3) = m_zero
305 this%soc(ip, 3, 3) = grad_v(ip, 2)
306 this%soc(ip, 4, 3) = grad_v(ip, 1)
307
308 end do
309 !$omp end do simd
310 !$omp end parallel
311
312 safe_deallocate_a(grad_v)
313
315 end subroutine zora_update_fully_relativistic
316
317 end subroutine zora_update
318
319#include "undef.F90"
320#include "real.F90"
321#include "zora_inc.F90"
322
323#include "undef.F90"
324#include "complex.F90"
325#include "zora_inc.F90"
326
327
328end module zora_oct_m
This module implements batches of mesh functions.
Definition: batch.F90:135
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:118
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
subroutine, public dderivatives_grad(der, ff, op_ff, ghost_update, set_bc, to_cartesian)
apply the gradient to a mesh function
integer, parameter, public scalar_relativistic_zora
Definition: epot.F90:168
integer, parameter, public fully_relativistic_zora
Definition: epot.F90:168
real(real64), parameter, public m_two
Definition: global.F90:202
real(real64), parameter, public m_zero
Definition: global.F90:200
real(real64), parameter, public p_c
Electron gyromagnetic ratio, see Phys. Rev. Lett. 130, 071801 (2023)
Definition: global.F90:242
This module implements the underlying real-space grid.
Definition: grid.F90:119
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1068
This module handles spin dimensions of the states and the k-point distribution.
This module implements the ZORA terms for the Hamoiltonian.
Definition: zora.F90:118
integer, parameter, public zora_scalar_relativistic
ZORA for scalar relativistic calculations.
Definition: zora.F90:140
subroutine zora_update(this, der, potential)
update the ZORA potentials
Definition: zora.F90:256
subroutine zzora_apply_batch(this, mesh, der, states_dim, psib, hpsib, set_bc)
apply the ZORA to a batch of states psib
Definition: zora.F90:632
class(zora_t) function, pointer zora_constructor(namespace, der, st_d, ep, mass)
initialize the ZORA
Definition: zora.F90:179
subroutine zora_finalize(this)
finalize the ZORA object and free memory
Definition: zora.F90:224
subroutine dzora_apply_batch(this, mesh, der, states_dim, psib, hpsib, set_bc)
apply the ZORA to a batch of states psib
Definition: zora.F90:493
integer, parameter, public zora_fully_relativistic
ZORA for fully relativistic calculations.
Definition: zora.F90:140
class representing derivatives
This class is responsible for calculating and applying the ZORA.
Definition: zora.F90:147
subroutine zora_update_fully_relativistic()
update quantities, necessary only for fully relativistic ZORA
Definition: zora.F90:364