Octopus
oct_exchange.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 debug_oct_m
25 use global_oct_m
26 use grid_oct_m
27 use mesh_oct_m
34 use xc_oct_m
35
36 implicit none
37
38 private
39 public :: &
46
48 private
49 logical :: oct_exchange = .false.
50 type(states_elec_t), pointer :: oct_st => null()
51 real(real64), allocatable :: oct_fxc(:, :, :)
52 real(real64), allocatable :: oct_pot(:, :)
53 real(real64), allocatable :: oct_rho(:, :)
54 end type oct_exchange_t
55
56contains
57
58 ! ---------------------------------------------------------
59 logical function oct_exchange_enabled(this) result(oct_exchange)
60 type(oct_exchange_t), intent(in) :: this
61
62 push_sub(oct_exchange_enabled)
63
64 oct_exchange = this%oct_exchange
65
67 end function oct_exchange_enabled
68
69
70 ! ---------------------------------------------------------
71 subroutine oct_exchange_set(this, st, mesh)
72 type(oct_exchange_t), intent(inout) :: this
73 type(states_elec_t), target, intent(in) :: st
74 class(mesh_t), intent(in) :: mesh
75
76 integer :: np, nspin
77
78 push_sub(oct_exchange_set)
79
80 ! In this release, no non-local part for the QOCT Hamiltonian.
81 nullify(this%oct_st)
82
83 this%oct_st => st
84 this%oct_exchange = .true.
85 np = mesh%np
86 nspin = this%oct_st%d%nspin
87
88 safe_allocate(this%oct_fxc(1:np, 1:nspin, 1:nspin))
89 safe_allocate(this%oct_pot(1:np, 1:nspin))
90 safe_allocate(this%oct_rho(1:np, 1:nspin))
91
92 this%oct_fxc = m_zero
93 this%oct_pot = m_zero
94 this%oct_rho = m_zero
95
96 pop_sub(oct_exchange_set)
97 end subroutine oct_exchange_set
98
99
100 ! ---------------------------------------------------------
101 subroutine oct_exchange_prepare(this, gr, psi, xc, psolver, namespace)
102 type(oct_exchange_t), intent(inout) :: this
103 type(grid_t), intent(in) :: gr
104 complex(real64), intent(in) :: psi(:, :, :, :)
105 type(xc_t), intent(in) :: xc
106 type(poisson_t), intent(in) :: psolver
107 type(namespace_t), intent(in) :: namespace
108
109 integer :: jst, ip, ik
110 complex(real64), allocatable :: psi2(:, :)
111
112 push_sub(oct_exchange_prepare)
113
114 safe_allocate(psi2(1:gr%np, 1:this%oct_st%d%dim))
115
116 select case (this%oct_st%d%ispin)
117 case (unpolarized)
118 assert(this%oct_st%nik == 1)
119
120 this%oct_pot = m_zero
121 this%oct_rho = m_zero
122 do jst = 1, this%oct_st%nst
123 call states_elec_get_state(this%oct_st, gr, jst, 1, psi2)
124 do ip = 1, gr%np
125 this%oct_rho(ip, 1) = this%oct_rho(ip, 1) + this%oct_st%occ(jst, 1)*aimag(conjg(psi2(ip, 1))*psi(ip, 1, jst, 1))
126 end do
127 end do
128 call dpoisson_solve(psolver, namespace, this%oct_pot(:, 1), this%oct_rho(:, 1), all_nodes = .false.)
129
130 case (spin_polarized)
131 assert(this%oct_st%nik == 2)
132
133 this%oct_pot = m_zero
134 this%oct_rho = m_zero
135 do ik = 1, 2
136 do jst = 1, this%oct_st%nst
137 call states_elec_get_state(this%oct_st, gr, jst, ik, psi2)
138 do ip = 1, gr%np
139 this%oct_rho(ip, ik) = this%oct_rho(ip, ik) + this%oct_st%occ(jst, ik) * aimag(conjg(psi2(ip, 1))*psi(ip, 1, jst, ik))
140 end do
141 end do
142 end do
144 do ik = 1, 2
145 call dpoisson_solve(psolver, namespace, this%oct_pot(:, ik), this%oct_rho(:, ik), all_nodes = .false.)
146 end do
147
148 end select
149
150 call xc_get_fxc(xc, gr, namespace, this%oct_st%rho, this%oct_st%d%ispin, this%oct_fxc)
151
152 safe_deallocate_a(psi2)
153 pop_sub(oct_exchange_prepare)
154 end subroutine oct_exchange_prepare
155
156
157 ! ---------------------------------------------------------
158 subroutine oct_exchange_remove(this)
159 type(oct_exchange_t), intent(inout) :: this
160
161 push_sub(oct_exchange_remove)
162
163 nullify(this%oct_st)
164 this%oct_exchange = .false.
165 safe_deallocate_a(this%oct_fxc)
166 safe_deallocate_a(this%oct_pot)
167 safe_deallocate_a(this%oct_rho)
168
169 pop_sub(oct_exchange_remove)
170 end subroutine oct_exchange_remove
171
172 ! ---------------------------------------------------------
173 subroutine oct_exchange_operator(this, namespace, mesh, hpsi, ist, ik)
174 type(oct_exchange_t), intent(in) :: this
175 type(namespace_t), intent(in) :: namespace
176 class(mesh_t), intent(in) :: mesh
177 complex(real64), intent(inout) :: hpsi(:, :)
178 integer, intent(in) :: ist
179 integer, intent(in) :: ik
180
181 integer :: ik2
182 complex(real64), allocatable :: psi(:, :), psi2(:, :)
183 integer :: ip
184
185 push_sub(oct_exchange_operator)
186
187 safe_allocate(psi(1:mesh%np, 1:this%oct_st%d%dim))
188 safe_allocate(psi2(1:mesh%np, 1:this%oct_st%d%dim))
189
190 select case (this%oct_st%d%ispin)
191 case (unpolarized)
192 assert(this%oct_st%nik == 1)
193 call states_elec_get_state(this%oct_st, mesh, ist, 1, psi2)
194 do ip = 1, mesh%np
195 hpsi(ip, 1) = hpsi(ip, 1) + m_two*m_zi*psi2(ip, 1)*(this%oct_pot(ip, 1) + this%oct_fxc(ip, 1, 1)*this%oct_rho(ip, 1))
196 end do
197
198 case (spin_polarized)
199 assert(this%oct_st%nik == 2)
200
201 call states_elec_get_state(this%oct_st, mesh, ist, ik, psi2)
202
203 do ik2 = 1, 2
204 do ip = 1, mesh%np
205 hpsi(ip, 1) = hpsi(ip, 1) + m_two * m_zi * this%oct_st%occ(ist, ik) * &
206 psi2(ip, 1) * (this%oct_pot(ip, ik2) + this%oct_fxc(ip, ik, ik2)*this%oct_rho(ip, ik2))
207 end do
208 end do
209
210 case (spinors)
211 call messages_not_implemented("Function oct_exchange_operator for spinors", namespace=namespace)
212 end select
213
214 safe_deallocate_a(psi)
215 safe_deallocate_a(psi2)
216 pop_sub(oct_exchange_operator)
217 end subroutine oct_exchange_operator
218
219end module oct_exchange_oct_m
220
221!! Local Variables:
222!! mode: f90
223!! coding: utf-8
224!! End:
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
integer, parameter, public unpolarized
Parameters...
integer, parameter, public spinors
integer, parameter, public spin_polarized
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
This module implements the underlying real-space grid.
Definition: grid.F90:117
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1113
subroutine, public oct_exchange_prepare(this, gr, psi, xc, psolver, namespace)
logical function, public oct_exchange_enabled(this)
subroutine, public oct_exchange_remove(this)
subroutine, public oct_exchange_set(this, st, mesh)
subroutine, public oct_exchange_operator(this, namespace, mesh, hpsi, ist, ik)
subroutine, public dpoisson_solve(this, namespace, pot, rho, all_nodes, kernel, reset)
Calculates the Poisson equation. Given the density returns the corresponding potential.
Definition: poisson.F90:893
This module handles spin dimensions of the states and the k-point distribution.
Definition: xc.F90:114
subroutine, public xc_get_fxc(xcs, gr, namespace, rho, ispin, fxc, fxc_grad, fxc_grad_spin)
Returns the exchange-correlation kernel.
Definition: xc.F90:1975
Describes mesh distribution to nodes.
Definition: mesh.F90:186
int true(void)