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 elf_oct_m
28 use grid_oct_m
29 use global_oct_m
31 use ions_oct_m
32 use, intrinsic :: iso_fortran_env
38 use mesh_oct_m
48 use space_oct_m
55 use utils_oct_m
56 use xc_oct_m
57
58 implicit none
59
60 private
61 public :: &
69 dinhomog_b, &
70 zinhomog_b, &
89 freq2str, &
90 magn_dir, &
91 em_wfs_tag, &
92 em_rho_tag, &
97
98
99 type matrix_t
100 private
101 real(real64), allocatable :: dmatrix(:, :)
102 complex(real64), allocatable :: zmatrix(:, :)
103 end type matrix_t
104
105contains
106
107 ! ---------------------------------------------------------
108 subroutine lr_calc_current(st, space, gr, lr, lr_m)
109 type(states_elec_t), intent(inout) :: st
110 class(space_t), intent(in) :: space
111 type(grid_t), intent(in) :: gr
112 type(lr_t), intent(inout) :: lr
113 type(lr_t), optional, intent(inout) :: lr_m
115 integer :: idir, ist, ispin, idim, ndim, np
116
117 complex(real64), allocatable :: psi(:, :), gpsi(:,:), gdl_psi(:,:), gdl_psi_m(:,:)
118
119 push_sub(lr_calc_current)
120
121 if (.not. allocated(lr%dl_j)) then
122 safe_allocate(lr%dl_j(1:gr%np, 1:space%dim, 1:st%d%nspin))
123 end if
124
125 assert(allocated(lr%zdl_psi))
126
127 np = gr%np
128 ndim = space%dim
129
130 safe_allocate(psi(1:gr%np_part, 1:ndim))
131 safe_allocate(gpsi(1:np, 1:ndim))
132 safe_allocate(gdl_psi(1:np, 1:ndim))
133 if (present(lr_m)) then
134 safe_allocate(gdl_psi_m(1:np, 1:ndim))
135 end if
136
137 lr%dl_j = m_zero
138
139 do ispin = 1, st%d%nspin
140 do ist = 1, st%nst
141
142 call states_elec_set_state(st, gr, ist, ispin, psi)
143
144 do idim = 1, st%d%dim
145
146 call zderivatives_grad(gr%der, lr%zdl_psi(:, idim, ist, ispin), gdl_psi)
147 call zderivatives_grad(gr%der, psi(:, idim), gpsi)
148
149 if (present(lr_m)) then
150
151 call zderivatives_grad(gr%der, lr_m%zdl_psi(:, idim, ist, ispin), gdl_psi_m)
152
153 do idir = 1, space%dim
154
155 lr%dl_j(1:np, idir, ispin) = lr%dl_j(1:np, idir, ispin) + ( &
156 + conjg(psi(1:np, idim))*gdl_psi(1:np, idir) &
157 - psi(1:np, idim)*conjg(gdl_psi_m(1:np, idir)) &
158 + conjg(lr_m%zdl_psi(1:np, idim, ist, ispin)) * gpsi(1:np, idir) &
159 - lr%zdl_psi (1:np, idim, ist, ispin) * conjg(gpsi(1:np, idir)) &
160 ) / (m_two * m_zi)
161 end do
162
163 else
164
165 do idir = 1, space%dim
166
167 lr%dl_j(1:np, idir, ispin) = lr%dl_j(1:np, idir, ispin) + ( &
168 + conjg(psi(1:np, idim))*gdl_psi(1:np, idir) &
169 - psi(1:np, idim)*conjg(gdl_psi(1:np, idir)) &
170 + conjg(lr%zdl_psi(1:np, idim, ist, ispin)) * gpsi(1:np, idir) &
171 - lr%zdl_psi(1:np, idim, ist, ispin) * conjg(gpsi(1:np, idir)) &
172 ) / (m_two * m_zi)
173
174 end do
175
176 end if
177
178 end do
179 end do
180 end do
181
182 safe_deallocate_a(psi)
183 safe_deallocate_a(gpsi)
184 safe_deallocate_a(gdl_psi)
185 if (present(lr_m)) then
186 safe_deallocate_a(gdl_psi_m)
187 end if
188
189 pop_sub(lr_calc_current)
190
191 end subroutine lr_calc_current
193
194! ---------------------------------------------------------
195 character(len=12) function freq2str(freq) result(str)
196 real(real64), intent(in) :: freq
197
198 push_sub(freq2str)
199
200 ! some compilers (xlf) do not put a leading zero when the number
201 ! is smaller than 1. We have to check and correct that behavior.
202
203 write(str, '(f11.4)') freq
204 str = adjustl(str)
205 if (abs(freq) < m_one) then
206 if (freq >= m_zero .and. str(1:1) /= '0') str = "0"//trim(str)
207 if (freq < m_zero .and. str(2:2) /= '0') str = "-0"//trim(str(2:))
208 end if
209 str = trim(adjustl(str))
210
211 pop_sub(freq2str)
212
213 end function freq2str
214
215
216! ---------------------------------------------------------
217 character(len=100) function em_rho_tag(freq, dir, dir2, ipert) result(str)
218 real(real64), intent(in) :: freq
219 integer, intent(in) :: dir
220 integer, optional, intent(in) :: dir2
221 integer, optional, intent(in) :: ipert
222
223 character(len=12) :: str_tmp
224
225 !this function has to be consistent with oct_search_file_lr in liboct/oct_f.c
226
227 push_sub(em_rho_tag)
228
229 str_tmp = freq2str(freq)
230 write(str, '(3a,i1)') 'rho_', trim(str_tmp), '_', dir
231 if (present(dir2)) write(str, '(2a,i1)') trim(str), "_", dir2
232 if (present(ipert)) write(str, '(3a)') trim(str), "_", index2pert(ipert)
233
234 pop_sub(em_rho_tag)
235
236 end function em_rho_tag
237
238
239! ---------------------------------------------------------
240 character(len=100) function em_wfs_tag(idir, ifactor, idir2, ipert) result(str)
241 integer, intent(in) :: idir
242 integer, intent(in) :: ifactor
243 integer, optional, intent(in) :: idir2
244 integer, optional, intent(in) :: ipert
245
246 push_sub(em_wfs_tag)
247
248 write(str, '(3a,i1)') "wfs_", index2axis(idir), "_f", ifactor
249 if (present(idir2)) write(str, '(3a)') trim(str), "_", index2axis(idir2)
250 if (present(ipert)) write(str, '(3a)') trim(str), "_", index2pert(ipert)
251
252 pop_sub(em_wfs_tag)
253
254 end function em_wfs_tag
255
256! ---------------------------------------------------------
257! Provides indices of axes forming the right-hand system
258! to the given axis (to choose components of the position
259! and velocity, r_\alpha and V_\beta, for calculation of
260! the M_\gamma component of the magnetic dipole moment
261! M_\gamma = e_{\alpha \beta \gamma} r_\alpha V_\beta /2)
262 integer pure function magn_dir(dir, ind) result(dir_out)
263 integer, intent(in) :: dir, ind
264
265 select case (dir)
266 case (1)
267 if (ind == 1) then
268 dir_out = 2
269 else
270 dir_out = 3
271 end if
272 case (2)
273 if (ind == 1) then
274 dir_out = 3
275 else
276 dir_out = 1
277 end if
278 case (3)
279 if (ind == 1) then
280 dir_out = 1
281 else
282 dir_out = 2
283 end if
284 case default
285 dir_out = 0
286 end select
287
288 end function magn_dir
289
290
291! ---------------------------------------------------------
292
293 character(len=2) pure function index2pert(ipert) result(ch)
294 integer, intent(in) :: ipert
295
296 select case (ipert)
297 case (1)
298 ch = 'B'
299 case (2)
300 ch = 'K2'
301 case (3)
302 ch = 'KB'
303 case (4)
304 ch = 'KE'
305 case (5)
306 ch = 'E'
307 end select
308
309 end function index2pert
311#include "undef.F90"
312#include "real.F90"
313#include "em_resp_calc_inc.F90"
314
315#include "undef.F90"
316#include "complex.F90"
317#include "em_resp_calc_inc.F90"
318
319end module em_resp_calc_oct_m
320
321!! Local Variables:
322!! mode: f90
323!! coding: utf-8
324!! End:
This module implements batches of mesh functions.
Definition: batch.F90:133
This module implements a calculator for the density and defines related functions.
Definition: density.F90:120
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 dlr_calc_elf(st, space, gr, kpoints, lr, lr_m)
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)
subroutine, public zlr_calc_elf(st, space, gr, kpoints, lr, lr_m)
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:190
real(real64), parameter, public m_zero
Definition: global.F90:188
complex(real64), parameter, public m_zi
Definition: global.F90:202
real(real64), parameter, public m_one
Definition: global.F90:189
This module implements the underlying real-space grid.
Definition: grid.F90:117
This module defines functions over batches of mesh functions.
Definition: mesh_batch.F90:116
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
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:118
character pure function, public index2axis(idir)
Definition: utils.F90:202
Definition: xc.F90:114