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