Octopus
propagator_magnus.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
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 debug_oct_m
29 use global_oct_m
30 use grid_oct_m
34 use ions_oct_m
35 use, intrinsic :: iso_fortran_env
36 use lasers_oct_m
39 use parser_oct_m
45 use space_oct_m
47 use v_ks_oct_m
48 use xc_oct_m
49
50 implicit none
51
52 private
53
54 public :: &
55 td_magnus, &
57
58contains
59
60 ! ---------------------------------------------------------
62 subroutine td_magnus(hm, ext_partners, gr, st, tr, namespace, time, dt)
63 type(hamiltonian_elec_t), intent(inout) :: hm
64 type(partner_list_t), intent(in) :: ext_partners
65 type(grid_t), intent(in) :: gr
66 type(states_elec_t), intent(inout) :: st
67 type(propagator_base_t), intent(inout) :: tr
68 type(namespace_t), intent(in) :: namespace
69 real(real64), intent(in) :: time
70 real(real64), intent(in) :: dt
71
72 integer :: j, is, i
73 real(real64) :: atime(2)
74 real(real64), allocatable :: vaux(:, :, :), pot(:)
75 type(lasers_t), pointer :: lasers
76
77 push_sub(propagator_dt.td_magnus)
78
79 assert(.not. family_is_mgga_with_exc(hm%xc))
80
81 safe_allocate(vaux(1:gr%np, 1:st%d%nspin, 1:2))
82
83 atime(1) = (m_half-sqrt(m_three)/6.0_real64)*dt
84 atime(2) = (m_half+sqrt(m_three)/6.0_real64)*dt
85
86 if (hm%theory_level /= independent_particles) then
87 do j = 1, 2
88 call potential_interpolation_interpolate(tr%vksold, 3, time, dt, time - dt + atime(j), vaux(:, :, j))
89 end do
90 else
91 vaux = m_zero
92 end if
93
94 do j = 1, 2
95 ! WARNING: This should be carefully tested, and extended to allow for velocity-gauge laser fields.
96 lasers => list_get_lasers(ext_partners)
97 if(associated(lasers)) then
98 do i = 1, lasers%no_lasers
99 select case (laser_kind(lasers%lasers(i)))
100 case (e_field_electric)
101 safe_allocate(pot(1:gr%np))
102 pot = m_zero
103 call laser_potential(lasers%lasers(i), gr, pot, time - dt + atime(j))
104 do is = 1, st%d%nspin
105 vaux(:, is, j) = vaux(:, is, j) + pot(:)
106 end do
107 safe_deallocate_a(pot)
109 write(message(1),'(a)') 'The Magnus propagator cannot be used with magnetic fields, or'
110 write(message(2),'(a)') 'with an electric field described in the velocity gauge.'
111 call messages_fatal(2, namespace=namespace)
112 end select
113 end do
114 end if
115 end do
116
117 tr%vmagnus(:, :, 2) = m_half*(vaux(:, :, 1) + vaux(:, :, 2))
118 tr%vmagnus(:, :, 1) = (sqrt(m_three)/12.0_real64)*dt*(vaux(:, :, 2) - vaux(:, :, 1))
119
120 call propagation_ops_elec_fuse_density_exp_apply(tr%te, namespace, st, gr, hm, dt, vmagnus = tr%vmagnus)
121
122 safe_deallocate_a(vaux)
123 pop_sub(propagator_dt.td_magnus)
124 end subroutine td_magnus
125
126
127 ! ---------------------------------------------------------
129 subroutine td_cfmagnus4(ks, namespace, space, hm, gr, st, tr, time, dt, ions_dyn, ions, ext_partners, iter)
130 type(v_ks_t), target, intent(inout) :: ks
131 type(namespace_t), intent(in) :: namespace
132 type(electron_space_t), intent(in) :: space
133 type(hamiltonian_elec_t), target, intent(inout) :: hm
134 type(grid_t), target, intent(in) :: gr
135 type(states_elec_t), target, intent(inout) :: st
136 type(propagator_base_t), target, intent(inout) :: tr
137 real(real64), intent(in) :: time
138 real(real64), intent(in) :: dt
139 type(ion_dynamics_t), intent(inout) :: ions_dyn
140 type(ions_t), intent(inout) :: ions
141 type(partner_list_t), intent(in) :: ext_partners
142 integer, intent(in) :: iter
143
144 real(real64) :: alpha1, alpha2, c1, c2, t1, t2
145 real(real64), allocatable :: vhxc1(:, :), vhxc2(:, :)
146
147 if (ion_dynamics_ions_move(ions_dyn) .or. list_has_gauge_field(ext_partners)) then
148 message(1) = "The commutator-free Magnus expansion cannot be used with moving ions or gauge fields"
149 call messages_fatal(1, namespace=namespace)
150 end if
151
152 push_sub(propagator_dt.td_cfmagnus4)
153
154 if (iter < 4) then
155 call td_explicit_runge_kutta4(ks, namespace, space, hm, gr, st, time, dt, ions_dyn, ions, ext_partners)
156 pop_sub(propagator_dt.td_cfmagnus4)
157 return
158 end if
159
160
161 alpha1 = (m_three - m_two * sqrt(m_three))/12.0_real64
162 alpha2 = (m_three + m_two * sqrt(m_three))/12.0_real64
163 c1 = m_half - sqrt(m_three)/6.0_real64
164 c2 = m_half + sqrt(m_three)/6.0_real64
165 t1 = time - dt + c1*dt
166 t2 = time - dt + c2*dt
167
168 safe_allocate(vhxc1(1:gr%np, 1:st%d%nspin))
169 safe_allocate(vhxc2(1:gr%np, 1:st%d%nspin))
170
171 call potential_interpolation_interpolate(tr%vksold, 4, time, dt, t1, vhxc1)
172 call potential_interpolation_interpolate(tr%vksold, 4, time, dt, t2, vhxc2)
173
174 hm%vhxc = m_two * (alpha2 * vhxc1 + alpha1 * vhxc2)
175 call hamiltonian_elec_update_with_ext_pot(hm, gr, space, ext_partners, (/ t1, t2 /), (/ m_two * alpha2, m_two * alpha1 /))
176 ! propagate by dt/2
177 call propagation_ops_elec_exp_apply(tr%te, namespace, st, gr, hm, m_half*dt)
178
179 hm%vhxc = m_two * (alpha1 * vhxc1 + alpha2 * vhxc2)
180 call hamiltonian_elec_update_with_ext_pot(hm, gr, space, ext_partners, (/ t1, t2 /), (/ m_two * alpha1, m_two * alpha2 /))
181 ! propagate by dt/2
182 !TODO: fuse this with density calc
183 call propagation_ops_elec_exp_apply(tr%te, namespace, st, gr, hm, m_half * dt)
184
185 call density_calc(st, gr, st%rho)
186
187 safe_deallocate_a(vhxc1)
188 safe_deallocate_a(vhxc2)
189 pop_sub(propagator_dt.td_cfmagnus4)
190 end subroutine td_cfmagnus4
191
193
194!! Local Variables:
195!! mode: f90
196!! coding: utf-8
197!! End:
double sqrt(double __x) __attribute__((__nothrow__
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
subroutine, public density_calc(st, gr, density, istin)
Computes the density from the orbitals in st.
Definition: density.F90:608
logical function, public list_has_gauge_field(partners)
type(lasers_t) function, pointer, public list_get_lasers(partners)
real(real64), parameter, public m_two
Definition: global.F90:189
real(real64), parameter, public m_zero
Definition: global.F90:187
real(real64), parameter, public m_half
Definition: global.F90:193
real(real64), parameter, public m_three
Definition: global.F90:190
This module implements the underlying real-space grid.
Definition: grid.F90:117
integer, parameter, public independent_particles
subroutine, public hamiltonian_elec_update_with_ext_pot(this, mesh, space, ext_partners, time, mu)
This is an extension of "hamiltonian_elec_update_pot" to be used by the CFM4 propagator....
This module defines classes and functions for interaction partners.
logical pure function, public ion_dynamics_ions_move(this)
integer, parameter, public e_field_electric
Definition: lasers.F90:176
integer, parameter, public e_field_vector_potential
Definition: lasers.F90:176
subroutine, public laser_potential(laser, mesh, pot, time)
Definition: lasers.F90:1039
integer pure elemental function, public laser_kind(laser)
Definition: lasers.F90:711
integer, parameter, public e_field_magnetic
Definition: lasers.F90:176
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:420
subroutine, public potential_interpolation_interpolate(potential_interpolation, order, time, dt, t, vhxc, vtau)
subroutine, public propagation_ops_elec_exp_apply(te, namespace, st, mesh, hm, dt)
subroutine, public propagation_ops_elec_fuse_density_exp_apply(te, namespace, st, gr, hm, dt, dt2, vmagnus)
subroutine, public td_cfmagnus4(ks, namespace, space, hm, gr, st, tr, time, dt, ions_dyn, ions, ext_partners, iter)
Commutator-free Magnus propagator of order 4.
subroutine, public td_magnus(hm, ext_partners, gr, st, tr, namespace, time, dt)
Magnus propagator.
subroutine, public td_explicit_runge_kutta4(ks, namespace, space, hm, gr, st, time, dt, ions_dyn, ions, ext_partners, qcchi)
Definition: xc.F90:114
logical pure function, public family_is_mgga_with_exc(xcs)
Is the xc function part of the mGGA family with an energy functional.
Definition: xc.F90:592