Octopus
em_resp_calc.F90
Go to the documentation of this file.
1!! Copyright (C) 2004-2012 Xavier Andrade, Eugene S. Kadantsev (ekadants@mjs1.phy.queensu.ca), David Strubbe
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
22 use batch_oct_m
23 use comm_oct_m
24 use debug_oct_m
27 use grid_oct_m
28 use global_oct_m
30 use ions_oct_m
31 use, intrinsic :: iso_fortran_env
37 use mesh_oct_m
47 use space_oct_m
54 use utils_oct_m
55 use xc_oct_m
57
58 implicit none
59
60 private
61 public :: &
67 dinhomog_b, &
68 zinhomog_b, &
87 freq2str, &
88 magn_dir, &
89 em_wfs_tag, &
90 em_rho_tag, &
95
96
97 type matrix_t
98 private
99 real(real64), allocatable :: dmatrix(:, :)
100 complex(real64), allocatable :: zmatrix(:, :)
101 end type matrix_t
102
103contains
104
105 ! ---------------------------------------------------------
106 subroutine lr_calc_current(st, space, gr, lr, lr_m)
107 type(states_elec_t), intent(inout) :: st
108 class(space_t), intent(in) :: space
109 type(grid_t), intent(in) :: gr
110 type(lr_t), intent(inout) :: lr
111 type(lr_t), optional, intent(inout) :: lr_m
112
113 integer :: idir, ist, ispin, idim, ndim, np, ip
114
115 complex(real64), allocatable :: psi(:, :), gpsi(:,:), gdl_psi(:,:), gdl_psi_m(:,:)
117 push_sub(lr_calc_current)
118
119 if (.not. allocated(lr%dl_j)) then
120 safe_allocate(lr%dl_j(1:gr%np, 1:space%dim, 1:st%d%nspin))
121 end if
122
123 assert(allocated(lr%zdl_psi))
124
125 np = gr%np
126 ndim = space%dim
127
128 safe_allocate(psi(1:gr%np_part, 1:ndim))
129 safe_allocate(gpsi(1:np, 1:ndim))
130 safe_allocate(gdl_psi(1:np, 1:ndim))
131 if (present(lr_m)) then
132 safe_allocate(gdl_psi_m(1:np, 1:ndim))
133 end if
134
135 lr%dl_j = m_zero
136
137 do ispin = 1, st%d%nspin
138 do ist = 1, st%nst
139
140 call states_elec_set_state(st, gr, ist, ispin, psi)
141
142 do idim = 1, st%d%dim
143
144 call zderivatives_grad(gr%der, lr%zdl_psi(:, idim, ist, ispin), gdl_psi)
145 call zderivatives_grad(gr%der, psi(:, idim), gpsi)
146
147 if (present(lr_m)) then
148
149 call zderivatives_grad(gr%der, lr_m%zdl_psi(:, idim, ist, ispin), gdl_psi_m)
150
151 !$omp parallel private(idir, ip)
152 do idir = 1, space%dim
153
154 !$omp do
155 do ip = 1, np
156 lr%dl_j(ip, idir, ispin) = lr%dl_j(ip, idir, ispin) + ( &
157 + conjg(psi(ip, idim))*gdl_psi(ip, idir) &
158 - psi(ip, idim)*conjg(gdl_psi_m(ip, idir)) &
159 + conjg(lr_m%zdl_psi(ip, idim, ist, ispin)) * gpsi(ip, idir) &
160 - lr%zdl_psi (ip, idim, ist, ispin) * conjg(gpsi(ip, idir)) &
161 ) / (m_two * m_zi)
162 end do
163 end do
164 !$omp end parallel
165
166 else
167
168 !$omp parallel private(idir, ip)
169 do idir = 1, space%dim
170
171 !$omp do
172 do ip = 1, np
173 lr%dl_j(ip, idir, ispin) = lr%dl_j(ip, idir, ispin) + ( &
174 + conjg(psi(ip, idim))*gdl_psi(ip, idir) &
175 - psi(ip, idim)*conjg(gdl_psi(ip, idir)) &
176 + conjg(lr%zdl_psi(ip, idim, ist, ispin)) * gpsi(ip, idir) &
177 - lr%zdl_psi(ip, idim, ist, ispin) * conjg(gpsi(ip, idir)) &
178 ) / (m_two * m_zi)
179 end do
180
181 end do
182 !$omp end parallel
183
184 end if
185
186 end do
187 end do
188 end do
189
190 safe_deallocate_a(psi)
191 safe_deallocate_a(gpsi)
192 safe_deallocate_a(gdl_psi)
193 if (present(lr_m)) then
194 safe_deallocate_a(gdl_psi_m)
195 end if
196
197 pop_sub(lr_calc_current)
198
199 end subroutine lr_calc_current
200
202! ---------------------------------------------------------
203 character(len=12) function freq2str(freq) result(str)
204 real(real64), intent(in) :: freq
205
206 push_sub(freq2str)
207
208 ! some compilers (xlf) do not put a leading zero when the number
209 ! is smaller than 1. We have to check and correct that behavior.
210
211 write(str, '(f11.4)') freq
212 str = adjustl(str)
213 if (abs(freq) < m_one) then
214 if (freq >= m_zero .and. str(1:1) /= '0') str = "0"//trim(str)
215 if (freq < m_zero .and. str(2:2) /= '0') str = "-0"//trim(str(2:))
216 end if
217 str = trim(adjustl(str))
218
219 pop_sub(freq2str)
220
221 end function freq2str
222
223
224! ---------------------------------------------------------
225 character(len=100) function em_rho_tag(freq, dir, dir2, ipert) result(str)
226 real(real64), intent(in) :: freq
227 integer, intent(in) :: dir
228 integer, optional, intent(in) :: dir2
229 integer, optional, intent(in) :: ipert
230
231 character(len=12) :: str_tmp
232
233 !this function has to be consistent with oct_search_file_lr in liboct/oct_f.c
234
235 push_sub(em_rho_tag)
236
237 str_tmp = freq2str(freq)
238 write(str, '(3a,i1)') 'rho_', trim(str_tmp), '_', dir
239 if (present(dir2)) write(str, '(2a,i1)') trim(str), "_", dir2
240 if (present(ipert)) write(str, '(3a)') trim(str), "_", index2pert(ipert)
241
242 pop_sub(em_rho_tag)
243
244 end function em_rho_tag
245
246
247! ---------------------------------------------------------
248 character(len=100) function em_wfs_tag(idir, ifactor, idir2, ipert) result(str)
249 integer, intent(in) :: idir
250 integer, intent(in) :: ifactor
251 integer, optional, intent(in) :: idir2
252 integer, optional, intent(in) :: ipert
253
254 push_sub(em_wfs_tag)
255
256 write(str, '(3a,i1)') "wfs_", index2axis(idir), "_f", ifactor
257 if (present(idir2)) write(str, '(3a)') trim(str), "_", index2axis(idir2)
258 if (present(ipert)) write(str, '(3a)') trim(str), "_", index2pert(ipert)
259
260 pop_sub(em_wfs_tag)
261
262 end function em_wfs_tag
263
264! ---------------------------------------------------------
265! Provides indices of axes forming the right-hand system
266! to the given axis (to choose components of the position
267! and velocity, r_\alpha and V_\beta, for calculation of
268! the M_\gamma component of the magnetic dipole moment
269! M_\gamma = e_{\alpha \beta \gamma} r_\alpha V_\beta /2)
270 integer pure function magn_dir(dir, ind) result(dir_out)
271 integer, intent(in) :: dir, ind
272
273 select case (dir)
274 case (1)
275 if (ind == 1) then
276 dir_out = 2
277 else
278 dir_out = 3
279 end if
280 case (2)
281 if (ind == 1) then
282 dir_out = 3
283 else
284 dir_out = 1
285 end if
286 case (3)
287 if (ind == 1) then
288 dir_out = 1
289 else
290 dir_out = 2
291 end if
292 case default
293 dir_out = 0
294 end select
295
296 end function magn_dir
297
299! ---------------------------------------------------------
300
301 character(len=2) pure function index2pert(ipert) result(ch)
302 integer, intent(in) :: ipert
303
304 select case (ipert)
305 case (1)
306 ch = 'B'
307 case (2)
308 ch = 'K2'
309 case (3)
310 ch = 'KB'
311 case (4)
312 ch = 'KE'
313 case (5)
314 ch = 'E'
315 end select
316
317 end function index2pert
318
319#include "undef.F90"
320#include "real.F90"
321#include "em_resp_calc_inc.F90"
322
323#include "undef.F90"
324#include "complex.F90"
325#include "em_resp_calc_inc.F90"
326
327end module em_resp_calc_oct_m
328
329!! Local Variables:
330!! mode: f90
331!! coding: utf-8
332!! End:
This module implements batches of mesh functions.
Definition: batch.F90:135
This module implements a calculator for the density and defines related functions.
Definition: density.F90:122
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
subroutine, public zderivatives_grad(der, ff, op_ff, ghost_update, set_bc, to_cartesian)
apply the gradient to a mesh function
subroutine, public dinhomog_kb_tot(sh, namespace, space, gr, st, hm, ions, idir, idir1, idir2, lr_k, lr_b, lr_k1, lr_k2, lr_kk1, lr_kk2, psi_out)
subroutine, public zlr_calc_magneto_optics_finite(sh, sh_mo, namespace, space, gr, st, hm, ions, nsigma, nfactor, lr_e, lr_b, chi)
subroutine, public dlr_calc_magnetization_periodic(namespace, space, mesh, st, hm, lr_k, magn)
integer pure function, public magn_dir(dir, ind)
subroutine, public dpost_orthogonalize(space, mesh, st, nfactor, nsigma, freq_factor, omega, eta, em_lr, kdotp_em_lr)
subroutine, public zlr_calc_magneto_optics_periodic(sh, sh2, namespace, space, gr, st, hm, ions, nsigma, nfactor, nfactor_ke, freq_factor, lr_e, lr_b, lr_k, lr_ke, lr_kb, frequency, zpol, zpol_kout)
subroutine, public zinhomog_k2_tot(namespace, space, gr, st, hm, ions, idir1, idir2, lr_k1, lr_k2, psi_out)
subroutine, public dlr_calc_beta(sh, namespace, space, gr, st, hm, xc, em_lr, dipole, beta, kdotp_lr, kdotp_em_lr, occ_response, dl_eig)
See (16) in X Andrade et al., J. Chem. Phys. 126, 184106 (2006) for finite systems and (10) in A Dal ...
subroutine, public dlr_calc_susceptibility(namespace, space, gr, st, hm, lr, nsigma, pert, chi_para, chi_dia)
subroutine, public lr_calc_current(st, space, gr, lr, lr_m)
subroutine, public dinhomog_ke_tot(sh, namespace, space, gr, st, hm, ions, idir, nsigma, lr_k, lr_e, lr_kk, psi_out)
subroutine, public dem_resp_calc_eigenvalues(space, mesh, latt, st, dl_eig)
subroutine, public zinhomog_b(sh, namespace, space, gr, st, hm, ions, idir1, idir2, lr_k1, lr_k2, psi_out)
subroutine, public zcalc_polarizability_periodic(space, mesh, symm, st, em_lr, kdotp_lr, nsigma, zpol, ndir, zpol_k)
alpha_ij(w) = -e sum(m occ, k) [(<u_mk(0)|-id/dk_i)|u_mkj(1)(w)> + <u_mkj(1)(-w)|(-id/dk_i|u_mk(0)>)]
subroutine, public dinhomog_b(sh, namespace, space, gr, st, hm, ions, idir1, idir2, lr_k1, lr_k2, psi_out)
character(len=2) pure function index2pert(ipert)
subroutine, public dcalc_polarizability_periodic(space, mesh, symm, st, em_lr, kdotp_lr, nsigma, zpol, ndir, zpol_k)
alpha_ij(w) = -e sum(m occ, k) [(<u_mk(0)|-id/dk_i)|u_mkj(1)(w)> + <u_mkj(1)(-w)|(-id/dk_i|u_mk(0)>)]
subroutine, public zpost_orthogonalize(space, mesh, st, nfactor, nsigma, freq_factor, omega, eta, em_lr, kdotp_em_lr)
character(len=100) function, public em_wfs_tag(idir, ifactor, idir2, ipert)
subroutine, public zlr_calc_magnetization_periodic(namespace, space, mesh, st, hm, lr_k, magn)
subroutine, public zinhomog_ke_tot(sh, namespace, space, gr, st, hm, ions, idir, nsigma, lr_k, lr_e, lr_kk, psi_out)
character(len=12) function, public freq2str(freq)
subroutine, public dlr_calc_susceptibility_periodic(namespace, space, symm, mesh, st, hm, lr_k, lr_b, lr_kk, lr_kb, magn)
subroutine, public zlr_calc_susceptibility_periodic(namespace, space, symm, mesh, st, hm, lr_k, lr_b, lr_kk, lr_kb, magn)
subroutine, public zlr_calc_susceptibility(namespace, space, gr, st, hm, lr, nsigma, pert, chi_para, chi_dia)
subroutine, public dlr_calc_magneto_optics_finite(sh, sh_mo, namespace, space, gr, st, hm, ions, nsigma, nfactor, lr_e, lr_b, chi)
character(len=100) function, public em_rho_tag(freq, dir, dir2, ipert)
subroutine, public dinhomog_k2_tot(namespace, space, gr, st, hm, ions, idir1, idir2, lr_k1, lr_k2, psi_out)
subroutine, public zlr_calc_beta(sh, namespace, space, gr, st, hm, xc, em_lr, dipole, beta, kdotp_lr, kdotp_em_lr, occ_response, dl_eig)
See (16) in X Andrade et al., J. Chem. Phys. 126, 184106 (2006) for finite systems and (10) in A Dal ...
subroutine, public zcalc_polarizability_finite(namespace, space, gr, st, hm, lr, nsigma, pert, zpol, doalldirs, ndir)
alpha_ij(w) = - sum(m occ) [<psi_m(0)|r_i|psi_mj(1)(w)> + <psi_mj(1)(-w)|r_i|psi_m(0)>] minus sign is...
subroutine, public dcalc_polarizability_finite(namespace, space, gr, st, hm, lr, nsigma, pert, zpol, doalldirs, ndir)
alpha_ij(w) = - sum(m occ) [<psi_m(0)|r_i|psi_mj(1)(w)> + <psi_mj(1)(-w)|r_i|psi_m(0)>] minus sign is...
subroutine, public dlr_calc_magneto_optics_periodic(sh, sh2, namespace, space, gr, st, hm, ions, nsigma, nfactor, nfactor_ke, freq_factor, lr_e, lr_b, lr_k, lr_ke, lr_kb, frequency, zpol, zpol_kout)
subroutine, public zinhomog_kb_tot(sh, namespace, space, gr, st, hm, ions, idir, idir1, idir2, lr_k, lr_b, lr_k1, lr_k2, lr_kk1, lr_kk2, psi_out)
subroutine, public zem_resp_calc_eigenvalues(space, mesh, latt, st, dl_eig)
real(real64), parameter, public m_two
Definition: global.F90:202
real(real64), parameter, public m_zero
Definition: global.F90:200
complex(real64), parameter, public m_zi
Definition: global.F90:214
real(real64), parameter, public m_one
Definition: global.F90:201
This module implements the underlying real-space grid.
Definition: grid.F90:119
This module defines functions over batches of mesh functions.
Definition: mesh_batch.F90:118
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
This module handles spin dimensions of the states and the k-point distribution.
This module is intended to contain simple general-purpose utility functions and procedures.
Definition: utils.F90:120
character pure function, public index2axis(idir)
Definition: utils.F90:205
Definition: xc.F90:120