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