Octopus
excited_states.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
24 use global_oct_m
25 use io_oct_m
26 use, intrinsic :: iso_fortran_env
28 use mesh_oct_m
34
35 implicit none
36
37 private
38 public :: &
50
51
52
53 interface dstates_elec_mpdotp
55 end interface dstates_elec_mpdotp
56
57 interface zstates_elec_mpdotp
59 end interface zstates_elec_mpdotp
60
62 module procedure dstates_elec_mpmatrixelement_g
64
66 module procedure zstates_elec_mpmatrixelement_g
68
69 type states_pair_t
70 ! Components are public by default
71 integer :: i
72 integer :: a
73 integer :: kk
74 end type states_pair_t
75
77 ! Components are public by default
78 type(states_elec_t), pointer :: st
79 integer :: n_pairs
80 type(states_pair_t), allocatable :: pair(:)
81 real(real64), allocatable :: weight(:)
82 end type excited_states_t
83
84contains
85
86 ! ---------------------------------------------------------
110 subroutine excited_states_init(excited_state, ground_state, filename, namespace)
111 type(excited_states_t), intent(inout) :: excited_state
112 type(states_elec_t), target, intent(in) :: ground_state
113 character(len=*), intent(in) :: filename
114 type(namespace_t), intent(in) :: namespace
115
116 integer :: iunit, nst, ispin, nik, &
117 n_possible_pairs, ipair, jpair, ist, ios, nspin, trash
118 integer, allocatable :: n_filled(:), n_partially_filled(:), n_half_filled(:), n_empty(:), &
119 filled(:, :), partially_filled(:, :), half_filled(:, :)
120 real(real64) :: dump
121 logical :: ok
122
123 push_sub(excited_states_init)
124
125 ! This is just to make the code more readable.
126 nst = ground_state%nst
127 nik = ground_state%nik
128 ispin = ground_state%d%ispin
129 nspin = ground_state%d%nspin
130
131 if (nik > 2 .or. ( (nik == 2) .and. (ispin /= spin_polarized))) then
132 message(1) = 'Cannot calculate projections onto excited states for periodic systems.'
133 call messages_fatal(1, namespace=namespace)
134 end if
135
136 safe_allocate( n_filled(1:nspin))
137 safe_allocate( n_empty(1:nspin))
138 safe_allocate(n_partially_filled(1:nspin))
139 safe_allocate( n_half_filled(1:nspin))
140 safe_allocate( filled(1:nst, 1:nspin))
141 safe_allocate(partially_filled(1:nst, 1:nspin))
142 safe_allocate( half_filled(1:nst, 1:nspin))
143
144 select case (ispin)
145 case (unpolarized)
146 call occupied_states(ground_state, namespace, 1, n_filled(1), n_partially_filled(1), n_half_filled(1), &
147 filled(:, 1), partially_filled(:, 1), half_filled(:, 1))
148 if (n_partially_filled(1) > 0) then
149 message(1) = 'Cannot calculate projections onto excited states if there are partially filled orbitals.'
150 call messages_fatal(1, namespace=namespace)
151 end if
152 ! We will not accept, for the time being, constructing excited states in spin-restricted mode if
153 ! there are single-particle states that are half-filled, *unless* there is only one state and it is
154 ! half-filled (single-particle calculation).
155 if ((n_half_filled(1) /= 0 .and. n_filled(1) > 0) .or. (n_half_filled(1) > 1)) then
156 message(1) = 'Cannot construct excited states from ground states that contain half-filled'
157 message(2) = 'orbitals - unless they are just one-particle states with only one half-filled'
158 message(3) = 'orbital and no doubly occupied ones. Try using the spin-unrestricted mode.'
159 call messages_fatal(3, namespace=namespace)
160 end if
161 if (n_half_filled(1) == 0) then
162 n_empty(1) = nst - n_filled(1)
163 n_possible_pairs = n_filled(1) * n_empty(1)
164 else ! This is for the one-electron case.
165 n_empty(1) = nst - 1
166 n_possible_pairs = n_empty(1)
167 end if
168
170 call occupied_states(ground_state, namespace, 1, n_filled(1), n_partially_filled(1), n_half_filled(1), &
171 filled(:, 1), partially_filled(:, 1), half_filled(:, 1))
172 call occupied_states(ground_state, namespace, 2, n_filled(2), n_partially_filled(2), n_half_filled(2), &
173 filled(:, 2), partially_filled(:, 2), half_filled(:, 2))
174 if (n_partially_filled(1) * n_partially_filled(2) > 0) then
175 message(1) = 'Cannot calculate projections onto excited states if there are partially filled orbitals.'
176 call messages_fatal(1, namespace=namespace)
177 end if
178 n_empty(1) = nst - n_filled(1)
179 n_empty(2) = nst - n_filled(2)
180 n_possible_pairs = n_filled(1) * n_empty(1) + n_filled(2) * n_empty(2)
181
182 case (spinors)
183 call occupied_states(ground_state, namespace, 1, n_filled(1), n_partially_filled(1), n_half_filled(1), &
184 filled(:, 1), partially_filled(:, 1), half_filled(:, 1))
185 if (n_partially_filled(1) > 0) then
186 message(1) = 'Cannot calculate projections onto excited states if there are partially filled orbitals.'
187 call messages_fatal(1, namespace=namespace)
188 end if
189 n_empty(1) = nst - n_filled(1)
190 n_possible_pairs = n_filled(1) * n_empty(1)
191 end select
192
193 iunit = io_open(trim(filename), namespace, action = 'read', status = 'old', die = .true.)
194 call io_skip_header(iunit)
195
196 ! Now we count the number of pairs in the file
197 ipair = 0
198 do
199 read(iunit, *, end = 101)
200 backspace(iunit)
201 read(iunit, *, iostat = ios) trash, trash, trash, dump
202 if (ios /= 0) then
203 message(1) = 'Error attempting to read the electron-hole pairs in file "'//trim(filename)//'"'
204 call messages_fatal(1, namespace=namespace)
205 end if
206 ipair = ipair + 1
207 end do
208101 continue
209 if (ipair == 0) then
210 message(1) = 'File "'//trim(filename)//'" is empty?'
211 call messages_fatal(1, namespace=namespace)
212 elseif (ipair > n_possible_pairs) then
213 message(1) = 'File "'//trim(filename)//'" contains too many electron-hole pairs.'
214 call messages_fatal(1, namespace=namespace)
215 end if
216
217 excited_state%n_pairs = ipair
218 safe_allocate(excited_state%pair(1:ipair))
219 safe_allocate(excited_state%weight(1:ipair))
220
221 rewind(iunit)
222 call io_skip_header(iunit)
223 do ipair = 1, excited_state%n_pairs
224 read(iunit, *) excited_state%pair(ipair)%i, excited_state%pair(ipair)%a, &
225 excited_state%pair(ipair)%kk, excited_state%weight(ipair)
226 if (((ispin == unpolarized) .or. (ispin == spinors)) .and. (excited_state%pair(ipair)%kk /= 1)) then
227 message(1) = 'Error reading excited state in file "'//trim(filename)//'":'
228 message(2) = 'Cannot treat a electron-hole pair for "down" spin when not working in spin-polarized mode.'
229 call messages_fatal(2, namespace=namespace)
230 end if
231 ! Check whether it is a legitimate electron-hole swap.
232
233 ! First, whether the occupied state belongs to the list of occupied states.
234 ok = .false.
235 do ist = 1, n_filled(excited_state%pair(ipair)%kk)
236 ok = excited_state%pair(ipair)%i == filled(ist, excited_state%pair(ipair)%kk)
237 if (ok) exit
238 end do
239
240 ! Treat differently the one-electron case in unpolarized mode
241 if (ispin == unpolarized .and. (n_half_filled(1) == 1)) then
242 ok = excited_state%pair(ipair)%i == half_filled(1, excited_state%pair(ipair)%kk)
243 end if
244
245 if (.not. ok) then
246 write(message(1),'(a6,i3,a1,i3,a8,i1,a)') 'Pair (', excited_state%pair(ipair)%i, ',', &
247 excited_state%pair(ipair)%a, '; k =', excited_state%pair(ipair)%kk, ') is not valid.'
248 call messages_fatal(1, namespace=namespace)
249 end if
250
251 ! Then, whether the unoccupied state is really unoccupied.
252 ok = .true.
253 do ist = 1, n_filled(excited_state%pair(ipair)%kk)
254 ok = .not. (excited_state%pair(ipair)%a == filled(ist, excited_state%pair(ipair)%kk))
255 end do
256 ! Treat differently the one-electron case in unpolarized mode
257 if (ispin == unpolarized .and. (n_half_filled(1) == 1)) then
258 ok = .not. (excited_state%pair(ipair)%i == half_filled(1, excited_state%pair(ipair)%kk))
259 end if
260 ok = .not. (excited_state%pair(ipair)%a > nst)
261 if (.not. ok) then
262 write(message(1),'(a6,i3,a1,i3,a8,i1,a)') 'Pair (', excited_state%pair(ipair)%i, ',', &
263 excited_state%pair(ipair)%a, '; k =', excited_state%pair(ipair)%kk, ') is not valid.'
264 call messages_fatal(1, namespace=namespace)
265 end if
266
267 ! Now, we check that there are no repetitions:
268 do jpair = 1, ipair - 1
269 ok = .not. pair_is_eq(excited_state%pair(ipair), excited_state%pair(jpair))
270 if (.not. ok) then
271 write(message(1),'(a6,i3,a1,i3,a8,i1,a)') 'Pair (', excited_state%pair(ipair)%i, ',', &
272 excited_state%pair(ipair)%a, '; k =', excited_state%pair(ipair)%kk, ') is repeated in the file.'
273 call messages_fatal(1, namespace=namespace)
274 end if
275 end do
276
277 end do
278
279 ! Now we point to the ground state from which the excited state is defined.
280 excited_state%st => ground_state
281
282 ! Check the normalization.
283 dump = sum(excited_state%weight(1:excited_state%n_pairs)**2)
284 if (.not. abs(dump - m_one) < 1.0e-5_real64) then
285 excited_state%weight(1:excited_state%n_pairs) = excited_state%weight(1:excited_state%n_pairs) / sqrt(dump)
286 message(1) = 'The excited state in file "'//trim(filename)//'" was not normalized.'
287 call messages_warning(1, namespace=namespace)
288 end if
289
290 call io_close(iunit)
291
292 safe_deallocate_a(n_filled)
293 safe_deallocate_a(n_partially_filled)
294 safe_deallocate_a(n_half_filled)
295 safe_deallocate_a(n_empty)
296 safe_deallocate_a(filled)
297 safe_deallocate_a(partially_filled)
298 safe_deallocate_a(half_filled)
299 pop_sub(excited_states_init)
300 end subroutine excited_states_init
301
302
303 ! ---------------------------------------------------------
305 subroutine excited_states_kill(excited_state)
306 type(excited_states_t), intent(inout) :: excited_state
307
308 push_sub(excited_states_kill)
309
310 nullify(excited_state%st)
311 safe_deallocate_a(excited_state%pair)
312 safe_deallocate_a(excited_state%weight)
313
314 pop_sub(excited_states_kill)
315 end subroutine excited_states_kill
316
317
318 ! ---------------------------------------------------------
319 subroutine excited_states_output(excited_state, dirname, namespace)
320 type(excited_states_t), intent(in) :: excited_state
321 character(len=*), intent(in) :: dirname
322 type(namespace_t), intent(in) :: namespace
323
324 integer :: iunit, ipair
325
326 push_sub(excited_states_output)
327
328 iunit = io_open(trim(dirname)//'/excitations', namespace, action = 'write', status = 'replace')
329 do ipair = 1, excited_state%n_pairs
330 write(iunit, '(3i5,es20.12)') excited_state%pair(ipair)%i, excited_state%pair(ipair)%a, &
331 excited_state%pair(ipair)%kk, excited_state%weight(ipair)
332 end do
333
334 call io_close(iunit)
335 pop_sub(excited_states_output)
336 end subroutine excited_states_output
337
338
339 ! ---------------------------------------------------------
340 logical function pair_is_eq(pair1, pair2) result(res)
341 type(states_pair_t), intent(in) :: pair1, pair2
342
343 res = (pair1%i == pair2%i) .and. (pair1%a == pair2%a) .and. (pair1%kk == pair2%kk)
344 end function pair_is_eq
345
346#include "undef.F90"
347#include "real.F90"
348#include "excited_states_inc.F90"
349
350#include "undef.F90"
351#include "complex.F90"
352#include "excited_states_inc.F90"
353#include "undef.F90"
354
355end module excited_states_oct_m
356
357!! Local Variables:
358!! mode: f90
359!! coding: utf-8
360!! End:
double sqrt(double __x) __attribute__((__nothrow__
integer, parameter, public unpolarized
Parameters...
integer, parameter, public spinors
integer, parameter, public spin_polarized
real(real64) function dstates_elec_mpdotp_x(namespace, mesh, excited_state, st, mat)
Returns the dot product of two many-body states; the first one is an "excited_state".
subroutine, public zstates_elec_matrix_swap(mat, pair)
The matrix mat should contain the dot products between two states. One of them (the one operating on ...
complex(real64) function zstates_elec_mpdotp_g(namespace, mesh, st1, st2, mat)
Returns the dot product of two many-body states st1 and st2.
subroutine, public excited_states_output(excited_state, dirname, namespace)
real(real64) function dstates_elec_mpdotp_g(namespace, mesh, st1, st2, mat)
Returns the dot product of two many-body states st1 and st2.
logical function pair_is_eq(pair1, pair2)
complex(real64) function zstates_elec_mpmatrixelement_g(namespace, mesh, st1, st2, opst2)
Returns <st1 | O | st2>, where both st1 and st2 are Slater determinants represented by states_elec_t ...
subroutine, public excited_states_kill(excited_state)
Kills an excited_state structure.
complex(real64) function zstates_elec_mpdotp_x(namespace, mesh, excited_state, st, mat)
Returns the dot product of two many-body states; the first one is an "excited_state".
subroutine, public dstates_elec_matrix_swap(mat, pair)
The matrix mat should contain the dot products between two states. One of them (the one operating on ...
real(real64) function dstates_elec_mpmatrixelement_g(namespace, mesh, st1, st2, opst2)
Returns <st1 | O | st2>, where both st1 and st2 are Slater determinants represented by states_elec_t ...
subroutine, public excited_states_init(excited_state, ground_state, filename, namespace)
Fills in an excited_state structure, by reading a file called "filename". This file describes the "pr...
real(real64), parameter, public m_one
Definition: global.F90:188
Definition: io.F90:114
subroutine, public io_close(iunit, grp)
Definition: io.F90:468
subroutine, public io_skip_header(iunit)
Definition: io.F90:679
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:395
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:543
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 occupied_states(st, namespace, ik, n_filled, n_partially_filled, n_half_filled, filled, partially_filled, half_filled)
return information about occupied orbitals in many-body state
int true(void)