| 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., 59 Temple Place - Suite 330, Boston, MA |
|---|
| 16 | !! 02111-1307, USA. |
|---|
| 17 | !! |
|---|
| 18 | !! $Id$ |
|---|
| 19 | |
|---|
| 20 | #include "global.h" |
|---|
| 21 | |
|---|
| 22 | module casida_m |
|---|
| 23 | use datasets_m |
|---|
| 24 | use excited_states_m |
|---|
| 25 | use global_m |
|---|
| 26 | use hamiltonian_m |
|---|
| 27 | use io_m |
|---|
| 28 | use lib_adv_alg_m |
|---|
| 29 | use lib_oct_m |
|---|
| 30 | use lib_oct_parser_m |
|---|
| 31 | use math_m |
|---|
| 32 | use mesh_function_m |
|---|
| 33 | use mesh_m |
|---|
| 34 | use messages_m |
|---|
| 35 | use mpi_m |
|---|
| 36 | use multicomm_m |
|---|
| 37 | use output_m |
|---|
| 38 | use poisson_m |
|---|
| 39 | use restart_m |
|---|
| 40 | use states_m |
|---|
| 41 | use system_m |
|---|
| 42 | use units_m |
|---|
| 43 | use xc_m |
|---|
| 44 | |
|---|
| 45 | implicit none |
|---|
| 46 | |
|---|
| 47 | private |
|---|
| 48 | public :: casida_run |
|---|
| 49 | |
|---|
| 50 | integer, parameter :: & |
|---|
| 51 | CASIDA_EPS_DIFF = 1, & |
|---|
| 52 | CASIDA_PETERSILKA = 2, & |
|---|
| 53 | CASIDA_CASIDA = 3 |
|---|
| 54 | |
|---|
| 55 | type casida_t |
|---|
| 56 | integer :: type ! CASIDA_EPS_DIFF | CASIDA_PETERSILKA | CASIDA_CASIDA |
|---|
| 57 | |
|---|
| 58 | integer, pointer :: n_occ(:) ! number of occupied states |
|---|
| 59 | integer, pointer :: n_unocc(:) ! number of unoccupied states |
|---|
| 60 | character(len=80) :: wfn_list |
|---|
| 61 | |
|---|
| 62 | integer :: n_pairs ! number of pairs to take into acount |
|---|
| 63 | type(states_pair_t), pointer :: pair(:) |
|---|
| 64 | |
|---|
| 65 | FLOAT, pointer :: mat(:,:) ! general purpose matrix |
|---|
| 66 | FLOAT, pointer :: w(:) ! The excitation energies. |
|---|
| 67 | FLOAT, pointer :: tm(:, :) ! The transition matrix elements (between the many-particle states) |
|---|
| 68 | FLOAT, pointer :: f(:) ! The (dipole) strengths |
|---|
| 69 | FLOAT, pointer :: s(:) ! The diagonal part of the S-matrix |
|---|
| 70 | |
|---|
| 71 | logical :: parallel_in_eh_pairs |
|---|
| 72 | type(mpi_grp_t) :: mpi_grp |
|---|
| 73 | end type casida_t |
|---|
| 74 | |
|---|
| 75 | contains |
|---|
| 76 | |
|---|
| 77 | ! --------------------------------------------------------- |
|---|
| 78 | subroutine casida_run(sys, h, fromScratch) |
|---|
| 79 | type(system_t), intent(inout) :: sys |
|---|
| 80 | type(hamiltonian_t), intent(inout) :: h |
|---|
| 81 | logical, intent(inout) :: fromScratch |
|---|
| 82 | |
|---|
| 83 | type(casida_t) :: cas |
|---|
| 84 | integer :: i, ierr, kpoints, dim, nst, n_filled, n_partially_filled, n_half_filled |
|---|
| 85 | character(len=80) :: trandens |
|---|
| 86 | |
|---|
| 87 | call push_sub('casida.casida_run') |
|---|
| 88 | |
|---|
| 89 | message(1) = 'Info: Starting linear response calculation.' |
|---|
| 90 | call write_info(1) |
|---|
| 91 | |
|---|
| 92 | call restart_look(trim(tmpdir)//'restart_gs', sys%gr%m, kpoints, dim, nst, ierr) |
|---|
| 93 | if(ierr.ne.0) then |
|---|
| 94 | message(1) = 'Could not properly read wave-functions from "'//trim(tmpdir)//'restart_gs".' |
|---|
| 95 | call write_fatal(1) |
|---|
| 96 | end if |
|---|
| 97 | |
|---|
| 98 | if(sys%st%d%ispin == SPINORS) then |
|---|
| 99 | message(1) = 'Linear response TDDFT ("Casida" mode) is not implemented for spinors-DFT.' |
|---|
| 100 | call write_fatal(1) |
|---|
| 101 | end if |
|---|
| 102 | |
|---|
| 103 | sys%st%nst = nst |
|---|
| 104 | sys%st%st_end = nst |
|---|
| 105 | deallocate(sys%st%eigenval, sys%st%occ) |
|---|
| 106 | |
|---|
| 107 | call states_allocate_wfns(sys%st, sys%gr%m) |
|---|
| 108 | |
|---|
| 109 | ALLOCATE(sys%st%eigenval(sys%st%nst, sys%st%d%nik), sys%st%nst*sys%st%d%nik) |
|---|
| 110 | ALLOCATE(sys%st%occ(sys%st%nst, sys%st%d%nik), sys%st%nst*sys%st%d%nik) |
|---|
| 111 | |
|---|
| 112 | if(sys%st%d%ispin == SPINORS) then |
|---|
| 113 | ALLOCATE(sys%st%spin(3, sys%st%nst, sys%st%d%nik), sys%st%nst*sys%st%d%nik*3) |
|---|
| 114 | sys%st%spin = M_ZERO |
|---|
| 115 | end if |
|---|
| 116 | sys%st%eigenval = huge(REAL_PRECISION) |
|---|
| 117 | sys%st%occ = M_ZERO |
|---|
| 118 | |
|---|
| 119 | call restart_read(trim(tmpdir)//'restart_gs', sys%st, sys%gr, sys%geo, ierr) |
|---|
| 120 | if(ierr.ne.0) then |
|---|
| 121 | message(1) = 'Could not properly read wave-functions from "'//trim(tmpdir)//'restart_gs".' |
|---|
| 122 | call write_fatal(1) |
|---|
| 123 | end if |
|---|
| 124 | |
|---|
| 125 | ALLOCATE(cas%n_occ(sys%st%d%nspin), sys%st%d%nspin) |
|---|
| 126 | ALLOCATE(cas%n_unocc(sys%st%d%nspin), sys%st%d%nspin) |
|---|
| 127 | |
|---|
| 128 | cas%n_occ(:) = 0 |
|---|
| 129 | do i = 1, sys%st%d%nspin |
|---|
| 130 | call occupied_states(sys%st, i, n_filled, n_partially_filled, n_half_filled) |
|---|
| 131 | cas%n_occ(i) = n_filled + n_partially_filled + n_half_filled |
|---|
| 132 | cas%n_unocc(i) = sys%st%nst - cas%n_occ(i) |
|---|
| 133 | end do |
|---|
| 134 | |
|---|
| 135 | select case(sys%st%d%ispin) |
|---|
| 136 | case(UNPOLARIZED) |
|---|
| 137 | write(message(1),'(a,i4,a)') "Info: Found",cas%n_occ(1)," occupied states." |
|---|
| 138 | write(message(2),'(a,i4,a)') "Info: Found",cas%n_unocc(1)," unoccupied states." |
|---|
| 139 | call write_info(2) |
|---|
| 140 | case(SPIN_POLARIZED) |
|---|
| 141 | write(message(1),'(a,i4,a)') "Info: Found",cas%n_occ(1)," occupied states with spin up." |
|---|
| 142 | write(message(2),'(a,i4,a)') "Info: Found",cas%n_unocc(1)," unoccupied states with spin up." |
|---|
| 143 | write(message(3),'(a,i4,a)') "Info: Found",cas%n_occ(2)," occupied states with spin down." |
|---|
| 144 | write(message(4),'(a,i4,a)') "Info: Found",cas%n_unocc(2)," unoccupied states with spin down." |
|---|
| 145 | call write_info(4) |
|---|
| 146 | end select |
|---|
| 147 | |
|---|
| 148 | |
|---|
| 149 | ! setup Hamiltonian |
|---|
| 150 | message(1) = 'Info: Setting up Hamiltonian.' |
|---|
| 151 | call write_info(1) |
|---|
| 152 | call system_h_setup(sys, h) |
|---|
| 153 | |
|---|
| 154 | !%Variable LinearResponseKohnShamStates |
|---|
| 155 | !%Type string |
|---|
| 156 | !%Section Linear Response::Casida |
|---|
| 157 | !%Description |
|---|
| 158 | !% The calculation of the excitation spectrum of a system in the frequency-domain |
|---|
| 159 | !% formulation of linear-response time-dependent density functional theory (TDDFT) |
|---|
| 160 | !% implies the use of a basis set of occupied/unoccupied Kohn-Sham orbitals. This |
|---|
| 161 | !% basis set should, in principle, include all pairs formed by all occupied states, |
|---|
| 162 | !% and an infinite number of unoccupied states. In practice, one has to truncate this |
|---|
| 163 | !% basis set, selecting a number of occupied and unoccupied states that will form the |
|---|
| 164 | !% pairs. These states are specified with this variable. If there are, say, 10 occupied |
|---|
| 165 | !% states, and one sets this variable to the value "10-18", this means that occupied |
|---|
| 166 | !% states from 10 to 15, and unoccupied states from 16 to 18 will be considered. |
|---|
| 167 | !% |
|---|
| 168 | !% This variable is a string in list form, i.e. expressions such as "1,2-5,8-15" are |
|---|
| 169 | !% valid. You should include a non-null number of unoccupied states and a non-null number |
|---|
| 170 | !% of occupied states. |
|---|
| 171 | !%End |
|---|
| 172 | call loct_parse_string(check_inp('LinearResponseKohnShamStates'), "1-1024", cas%wfn_list) |
|---|
| 173 | write(message(1),'(a,a)') "Info: States that form the basis: ",trim(cas%wfn_list) |
|---|
| 174 | Call write_info(1) |
|---|
| 175 | |
|---|
| 176 | !%Variable LinearResponseTransitionDensities |
|---|
| 177 | !%Type string |
|---|
| 178 | !%Section Linear Response::Casida |
|---|
| 179 | !%Description |
|---|
| 180 | !% Specifies which transition densities are to be calculated and written down. The |
|---|
| 181 | !% transition density for the many-body state n will be written to a file called |
|---|
| 182 | !% linear/rho0n. |
|---|
| 183 | !% |
|---|
| 184 | !% By default, no transition density is calculated. |
|---|
| 185 | !% |
|---|
| 186 | !% This variable is a string in list form, i.e. expressions such as "1,2-5,8-15" are |
|---|
| 187 | !% valid. |
|---|
| 188 | !%End |
|---|
| 189 | call loct_parse_string(check_inp('LinearResponseTransitionDensities'), "0", trandens) |
|---|
| 190 | |
|---|
| 191 | ! Initialize structure |
|---|
| 192 | call casida_type_init(cas, sys%gr%sb%dim, sys%st%d%nspin, sys%mc) |
|---|
| 193 | |
|---|
| 194 | if(fromScratch) call loct_rm(trim(tmpdir)//'restart_casida') |
|---|
| 195 | |
|---|
| 196 | ! First, print the differences between KS eigenvalues (first approximation to the |
|---|
| 197 | ! excitation energies, or rather, to the DOS. |
|---|
| 198 | message(1) = "Info: Approximating resonance energies through KS eigenvalue differences" |
|---|
| 199 | call write_info(1) |
|---|
| 200 | cas%type = CASIDA_EPS_DIFF |
|---|
| 201 | call casida_work(sys, h, cas) |
|---|
| 202 | call casida_write(cas, 'eps-diff') |
|---|
| 203 | |
|---|
| 204 | ! Then, calculate the excitation energies by making use of the Petersilka approximation |
|---|
| 205 | message(1) = "Info: Calculating resonance energies a la Petersilka" |
|---|
| 206 | call write_info(1) |
|---|
| 207 | cas%type = CASIDA_PETERSILKA |
|---|
| 208 | call casida_work(sys, h, cas) |
|---|
| 209 | call casida_write(cas, 'petersilka') |
|---|
| 210 | |
|---|
| 211 | ! And finally, solve the full Casida problem. |
|---|
| 212 | message(1) = "Info: Calculating resonance energies a la Casida" |
|---|
| 213 | call write_info(1) |
|---|
| 214 | cas%type = CASIDA_CASIDA |
|---|
| 215 | call casida_work(sys, h, cas) |
|---|
| 216 | call casida_write(cas, 'casida') |
|---|
| 217 | |
|---|
| 218 | ! Calculate and write the transition matrix |
|---|
| 219 | if (sys%st%d%wfs_type == M_REAL) then |
|---|
| 220 | call dget_transition_densities(cas, sys, trandens) |
|---|
| 221 | else |
|---|
| 222 | call zget_transition_densities(cas, sys, trandens) |
|---|
| 223 | end if |
|---|
| 224 | |
|---|
| 225 | call casida_type_end(cas) |
|---|
| 226 | |
|---|
| 227 | call pop_sub() |
|---|
| 228 | end subroutine casida_run |
|---|
| 229 | |
|---|
| 230 | ! --------------------------------------------------------- |
|---|
| 231 | ! allocates stuff, and constructs the arrays pair_i and pair_j |
|---|
| 232 | subroutine casida_type_init(cas, dim, nspin, mc) |
|---|
| 233 | type(casida_t), intent(inout) :: cas |
|---|
| 234 | integer, intent(in) :: dim, nspin |
|---|
| 235 | type(multicomm_t), intent(in) :: mc |
|---|
| 236 | |
|---|
| 237 | integer :: i, a, j, k |
|---|
| 238 | |
|---|
| 239 | call push_sub('casida.casida_type_init') |
|---|
| 240 | |
|---|
| 241 | ! count pairs |
|---|
| 242 | cas%n_pairs = 0 |
|---|
| 243 | do k = 1, nspin |
|---|
| 244 | do a = cas%n_occ(k)+1, cas%n_occ(k) + cas%n_unocc(k) |
|---|
| 245 | if(loct_isinstringlist(a, cas%wfn_list)) then |
|---|
| 246 | do i = 1, cas%n_occ(k) |
|---|
| 247 | if(loct_isinstringlist(i, cas%wfn_list)) then |
|---|
| 248 | cas%n_pairs = cas%n_pairs + 1 |
|---|
| 249 | end if |
|---|
| 250 | end do |
|---|
| 251 | end if |
|---|
| 252 | end do |
|---|
| 253 | end do |
|---|
| 254 | |
|---|
| 255 | if(cas%n_pairs < 1) then |
|---|
| 256 | message(1) = "Error: Maybe there are no unoccupied states?" |
|---|
| 257 | call write_fatal(1) |
|---|
| 258 | end if |
|---|
| 259 | |
|---|
| 260 | ! allocate stuff |
|---|
| 261 | ALLOCATE(cas%pair(cas%n_pairs), cas%n_pairs) |
|---|
| 262 | ALLOCATE(cas%mat(cas%n_pairs, cas%n_pairs), cas%n_pairs*cas%n_pairs) |
|---|
| 263 | ALLOCATE(cas%tm(cas%n_pairs, dim), cas%n_pairs*dim) |
|---|
| 264 | ALLOCATE(cas%f(cas%n_pairs), cas%n_pairs) |
|---|
| 265 | ALLOCATE(cas%s(cas%n_pairs), cas%n_pairs) |
|---|
| 266 | ALLOCATE(cas%w(cas%n_pairs), cas%n_pairs) |
|---|
| 267 | |
|---|
| 268 | ! create pairs |
|---|
| 269 | j = 1 |
|---|
| 270 | do k = 1, nspin |
|---|
| 271 | do a = cas%n_occ(k)+1, cas%n_occ(k) + cas%n_unocc(k) |
|---|
| 272 | if(loct_isinstringlist(a, cas%wfn_list)) then |
|---|
| 273 | do i = 1, cas%n_occ(k) |
|---|
| 274 | if(loct_isinstringlist(i, cas%wfn_list)) then |
|---|
| 275 | cas%pair(j)%i = i |
|---|
| 276 | cas%pair(j)%a = a |
|---|
| 277 | cas%pair(j)%sigma = k |
|---|
| 278 | j = j + 1 |
|---|
| 279 | end if |
|---|
| 280 | end do |
|---|
| 281 | end if |
|---|
| 282 | end do |
|---|
| 283 | end do |
|---|
| 284 | |
|---|
| 285 | ! now let us take care of initializing the parallel stuff |
|---|
| 286 | cas%parallel_in_eh_pairs = multicomm_strategy_is_parallel(mc, P_STRATEGY_OTHER) |
|---|
| 287 | if(cas%parallel_in_eh_pairs) then |
|---|
| 288 | call mpi_grp_init(cas%mpi_grp, mc%group_comm(P_STRATEGY_OTHER)) |
|---|
| 289 | else |
|---|
| 290 | call mpi_grp_init(cas%mpi_grp, -1) |
|---|
| 291 | end if |
|---|
| 292 | |
|---|
| 293 | call pop_sub() |
|---|
| 294 | end subroutine casida_type_init |
|---|
| 295 | |
|---|
| 296 | |
|---|
| 297 | ! --------------------------------------------------------- |
|---|
| 298 | subroutine casida_type_end(cas) |
|---|
| 299 | type(casida_t), intent(inout) :: cas |
|---|
| 300 | call push_sub('casida.casida_type_end') |
|---|
| 301 | |
|---|
| 302 | ASSERT(associated(cas%pair)) |
|---|
| 303 | deallocate(cas%pair, cas%mat, cas%tm, cas%s, cas%f, cas%w) |
|---|
| 304 | nullify (cas%pair, cas%mat, cas%tm, cas%s, cas%f, cas%w) |
|---|
| 305 | |
|---|
| 306 | call pop_sub() |
|---|
| 307 | end subroutine casida_type_end |
|---|
| 308 | |
|---|
| 309 | |
|---|
| 310 | ! --------------------------------------------------------- |
|---|
| 311 | ! this subroutine calculates electronic excitation energies using |
|---|
| 312 | ! the matrix formulation of M. Petersilka, or of M. Casida |
|---|
| 313 | subroutine casida_work(sys, h, cas) |
|---|
| 314 | type(system_t), target, intent(inout) :: sys |
|---|
| 315 | type(hamiltonian_t), intent(in) :: h |
|---|
| 316 | type(casida_t), intent(inout) :: cas |
|---|
| 317 | |
|---|
| 318 | logical, allocatable :: saved_K(:, :) ! which matrix elements have been loaded |
|---|
| 319 | type(states_t), pointer :: st |
|---|
| 320 | type(mesh_t), pointer :: m |
|---|
| 321 | |
|---|
| 322 | FLOAT, allocatable :: rho(:, :), fxc(:,:,:), pot(:) |
|---|
| 323 | integer :: is, j_old, b_old, mu_old |
|---|
| 324 | |
|---|
| 325 | call push_sub('casida.casida_work') |
|---|
| 326 | |
|---|
| 327 | ! sanity checks |
|---|
| 328 | ASSERT(cas%type>=CASIDA_EPS_DIFF.and.cas%type<=CASIDA_CASIDA) |
|---|
| 329 | |
|---|
| 330 | ! some shortcuts |
|---|
| 331 | st => sys%st |
|---|
| 332 | m => sys%gr%m |
|---|
| 333 | |
|---|
| 334 | ! initialize stuff |
|---|
| 335 | ALLOCATE(saved_K(cas%n_pairs, cas%n_pairs), cas%n_pairs*cas%n_pairs) |
|---|
| 336 | cas%mat = M_ZERO |
|---|
| 337 | saved_K = .false. |
|---|
| 338 | cas%tm = M_ZERO |
|---|
| 339 | cas%f = M_ZERO |
|---|
| 340 | cas%w = M_ZERO |
|---|
| 341 | cas%s = M_ZERO |
|---|
| 342 | |
|---|
| 343 | ! load saved matrix elements |
|---|
| 344 | call load_saved() |
|---|
| 345 | |
|---|
| 346 | ! This is to be allocated here, and is used inside K_term. |
|---|
| 347 | ALLOCATE(pot(m%np), m%np) |
|---|
| 348 | j_old = -1; b_old = -1; mu_old = -1 |
|---|
| 349 | |
|---|
| 350 | ! We calculate here the kernel, since it will be needed later. |
|---|
| 351 | ALLOCATE(rho(m%np, st%d%nspin), m%np*st%d%nspin) |
|---|
| 352 | ALLOCATE(fxc(m%np, st%d%nspin, st%d%nspin), m%np*st%d%nspin*st%d%nspin) |
|---|
| 353 | rho = M_ZERO; fxc = M_ZERO |
|---|
| 354 | |
|---|
| 355 | if(associated(st%rho_core)) then |
|---|
| 356 | do is = 1, st%d%spin_channels |
|---|
| 357 | rho(1:m%np, is) = st%rho(1:m%np, is) + st%rho_core(1:m%np)/st%d%spin_channels |
|---|
| 358 | end do |
|---|
| 359 | else |
|---|
| 360 | rho(1:m%np, 1:st%d%nspin) = st%rho(1:m%np, 1:st%d%nspin) |
|---|
| 361 | end if |
|---|
| 362 | call xc_get_fxc(sys%ks%xc, m, rho, st%d%ispin, fxc) |
|---|
| 363 | |
|---|
| 364 | select case(cas%type) |
|---|
| 365 | case(CASIDA_EPS_DIFF) |
|---|
| 366 | call solve_petersilka() |
|---|
| 367 | case(CASIDA_PETERSILKA) |
|---|
| 368 | call solve_petersilka() |
|---|
| 369 | case(CASIDA_CASIDA) |
|---|
| 370 | call solve_casida() |
|---|
| 371 | end select |
|---|
| 372 | |
|---|
| 373 | ! clean up |
|---|
| 374 | deallocate(fxc, rho, pot, saved_K) |
|---|
| 375 | |
|---|
| 376 | call pop_sub() |
|---|
| 377 | contains |
|---|
| 378 | |
|---|
| 379 | ! --------------------------------------------------------- |
|---|
| 380 | subroutine solve_petersilka |
|---|
| 381 | integer :: ia, iunit, k |
|---|
| 382 | FLOAT :: f |
|---|
| 383 | FLOAT, allocatable :: deltav(:), x(:) |
|---|
| 384 | |
|---|
| 385 | call push_sub('casida.solve_petersilka') |
|---|
| 386 | |
|---|
| 387 | ! initialize progress bar |
|---|
| 388 | if(mpi_grp_is_root(mpi_world)) call loct_progress_bar(-1, cas%n_pairs) |
|---|
| 389 | |
|---|
| 390 | ! file to save matrix elements |
|---|
| 391 | iunit = io_open(trim(tmpdir)//'restart_casida', action='write', position='append', is_tmp=.true.) |
|---|
| 392 | |
|---|
| 393 | do ia = 1, cas%n_pairs |
|---|
| 394 | cas%w(ia) = st%eigenval(cas%pair(ia)%a, cas%pair(ia)%sigma) - & |
|---|
| 395 | st%eigenval(cas%pair(ia)%i, cas%pair(ia)%sigma) |
|---|
| 396 | |
|---|
| 397 | if(cas%type == CASIDA_PETERSILKA) then |
|---|
| 398 | if(saved_K(ia, ia)) then |
|---|
| 399 | f = cas%mat(ia, ia) |
|---|
| 400 | else |
|---|
| 401 | f = K_term(cas%pair(ia), cas%pair(ia)) |
|---|
| 402 | write(iunit, *) ia, ia, f |
|---|
| 403 | end if |
|---|
| 404 | cas%w(ia) = cas%w(ia) + M_TWO*f |
|---|
| 405 | end if |
|---|
| 406 | |
|---|
| 407 | if(mpi_grp_is_root(mpi_world)) call loct_progress_bar(ia, cas%n_pairs) |
|---|
| 408 | end do |
|---|
| 409 | |
|---|
| 410 | ALLOCATE(x(cas%n_pairs), cas%n_pairs) |
|---|
| 411 | ALLOCATE(deltav(m%np), m%np) |
|---|
| 412 | do k = 1, m%sb%dim |
|---|
| 413 | |
|---|
| 414 | !WARNING: should x always be real? |
|---|
| 415 | x = dks_matrix_elements(cas, st, m, deltav) |
|---|
| 416 | |
|---|
| 417 | !FIXME: Calculate the oscillator strengths and matrix elements a la Petersilka |
|---|
| 418 | end do |
|---|
| 419 | deallocate(x, deltav) |
|---|
| 420 | |
|---|
| 421 | if(mpi_grp_is_root(mpi_world)) write(*, "(1x)") |
|---|
| 422 | |
|---|
| 423 | ! close restart file |
|---|
| 424 | call io_close(iunit) |
|---|
| 425 | call pop_sub() |
|---|
| 426 | end subroutine solve_petersilka |
|---|
| 427 | |
|---|
| 428 | |
|---|
| 429 | ! --------------------------------------------------------- |
|---|
| 430 | subroutine solve_casida() |
|---|
| 431 | FLOAT :: temp |
|---|
| 432 | integer :: ia, jb, k |
|---|
| 433 | integer :: max, actual, iunit, counter |
|---|
| 434 | FLOAT, allocatable :: deltav(:) |
|---|
| 435 | |
|---|
| 436 | FLOAT, allocatable :: dx(:), tmp(:,:) |
|---|
| 437 | CMPLX, allocatable :: zx(:) |
|---|
| 438 | type(states_pair_t), pointer :: p, q |
|---|
| 439 | #ifdef HAVE_MPI |
|---|
| 440 | FLOAT, allocatable :: mpi_mat(:,:) |
|---|
| 441 | #endif |
|---|
| 442 | |
|---|
| 443 | call push_sub('casida.solve_casida') |
|---|
| 444 | |
|---|
| 445 | max = (cas%n_pairs*(1 + cas%n_pairs)/2)/cas%mpi_grp%size |
|---|
| 446 | counter = 0 |
|---|
| 447 | actual = 0 |
|---|
| 448 | if(mpi_grp_is_root(mpi_world)) call loct_progress_bar(-1, max) |
|---|
| 449 | |
|---|
| 450 | if(.not.mpi_grp_is_root(mpi_world)) cas%mat = M_ZERO |
|---|
| 451 | |
|---|
| 452 | ! calculate the matrix elements of (v + fxc) |
|---|
| 453 | do jb = 1, cas%n_pairs |
|---|
| 454 | actual = actual + 1 |
|---|
| 455 | if(mod(actual, cas%mpi_grp%size) .ne. cas%mpi_grp%rank) cycle |
|---|
| 456 | do ia = jb, cas%n_pairs |
|---|
| 457 | counter = counter + 1 |
|---|
| 458 | ! if not loaded, then calculate matrix element |
|---|
| 459 | if(.not.saved_K(ia, jb)) then |
|---|
| 460 | cas%mat(ia, jb) = K_term(cas%pair(ia), cas%pair(jb)) |
|---|
| 461 | end if |
|---|
| 462 | if(jb /= ia) cas%mat(jb, ia) = cas%mat(ia, jb) ! the matrix is symmetric |
|---|
| 463 | end do |
|---|
| 464 | if(mpi_grp_is_root(mpi_world)) call loct_progress_bar(counter, max) |
|---|
| 465 | end do |
|---|
| 466 | |
|---|
| 467 | ! sum all matrix elements |
|---|
| 468 | #ifdef HAVE_MPI |
|---|
| 469 | if(cas%parallel_in_eh_pairs) then |
|---|
| 470 | ALLOCATE(mpi_mat(cas%n_pairs, cas%n_pairs), cas%n_pairs*cas%n_pairs) |
|---|
| 471 | call MPI_Allreduce(cas%mat(1,1), mpi_mat(1,1), cas%n_pairs**2, & |
|---|
| 472 | MPI_FLOAT, MPI_SUM, cas%mpi_grp%comm, mpi_err) |
|---|
| 473 | cas%mat = mpi_mat |
|---|
| 474 | deallocate(mpi_mat) |
|---|
| 475 | end if |
|---|
| 476 | #endif |
|---|
| 477 | !if(mpi_grp_is_root(cas%mpi_grp)) print *, "mat =", cas%mat |
|---|
| 478 | |
|---|
| 479 | ! all processors with the exception of the first are done |
|---|
| 480 | if (mpi_grp_is_root(cas%mpi_grp)) then |
|---|
| 481 | |
|---|
| 482 | ! complete progress bar |
|---|
| 483 | if(mpi_grp_is_root(mpi_world)) write(stdout, '(1x)') |
|---|
| 484 | |
|---|
| 485 | ! complete the matrix and output the restart file |
|---|
| 486 | iunit = io_open(trim(tmpdir)//'restart_casida', action='write', position='append', is_tmp=.true.) |
|---|
| 487 | do ia = 1, cas%n_pairs |
|---|
| 488 | p => cas%pair(ia) |
|---|
| 489 | temp = st%eigenval(p%a, p%sigma) - st%eigenval(p%i, p%sigma) |
|---|
| 490 | |
|---|
| 491 | do jb = ia, cas%n_pairs |
|---|
| 492 | q => cas%pair(jb) |
|---|
| 493 | if(.not.saved_K(ia, jb)) write(iunit, *) ia, jb, cas%mat(ia, jb) |
|---|
| 494 | |
|---|
| 495 | if(sys%st%d%ispin == UNPOLARIZED) then |
|---|
| 496 | cas%mat(ia, jb) = M_FOUR * sqrt(temp) * cas%mat(ia, jb) * & |
|---|
| 497 | sqrt(st%eigenval(q%a, 1) - st%eigenval(q%i, 1)) |
|---|
| 498 | else if(sys%st%d%ispin == SPIN_POLARIZED) then |
|---|
| 499 | cas%mat(ia, jb) = M_TWO * sqrt(temp) * cas%mat(ia, jb) * & |
|---|
| 500 | sqrt(st%eigenval(q%a, q%sigma) - st%eigenval(q%i, q%sigma)) |
|---|
| 501 | end if |
|---|
| 502 | |
|---|
| 503 | if(jb /= ia) cas%mat(jb, ia) = cas%mat(ia, jb) ! the matrix is symmetric |
|---|
| 504 | end do |
|---|
| 505 | cas%mat(ia, ia) = temp**2 + cas%mat(ia, ia) |
|---|
| 506 | end do |
|---|
| 507 | call io_close(iunit) |
|---|
| 508 | ALLOCATE(tmp(1:cas%n_pairs,1:cas%n_pairs),cas%n_pairs*cas%n_pairs) |
|---|
| 509 | tmp(1:cas%n_pairs,1:cas%n_pairs) = cas%mat(1:cas%n_pairs,1:cas%n_pairs) |
|---|
| 510 | ! now we diagonalize the matrix |
|---|
| 511 | call lalg_eigensolve(cas%n_pairs, tmp, cas%mat, cas%w) |
|---|
| 512 | DEALLOCATE(tmp) |
|---|
| 513 | |
|---|
| 514 | do ia = 1, cas%n_pairs |
|---|
| 515 | if(cas%w(ia) < M_ZERO) then |
|---|
| 516 | write(message(1),'(a,i4,a)') 'For whatever reason, the excitation energy',ia,' is negative.' |
|---|
| 517 | write(message(2),'(a)') 'This should not happen.' |
|---|
| 518 | call write_warning(2) |
|---|
| 519 | cas%w(ia) = M_ZERO |
|---|
| 520 | else |
|---|
| 521 | cas%w(ia) = sqrt(cas%w(ia)) |
|---|
| 522 | end if |
|---|
| 523 | end do |
|---|
| 524 | |
|---|
| 525 | ! And let us now get the S matrix... |
|---|
| 526 | do ia = 1, cas%n_pairs |
|---|
| 527 | if(sys%st%d%ispin == UNPOLARIZED) then |
|---|
| 528 | cas%s(ia) = M_HALF / ( st%eigenval(cas%pair(ia)%a, 1) - st%eigenval(cas%pair(ia)%i, 1) ) |
|---|
| 529 | elseif(sys%st%d%ispin == SPIN_POLARIZED) then |
|---|
| 530 | cas%s(ia) = M_ONE / ( st%eigenval(cas%pair(ia)%a, cas%pair(ia)%sigma) - & |
|---|
| 531 | st%eigenval(cas%pair(ia)%i, cas%pair(ia)%sigma) ) |
|---|
| 532 | end if |
|---|
| 533 | end do |
|---|
| 534 | |
|---|
| 535 | ALLOCATE(deltav(m%np), m%np) |
|---|
| 536 | if (st%d%wfs_type == M_REAL) then |
|---|
| 537 | ALLOCATE(dx(cas%n_pairs), cas%n_pairs) |
|---|
| 538 | do k = 1, m%sb%dim |
|---|
| 539 | deltav(1:m%np) = m%x(1:m%np, k) |
|---|
| 540 | ! let us get now the x vector. |
|---|
| 541 | dx = dks_matrix_elements(cas, st, m, deltav) |
|---|
| 542 | ! And now we are able to get the transition matrix elements between many-electron states. |
|---|
| 543 | do ia = 1, cas%n_pairs |
|---|
| 544 | cas%tm(ia, k) = dtransition_matrix_element(cas, ia, dx) |
|---|
| 545 | end do |
|---|
| 546 | end do |
|---|
| 547 | deallocate(deltav, dx) |
|---|
| 548 | else |
|---|
| 549 | ALLOCATE(zx(cas%n_pairs), cas%n_pairs) |
|---|
| 550 | do k = 1, m%sb%dim |
|---|
| 551 | deltav(1:m%np) = m%x(1:m%np, k) |
|---|
| 552 | ! let us get now the x vector. |
|---|
| 553 | zx = zks_matrix_elements(cas, st, m, deltav) |
|---|
| 554 | ! And now we are able to get the transition matrix elements between many-electron states. |
|---|
| 555 | do ia = 1, cas%n_pairs |
|---|
| 556 | cas%tm(ia, k) = ztransition_matrix_element(cas, ia, zx) |
|---|
| 557 | end do |
|---|
| 558 | end do |
|---|
| 559 | deallocate(deltav, zx) |
|---|
| 560 | end if |
|---|
| 561 | |
|---|
| 562 | |
|---|
| 563 | ! And the oscillatory strengths. |
|---|
| 564 | do ia = 1, cas%n_pairs |
|---|
| 565 | cas%f(ia) = (M_TWO/m%sb%dim) * cas%w(ia) * sum( (abs(cas%tm(ia, :)))**2 ) |
|---|
| 566 | end do |
|---|
| 567 | |
|---|
| 568 | end if |
|---|
| 569 | |
|---|
| 570 | #if defined(HAVE_MPI) |
|---|
| 571 | if(cas%parallel_in_eh_pairs) then |
|---|
| 572 | call MPI_Barrier(cas%mpi_grp%comm, mpi_err) |
|---|
| 573 | end if |
|---|
| 574 | #endif |
|---|
| 575 | |
|---|
| 576 | call pop_sub() |
|---|
| 577 | end subroutine solve_casida |
|---|
| 578 | |
|---|
| 579 | |
|---|
| 580 | ! return the matrix element of <i(p),a(p)|v + fxc|j(q),b(q)> |
|---|
| 581 | function K_term(p, q) |
|---|
| 582 | FLOAT :: K_term |
|---|
| 583 | type(states_pair_t), intent(in) :: p, q |
|---|
| 584 | |
|---|
| 585 | integer :: i, j, sigma, a, b, mu |
|---|
| 586 | FLOAT, allocatable :: rho_i(:), rho_j(:) |
|---|
| 587 | |
|---|
| 588 | i = p%i; a = p%a; sigma = p%sigma |
|---|
| 589 | j = q%i; b = q%a; mu = q%sigma |
|---|
| 590 | |
|---|
| 591 | ALLOCATE(rho_i(m%np), m%np) |
|---|
| 592 | ALLOCATE(rho_j(m%np), m%np) |
|---|
| 593 | |
|---|
| 594 | if (st%d%wfs_type == M_REAL) then |
|---|
| 595 | rho_i(:) = st%dpsi(1:m%np, 1, i, sigma) * st%dpsi(1:m%np, 1, a, sigma) |
|---|
| 596 | rho_j(:) = st%dpsi(1:m%np, 1, j, mu) * st%dpsi(1:m%np, 1, b, mu) |
|---|
| 597 | else |
|---|
| 598 | rho_i(:) = st%zpsi(1:m%np, 1, i, sigma) * conjg(st%zpsi(1:m%np, 1, a, sigma)) |
|---|
| 599 | rho_j(:) = conjg(st%zpsi(1:m%np, 1, j, mu)) * st%zpsi(1:m%np, 1, b, mu) |
|---|
| 600 | end if |
|---|
| 601 | |
|---|
| 602 | ! first the Hartree part (only works for real wfs...) |
|---|
| 603 | if( j.ne.j_old .or. b.ne.b_old .or. mu.ne.mu_old) then |
|---|
| 604 | pot = M_ZERO |
|---|
| 605 | if( (.not.h%ip_app) ) call dpoisson_solve(sys%gr, pot, rho_j, all_nodes=.false.) |
|---|
| 606 | end if |
|---|
| 607 | |
|---|
| 608 | K_term = dmf_dotp(m, rho_i(:), pot(:)) |
|---|
| 609 | rho(1:m%np, 1) = rho_i(1:m%np) * rho_j(1:m%np) * fxc(1:m%np, sigma, mu) |
|---|
| 610 | K_term = K_term + dmf_integrate(m, rho(:, 1)) |
|---|
| 611 | |
|---|
| 612 | j_old = j; b_old = b; mu_old = mu |
|---|
| 613 | |
|---|
| 614 | deallocate(rho_i, rho_j) |
|---|
| 615 | end function K_term |
|---|
| 616 | |
|---|
| 617 | ! --------------------------------------------------------- |
|---|
| 618 | subroutine load_saved |
|---|
| 619 | integer :: iunit, err |
|---|
| 620 | integer :: ia, jb |
|---|
| 621 | FLOAT :: val |
|---|
| 622 | |
|---|
| 623 | call push_sub('casida.load_saved') |
|---|
| 624 | |
|---|
| 625 | iunit = io_open(trim(tmpdir)//'restart_casida', action='read', status='old', die=.false., is_tmp=.true.) |
|---|
| 626 | if( iunit <= 0) return |
|---|
| 627 | |
|---|
| 628 | do |
|---|
| 629 | read(iunit, fmt=*, iostat=err) ia, jb, val |
|---|
| 630 | if(err.ne.0) exit |
|---|
| 631 | if((ia > 0.and.ia <= cas%n_pairs) .and. (jb > 0.and.jb <= cas%n_pairs)) then |
|---|
| 632 | cas%mat(ia, jb) = val |
|---|
| 633 | saved_K(ia, jb) = .true. |
|---|
| 634 | cas%mat(jb, ia) = val |
|---|
| 635 | saved_K(jb, ia) = .true. |
|---|
| 636 | end if |
|---|
| 637 | end do |
|---|
| 638 | |
|---|
| 639 | if(iunit > 0) call io_close(iunit) |
|---|
| 640 | call pop_sub() |
|---|
| 641 | end subroutine load_saved |
|---|
| 642 | |
|---|
| 643 | end subroutine casida_work |
|---|
| 644 | |
|---|
| 645 | |
|---|
| 646 | ! --------------------------------------------------------- |
|---|
| 647 | subroutine casida_write(cas, filename) |
|---|
| 648 | type(casida_t), intent(in) :: cas |
|---|
| 649 | character(len=*), intent(in) :: filename |
|---|
| 650 | |
|---|
| 651 | character(len=5) :: str |
|---|
| 652 | integer :: iunit, ia, jb, dim |
|---|
| 653 | FLOAT :: temp |
|---|
| 654 | integer, allocatable :: ind(:) |
|---|
| 655 | FLOAT, allocatable :: w(:) |
|---|
| 656 | |
|---|
| 657 | if(.not.mpi_grp_is_root(cas%mpi_grp)) return |
|---|
| 658 | |
|---|
| 659 | call push_sub('casida.casida_write') |
|---|
| 660 | |
|---|
| 661 | dim = size(cas%tm, 2) |
|---|
| 662 | |
|---|
| 663 | ALLOCATE(w(cas%n_pairs), cas%n_pairs) |
|---|
| 664 | ALLOCATE(ind(cas%n_pairs), cas%n_pairs) |
|---|
| 665 | w = cas%w |
|---|
| 666 | call sort(w, ind) |
|---|
| 667 | |
|---|
| 668 | ! output excitation energies and oscillator strengths |
|---|
| 669 | call io_mkdir('linear') |
|---|
| 670 | iunit = io_open('linear/'//trim(filename), action='write') |
|---|
| 671 | |
|---|
| 672 | if(cas%type == CASIDA_EPS_DIFF) write(iunit, '(2a4)', advance='no') 'From', ' To ' |
|---|
| 673 | |
|---|
| 674 | select case(dim) |
|---|
| 675 | case(1); write(iunit, '(3(a15,1x))') 'E' , '<x>', '<f>' |
|---|
| 676 | case(2); write(iunit, '(4(a15,1x))') 'E' , '<x>', '<y>', '<f>' |
|---|
| 677 | case(3); write(iunit, '(5(a15,1x))') 'E' , '<x>', '<y>', '<z>', '<f>' |
|---|
| 678 | end select |
|---|
| 679 | do ia = 1, cas%n_pairs |
|---|
| 680 | if((cas%type==CASIDA_EPS_DIFF).or.(cas%type==CASIDA_PETERSILKA)) then |
|---|
| 681 | write(iunit, '(2i4)', advance='no') cas%pair(ind(ia))%i, cas%pair(ind(ia))%a |
|---|
| 682 | end if |
|---|
| 683 | write(iunit, '(5(es15.8,1x))') cas%w(ind(ia)) / units_out%energy%factor, & |
|---|
| 684 | cas%tm(ind(ia), 1:dim) / units_out%length%factor, cas%f(ind(ia)) |
|---|
| 685 | end do |
|---|
| 686 | call io_close(iunit) |
|---|
| 687 | |
|---|
| 688 | ! output eigenvectors in casida approach |
|---|
| 689 | |
|---|
| 690 | if(cas%type.ne.CASIDA_CASIDA) return |
|---|
| 691 | |
|---|
| 692 | call io_mkdir('linear/excitations') |
|---|
| 693 | do ia = 1, cas%n_pairs |
|---|
| 694 | write(str,'(i5.5)') ia |
|---|
| 695 | iunit = io_open('linear/excitations/'//trim(str), action='write') |
|---|
| 696 | ! First, a little header |
|---|
| 697 | write(iunit,'(a,es14.5)') '# Energy ['// trim(units_out%energy%abbrev) // '] = ', & |
|---|
| 698 | cas%w(ind(ia)) / units_out%energy%factor |
|---|
| 699 | write(iunit,'(a,es14.5)') '# <X> ['//trim(units_out%length%abbrev)// '] = ', & |
|---|
| 700 | cas%tm(ind(ia),1) / units_out%length%factor |
|---|
| 701 | if(dim > 1) & |
|---|
| 702 | write(iunit,'(a,es14.5)') '# <Y> ['//trim(units_out%length%abbrev)// '] = ', & |
|---|
| 703 | cas%tm(ind(ia),2) / units_out%length%factor |
|---|
| 704 | if(dim > 2) & |
|---|
| 705 | write(iunit,'(a,es14.5)') '# <Z> ['//trim(units_out%length%abbrev)// '] = ', & |
|---|
| 706 | cas%tm(ind(ia),3) / units_out%length%factor |
|---|
| 707 | |
|---|
| 708 | temp = M_ONE |
|---|
| 709 | ! I do not know what this does, or what is for. |
|---|
| 710 | !if( maxval(cas%mat(:, ind(ia))) < abs(minval(cas%mat(:, ind(ia)))) ) temp = -temp |
|---|
| 711 | |
|---|
| 712 | do jb = 1, cas%n_pairs |
|---|
| 713 | write(iunit,*) cas%pair(jb)%i, cas%pair(jb)%a, cas%pair(jb)%sigma, temp * cas%mat(jb, ind(ia)) |
|---|
| 714 | end do |
|---|
| 715 | call io_close(iunit) |
|---|
| 716 | end do |
|---|
| 717 | |
|---|
| 718 | deallocate(w, ind) |
|---|
| 719 | call pop_sub() |
|---|
| 720 | end subroutine casida_write |
|---|
| 721 | |
|---|
| 722 | |
|---|
| 723 | #include "undef.F90" |
|---|
| 724 | #include "real.F90" |
|---|
| 725 | #include "casida_inc.F90" |
|---|
| 726 | |
|---|
| 727 | #include "undef.F90" |
|---|
| 728 | #include "complex.F90" |
|---|
| 729 | #include "casida_inc.F90" |
|---|
| 730 | |
|---|
| 731 | end module casida_m |
|---|
| 732 | |
|---|
| 733 | !! Local Variables: |
|---|
| 734 | !! mode: f90 |
|---|
| 735 | !! coding: utf-8 |
|---|
| 736 | !! End: |
|---|