Octopus
rdmft.F90
Go to the documentation of this file.
1!! Copyright (C) 2012-2019 I. Theophilou, N. Helbig
2!! Copyright (C) 2019 F. Buchholz, M. Oliveira
3!!
4!! This program is free software; you can redistribute it and/or modify
5!! it under the terms of the GNU General Public License as published by
6!! the Free Software Foundation; either version 2, or (at your option)
7!! any later version.
8!!
9!! This program is distributed in the hope that it will be useful,
10!! but WITHOUT ANY WARRANTY; without even the implied warranty of
11!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12!! GNU General Public License for more details.
13!!
14!! You should have received a copy of the GNU General Public License
15!! along with this program; if not, write to the Free Software
16!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17!! 02110-1301, USA.
18!!
19
20#include "global.h"
21
22module rdmft_oct_m
23 use debug_oct_m
30 use energy_oct_m
32 use global_oct_m
33 use grid_oct_m
37 use io_oct_m
39 use ions_oct_m
40 use, intrinsic :: iso_fortran_env
42 use loct_oct_m
43 use math_oct_m
44 use mesh_oct_m
48 use mpi_oct_m
52 use output_oct_m
55 use parser_oct_m
60 use space_oct_m
65 use unit_oct_m
67 use v_ks_oct_m
68 use xc_oep_oct_m
69
70 implicit none
71
72 private
73 public :: &
74 rdm_t, &
75 rdmft_init, &
76 rdmft_end, &
78
79 type rdm_t
80 private
81 type(eigensolver_t) :: eigens
82 integer :: max_iter
83 integer :: iter
84 integer :: nst
85 integer :: n_twoint !number of unique two electron integrals
86 logical :: do_basis
87 logical :: hf
88 real(real64) :: mu
89 real(real64) :: occsum
90 real(real64) :: qtot
91 real(real64) :: scale_f
92 real(real64) :: toler
93 real(real64) :: conv_ener
94 real(real64) :: maxFO
95 real(real64) :: tolerFO
96
97 real(real64), allocatable :: eone(:)
98 real(real64), allocatable :: eone_int(:,:)
99 real(real64), allocatable :: twoint(:)
100 real(real64), allocatable :: hartree(:,:)
101 real(real64), allocatable :: exchange(:,:)
102 real(real64), allocatable :: evalues(:)
103 real(real64), allocatable :: vecnat(:,:)
104 real(real64), allocatable :: Coul(:,:,:)
105 real(real64), allocatable :: Exch(:,:,:)
106
107 integer, allocatable :: i_index(:,:)
108 integer, allocatable :: j_index(:,:)
109 integer, allocatable :: k_index(:,:)
110 integer, allocatable :: l_index(:,:)
111 end type rdm_t
112
113 type(rdm_t), pointer :: rdm_ptr
114
115contains
116
117 ! ---------------------------------------------------------
118 subroutine rdmft_init(rdm, namespace, gr, st, mc, space, fromScratch)
119 type(rdm_t), intent(out) :: rdm
120 type(namespace_t), intent(in) :: namespace
121 type(grid_t), intent(inout) :: gr
122 type(states_elec_t), intent(in) :: st
123 type(multicomm_t), intent(in) :: mc
124 class(space_t), intent(in) :: space
125 logical, intent(in) :: fromScratch
126
127 push_sub(rdmft_init)
128
129 if(st%nst < st%qtot + 1) then
130 message(1) = "Too few states to run RDMFT calculation"
131 message(2) = "Number of states should be at least the number of electrons plus one"
132 call messages_fatal(2, namespace=namespace)
133 end if
134
135 if (states_are_complex(st)) then
136 call messages_not_implemented("Complex states for RDMFT", namespace=namespace)
137 end if
138
139 ! The documentation for the variable is found in scf_init.
140 call parse_variable(namespace, 'MaximumIter', 200, rdm%max_iter)
141
142 !%Variable RDMTolerance
143 !%Type float
144 !%Default 1e-7 Ha
145 !%Section SCF::RDMFT
146 !%Description
147 !% Convergence criterion for stopping the occupation numbers minimization. Minimization is
148 !% stopped when all derivatives of the energy wrt. each occupation number
149 !% are smaller than this criterion. The bisection for finding the correct mu that is needed
150 !% for the occupation number minimization also stops according to this criterion.
151 !%End
152 call parse_variable(namespace, 'RDMTolerance', 1.0e-7_real64, rdm%toler)
153
154 !%Variable RDMToleranceFO
155 !%Type float
156 !%Default 1e-4 Ha
157 !%Section SCF::RDMFT
158 !%Description
159 !% Convergence criterion for stopping the diagonalization of the Fock matrix in the Piris method.
160 !% Orbital minimization is stopped when all off-diagonal ellements of the Fock matrix
161 !% are smaller than this criterion.
162 !%End
163 call parse_variable(namespace, 'RDMToleranceFO', 1.0e-4_real64, rdm%tolerFO)
164
165 !%Variable RDMConvEner
166 !%Type float
167 !%Default 1e-6 Ha
168 !%Section SCF::RDMFT
169 !%Description
170 !% Convergence criterion for stopping the overall minimization of the energy with
171 !% respect to occupation numbers and the orbitals. The minimization of the
172 !% energy stops when the total energy difference between two subsequent
173 !% minimizations of the energy with respect to the occupation numbers and the
174 !% orbitals is smaller than this criterion. It is also used to exit the orbital minimization.
175 !%End
176 call parse_variable(namespace, 'RDMConvEner', 1.0e-7_real64, rdm%conv_ener)
178 !%Variable RDMBasis
179 !%Type logical
180 !%Default yes
181 !%Section SCF::RDMFT
182 !%Description
183 !% If true, all the energy terms and corresponding derivatives involved in RDMFT will
184 !% not be calculated on the grid but on the basis of the initial orbitals
185 !%End
186 call parse_variable(namespace, 'RDMBasis',.true., rdm%do_basis)
188 if (rdm%do_basis .and. fromscratch) then
189 call messages_write("RDMFT calculations with RDMBasis = yes cannot be started FromScratch", new_line=.true.)
190 call messages_write("Run a calculation for independent particles first")
191 call messages_fatal(namespace=namespace)
192 end if
194 !%Variable RDMHartreeFock
195 !%Type logical
196 !%Default no
197 !%Section SCF::RDMFT
198 !%Description
199 !% If true, the code simulates a HF calculation, by omitting the occ.num. optimization
200 !% can be used for test reasons
201 !%End
202 call parse_variable(namespace, 'RDMHartreeFock',.false., rdm%hf)
204 rdm%nst = st%nst
205 if (rdm%do_basis) then
206 rdm%n_twoint = rdm%nst*(rdm%nst + 1)*(rdm%nst**2 + rdm%nst + 2)/8
207 safe_allocate(rdm%eone_int(1:rdm%nst, 1:rdm%nst))
208 safe_allocate(rdm%twoint(1:rdm%n_twoint))
209 safe_allocate(rdm%i_index(1:2,1:rdm%n_twoint))
210 safe_allocate(rdm%j_index(1:2,1:rdm%n_twoint))
211 safe_allocate(rdm%k_index(1:2,1:rdm%n_twoint))
212 safe_allocate(rdm%l_index(1:2,1:rdm%n_twoint))
213 safe_allocate(rdm%vecnat(1:rdm%nst, 1:rdm%nst))
214 safe_allocate(rdm%Coul(1:rdm%nst, 1:rdm%nst, 1:rdm%nst))
215 safe_allocate(rdm%Exch(1:rdm%nst, 1:rdm%nst, 1:rdm%nst))
216 rdm%eone_int = m_zero
217 rdm%twoint = m_zero
218 rdm%vecnat = diagonal_matrix(rdm%nst, m_one)
219 rdm%i_index = m_zero
220 rdm%j_index = m_zero
221 rdm%k_index = m_zero
222 rdm%l_index = m_zero
223 rdm%Coul = m_zero
224 rdm%Exch = m_zero
225 else
226 ! initialize eigensolver.
227 call eigensolver_init(rdm%eigens, namespace, gr, st, mc, space)
228 if (rdm%eigens%additional_terms) call messages_not_implemented("CG Additional Terms with RDMFT", namespace=namespace)
229 end if
230
231 safe_allocate(rdm%eone(1:rdm%nst))
232 safe_allocate(rdm%hartree(1:rdm%nst, 1:rdm%nst))
233 safe_allocate(rdm%exchange(1:rdm%nst, 1:rdm%nst))
234 safe_allocate(rdm%evalues(1:rdm%nst))
235
236 rdm%eone = m_zero
237 rdm%hartree = m_zero
238 rdm%exchange = m_zero
239 rdm%evalues = m_zero
240 rdm%mu = m_two*st%eigenval(int(st%qtot*m_half), 1)
241 rdm%qtot = st%qtot
242 rdm%occsum = m_zero
243 rdm%scale_f = 1e-2_real64
244 rdm%maxFO = m_zero
245 rdm%iter = 0
246
247 pop_sub(rdmft_init)
248 end subroutine rdmft_init
249
250 ! ----------------------------------------
251
252 subroutine rdmft_end(rdm)
253 type(rdm_t), intent(inout) :: rdm
254
255 push_sub(rdmft_end)
256
257 safe_deallocate_a(rdm%evalues)
258 safe_deallocate_a(rdm%eone)
259 safe_deallocate_a(rdm%hartree)
260 safe_deallocate_a(rdm%exchange)
261
262 if (rdm%do_basis) then
263 safe_deallocate_a(rdm%eone_int)
264 safe_deallocate_a(rdm%twoint)
265 safe_deallocate_a(rdm%i_index)
266 safe_deallocate_a(rdm%j_index)
267 safe_deallocate_a(rdm%k_index)
268 safe_deallocate_a(rdm%l_index)
269 safe_deallocate_a(rdm%vecnat)
270 safe_deallocate_a(rdm%Coul)
271 safe_deallocate_a(rdm%Exch)
272 else
273 call eigensolver_end(rdm%eigens)
274 end if
275
276 pop_sub(rdmft_end)
277 end subroutine rdmft_end
278
279 ! ----------------------------------------
280
281 ! scf for the occupation numbers and the natural orbitals
282 subroutine scf_rdmft(rdm, namespace, space, gr, ions, ext_partners, st, ks, hm, outp, restart_dump)
283 type(rdm_t), intent(inout) :: rdm
284 type(namespace_t), intent(in) :: namespace
285 type(electron_space_t), intent(in) :: space
286 type(grid_t), intent(in) :: gr
287 type(ions_t), intent(in) :: ions
288 type(partner_list_t), intent(in) :: ext_partners
289 type(states_elec_t), intent(inout) :: st
290 type(v_ks_t), intent(inout) :: ks
291 type(hamiltonian_elec_t), intent(inout) :: hm
292 type(output_t), intent(in) :: outp
293 type(restart_t), intent(in) :: restart_dump
294
295 type(states_elec_t) :: states_save
296 integer :: iter, icount, ip, ist, ierr, maxcount, iorb
297 integer(int64) :: what_i
298 real(real64) :: energy, energy_dif, energy_old, energy_occ, xpos, xneg, rel_ener
299 real(real64), allocatable :: dpsi(:,:), dpsi2(:,:)
300 logical :: conv
301 character(len=MAX_PATH_LEN) :: dirname
302
303 push_sub(scf_rdmft)
304
305 if (hm%d%ispin /= 1) then
306 call messages_not_implemented("RDMFT exchange function not yet implemented for spin_polarized or spinors", &
307 namespace=namespace)
308 end if
309
310 ! problem is about k-points for exchange
311 if (space%is_periodic()) then
312 call messages_not_implemented("Periodic system calculations for RDMFT", namespace=namespace)
313 end if
314
315 ! exchange routine needs all states on each processor currently
316 if(st%parallel_in_states) then
317 call messages_not_implemented("RDMFT parallel in states", namespace=namespace)
318 end if
319
320 call messages_print_with_emphasis(msg='RDMFT Calculation', namespace=namespace)
321 call messages_print_var_value('RDMBasis', rdm%do_basis, namespace=namespace)
322
323 !set initial values
324 energy_old = 1.0e20_real64
325 xpos = m_zero
326 xneg = m_zero
327 energy = m_zero
328 if (.not. rdm%do_basis) then
329 maxcount = 1 !still needs to be checked
330 else
331 maxcount = 50
332 !precalculate matrix elements in basis
333 write(message(1),'(a)') 'Calculating Coulomb and exchange matrix elements in basis'
334 write(message(2),'(a)') '--this may take a while--'
335 call messages_info(2, namespace=namespace)
336
337 call two_body_me(gr, st, space, namespace, hm%kpoints, hm%exxop%psolver, 1, st%nst, rdm%i_index, rdm%j_index, rdm%k_index, &
338 rdm%l_index, rdm%twoint)
339 call rdm_integrals(rdm, namespace, hm, st, gr)
340 call sum_integrals(rdm)
341 endif
342
343 ! Start the actual minimization, first step is minimization of occupation numbers
344 ! Orbital minimization is according to Piris and Ugalde, Vol. 30, No. 13, J. Comput. Chem. (scf_orb) or
345 ! using conjugated gradient (scf_orb_cg)
346 do iter = 1, rdm%max_iter
347 rdm%iter = rdm%iter + 1
348 write(message(1), '(a)') '**********************************************************************'
349 write(message(2),'(a, i4)') 'Iteration:', iter
350 call messages_info(2, namespace=namespace)
351 ! occupation number optimization unless we are doing Hartree-Fock
352 if (rdm%hf) then
353 call scf_occ_no(rdm, namespace, gr, hm, space, st, energy_occ)
354 else
355 call scf_occ(rdm, namespace, gr, hm, space, st, energy_occ)
356 end if
357 ! orbital optimization
358 write(message(1), '(a)') 'Optimization of natural orbitals'
359 call messages_info(1, namespace=namespace)
360 do icount = 1, maxcount
361 if (rdm%do_basis) then
362 call scf_orb(rdm, namespace, gr, st, hm, space, energy)
363 else
364 call scf_orb_cg(rdm, namespace, space, gr, ions, ext_partners, st, ks, hm, energy)
365 end if
366 energy_dif = energy - energy_old
367 energy_old = energy
368 if (rdm%do_basis) then
369 if (abs(energy_dif)/abs(energy) < rdm%conv_ener .and. rdm%maxFO < rdm%tolerFO) exit
370 if (energy_dif < m_zero) then
371 xneg = xneg + 1
372 else
373 xpos = xpos + 1
374 end if
375 if (xneg > 1.5e0_real64*xpos) then
376 rdm%scale_f = 1.01_real64*rdm%scale_f
377 elseif (xneg < 1.1e0_real64*xpos) then
378 rdm%scale_f = 0.95_real64* rdm%scale_f
379 end if
380 endif !rdm%do_basis
381 end do !icount
382 xneg = m_zero
383 xpos = m_zero
384
385 rel_ener = abs(energy_occ-energy)/abs(energy)
386
387 write(message(1),'(a,11x,es20.10)') 'Total energy:', units_from_atomic(units_out%energy,energy + hm%ep%eii)
388 write(message(2),'(a,1x,es20.10)') 'Rel. energy difference:', rel_ener
389 call messages_info(2, namespace=namespace)
390
391 if (.not. rdm%hf .and. rdm%do_basis) then
392 write(message(1),'(a,18x,es20.10)') 'Max F0:', rdm%maxFO
393 call messages_info(1, namespace=namespace)
394 end if
395
396
397 if (rdm%do_basis) then
398 conv = (rel_ener < rdm%conv_ener) .and. rdm%maxFO < rdm%tolerFO
399 else
400 conv = rel_ener < rdm%conv_ener
401 endif
402
403 if (rdm%toler > 1e-4_real64) rdm%toler = rdm%toler*1e-1_real64 !Is this still okay or does it restrict the possible convergence? FB: Does this makes sense at all?
404
405 ! save restart information
406 if ((conv .or. (modulo(iter, outp%restart_write_interval) == 0) .or. iter == rdm%max_iter)) then
407 if (rdm%do_basis) then
408 call states_elec_copy(states_save, st)
409 safe_allocate(dpsi(1:gr%np, 1:st%d%dim))
410 safe_allocate(dpsi2(1:gr%np, 1:st%d%dim))
411 do iorb = 1, st%nst
412 dpsi = m_zero
413 do ist = 1, st%nst
414 call states_elec_get_state(st, gr, ist, 1, dpsi2)
415 do ip = 1, gr%np
416 dpsi(ip,1) = dpsi(ip,1) + rdm%vecnat(ist, iorb)*dpsi2(ip,1)
417 end do
418 end do
419 call states_elec_set_state(states_save, gr, iorb, 1, dpsi)
420 end do
421 call density_calc(states_save, gr, states_save%rho)
422 ! if other quantities besides the densities and the states are needed they also have to be recalculated here!
423 call states_elec_dump(restart_dump, space, states_save, gr, hm%kpoints, ierr, iter=iter)
424
425 if (conv .or. iter == rdm%max_iter) then
426 call states_elec_end(st)
427 call states_elec_copy(st, states_save)
428 end if
429
430 call states_elec_end(states_save)
431
432 safe_deallocate_a(dpsi)
433 safe_deallocate_a(dpsi2)
434 else
435 call states_elec_dump(restart_dump, space, st, gr, hm%kpoints, ierr, iter=iter)
436
437 ! calculate maxFO for cg-solver
438 if (.not. rdm%hf) then
439 call calc_maxfo (namespace, hm, st, gr, rdm)
440 write(message(1),'(a,18x,es20.10)') 'Max F0:', rdm%maxFO
441 call messages_info(1, namespace=namespace)
442 end if
443 endif
444
445 if (ierr /= 0) then
446 message(1) = 'Unable to write states wavefunctions.'
447 call messages_warning(1, namespace=namespace)
448 end if
449
450 endif
451
452 ! write output for iterations if requested
453 if (any(outp%what) .and. outp%duringscf) then
454 do what_i = lbound(outp%what, 1), ubound(outp%what, 1)
455 if (outp%what_now(what_i, iter)) then
456 write(dirname,'(a,a,i4.4)') trim(outp%iter_dir), "scf.", iter
457 call output_all(outp, namespace, space, dirname, gr, ions, iter, st, hm, ks)
458 call output_modelmb(outp, namespace, space, dirname, gr, ions, iter, st)
459 call scf_write_static(dirname, "info")
460 exit
461 end if
462 end do
463 end if
464
465 if (conv) exit
466 end do
467
468 if(conv) then
469 write(message(1),'(a,i3,a)') 'The calculation converged after ',rdm%iter,' iterations'
470 write(message(2),'(a,9x,es20.10)') 'The total energy is ', units_from_atomic(units_out%energy,energy + hm%ep%eii)
471 call messages_info(2, namespace=namespace)
472 else
473 write(message(1),'(a,i3,a)') 'The calculation did not converge after ', iter-1, ' iterations '
474 write(message(2),'(a,es15.5)') 'Relative energy difference between the last two iterations ', rel_ener
475 write(message(3),'(a,es15.5)') 'The maximal non-diagonal element of the Hermitian matrix F is ', rdm%maxFO
476 call messages_info(3, namespace=namespace)
477 end if
478
479 call scf_write_static(static_dir, "info")
480 call output_all(outp, namespace, space, static_dir, gr, ions, -1, st, hm, ks)
481 call output_modelmb(outp, namespace, space, static_dir, gr, ions, -1, st)
482
483 pop_sub(scf_rdmft)
484
485 contains
486 ! ---------------------------------------------------------
487 subroutine scf_write_static(dir, fname)
488 character(len=*), intent(in) :: dir, fname
489
490 integer :: iunit, ist
491 real(real64), allocatable :: photon_number_state (:), ekin_state (:), epot_state (:)
492
494
495 safe_allocate(photon_number_state(1:st%nst))
496 safe_allocate(ekin_state(1:st%nst))
497 safe_allocate(epot_state(1:st%nst))
498
499 if(mpi_grp_is_root(mpi_world)) then
500 call io_mkdir(dir, namespace)
501 iunit = io_open(trim(dir) // "/" // trim(fname), namespace, action='write')
502
503 call grid_write_info(gr, iunit=iunit)
504
505 call v_ks_write_info(ks, iunit=iunit)
506
507 if (rdm%do_basis) then
508 write(iunit, '(a)')'Orbital optimization with [basis set]'
509 else
510 write(iunit, '(a)')'Orbital optimization with [conjugated gradients]'
511 end if
512 write(iunit, '(1x)')
513
514 if (rdm%hf) then
515 write(iunit, '(a)')'Hartree Fock calculation'
516 write(iunit, '(1x)')
517 end if
518
519 if (hm%psolver%is_dressed) then
520 write(iunit, '(a)')'Dressed state calculation'
521 call photon_mode_write_info(hm%psolver%photons, iunit=iunit)
522 write(iunit, '(1x)')
523 end if
524
525 ! scf information
526 if(conv) then
527 write(iunit, '(a, i4, a)')'SCF converged in ', iter, ' iterations'
528 else
529 write(iunit, '(a)') 'SCF *not* converged!'
530 end if
531 write(iunit, '(1x)')
532
533 write(iunit, '(3a,es20.10)') 'Total Energy [', trim(units_abbrev(units_out%energy)), ']:', &
534 units_from_atomic(units_out%energy, energy + hm%ep%eii)
535 write(iunit,'(a,1x,f16.12)') 'Sum of occupation numbers:', rdm%occsum
536 else
537 iunit = 0
538 end if
539
540 if (hm%psolver%is_dressed) then
541 call calc_photon_number(space, gr, st, hm%psolver%photons, photon_number_state, ekin_state, epot_state)
542 if(mpi_grp_is_root(mpi_world)) then
543 write(iunit,'(a,1x,f14.12)') 'Total mode occupation:', hm%psolver%photons%number(1)
544 end if
545 end if
546
547 if(mpi_grp_is_root(mpi_world)) then
548 if (rdm%max_iter > 0) then
549 write(iunit, '(a)') 'Convergence:'
550 write(iunit, '(6x, a, es15.8,a,es15.8,a)') 'maxFO = ', rdm%maxFO
551 write(iunit, '(6x, a, es15.8,a,es15.8,a)') 'rel_ener = ', rel_ener
552 write(iunit,'(1x)')
553 end if
554 ! otherwise, these values are uninitialized, and unknown.
555 end if
556
557 if (mpi_grp_is_root(mpi_world)) then
558 ! Write header
559 write(iunit,'(a)') 'Natural occupation numbers:'
560 write(iunit,'(a4,5x,a12)', advance='no') '#st', 'Occupation'
561 if (.not. rdm%do_basis) write(iunit,'(5x,a12)', advance='no') 'conv'
562 if (hm%psolver%is_dressed) write(iunit,'(3(5x,a12))', advance='no') 'Mode Occ.', '-1/2d^2/dq^2', '1/2w^2q^2'
563 write(iunit,*)
564
565 ! Write values
566 do ist = 1, st%nst
567 write(iunit,'(i4,3x,f14.12)', advance='no') ist, st%occ(ist, 1)
568 if (.not. rdm%do_basis) write(iunit,'(3x,f14.12)', advance='no') rdm%eigens%diff(ist, 1)
569 if (hm%psolver%is_dressed) then
570 write(iunit,'(3(3x,f14.12))', advance='no') photon_number_state(ist), ekin_state(ist), epot_state(ist)
571 end if
572 write(iunit,*)
573 end do
574 end if
575
576 if (mpi_grp_is_root(mpi_world)) then
577 call io_close(iunit)
578 end if
579
580 safe_deallocate_a(photon_number_state)
581 safe_deallocate_a(ekin_state)
582 safe_deallocate_a(epot_state)
583
585 end subroutine scf_write_static
586 end subroutine scf_rdmft
587
588 ! ---------------------------------------------------------
589 subroutine calc_maxfo (namespace, hm, st, gr, rdm)
590 type(namespace_t), intent(in) :: namespace
591 type(rdm_t), intent(inout) :: rdm
592 type(grid_t), intent(in) :: gr
593 type(hamiltonian_elec_t), intent(inout) :: hm
594 type(states_elec_t), intent(inout) :: st
595
596 real(real64), allocatable :: lambda(:,:), FO(:,:)
597 integer :: ist, jst
598
599 push_sub(calc_maxfo)
600
601 safe_allocate(lambda(1:st%nst,1:st%nst))
602 safe_allocate(fo(1:st%nst, 1:st%nst))
603
604 ! calculate FO operator to check Hermiticity of lagrange multiplier matrix (lambda)
605 lambda = m_zero
606 fo = m_zero
607 call construct_lambda(namespace, hm, st, gr, lambda, rdm)
608
609 !Set up FO matrix to check maxFO
610 do ist = 1, st%nst
611 do jst = 1, ist - 1
612 fo(jst, ist) = - (lambda(jst, ist) - lambda(ist ,jst))
613 end do
614 end do
615 rdm%maxFO = maxval(abs(fo))
616
617 safe_deallocate_a(lambda)
618 safe_deallocate_a(fo)
619
620 pop_sub(calc_maxfo)
621 end subroutine calc_maxfo
622
623 ! ---------------------------------------------------------
624 subroutine calc_photon_number(space, gr, st, photons, photon_number_state, ekin_state, epot_state)
625 class(space_t), intent(in) :: space
626 type(grid_t), intent(in) :: gr
627 type(states_elec_t), intent(in) :: st
628 type(photon_mode_t), intent(inout) :: photons
629 real(real64), intent(out) :: photon_number_state(:)
630 real(real64), intent(out) :: ekin_state(:)
631 real(real64), intent(out) :: epot_state(:)
632
633 integer :: ist, dim_photon
634 real(real64) :: q2_exp, laplace_exp
635 real(real64), allocatable :: psi(:, :), psi_q2(:), dpsidq(:), d2psidq2(:)
636
637 push_sub(calc_photon_number)
638
639 ! The photon dimension is always the last
640 dim_photon = space%dim
641
642 safe_allocate(psi(1:gr%np_part, 1))
643 safe_allocate(psi_q2(1:gr%np))
644 safe_allocate(dpsidq(1:gr%np_part))
645 safe_allocate(d2psidq2(1:gr%np))
646
647 photons%number(1) = m_zero
648
649 do ist = 1, st%nst
650 call states_elec_get_state(st, gr, ist, 1, psi)
651
652 ! <phi(ist)|d^2/dq^2|phi(ist)> ~= <phi(ist)| d/dq (d/dq|phi(ist)>)
653 call dderivatives_partial(gr%der, psi(:, 1), dpsidq(:), dim_photon, ghost_update = .true., set_bc = .true.)
654 call dderivatives_partial(gr%der, dpsidq(1:gr%np_part), d2psidq2(:), dim_photon, ghost_update = .true., set_bc = .true.)
655 laplace_exp = dmf_dotp(gr, psi(:, 1), d2psidq2(:))
656 ekin_state(ist) = -m_half*laplace_exp
657
658 ! <phi(ist)|q^2|psi(ist)>= |q|psi(ist)>|^2
659 psi_q2(1:gr%np) = psi(1:gr%np, 1) * gr%x(1:gr%np, dim_photon)**2
660 q2_exp = dmf_dotp(gr, psi(:, 1), psi_q2(:))
661 epot_state(ist) = m_half * photons%omega(1)**2 * q2_exp
662
663 !! N_phot(ist)=( <phi_i|H_ph|phi_i>/omega - 0.5 ) / N_elec
664 !! with <phi_i|H_ph|phi_i>=-0.5* <phi(ist)|d^2/dq^2|phi(ist)> + 0.5*omega <phi(ist)|q^2|psi(ist)>
665 photon_number_state(ist) = -m_half*laplace_exp / photons%omega(1) + m_half * photons%omega(1) * q2_exp
666 photon_number_state(ist) = photon_number_state(ist) - m_half
667
668 !! N_phot_total= sum_ist occ_ist*N_phot(ist)
669 photons%number(1) = photons%number(1) + (photon_number_state(ist) + m_half)*st%occ(ist, 1) ! 0.5 must be added again to do the normalization due to the total charge correctly
670 end do
671
672 photons%number(1) = photons%number(1) - st%qtot/m_two
673
674 safe_deallocate_a(psi)
675 safe_deallocate_a(psi_q2)
676 safe_deallocate_a(dpsidq)
677 safe_deallocate_a(d2psidq2)
678
679 pop_sub(calc_photon_number)
680 end subroutine calc_photon_number
681
682 ! ---------------------------------------------------------
683
684 ! reset occ.num. to 2/0
685 subroutine set_occ_pinning(st)
686 type(states_elec_t), intent(inout) :: st
687
688 real(real64), allocatable :: occin(:,:)
689
690 push_sub(set_occ_pinning)
691
692 safe_allocate(occin(1:st%nst, 1:st%nik))
693
694 occin(1:st%nst, 1:st%nik) = st%occ(1:st%nst, 1:st%nik)
695 where(occin(:,:) < m_one) occin(:,:) = m_zero
696 where(occin(:,:) > m_one) occin(:,:) = st%smear%el_per_state
697
698 st%occ = occin
699
700 safe_deallocate_a(occin)
701
702 pop_sub(set_occ_pinning)
703 end subroutine set_occ_pinning
704
705
706 ! ---------------------------------------------------------
707 ! dummy routine for occupation numbers which only calculates the necessary variables for further use
708 ! used in Hartree-Fock mode
709 subroutine scf_occ_no(rdm, namespace, gr, hm, space, st, energy)
710 type(rdm_t), intent(inout) :: rdm
711 type(namespace_t), intent(in) :: namespace
712 type(grid_t), intent(in) :: gr
713 type(hamiltonian_elec_t), intent(in) :: hm
714 class(space_t), intent(in) :: space
715 type(states_elec_t), intent(inout) :: st
716 real(real64), intent(out) :: energy
718 integer :: ist
719
720 push_sub(scf_occ_no)
721
722 write(message(1),'(a)') 'SKIP Optimization of occupation numbers'
723 call messages_info(1, namespace=namespace)
724
725 call set_occ_pinning(st)
726
727 energy = m_zero
728
729 call rdm_derivatives(rdm, namespace, hm, st, gr, space)
730
731 call total_energy_rdm(rdm, st%occ(:,1), energy)
732
733 rdm%occsum = sum(st%occ(1:st%nst, 1:st%nik))
734
735 write(message(1),'(a4,5x,a12)')'#st','Occupation'
736 call messages_info(1, namespace=namespace)
737
738 do ist = 1, st%nst
739 write(message(1),'(i4,3x,f11.9)') ist, st%occ(ist, 1)
740 call messages_info(1, namespace=namespace)
741 end do
742
743 write(message(1),'(a,1x,f13.9)') 'Sum of occupation numbers', rdm%occsum
744 write(message(2),'(a,es20.10)') 'Total energy occ', units_from_atomic(units_out%energy,energy + hm%ep%eii)
745 call messages_info(2, namespace=namespace)
746
747 pop_sub(scf_occ_no)
748 end subroutine scf_occ_no
749
750 ! scf for the occupation numbers
751 subroutine scf_occ(rdm, namespace, gr, hm, space, st, energy)
752 type(rdm_t), target, intent(inout) :: rdm
753 type(namespace_t), intent(in) :: namespace
754 type(grid_t), intent(in) :: gr
755 type(hamiltonian_elec_t), intent(in) :: hm
756 class(space_t), intent(in) :: space
757 type(states_elec_t), intent(inout) :: st
758 real(real64), intent(out) :: energy
759
760 integer :: ist, icycle, ierr
761 real(real64) :: sumgi1, sumgi2, sumgim, mu1, mu2, mum, dinterv, thresh_occ
762 real(real64), allocatable :: occin(:,:)
763 real(real64), parameter :: smallocc = 0.00001_real64
764 real(real64), allocatable :: theta(:)
765 real(real64) :: objective
766
767 push_sub(scf_occ)
768 call profiling_in("SCF_OCC")
769
770 write(message(1),'(a)') 'Optimization of occupation numbers'
771 call messages_info(1, namespace=namespace)
772
773 safe_allocate(occin(1:st%nst, 1:st%nik))
774 safe_allocate(theta(1:st%nst))
775
776 occin = m_zero
777 theta = m_zero
778 energy = m_zero
779
780 ! Defines a threshold on occ nums to avoid numerical instabilities.
781 ! Needs to be changed consistently with the same variable in objective_rdmft
782 thresh_occ = 1e-14_real64
783
784 !Initialize the occin. Smallocc is used for numerical stability
785 occin(1:st%nst, 1:st%nik) = st%occ(1:st%nst, 1:st%nik)
786 where(occin(:,:) < smallocc) occin(:,:) = smallocc
787 where(occin(:,:) > st%smear%el_per_state - smallocc) occin(:,:) = st%smear%el_per_state - smallocc
788
789 !Renormalize the occupation numbers
790 rdm%occsum = st%qtot
791
792 st%occ = occin
793
794 call rdm_derivatives(rdm, namespace, hm, st, gr, space)
795
796 !finding the chemical potential mu such that the occupation numbers sum up to the number of electrons
797 !bisection to find the root of rdm%occsum-st%qtot=M_ZERO
798 mu1 = rdm%mu !initial guess for mu
799 mu2 = -1.0e-6_real64
800 dinterv = m_half
801
802 ! Set pointer to rdm, so that it is available in the functions called by the minimizer
803 rdm_ptr => rdm
804
805 !use n_j=sin^2(2pi*theta_j) to treat pinned states, minimize for both intial mu
806 theta(:) = asin(sqrt(occin(:, 1)/st%smear%el_per_state))*(m_half/m_pi)
807 call minimize_multidim(minmethod_bfgs, st%nst, theta, 0.05_real64, 0.01_real64, &
808 1e-12_real64, 1e-12_real64, 200, objective_rdmft, write_iter_info_rdmft, objective, ierr)
809 sumgi1 = rdm%occsum - st%qtot
810 rdm%mu = mu2
811 theta(:) = asin(sqrt(occin(:, 1)/st%smear%el_per_state))*(m_half/m_pi)
812 call minimize_multidim(minmethod_bfgs, st%nst, theta, 0.05_real64, 0.01_real64, &
813 1e-12_real64, 1e-12_real64, 200, objective_rdmft, write_iter_info_rdmft, objective, ierr)
814 sumgi2 = rdm%occsum - st%qtot
815
816 ! Adjust the interval between the initial mu to include the root of rdm%occsum-st%qtot=M_ZERO
817 do while (sumgi1*sumgi2 > m_zero)
818 if (sumgi2 > m_zero) then
819 mu2 = mu1
820 sumgi2 = sumgi1
821 mu1 = mu1 - dinterv
822 rdm%mu = mu1
823 theta(:) = asin(sqrt(occin(:, 1)/st%smear%el_per_state))*(m_half/m_pi)
824 call minimize_multidim(minmethod_bfgs, st%nst, theta, 0.05_real64, 0.01_real64, &
825 1e-12_real64, 1e-12_real64, 200, objective_rdmft, write_iter_info_rdmft, objective, ierr)
826 sumgi1 = rdm%occsum - st%qtot
827 else
828 mu1 = mu2
829 sumgi1 = sumgi2
830 mu2 = mu2 + dinterv
831 rdm%mu = mu2
832 theta(:) = asin(sqrt(occin(:, 1)/st%smear%el_per_state))*(m_half/m_pi)
833 call minimize_multidim(minmethod_bfgs, st%nst, theta, 0.05_real64, 0.01_real64, &
834 1e-12_real64, 1e-12_real64, 200, objective_rdmft, write_iter_info_rdmft, objective, ierr)
835 sumgi2 = rdm%occsum - st%qtot
836 end if
837 end do
838
839 do icycle = 1, 50
840 mum = (mu1 + mu2)*m_half
841 rdm%mu = mum
842 theta(:) = asin(sqrt(occin(:, 1)/st%smear%el_per_state))*(m_half/m_pi)
843 call minimize_multidim(minmethod_bfgs, st%nst, theta, 0.05_real64, 0.0001_real64, &
844 1e-12_real64, 1e-12_real64, 200, objective_rdmft, write_iter_info_rdmft, objective, ierr)
845 sumgim = rdm%occsum - st%qtot
846
847 if (sumgi1*sumgim < m_zero) then
848 mu2 = mum
849 else
850 mu1 = mum
851 sumgi1 = sumgim
852 end if
853
854 ! check occ.num. threshold again after minimization
855 do ist = 1, st%nst
856 st%occ(ist,1) = m_two*sin(theta(ist)*m_pi*m_two)**2
857 if (st%occ(ist,1) <= thresh_occ ) st%occ(ist,1) = thresh_occ
858 end do
859
860 if (abs(sumgim) < rdm%toler .or. abs((mu1-mu2)*m_half) < rdm%toler) exit
861 end do
862
863 nullify(rdm_ptr)
864
865 if (icycle >= 50) then
866 write(message(1),'(a,1x,f11.4)') 'Bisection ended without finding mu, sum of occupation numbers:', rdm%occsum
867 call messages_fatal(1, namespace=namespace)
868 end if
869
870 do ist = 1, st%nst
871 st%occ(ist, 1) = st%smear%el_per_state*sin(theta(ist)*m_pi*m_two)**2
872 end do
873
874 objective = objective + rdm%mu*(rdm%occsum - rdm%qtot)
875 energy = objective
876
877 write(message(1),'(a4,5x,a12)')'#st','Occupation'
878 call messages_info(1, namespace=namespace)
879
880 do ist = 1, st%nst
881 write(message(1),'(i4,3x,f14.12)') ist, st%occ(ist, 1)
882 call messages_info(1, namespace=namespace)
883 end do
884
885 write(message(1),'(a,3x,f11.9)') 'Sum of occupation numbers: ', rdm%occsum
886 write(message(2),'(a,11x,es20.10)') 'Total energy: ', units_from_atomic(units_out%energy, energy + hm%ep%eii)
887 call messages_info(2, namespace=namespace)
888
889 safe_deallocate_a(occin)
890 safe_deallocate_a(theta)
891
892 call profiling_out("SCF_OCC")
893 pop_sub(scf_occ)
894 end subroutine scf_occ
895
896 ! ---------------------------------------------------------
897 subroutine objective_rdmft(size, theta, objective, getgrad, df)
898 integer, intent(in) :: size
899 real(real64), intent(in) :: theta(size)
900 real(real64), intent(inout) :: objective
901 integer, intent(in) :: getgrad
902 real(real64), intent(inout) :: df(size)
903
904 integer :: ist
905 real(real64) :: thresh_occ, thresh_theta
906 real(real64), allocatable :: dE_dn(:),occ(:)
907
908 push_sub(objective_rdmft)
909
910 assert(size == rdm_ptr%nst)
911
912 safe_allocate(de_dn(1:size))
913 safe_allocate(occ(1:size))
914
915 occ = m_zero
916
917 ! Defines a threshold on occ nums to avoid numerical instabilities.
918 ! Needs to be changed consistently with the same variable in scf_occ
919 thresh_occ = 1e-14_real64
920 thresh_theta = asin(sqrt(thresh_occ/m_two))*(m_half/m_pi)
921
922 do ist = 1, size
923 occ(ist) = m_two*sin(theta(ist)*m_pi*m_two)**2
924 if (occ(ist) <= thresh_occ ) occ(ist) = thresh_occ
925 end do
926
927 rdm_ptr%occsum = sum(occ(1:size))
928
929 !calculate the total energy without nuclei interaction and the energy
930 !derivatives with respect to the occupation numbers
931
932 call total_energy_rdm(rdm_ptr, occ, objective, de_dn)
933 do ist = 1, size
934 if (occ(ist) <= thresh_occ ) then
935 df(ist) = m_four*m_pi*sin(m_four*thresh_theta*m_pi)*(de_dn(ist) - rdm_ptr%mu)
936 else
937 df(ist) = m_four*m_pi*sin(m_four*theta(ist)*m_pi)*(de_dn(ist) - rdm_ptr%mu)
938 end if
939 end do
940 objective = objective - rdm_ptr%mu*(rdm_ptr%occsum - rdm_ptr%qtot)
941
942 safe_deallocate_a(de_dn)
943 safe_deallocate_a(occ)
944
945 pop_sub(objective_rdmft)
946 end subroutine objective_rdmft
947
948 ! ---------------------------------------------------------
949 subroutine write_iter_info_rdmft(iter, size, energy, maxdr, maxdf, theta)
950 integer, intent(in) :: iter
951 integer, intent(in) :: size
952 real(real64), intent(in) :: energy, maxdr, maxdf
953 real(real64), intent(in) :: theta(size)
954
955 push_sub(write_iter_info_rdmft)
956
957 ! Nothing to do.
958
959 pop_sub(write_iter_info_rdmft)
960 end subroutine write_iter_info_rdmft
961
962 ! scf for the natural orbitals
963 subroutine scf_orb(rdm, namespace, gr, st, hm, space, energy)
964 type(rdm_t), intent(inout) :: rdm
965 type(namespace_t), intent(in) :: namespace
966 type(grid_t), intent(in) :: gr
967 type(states_elec_t), intent(inout) :: st
968 type(hamiltonian_elec_t), intent(in) :: hm
969 class(space_t), intent(in) :: space
970 real(real64), intent(out) :: energy
971
972 integer :: ist, jst
973 real(real64), allocatable :: lambda(:,:), fo(:,:)
974
975 push_sub(scf_orb)
976 call profiling_in("SCF_ORB_BASIS")
977
978 !matrix of Lagrange Multipliers from Equation (8), Piris and Ugalde, Vol. 30, No. 13, J. Comput. Chem.
979 safe_allocate(lambda(1:st%nst,1:st%nst))
980 safe_allocate(fo(1:st%nst, 1:st%nst)) !Generalized Fockian Equation (11)
981
982 lambda = m_zero
983 fo = m_zero
984
985 call construct_lambda(namespace, hm, st, gr, lambda, rdm)
986
987 !Set up fo matrix
988 if (rdm%iter==1) then
989 do ist = 1, st%nst
990 do jst = 1, ist
991 fo(ist, jst) = m_half*(lambda(ist, jst) + lambda(jst, ist))
992 fo(jst, ist) = fo(ist, jst)
993 end do
994 end do
995 else
996 do ist = 1, st%nst
997 do jst = 1, ist - 1
998 fo(jst, ist) = - ( lambda(jst, ist) - lambda(ist ,jst))
999 end do
1000 end do
1001 rdm%maxfo = maxval(abs(fo))
1002 do ist = 1, st%nst
1003 fo(ist, ist) = rdm%evalues(ist)
1004 do jst = 1, ist-1
1005 if(abs(fo(jst, ist)) > rdm%scale_f) then
1006 fo(jst, ist) = rdm%scale_f*fo(jst,ist)/abs(fo(jst, ist))
1007 end if
1008 fo(ist, jst) = fo(jst, ist)
1009 end do
1010 end do
1011 end if
1012
1013 call lalg_eigensolve(st%nst, fo, rdm%evalues)
1014 call assign_eigfunctions(rdm, st, fo)
1015 call sum_integrals(rdm) ! to calculate rdm%Coul and rdm%Exch with the new rdm%vecnat
1016 call rdm_derivatives(rdm, namespace, hm, st, gr, space)
1017 call total_energy_rdm(rdm, st%occ(:,1), energy)
1018
1019 safe_deallocate_a(lambda)
1020 safe_deallocate_a(fo)
1021
1022 call profiling_out("SCF_ORB_BASIS")
1023 pop_sub(scf_orb)
1024 end subroutine scf_orb
1025
1026
1027 !-----------------------------------------------------------------
1028 ! Minimize the total energy wrt. an orbital by conjugate gradient
1029 !-----------------------------------------------------------------
1030 subroutine scf_orb_cg(rdm, namespace, space, gr, ions, ext_partners, st, ks, hm, energy)
1031 type(rdm_t), intent(inout) :: rdm
1032 type(namespace_t), intent(in) :: namespace
1033 type(electron_space_t), intent(in) :: space
1034 type(grid_t), intent(in) :: gr
1035 type(ions_t), intent(in) :: ions
1036 type(partner_list_t), intent(in) :: ext_partners
1037 type(states_elec_t), intent(inout) :: st
1038 type(v_ks_t), intent(inout) :: ks
1039 type(hamiltonian_elec_t), intent(inout) :: hm
1040 real(real64), intent(out) :: energy
1041
1042 integer :: ik, ist, maxiter
1043
1044
1045 push_sub(scf_orb_cg)
1046 call profiling_in("CG")
1047
1048 call v_ks_calc(ks, namespace, space, hm, st, ions, ext_partners)
1049 call hm%update(gr, namespace, space, ext_partners)
1050
1051 rdm%eigens%converged = 0
1052 if(mpi_grp_is_root(mpi_world) .and. .not. debug%info) then
1053 call loct_progress_bar(-1, st%lnst*st%d%kpt%nlocal)
1054 end if
1055 do ik = st%d%kpt%start, st%d%kpt%end
1056 rdm%eigens%matvec = 0
1057 maxiter = rdm%eigens%es_maxiter
1058 call deigensolver_cg(namespace, gr, st, hm, hm%xc, rdm%eigens%pre, rdm%eigens%tolerance, maxiter, &
1059 rdm%eigens%converged(ik), ik, rdm%eigens%diff(:, ik), rdm%eigens%energy_change_threshold, &
1060 rdm%eigens%orthogonalize_to_all, rdm%eigens%conjugate_direction, rdm%eigens%additional_terms)
1061
1062 if (.not. rdm%eigens%folded_spectrum) then
1063 ! recheck convergence after subspace diagonalization, since states may have reordered (copied from eigensolver_run)
1064 rdm%eigens%converged(ik) = 0
1065 do ist = 1, st%nst
1066 if(rdm%eigens%diff(ist, ik) < rdm%eigens%tolerance) then
1067 rdm%eigens%converged(ik) = ist
1068 else
1069 exit
1070 end if
1071 end do
1072 end if
1073 end do
1074
1075 if(mpi_grp_is_root(mpi_world) .and. .not. debug%info) then
1076 write(stdout, '(1x)')
1077 end if
1078
1079 ! calculate total energy with new states
1080 call density_calc (st, gr, st%rho)
1081 call v_ks_calc(ks, namespace, space, hm, st, ions, ext_partners)
1082 call hm%update(gr, namespace, space, ext_partners)
1083 call rdm_derivatives(rdm, namespace, hm, st, gr, space)
1084
1085 call total_energy_rdm(rdm, st%occ(:,1), energy)
1086
1087 call profiling_out("CG")
1088 pop_sub(scf_orb_cg)
1089 end subroutine scf_orb_cg
1090
1091
1092 ! ----------------------------------------
1093 ! constructs the Lagrange multiplyers needed for the orbital minimization
1094 subroutine construct_lambda(namespace, hm, st, gr, lambda, rdm)
1095 type(namespace_t), intent(in) :: namespace
1096 type(hamiltonian_elec_t), intent(in) :: hm
1097 type(states_elec_t), intent(inout) :: st
1098 type(grid_t), intent(in) :: gr
1099 real(real64), intent(out) :: lambda(:,:)
1100 type(rdm_t), intent(inout) :: rdm
1101
1102 real(real64), allocatable :: hpsi(:,:), hpsi1(:,:), dpsi(:,:), dpsi1(:,:)
1103 real(real64), allocatable :: fock(:,:,:), fvec(:)
1104 integer :: ist, iorb, jorb, jst
1105
1106 push_sub(construct_lambda)
1107
1108 lambda = m_zero
1109
1110 !calculate the Lagrange multiplyer lambda matrix on the grid, Eq. (9), Piris and Ugalde, Vol. 30, No. 13, J. Comput. Chem.
1111 if (.not. rdm%do_basis) then
1112 safe_allocate(hpsi(1:gr%np,1:st%d%dim))
1113 safe_allocate(hpsi1(1:gr%np,1:st%d%dim))
1114 safe_allocate(dpsi(1:gr%np_part ,1:st%d%dim))
1115 safe_allocate(dpsi1(1:gr%np_part ,1:st%d%dim))
1116
1117 do iorb = 1, st%nst
1118 call states_elec_get_state(st, gr, iorb, 1, dpsi)
1119 call dhamiltonian_elec_apply_single(hm, namespace, gr, dpsi, hpsi, iorb, 1)
1120
1121 do jorb = iorb, st%nst
1122 ! calculate <phi_j|H|phi_i> =lam_ji
1123 call states_elec_get_state(st, gr, jorb, 1, dpsi1)
1124 lambda(jorb, iorb) = dmf_dotp(gr, dpsi1(:,1), hpsi(:,1))
1125
1126 ! calculate <phi_i|H|phi_j>=lam_ij
1127 if (.not. iorb == jorb ) then
1128 call dhamiltonian_elec_apply_single(hm, namespace, gr, dpsi1, hpsi1, jorb, 1)
1129 lambda(iorb, jorb) = dmf_dotp(gr, dpsi(:,1), hpsi1(:,1))
1130 end if
1131 end do
1132 end do
1133
1134
1135 else ! calculate the same lambda matrix on the basis
1136 !call sum_integrals(rdm)
1137 safe_allocate(fvec(1:st%nst))
1138 safe_allocate(fock(1:st%nst, 1:st%nst, 1:st%nst))
1139 fock = m_zero
1140
1141 do iorb = 1, st%nst
1142 do ist = 1, st%nst
1143 do jst = 1, ist
1144 fock(ist, jst, iorb) = st%occ(iorb, 1)*rdm%eone_int(ist,jst)
1145 do jorb = 1, st%nst
1146 !The coefficient of the Exchange term below is only for the Mueller functional
1147 fock(ist ,jst, iorb) = fock(ist, jst, iorb) + st%occ(iorb, 1)*st%occ(jorb, 1)*rdm%Coul(ist, jst, jorb) &
1148 - sqrt(st%occ(iorb, 1))*sqrt(st%occ(jorb, 1))*rdm%Exch(ist, jst, jorb)
1149 end do
1150 fock(jst, ist, iorb) = fock(ist, jst, iorb)
1151 end do
1152 end do
1153 end do
1154
1155 do jorb = 1, st%nst
1156 do ist = 1, st%nst
1157 fvec(ist) = m_zero
1158 do jst = 1, st%nst
1159 fvec(ist) = fvec(ist) + fock(ist, jst, jorb)*rdm%vecnat(jst, jorb)
1160 end do
1161 end do
1162 do iorb= 1, st%nst
1163 lambda(iorb, jorb) = m_zero
1164 do ist = 1, st%nst
1165 lambda(iorb, jorb) = lambda(iorb, jorb) + rdm%vecnat(ist, iorb)*fvec(ist)
1166 end do
1167 end do
1168 end do
1169 end if
1170
1171
1172 if (.not. rdm%do_basis) then
1173 safe_deallocate_a(hpsi)
1174 safe_deallocate_a(hpsi1)
1175 safe_deallocate_a(dpsi)
1176 safe_deallocate_a(dpsi1)
1177 else
1178 safe_deallocate_a(fvec)
1179 safe_deallocate_a(fock)
1180 end if
1181
1182 pop_sub(construct_lambda)
1183 end subroutine construct_lambda
1184
1185 ! ----------------------------------------
1186
1187 ! finds the new states after the minimization of the orbitals (Piris method)
1188 subroutine assign_eigfunctions(rdm, st, lambda)
1189 type(rdm_t), intent(inout) :: rdm
1190 type(states_elec_t), intent(inout) :: st
1191 real(real64), intent(in) :: lambda(:, :)
1192
1193 integer :: iorb, jorb, ist
1194 real(real64), allocatable :: vecnat_new(:,:)
1195
1196 push_sub(assign_eigenfunctions)
1197
1198 safe_allocate(vecnat_new(1:st%nst, 1:st%nst))
1199 do iorb = 1, st%nst
1200 do ist = 1, st%nst
1201 vecnat_new(ist, iorb) = m_zero
1202 do jorb = 1, st%nst
1203 vecnat_new(ist , iorb) = vecnat_new(ist, iorb) + rdm%vecnat(ist, jorb)*lambda(jorb, iorb)
1204 end do
1205 end do
1206 end do
1207
1208 rdm%vecnat = vecnat_new
1209
1210 safe_deallocate_a(vecnat_new)
1211
1212 pop_sub(assign_eigenfunctions)
1213 end subroutine assign_eigfunctions
1214
1215 ! --------------------------------------------
1216
1217 ! calculates the total energy when only the occupation numbers are updated
1218 subroutine total_energy_rdm(rdm, occ, energy, dE_dn)
1219 type(rdm_t), intent(in) :: rdm
1220 real(real64), intent(in) :: occ(:)
1221 real(real64), intent(out) :: energy
1222 real(real64), optional, intent(out) :: dE_dn(:)
1223
1224 integer :: ist, jst
1225 real(real64), allocatable :: V_h(:), V_x(:)
1226
1227 push_sub(total_energy_rdm)
1228
1229 safe_allocate(v_h(1:rdm%nst))
1230 safe_allocate(v_x(1:rdm%nst))
1231
1232 energy = m_zero
1233 v_h = m_zero
1234 v_x = m_zero
1235
1236 !Calculate hartree and exchange contribution
1237 !This is only for the Mueller functional and has to be changed
1238 do ist = 1, rdm%nst
1239 do jst = 1, rdm%nst
1240 v_h(ist) = v_h(ist) + occ(jst)*rdm%hartree(ist, jst)
1241 v_x(ist) = v_x(ist) - sqrt(occ(jst))*rdm%exchange(ist, jst)
1242 end do
1243 v_x(ist) = v_x(ist)*m_half/max(sqrt(occ(ist)), 1.0e-16_real64)
1244 end do
1245
1246
1247 !Calculate the energy derivative with respect to the occupation numbers
1248 if (present(de_dn)) then
1249 de_dn(:) = rdm%eone(:) + v_h(:) + v_x(:)
1250 end if
1251
1252 !Total energy calculation without nuclei interaction
1253 do ist = 1, rdm%nst
1254 energy = energy + occ(ist)*rdm%eone(ist) &
1255 + m_half*occ(ist)*v_h(ist) &
1256 + occ(ist)*v_x(ist)
1257 end do
1258
1259 safe_deallocate_a(v_h)
1260 safe_deallocate_a(v_x)
1261
1262 pop_sub(total_energy_rdm)
1263 end subroutine total_energy_rdm
1264
1265 ! ----------------------------------------
1266 ! calculates the derivatives of the energy terms with respect to the occupation numbers
1267 subroutine rdm_derivatives(rdm, namespace, hm, st, gr, space)
1268 type(rdm_t), intent(inout) :: rdm
1269 type(namespace_t), intent(in) :: namespace
1270 type(hamiltonian_elec_t), intent(in) :: hm
1271 type(states_elec_t), intent(inout) :: st
1272 type(grid_t), intent(in) :: gr
1273 class(space_t), intent(in) :: space
1274
1275
1276 real(real64), allocatable :: hpsi(:,:), rho1(:), rho(:), dpsi(:,:), dpsi2(:,:)
1277 real(real64), allocatable :: v_ij(:,:,:,:,:)
1278 real(real64) :: dd
1279 type(states_elec_t) :: xst
1280
1281 integer :: ist, jst, nspin_, iorb, jorb
1282
1283 push_sub(rdm_derivatives)
1284
1285
1286 nspin_ = min(st%d%nspin, 2)
1287
1288 if (rdm%do_basis.eqv..false.) then
1289 safe_allocate(hpsi(1:gr%np, 1:st%d%dim))
1290 safe_allocate(rho1(1:gr%np))
1291 safe_allocate(rho(1:gr%np))
1292 safe_allocate(dpsi(1:gr%np_part, 1:st%d%dim))
1293 safe_allocate(dpsi2(1:gr%np, 1:st%d%dim))
1294 safe_allocate(v_ij(1:gr%np, 1:st%nst, 1:st%nst, 1:st%nik, 1:st%nik))
1295
1296 v_ij = m_zero
1297 rdm%eone = m_zero
1298 rdm%hartree = m_zero
1299 rdm%exchange = m_zero
1300
1301 !derivative of one-electron energy with respect to the natural orbitals occupation number
1302 do ist = 1, st%nst
1303 call states_elec_get_state(st, gr, ist, 1, dpsi)
1304
1305 ! calculate one-body energy
1306 call dhamiltonian_elec_apply_single(hm, namespace, gr, dpsi, hpsi, ist, 1, &
1308 rdm%eone(ist) = dmf_dotp(gr, dpsi(:, 1), hpsi(:, 1))
1309 end do
1310
1311 !integrals used for the hartree and exchange parts of the total energy and their derivatives
1312 ! maybe better to let that be done from the lower level routines like hamiltonian apply?
1313 !
1314 ! only used to calculate total energy
1315 call xst%nullify()
1316 call dexchange_operator_compute_potentials(hm%exxop, namespace, space, gr, st, xst, hm%kpoints, f_out = v_ij)
1317 call states_elec_end(xst)
1318
1319 do ist = 1, st%nst
1320 call states_elec_get_state(st, gr, ist, 1, dpsi)
1321
1322 rho1(1:gr%np) = dpsi(1:gr%np, 1)**2
1323
1324 do jst = ist, st%nst
1325 rdm%hartree(ist, jst) = dmf_dotp(gr, rho1, v_ij(:,jst, jst, 1, 1))
1326 rdm%hartree(jst, ist) = rdm%hartree(ist, jst)
1327 call states_elec_get_state(st, gr, jst, 1, dpsi2)
1328 rho(1:gr%np) = dpsi2(1:gr%np, 1)*dpsi(1:gr%np, 1)
1329 rdm%exchange(ist, jst) = dmf_dotp(gr, rho, v_ij(:, ist, jst, 1, 1))
1330 rdm%exchange(jst, ist) = rdm%exchange(ist, jst)
1331 end do
1332 end do
1333
1334
1335 safe_deallocate_a(hpsi)
1336 safe_deallocate_a(rho)
1337 safe_deallocate_a(rho1)
1338 safe_deallocate_a(dpsi)
1339 safe_deallocate_a(dpsi2)
1340 safe_deallocate_a(v_ij)
1341
1342 else !if energy derivatives are expanded in a basis set
1343
1344 do iorb = 1, st%nst
1345 rdm%eone(iorb) = m_zero
1346 do ist = 1, st%nst
1347 do jst = 1, st%nst
1348 dd = rdm%vecnat(ist, iorb)*rdm%vecnat(jst, iorb)
1349 rdm%eone(iorb) = rdm%eone(iorb) + dd*rdm%eone_int(ist, jst)
1350 end do
1351 end do
1352 end do
1353
1354 do iorb = 1, st%nst
1355 do jorb =1 , iorb
1356 rdm%hartree(iorb ,jorb) = m_zero
1357 rdm%exchange(iorb,jorb) = m_zero
1358 do ist =1, st%nst
1359 do jst =1, st%nst
1360 dd = rdm%vecnat(ist, iorb)*rdm%vecnat(jst, iorb)
1361 rdm%hartree(iorb ,jorb) = rdm%hartree(iorb ,jorb)+rdm%Coul(ist,jst, jorb)*dd
1362 rdm%exchange(iorb ,jorb) = rdm%exchange(iorb ,jorb)+rdm%Exch(ist,jst, jorb)*dd
1363 end do
1364 end do
1365 rdm%hartree(jorb, iorb) = rdm%hartree(iorb, jorb)
1366 rdm%exchange(jorb, iorb) = rdm%exchange(iorb, jorb)
1367 end do
1368 end do
1369 end if
1370
1371 pop_sub(rdm_derivatives)
1372 end subroutine rdm_derivatives
1373
1374 ! --------------------------------------------
1375 !calculates the one electron integrals in the basis of the initial orbitals
1376 subroutine rdm_integrals(rdm, namespace, hm, st, mesh)
1377 type(rdm_t), intent(inout) :: rdm
1378 type(namespace_t), intent(in) :: namespace
1379 type(hamiltonian_elec_t), intent(in) :: hm
1380 type(states_elec_t), intent(in) :: st
1381 class(mesh_t), intent(in) :: mesh
1382
1383 real(real64), allocatable :: hpsi(:,:)
1384 real(real64), allocatable :: dpsi(:,:), dpsi2(:,:)
1385 integer :: ist, jst
1386
1387 push_sub(rdm_integrals)
1388
1389 safe_allocate(dpsi(1:mesh%np_part, 1:st%d%dim))
1390 safe_allocate(dpsi2(1:mesh%np, 1:st%d%dim))
1391 safe_allocate(hpsi(1:mesh%np, 1:st%d%dim))
1392
1393 !calculate integrals of the one-electron energy term with respect to the initial orbital basis
1394 do ist = 1, st%nst
1395 call states_elec_get_state(st, mesh, ist, 1, dpsi)
1396 do jst = ist, st%nst
1397 call states_elec_get_state(st, mesh, jst, 1, dpsi2)
1398
1399 ! calculate one-body integrals
1400 call dhamiltonian_elec_apply_single(hm, namespace, mesh, dpsi, hpsi, ist, 1, &
1402 rdm%eone_int(jst, ist) = dmf_dotp(mesh, dpsi2(:, 1), hpsi(:, 1))
1403 rdm%eone_int(ist, jst) = rdm%eone_int(jst, ist)
1404 end do
1405 end do
1406
1407 safe_deallocate_a(hpsi)
1408 safe_deallocate_a(dpsi)
1409 safe_deallocate_a(dpsi2)
1410
1411 pop_sub(rdm_integrals)
1412 end subroutine rdm_integrals
1413
1414 ! --------------------------------------------
1415 ! constructs the Hartree and Exchange part of the RDMFT Fock matrix
1416 subroutine sum_integrals(rdm)
1417 type(rdm_t), intent(inout) :: rdm
1418
1419 integer :: ist, jst, kst, lst, iorb, icount
1420 logical :: inv_pairs
1421 real(real64) :: two_int, wij, wik, wil, wjk, wjl, wkl
1422 real(real64), allocatable :: dm(:,:,:)
1423
1424 push_sub(sum_integrals)
1425
1426 safe_allocate(dm(1:rdm%nst, 1:rdm%nst, 1:rdm%nst))
1427
1428 rdm%Coul = m_zero
1429 rdm%Exch = m_zero
1430 dm = m_zero
1431
1432 do iorb = 1, rdm%nst
1433 do ist = 1, rdm%nst
1434 do jst = 1, ist
1435 dm(ist, jst, iorb) = rdm%vecnat(ist, iorb)*rdm%vecnat(jst, iorb)
1436 dm(jst, ist, iorb) = dm(ist, jst, iorb)
1437 end do
1438 end do
1439 end do
1440
1441 do icount = 1, rdm%n_twoint
1442
1443 ist = rdm%i_index(1,icount)
1444 jst = rdm%j_index(1,icount)
1445 kst = rdm%k_index(1,icount)
1446 lst = rdm%l_index(1,icount)
1447
1448 two_int = rdm%twoint(icount)
1449
1450 ! create weights of unique integrals
1451 if(ist == jst) then
1452 wij = m_one
1453 else
1454 wij = m_two
1455 endif
1456 if(kst == lst) then
1457 wkl = m_one
1458 else
1459 wkl = m_two
1460 endif
1461
1462 if(ist == kst .and. jst /= lst) then
1463 wik = m_two
1464 else
1465 wik = m_one
1466 endif
1467 if(ist == lst .and. jst /= kst) then
1468 wil = m_two
1469 else
1470 wil = m_one
1471 endif
1472 if(jst == kst .and. ist /= lst) then
1473 wjk = m_two
1474 else
1475 wjk = m_one
1476 endif
1477 if(jst == lst .and. ist /= kst) then
1478 wjl = m_two
1479 else
1480 wjl = m_one
1481 endif
1482
1483 inv_pairs = (ist /= kst .or. jst /= lst)
1484
1485 do iorb = 1, rdm%nst
1486
1487 !the Hartree terms
1488 rdm%Coul(ist, jst, iorb) = rdm%Coul(ist, jst, iorb) + dm(kst, lst, iorb)*wkl*two_int
1489 if (inv_pairs) rdm%Coul(kst, lst, iorb) = rdm%Coul(kst, lst, iorb) + dm(ist, jst, iorb)*wij*two_int
1490
1491 !the exchange terms
1492 !weights are only included if they can differ from one
1493 rdm%Exch(ist, kst, iorb) = rdm%Exch(ist, kst, iorb) + two_int*dm(jst, lst, iorb)*wik
1494 if (kst /= lst) then
1495 rdm%Exch(ist, lst, iorb) = rdm%Exch(ist, lst, iorb) + two_int*dm(jst, kst, iorb)*wil
1496 end if
1497 if (ist /= jst) then
1498 if(jst >= kst) then
1499 rdm%Exch(jst, kst, iorb) = rdm%Exch(jst, kst, iorb) + two_int*dm(ist, lst, iorb)*wjk
1500 else
1501 if (inv_pairs) rdm%Exch(kst, jst, iorb) = rdm%Exch(kst, jst, iorb) + two_int*dm(ist, lst, iorb)
1502 end if
1503 end if
1504 if (ist /=jst .and. kst /= lst) then
1505 if (jst >= lst) then
1506 rdm%Exch(jst, lst, iorb) = rdm%Exch(jst, lst, iorb) + two_int*dm(ist, kst, iorb)*wjl
1507 else
1508 if (inv_pairs) rdm%Exch(lst, jst, iorb) = rdm%Exch(lst, jst, iorb) + two_int*dm(ist, kst, iorb)
1509 end if
1510 end if
1511
1512 end do !iorb
1513 end do !icount
1514
1515 do iorb =1, rdm%nst
1516 do ist = 1, rdm%nst
1517 do jst = 1, ist-1
1518 rdm%Coul(jst, ist, iorb) = rdm%Coul(ist, jst, iorb)
1519 rdm%Exch(jst, ist, iorb) = rdm%Exch(ist, jst, iorb)
1520 end do
1521 end do
1522 end do
1523
1524 safe_deallocate_a(dm)
1525
1526 pop_sub(sum_integrals)
1527 end subroutine sum_integrals
1528
1529end module rdmft_oct_m
1530
1531
1532!! Local Variables:
1533!! mode: f90
1534!! coding: utf-8
1535!! End:
Prints out to iunit a message in the form: ["InputVariable" = value] where "InputVariable" is given b...
Definition: messages.F90:180
double sin(double __x) __attribute__((__nothrow__
double asin(double __x) __attribute__((__nothrow__
subroutine minimize_multidim(method, dim, x, step, line_tol, tolgrad, toldr, maxiter, f, write_iter_info, minimum, ierr)
Definition: minimizer.F90:403
type(debug_t), save, public debug
Definition: debug.F90:156
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:609
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
subroutine, public dderivatives_partial(der, ff, op_ff, dir, ghost_update, set_bc)
apply the partial derivative along dir to a mesh function
subroutine, public deigensolver_cg(namespace, mesh, st, hm, xc, pre, tol, niter, converged, ik, diff, energy_change_threshold, orthogonalize_to_all, conjugate_direction, additional_terms, shift)
conjugate-gradients method.
Definition: eigen_cg.F90:197
subroutine, public eigensolver_init(eigens, namespace, gr, st, mc, space)
subroutine, public eigensolver_end(eigens)
subroutine, public dexchange_operator_compute_potentials(this, namespace, space, gr, st, xst, kpoints, ex, F_out)
real(real64), parameter, public m_two
Definition: global.F90:190
real(real64), parameter, public m_zero
Definition: global.F90:188
real(real64), parameter, public m_four
Definition: global.F90:192
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:186
character(len= *), parameter, public static_dir
Definition: global.F90:252
real(real64), parameter, public m_half
Definition: global.F90:194
real(real64), parameter, public m_one
Definition: global.F90:189
This module implements the underlying real-space grid.
Definition: grid.F90:117
subroutine, public grid_write_info(gr, iunit, namespace)
Definition: grid.F90:522
integer, parameter, public term_local_external
integer, parameter, public term_non_local_potential
integer, parameter, public term_kinetic
subroutine, public dhamiltonian_elec_apply_single(hm, namespace, mesh, psi, hpsi, ist, ik, terms, set_bc, set_phase)
This module defines classes and functions for interaction partners.
Definition: io.F90:114
subroutine, public io_close(iunit, grp)
Definition: io.F90:418
subroutine, public io_mkdir(fname, namespace, parents)
Definition: io.F90:311
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:352
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:115
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
Definition: messages.F90:920
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1113
character(len=512), private msg
Definition: messages.F90:165
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:537
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:414
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:616
integer minmethod_bfgs
Definition: minimizer.F90:134
This module contains some common usage patterns of MPI routines.
Definition: mpi_lib.F90:115
logical function mpi_grp_is_root(grp)
Is the current MPI process of grpcomm, root.
Definition: mpi.F90:430
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:266
This module handles the communicators for the various parallelization strategies.
Definition: multicomm.F90:145
this module contains the low-level part of the output system
Definition: output_low.F90:115
subroutine, public output_modelmb(outp, namespace, space, dir, gr, ions, iter, st)
this module contains the output system
Definition: output.F90:115
subroutine, public output_all(outp, namespace, space, dir, gr, ions, iter, st, hm, ks)
Definition: output.F90:493
subroutine, public photon_mode_write_info(this, iunit, namespace)
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:623
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:552
subroutine scf_occ(rdm, namespace, gr, hm, space, st, energy)
Definition: rdmft.F90:845
subroutine calc_maxfo(namespace, hm, st, gr, rdm)
Definition: rdmft.F90:683
subroutine objective_rdmft(size, theta, objective, getgrad, df)
Definition: rdmft.F90:991
subroutine scf_orb_cg(rdm, namespace, space, gr, ions, ext_partners, st, ks, hm, energy)
Definition: rdmft.F90:1124
subroutine, public rdmft_end(rdm)
Definition: rdmft.F90:346
subroutine, public rdmft_init(rdm, namespace, gr, st, mc, space, fromScratch)
Definition: rdmft.F90:212
subroutine write_iter_info_rdmft(iter, size, energy, maxdr, maxdf, theta)
Definition: rdmft.F90:1043
subroutine set_occ_pinning(st)
Definition: rdmft.F90:779
subroutine calc_photon_number(space, gr, st, photons, photon_number_state, ekin_state, epot_state)
Definition: rdmft.F90:718
subroutine assign_eigfunctions(rdm, st, lambda)
Definition: rdmft.F90:1282
subroutine, public scf_rdmft(rdm, namespace, space, gr, ions, ext_partners, st, ks, hm, outp, restart_dump)
Definition: rdmft.F90:376
subroutine construct_lambda(namespace, hm, st, gr, lambda, rdm)
Definition: rdmft.F90:1188
subroutine sum_integrals(rdm)
Definition: rdmft.F90:1510
subroutine rdm_integrals(rdm, namespace, hm, st, mesh)
Definition: rdmft.F90:1470
subroutine scf_orb(rdm, namespace, gr, st, hm, space, energy)
Definition: rdmft.F90:1057
subroutine total_energy_rdm(rdm, occ, energy, dE_dn)
Definition: rdmft.F90:1312
subroutine scf_occ_no(rdm, namespace, gr, hm, space, st, energy)
Definition: rdmft.F90:803
subroutine rdm_derivatives(rdm, namespace, hm, st, gr, space)
Definition: rdmft.F90:1361
pure logical function, public states_are_complex(st)
subroutine, public states_elec_end(st)
finalize the states_elec_t object
subroutine, public states_elec_copy(stout, stin, exclude_wfns, exclude_eigenval, special)
make a (selective) copy of a states_elec_t object
This module handles reading and writing restart information for the states_elec_t.
subroutine, public states_elec_dump(restart, space, st, mesh, kpoints, ierr, iter, lr, st_start_writing, verbose)
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:132
character(len=20) pure function, public units_abbrev(this)
Definition: unit.F90:223
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
subroutine, public v_ks_write_info(ks, iunit, namespace)
Definition: v_ks.F90:642
subroutine, public v_ks_calc(ks, namespace, space, hm, st, ions, ext_partners, calc_eigenval, time, calc_energy, calc_current, force_semilocal)
Definition: v_ks.F90:730
subroutine scf_write_static(dir, fname)
Definition: rdmft.F90:581
Extension of space that contains the knowledge of the spin dimension.
Description of the grid, containing information on derivatives, stencil, and symmetries.
Definition: grid.F90:168
Describes mesh distribution to nodes.
Definition: mesh.F90:186
output handler class
Definition: output_low.F90:164
The states_elec_t class contains all electronic wave functions.
int true(void)