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 mesh_oct_m
33 use xc_oct_m
34
35 implicit none
36
37 private
38 public :: &
45
47 private
48 logical :: oct_exchange = .false.
49 type(states_elec_t), pointer :: oct_st => null()
50 real(real64), allocatable :: oct_fxc(:, :, :)
51 real(real64), allocatable :: oct_pot(:, :)
52 real(real64), allocatable :: oct_rho(:, :)
53 end type oct_exchange_t
54
55contains
56
57 ! ---------------------------------------------------------
58 logical function oct_exchange_enabled(this) result(oct_exchange)
59 type(oct_exchange_t), intent(in) :: this
60
61 push_sub(oct_exchange_enabled)
62
63 oct_exchange = this%oct_exchange
64
66 end function oct_exchange_enabled
67
68
69 ! ---------------------------------------------------------
70 subroutine oct_exchange_set(this, st, mesh)
71 type(oct_exchange_t), intent(inout) :: this
72 type(states_elec_t), target, intent(in) :: st
73 class(mesh_t), intent(in) :: mesh
74
75 integer :: np, nspin
76
77 push_sub(oct_exchange_set)
78
79 ! In this release, no non-local part for the QOCT Hamiltonian.
80 nullify(this%oct_st)
81
82 this%oct_st => st
83 this%oct_exchange = .true.
84 np = mesh%np
85 nspin = this%oct_st%d%nspin
86
87 safe_allocate(this%oct_fxc(1:np, 1:nspin, 1:nspin))
88 safe_allocate(this%oct_pot(1:np, 1:nspin))
89 safe_allocate(this%oct_rho(1:np, 1:nspin))
90
91 this%oct_fxc = m_zero
92 this%oct_pot = m_zero
93 this%oct_rho = m_zero
94
95 pop_sub(oct_exchange_set)
96 end subroutine oct_exchange_set
97
98
99 ! ---------------------------------------------------------
100 subroutine oct_exchange_prepare(this, mesh, psi, xc, psolver, namespace)
101 type(oct_exchange_t), intent(inout) :: this
102 class(mesh_t), intent(in) :: mesh
103 complex(real64), intent(in) :: psi(:, :, :, :)
104 type(xc_t), intent(in) :: xc
105 type(poisson_t), intent(in) :: psolver
106 type(namespace_t), intent(in) :: namespace
107
108 integer :: jst, ip, ik
109 complex(real64), allocatable :: psi2(:, :)
110
111 push_sub(oct_exchange_prepare)
112
113 safe_allocate(psi2(1:mesh%np, 1:this%oct_st%d%dim))
115 select case (this%oct_st%d%ispin)
116 case (unpolarized)
117 assert(this%oct_st%nik == 1)
118
119 this%oct_pot = m_zero
120 this%oct_rho = m_zero
121 do jst = 1, this%oct_st%nst
122 call states_elec_get_state(this%oct_st, mesh, jst, 1, psi2)
123 do ip = 1, mesh%np
124 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))
125 end do
126 end do
127 call dpoisson_solve(psolver, namespace, this%oct_pot(:, 1), this%oct_rho(:, 1), all_nodes = .false.)
128
129 case (spin_polarized)
130 assert(this%oct_st%nik == 2)
131
132 this%oct_pot = m_zero
133 this%oct_rho = m_zero
134 do ik = 1, 2
135 do jst = 1, this%oct_st%nst
136 call states_elec_get_state(this%oct_st, mesh, jst, ik, psi2)
137 do ip = 1, mesh%np
138 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))
139 end do
140 end do
141 end do
143 do ik = 1, 2
144 call dpoisson_solve(psolver, namespace, this%oct_pot(:, ik), this%oct_rho(:, ik), all_nodes = .false.)
145 end do
146
147 end select
148
149 this%oct_fxc = m_zero
150 call xc_get_fxc(xc, mesh, namespace, this%oct_st%rho, this%oct_st%d%ispin, this%oct_fxc)
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:189
real(real64), parameter, public m_zero
Definition: global.F90:187
complex(real64), parameter, public m_zi
Definition: global.F90:201
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1125
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 oct_exchange_prepare(this, mesh, psi, xc, psolver, namespace)
subroutine, public dpoisson_solve(this, namespace, pot, rho, all_nodes, kernel)
Calculates the Poisson equation. Given the density returns the corresponding potential.
Definition: poisson.F90:892
This module handles spin dimensions of the states and the k-point distribution.
Definition: xc.F90:114
subroutine, public xc_get_fxc(xcs, mesh, namespace, rho, ispin, fxc, zfxc)
Definition: xc.F90:1974
Describes mesh distribution to nodes.
Definition: mesh.F90:186
int true(void)