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