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 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 do idir = 1, space%dim
152
153 lr%dl_j(1:np, idir, ispin) = lr%dl_j(1:np, idir, ispin) + ( &
154 + conjg(psi(1:np, idim))*gdl_psi(1:np, idir) &
155 - psi(1:np, idim)*conjg(gdl_psi_m(1:np, idir)) &
156 + conjg(lr_m%zdl_psi(1:np, idim, ist, ispin)) * gpsi(1:np, idir) &
157 - lr%zdl_psi (1:np, idim, ist, ispin) * conjg(gpsi(1:np, idir)) &
158 ) / (m_two * m_zi)
159 end do
160
161 else
162
163 do idir = 1, space%dim
164
165 lr%dl_j(1:np, idir, ispin) = lr%dl_j(1:np, idir, ispin) + ( &
166 + conjg(psi(1:np, idim))*gdl_psi(1:np, idir) &
167 - psi(1:np, idim)*conjg(gdl_psi(1:np, idir)) &
168 + conjg(lr%zdl_psi(1:np, idim, ist, ispin)) * gpsi(1:np, idir) &
169 - lr%zdl_psi(1:np, idim, ist, ispin) * conjg(gpsi(1:np, idir)) &
170 ) / (m_two * m_zi)
171
172 end do
173
174 end if
175
176 end do
177 end do
178 end do
179
180 safe_deallocate_a(psi)
181 safe_deallocate_a(gpsi)
182 safe_deallocate_a(gdl_psi)
183 if (present(lr_m)) then
184 safe_deallocate_a(gdl_psi_m)
185 end if
186
187 pop_sub(lr_calc_current)
188
189 end subroutine lr_calc_current
190
191
192! ---------------------------------------------------------
193 character(len=12) function freq2str(freq) result(str)
194 real(real64), intent(in) :: freq
196 push_sub(freq2str)
197
198 ! some compilers (xlf) do not put a leading zero when the number
199 ! is smaller than 1. We have to check and correct that behavior.
200
201 write(str, '(f11.4)') freq
202 str = adjustl(str)
203 if (abs(freq) < m_one) then
204 if (freq >= m_zero .and. str(1:1) /= '0') str = "0"//trim(str)
205 if (freq < m_zero .and. str(2:2) /= '0') str = "-0"//trim(str(2:))
206 end if
207 str = trim(adjustl(str))
208
209 pop_sub(freq2str)
210
211 end function freq2str
212
213
214! ---------------------------------------------------------
215 character(len=100) function em_rho_tag(freq, dir, dir2, ipert) result(str)
216 real(real64), intent(in) :: freq
217 integer, intent(in) :: dir
218 integer, optional, intent(in) :: dir2
219 integer, optional, intent(in) :: ipert
220
221 character(len=12) :: str_tmp
222
223 !this function has to be consistent with oct_search_file_lr in liboct/oct_f.c
224
225 push_sub(em_rho_tag)
226
227 str_tmp = freq2str(freq)
228 write(str, '(3a,i1)') 'rho_', trim(str_tmp), '_', dir
229 if (present(dir2)) write(str, '(2a,i1)') trim(str), "_", dir2
230 if (present(ipert)) write(str, '(3a)') trim(str), "_", index2pert(ipert)
231
232 pop_sub(em_rho_tag)
233
234 end function em_rho_tag
235
236
237! ---------------------------------------------------------
238 character(len=100) function em_wfs_tag(idir, ifactor, idir2, ipert) result(str)
239 integer, intent(in) :: idir
240 integer, intent(in) :: ifactor
241 integer, optional, intent(in) :: idir2
242 integer, optional, intent(in) :: ipert
243
244 push_sub(em_wfs_tag)
245
246 write(str, '(3a,i1)') "wfs_", index2axis(idir), "_f", ifactor
247 if (present(idir2)) write(str, '(3a)') trim(str), "_", index2axis(idir2)
248 if (present(ipert)) write(str, '(3a)') trim(str), "_", index2pert(ipert)
249
250 pop_sub(em_wfs_tag)
251
252 end function em_wfs_tag
253
254! ---------------------------------------------------------
255! Provides indices of axes forming the right-hand system
256! to the given axis (to choose components of the position
257! and velocity, r_\alpha and V_\beta, for calculation of
258! the M_\gamma component of the magnetic dipole moment
259! M_\gamma = e_{\alpha \beta \gamma} r_\alpha V_\beta /2)
260 integer pure function magn_dir(dir, ind) result(dir_out)
261 integer, intent(in) :: dir, ind
262
263 select case (dir)
264 case (1)
265 if (ind == 1) then
266 dir_out = 2
267 else
268 dir_out = 3
269 end if
270 case (2)
271 if (ind == 1) then
272 dir_out = 3
273 else
274 dir_out = 1
275 end if
276 case (3)
277 if (ind == 1) then
278 dir_out = 1
279 else
280 dir_out = 2
281 end if
282 case default
283 dir_out = 0
284 end select
285
286 end function magn_dir
287
288
289! ---------------------------------------------------------
290
291 character(len=2) pure function index2pert(ipert) result(ch)
292 integer, intent(in) :: ipert
293
294 select case (ipert)
295 case (1)
296 ch = 'B'
297 case (2)
298 ch = 'K2'
299 case (3)
300 ch = 'KB'
301 case (4)
302 ch = 'KE'
303 case (5)
304 ch = 'E'
305 end select
306
307 end function index2pert
309#include "undef.F90"
310#include "real.F90"
311#include "em_resp_calc_inc.F90"
312
313#include "undef.F90"
314#include "complex.F90"
315#include "em_resp_calc_inc.F90"
316
317end module em_resp_calc_oct_m
318
319!! Local Variables:
320!! mode: f90
321!! coding: utf-8
322!! 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:189
real(real64), parameter, public m_zero
Definition: global.F90:187
complex(real64), parameter, public m_zi
Definition: global.F90:201
real(real64), parameter, public m_one
Definition: global.F90:188
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