Octopus
photon_mode_mf.F90
Go to the documentation of this file.
1!! Copyright (C) 2017 Johannes Flick
2!! Copyright (C) 2021 Davis Welakuh (merged)
3!!
4!! This program is free software; you can redistribute it and/or modify
5!! it under the terms of the GNU General Public License as published by
6!! the Free Software Foundation; either version 2, or (at your option)
7!! any later version.
8!!
9!! This program is distributed in the hope that it will be useful,
10!! but WITHOUT ANY WARRANTY; without even the implied warranty of
11!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12!! GNU General Public License for more details.
13!!
14!! You should have received a copy of the GNU General Public License
15!! along with this program; if not, write to the Free Software
16!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17!! 02110-1301, USA.
18
19!! v_mxc = - omega*q_alpha*(lambda*r) + (lambda*dipole)*(lambda*r)
20!! see PRL 115, 093001 (2015) and PRL 121, 113002 (2018)
21#include "global.h"
22
24 use debug_oct_m
25 use global_oct_m
27 use grid_oct_m
29 use io_oct_m
30 use ions_oct_m
35 use ps_oct_m
39
40
41 implicit none
42
43 private
44
45 public :: &
46 mf_t, &
47 mf_init, &
48 mf_end, &
49 mf_calc, &
52 type mf_t
53 real(real64), pointer :: vmf(:)
54 real(real64), allocatable :: dipole(:)
55 real(real64), allocatable :: dipole_former(:)
56 complex(real64), allocatable :: integral(:)
57 real(real64), allocatable :: pt_q(:), pt_p(:)
58 real(real64), allocatable :: pt_q_former(:)
59 real(real64) :: time_former
60 real(real64), pointer :: fmf(:) !! meanfield force
61 logical :: has_restart
62
63 end type mf_t
64
65contains
66
67 subroutine mf_init(this, gr, st, ions, pt_mode)
68 type(mf_t), intent(out) :: this
69 type(grid_t), intent(in) :: gr
70 type(states_elec_t), intent(in) :: st
71 type(ions_t), intent(in) :: ions
72 type(photon_mode_t), intent(in) :: pt_mode
73
74 integer :: ions_dim
75
76 push_sub(mf_init)
77
78 ions_dim = gr%box%dim
79
80 safe_allocate(this%vmf(1:gr%np))
81 safe_allocate(this%dipole(1:ions_dim))
82 safe_allocate(this%dipole_former(1:ions_dim))
83
84 safe_allocate(this%integral(1:pt_mode%nmodes))
85 safe_allocate(this%pt_q(1:pt_mode%nmodes))
86 safe_allocate(this%pt_p(1:pt_mode%nmodes))
87 safe_allocate(this%pt_q_former(1:pt_mode%nmodes))
88 safe_allocate(this%fmf(1:ions_dim))
89
90 this%vmf = m_zero
91 this%has_restart = .false.
92
93
94 this%dipole = - ions%dipole() - st%dipole(gr)
95
96 this%dipole_former = m_zero
97 this%integral = m_zero
98
99 if (pt_mode%has_q0_p0) then
100 this%pt_q(1:pt_mode%nmodes) = pt_mode%pt_coord_q0(1:pt_mode%nmodes)
101 this%pt_p(1:pt_mode%nmodes) = pt_mode%pt_momen_p0(1:pt_mode%nmodes)
102 else
103 this%pt_q = m_zero
104 this%pt_p = m_zero
105 end if
106
107 this%pt_q_former = m_zero
108 this%time_former = m_zero
109
110 this%fmf(1:ions_dim) = m_zero
111
112 pop_sub(mf_init)
113 end subroutine mf_init
114
115!------------------------------------------
116
117 subroutine mf_end(this)
118 type(mf_t), intent(inout) :: this
119
120 push_sub(mf_end)
121
122 safe_deallocate_p(this%vmf)
123 safe_deallocate_a(this%dipole_former)
124 safe_deallocate_a(this%dipole)
125
126 safe_deallocate_a(this%integral)
127 safe_deallocate_a(this%pt_p)
128 safe_deallocate_a(this%pt_q)
129 safe_deallocate_a(this%pt_q_former)
130
131 safe_deallocate_p(this%fmf)
132
133 pop_sub(mf_end)
134 end subroutine mf_end
135
136!------------------------------------------
137
138 subroutine mf_calc(this, gr, st, ions, pt_mode, time)
139 type(mf_t), intent(inout) :: this
140 type(grid_t), intent(inout) :: gr
141 type(states_elec_t), intent(inout) :: st
142 type(ions_t), intent(in) :: ions
143 type(photon_mode_t), intent(inout) :: pt_mode
144 real(real64), intent(in) :: time
145
146 real(real64) :: lambda_pol_dipole, lambda_pol_dipole_former
147 complex(real64) :: integrand
148 real(real64) :: q0, p0, vmf_coeff
149 integer :: ii, jj, ions_dim
150 logical, save :: first = .true.
152 push_sub(mf_calc)
154 ions_dim = gr%box%dim
156 if (.not. (first .and. this%has_restart)) then
157 do ii = 1, pt_mode%nmodes
158 this%pt_q_former(ii) = this%pt_q(ii)
159 end do
160
161 this%dipole_former = this%dipole
162 this%dipole = - ions%dipole() - st%dipole(gr)
163
164 end if
165
166 this%vmf(1:gr%np) = m_zero
167 this%fmf(1:ions_dim) = m_zero
168
169 do ii = 1, pt_mode%nmodes
170 lambda_pol_dipole = m_zero
171 lambda_pol_dipole_former = m_zero
172 do jj = 1, ions_dim
173 lambda_pol_dipole = lambda_pol_dipole + &
174 pt_mode%lambda(ii)*pt_mode%pol(ii, jj)*this%dipole(jj)
175 lambda_pol_dipole_former = lambda_pol_dipole_former + &
176 pt_mode%lambda(ii)*pt_mode%pol(ii, jj)*this%dipole_former(jj)
177 end do
178
179 if (.not.(first .and. this%has_restart)) then
180 if (abs(time) <= m_epsilon) then
181 this%integral(ii) = m_zero
182 else if (abs(this%integral(ii)) <= m_epsilon) then
183 this%integral(ii) = m_half*lambda_pol_dipole*exp(-m_zi*pt_mode%omega(ii)*(this%time_former))
184 else
185 this%integral(ii) = this%integral(ii) + lambda_pol_dipole*exp(-m_zi*pt_mode%omega(ii)*(this%time_former))
186 end if
187 end if
188
189 integrand = -(this%integral(ii)*exp(m_zi*pt_mode%omega(ii)*(time)*pt_mode%mu))* &
190 (time*pt_mode%mu - this%time_former)
191
192 this%pt_q(ii) = aimag(integrand)
193 this%pt_p(ii) = pt_mode%omega(ii)*real(integrand)
194
195 if (pt_mode%has_q0_p0) then
196 q0 = pt_mode%pt_coord_q0(ii)*cos(pt_mode%omega(ii)*(time)*pt_mode%mu)
197 q0 = q0 + pt_mode%pt_momen_p0(ii)/pt_mode%omega(ii)*sin(pt_mode%omega(ii)*(time)*pt_mode%mu)
198 this%pt_q(ii) = this%pt_q(ii) + q0
199
200 p0 = -pt_mode%pt_coord_q0(ii)*pt_mode%omega(ii)*sin(pt_mode%omega(ii)*(time)*pt_mode%mu)
201 p0 = p0 + pt_mode%pt_momen_p0(ii)*cos(pt_mode%omega(ii)*(time)*pt_mode%mu)
202 this%pt_p(ii) = this%pt_p(ii) + p0
203 end if
204
205 if (.not.allocated(pt_mode%pol_dipole)) then
206 call photon_mode_compute_dipoles(pt_mode, gr)
207 end if
208
209 ! we need the negative sign due to the electric pol_dipole
210 vmf_coeff = m_half*((lambda_pol_dipole + lambda_pol_dipole_former) + pt_mode%omega(ii)* &
211 (this%pt_q(ii) + this%pt_q_former(ii)))*pt_mode%lambda(ii)
212 call lalg_axpy(gr%np, -vmf_coeff, pt_mode%pol_dipole(:, ii), this%vmf)
213 do jj = 1, ions_dim
214 this%fmf(jj) = this%fmf(jj) - pt_mode%omega(ii)*pt_mode%lambda(ii)* &
215 pt_mode%pol(ii, jj)*(this%pt_q(ii) + lambda_pol_dipole/pt_mode%omega(ii)) !minus?
216 end do
217 end do
218
219 if (first .and. this%has_restart) then
220 first = .false.
221 end if
222
223 this%time_former = time*pt_mode%mu
224
225 pop_sub(mf_calc)
226 end subroutine mf_calc
227
228! ---------------------------------------------------------
229
230 subroutine mf_photons_dump(restart, this, gr, dt, pt_mode, ierr)
231 type(restart_t), intent(in) :: restart
232 type(mf_t), intent(in) :: this
233 type(grid_t), intent(in) :: gr
234 real(real64), intent(in) :: dt
235 type(photon_mode_t), intent(in) :: pt_mode
236 integer, intent(out) :: ierr
237
238 character(len=80), allocatable :: lines(:)
239 integer :: iunit, err, jj, ions_dim
240
241 push_sub(mf_photons_dump)
242 ions_dim = gr%box%dim
243
244 safe_allocate(lines(1:2*ions_dim + 4))
245
246 ierr = 0
247
248 iunit = restart%open('photon_mf')
249 write(lines(1), '(a10,2x,es19.12)') 'pt_integral_real', real(this%integral(1))
250 write(lines(2), '(a10,2x,es19.12)') 'pt_integral_aimag', aimag(this%integral(1))
251 write(lines(3), '(a10,2x,es19.12)') 'pt_q_former', this%pt_q_former(1)
252 write(lines(4), '(a10,2x,es19.12)') 'pt_time_former', this%time_former - dt*pt_mode%mu
253 do jj = 1, ions_dim
254 write(lines(4 + jj), '(a10,2x,es19.12)') 'dipole', this%dipole(jj)
255 end do
256 do jj = 1, ions_dim
257 write(lines(4 + ions_dim + jj), '(a10,2x,es19.12)') 'dipole_former', this%dipole_former(jj)
258 end do
259 call restart%write(iunit, lines, 2*ions_dim + 4, err)
260 if (err /= 0) ierr = ierr + 1
261 call restart%close(iunit)
262
263 safe_deallocate_a(lines)
264
265 pop_sub(mf_photons_dump)
266 end subroutine mf_photons_dump
267
268! ---------------------------------------------------------
269
270 subroutine mf_photons_load(restart, this, gr, ierr)
271 type(restart_t), intent(in) :: restart
272 type(mf_t), intent(inout) :: this
273 type(grid_t), intent(in) :: gr
274 integer, intent(out) :: ierr
275
276 integer :: err, iunit, jj, ions_dim
277 character(len=128), allocatable :: lines(:)
278 character(len=7) :: dummy
279 real(real64), allocatable :: rr(:)
280
281 push_sub(mf_photons_load)
282
283 ierr = 0
284 ions_dim = gr%box%dim
285
286 if (restart%skip()) then
287 ierr = -1
288 pop_sub(mf_photons_load)
289 return
290 end if
291
292 message(1) = "Debug: Reading Photons restart."
293 call messages_info(1, namespace=restart%namespace, debug_only=.true.)
294
295 safe_allocate(rr(1:2*ions_dim + 4))
296 safe_allocate(lines(1:2*ions_dim + 4))
297 iunit = restart%open('photon_mf')
298 call restart%read(iunit, lines, 2*ions_dim + 4, err)
299 if (err /= 0) then
300 ierr = ierr + 1
301 else
302 do jj = 1, 2*ions_dim + 4
303 read(lines(jj),'(a10,2x,es19.12)') dummy, rr(jj)
304 end do
305
306 this%integral(1) = cmplx(rr(1), rr(2), real64)
307 this%pt_q_former(1) = rr(3)
308 this%time_former = rr(4)
309 do jj = 1, ions_dim
310 this%dipole(jj) = rr(jj + 4)
311 end do
312 do jj = 1, ions_dim
313 this%dipole_former(jj) = rr(jj + ions_dim + 4)
314 end do
315 this%has_restart = .true.
316
317 end if
318 call restart%close(iunit)
319
320 message(1) = "Debug: Reading Photons restart done."
321 call messages_info(1, namespace=restart%namespace, debug_only=.true.)
322
323 safe_deallocate_a(rr)
324 safe_deallocate_a(lines)
326 pop_sub(mf_photons_load)
327 end subroutine mf_photons_load
328
329! ---------------------------------------------------------
330
331end module photon_mode_mf_oct_m
332
333!! Local Variables:
334!! mode: f90
335!! coding: utf-8
336!! End:
constant times a vector plus a vector
Definition: lalg_basic.F90:173
double exp(double __x) __attribute__((__nothrow__
double sin(double __x) __attribute__((__nothrow__
double cos(double __x) __attribute__((__nothrow__
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_epsilon
Definition: global.F90:216
real(real64), parameter, public m_half
Definition: global.F90:206
This module implements the underlying real-space grid.
Definition: grid.F90:119
Definition: io.F90:116
This module defines various routines, operating on mesh functions.
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
subroutine, public mf_photons_load(restart, this, gr, ierr)
subroutine, public mf_init(this, gr, st, ions, pt_mode)
subroutine, public mf_photons_dump(restart, this, gr, dt, pt_mode, ierr)
subroutine, public mf_end(this)
subroutine, public mf_calc(this, gr, st, ions, pt_mode, time)
subroutine, public photon_mode_compute_dipoles(this, mesh)
Computes the polarization dipole.
Definition: ps.F90:116
Description of the grid, containing information on derivatives, stencil, and symmetries.
Definition: grid.F90:171
int true(void)