Octopus
current.F90
Go to the documentation of this file.
1!! Copyright (C) 2008-2019 X. Andrade, F. Bonafe, R. Jestaedt, H. Appel
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
21module current_oct_m
22 use accel_oct_m
23 use batch_oct_m
26 use comm_oct_m
27 use debug_oct_m
31 use global_oct_m
32 use grid_oct_m
34 use, intrinsic :: iso_fortran_env
36 use lda_u_oct_m
37 use math_oct_m
40 use mesh_oct_m
44 use parser_oct_m
48 use space_oct_m
50 use types_oct_m
51 use unit_oct_m
55 use xc_oct_m
56
57 implicit none
58
59 private
60
61 type current_t
62 private
63 integer :: method
64 logical :: include_diamag
65 end type current_t
66
67
68 public :: &
69 current_t, &
75
76 integer, parameter, public :: &
77 CURRENT_GRADIENT = 1, &
80
81contains
82
83 subroutine current_init(this, namespace)
84 type(current_t), intent(out) :: this
85 type(namespace_t), intent(in) :: namespace
86
87 push_sub(current_init)
88
89 !%Variable CurrentDensity
90 !%Default gradient_corrected
91 !%Type integer
92 !%Section Hamiltonian
93 !%Description
94 !% This variable selects the method used to
95 !% calculate the current density. For the moment this variable is
96 !% for development purposes and users should not need to use
97 !% it.
98 !%Option gradient 1
99 !% The calculation of current is done using the gradient operator. (Experimental)
100 !%Option gradient_corrected 2
101 !% The calculation of current is done using the gradient operator
102 !% with additional corrections for the total current from non-local operators.
103 !%Option hamiltonian 3
104 !% The current density is obtained from the commutator of the
105 !% Hamiltonian with the position operator. (Experimental)
106 !%End
107
108 call parse_variable(namespace, 'CurrentDensity', current_gradient_corr, this%method)
109 if (.not. varinfo_valid_option('CurrentDensity', this%method)) call messages_input_error(namespace, 'CurrentDensity')
110 if (this%method /= current_gradient_corr) then
111 call messages_experimental("CurrentDensity /= gradient_corrected")
112 end if
113
114 !%Variable CalculateDiamagneticCurrent
115 !%Default no
116 !%Type logical
117 !%Section Hamiltonian
118 !%Description
119 !% This variable decides whether the current density arising from the non-uniform
120 !% vector potential, defined as:
121 !% <math> \vec{J}_{dmc}(\vec{r}, t)=-\frac{e^2}{m_e c_0} n(\vec{r}, t) \vec{A}(\vec{r},t)$ </math>
122 !% is included in the total current density.
123 !%End
124 call parse_variable(namespace, 'CalculateDiamagneticCurrent', .false., this%include_diamag)
125
126 pop_sub(current_init)
127 end subroutine current_init
128
129 ! ---------------------------------------------------------
130
131 subroutine current_batch_accumulate(st, der, ik, ib, psib, gpsib)
132 type(states_elec_t), intent(inout) :: st
133 type(derivatives_t), intent(inout) :: der
134 integer, intent(in) :: ik
135 integer, intent(in) :: ib
136 type(wfs_elec_t), intent(in) :: psib
137 class(wfs_elec_t), intent(in) :: gpsib(:)
138
139 integer :: ist, idir, ii, ip, idim, wgsize
140 complex(real64), allocatable :: psi(:, :), gpsi(:, :)
141 real(real64), allocatable :: current_tmp(:, :)
142 complex(real64) :: c_tmp
143 real(real64) :: ww
144 real(real64), allocatable :: weight(:)
145 type(accel_mem_t) :: buff_weight, buff_current
146 type(accel_kernel_t), save :: kernel
147
148 safe_allocate(psi(1:der%mesh%np_part, 1:st%d%dim))
149 safe_allocate(gpsi(1:der%mesh%np_part, 1:st%d%dim))
150
151 if (st%d%ispin == spinors .or. (psib%status() == batch_device_packed .and. der%dim /= 3)) then
152
153 do idir = 1, der%dim
155
156 ww = st%kweights(ik)*st%occ(ist, ik)
157 if (abs(ww) <= m_epsilon) cycle
158
159 do idim = 1, st%d%dim
160 ii = st%group%psib(ib, ik)%inv_index((/ist, idim/))
161 call batch_get_state(psib, ii, der%mesh%np, psi(:, idim))
162 call batch_get_state(gpsib(idir), ii, der%mesh%np, gpsi(:, idim))
163 end do
164
165 if (st%d%ispin /= spinors) then
166 !$omp parallel do
167 do ip = 1, der%mesh%np
168 st%current_kpt(ip, idir, ik) = st%current_kpt(ip, idir, ik) + ww*aimag(conjg(psi(ip, 1))*gpsi(ip, 1))
169 end do
170 !$omp end parallel do
171 else
172 !$omp parallel do private(c_tmp)
173 do ip = 1, der%mesh%np
174 st%current_para(ip, idir, 1) = st%current_para(ip, idir, 1) + ww*aimag(conjg(psi(ip, 1))*gpsi(ip, 1))
175 st%current_para(ip, idir, 2) = st%current_para(ip, idir, 2) + ww*aimag(conjg(psi(ip, 2))*gpsi(ip, 2))
176 c_tmp = -m_half*m_zi*(conjg(psi(ip, 2))*gpsi(ip, 1) - psi(ip, 1)*conjg(gpsi(ip, 2)))
177 st%current_para(ip, idir, 3) = st%current_para(ip, idir, 3) + ww*real(c_tmp, real64)
178 st%current_para(ip, idir, 4) = st%current_para(ip, idir, 4) + ww*aimag(c_tmp)
179 end do
180 !$omp end parallel do
181 end if
182
183 end do
184 end do
185
186 else if (psib%status() == batch_device_packed) then
187
188 assert(der%dim == 3)
189
190 safe_allocate(weight(1:psib%nst))
191 do ist = 1, psib%nst
192 weight(ist) = st%kweights(ik)*st%occ(psib%ist(ist), ik)
193 end do
194
195
196 call accel_create_buffer(buff_weight, accel_mem_read_only, type_float, psib%nst)
197 call accel_write_buffer(buff_weight, psib%nst, weight, async=.true.)
198
199 call accel_create_buffer(buff_current, accel_mem_write_only, type_float, der%mesh%np*3)
200
201 call accel_kernel_start_call(kernel, 'density.cl', 'current_accumulate')
202
203 call accel_set_kernel_arg(kernel, 0, psib%nst)
204 call accel_set_kernel_arg(kernel, 1, der%mesh%np)
205 call accel_set_kernel_arg(kernel, 2, buff_weight)
206 call accel_set_kernel_arg(kernel, 3, psib%ff_device)
207 call accel_set_kernel_arg(kernel, 4, log2(int(psib%pack_size(1), int32)))
208 call accel_set_kernel_arg(kernel, 5, gpsib(1)%ff_device)
209 call accel_set_kernel_arg(kernel, 6, gpsib(2)%ff_device)
210 call accel_set_kernel_arg(kernel, 7, gpsib(3)%ff_device)
211 call accel_set_kernel_arg(kernel, 8, log2(int(gpsib(1)%pack_size(1), int32)))
212 call accel_set_kernel_arg(kernel, 9, buff_current)
213
214 wgsize = accel_kernel_workgroup_size(kernel)
215
216 call accel_kernel_run(kernel, (/pad(der%mesh%np, wgsize)/), (/wgsize/))
217
218 safe_allocate(current_tmp(1:der%mesh%np, 1:der%dim))
219
220 call accel_read_buffer(buff_current, der%mesh%np*der%dim, current_tmp)
221
222 call lalg_axpy(der%mesh%np, der%dim, m_one, current_tmp, st%current_kpt(:,:,ik))
223
224 safe_deallocate_a(current_tmp)
225
226 call accel_release_buffer(buff_weight)
227 call accel_release_buffer(buff_current)
228
229 safe_deallocate_a(weight)
230
231 else
232
233 assert(psib%is_packed() .eqv. gpsib(1)%is_packed())
234
235 !$omp parallel private(ip, ist, ww, idir)
236 do ii = 1, psib%nst
237 ist = states_elec_block_min(st, ib) + ii - 1
238 ww = st%kweights(ik)*st%occ(ist, ik)
239 if (abs(ww) <= m_epsilon) cycle
240
241 if (psib%is_packed()) then
242 do idir = 1, der%dim
243 !$omp do
244 do ip = 1, der%mesh%np
245 st%current_kpt(ip, idir, ik) = st%current_kpt(ip, idir, ik) &
246 + ww*aimag(conjg(psib%zff_pack(ii, ip))*gpsib(idir)%zff_pack(ii, ip))
247 end do
248 !$omp end do nowait
249 end do
250 else
251 do idir = 1, der%dim
252 !$omp do
253 do ip = 1, der%mesh%np
254 st%current_kpt(ip, idir, ik) = st%current_kpt(ip, idir, ik) &
255 + ww*aimag(conjg(psib%zff(ip, 1, ii))*gpsib(idir)%zff(ip, 1, ii))
256 end do
257 !$omp end do nowait
258 end do
259 end if
260 end do
261 !$omp end parallel
262
263 end if
264
265 safe_deallocate_a(psi)
266 safe_deallocate_a(gpsi)
267
268 end subroutine current_batch_accumulate
269
270
271 ! ---------------------------------------------------------
273 subroutine current_calculate(this, namespace, gr, hm, space, st)
274 type(current_t), intent(in) :: this
275 type(namespace_t), intent(in) :: namespace
276 type(grid_t), intent(inout) :: gr
277 type(hamiltonian_elec_t), intent(in) :: hm
278 class(space_t), intent(in) :: space
279 type(states_elec_t), intent(inout) :: st
280
281
282 call profiling_in("CURRENT_TOTAL")
283 push_sub(current_calculate)
284
285 call current_calculate_para(this, namespace, gr, hm, space, st)
286 st%current = st%current_para
287
288 if (this%include_diamag) then
289 call current_calculate_dia_non_unif_vec_pot(gr%der, hm, st)
290 st%current = st%current + st%current_dia
291 end if
292
293 call profiling_out("CURRENT_TOTAL")
294 pop_sub(current_calculate)
295
296 end subroutine current_calculate
297
298 ! ---------------------------------------------------------
301 subroutine current_calculate_dia_non_unif_vec_pot(der, hm, st)
302 type(derivatives_t), intent(inout) :: der
303 type(hamiltonian_elec_t), intent(in) :: hm
304 type(states_elec_t), intent(inout) :: st
305
306 integer :: ispin, idir, ip
307
308 call profiling_in("CURRENT_DIA_NON_UNIF_A")
310
311 st%current_dia = m_zero
312
313 if(allocated(hm%hm_base%vector_potential)) then
314 do ispin = 1, st%d%nspin
315 do idir = 1, der%dim
316 !$omp parallel do
317 do ip = 1, der%mesh%np
318 ! the vector potential is assumed to be devided by c_0 already
319 st%current_dia(ip, idir, ispin) = st%current_dia(ip, idir, ispin) + &
320 st%rho(ip, ispin)*hm%hm_base%vector_potential(idir, ip)
321 end do
322 !$omp end parallel do
323 end do
324 end do
325 end if
326
327 call profiling_out("CURRENT_DIA_NON_UNIF_A")
329
331
332 ! ---------------------------------------------------------
336 subroutine current_calculate_mag(der, st)
337 type(derivatives_t), intent(inout) :: der
338 type(states_elec_t), intent(inout) :: st
339
340 integer :: idir, ip
341 real(real64), allocatable :: magnetization_density(:, :), curl_mag(:, :)
342
343 call profiling_in("CURRENT_MAG")
344 push_sub(current_calculate_mag)
345
346 st%current_mag = m_zero
347
348 if (st%d%ispin /= unpolarized) then
349 safe_allocate(magnetization_density(1:der%mesh%np_part, 1:der%dim))
350 safe_allocate(curl_mag(1:der%mesh%np_part, 1:der%dim))
351
352 call magnetic_density(der%mesh, st%d, st%rho, magnetization_density)
353 call dderivatives_curl(der, magnetization_density, curl_mag)
354
355 do idir = 1, der%dim
356 !$omp parallel do
357 do ip = 1, der%mesh%np
358 st%current_mag(ip, idir, 1) = st%current_mag(ip, idir, 1) + m_half * curl_mag(ip, idir)
359 end do
360 !$omp end parallel do
361 end do
362
363 safe_deallocate_a(magnetization_density)
364 safe_deallocate_a(curl_mag)
365 end if
367 call profiling_out("CURRENT_MAG")
368 pop_sub(current_calculate_mag)
369
370 end subroutine current_calculate_mag
371
372 ! ---------------------------------------------------------
375 subroutine current_calculate_para(this, namespace, gr, hm, space, st)
376 type(current_t), intent(in) :: this
377 type(namespace_t), intent(in) :: namespace
378 type(grid_t), intent(inout) :: gr
379 type(hamiltonian_elec_t), intent(in) :: hm
380 class(space_t), intent(in) :: space
381 type(states_elec_t), intent(inout) :: st
382
383 integer :: ik, ist, idir, idim, ip, ib, ii, ispin
384 complex(real64), allocatable :: gpsi(:, :, :), psi(:, :), hpsi(:, :), rhpsi(:, :), rpsi(:, :), hrpsi(:, :)
385 type(wfs_elec_t) :: hpsib, rhpsib, rpsib, hrpsib, epsib
386 class(wfs_elec_t), allocatable :: commpsib(:)
387 real(real64) :: ww
388 complex(real64) :: c_tmp
389
390 call profiling_in("CURRENT_PARA")
391 push_sub(current_calculate_para)
392
393 ! spin not implemented or tested
394 assert(all(ubound(st%current_para) == (/gr%np_part, gr%der%dim, st%d%nspin/)))
395 assert(all(ubound(st%current_kpt) == (/gr%np, gr%der%dim, st%d%kpt%end/)))
396 assert(all(lbound(st%current_kpt) == (/1, 1, st%d%kpt%start/)))
397
398 safe_allocate(psi(1:gr%np_part, 1:st%d%dim))
399 safe_allocate(gpsi(1:gr%np, 1:gr%der%dim, 1:st%d%dim))
400 safe_allocate(hpsi(1:gr%np_part, 1:st%d%dim))
401 safe_allocate(rhpsi(1:gr%np_part, 1:st%d%dim))
402 safe_allocate(rpsi(1:gr%np_part, 1:st%d%dim))
403 safe_allocate(hrpsi(1:gr%np_part, 1:st%d%dim))
404 safe_allocate_type_array(wfs_elec_t, commpsib, (1:gr%der%dim))
405
406 !$omp parallel private(idir, ip, ispin)
407 do ik = st%d%kpt%start, st%d%kpt%end
408 do idir = 1, gr%der%dim
409 !$omp do
410 do ip = 1, gr%np
411 st%current_kpt(ip, idir, ik) = m_zero
412 end do
413 !$omp end do nowait
414 end do
415 end do
416 do ispin = 1, st%d%nspin
417 do idir = 1, gr%der%dim
418 !$omp do
419 do ip = 1, gr%np
420 st%current_para(ip, idir, ispin) = m_zero
421 end do
422 !$omp end do nowait
423 end do
424 end do
425 !$omp end parallel
426
427 select case (this%method)
428
430
431 do ik = st%d%kpt%start, st%d%kpt%end
432 ispin = st%d%get_spin_index(ik)
433 do ib = st%group%block_start, st%group%block_end
434
435 call st%group%psib(ib, ik)%do_pack(copy = .true.)
436
437 call st%group%psib(ib, ik)%copy_to(hpsib)
438 call st%group%psib(ib, ik)%copy_to(rhpsib)
439 call st%group%psib(ib, ik)%copy_to(rpsib)
440 call st%group%psib(ib, ik)%copy_to(hrpsib)
441
442 call boundaries_set(gr%der%boundaries, gr, st%group%psib(ib, ik))
443 call zhamiltonian_elec_apply_batch(hm, namespace, gr, st%group%psib(ib, ik), hpsib, set_bc = .false.)
444
445 do idir = 1, gr%der%dim
446
447 call batch_mul(gr%np, gr%x(:, idir), hpsib, rhpsib)
448 call batch_mul(gr%np_part, gr%x(:, idir), st%group%psib(ib, ik), rpsib)
449
450 call zhamiltonian_elec_apply_batch(hm, namespace, gr, rpsib, hrpsib, set_bc = .false.)
451
452 do ist = states_elec_block_min(st, ib), states_elec_block_max(st, ib)
453 ww = st%kweights(ik)*st%occ(ist, ik)
454 if (ww <= m_epsilon) cycle
455
456 do idim = 1, st%d%dim
457 ii = st%group%psib(ib, ik)%inv_index((/ist, idim/))
458 call batch_get_state(st%group%psib(ib, ik), ii, gr%np, psi(:, idim))
459 call batch_get_state(hrpsib, ii, gr%np, hrpsi(:, idim))
460 call batch_get_state(rhpsib, ii, gr%np, rhpsi(:, idim))
461 end do
462
463 if (st%d%ispin /= spinors) then
464 !$omp parallel do
465 do ip = 1, gr%np
466 st%current_kpt(ip, idir, ik) = st%current_kpt(ip, idir, ik) &
467 - ww*aimag(conjg(psi(ip, 1))*hrpsi(ip, 1) - conjg(psi(ip, 1))*rhpsi(ip, 1))
468 end do
469 !$omp end parallel do
470 else
471 !$omp parallel do private(c_tmp)
472 do ip = 1, gr%np
473 st%current_para(ip, idir, 1) = st%current_para(ip, idir, 1) + &
474 ww*aimag(conjg(psi(ip, 1))*hrpsi(ip, 1) - conjg(psi(ip, 1))*rhpsi(ip, 1))
475 st%current_para(ip, idir, 2) = st%current_para(ip, idir, 2) + &
476 ww*aimag(conjg(psi(ip, 2))*hrpsi(ip, 2) - conjg(psi(ip, 2))*rhpsi(ip, 2))
477 c_tmp = -m_half*m_zi*(conjg(psi(ip, 2))*hrpsi(ip, 1) - conjg(psi(ip, 2))*rhpsi(ip, 1) &
478 -psi(ip, 1)*conjg(hrpsi(ip, 2)) - psi(ip, 1)*conjg(rhpsi(ip, 2)))
479 st%current_para(ip, idir, 3) = st%current_para(ip, idir, 3) + ww*real(c_tmp, real64)
480 st%current_para(ip, idir, 4) = st%current_para(ip, idir, 4) + ww*aimag(c_tmp)
481 end do
482 !$omp end parallel do
483 end if
484
485 end do
486
487 end do
488
489 call st%group%psib(ib, ik)%do_unpack(copy = .false.)
490
491 call hpsib%end()
492 call rhpsib%end()
493 call rpsib%end()
494 call hrpsib%end()
495
496 end do
497 end do
498
499 case (current_gradient, current_gradient_corr)
500
501 if (this%method == current_gradient_corr .and. .not. family_is_mgga_with_exc(hm%xc) &
502 .and. hm%theory_level /= hartree_fock &
503 .and. hm%theory_level /= generalized_kohn_sham_dft &
504 .and. hm%theory_level /= rdmft &
505 .and. hm%vnl%apply_projector_matrices) then
506
507 ! we can use the packed version
508
509 do ik = st%d%kpt%start, st%d%kpt%end
510 ispin = st%d%get_spin_index(ik)
511 do ib = st%group%block_start, st%group%block_end
512
513 ! copy st%group%psib(ib, ik) to epsib and set the phase
514 call hamiltonian_elec_copy_and_set_phase(hm, gr, st%d%kpt, st%group%psib(ib, ik), epsib)
515
516 ! this now takes non-orthogonal axis into account
517 call zderivatives_batch_grad(gr%der, epsib, commpsib, set_bc=.false.)
518
519 call hm%vnl%zposition_commutator(gr, st%d, gr%der%boundaries%spiral, epsib, commpsib, async=.true.)
520
521 call zlda_u_commute_r(hm%lda_u, gr, space, st%d, namespace, epsib, commpsib)
522
523 call current_batch_accumulate(st, gr%der, ik, ib, epsib, commpsib)
524
525 do idir = 1, gr%der%dim
526 call commpsib(idir)%end()
527 end do
528
529 call epsib%end()
530
531 call accel_finish()
532 end do
533 end do
534
535 else
536
537 ! use the slow non-packed version
538
539 do ik = st%d%kpt%start, st%d%kpt%end
540 ispin = st%d%get_spin_index(ik)
541 do ist = st%st_start, st%st_end
542
543 ww = st%kweights(ik)*st%occ(ist, ik)
544 if (abs(ww) <= m_epsilon) cycle
545
546 call states_elec_get_state(st, gr, ist, ik, psi)
547
548 if (hm%phase%is_allocated()) then
549 call hm%phase%apply_to_single(psi, gr%np, st%d%dim, ik, .false.)
550 ! apply phase correction while setting boundary -> memory needs to be
551 ! accessed only once
552 do idim = 1, st%d%dim
553 call boundaries_set(gr%der%boundaries, gr, psi(:, idim), phase_correction = hm%phase%phase_corr(:, ik), &
554 buff_phase_corr = hm%phase%buff_phase_corr, offset=int((ik-st%d%kpt%start)*(gr%np_part-gr%np)))
555 end do
556 else
557 do idim = 1, st%d%dim
558 call boundaries_set(gr%der%boundaries, gr, psi(:, idim))
559 end do
560 end if
561
562 do idim = 1, st%d%dim
563 call zderivatives_grad(gr%der, psi(:, idim), gpsi(:, :, idim), set_bc = .false.)
564 end do
565
566 if (this%method == current_gradient_corr) then
567 !A nonlocal contribution from the MGGA potential must be included
568 !This must be done first, as this is like a position-dependent mass
569 if (family_is_mgga_with_exc(hm%xc)) then
570 do idim = 1, st%d%dim
571 do idir = 1, gr%der%dim
572 !$omp parallel do
573 do ip = 1, gr%np
574 gpsi(ip, idir, idim) = (m_one+m_two*hm%vtau(ip,ispin))*gpsi(ip, idir, idim)
575 end do
576 !$omp end parallel do
577 end do
578 end do
579 end if
580
581 !A nonlocal contribution from the pseudopotential must be included
582 call zprojector_commute_r_allatoms_alldir(hm%ep%proj, hm%ions, gr, st%d%dim, &
583 gr%der%boundaries, ik, psi, gpsi)
584 !A nonlocal contribution from the scissor must be included
585 if (hm%scissor%apply) then
586 call scissor_commute_r(hm%scissor, gr, ik, psi, gpsi)
587 end if
588
589 call zlda_u_commute_r_single(hm%lda_u, gr, space, st%d, namespace, ist, ik, &
590 psi, gpsi, hm%phase%is_allocated())
591
592 call zexchange_operator_commute_r(hm%exxop, namespace, gr, st%d, ik, psi, gpsi)
593
594 end if
595
596 if (st%d%ispin /= spinors) then
597 do idir = 1, gr%der%dim
598 !$omp parallel do
599 do ip = 1, gr%np
600 st%current_kpt(ip, idir, ik) = st%current_kpt(ip, idir, ik) + &
601 ww*aimag(conjg(psi(ip, 1))*gpsi(ip, idir, 1))
602 end do
603 !$omp end parallel do
604 end do
605 else
606 do idir = 1, gr%der%dim
607 !$omp parallel do private(c_tmp)
608 do ip = 1, gr%np
609 st%current_para(ip, idir, 1) = st%current_para(ip, idir, 1) + &
610 ww*aimag(conjg(psi(ip, 1))*gpsi(ip, idir, 1))
611 st%current_para(ip, idir, 2) = st%current_para(ip, idir, 2) + &
612 ww*aimag(conjg(psi(ip, 2))*gpsi(ip, idir, 2))
613 c_tmp = -m_half*m_zi*(conjg(psi(ip, 2))*gpsi(ip, idir, 1) - psi(ip, 1)*conjg(gpsi(ip, idir, 2)))
614 st%current_para(ip, idir, 3) = st%current_para(ip, idir, 3) + ww*real(c_tmp, real64)
615 st%current_para(ip, idir, 4) = st%current_para(ip, idir, 4) + ww*aimag(c_tmp)
616 end do
617 !$omp end parallel do
618 end do
619 end if
620
621 end do
622 end do
623
624 end if
625
626 case default
627
628 assert(.false.)
629
630 end select
631
632 if (st%d%ispin /= spinors) then
633 !We sum the current over k-points
634 do ik = st%d%kpt%start, st%d%kpt%end
635 ispin = st%d%get_spin_index(ik)
636 call lalg_axpy(gr%np, gr%der%dim, m_one, st%current_kpt(:, :, ik), st%current_para(:, :, ispin))
637 end do
638 end if
639
640 if (st%parallel_in_states .or. st%d%kpt%parallel) then
641 call comm_allreduce(st%st_kpt_mpi_grp, st%current_para, dim = (/gr%np, gr%der%dim, st%d%nspin/))
642 end if
643
644 if (st%symmetrize_density) then
645 do ispin = 1, st%d%nspin
646 call dgrid_symmetrize_vector_field(gr, st%current_para(:, :, ispin), suppress_warning = .true.)
647 end do
648 end if
649
650 safe_deallocate_a(gpsi)
651 safe_deallocate_a(psi)
652 safe_deallocate_a(hpsi)
653 safe_deallocate_a(rhpsi)
654 safe_deallocate_a(rpsi)
655 safe_deallocate_a(hrpsi)
656 safe_deallocate_a(commpsib)
657
658 call profiling_out("CURRENT_PARA")
660
661 end subroutine current_calculate_para
662
663
664 ! ---------------------------------------------------------
665 ! Calculate the current matrix element between two states
666 ! I_{ij}(t) = <i| J(t) |j>
667 ! This is used only in the floquet_observables utility and
668 ! is highly experimental
669
670 subroutine current_calculate_mel(der, hm, psi_i, psi_j, ik, cmel)
671 type(derivatives_t), intent(inout) :: der
672 type(hamiltonian_elec_t), intent(in) :: hm
673 complex(real64), intent(in) :: psi_i(:,:)
674 complex(real64), intent(in) :: psi_j(:,:)
675 integer, intent(in) :: ik
676 complex(real64), intent(out) :: cmel(:,:) ! the current vector cmel(1:der%dim, 1:st%d%nspin)
677
678 integer :: idir, idim, ip, ispin
679 complex(real64), allocatable :: gpsi_j(:, :, :), ppsi_j(:,:), gpsi_i(:, :, :), ppsi_i(:,:)
680
681 push_sub(current_calculate_mel)
682
683 safe_allocate(gpsi_i(1:der%mesh%np, 1:der%dim, 1:hm%d%dim))
684 safe_allocate(ppsi_i(1:der%mesh%np_part,1:hm%d%dim))
685 safe_allocate(gpsi_j(1:der%mesh%np, 1:der%dim, 1:hm%d%dim))
686 safe_allocate(ppsi_j(1:der%mesh%np_part,1:hm%d%dim))
687
688 cmel = m_z0
689
690 ispin = hm%d%get_spin_index(ik)
691 ppsi_i(:,:) = m_z0
692 ppsi_i(1:der%mesh%np,:) = psi_i(1:der%mesh%np,:)
693 ppsi_j(:,:) = m_z0
694 ppsi_j(1:der%mesh%np,:) = psi_j(1:der%mesh%np,:)
695
696
697 do idim = 1, hm%d%dim
698 call boundaries_set(der%boundaries, der%mesh, ppsi_i(:, idim))
699 call boundaries_set(der%boundaries, der%mesh, ppsi_j(:, idim))
700 end do
701
702 if (hm%phase%is_allocated()) then
703 ! Apply the phase that contains both the k-point and vector-potential terms.
704 call hm%phase%apply_to_single(ppsi_i, der%mesh%np_part, hm%d%dim, ik, .false.)
705 call hm%phase%apply_to_single(ppsi_j, der%mesh%np_part, hm%d%dim, ik, .false.)
706 end if
707
708 do idim = 1, hm%d%dim
709 call zderivatives_grad(der, ppsi_i(:, idim), gpsi_i(:, :, idim), set_bc = .false.)
710 call zderivatives_grad(der, ppsi_j(:, idim), gpsi_j(:, :, idim), set_bc = .false.)
711 end do
712
713 !A nonlocal contribution from the MGGA potential must be included
714 !This must be done first, as this is like a position-dependent mass
715 if (family_is_mgga_with_exc(hm%xc)) then
716 do idim = 1, hm%d%dim
717 do idir = 1, der%dim
718 !$omp parallel do
719 do ip = 1, der%mesh%np
720 gpsi_i(ip, idir, idim) = (m_one+m_two*hm%vtau(ip,ispin))*gpsi_i(ip, idir, idim)
721 gpsi_j(ip, idir, idim) = (m_one+m_two*hm%vtau(ip,ispin))*gpsi_j(ip, idir, idim)
722 end do
723 !$omp end parallel do
724 end do
725 end do
726
727 !A nonlocal contribution from the pseudopotential must be included
728 call zprojector_commute_r_allatoms_alldir(hm%ep%proj, hm%ions, der%mesh, hm%d%dim, &
729 der%boundaries, ik, ppsi_i, gpsi_i)
730 call zprojector_commute_r_allatoms_alldir(hm%ep%proj, hm%ions, der%mesh, hm%d%dim, &
731 der%boundaries, ik, ppsi_j, gpsi_j)
732 !A nonlocal contribution from the scissor must be included
733 if (hm%scissor%apply) then
734 call scissor_commute_r(hm%scissor, der%mesh, ik, ppsi_i, gpsi_i)
735 call scissor_commute_r(hm%scissor, der%mesh, ik, ppsi_j, gpsi_j)
736 end if
737
738 end if
739
740
741 do idir = 1, der%dim
742
743 do idim = 1, hm%d%dim
744
745 cmel(idir,ispin) = m_zi * zmf_dotp(der%mesh, psi_i(:, idim), gpsi_j(:, idir,idim), reduce = .false.)
746 cmel(idir,ispin) = cmel(idir,ispin) - m_zi * zmf_dotp(der%mesh, gpsi_i(:, idir, idim), psi_j(:, idim), reduce = .false.)
747
748 end do
749 end do
750
751 if (der%mesh%parallel_in_domains) call der%mesh%allreduce(cmel)
752
753
754
755 safe_deallocate_a(gpsi_i)
756 safe_deallocate_a(ppsi_i)
757 safe_deallocate_a(gpsi_j)
758 safe_deallocate_a(ppsi_j)
759
760 pop_sub(current_calculate_mel)
761
762 end subroutine current_calculate_mel
764 ! ---------------------------------------------------------
765 subroutine current_heat_calculate(space, der, hm, st, current)
766 class(space_t), intent(in) :: space
767 type(derivatives_t), intent(in) :: der
768 type(hamiltonian_elec_t), intent(in) :: hm
769 type(states_elec_t), intent(in) :: st
770 real(real64), intent(out) :: current(:, :, :)
771
772 integer :: ik, ist, idir, idim, ip, ispin, ndim
773 complex(real64), allocatable :: gpsi(:, :, :), psi(:, :), g2psi(:, :, :, :)
774 complex(real64) :: tmp
775
776 push_sub(current_heat_calculate)
777
778 assert(space%is_periodic())
779 assert(st%d%dim == 1)
780
781 ndim = space%dim
782
783 safe_allocate(psi(1:der%mesh%np_part, 1:st%d%dim))
784 safe_allocate(gpsi(1:der%mesh%np_part, 1:ndim, 1:st%d%dim))
785 safe_allocate(g2psi(1:der%mesh%np, 1:ndim, 1:ndim, 1:st%d%dim))
786
787 do ip = 1, der%mesh%np
788 current(ip, 1:ndim, 1:st%d%nspin) = st%current(ip, 1:ndim, 1:st%d%nspin)*hm%ep%vpsl(ip)
789 end do
790
791
792 do ik = st%d%kpt%start, st%d%kpt%end
793 ispin = st%d%get_spin_index(ik)
794 do ist = st%st_start, st%st_end
795
796 if (abs(st%kweights(ik)*st%occ(ist, ik)) <= m_epsilon) cycle
797
798 call states_elec_get_state(st, der%mesh, ist, ik, psi)
799 do idim = 1, st%d%dim
800 call boundaries_set(der%boundaries, der%mesh, psi(:, idim))
801 end do
802
803 if (hm%phase%is_allocated()) then
804 call hm%phase%apply_to_single(psi, der%mesh%np_part, st%d%dim, ik, conjugate = .false.)
805 end if
806
807 do idim = 1, st%d%dim
808 call zderivatives_grad(der, psi(:, idim), gpsi(:, :, idim), set_bc = .false.)
809 end do
810 do idir = 1, ndim
811 if (hm%phase%is_allocated()) then
812 call hm%phase%apply_to_single(gpsi(:, idir, :), der%mesh%np, st%d%dim, ik, conjugate = .true.)
813 end if
814
815 do idim = 1, st%d%dim
816 call boundaries_set(der%boundaries, der%mesh, gpsi(:,idir, idim))
817 end do
818
819 if (hm%phase%is_allocated()) then
820 call hm%phase%apply_to_single(gpsi(:, idir, :), der%mesh%np_part, st%d%dim, ik, conjugate = .false.)
821 end if
822
823 do idim = 1, st%d%dim
824 call zderivatives_grad(der, gpsi(:, idir, idim), g2psi(:, :, idir, idim), set_bc = .false.)
825 end do
826 end do
827 idim = 1
828 do ip = 1, der%mesh%np
829 do idir = 1, ndim
830 !tmp = sum(conjg(g2psi(ip, idir, 1:ndim, idim))*gpsi(ip, idir, idim)) - sum(conjg(gpsi(ip, 1:ndim, idim))*g2psi(ip, idir, 1:ndim, idim))
831 tmp = sum(conjg(g2psi(ip, 1:ndim, idir, idim))*gpsi(ip, 1:ndim, idim)) - &
832 sum(conjg(gpsi(ip, 1:ndim, idim))*g2psi(ip, 1:ndim, idir, idim))
833 tmp = tmp - conjg(gpsi(ip, idir, idim))*sum(g2psi(ip, 1:ndim, 1:ndim, idim)) + &
834 sum(conjg(g2psi(ip, 1:ndim, 1:ndim, idim)))*gpsi(ip, idir, idim)
835 current(ip, idir, ispin) = current(ip, idir, ispin) + st%kweights(ik)*st%occ(ist, ik)*aimag(tmp)/8.0_real64
836 end do
837 end do
838 end do
839 end do
840
841
843
844 end subroutine current_heat_calculate
845
846end module current_oct_m
847
848!! Local Variables:
849!! mode: f90
850!! coding: utf-8
851!! End:
constant times a vector plus a vector
Definition: lalg_basic.F90:170
subroutine, public accel_kernel_start_call(this, file_name, kernel_name, flags)
Definition: accel.F90:2144
subroutine, public accel_finish()
Definition: accel.F90:1296
subroutine, public accel_release_buffer(this)
Definition: accel.F90:1246
integer, parameter, public accel_mem_write_only
Definition: accel.F90:183
integer function, public accel_kernel_workgroup_size(kernel)
Definition: accel.F90:1478
integer, parameter, public accel_mem_read_only
Definition: accel.F90:183
This module implements batches of mesh functions.
Definition: batch.F90:133
integer, parameter, public batch_device_packed
functions are stored in device memory in packed order
Definition: batch.F90:276
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:116
Module implementing boundary conditions in Octopus.
Definition: boundaries.F90:122
subroutine current_batch_accumulate(st, der, ik, ib, psib, gpsib)
Definition: current.F90:225
subroutine current_calculate_dia_non_unif_vec_pot(der, hm, st)
Compute diamagnetic current density from non-uniform vector potential (the part coming from the unifo...
Definition: current.F90:395
subroutine, public current_calculate_mag(der, st)
Compute magnetization current Note: due to the the numerical curl, the magnetization current could de...
Definition: current.F90:430
integer, parameter, public current_hamiltonian
Definition: current.F90:169
integer, parameter, public current_gradient_corr
Definition: current.F90:169
subroutine, public current_heat_calculate(space, der, hm, st, current)
Definition: current.F90:859
subroutine current_calculate_para(this, namespace, gr, hm, space, st)
Compute paramagnetic current density (including full diamagnetic term if method = Hamiltonian us used...
Definition: current.F90:469
subroutine, public current_calculate_mel(der, hm, psi_i, psi_j, ik, cmel)
Definition: current.F90:764
subroutine, public current_calculate(this, namespace, gr, hm, space, st)
Compute total electronic current density.
Definition: current.F90:367
subroutine, public current_init(this, namespace)
Definition: current.F90:177
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
subroutine, public dderivatives_curl(der, ff, op_ff, ghost_update, set_bc)
apply the curl operator to a vector of mesh functions
subroutine, public zderivatives_batch_grad(der, ffb, opffb, ghost_update, set_bc, to_cartesian, metric, factor)
apply the gradient to a batch of mesh functions
subroutine, public zderivatives_grad(der, ff, op_ff, ghost_update, set_bc, to_cartesian)
apply the gradient to a mesh function
integer, parameter, public unpolarized
Parameters...
integer, parameter, public spinors
subroutine, public zexchange_operator_commute_r(this, namespace, mesh, st_d, ik, psi, gpsi)
real(real64), parameter, public m_two
Definition: global.F90:189
real(real64), parameter, public m_zero
Definition: global.F90:187
complex(real64), parameter, public m_z0
Definition: global.F90:197
complex(real64), parameter, public m_zi
Definition: global.F90:201
real(real64), parameter, public m_epsilon
Definition: global.F90:203
real(real64), parameter, public m_half
Definition: global.F90:193
real(real64), parameter, public m_one
Definition: global.F90:188
This module implements the underlying real-space grid.
Definition: grid.F90:117
subroutine, public dgrid_symmetrize_vector_field(gr, field, suppress_warning)
Definition: grid.F90:687
integer, parameter, public generalized_kohn_sham_dft
integer, parameter, public rdmft
subroutine, public zhamiltonian_elec_apply_batch(hm, namespace, mesh, psib, hpsib, terms, set_bc)
subroutine, public hamiltonian_elec_copy_and_set_phase(hm, gr, kpt, psib, psib_with_phase)
Copy a batch to another batch and apply the Bloch phase to it.
integer, parameter, public hartree_fock
subroutine, public zlda_u_commute_r(this, mesh, space, d, namespace, psib, gpsib)
This routine computes [r,V_lda+u] .
Definition: lda_u.F90:5026
subroutine, public zlda_u_commute_r_single(this, mesh, space, d, namespace, ist, ik, psi, gpsi, has_phase)
Definition: lda_u.F90:4975
subroutine, public magnetic_density(mesh, std, rho, md)
Definition: magnetic.F90:156
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:115
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:723
subroutine, public messages_experimental(name, namespace)
Definition: messages.F90:1097
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:623
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:552
subroutine, public zprojector_commute_r_allatoms_alldir(pj, ions, mesh, dim, bnd, ik, psi, cpsi)
This function calculates |cpsi> += [x, V_nl] |psi>
Definition: projector.F90:1762
integer pure function, public states_elec_block_max(st, ib)
return index of last state in block ib
integer pure function, public states_elec_block_min(st, ib)
return index of first state in block ib
type(type_t), public type_float
Definition: types.F90:133
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:132
This module defines the unit system, used for input and output.
Definition: xc.F90:114
logical pure function, public family_is_mgga_with_exc(xcs)
Is the xc function part of the mGGA family with an energy functional.
Definition: xc.F90:592
class representing derivatives
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.
batches of electronic states
Definition: wfs_elec.F90:138
int true(void)