(git:ce05c02)
Loading...
Searching...
No Matches
qs_active_space_methods.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief Determine active space Hamiltonian
10!> \par History
11!> 04.2016 created [JGH]
12!> \author JGH
13! **************************************************************************************************
15 USE admm_types, ONLY: admm_type, &
25 srules, &
36 USE cp_files, ONLY: close_file, &
43 USE cp_fm_types, ONLY: &
49 USE cp_output_handling, ONLY: &
54 USE cp_dbcsr_api, ONLY: &
55 dbcsr_copy, dbcsr_csr_create, dbcsr_csr_type, dbcsr_p_type, dbcsr_type, dbcsr_release, &
59 USE erf_complex, ONLY: erfz_fast
61 USE input_constants, ONLY: &
71 USE iso_c_binding, ONLY: c_null_char
72 USE kinds, ONLY: default_path_length, &
74 dp, &
75 int_8
77 USE machine, ONLY: m_walltime, m_flush
78 USE mathlib, ONLY: diamat_all
79 USE mathconstants, ONLY: fourpi, twopi, pi, rootpi
81 USE message_passing, ONLY: mp_comm_type, &
85 USE mt_util, ONLY: mt0d
89 USE periodic_table, ONLY: ptable
90 USE physcon, ONLY: angstrom, bohr
92 USE pw_env_methods, ONLY: pw_env_create, &
94 USE pw_env_types, ONLY: pw_env_get, &
100 pw_transfer, &
105 USE pw_poisson_types, ONLY: analytic0d, &
106 periodic3d, &
111 USE pw_pool_types, ONLY: &
113 USE pw_types, ONLY: &
116 USE qcschema, ONLY: qcschema_env_create, &
124 eri_type, &
132 USE qs_environment_types, ONLY: get_qs_env, &
135 USE qs_integrate_potential, ONLY: integrate_v_rspace
136 USE qs_kind_types, ONLY: qs_kind_type
139 USE qs_ks_types, ONLY: qs_ks_did_change, &
143 USE qs_mo_types, ONLY: allocate_mo_set, &
144 get_mo_set, &
145 init_mo_set, &
150 USE qs_rho_types, ONLY: qs_rho_get, &
152 USE qs_subsys_types, ONLY: qs_subsys_get, &
156#ifndef __NO_SOCKETS
157 USE sockets_interface, ONLY: accept_socket, &
158 close_socket, &
161 readbuffer, &
164#endif
169 USE util, ONLY: get_limit
170#include "./base/base_uses.f90"
171
172 IMPLICIT NONE
173 PRIVATE
174
175 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_active_space_methods'
176
177 PUBLIC :: active_space_main
178
179 TYPE, EXTENDS(eri_type_eri_element_func) :: eri_fcidump_print
180 INTEGER :: unit_nr = -1, bra_start = -1, ket_start = -1
181 CONTAINS
182 PROCEDURE :: func => eri_fcidump_print_func
183 END TYPE eri_fcidump_print
184
185 TYPE, EXTENDS(eri_type_eri_element_func) :: eri_fcidump_checksum
186 INTEGER :: bra_start = 0, ket_start = 0
187 REAL(KIND=dp) :: checksum = 0.0_dp
188 CONTAINS
189 PROCEDURE, PASS :: set => eri_fcidump_set
190 PROCEDURE :: func => eri_fcidump_checksum_func
191 END TYPE eri_fcidump_checksum
192
193CONTAINS
194
195! **************************************************************************************************
196!> \brief Sets the starting indices of the bra and ket.
197!> \param this object reference
198!> \param bra_start starting index of the bra
199!> \param ket_start starting index of the ket
200! **************************************************************************************************
201 SUBROUTINE eri_fcidump_set(this, bra_start, ket_start)
202 CLASS(eri_fcidump_checksum) :: this
203 INTEGER, INTENT(IN) :: bra_start, ket_start
204 this%bra_start = bra_start
205 this%ket_start = ket_start
206 END SUBROUTINE eri_fcidump_set
207
208! **************************************************************************************************
209!> \brief Main method for determining the active space Hamiltonian
210!> \param qs_env ...
211! **************************************************************************************************
212 SUBROUTINE active_space_main(qs_env)
213 TYPE(qs_environment_type), POINTER :: qs_env
214
215 CHARACTER(len=*), PARAMETER :: routinen = 'active_space_main'
216
217 CHARACTER(len=10) :: cshell, lnam(5)
218 CHARACTER(len=default_path_length) :: qcschema_filename
219 CHARACTER(LEN=default_string_length) :: basis_type
220 INTEGER :: as_solver, eri_method, eri_operator, eri_print, group_size, handle, i, iatom, &
221 ishell, isp, ispin, iw, j, jm, m, max_orb_ind, mselect, n1, n2, nao, natom, nel, &
222 nelec_active, nelec_inactive, nelec_total, nmo, nmo_active, nmo_available, nmo_inactive, &
223 nmo_inactive_remaining, nmo_occ, nmo_virtual, nn1, nn2, nrow_global, nspins
224 INTEGER, DIMENSION(5) :: nshell
225 INTEGER, DIMENSION(:), POINTER :: invals
226 LOGICAL :: do_ddapc, do_kpoints, ex_omega, &
227 ex_operator, ex_perd, ex_rcut, &
228 explicit, stop_after_print, store_wfn
229 REAL(kind=dp) :: alpha, eri_eps_filter, eri_eps_grid, eri_eps_int, eri_gpw_cutoff, &
230 eri_op_omega, eri_rcut, eri_rel_cutoff, fel, focc, maxocc, nze_percentage
231 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: eigenvalues
232 REAL(kind=dp), DIMENSION(:), POINTER :: evals_virtual
233 TYPE(active_space_type), POINTER :: active_space_env
234 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
235 TYPE(cell_type), POINTER :: cell
236 TYPE(cp_blacs_env_type), POINTER :: context
237 TYPE(cp_fm_struct_type), POINTER :: fm_struct_tmp
238 TYPE(cp_fm_type) :: fm_dummy, mo_virtual
239 TYPE(cp_fm_type), POINTER :: fm_target_active, fm_target_inactive, &
240 fmat, mo_coeff, mo_ref, mo_target
241 TYPE(cp_logger_type), POINTER :: logger
242 TYPE(dbcsr_csr_type), POINTER :: eri_mat
243 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: ks_matrix, rho_ao, s_matrix
244 TYPE(dbcsr_type), POINTER :: denmat
245 TYPE(dft_control_type), POINTER :: dft_control
246 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
247 TYPE(mo_set_type), POINTER :: mo_set, mo_set_active, mo_set_inactive
248 TYPE(mp_para_env_type), POINTER :: para_env
249 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
250 TYPE(preconditioner_type), POINTER :: local_preconditioner
251 TYPE(qcschema_type) :: qcschema_env
252 TYPE(qs_energy_type), POINTER :: energy
253 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
254 TYPE(qs_ks_env_type), POINTER :: ks_env
255 TYPE(qs_rho_type), POINTER :: rho
256 TYPE(scf_control_type), POINTER :: scf_control
257 TYPE(section_vals_type), POINTER :: adiabatic_rescaling, as_input, &
258 hfx_section, input, loc_print, &
259 loc_section, print_orb, xc_section
260
261 !--------------------------------------------------------------------------------------------!
262
263 CALL get_qs_env(qs_env, input=input)
264 as_input => section_vals_get_subs_vals(input, "DFT%ACTIVE_SPACE")
265 CALL section_vals_get(as_input, explicit=explicit)
266 IF (.NOT. explicit) RETURN
267 CALL timeset(routinen, handle)
268
269 logger => cp_get_default_logger()
271
272 IF (iw > 0) THEN
273 WRITE (iw, '(/,T2,A)') &
274 '!-----------------------------------------------------------------------------!'
275 WRITE (iw, '(T26,A)') "Active Space Embedding Module"
276 WRITE (iw, '(T2,A)') &
277 '!-----------------------------------------------------------------------------!'
278 END IF
279
280 ! k-points?
281 CALL get_qs_env(qs_env, do_kpoints=do_kpoints, dft_control=dft_control)
282 IF (do_kpoints) THEN
283 CALL cp_abort(__location__, "k-points not supported in active space module")
284 END IF
285
286 ! adiabatic rescaling?
287 adiabatic_rescaling => section_vals_get_subs_vals(input, "DFT%XC%ADIABATIC_RESCALING")
288 CALL section_vals_get(adiabatic_rescaling, explicit=explicit)
289 IF (explicit) THEN
290 CALL cp_abort(__location__, "Adiabatic rescaling not supported in active space module")
291 END IF
292
293 ! Setup the possible usage of DDAPC charges
294 do_ddapc = dft_control%qs_control%ddapc_restraint .OR. &
295 qs_env%cp_ddapc_ewald%do_decoupling .OR. &
296 qs_env%cp_ddapc_ewald%do_qmmm_periodic_decpl .OR. &
297 qs_env%cp_ddapc_ewald%do_solvation
298 IF (do_ddapc) THEN
299 CALL cp_abort(__location__, "DDAPC charges are not supported in the active space module")
300 END IF
301 IF (dft_control%do_sccs) THEN
302 CALL cp_abort(__location__, "SCCS is not supported in the active space module")
303 END IF
304 IF (dft_control%correct_surf_dip) THEN
305 IF (dft_control%surf_dip_correct_switch) THEN
306 CALL cp_abort(__location__, "Surface dipole correction not supported in the AS module")
307 END IF
308 END IF
309 IF (dft_control%smeagol_control%smeagol_enabled) THEN
310 CALL cp_abort(__location__, "SMEAGOL is not supported in the active space module")
311 END IF
312 IF (dft_control%qs_control%do_kg) THEN
313 CALL cp_abort(__location__, "KG correction not supported in the active space module")
314 END IF
315
316 NULLIFY (active_space_env)
317 CALL create_active_space_type(active_space_env)
318 active_space_env%energy_total = 0.0_dp
319 active_space_env%energy_ref = 0.0_dp
320 active_space_env%energy_inactive = 0.0_dp
321 active_space_env%energy_active = 0.0_dp
322
323 ! input options
324
325 ! figure out what needs to be printed/stored
326 IF (btest(cp_print_key_should_output(logger%iter_info, as_input, "FCIDUMP"), cp_p_file)) THEN
327 active_space_env%fcidump = .true.
328 END IF
329
330 CALL section_vals_val_get(as_input, "QCSCHEMA", c_val=qcschema_filename, explicit=explicit)
331 IF (explicit) THEN
332 active_space_env%qcschema = .true.
333 active_space_env%qcschema_filename = qcschema_filename
334 END IF
335
336 CALL section_vals_val_get(as_input, "ACTIVE_ELECTRONS", i_val=nelec_active)
337 CALL get_qs_env(qs_env, nelectron_total=nelec_total)
338
339 IF (nelec_active <= 0) cpabort("Specify a positive number of active electrons.")
340 IF (nelec_active > nelec_total) cpabort("More active electrons than total electrons.")
341
342 nelec_inactive = nelec_total - nelec_active
343 IF (mod(nelec_inactive, 2) /= 0) THEN
344 cpabort("The remaining number of inactive electrons has to be even.")
345 END IF
346
347 CALL section_vals_val_get(as_input, "ALPHA", r_val=alpha)
348 IF (alpha < 0.0 .OR. alpha > 1.0) cpabort("Specify a damping factor between 0 and 1.")
349 active_space_env%alpha = alpha
350
351 IF (iw > 0) THEN
352 WRITE (iw, '(T3,A,T70,I10)') "Total number of electrons", nelec_total
353 WRITE (iw, '(T3,A,T70,I10)') "Number of inactive electrons", nelec_inactive
354 WRITE (iw, '(T3,A,T70,I10)') "Number of active electrons", nelec_active
355 END IF
356
357 CALL get_qs_env(qs_env, dft_control=dft_control)
358 nspins = dft_control%nspins
359
360 active_space_env%nelec_active = nelec_active
361 active_space_env%nelec_inactive = nelec_inactive
362 active_space_env%nelec_total = nelec_total
363 active_space_env%nspins = nspins
364 active_space_env%multiplicity = dft_control%multiplicity
365
366 ! define the active/inactive space orbitals
367 CALL section_vals_val_get(as_input, "ACTIVE_ORBITALS", explicit=explicit, i_val=nmo_active)
368 IF (.NOT. explicit) THEN
369 CALL cp_abort(__location__, "Number of Active Orbitals has to be specified.")
370 END IF
371 active_space_env%nmo_active = nmo_active
372 ! this is safe because nelec_inactive is always even
373 nmo_inactive = nelec_inactive/2
374 active_space_env%nmo_inactive = nmo_inactive
375
376 CALL section_vals_val_get(as_input, "ORBITAL_SELECTION", i_val=mselect)
377 IF (iw > 0) THEN
378 SELECT CASE (mselect)
379 CASE DEFAULT
380 cpabort("Unknown orbital selection method")
381 CASE (casci_canonical)
382 WRITE (iw, '(/,T3,A)') &
383 "Active space orbitals selected using energy ordered canonical orbitals"
384 CASE (wannier_projection)
385 WRITE (iw, '(/,T3,A)') &
386 "Active space orbitals selected using projected Wannier orbitals"
387 CASE (mao_projection)
388 WRITE (iw, '(/,T3,A)') &
389 "Active space orbitals selected using modified atomic orbitals (MAO)"
390 CASE (manual_selection)
391 WRITE (iw, '(/,T3,A)') &
392 "Active space orbitals selected manually"
393 END SELECT
394
395 WRITE (iw, '(T3,A,T70,I10)') "Number of inactive orbitals", nmo_inactive
396 WRITE (iw, '(T3,A,T70,I10)') "Number of active orbitals", nmo_active
397 END IF
398
399 ! get projection spaces
400 CALL section_vals_val_get(as_input, "SUBSPACE_ATOM", i_val=iatom, explicit=explicit)
401 IF (explicit) THEN
402 CALL get_qs_env(qs_env, natom=natom)
403 IF (iatom <= 0 .OR. iatom > natom) THEN
404 IF (iw > 0) THEN
405 WRITE (iw, '(/,T3,A,I3)') "ERROR: SUBSPACE_ATOM number is not valid", iatom
406 END IF
407 cpabort("Select a valid SUBSPACE_ATOM")
408 END IF
409 END IF
410 CALL section_vals_val_get(as_input, "SUBSPACE_SHELL", c_val=cshell, explicit=explicit)
411 nshell = 0
412 lnam = ""
413 IF (explicit) THEN
414 cshell = adjustl(cshell)
415 n1 = 1
416 DO i = 1, 5
417 ishell = i
418 IF (cshell(n1:n1) == " ") THEN
419 ishell = ishell - 1
420 EXIT
421 END IF
422 READ (cshell(n1:), "(I1,A1)") nshell(i), lnam(i)
423 n1 = n1 + 2
424 END DO
425 END IF
426
427 ! generate orbitals
428 SELECT CASE (mselect)
429 CASE DEFAULT
430 cpabort("Unknown orbital selection method")
431 CASE (casci_canonical)
432 CALL get_qs_env(qs_env, mos=mos)
433
434 ! total number of occupied orbitals, i.e. inactive plus active MOs
435 nmo_occ = nmo_inactive + nmo_active
436
437 ! set inactive orbital indices, these are trivially 1...nmo_inactive
438 ALLOCATE (active_space_env%inactive_orbitals(nmo_inactive, nspins))
439 DO ispin = 1, nspins
440 DO i = 1, nmo_inactive
441 active_space_env%inactive_orbitals(i, ispin) = i
442 END DO
443 END DO
444
445 ! set active orbital indices, these are shifted by nmo_inactive
446 ALLOCATE (active_space_env%active_orbitals(nmo_active, nspins))
447 DO ispin = 1, nspins
448 DO i = 1, nmo_active
449 active_space_env%active_orbitals(i, ispin) = nmo_inactive + i
450 END DO
451 END DO
452
453 ! allocate and initialize inactive and active mo coefficients.
454 ! These are stored in a data structure for the full occupied space:
455 ! for inactive mos, the active subset is set to zero, vice versa for the active mos
456 ! TODO: allocate data structures only for the eaxct number MOs
457 maxocc = 2.0_dp
458 IF (nspins > 1) maxocc = 1.0_dp
459 ALLOCATE (active_space_env%mos_active(nspins))
460 ALLOCATE (active_space_env%mos_inactive(nspins))
461 DO ispin = 1, nspins
462 CALL get_mo_set(mos(ispin), mo_coeff=mo_ref, nao=nao)
463 CALL cp_fm_get_info(mo_ref, context=context, para_env=para_env, nrow_global=nrow_global)
464 ! the right number of active electrons per spin channel is initialized further down
465 CALL allocate_mo_set(active_space_env%mos_active(ispin), nao, nmo_occ, 0, 0.0_dp, maxocc, 0.0_dp)
466 CALL cp_fm_struct_create(fm_struct_tmp, para_env=para_env, context=context, &
467 nrow_global=nrow_global, ncol_global=nmo_occ)
468 CALL init_mo_set(active_space_env%mos_active(ispin), fm_struct=fm_struct_tmp, name="Active Space MO")
469 CALL cp_fm_struct_release(fm_struct_tmp)
470 IF (nspins == 2) THEN
471 nel = nelec_inactive/2
472 ELSE
473 nel = nelec_inactive
474 END IF
475 CALL allocate_mo_set(active_space_env%mos_inactive(ispin), nao, nmo_occ, nel, &
476 REAL(nel, kind=dp), maxocc, 0.0_dp)
477 CALL cp_fm_struct_create(fm_struct_tmp, para_env=para_env, context=context, &
478 nrow_global=nrow_global, ncol_global=nmo_occ)
479 CALL init_mo_set(active_space_env%mos_inactive(ispin), fm_struct=fm_struct_tmp, name="Inactive Space MO")
480 CALL cp_fm_struct_release(fm_struct_tmp)
481 END DO
482
483 ! create canonical orbitals
484 CALL get_qs_env(qs_env, scf_control=scf_control)
485 IF (dft_control%roks .AND. scf_control%roks_scheme /= high_spin_roks) THEN
486 cpabort("Unclear how we define MOs in the general restricted case ... stopping")
487 ELSE
488 IF (dft_control%do_admm) THEN
489 IF (dft_control%do_admm_mo) THEN
490 cpabort("ADMM currently possible only with purification none_dm")
491 END IF
492 END IF
493
494 ALLOCATE (eigenvalues(nmo_occ, nspins))
495 eigenvalues = 0.0_dp
496 CALL get_qs_env(qs_env, matrix_ks=ks_matrix, matrix_s=s_matrix, scf_control=scf_control)
497
498 ! calculate virtual MOs and copy inactive and active orbitals
499 IF (iw > 0) THEN
500 WRITE (iw, '(/,T3,A)') "Calculating virtual MOs..."
501 END IF
502 DO ispin = 1, nspins
503 ! nmo_available is the number of MOs available from the SCF calculation:
504 ! this is at least the number of occupied orbitals in the SCF, plus
505 ! any number of added MOs (virtuals) requested in the SCF section
506 CALL get_mo_set(mos(ispin), mo_coeff=mo_ref, nmo=nmo_available)
507
508 ! calculate how many extra MOs we still have to compute
509 nmo_virtual = nmo_occ - nmo_available
510 nmo_virtual = max(nmo_virtual, 0)
511
512 NULLIFY (evals_virtual)
513 ALLOCATE (evals_virtual(nmo_virtual))
514
515 CALL cp_fm_get_info(mo_ref, context=context, para_env=para_env, &
516 nrow_global=nrow_global)
517
518 CALL cp_fm_struct_create(fm_struct_tmp, para_env=para_env, context=context, &
519 nrow_global=nrow_global, ncol_global=nmo_virtual)
520 CALL cp_fm_create(mo_virtual, fm_struct_tmp, name="virtual")
521 CALL cp_fm_struct_release(fm_struct_tmp)
522 CALL cp_fm_init_random(mo_virtual, nmo_virtual)
523
524 NULLIFY (local_preconditioner)
525
526 ! compute missing virtual MOs
527 CALL ot_eigensolver(matrix_h=ks_matrix(ispin)%matrix, matrix_s=s_matrix(1)%matrix, &
528 matrix_c_fm=mo_virtual, matrix_orthogonal_space_fm=mo_ref, &
529 eps_gradient=scf_control%eps_lumos, &
530 preconditioner=local_preconditioner, &
531 iter_max=scf_control%max_iter_lumos, &
532 size_ortho_space=nmo_available)
533
534 ! get the eigenvalues
535 CALL calculate_subspace_eigenvalues(mo_virtual, ks_matrix(ispin)%matrix, evals_virtual)
536
537 ! we need to send the copy of MOs to preserve the sign
538 CALL cp_fm_create(fm_dummy, mo_ref%matrix_struct)
539 CALL cp_fm_to_fm(mo_ref, fm_dummy)
540 CALL calculate_subspace_eigenvalues(fm_dummy, ks_matrix(ispin)%matrix, &
541 evals_arg=eigenvalues(:, ispin), do_rotation=.true.)
542
543 ! copy inactive orbitals
544 mo_set => active_space_env%mos_inactive(ispin)
545 CALL get_mo_set(mo_set, mo_coeff=mo_target)
546 DO i = 1, SIZE(active_space_env%inactive_orbitals, 1)
547 m = active_space_env%inactive_orbitals(i, ispin)
548 CALL cp_fm_to_fm(mo_ref, mo_target, 1, m, m)
549 mo_set%eigenvalues(m) = eigenvalues(m, ispin)
550 IF (nspins > 1) THEN
551 mo_set%occupation_numbers(m) = 1.0
552 ELSE
553 mo_set%occupation_numbers(m) = 2.0
554 END IF
555 END DO
556
557 ! copy active orbitals
558 mo_set => active_space_env%mos_active(ispin)
559 CALL get_mo_set(mo_set, mo_coeff=mo_target)
560 ! for mult > 1, put the polarized electrons in the alpha channel
561 IF (nspins == 2) THEN
562 IF (ispin == 1) THEN
563 nel = (nelec_active + active_space_env%multiplicity - 1)/2
564 ELSE
565 nel = (nelec_active - active_space_env%multiplicity + 1)/2
566 END IF
567 ELSE
568 nel = nelec_active
569 END IF
570 mo_set%nelectron = nel
571 mo_set%n_el_f = real(nel, kind=dp)
572 DO i = 1, nmo_active
573 m = active_space_env%active_orbitals(i, ispin)
574 IF (m > nmo_available) THEN
575 CALL cp_fm_to_fm(mo_virtual, mo_target, 1, m - nmo_available, m)
576 eigenvalues(m, ispin) = evals_virtual(m - nmo_available)
577 mo_set%occupation_numbers(m) = 0.0
578 ELSE
579 CALL cp_fm_to_fm(mo_ref, mo_target, 1, m, m)
580 mo_set%occupation_numbers(m) = mos(ispin)%occupation_numbers(m)
581 END IF
582 mo_set%eigenvalues(m) = eigenvalues(m, ispin)
583 END DO
584 ! Release
585 DEALLOCATE (evals_virtual)
586 CALL cp_fm_release(fm_dummy)
587 CALL cp_fm_release(mo_virtual)
588 END DO
589
590 IF (iw > 0) THEN
591 DO ispin = 1, nspins
592 WRITE (iw, '(/,T3,A,I3,T66,A)') "Canonical Orbital Selection for spin", ispin, &
593 "[atomic units]"
594 DO i = 1, nmo_inactive, 4
595 jm = min(3, nmo_inactive - i)
596 WRITE (iw, '(T3,4(F14.6,A5))') (eigenvalues(i + j, ispin), " [I]", j=0, jm)
597 END DO
598 DO i = nmo_inactive + 1, nmo_inactive + nmo_active, 4
599 jm = min(3, nmo_inactive + nmo_active - i)
600 WRITE (iw, '(T3,4(F14.6,A5))') (eigenvalues(i + j, ispin), " [A]", j=0, jm)
601 END DO
602 WRITE (iw, '(/,T3,A,I3)') "Active Orbital Indices for spin", ispin
603 DO i = 1, SIZE(active_space_env%active_orbitals, 1), 4
604 jm = min(3, SIZE(active_space_env%active_orbitals, 1) - i)
605 WRITE (iw, '(T3,4(I4))') (active_space_env%active_orbitals(i + j, ispin), j=0, jm)
606 END DO
607 END DO
608 END IF
609 DEALLOCATE (eigenvalues)
610 END IF
611
612 CASE (manual_selection)
613 ! create canonical orbitals
614 IF (dft_control%roks) THEN
615 cpabort("Unclear how we define MOs in the restricted case ... stopping")
616 ELSE
617 IF (dft_control%do_admm) THEN
618 ! For admm_mo, the auxiliary density is computed from the MOs, which never change
619 ! in the rs-dft embedding, therefore the energy is wrong as the LR HFX never changes.
620 ! For admm_dm, the auxiliary density is computed from the density matrix, which is
621 ! updated at each iteration and therefore works.
622 IF (dft_control%do_admm_mo) THEN
623 cpabort("ADMM currently possible only with purification none_dm")
624 END IF
625 END IF
626
627 CALL section_vals_val_get(as_input, "ACTIVE_ORBITAL_INDICES", explicit=explicit, i_vals=invals)
628 IF (.NOT. explicit) THEN
629 CALL cp_abort(__location__, "Manual orbital selection requires to explicitly "// &
630 "set the active orbital indices via ACTIVE_ORBITAL_INDICES")
631 END IF
632
633 IF (nspins == 1) THEN
634 cpassert(SIZE(invals) == nmo_active)
635 ELSE
636 cpassert(SIZE(invals) == 2*nmo_active)
637 END IF
638 ALLOCATE (active_space_env%inactive_orbitals(nmo_inactive, nspins))
639 ALLOCATE (active_space_env%active_orbitals(nmo_active, nspins))
640
641 DO ispin = 1, nspins
642 DO i = 1, nmo_active
643 active_space_env%active_orbitals(i, ispin) = invals(i + (ispin - 1)*nmo_active)
644 END DO
645 END DO
646
647 CALL get_qs_env(qs_env, mos=mos)
648
649 ! include MOs up to the largest index in the list
650 max_orb_ind = maxval(invals)
651 maxocc = 2.0_dp
652 IF (nspins > 1) maxocc = 1.0_dp
653 ALLOCATE (active_space_env%mos_active(nspins))
654 ALLOCATE (active_space_env%mos_inactive(nspins))
655 DO ispin = 1, nspins
656 ! init active orbitals
657 CALL get_mo_set(mos(ispin), mo_coeff=mo_ref, nao=nao)
658 CALL cp_fm_get_info(mo_ref, context=context, para_env=para_env, nrow_global=nrow_global)
659 CALL allocate_mo_set(active_space_env%mos_active(ispin), nao, max_orb_ind, 0, 0.0_dp, maxocc, 0.0_dp)
660 CALL cp_fm_struct_create(fm_struct_tmp, para_env=para_env, context=context, &
661 nrow_global=nrow_global, ncol_global=max_orb_ind)
662 CALL init_mo_set(active_space_env%mos_active(ispin), fm_struct=fm_struct_tmp, name="Active Space MO")
663 CALL cp_fm_struct_release(fm_struct_tmp)
664
665 ! init inactive orbitals
666 IF (nspins == 2) THEN
667 nel = nelec_inactive/2
668 ELSE
669 nel = nelec_inactive
670 END IF
671 CALL allocate_mo_set(active_space_env%mos_inactive(ispin), nao, max_orb_ind, nel, real(nel, kind=dp), maxocc, 0.0_dp)
672 CALL cp_fm_struct_create(fm_struct_tmp, para_env=para_env, context=context, &
673 nrow_global=nrow_global, ncol_global=max_orb_ind)
674 CALL init_mo_set(active_space_env%mos_inactive(ispin), fm_struct=fm_struct_tmp, name="Inactive Space MO")
675 ! small hack: set the correct inactive occupations down below
676 active_space_env%mos_inactive(ispin)%occupation_numbers = 0.0_dp
677 CALL cp_fm_struct_release(fm_struct_tmp)
678 END DO
679
680 ALLOCATE (eigenvalues(max_orb_ind, nspins))
681 eigenvalues = 0.0_dp
682 CALL get_qs_env(qs_env, matrix_ks=ks_matrix, matrix_s=s_matrix, scf_control=scf_control)
683
684 ! calculate virtual MOs and copy inactive and active orbitals
685 IF (iw > 0) THEN
686 WRITE (iw, '(/,T3,A)') "Calculating virtual MOs..."
687 END IF
688 DO ispin = 1, nspins
689 CALL get_mo_set(mos(ispin), mo_coeff=mo_ref, nmo=nmo_available)
690 nmo_virtual = max_orb_ind - nmo_available
691 nmo_virtual = max(nmo_virtual, 0)
692
693 NULLIFY (evals_virtual)
694 ALLOCATE (evals_virtual(nmo_virtual))
695
696 CALL cp_fm_get_info(mo_ref, context=context, para_env=para_env, &
697 nrow_global=nrow_global)
698
699 CALL cp_fm_struct_create(fm_struct_tmp, para_env=para_env, context=context, &
700 nrow_global=nrow_global, ncol_global=nmo_virtual)
701 CALL cp_fm_create(mo_virtual, fm_struct_tmp, name="virtual")
702 CALL cp_fm_struct_release(fm_struct_tmp)
703 CALL cp_fm_init_random(mo_virtual, nmo_virtual)
704
705 NULLIFY (local_preconditioner)
706
707 CALL ot_eigensolver(matrix_h=ks_matrix(ispin)%matrix, matrix_s=s_matrix(1)%matrix, &
708 matrix_c_fm=mo_virtual, matrix_orthogonal_space_fm=mo_ref, &
709 eps_gradient=scf_control%eps_lumos, &
710 preconditioner=local_preconditioner, &
711 iter_max=scf_control%max_iter_lumos, &
712 size_ortho_space=nmo_available)
713
714 CALL calculate_subspace_eigenvalues(mo_virtual, ks_matrix(ispin)%matrix, &
715 evals_virtual)
716
717 ! We need to send the copy of MOs to preserve the sign
718 CALL cp_fm_create(fm_dummy, mo_ref%matrix_struct)
719 CALL cp_fm_to_fm(mo_ref, fm_dummy)
720
721 CALL calculate_subspace_eigenvalues(fm_dummy, ks_matrix(ispin)%matrix, &
722 evals_arg=eigenvalues(:, ispin), do_rotation=.true.)
723
724 mo_set_active => active_space_env%mos_active(ispin)
725 CALL get_mo_set(mo_set_active, mo_coeff=fm_target_active)
726 mo_set_inactive => active_space_env%mos_inactive(ispin)
727 CALL get_mo_set(mo_set_inactive, mo_coeff=fm_target_inactive)
728
729 ! copy orbitals
730 nmo_inactive_remaining = nmo_inactive
731 DO i = 1, max_orb_ind
732 ! case for i being an active orbital
733 IF (any(active_space_env%active_orbitals(:, ispin) == i)) THEN
734 IF (i > nmo_available) THEN
735 CALL cp_fm_to_fm(mo_virtual, fm_target_active, 1, i - nmo_available, i)
736 eigenvalues(i, ispin) = evals_virtual(i - nmo_available)
737 mo_set_active%occupation_numbers(i) = 0.0
738 ELSE
739 CALL cp_fm_to_fm(fm_dummy, fm_target_active, 1, i, i)
740 mo_set_active%occupation_numbers(i) = mos(ispin)%occupation_numbers(i)
741 END IF
742 mo_set_active%eigenvalues(i) = eigenvalues(i, ispin)
743 ! if it was not an active orbital, check whether it is an inactive orbital
744 ELSEIF (nmo_inactive_remaining > 0) THEN
745 CALL cp_fm_to_fm(fm_dummy, fm_target_inactive, 1, i, i)
746 ! store on the fly the mapping of inactive orbitals
747 active_space_env%inactive_orbitals(nmo_inactive - nmo_inactive_remaining + 1, ispin) = i
748 mo_set_inactive%eigenvalues(i) = eigenvalues(i, ispin)
749 mo_set_inactive%occupation_numbers(i) = mos(ispin)%occupation_numbers(i)
750 ! hack: set homo and lumo manually
751 IF (nmo_inactive_remaining == 1) THEN
752 mo_set_inactive%homo = i
753 mo_set_inactive%lfomo = i + 1
754 END IF
755 nmo_inactive_remaining = nmo_inactive_remaining - 1
756 ELSE
757 cycle
758 END IF
759 END DO
760
761 ! Release
762 DEALLOCATE (evals_virtual)
763 CALL cp_fm_release(fm_dummy)
764 CALL cp_fm_release(mo_virtual)
765 END DO
766
767 IF (iw > 0) THEN
768 DO ispin = 1, nspins
769 WRITE (iw, '(/,T3,A,I3,T66,A)') "Orbital Energies and Selection for spin", ispin, "[atomic units]"
770
771 DO i = 1, max_orb_ind, 4
772 jm = min(3, max_orb_ind - i)
773 WRITE (iw, '(T4)', advance="no")
774 DO j = 0, jm
775 IF (any(active_space_env%active_orbitals(:, ispin) == i + j)) THEN
776 WRITE (iw, '(T3,F12.6,A5)', advance="no") eigenvalues(i + j, ispin), " [A]"
777 ELSEIF (any(active_space_env%inactive_orbitals(:, ispin) == i + j)) THEN
778 WRITE (iw, '(T3,F12.6,A5)', advance="no") eigenvalues(i + j, ispin), " [I]"
779 ELSE
780 WRITE (iw, '(T3,F12.6,A5)', advance="no") eigenvalues(i + j, ispin), " [V]"
781 END IF
782 END DO
783 WRITE (iw, *)
784 END DO
785 WRITE (iw, '(/,T3,A,I3)') "Active Orbital Indices for spin", ispin
786 DO i = 1, SIZE(active_space_env%active_orbitals, 1), 4
787 jm = min(3, SIZE(active_space_env%active_orbitals, 1) - i)
788 WRITE (iw, '(T3,4(I4))') (active_space_env%active_orbitals(i + j, ispin), j=0, jm)
789 END DO
790 END DO
791 END IF
792 DEALLOCATE (eigenvalues)
793 END IF
794
795 CASE (wannier_projection)
796 NULLIFY (loc_section, loc_print)
797 loc_section => section_vals_get_subs_vals(as_input, "LOCALIZE")
798 cpassert(ASSOCIATED(loc_section))
799 loc_print => section_vals_get_subs_vals(as_input, "LOCALIZE%PRINT")
800 !
801 cpabort("not yet available")
802 !
803 CASE (mao_projection)
804 !
805 cpabort("not yet available")
806 !
807 END SELECT
808
809 ! Print orbitals on Cube files
810 print_orb => section_vals_get_subs_vals(as_input, "PRINT_ORBITAL_CUBES")
811 CALL section_vals_get(print_orb, explicit=explicit)
812 CALL section_vals_val_get(print_orb, "STOP_AFTER_CUBES", l_val=stop_after_print)
813 IF (explicit) THEN
814 !
815 CALL print_orbital_cubes(print_orb, qs_env, active_space_env%mos_active)
816 !
817 IF (stop_after_print) THEN
818
819 IF (iw > 0) THEN
820 WRITE (iw, '(/,T2,A)') &
821 '!----------------- Early End of Active Space Interface -----------------------!'
822 END IF
823
824 CALL timestop(handle)
825
826 RETURN
827 END IF
828 END IF
829
830 ! calculate inactive density matrix
831 CALL get_qs_env(qs_env, rho=rho)
832 CALL qs_rho_get(rho, rho_ao=rho_ao)
833 cpassert(ASSOCIATED(rho_ao))
834 CALL dbcsr_allocate_matrix_set(active_space_env%pmat_inactive, nspins)
835 DO ispin = 1, nspins
836 ALLOCATE (denmat)
837 CALL dbcsr_copy(denmat, rho_ao(ispin)%matrix)
838 mo_set => active_space_env%mos_inactive(ispin)
839 CALL calculate_density_matrix(mo_set, denmat)
840 active_space_env%pmat_inactive(ispin)%matrix => denmat
841 END DO
842
843 ! read in ERI parameters
844 CALL section_vals_val_get(as_input, "ERI%METHOD", i_val=eri_method)
845 active_space_env%eri%method = eri_method
846 CALL section_vals_val_get(as_input, "ERI%OPERATOR", i_val=eri_operator, explicit=ex_operator)
847 active_space_env%eri%operator = eri_operator
848 CALL section_vals_val_get(as_input, "ERI%OMEGA", r_val=eri_op_omega, explicit=ex_omega)
849 active_space_env%eri%omega = eri_op_omega
850 CALL section_vals_val_get(as_input, "ERI%CUTOFF_RADIUS", r_val=eri_rcut, explicit=ex_rcut)
851 active_space_env%eri%cutoff_radius = eri_rcut ! this is already converted to bohr!
852 CALL section_vals_val_get(as_input, "ERI%PERIODICITY", i_vals=invals, explicit=ex_perd)
853 CALL section_vals_val_get(as_input, "ERI%EPS_INTEGRAL", r_val=eri_eps_int)
854 active_space_env%eri%eps_integral = eri_eps_int
855 ! if eri periodicity is explicitly set, we use it, otherwise we use the cell periodicity
856 IF (ex_perd) THEN
857 IF (SIZE(invals) == 1) THEN
858 active_space_env%eri%periodicity(1:3) = invals(1)
859 ELSE
860 active_space_env%eri%periodicity(1:3) = invals(1:3)
861 END IF
862 ELSE
863 CALL get_qs_env(qs_env, cell=cell)
864 active_space_env%eri%periodicity(1:3) = cell%perd(1:3)
865 END IF
866 IF (iw > 0) THEN
867 WRITE (iw, '(/,T3,A)') "Calculation of Electron Repulsion Integrals"
868
869 SELECT CASE (eri_method)
871 WRITE (iw, '(T3,A,T50,A)') "Integration method", "GPW Fourier transform over MOs"
872 CASE (eri_method_gpw_ht)
873 WRITE (iw, '(T3,A,T44,A)') "Integration method", "Half transformed integrals from GPW"
874 CASE DEFAULT
875 cpabort("Unknown ERI method")
876 END SELECT
877
878 SELECT CASE (eri_operator)
880 WRITE (iw, '(T3,A,T73,A)') "ERI operator", "Coulomb"
881
883 WRITE (iw, '(T3,A,T74,A)') "ERI operator", "Yukawa"
884 IF (.NOT. ex_omega) CALL cp_abort(__location__, &
885 "Yukawa operator requires OMEGA to be explicitly set")
886 WRITE (iw, '(T3,A,T66,F14.3)') "ERI operator parameter OMEGA", eri_op_omega
887
888 CASE (eri_operator_erf)
889 WRITE (iw, '(T3,A,T63,A)') "ERI operator", "Longrange Coulomb"
890 IF (.NOT. ex_omega) CALL cp_abort(__location__, &
891 "Longrange operator requires OMEGA to be explicitly set")
892 WRITE (iw, '(T3,A,T66,F14.3)') "ERI operator parameter OMEGA", eri_op_omega
893
894 CASE (eri_operator_erfc)
895 WRITE (iw, '(T3,A,T62,A)') "ERI operator", "Shortrange Coulomb"
896 IF (.NOT. ex_omega) CALL cp_abort(__location__, &
897 "Shortrange operator requires OMEGA to be explicitly set")
898 WRITE (iw, '(T3,A,T66,F14.3)') "ERI operator parameter OMEGA", eri_op_omega
899
900 CASE (eri_operator_trunc)
901 WRITE (iw, '(T3,A,T63,A)') "ERI operator", "Truncated Coulomb"
902 IF (.NOT. ex_rcut) CALL cp_abort(__location__, &
903 "Cutoff radius not specified for trunc. Coulomb operator")
904 WRITE (iw, '(T3,A,T66,F14.3)') "ERI operator cutoff radius (au)", eri_rcut
905
907 WRITE (iw, '(T3,A,T53,A)') "ERI operator", "Longrange truncated Coulomb"
908 IF (.NOT. ex_rcut) CALL cp_abort(__location__, &
909 "Cutoff radius not specified for trunc. longrange operator")
910 WRITE (iw, '(T3,A,T66,F14.3)') "ERI operator cutoff radius (au)", eri_rcut
911 IF (.NOT. ex_omega) CALL cp_abort(__location__, &
912 "LR truncated operator requires OMEGA to be explicitly set")
913 WRITE (iw, '(T3,A,T66,F14.3)') "ERI operator parameter OMEGA", eri_op_omega
914 IF (eri_op_omega < 0.01_dp) THEN
915 cpabort("LR truncated operator requires OMEGA >= 0.01 to be stable")
916 END IF
917
918 CASE DEFAULT
919 cpabort("Unknown ERI operator")
920
921 END SELECT
922
923 WRITE (iw, '(T3,A,T68,E12.4)') "Accuracy of ERIs", eri_eps_int
924 WRITE (iw, '(T3,A,T71,3I3)') "Periodicity", active_space_env%eri%periodicity(1:3)
925
926 ! TODO: should be moved after ERI calculation, as it depends on screening
927 IF (nspins < 2) THEN
928 WRITE (iw, '(T3,A,T68,I12)') "Total Number of ERI", (nmo_active**4)/8
929 ELSE
930 WRITE (iw, '(T3,A,T68,I12)') "Total Number of ERI (aa|aa)", (nmo_active**4)/8
931 WRITE (iw, '(T3,A,T68,I12)') "Total Number of ERI (bb|bb)", (nmo_active**4)/8
932 WRITE (iw, '(T3,A,T68,I12)') "Total Number of ERI (aa|bb)", (nmo_active**4)/4
933 END IF
934 END IF
935
936 ! allocate container for integrals (CSR matrix)
937 CALL get_qs_env(qs_env, para_env=para_env)
938 m = (nspins*(nspins + 1))/2
939 ! With ROHF/ROKS, we need ERIs from only a single set of orbitals
940 IF (dft_control%roks) m = 1
941 ALLOCATE (active_space_env%eri%eri(m))
942 DO i = 1, m
943 CALL get_mo_set(active_space_env%mos_active(1), nmo=nmo)
944 ALLOCATE (active_space_env%eri%eri(i)%csr_mat)
945 eri_mat => active_space_env%eri%eri(i)%csr_mat
946 IF (i == 1) THEN
947 n1 = nmo
948 n2 = nmo
949 ELSEIF (i == 2) THEN
950 n1 = nmo
951 n2 = nmo
952 ELSE
953 n1 = nmo
954 n2 = nmo
955 END IF
956 nn1 = (n1*(n1 + 1))/2
957 nn2 = (n2*(n2 + 1))/2
958 CALL dbcsr_csr_create(eri_mat, nn1, nn2, 0_int_8, 0, 0, para_env%get_handle())
959 active_space_env%eri%norb = nmo
960 END DO
961
962 SELECT CASE (eri_method)
964 CALL section_vals_val_get(as_input, "ERI_GPW%EPS_GRID", r_val=eri_eps_grid)
965 active_space_env%eri%eri_gpw%eps_grid = eri_eps_grid
966 CALL section_vals_val_get(as_input, "ERI_GPW%EPS_FILTER", r_val=eri_eps_filter)
967 active_space_env%eri%eri_gpw%eps_filter = eri_eps_filter
968 CALL section_vals_val_get(as_input, "ERI_GPW%CUTOFF", r_val=eri_gpw_cutoff)
969 active_space_env%eri%eri_gpw%cutoff = eri_gpw_cutoff
970 CALL section_vals_val_get(as_input, "ERI_GPW%REL_CUTOFF", r_val=eri_rel_cutoff)
971 active_space_env%eri%eri_gpw%rel_cutoff = eri_rel_cutoff
972 CALL section_vals_val_get(as_input, "ERI_GPW%PRINT_LEVEL", i_val=eri_print)
973 active_space_env%eri%eri_gpw%print_level = eri_print
974 CALL section_vals_val_get(as_input, "ERI_GPW%STORE_WFN", l_val=store_wfn)
975 active_space_env%eri%eri_gpw%store_wfn = store_wfn
976 CALL section_vals_val_get(as_input, "ERI_GPW%GROUP_SIZE", i_val=group_size)
977 active_space_env%eri%eri_gpw%group_size = group_size
978 ! Always redo Poisson solver for now
979 active_space_env%eri%eri_gpw%redo_poisson = .true.
980 ! active_space_env%eri%eri_gpw%redo_poisson = (ex_operator .OR. ex_perd)
981 IF (iw > 0) THEN
982 WRITE (iw, '(/,T2,A,T71,F10.1)') "ERI_GPW| Energy cutoff [Ry]", eri_gpw_cutoff
983 WRITE (iw, '(T2,A,T71,F10.1)') "ERI_GPW| Relative energy cutoff [Ry]", eri_rel_cutoff
984 END IF
985 !
986 CALL calculate_eri_gpw(active_space_env%mos_active, active_space_env%active_orbitals, active_space_env%eri, qs_env, iw, &
987 dft_control%roks)
988 !
989 CASE DEFAULT
990 cpabort("Unknown ERI method")
991 END SELECT
992 IF (iw > 0) THEN
993 DO isp = 1, SIZE(active_space_env%eri%eri)
994 eri_mat => active_space_env%eri%eri(isp)%csr_mat
995 nze_percentage = 100.0_dp*(real(eri_mat%nze_total, kind=dp) &
996 /real(eri_mat%nrows_total, kind=dp))/real(eri_mat%ncols_total, kind=dp)
997 WRITE (iw, '(/,T2,A,I2,T30,A,T68,I12)') "ERI_GPW| Spinmatrix:", isp, &
998 "Number of CSR non-zero elements:", eri_mat%nze_total
999 WRITE (iw, '(T2,A,I2,T30,A,T68,F12.4)') "ERI_GPW| Spinmatrix:", isp, &
1000 "Percentage CSR non-zero elements:", nze_percentage
1001 WRITE (iw, '(T2,A,I2,T30,A,T68,I12)') "ERI_GPW| Spinmatrix:", isp, &
1002 "nrows_total", eri_mat%nrows_total
1003 WRITE (iw, '(T2,A,I2,T30,A,T68,I12)') "ERI_GPW| Spinmatrix:", isp, &
1004 "ncols_total", eri_mat%ncols_total
1005 WRITE (iw, '(T2,A,I2,T30,A,T68,I12)') "ERI_GPW| Spinmatrix:", isp, &
1006 "nrows_local", eri_mat%nrows_local
1007 END DO
1008 CALL m_flush(iw)
1009 END IF
1010 CALL para_env%sync()
1011
1012 ! set the reference active space density matrix
1013 nspins = active_space_env%nspins
1014 ALLOCATE (active_space_env%p_active(nspins))
1015 DO isp = 1, nspins
1016 mo_set => active_space_env%mos_active(isp)
1017 CALL get_mo_set(mo_set, mo_coeff=mo_coeff, nmo=nmo)
1018 CALL create_subspace_matrix(mo_coeff, active_space_env%p_active(isp), nmo)
1019 END DO
1020 SELECT CASE (mselect)
1021 CASE DEFAULT
1022 cpabort("Unknown orbital selection method")
1024 focc = 2.0_dp
1025 IF (nspins == 2) focc = 1.0_dp
1026 DO isp = 1, nspins
1027 fmat => active_space_env%p_active(isp)
1028 CALL cp_fm_set_all(fmat, alpha=0.0_dp)
1029 IF (nspins == 2) THEN
1030 IF (isp == 1) THEN
1031 nel = (active_space_env%nelec_active + active_space_env%multiplicity - 1)/2
1032 ELSE
1033 nel = (active_space_env%nelec_active - active_space_env%multiplicity + 1)/2
1034 END IF
1035 ELSE
1036 nel = active_space_env%nelec_active
1037 END IF
1038 DO i = 1, nmo_active
1039 m = active_space_env%active_orbitals(i, isp)
1040 fel = min(focc, real(nel, kind=dp))
1041 CALL cp_fm_set_element(fmat, m, m, fel)
1042 nel = nel - nint(fel)
1043 nel = max(nel, 0)
1044 END DO
1045 END DO
1046 CASE (wannier_projection)
1047 cpabort("NOT IMPLEMENTED")
1048 CASE (mao_projection)
1049 cpabort("NOT IMPLEMENTED")
1050 END SELECT
1051
1052 ! compute alpha-beta overlap matrix in case of spin-polarized calculation
1053 CALL calculate_spin_pol_overlap(active_space_env%mos_active, qs_env, active_space_env)
1054
1055 ! figure out if we have a new xc section for the AS
1056 xc_section => section_vals_get_subs_vals(input, "DFT%ACTIVE_SPACE%XC")
1057 explicit = .false.
1058 IF (ASSOCIATED(xc_section)) CALL section_vals_get(xc_section, explicit=explicit)
1059
1060 ! rebuild KS matrix if needed
1061 IF (explicit) THEN
1062 ! release the hfx data if it was part of the SCF functional
1063 IF (ASSOCIATED(qs_env%x_data)) CALL hfx_release(qs_env%x_data)
1064 ! also release the admm environment in case we are using admm
1065 IF (ASSOCIATED(qs_env%admm_env)) CALL admm_env_release(qs_env%admm_env)
1066
1067 CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, qs_kind_set=qs_kind_set, &
1068 particle_set=particle_set, cell=cell, ks_env=ks_env)
1069 IF (dft_control%do_admm) THEN
1070 basis_type = 'AUX_FIT'
1071 ELSE
1072 basis_type = 'ORB'
1073 END IF
1074 hfx_section => section_vals_get_subs_vals(xc_section, "HF")
1075 CALL hfx_create(qs_env%x_data, para_env, hfx_section, atomic_kind_set, &
1076 qs_kind_set, particle_set, dft_control, cell, orb_basis=basis_type, &
1077 nelectron_total=nelec_total)
1078
1079 qs_env%requires_matrix_vxc = .true. ! needs to be set only once
1080
1081 ! a bit of a hack: this forces a new re-init of HFX
1082 CALL set_ks_env(ks_env, s_mstruct_changed=.true.)
1083 CALL qs_ks_build_kohn_sham_matrix(qs_env, calculate_forces=.false., &
1084 just_energy=.false., &
1085 ext_xc_section=xc_section)
1086 ! we need to reset it to false
1087 CALL set_ks_env(ks_env, s_mstruct_changed=.false.)
1088 ELSE
1089 xc_section => section_vals_get_subs_vals(input, "DFT%XC")
1090 END IF
1091 ! set the xc_section
1092 active_space_env%xc_section => xc_section
1093
1094 CALL get_qs_env(qs_env, energy=energy)
1095 ! transform KS/Fock, Vxc and Hcore to AS MO basis
1096 CALL calculate_operators(active_space_env%mos_active, qs_env, active_space_env)
1097 ! set the reference energy in the active space
1098 active_space_env%energy_ref = energy%total
1099 ! calculate inactive energy and embedding potential
1100 CALL subspace_fock_matrix(active_space_env, dft_control%roks)
1101
1102 ! associate the active space environment with the qs environment
1103 CALL set_qs_env(qs_env, active_space=active_space_env)
1104
1105 ! Perform the embedding calculation only if qiskit is specified
1106 CALL section_vals_val_get(as_input, "AS_SOLVER", i_val=as_solver)
1107 SELECT CASE (as_solver)
1108 CASE (no_solver)
1109 IF (iw > 0) THEN
1110 WRITE (iw, '(/,T3,A)') "No active space solver specified, skipping embedding calculation"
1111 CALL m_flush(iw)
1112 END IF
1113 CALL para_env%sync()
1114 CASE (qiskit_solver)
1115 CALL rsdft_embedding(qs_env, active_space_env, as_input)
1116 CALL qs_scf_compute_properties(qs_env, wf_type="MC-DFT", do_mp2=.false.)
1117 CASE DEFAULT
1118 cpabort("Unknown active space solver")
1119 END SELECT
1120
1121 ! Output a FCIDUMP file if requested
1122 IF (active_space_env%fcidump) CALL fcidump(active_space_env, as_input, dft_control%roks)
1123
1124 ! Output a QCSchema file if requested
1125 IF (active_space_env%qcschema) THEN
1126 CALL qcschema_env_create(qcschema_env, qs_env)
1127 CALL qcschema_to_hdf5(qcschema_env, active_space_env%qcschema_filename)
1128 CALL qcschema_env_release(qcschema_env)
1129 END IF
1130
1131 IF (iw > 0) THEN
1132 WRITE (iw, '(/,T2,A)') &
1133 '!-------------------- End of Active Space Interface --------------------------!'
1134 CALL m_flush(iw)
1135 END IF
1136 CALL para_env%sync()
1137
1138 CALL timestop(handle)
1139
1140 END SUBROUTINE active_space_main
1141
1142! **************************************************************************************************
1143!> \brief computes the alpha-beta overlap within the active subspace
1144!> \param mos the molecular orbital set within the active subspace
1145!> \param qs_env ...
1146!> \param active_space_env ...
1147!> \par History
1148!> 04.2016 created [JGH]
1149! **************************************************************************************************
1150 SUBROUTINE calculate_spin_pol_overlap(mos, qs_env, active_space_env)
1151
1152 TYPE(mo_set_type), DIMENSION(:), INTENT(IN) :: mos
1153 TYPE(qs_environment_type), POINTER :: qs_env
1154 TYPE(active_space_type), POINTER :: active_space_env
1155
1156 CHARACTER(len=*), PARAMETER :: routinen = 'calculate_spin_pol_overlap'
1157
1158 INTEGER :: handle, nmo, nspins
1159 TYPE(cp_fm_type), POINTER :: mo_coeff_a, mo_coeff_b
1160 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: s_matrix
1161
1162 CALL timeset(routinen, handle)
1163
1164 nspins = active_space_env%nspins
1165
1166 ! overlap in AO
1167 IF (nspins > 1) THEN
1168 CALL get_qs_env(qs_env, matrix_s=s_matrix)
1169 ALLOCATE (active_space_env%sab_sub(1))
1170
1171 CALL get_mo_set(mo_set=mos(1), mo_coeff=mo_coeff_a, nmo=nmo)
1172 CALL get_mo_set(mo_set=mos(2), mo_coeff=mo_coeff_b, nmo=nmo)
1173 CALL subspace_operator(mo_coeff_a, nmo, s_matrix(1)%matrix, active_space_env%sab_sub(1), mo_coeff_b)
1174 END IF
1175
1176 CALL timestop(handle)
1177
1178 END SUBROUTINE calculate_spin_pol_overlap
1179
1180! **************************************************************************************************
1181!> \brief computes the one-electron operators in the subspace of the provided orbital set
1182!> \param mos the molecular orbital set within the active subspace
1183!> \param qs_env ...
1184!> \param active_space_env ...
1185!> \par History
1186!> 04.2016 created [JGH]
1187! **************************************************************************************************
1188 SUBROUTINE calculate_operators(mos, qs_env, active_space_env)
1189
1190 TYPE(mo_set_type), DIMENSION(:), INTENT(IN) :: mos
1191 TYPE(qs_environment_type), POINTER :: qs_env
1192 TYPE(active_space_type), POINTER :: active_space_env
1193
1194 CHARACTER(len=*), PARAMETER :: routinen = 'calculate_operators'
1195
1196 INTEGER :: handle, ispin, nmo, nspins
1197 TYPE(cp_fm_type), POINTER :: mo_coeff
1198 TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: h_matrix, ks_matrix
1199
1200 CALL timeset(routinen, handle)
1201
1202 nspins = active_space_env%nspins
1203
1204 ! Kohn-Sham / Fock operator
1205 CALL cp_fm_release(active_space_env%ks_sub)
1206 CALL get_qs_env(qs_env, matrix_ks_kp=ks_matrix)
1207 ALLOCATE (active_space_env%ks_sub(nspins))
1208 DO ispin = 1, nspins
1209 CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, nmo=nmo)
1210 CALL subspace_operator(mo_coeff, nmo, ks_matrix(ispin, 1)%matrix, active_space_env%ks_sub(ispin))
1211 END DO
1212
1213 ! Core Hamiltonian
1214 CALL cp_fm_release(active_space_env%h_sub)
1215
1216 NULLIFY (h_matrix)
1217 CALL get_qs_env(qs_env=qs_env, matrix_h_kp=h_matrix)
1218 ALLOCATE (active_space_env%h_sub(nspins))
1219 DO ispin = 1, nspins
1220 CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, nmo=nmo)
1221 CALL subspace_operator(mo_coeff, nmo, h_matrix(1, 1)%matrix, active_space_env%h_sub(ispin))
1222 END DO
1223
1224 CALL timestop(handle)
1225
1226 END SUBROUTINE calculate_operators
1227
1228! **************************************************************************************************
1229!> \brief computes a one-electron operator in the subspace of the provided orbital set
1230!> \param mo_coeff the orbital coefficient matrix
1231!> \param nmo the number of subspace orbitals
1232!> \param op_matrix operator matrix in AO basis
1233!> \param op_sub operator in orbital basis
1234!> \param mo_coeff_b the beta orbital coefficients
1235!> \par History
1236!> 04.2016 created [JGH]
1237! **************************************************************************************************
1238 SUBROUTINE subspace_operator(mo_coeff, nmo, op_matrix, op_sub, mo_coeff_b)
1239
1240 TYPE(cp_fm_type), INTENT(IN) :: mo_coeff
1241 INTEGER, INTENT(IN) :: nmo
1242 TYPE(dbcsr_type), POINTER :: op_matrix
1243 TYPE(cp_fm_type), INTENT(INOUT) :: op_sub
1244 TYPE(cp_fm_type), INTENT(IN), OPTIONAL :: mo_coeff_b
1245
1246 CHARACTER(len=*), PARAMETER :: routinen = 'subspace_operator'
1247
1248 INTEGER :: handle, ncol, nrow
1249 TYPE(cp_fm_type) :: vectors
1250
1251 CALL timeset(routinen, handle)
1252
1253 CALL cp_fm_get_info(matrix=mo_coeff, ncol_global=ncol, nrow_global=nrow)
1254 cpassert(nmo <= ncol)
1255
1256 IF (nmo > 0) THEN
1257 CALL cp_fm_create(vectors, mo_coeff%matrix_struct, "vectors")
1258 CALL create_subspace_matrix(mo_coeff, op_sub, nmo)
1259
1260 IF (PRESENT(mo_coeff_b)) THEN
1261 ! if beta orbitals are present, compute the cross alpha_beta term
1262 CALL cp_dbcsr_sm_fm_multiply(op_matrix, mo_coeff_b, vectors, nmo)
1263 ELSE
1264 ! otherwise the same spin, whatever that is
1265 CALL cp_dbcsr_sm_fm_multiply(op_matrix, mo_coeff, vectors, nmo)
1266 END IF
1267
1268 CALL parallel_gemm('T', 'N', nmo, nmo, nrow, 1.0_dp, mo_coeff, vectors, 0.0_dp, op_sub)
1269 CALL cp_fm_release(vectors)
1270 END IF
1271
1272 CALL timestop(handle)
1273
1274 END SUBROUTINE subspace_operator
1275
1276! **************************************************************************************************
1277!> \brief creates a matrix of subspace size
1278!> \param orbitals the orbital coefficient matrix
1279!> \param op_sub operator in orbital basis
1280!> \param n the number of orbitals
1281!> \par History
1282!> 04.2016 created [JGH]
1283! **************************************************************************************************
1284 SUBROUTINE create_subspace_matrix(orbitals, op_sub, n)
1285
1286 TYPE(cp_fm_type), INTENT(IN) :: orbitals
1287 TYPE(cp_fm_type), INTENT(OUT) :: op_sub
1288 INTEGER, INTENT(IN) :: n
1289
1290 TYPE(cp_fm_struct_type), POINTER :: fm_struct
1291
1292 IF (n > 0) THEN
1293
1294 NULLIFY (fm_struct)
1295 CALL cp_fm_struct_create(fm_struct, nrow_global=n, ncol_global=n, &
1296 para_env=orbitals%matrix_struct%para_env, &
1297 context=orbitals%matrix_struct%context)
1298 CALL cp_fm_create(op_sub, fm_struct, name="Subspace operator")
1299 CALL cp_fm_struct_release(fm_struct)
1300
1301 END IF
1302
1303 END SUBROUTINE create_subspace_matrix
1304
1305! **************************************************************************************************
1306!> \brief computes the electron repulsion integrals using the GPW technology
1307!> \param mos the molecular orbital set within the active subspace
1308!> \param orbitals ...
1309!> \param eri_env ...
1310!> \param qs_env ...
1311!> \param iw ...
1312!> \param restricted ...
1313!> \par History
1314!> 04.2016 created [JGH]
1315! **************************************************************************************************
1316 SUBROUTINE calculate_eri_gpw(mos, orbitals, eri_env, qs_env, iw, restricted)
1317
1318 TYPE(mo_set_type), DIMENSION(:), INTENT(IN) :: mos
1319 INTEGER, DIMENSION(:, :), POINTER :: orbitals
1320 TYPE(eri_type) :: eri_env
1321 TYPE(qs_environment_type), POINTER :: qs_env
1322 INTEGER, INTENT(IN) :: iw
1323 LOGICAL, INTENT(IN) :: restricted
1324
1325 CHARACTER(len=*), PARAMETER :: routinen = 'calculate_eri_gpw'
1326
1327 INTEGER :: col_local, color, handle, i1, i2, i3, i4, i_multigrid, icount2, intcount, &
1328 irange(2), isp, isp1, isp2, ispin, iwa1, iwa12, iwa2, iwb1, iwb12, iwb2, iwbs, iwbt, &
1329 iwfn, n_multigrid, ncol_global, ncol_local, nmm, nmo, nmo1, nmo2, nrow_global, &
1330 nrow_local, nspins, number_of_subgroups, nx, row_local, stored_integrals
1331 INTEGER, ALLOCATABLE, DIMENSION(:) :: eri_index
1332 INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
1333 LOGICAL :: print1, print2, &
1334 skip_load_balance_distributed
1335 REAL(kind=dp) :: dvol, erint, pair_int, &
1336 progression_factor, rc, rsize, t1, t2
1337 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: eri
1338 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
1339 TYPE(cell_type), POINTER :: cell
1340 TYPE(cp_blacs_env_type), POINTER :: blacs_env, blacs_env_sub
1341 TYPE(cp_fm_struct_type), POINTER :: fm_struct
1342 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_matrix_pq_rnu, fm_matrix_pq_rs, &
1343 fm_mo_coeff_as
1344 TYPE(cp_fm_type), POINTER :: mo_coeff
1345 TYPE(dbcsr_p_type) :: mat_munu
1346 TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:) :: matrix_pq_rnu, mo_coeff_as
1347 TYPE(dft_control_type), POINTER :: dft_control
1348 TYPE(mp_para_env_type), POINTER :: para_env
1349 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1350 POINTER :: sab_orb_sub
1351 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1352 TYPE(pw_c1d_gs_type) :: pot_g, rho_g
1353 TYPE(pw_env_type), POINTER :: pw_env_sub
1354 TYPE(pw_poisson_type), POINTER :: poisson_env
1355 TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1356 TYPE(pw_r3d_rs_type) :: rho_r, wfn_r
1357 TYPE(pw_r3d_rs_type), ALLOCATABLE, &
1358 DIMENSION(:, :), TARGET :: wfn_a
1359 TYPE(pw_r3d_rs_type), POINTER :: wfn1, wfn2, wfn3, wfn4
1360 TYPE(qs_control_type), POINTER :: qs_control, qs_control_old
1361 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1362 TYPE(qs_ks_env_type), POINTER :: ks_env
1363 TYPE(task_list_type), POINTER :: task_list_sub
1364
1365 CALL timeset(routinen, handle)
1366
1367 IF (iw > 0) t1 = m_walltime()
1368
1369 ! print levels
1370 SELECT CASE (eri_env%eri_gpw%print_level)
1371 CASE (silent_print_level)
1372 print1 = .false.
1373 print2 = .false.
1374 CASE (low_print_level)
1375 print1 = .false.
1376 print2 = .false.
1377 CASE (medium_print_level)
1378 print1 = .true.
1379 print2 = .false.
1380 CASE (high_print_level)
1381 print1 = .true.
1382 print2 = .true.
1383 CASE (debug_print_level)
1384 print1 = .true.
1385 print2 = .true.
1386 CASE DEFAULT
1387 ! do nothing
1388 END SELECT
1389
1390 ! Check the input group
1391 CALL get_qs_env(qs_env, para_env=para_env, blacs_env=blacs_env)
1392 IF (eri_env%eri_gpw%group_size < 1) eri_env%eri_gpw%group_size = para_env%num_pe
1393 IF (mod(para_env%num_pe, eri_env%eri_gpw%group_size) /= 0) &
1394 cpabort("Group size must be a divisor of the total number of processes!")
1395 ! Create a new para_env or reuse the old one
1396 IF (eri_env%eri_gpw%group_size == para_env%num_pe) THEN
1397 eri_env%para_env_sub => para_env
1398 CALL eri_env%para_env_sub%retain()
1399 blacs_env_sub => blacs_env
1400 CALL blacs_env_sub%retain()
1401 number_of_subgroups = 1
1402 color = 0
1403 ELSE
1404 number_of_subgroups = para_env%num_pe/eri_env%eri_gpw%group_size
1405 color = para_env%mepos/eri_env%eri_gpw%group_size
1406 ALLOCATE (eri_env%para_env_sub)
1407 CALL eri_env%para_env_sub%from_split(para_env, color)
1408 NULLIFY (blacs_env_sub)
1409 CALL cp_blacs_env_create(blacs_env_sub, eri_env%para_env_sub, blacs_grid_square, .true.)
1410 END IF
1411 CALL eri_env%comm_exchange%from_split(para_env, eri_env%para_env_sub%mepos)
1412
1413 ! This should be done differently! Copied from MP2 code
1414 CALL get_qs_env(qs_env, dft_control=dft_control)
1415 ALLOCATE (qs_control)
1416 qs_control_old => dft_control%qs_control
1417 qs_control = qs_control_old
1418 dft_control%qs_control => qs_control
1419 progression_factor = qs_control%progression_factor
1420 n_multigrid = SIZE(qs_control%e_cutoff)
1421 nspins = SIZE(mos)
1422 ! In case of ROHF/ROKS, we assume the orbital coefficients in both spin channels to be the same
1423 ! and save operations by calculating ERIs from only one spin channel
1424 IF (restricted) nspins = 1
1425 ! Allocate new cutoffs (just in private qs_control, not in qs_control_old)
1426 ALLOCATE (qs_control%e_cutoff(n_multigrid))
1427
1428 qs_control%cutoff = eri_env%eri_gpw%cutoff*0.5_dp
1429 qs_control%e_cutoff(1) = qs_control%cutoff
1430 DO i_multigrid = 2, n_multigrid
1431 qs_control%e_cutoff(i_multigrid) = qs_control%e_cutoff(i_multigrid - 1) &
1432 /progression_factor
1433 END DO
1434 qs_control%relative_cutoff = eri_env%eri_gpw%rel_cutoff*0.5_dp
1435
1436 ! For now, we will distribute neighbor lists etc. within the global communicator
1437 CALL get_qs_env(qs_env, ks_env=ks_env)
1438 CALL create_mat_munu(mat_munu, qs_env, eri_env%eri_gpw%eps_grid, blacs_env_sub, sab_orb_sub=sab_orb_sub, &
1439 do_alloc_blocks_from_nbl=.true., dbcsr_sym_type=dbcsr_type_symmetric)
1440 CALL dbcsr_set(mat_munu%matrix, 0.0_dp)
1441
1442 ! Generate the appropriate pw_env
1443 NULLIFY (pw_env_sub)
1444 CALL pw_env_create(pw_env_sub)
1445 CALL pw_env_rebuild(pw_env_sub, qs_env, external_para_env=eri_env%para_env_sub)
1446 CALL pw_env_get(pw_env_sub, auxbas_pw_pool=auxbas_pw_pool, poisson_env=poisson_env)
1447
1448 ! TODO: maybe we can let `pw_env_rebuild` do what we manually overwrite here?
1449 IF (eri_env%eri_gpw%redo_poisson) THEN
1450 ! We need to rebuild the Poisson solver on the fly
1451 IF (sum(eri_env%periodicity) /= 0) THEN
1452 poisson_env%parameters%solver = pw_poisson_periodic
1453 ELSE
1454 poisson_env%parameters%solver = pw_poisson_analytic
1455 END IF
1456 poisson_env%parameters%periodic = eri_env%periodicity
1457
1458 ! Rebuilds the poisson green (influence) function according
1459 ! to the poisson solver and parameters set so far.
1460 ! Also sets the variable poisson_env%rebuild to .FALSE.
1461 CALL pw_poisson_rebuild(poisson_env)
1462
1463 ! set the cutoff radius for the Greens function in case we use ANALYTIC Poisson solver
1464 CALL get_qs_env(qs_env, cell=cell)
1465 rc = cell%hmat(1, 1)
1466 DO iwa1 = 1, 3
1467 ! TODO: I think this is not the largest possible radius inscribed in the cell
1468 rc = min(rc, 0.5_dp*cell%hmat(iwa1, iwa1))
1469 END DO
1470 poisson_env%green_fft%radius = rc
1471
1472 ! Overwrite the Greens function with the one we want
1473 CALL pw_eri_green_create(poisson_env%green_fft, eri_env)
1474
1475 IF (iw > 0) THEN
1476 CALL get_qs_env(qs_env, cell=cell)
1477 IF (sum(cell%perd) /= sum(eri_env%periodicity)) THEN
1478 IF (sum(eri_env%periodicity) /= 0) THEN
1479 WRITE (unit=iw, fmt="(/,T2,A,T51,A30)") &
1480 "ERI_GPW| Switching Poisson solver to", "PERIODIC"
1481 ELSE
1482 WRITE (unit=iw, fmt="(/,T2,A,T51,A30)") &
1483 "ERI_GPW| Switching Poisson solver to", "ANALYTIC"
1484 END IF
1485 END IF
1486 ! print out the Greens function to check it matches the Poisson solver
1487 SELECT CASE (poisson_env%green_fft%method)
1488 CASE (periodic3d)
1489 WRITE (unit=iw, fmt="(T2,A,T51,A30)") &
1490 "ERI_GPW| Poisson Greens function", "PERIODIC"
1491 CASE (analytic0d)
1492 WRITE (unit=iw, fmt="(T2,A,T51,A30)") &
1493 "ERI_GPW| Poisson Greens function", "ANALYTIC"
1494 WRITE (unit=iw, fmt="(T2,A,T71,F10.4)") "ERI_GPW| Poisson cutoff radius", &
1495 poisson_env%green_fft%radius*angstrom
1496 CASE DEFAULT
1497 cpabort("Wrong Greens function setup")
1498 END SELECT
1499 END IF
1500 END IF
1501
1502 ALLOCATE (mo_coeff_as(nspins), fm_mo_coeff_as(nspins))
1503 DO ispin = 1, nspins
1504 block
1505 REAL(kind=dp), DIMENSION(:, :), ALLOCATABLE :: c
1506 INTEGER :: nmo
1507 TYPE(group_dist_d1_type) :: gd_array
1508 TYPE(cp_fm_type), POINTER :: mo_coeff
1509 CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, nmo=nmo)
1510 CALL grep_rows_in_subgroups(para_env, eri_env%para_env_sub, mo_coeff, gd_array, c)
1511
1512 CALL build_dbcsr_from_rows(eri_env%para_env_sub, mo_coeff_as(ispin), &
1513 c(:, :nmo), mat_munu%matrix, gd_array, eri_env%eri_gpw%eps_filter)
1514 CALL release_group_dist(gd_array)
1515 DEALLOCATE (c)
1516 END block
1517
1518 CALL dbcsr_get_info(mo_coeff_as(ispin), nfullrows_total=nrow_global, nfullcols_total=ncol_global)
1519
1520 NULLIFY (fm_struct)
1521 CALL cp_fm_struct_create(fm_struct, context=blacs_env_sub, para_env=eri_env%para_env_sub, &
1522 nrow_global=nrow_global, ncol_global=ncol_global)
1523 CALL cp_fm_create(fm_mo_coeff_as(ispin), fm_struct)
1524 CALL cp_fm_struct_release(fm_struct)
1525
1526 CALL copy_dbcsr_to_fm(mo_coeff_as(ispin), fm_mo_coeff_as(ispin))
1527 END DO
1528
1529 IF (eri_env%method == eri_method_gpw_ht) THEN
1530 ! We need a task list
1531 NULLIFY (task_list_sub)
1532 skip_load_balance_distributed = dft_control%qs_control%skip_load_balance_distributed
1533 CALL allocate_task_list(task_list_sub)
1534 CALL generate_qs_task_list(ks_env, task_list_sub, basis_type="ORB", &
1535 reorder_rs_grid_ranks=.true., &
1536 skip_load_balance_distributed=skip_load_balance_distributed, &
1537 pw_env_external=pw_env_sub, sab_orb_external=sab_orb_sub)
1538
1539 ! Create sparse matrices carrying the matrix products, Code borrowed from the MP2 GPW method
1540 ! Create equal distributions for them (no sparsity present)
1541 ! We use the routines from mp2 suggesting that one may replicate the grids later for better performance
1542 ALLOCATE (matrix_pq_rnu(nspins), fm_matrix_pq_rnu(nspins), fm_matrix_pq_rs(nspins))
1543 DO ispin = 1, nspins
1544 CALL dbcsr_create(matrix_pq_rnu(ispin), template=mo_coeff_as(ispin))
1545 CALL dbcsr_set(matrix_pq_rnu(ispin), 0.0_dp)
1546
1547 CALL dbcsr_get_info(matrix_pq_rnu(ispin), nfullrows_total=nrow_global, nfullcols_total=ncol_global)
1548
1549 NULLIFY (fm_struct)
1550 CALL cp_fm_struct_create(fm_struct, context=blacs_env_sub, para_env=eri_env%para_env_sub, &
1551 nrow_global=nrow_global, ncol_global=ncol_global)
1552 CALL cp_fm_create(fm_matrix_pq_rnu(ispin), fm_struct)
1553 CALL cp_fm_struct_release(fm_struct)
1554
1555 NULLIFY (fm_struct)
1556 CALL cp_fm_struct_create(fm_struct, context=blacs_env_sub, para_env=eri_env%para_env_sub, &
1557 nrow_global=ncol_global, ncol_global=ncol_global)
1558 CALL cp_fm_create(fm_matrix_pq_rs(ispin), fm_struct)
1559 CALL cp_fm_struct_release(fm_struct)
1560 END DO
1561
1562 ! Copy the active space of the MOs into DBCSR matrices
1563 END IF
1564
1565 CALL auxbas_pw_pool%create_pw(wfn_r)
1566 CALL auxbas_pw_pool%create_pw(rho_g)
1567 CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set, cell=cell, &
1568 particle_set=particle_set, atomic_kind_set=atomic_kind_set)
1569
1570 ! pre-calculate wavefunctions on reals space grid
1571 nspins = SIZE(mos)
1572 ! In case of ROHF/ROKS, we assume the orbital coefficients in both spin channels to be the same
1573 ! and save operations by calculating ERIs from only one spin channel
1574 IF (restricted) nspins = 1
1575 IF (eri_env%eri_gpw%store_wfn) THEN
1576 ! pre-calculate wavefunctions on reals space grid
1577 rsize = 0.0_dp
1578 nmo = 0
1579 DO ispin = 1, nspins
1580 CALL get_mo_set(mo_set=mos(ispin), nmo=nx)
1581 nmo = max(nmo, nx)
1582 rsize = real(SIZE(wfn_r%array), kind=dp)*nx
1583 END DO
1584 IF (print1 .AND. iw > 0) THEN
1585 rsize = rsize*8._dp/1000000._dp
1586 WRITE (iw, "(T2,'ERI_GPW|',' Store active orbitals on real space grid ',T66,F12.3,' MB')") rsize
1587 END IF
1588 ALLOCATE (wfn_a(nmo, nspins))
1589 DO ispin = 1, nspins
1590 CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, nmo=nmo)
1591 DO i1 = 1, SIZE(orbitals, 1)
1592 iwfn = orbitals(i1, ispin)
1593 CALL auxbas_pw_pool%create_pw(wfn_a(iwfn, ispin))
1594 CALL calculate_wavefunction(mo_coeff, iwfn, wfn_a(iwfn, ispin), rho_g, atomic_kind_set, &
1595 qs_kind_set, cell, dft_control, particle_set, pw_env_sub)
1596 IF (print2 .AND. iw > 0) THEN
1597 WRITE (iw, "(T2,'ERI_GPW|',' Orbital stored ',I4,' Spin ',i1)") iwfn, ispin
1598 END IF
1599 END DO
1600 END DO
1601 ELSE
1602 ! Even if we do not store all WFNs, we still need containers for the functions to store
1603 ALLOCATE (wfn1, wfn2)
1604 CALL auxbas_pw_pool%create_pw(wfn1)
1605 CALL auxbas_pw_pool%create_pw(wfn2)
1606 IF (eri_env%method /= eri_method_gpw_ht) THEN
1607 ALLOCATE (wfn3, wfn4)
1608 CALL auxbas_pw_pool%create_pw(wfn3)
1609 CALL auxbas_pw_pool%create_pw(wfn4)
1610 END IF
1611 END IF
1612
1613 ! get some of the grids ready
1614 CALL auxbas_pw_pool%create_pw(rho_r)
1615 CALL auxbas_pw_pool%create_pw(pot_g)
1616
1617 ! run the FFT once, to set up buffers and to take into account the memory
1618 CALL pw_zero(rho_r)
1619 CALL pw_transfer(rho_r, rho_g)
1620 dvol = rho_r%pw_grid%dvol
1621
1622 IF (iw > 0) THEN
1623 CALL m_flush(iw)
1624 END IF
1625 ! calculate the integrals
1626 stored_integrals = 0
1627 DO isp1 = 1, nspins
1628 CALL get_mo_set(mo_set=mos(isp1), nmo=nmo1)
1629 nmm = (nmo1*(nmo1 + 1))/2
1630 irange = get_irange_csr(nmm, eri_env%comm_exchange)
1631 DO i1 = 1, SIZE(orbitals, 1)
1632 iwa1 = orbitals(i1, isp1)
1633 IF (eri_env%eri_gpw%store_wfn) THEN
1634 wfn1 => wfn_a(iwa1, isp1)
1635 ELSE
1636 CALL calculate_wavefunction(fm_mo_coeff_as(isp1), iwa1, wfn1, rho_g, atomic_kind_set, &
1637 qs_kind_set, cell, dft_control, particle_set, pw_env_sub)
1638 END IF
1639 DO i2 = i1, SIZE(orbitals, 1)
1640 iwa2 = orbitals(i2, isp1)
1641 iwa12 = csr_idx_to_combined(iwa1, iwa2, nmo1)
1642 ! Skip calculation directly if the pair is not part of our subgroup
1643 IF (iwa12 < irange(1) .OR. iwa12 > irange(2)) cycle
1644 iwa12 = iwa12 - irange(1) + 1
1645 IF (eri_env%eri_gpw%store_wfn) THEN
1646 wfn2 => wfn_a(iwa2, isp1)
1647 ELSE
1648 CALL calculate_wavefunction(fm_mo_coeff_as(isp1), iwa2, wfn2, rho_g, atomic_kind_set, &
1649 qs_kind_set, cell, dft_control, particle_set, pw_env_sub)
1650 END IF
1651 ! calculate charge distribution and potential
1652 CALL pw_zero(rho_r)
1653 CALL pw_multiply(rho_r, wfn1, wfn2)
1654 CALL pw_transfer(rho_r, rho_g)
1655 CALL pw_poisson_solve(poisson_env, rho_g, pair_int, pot_g)
1656
1657 ! screening using pair_int
1658 IF (pair_int < eri_env%eps_integral) cycle
1659 CALL pw_transfer(pot_g, rho_r)
1660 !
1661 IF (eri_env%method == eri_method_gpw_ht) THEN
1662 CALL pw_scale(rho_r, dvol)
1663 DO isp2 = isp1, nspins
1664 CALL get_mo_set(mo_set=mos(isp2), nmo=nmo2)
1665 nx = (nmo2*(nmo2 + 1))/2
1666 ALLOCATE (eri(nx), eri_index(nx))
1667 CALL dbcsr_set(mat_munu%matrix, 0.0_dp)
1668 CALL integrate_v_rspace(rho_r, hmat=mat_munu, qs_env=qs_env, &
1669 calculate_forces=.false., compute_tau=.false., gapw=.false., &
1670 pw_env_external=pw_env_sub, task_list_external=task_list_sub)
1671
1672 CALL dbcsr_multiply("N", "N", 1.0_dp, mat_munu%matrix, mo_coeff_as(isp2), &
1673 0.0_dp, matrix_pq_rnu(isp2), filter_eps=eri_env%eri_gpw%eps_filter)
1674 CALL copy_dbcsr_to_fm(matrix_pq_rnu(isp2), fm_matrix_pq_rnu(isp2))
1675
1676 CALL cp_fm_get_info(fm_matrix_pq_rnu(isp2), ncol_global=ncol_global, nrow_global=nrow_global)
1677
1678 CALL parallel_gemm("T", "N", ncol_global, ncol_global, nrow_global, 0.5_dp, &
1679 fm_matrix_pq_rnu(isp2), fm_mo_coeff_as(isp2), &
1680 0.0_dp, fm_matrix_pq_rs(isp2))
1681 CALL parallel_gemm("T", "N", ncol_global, ncol_global, nrow_global, 0.5_dp, &
1682 fm_mo_coeff_as(isp2), fm_matrix_pq_rnu(isp2), &
1683 1.0_dp, fm_matrix_pq_rs(isp2))
1684
1685 CALL cp_fm_get_info(fm_matrix_pq_rs(isp2), ncol_local=ncol_local, nrow_local=nrow_local, &
1686 col_indices=col_indices, row_indices=row_indices)
1687
1688 icount2 = 0
1689 DO col_local = 1, ncol_local
1690 iwb2 = orbitals(col_indices(col_local), isp2)
1691 DO row_local = 1, nrow_local
1692 iwb1 = orbitals(row_indices(row_local), isp2)
1693
1694 IF (iwb1 <= iwb2) THEN
1695 iwb12 = csr_idx_to_combined(iwb1, iwb2, nmo2)
1696 erint = fm_matrix_pq_rs(isp2)%local_data(row_local, col_local)
1697 IF (abs(erint) > eri_env%eps_integral .AND. (irange(1) - 1 + iwa12 <= iwb12 .OR. isp1 /= isp2)) THEN
1698 icount2 = icount2 + 1
1699 eri(icount2) = erint
1700 eri_index(icount2) = iwb12
1701 END IF
1702 END IF
1703 END DO
1704 END DO
1705 stored_integrals = stored_integrals + icount2
1706 !
1707 isp = (isp1 - 1)*isp2 + (isp2 - isp1 + 1)
1708 CALL update_csr_matrix(eri_env%eri(isp)%csr_mat, icount2, eri, eri_index, iwa12)
1709 !
1710 DEALLOCATE (eri, eri_index)
1711 END DO
1712 ELSEIF (eri_env%method == eri_method_full_gpw) THEN
1713 DO isp2 = isp1, nspins
1714 CALL get_mo_set(mo_set=mos(isp2), nmo=nmo2)
1715 nx = (nmo2*(nmo2 + 1))/2
1716 ALLOCATE (eri(nx), eri_index(nx))
1717 icount2 = 0
1718 iwbs = 1
1719 IF (isp1 == isp2) iwbs = i1
1720 isp = (isp1 - 1)*isp2 + (isp2 - isp1 + 1)
1721 DO i3 = iwbs, SIZE(orbitals, 1)
1722 iwb1 = orbitals(i3, isp2)
1723 IF (eri_env%eri_gpw%store_wfn) THEN
1724 wfn3 => wfn_a(iwb1, isp2)
1725 ELSE
1726 CALL calculate_wavefunction(fm_mo_coeff_as(isp1), iwb1, wfn3, rho_g, atomic_kind_set, &
1727 qs_kind_set, cell, dft_control, particle_set, pw_env_sub)
1728 END IF
1729 CALL pw_zero(wfn_r)
1730 CALL pw_multiply(wfn_r, rho_r, wfn3)
1731 iwbt = i3
1732 IF (isp1 == isp2 .AND. i1 == i3) iwbt = i2
1733 DO i4 = iwbt, SIZE(orbitals, 1)
1734 iwb2 = orbitals(i4, isp2)
1735 IF (eri_env%eri_gpw%store_wfn) THEN
1736 wfn4 => wfn_a(iwb2, isp2)
1737 ELSE
1738 CALL calculate_wavefunction(fm_mo_coeff_as(isp1), iwb2, wfn4, rho_g, atomic_kind_set, &
1739 qs_kind_set, cell, dft_control, particle_set, pw_env_sub)
1740 END IF
1741 ! We reduce the amount of communication by collecting the local sums first and sum globally later
1742 erint = pw_integral_ab(wfn_r, wfn4, local_only=.true.)
1743 icount2 = icount2 + 1
1744 eri(icount2) = erint
1745 eri_index(icount2) = csr_idx_to_combined(iwb1, iwb2, nmo2)
1746 END DO
1747 END DO
1748 ! Now, we sum the integrals globally
1749 CALL eri_env%para_env_sub%sum(eri)
1750 ! and we reorder the integrals to prevent storing too small integrals
1751 intcount = 0
1752 icount2 = 0
1753 iwbs = 1
1754 IF (isp1 == isp2) iwbs = i1
1755 isp = (isp1 - 1)*isp2 + (isp2 - isp1 + 1)
1756 DO i3 = iwbs, SIZE(orbitals, 1)
1757 iwb1 = orbitals(i3, isp2)
1758 iwbt = i3
1759 IF (isp1 == isp2 .AND. i1 == i3) iwbt = i2
1760 DO i4 = iwbt, SIZE(orbitals, 1)
1761 iwb2 = orbitals(i4, isp2)
1762 intcount = intcount + 1
1763 erint = eri(intcount)
1764 IF (abs(erint) > eri_env%eps_integral) THEN
1765 IF (mod(intcount, eri_env%para_env_sub%num_pe) == eri_env%para_env_sub%mepos) THEN
1766 icount2 = icount2 + 1
1767 eri(icount2) = erint
1768 eri_index(icount2) = eri_index(intcount)
1769 END IF
1770 END IF
1771 END DO
1772 END DO
1773 stored_integrals = stored_integrals + icount2
1774 !
1775 CALL update_csr_matrix(eri_env%eri(isp)%csr_mat, icount2, eri, eri_index, iwa12)
1776 !
1777 DEALLOCATE (eri, eri_index)
1778 END DO
1779 ELSE
1780 cpabort("Unknown option")
1781 END IF
1782 END DO
1783 END DO
1784 END DO
1785
1786 IF (print1 .AND. iw > 0) THEN
1787 WRITE (iw, "(T2,'ERI_GPW|',' Number of Integrals stored locally',T71,I10)") stored_integrals
1788 END IF
1789
1790 IF (eri_env%eri_gpw%store_wfn) THEN
1791 DO ispin = 1, nspins
1792 DO i1 = 1, SIZE(orbitals, 1)
1793 iwfn = orbitals(i1, ispin)
1794 CALL wfn_a(iwfn, ispin)%release()
1795 END DO
1796 END DO
1797 DEALLOCATE (wfn_a)
1798 ELSE
1799 CALL wfn1%release()
1800 CALL wfn2%release()
1801 DEALLOCATE (wfn1, wfn2)
1802 IF (eri_env%method /= eri_method_gpw_ht) THEN
1803 CALL wfn3%release()
1804 CALL wfn4%release()
1805 DEALLOCATE (wfn3, wfn4)
1806 END IF
1807 END IF
1808 CALL auxbas_pw_pool%give_back_pw(wfn_r)
1809 CALL auxbas_pw_pool%give_back_pw(rho_g)
1810 CALL auxbas_pw_pool%give_back_pw(rho_r)
1811 CALL auxbas_pw_pool%give_back_pw(pot_g)
1812
1813 IF (eri_env%method == eri_method_gpw_ht) THEN
1814 DO ispin = 1, nspins
1815 CALL dbcsr_release(mo_coeff_as(ispin))
1816 CALL dbcsr_release(matrix_pq_rnu(ispin))
1817 CALL cp_fm_release(fm_matrix_pq_rnu(ispin))
1818 CALL cp_fm_release(fm_matrix_pq_rs(ispin))
1819 END DO
1820 DEALLOCATE (matrix_pq_rnu, fm_matrix_pq_rnu, fm_matrix_pq_rs)
1821 CALL deallocate_task_list(task_list_sub)
1822 END IF
1823 DO ispin = 1, nspins
1824 CALL dbcsr_release(mo_coeff_as(ispin))
1825 CALL cp_fm_release(fm_mo_coeff_as(ispin))
1826 END DO
1827 DEALLOCATE (mo_coeff_as, fm_mo_coeff_as)
1828 CALL release_neighbor_list_sets(sab_orb_sub)
1829 CALL cp_blacs_env_release(blacs_env_sub)
1830 CALL dbcsr_release(mat_munu%matrix)
1831 DEALLOCATE (mat_munu%matrix)
1832 CALL pw_env_release(pw_env_sub)
1833 ! Return to the old qs_control
1834 dft_control%qs_control => qs_control_old
1835 DEALLOCATE (qs_control%e_cutoff)
1836 DEALLOCATE (qs_control)
1837
1838 ! print out progress
1839 IF (iw > 0) THEN
1840 t2 = m_walltime()
1841 WRITE (iw, '(/,T2,A,T66,F14.2)') "ERI_GPW| ERI calculation took (sec)", t2 - t1
1842 CALL m_flush(iw)
1843 END IF
1844
1845 CALL timestop(handle)
1846
1847 END SUBROUTINE calculate_eri_gpw
1848
1849! **************************************************************************************************
1850!> \brief Sets the Green's function for the ERI calculation. Here we deal with the G=0 case!
1851!> \param green ...
1852!> \param eri_env ...
1853!> \par History
1854!> 04.2016 created [JGH]
1855!> 08.2025 added support for the LR truncation [SB]
1856! **************************************************************************************************
1857 SUBROUTINE pw_eri_green_create(green, eri_env)
1858
1859 TYPE(greens_fn_type), INTENT(INOUT) :: green
1860 TYPE(eri_type) :: eri_env
1861
1862 COMPLEX(KIND=dp) :: erf_fac_p, z_p
1863 INTEGER :: ig
1864 REAL(kind=dp) :: cossin_fac, ea, erfcos_fac, exp_prefac, &
1865 g, g0, g2, g3d, ga, ginf, omega, &
1866 omega2, rc, rc2
1867
1868 ! initialize influence function
1869 associate(gf => green%influence_fn, grid => green%influence_fn%pw_grid)
1870 SELECT CASE (green%method)
1871 CASE (periodic3d)
1872
1873 SELECT CASE (eri_env%operator)
1874 CASE (eri_operator_coulomb)
1875 DO ig = grid%first_gne0, grid%ngpts_cut_local
1876 g2 = grid%gsq(ig)
1877 gf%array(ig) = fourpi/g2
1878 END DO
1879 IF (grid%have_g0) gf%array(1) = 0.0_dp
1880
1881 CASE (eri_operator_yukawa)
1882 CALL cp_warn(__location__, "Yukawa operator has not been tested")
1883 omega2 = eri_env%omega**2
1884 DO ig = grid%first_gne0, grid%ngpts_cut_local
1885 g2 = grid%gsq(ig)
1886 gf%array(ig) = fourpi/(omega2 + g2)
1887 END DO
1888 IF (grid%have_g0) gf%array(1) = fourpi/omega2
1889
1890 CASE (eri_operator_erf)
1891 omega2 = eri_env%omega**2
1892 DO ig = grid%first_gne0, grid%ngpts_cut_local
1893 g2 = grid%gsq(ig)
1894 gf%array(ig) = fourpi/g2*exp(-0.25_dp*g2/omega2)
1895 END DO
1896 IF (grid%have_g0) gf%array(1) = 0.0_dp
1897
1898 CASE (eri_operator_erfc)
1899 omega2 = eri_env%omega**2
1900 DO ig = grid%first_gne0, grid%ngpts_cut_local
1901 g2 = grid%gsq(ig)
1902 gf%array(ig) = fourpi/g2*(1.0_dp - exp(-0.25_dp*g2/omega2))
1903 END DO
1904 IF (grid%have_g0) gf%array(1) = pi/omega2
1905
1906 CASE (eri_operator_trunc)
1907 rc = eri_env%cutoff_radius
1908 DO ig = grid%first_gne0, grid%ngpts_cut_local
1909 g2 = grid%gsq(ig)
1910 g = sqrt(g2)
1911 ! Taylor expansion around zero
1912 IF (g*rc >= 0.005_dp) THEN
1913 gf%array(ig) = fourpi/g2*(1.0_dp - cos(g*rc))
1914 ELSE
1915 gf%array(ig) = fourpi/g2*(g*rc)**2/2.0_dp*(1.0_dp - (g*rc)**2/12.0_dp)
1916 END IF
1917 END DO
1918 IF (grid%have_g0) gf%array(1) = twopi*rc**2
1919
1920 CASE (eri_operator_lr_trunc)
1921 omega = eri_env%omega
1922 omega2 = omega**2
1923 rc = eri_env%cutoff_radius
1924 rc2 = rc**2
1925 g0 = 0.001_dp ! threshold for the G=0 case
1926 ginf = 20.0_dp ! threshold for the Taylor exapnsion arounf G=∞
1927 DO ig = grid%first_gne0, grid%ngpts_cut_local
1928 g2 = grid%gsq(ig)
1929 g = sqrt(g2)
1930 IF (g <= 2.0_dp*g0) THEN
1931 gf%array(ig) = -pi/omega2*erf(omega*rc) &
1932 + twopi*rc2*erf(omega*rc) &
1933 + 2*rootpi*rc*exp(-omega2*rc2)/omega
1934 ELSE IF (g >= 2.0_dp*ginf*omega) THEN
1935 ! exponential prefactor
1936 exp_prefac = exp(-omega2*rc2)/(rootpi*(omega2*rc2 + 0.25_dp*g2/omega2))
1937 ! cos sin factor
1938 cossin_fac = omega*rc*cos(g*rc) - 0.5_dp*g/omega*sin(g*rc)
1939 ! real erf term with cosine
1940 erfcos_fac = erf(omega*rc)*cos(g*rc)
1941 ! Combine terms
1942 gf%array(ig) = fourpi/g2*(-exp_prefac*cossin_fac - erfcos_fac)
1943 ELSE
1944 ! exponential prefactor
1945 exp_prefac = twopi/g2*exp(-0.25_dp*g2/omega2)
1946 ! Compute complex arguments for erf
1947 z_p = cmplx(omega*rc, 0.5_dp*g/omega, kind=dp)
1948 ! Evaluate complex error functions
1949 erf_fac_p = 2.0_dp*real(erfz_fast(z_p))
1950 ! Real erf term with cosine
1951 erfcos_fac = fourpi/g2*erf(omega*rc)*cos(g*rc)
1952 ! Combine terms
1953 gf%array(ig) = exp_prefac*erf_fac_p - erfcos_fac
1954 END IF
1955 END DO
1956 IF (grid%have_g0) THEN
1957 gf%array(1) = -pi/omega2*erf(omega*rc) &
1958 + twopi*rc2*erf(omega*rc) &
1959 + 2*rootpi*rc*exp(-omega2*rc2)/omega
1960 END IF
1961
1962 CASE DEFAULT
1963 cpabort("Please specify a valid operator for the periodic Poisson solver")
1964 END SELECT
1965
1966 ! The analytic Poisson solver simply limits the domain of integration
1967 ! of the Fourier transform to a sphere of radius Rc, rather than integrating
1968 ! over all space (-∞,∞)
1969 CASE (analytic0d)
1970
1971 SELECT CASE (eri_env%operator)
1972 ! This is identical to the truncated Coulomb operator integrated
1973 ! over all space, when the truncation radius is equal to the radius of
1974 ! the Poisson solver
1975 CASE (eri_operator_coulomb, eri_operator_trunc)
1976 IF (eri_env%operator == eri_operator_coulomb) THEN
1977 rc = green%radius
1978 ELSE
1979 rc = eri_env%cutoff_radius
1980 END IF
1981 DO ig = grid%first_gne0, grid%ngpts_cut_local
1982 g2 = grid%gsq(ig)
1983 g = sqrt(g2)
1984 ! Taylor expansion around zero
1985 IF (g*rc >= 0.005_dp) THEN
1986 gf%array(ig) = fourpi/g2*(1.0_dp - cos(g*rc))
1987 ELSE
1988 gf%array(ig) = fourpi/g2*(g*rc)**2/2.0_dp*(1.0_dp - (g*rc)**2/12.0_dp)
1989 END IF
1990 END DO
1991 IF (grid%have_g0) gf%array(1) = twopi*rc**2
1992
1993 ! Not tested
1994 CASE (eri_operator_yukawa)
1995 CALL cp_warn(__location__, "Yukawa operator has not been tested")
1996 rc = green%radius
1997 omega = eri_env%omega
1998 ea = exp(-omega*rc)
1999 DO ig = grid%first_gne0, grid%ngpts_cut_local
2000 g2 = grid%gsq(ig)
2001 g = sqrt(g2)
2002 g3d = fourpi/(omega**2 + g2)
2003 gf%array(ig) = g3d*(1.0_dp - ea*(cos(g*rc) + omega/g*sin(g*rc)))
2004 END DO
2005 IF (grid%have_g0) gf%array(1) = fourpi/(omega**2)*(1.0_dp - ea*(1.0_dp + omega*rc))
2006
2007 ! Long-range Coulomb
2008 ! TODO: this should be equivalent to LR truncated Coulomb from above!
2009 CASE (eri_operator_erf, eri_operator_lr_trunc)
2010 IF (eri_env%operator == eri_operator_erf) THEN
2011 rc = green%radius
2012 ELSE
2013 rc = eri_env%cutoff_radius
2014 END IF
2015 omega2 = eri_env%omega**2
2016 DO ig = grid%first_gne0, grid%ngpts_cut_local
2017 g2 = grid%gsq(ig)
2018 g = sqrt(g2)
2019 ga = -0.25_dp*g2/omega2
2020 gf%array(ig) = fourpi/g2*exp(ga)*(1.0_dp - cos(g*rc))
2021 END DO
2022 IF (grid%have_g0) gf%array(1) = twopi*rc**2
2023
2024 ! Short-range Coulomb
2025 ! TODO: this should actually be properly derived and see whether it is correct
2026 CASE (eri_operator_erfc)
2027 CALL cp_warn(__location__, &
2028 "Short-range Coulomb operator may be incorrect with ANALYTIC0D Poisson solver")
2029 rc = green%radius
2030 omega2 = eri_env%omega**2
2031 DO ig = grid%first_gne0, grid%ngpts_cut_local
2032 g2 = grid%gsq(ig)
2033 g = sqrt(g2)
2034 ga = -0.25_dp*g2/omega2
2035 gf%array(ig) = fourpi/g2*(1.0_dp - exp(ga))*(1.0_dp - cos(g*rc))
2036 END DO
2037 IF (grid%have_g0) gf%array(1) = pi/omega2
2038
2039 CASE DEFAULT
2040 cpabort("Unsupported operator")
2041 END SELECT
2042
2043 CASE DEFAULT
2044 cpabort("Unsupported Poisson solver")
2045 END SELECT
2046 END associate
2047
2048 END SUBROUTINE pw_eri_green_create
2049
2050! **************************************************************************************************
2051!> \brief Adds data for a new row to the csr matrix
2052!> \param csr_mat ...
2053!> \param nnz ...
2054!> \param rdat ...
2055!> \param rind ...
2056!> \param irow ...
2057!> \par History
2058!> 04.2016 created [JGH]
2059! **************************************************************************************************
2060 SUBROUTINE update_csr_matrix(csr_mat, nnz, rdat, rind, irow)
2061
2062 TYPE(dbcsr_csr_type), INTENT(INOUT) :: csr_mat
2063 INTEGER, INTENT(IN) :: nnz
2064 REAL(kind=dp), DIMENSION(:), INTENT(IN) :: rdat
2065 INTEGER, DIMENSION(:), INTENT(IN) :: rind
2066 INTEGER, INTENT(IN) :: irow
2067
2068 INTEGER :: k, nrow, nze, nze_new
2069
2070 IF (irow /= 0) THEN
2071 nze = csr_mat%nze_local
2072 nze_new = nze + nnz
2073 ! values
2074 CALL reallocate(csr_mat%nzval_local%r_dp, 1, nze_new)
2075 csr_mat%nzval_local%r_dp(nze + 1:nze_new) = rdat(1:nnz)
2076 ! col indices
2077 CALL reallocate(csr_mat%colind_local, 1, nze_new)
2078 csr_mat%colind_local(nze + 1:nze_new) = rind(1:nnz)
2079 ! rows
2080 nrow = csr_mat%nrows_local
2081 CALL reallocate(csr_mat%rowptr_local, 1, irow + 1)
2082 csr_mat%rowptr_local(nrow + 1:irow) = nze + 1
2083 csr_mat%rowptr_local(irow + 1) = nze_new + 1
2084 ! nzerow
2085 CALL reallocate(csr_mat%nzerow_local, 1, irow)
2086 DO k = nrow + 1, irow
2087 csr_mat%nzerow_local(k) = csr_mat%rowptr_local(k + 1) - csr_mat%rowptr_local(k)
2088 END DO
2089 csr_mat%nrows_local = irow
2090 csr_mat%nze_local = csr_mat%nze_local + nnz
2091 END IF
2092 csr_mat%nze_total = csr_mat%nze_total + nnz
2093 csr_mat%has_indices = .true.
2094
2095 END SUBROUTINE update_csr_matrix
2096
2097! **************************************************************************************************
2098!> \brief Computes and prints the active orbitals on Cube Files
2099!> \param input ...
2100!> \param qs_env the qs_env in which the qs_env lives
2101!> \param mos ...
2102! **************************************************************************************************
2103 SUBROUTINE print_orbital_cubes(input, qs_env, mos)
2104 TYPE(section_vals_type), POINTER :: input
2105 TYPE(qs_environment_type), POINTER :: qs_env
2106 TYPE(mo_set_type), DIMENSION(:), INTENT(IN) :: mos
2107
2108 CHARACTER(LEN=default_path_length) :: filebody, filename, title
2109 INTEGER :: i, imo, isp, nmo, str(3), unit_nr
2110 INTEGER, DIMENSION(:), POINTER :: alist, blist, istride
2111 LOGICAL :: do_mo, explicit_a, explicit_b
2112 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
2113 TYPE(cell_type), POINTER :: cell
2114 TYPE(cp_fm_type), POINTER :: mo_coeff
2115 TYPE(dft_control_type), POINTER :: dft_control
2116 TYPE(mp_para_env_type), POINTER :: para_env
2117 TYPE(particle_list_type), POINTER :: particles
2118 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2119 TYPE(pw_c1d_gs_type) :: wf_g
2120 TYPE(pw_env_type), POINTER :: pw_env
2121 TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
2122 TYPE(pw_r3d_rs_type) :: wf_r
2123 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
2124 TYPE(qs_subsys_type), POINTER :: subsys
2125 TYPE(section_vals_type), POINTER :: dft_section, scf_input
2126
2127 CALL section_vals_val_get(input, "FILENAME", c_val=filebody)
2128 CALL section_vals_val_get(input, "STRIDE", i_vals=istride)
2129 IF (SIZE(istride) == 1) THEN
2130 str(1:3) = istride(1)
2131 ELSEIF (SIZE(istride) == 3) THEN
2132 str(1:3) = istride(1:3)
2133 ELSE
2134 cpabort("STRIDE arguments inconsistent")
2135 END IF
2136 CALL section_vals_val_get(input, "ALIST", i_vals=alist, explicit=explicit_a)
2137 CALL section_vals_val_get(input, "BLIST", i_vals=blist, explicit=explicit_b)
2138
2139 CALL get_qs_env(qs_env=qs_env, &
2140 dft_control=dft_control, &
2141 para_env=para_env, &
2142 subsys=subsys, &
2143 atomic_kind_set=atomic_kind_set, &
2144 qs_kind_set=qs_kind_set, &
2145 cell=cell, &
2146 particle_set=particle_set, &
2147 pw_env=pw_env, &
2148 input=scf_input)
2149
2150 CALL qs_subsys_get(subsys, particles=particles)
2151 !
2152 CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
2153 CALL auxbas_pw_pool%create_pw(wf_r)
2154 CALL auxbas_pw_pool%create_pw(wf_g)
2155 !
2156 dft_section => section_vals_get_subs_vals(scf_input, "DFT")
2157 !
2158 DO isp = 1, SIZE(mos)
2159 CALL get_mo_set(mo_set=mos(isp), mo_coeff=mo_coeff, nmo=nmo)
2160
2161 IF (SIZE(mos) > 1) THEN
2162 SELECT CASE (isp)
2163 CASE (1)
2164 CALL write_mo_set_to_output_unit(mos(isp), qs_kind_set, particle_set, &
2165 dft_section, 4, 0, final_mos=.true., spin="ALPHA")
2166 CASE (2)
2167 CALL write_mo_set_to_output_unit(mos(isp), qs_kind_set, particle_set, &
2168 dft_section, 4, 0, final_mos=.true., spin="BETA")
2169 CASE DEFAULT
2170 cpabort("Invalid spin")
2171 END SELECT
2172 ELSE
2173 CALL write_mo_set_to_output_unit(mos(isp), qs_kind_set, particle_set, &
2174 dft_section, 4, 0, final_mos=.true.)
2175 END IF
2176
2177 DO imo = 1, nmo
2178 IF (isp == 1 .AND. explicit_a) THEN
2179 IF (alist(1) == -1) THEN
2180 do_mo = .true.
2181 ELSE
2182 do_mo = .false.
2183 DO i = 1, SIZE(alist)
2184 IF (imo == alist(i)) do_mo = .true.
2185 END DO
2186 END IF
2187 ELSE IF (isp == 2 .AND. explicit_b) THEN
2188 IF (blist(1) == -1) THEN
2189 do_mo = .true.
2190 ELSE
2191 do_mo = .false.
2192 DO i = 1, SIZE(blist)
2193 IF (imo == blist(i)) do_mo = .true.
2194 END DO
2195 END IF
2196 ELSE
2197 do_mo = .true.
2198 END IF
2199 IF (.NOT. do_mo) cycle
2200 CALL calculate_wavefunction(mo_coeff, imo, wf_r, wf_g, atomic_kind_set, &
2201 qs_kind_set, cell, dft_control, particle_set, pw_env)
2202 IF (para_env%is_source()) THEN
2203 WRITE (filename, '(A,A1,I4.4,A1,I1.1,A)') trim(filebody), "_", imo, "_", isp, ".cube"
2204 CALL open_file(filename, unit_number=unit_nr, file_status="UNKNOWN", file_action="WRITE")
2205 WRITE (title, *) "Active Orbital ", imo, " spin ", isp
2206 ELSE
2207 unit_nr = -1
2208 END IF
2209 CALL cp_pw_to_cube(wf_r, unit_nr, title, particles=particles, stride=istride)
2210 IF (para_env%is_source()) THEN
2211 CALL close_file(unit_nr)
2212 END IF
2213 END DO
2214 END DO
2215
2216 CALL auxbas_pw_pool%give_back_pw(wf_r)
2217 CALL auxbas_pw_pool%give_back_pw(wf_g)
2218
2219 END SUBROUTINE print_orbital_cubes
2220
2221! **************************************************************************************************
2222!> \brief Writes a FCIDUMP file
2223!> \param active_space_env ...
2224!> \param as_input ...
2225!> \param restricted ...
2226!> \par History
2227!> 04.2016 created [JGH]
2228! **************************************************************************************************
2229 SUBROUTINE fcidump(active_space_env, as_input, restricted)
2230
2231 TYPE(active_space_type), POINTER :: active_space_env
2232 TYPE(section_vals_type), POINTER :: as_input
2233 LOGICAL, INTENT(IN) :: restricted
2234
2235 INTEGER :: i, i1, i2, i3, i4, isym, iw, m1, m2, &
2236 nmo, norb, nspins
2237 REAL(kind=dp) :: checksum, esub
2238 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: fmat
2239 TYPE(cp_logger_type), POINTER :: logger
2240 TYPE(eri_fcidump_checksum) :: eri_checksum
2241
2242 checksum = 0.0_dp
2243
2244 logger => cp_get_default_logger()
2245 iw = cp_print_key_unit_nr(logger, as_input, "FCIDUMP", &
2246 extension=".fcidump", file_status="REPLACE", file_action="WRITE", file_form="FORMATTED")
2247 !
2248 nspins = active_space_env%nspins
2249 norb = SIZE(active_space_env%active_orbitals, 1)
2250 IF (nspins == 1 .OR. restricted) THEN
2251 ! Closed shell or restricted open-shell
2252 associate(ms2 => active_space_env%multiplicity, &
2253 nelec => active_space_env%nelec_active)
2254
2255 IF (iw > 0) THEN
2256 WRITE (iw, "(A,A,I4,A,I4,A,I2,A)") "&FCI", " NORB=", norb, ",NELEC=", nelec, ",MS2=", ms2, ","
2257 isym = 1
2258 WRITE (iw, "(A,1000(I1,','))") " ORBSYM=", (isym, i=1, norb)
2259 isym = 0
2260 WRITE (iw, "(A,I1,A)") " ISYM=", isym, ","
2261 IF (restricted) WRITE (iw, "(A,I1,A)") " UHF=", 0, ","
2262 WRITE (iw, "(A)") " /"
2263 END IF
2264 !
2265 ! Print integrals: ERI
2266 CALL active_space_env%eri%eri_foreach(1, active_space_env%active_orbitals, &
2267 eri_fcidump_print(iw, 1, 1), 1, 1)
2268 CALL eri_checksum%set(1, 1)
2269 CALL active_space_env%eri%eri_foreach(1, active_space_env%active_orbitals, eri_checksum, 1, 1)
2270
2271 ! Print integrals: Fij
2272 ! replicate Fock matrix
2273 nmo = active_space_env%eri%norb
2274 ALLOCATE (fmat(nmo, nmo))
2275 CALL replicate_and_symmetrize_matrix(nmo, active_space_env%fock_sub(1), fmat)
2276 IF (iw > 0) THEN
2277 i3 = 0; i4 = 0
2278 DO m1 = 1, SIZE(active_space_env%active_orbitals, 1)
2279 i1 = active_space_env%active_orbitals(m1, 1)
2280 DO m2 = m1, SIZE(active_space_env%active_orbitals, 1)
2281 i2 = active_space_env%active_orbitals(m2, 1)
2282 checksum = checksum + abs(fmat(i1, i2))
2283 WRITE (iw, "(ES23.16,4I4)") fmat(i1, i2), m1, m2, i3, i4
2284 END DO
2285 END DO
2286 END IF
2287 DEALLOCATE (fmat)
2288 ! Print energy
2289 esub = active_space_env%energy_inactive
2290 i1 = 0; i2 = 0; i3 = 0; i4 = 0
2291 checksum = checksum + abs(esub)
2292 IF (iw > 0) WRITE (iw, "(ES23.16,4I4)") esub, i1, i2, i3, i4
2293 END associate
2294
2295 ELSE
2296 associate(ms2 => active_space_env%multiplicity, &
2297 nelec => active_space_env%nelec_active)
2298
2299 IF (iw > 0) THEN
2300 WRITE (iw, "(A,A,I4,A,I4,A,I2,A)") "&FCI", " NORB=", norb, ",NELEC=", nelec, ",MS2=", ms2, ","
2301 isym = 1
2302 WRITE (iw, "(A,1000(I1,','))") " ORBSYM=", (isym, i=1, norb)
2303 isym = 0
2304 WRITE (iw, "(A,I1,A)") " ISYM=", isym, ","
2305 WRITE (iw, "(A,I1,A)") " UHF=", 1, ","
2306 WRITE (iw, "(A)") " /"
2307 END IF
2308 !
2309 ! Print integrals: ERI
2310 ! alpha-alpha
2311 CALL active_space_env%eri%eri_foreach(1, active_space_env%active_orbitals, &
2312 eri_fcidump_print(iw, 1, 1), 1, 1)
2313 CALL eri_checksum%set(1, 1)
2314 CALL active_space_env%eri%eri_foreach(1, active_space_env%active_orbitals, eri_checksum, 1, 1)
2315 ! alpha-beta
2316 CALL active_space_env%eri%eri_foreach(2, active_space_env%active_orbitals, &
2317 eri_fcidump_print(iw, 1, norb + 1), 1, 2)
2318 CALL eri_checksum%set(1, norb + 1)
2319 CALL active_space_env%eri%eri_foreach(2, active_space_env%active_orbitals, eri_checksum, 1, 2)
2320 ! beta-beta
2321 CALL active_space_env%eri%eri_foreach(3, active_space_env%active_orbitals, &
2322 eri_fcidump_print(iw, norb + 1, norb + 1), 2, 2)
2323 CALL eri_checksum%set(norb + 1, norb + 1)
2324 CALL active_space_env%eri%eri_foreach(3, active_space_env%active_orbitals, eri_checksum, 2, 2)
2325 ! Print integrals: Fij
2326 ! alpha
2327 nmo = active_space_env%eri%norb
2328 ALLOCATE (fmat(nmo, nmo))
2329 CALL replicate_and_symmetrize_matrix(nmo, active_space_env%fock_sub(1), fmat)
2330 IF (iw > 0) THEN
2331 i3 = 0; i4 = 0
2332 DO m1 = 1, norb
2333 i1 = active_space_env%active_orbitals(m1, 1)
2334 DO m2 = m1, norb
2335 i2 = active_space_env%active_orbitals(m2, 1)
2336 checksum = checksum + abs(fmat(i1, i2))
2337 WRITE (iw, "(ES23.16,4I4)") fmat(i1, i2), m1, m2, i3, i4
2338 END DO
2339 END DO
2340 END IF
2341 DEALLOCATE (fmat)
2342 ! beta
2343 ALLOCATE (fmat(nmo, nmo))
2344 CALL replicate_and_symmetrize_matrix(nmo, active_space_env%fock_sub(2), fmat)
2345 IF (iw > 0) THEN
2346 i3 = 0; i4 = 0
2347 DO m1 = 1, SIZE(active_space_env%active_orbitals, 1)
2348 i1 = active_space_env%active_orbitals(m1, 2)
2349 DO m2 = m1, SIZE(active_space_env%active_orbitals, 1)
2350 i2 = active_space_env%active_orbitals(m2, 2)
2351 checksum = checksum + abs(fmat(i1, i2))
2352 WRITE (iw, "(ES23.16,4I4)") fmat(i1, i2), m1 + norb, m2 + norb, i3, i4
2353 END DO
2354 END DO
2355 END IF
2356 DEALLOCATE (fmat)
2357 ! Print energy
2358 esub = active_space_env%energy_inactive
2359 i1 = 0; i2 = 0; i3 = 0; i4 = 0
2360 checksum = checksum + abs(esub)
2361 IF (iw > 0) WRITE (iw, "(ES23.16,4I4)") esub, i1, i2, i3, i4
2362 END associate
2363 END IF
2364 !
2365 CALL cp_print_key_finished_output(iw, logger, as_input, "FCIDUMP")
2366
2367 !>>
2368 iw = cp_logger_get_default_io_unit(logger)
2369 IF (iw > 0) WRITE (iw, '(T4,A,T66,F12.8)') "FCIDUMP| Checksum:", eri_checksum%checksum + checksum
2370 !<<
2371
2372 END SUBROUTINE fcidump
2373
2374! **************************************************************************************************
2375!> \brief replicate and symmetrize a matrix
2376!> \param norb the number of orbitals
2377!> \param distributed_matrix ...
2378!> \param replicated_matrix ...
2379! **************************************************************************************************
2380 SUBROUTINE replicate_and_symmetrize_matrix(norb, distributed_matrix, replicated_matrix)
2381 INTEGER, INTENT(IN) :: norb
2382 TYPE(cp_fm_type), INTENT(IN) :: distributed_matrix
2383 REAL(dp), DIMENSION(:, :), INTENT(INOUT) :: replicated_matrix
2384
2385 INTEGER :: i1, i2
2386 REAL(dp) :: mval
2387
2388 replicated_matrix(:, :) = 0.0_dp
2389 DO i1 = 1, norb
2390 DO i2 = i1, norb
2391 CALL cp_fm_get_element(distributed_matrix, i1, i2, mval)
2392 replicated_matrix(i1, i2) = mval
2393 replicated_matrix(i2, i1) = mval
2394 END DO
2395 END DO
2396 END SUBROUTINE replicate_and_symmetrize_matrix
2397
2398! **************************************************************************************************
2399!> \brief Calculates active space Fock matrix and inactive energy
2400!> \param active_space_env ...
2401!> \param restricted ...
2402!> \par History
2403!> 06.2016 created [JGH]
2404! **************************************************************************************************
2405 SUBROUTINE subspace_fock_matrix(active_space_env, restricted)
2406
2407 TYPE(active_space_type), POINTER :: active_space_env
2408 LOGICAL, INTENT(IN) :: restricted
2409
2410 INTEGER :: i1, i2, is, norb, nspins
2411 REAL(kind=dp) :: eeri, eref, esub, mval
2412 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: ks_a_mat, ks_a_ref, ks_b_mat, ks_b_ref, &
2413 ks_mat, ks_ref, p_a_mat, p_b_mat, p_mat
2414 TYPE(cp_fm_type), POINTER :: matrix, mo_coef
2415 TYPE(dbcsr_csr_type), POINTER :: eri, eri_aa, eri_ab, eri_bb
2416
2417 eref = active_space_env%energy_ref
2418 nspins = active_space_env%nspins
2419
2420 IF (nspins == 1) THEN
2421 CALL get_mo_set(active_space_env%mos_active(1), nmo=norb, mo_coeff=mo_coef)
2422 !
2423 ! Loop over ERI, calculate subspace HF energy and Fock matrix
2424 !
2425 ! replicate KS, Core, and P matrices
2426 ALLOCATE (ks_mat(norb, norb), ks_ref(norb, norb), p_mat(norb, norb))
2427 ks_ref = 0.0_dp
2428
2429 ! ks_mat contains the KS/Fock matrix (of full density) projected onto the AS MO subspace (f_ref in eq. 19)
2430 CALL replicate_and_symmetrize_matrix(norb, active_space_env%ks_sub(1), ks_mat)
2431 CALL replicate_and_symmetrize_matrix(norb, active_space_env%p_active(1), p_mat)
2432
2433 ! compute ks_ref = V_H[rho^A] + V_HFX[rho^A]
2434 eri => active_space_env%eri%eri(1)%csr_mat
2435 CALL build_subspace_fock_matrix(active_space_env%active_orbitals, eri, p_mat, ks_ref, &
2436 active_space_env%eri%comm_exchange)
2437
2438 ! compute eeri = E_H[rho^A] + E_HFX[rho^A] as
2439 ! eeri = 1/2 * (SUM_pq (V_H[rho^A] + V_HFX[rho^A])_pq * D^A_pq)
2440 eeri = 0.5_dp*sum(ks_ref*p_mat)
2441
2442 ! now calculate the inactive energy acoording to eq. 19, that is
2443 ! esub = E^I = E_ref - f_ref .* D^A + E_H[rho^A] + E_HFX[rho^A]
2444 ! where f^ref = ks_mat, which is the KS/Fock matrix in MO basis, transformed previously
2445 ! and is equal to ks_mat = h^0 + V_core + V_H[rho] + V_HFX[rho]
2446 esub = eref - sum(ks_mat(1:norb, 1:norb)*p_mat(1:norb, 1:norb)) + eeri
2447
2448 ! reuse ks_mat to store f^I = f^ref - (V_H[rho^A] + V_HFX[rho^A]) according to eq. 20
2449 ks_mat(1:norb, 1:norb) = ks_mat(1:norb, 1:norb) - ks_ref(1:norb, 1:norb)
2450 ! this is now the embedding potential for the AS calculation!
2451
2452 active_space_env%energy_inactive = esub
2453
2454 CALL cp_fm_release(active_space_env%fock_sub)
2455 ALLOCATE (active_space_env%fock_sub(nspins))
2456 DO is = 1, nspins
2457 matrix => active_space_env%ks_sub(is)
2458 CALL cp_fm_create(active_space_env%fock_sub(is), matrix%matrix_struct, &
2459 name="Active Fock operator")
2460 END DO
2461 matrix => active_space_env%fock_sub(1)
2462 DO i1 = 1, norb
2463 DO i2 = 1, norb
2464 mval = ks_mat(i1, i2)
2465 CALL cp_fm_set_element(matrix, i1, i2, mval)
2466 END DO
2467 END DO
2468 ELSE
2469
2470 CALL get_mo_set(active_space_env%mos_active(1), nmo=norb)
2471 !
2472 ! Loop over ERI, calculate subspace HF energy and Fock matrix
2473 !
2474 ! replicate KS, Core, and P matrices
2475 ALLOCATE (ks_a_mat(norb, norb), ks_b_mat(norb, norb), &
2476 & ks_a_ref(norb, norb), ks_b_ref(norb, norb), &
2477 & p_a_mat(norb, norb), p_b_mat(norb, norb))
2478 ks_a_ref(:, :) = 0.0_dp; ks_b_ref(:, :) = 0.0_dp
2479
2480 CALL replicate_and_symmetrize_matrix(norb, active_space_env%p_active(1), p_a_mat)
2481 CALL replicate_and_symmetrize_matrix(norb, active_space_env%p_active(2), p_b_mat)
2482 CALL replicate_and_symmetrize_matrix(norb, active_space_env%ks_sub(1), ks_a_mat)
2483 CALL replicate_and_symmetrize_matrix(norb, active_space_env%ks_sub(2), ks_b_mat)
2484 !
2485 !
2486 IF (restricted) THEN
2487 ! In the restricted case, we use the same ERIs for each spin channel
2488 eri_aa => active_space_env%eri%eri(1)%csr_mat
2489 CALL build_subspace_spin_fock_matrix(active_space_env%active_orbitals, eri_aa, eri_aa, p_a_mat, p_b_mat, ks_a_ref, &
2490 tr_mixed_eri=.false., comm_exchange=active_space_env%eri%comm_exchange)
2491 CALL build_subspace_spin_fock_matrix(active_space_env%active_orbitals, eri_aa, eri_aa, p_b_mat, p_a_mat, ks_b_ref, &
2492 tr_mixed_eri=.true., comm_exchange=active_space_env%eri%comm_exchange)
2493 ELSE
2494 eri_aa => active_space_env%eri%eri(1)%csr_mat
2495 eri_ab => active_space_env%eri%eri(2)%csr_mat
2496 eri_bb => active_space_env%eri%eri(3)%csr_mat
2497 CALL build_subspace_spin_fock_matrix(active_space_env%active_orbitals, eri_aa, eri_ab, p_a_mat, p_b_mat, ks_a_ref, &
2498 tr_mixed_eri=.false., comm_exchange=active_space_env%eri%comm_exchange)
2499 CALL build_subspace_spin_fock_matrix(active_space_env%active_orbitals, eri_bb, eri_ab, p_b_mat, p_a_mat, ks_b_ref, &
2500 tr_mixed_eri=.true., comm_exchange=active_space_env%eri%comm_exchange)
2501 END IF
2502 !
2503 ! calculate energy
2504 eeri = 0.0_dp
2505 eeri = 0.5_dp*(sum(ks_a_ref*p_a_mat) + sum(ks_b_ref*p_b_mat))
2506 esub = eref - sum(ks_a_mat*p_a_mat) - sum(ks_b_mat*p_b_mat) + eeri
2507 ks_a_mat(:, :) = ks_a_mat(:, :) - ks_a_ref(:, :)
2508 ks_b_mat(:, :) = ks_b_mat(:, :) - ks_b_ref(:, :)
2509 !
2510 active_space_env%energy_inactive = esub
2511 !
2512 CALL cp_fm_release(active_space_env%fock_sub)
2513 ALLOCATE (active_space_env%fock_sub(nspins))
2514 DO is = 1, nspins
2515 matrix => active_space_env%ks_sub(is)
2516 CALL cp_fm_create(active_space_env%fock_sub(is), matrix%matrix_struct, &
2517 name="Active Fock operator")
2518 END DO
2519
2520 matrix => active_space_env%fock_sub(1)
2521 DO i1 = 1, norb
2522 DO i2 = 1, norb
2523 mval = ks_a_mat(i1, i2)
2524 CALL cp_fm_set_element(matrix, i1, i2, mval)
2525 END DO
2526 END DO
2527 matrix => active_space_env%fock_sub(2)
2528 DO i1 = 1, norb
2529 DO i2 = 1, norb
2530 mval = ks_b_mat(i1, i2)
2531 CALL cp_fm_set_element(matrix, i1, i2, mval)
2532 END DO
2533 END DO
2534
2535 END IF
2536
2537 END SUBROUTINE subspace_fock_matrix
2538
2539! **************************************************************************************************
2540!> \brief build subspace fockian
2541!> \param active_orbitals the active orbital indices
2542!> \param eri two electon integrals in MO
2543!> \param p_mat density matrix
2544!> \param ks_ref fockian matrix
2545!> \param comm_exchange ...
2546! **************************************************************************************************
2547 SUBROUTINE build_subspace_fock_matrix(active_orbitals, eri, p_mat, ks_ref, comm_exchange)
2548 INTEGER, DIMENSION(:, :), INTENT(IN) :: active_orbitals
2549 TYPE(dbcsr_csr_type), INTENT(IN) :: eri
2550 REAL(dp), DIMENSION(:, :), INTENT(IN) :: p_mat
2551 REAL(dp), DIMENSION(:, :), INTENT(INOUT) :: ks_ref
2552 TYPE(mp_comm_type), INTENT(IN) :: comm_exchange
2553
2554 CHARACTER(LEN=*), PARAMETER :: routinen = 'build_subspace_fock_matrix'
2555
2556 INTEGER :: handle, i1, i12, i12l, i2, i3, i34, &
2557 i34l, i4, irptr, m1, m2, nindex, &
2558 nmo_total, norb
2559 INTEGER, DIMENSION(2) :: irange
2560 REAL(dp) :: erint
2561 TYPE(mp_comm_type) :: mp_group
2562
2563 CALL timeset(routinen, handle)
2564
2565 ! Nothing to do
2566 norb = SIZE(active_orbitals, 1)
2567 nmo_total = SIZE(p_mat, 1)
2568 nindex = (nmo_total*(nmo_total + 1))/2
2569 CALL mp_group%set_handle(eri%mp_group%get_handle())
2570 irange = get_irange_csr(nindex, comm_exchange)
2571 DO m1 = 1, norb
2572 i1 = active_orbitals(m1, 1)
2573 DO m2 = m1, norb
2574 i2 = active_orbitals(m2, 1)
2575 i12 = csr_idx_to_combined(i1, i2, nmo_total)
2576 IF (i12 >= irange(1) .AND. i12 <= irange(2)) THEN
2577 i12l = i12 - irange(1) + 1
2578 irptr = eri%rowptr_local(i12l) - 1
2579 DO i34l = 1, eri%nzerow_local(i12l)
2580 i34 = eri%colind_local(irptr + i34l)
2581 CALL csr_idx_from_combined(i34, nmo_total, i3, i4)
2582 erint = eri%nzval_local%r_dp(irptr + i34l)
2583 ! Coulomb
2584 ks_ref(i1, i2) = ks_ref(i1, i2) + erint*p_mat(i3, i4)
2585 IF (i3 /= i4) THEN
2586 ks_ref(i1, i2) = ks_ref(i1, i2) + erint*p_mat(i3, i4)
2587 END IF
2588 IF (i12 /= i34) THEN
2589 ks_ref(i3, i4) = ks_ref(i3, i4) + erint*p_mat(i1, i2)
2590 IF (i1 /= i2) THEN
2591 ks_ref(i3, i4) = ks_ref(i3, i4) + erint*p_mat(i1, i2)
2592 END IF
2593 END IF
2594 ! Exchange
2595 erint = -0.5_dp*erint
2596 ks_ref(i1, i3) = ks_ref(i1, i3) + erint*p_mat(i2, i4)
2597 IF (i1 /= i2) THEN
2598 ks_ref(i2, i3) = ks_ref(i2, i3) + erint*p_mat(i1, i4)
2599 END IF
2600 IF (i3 /= i4) THEN
2601 ks_ref(i1, i4) = ks_ref(i1, i4) + erint*p_mat(i2, i3)
2602 END IF
2603 IF (i1 /= i2 .AND. i3 /= i4) THEN
2604 ks_ref(i2, i4) = ks_ref(i2, i4) + erint*p_mat(i1, i3)
2605 END IF
2606 END DO
2607 END IF
2608 END DO
2609 END DO
2610 !
2611 DO m1 = 1, norb
2612 i1 = active_orbitals(m1, 1)
2613 DO m2 = m1, norb
2614 i2 = active_orbitals(m2, 1)
2615 ks_ref(i2, i1) = ks_ref(i1, i2)
2616 END DO
2617 END DO
2618 CALL mp_group%sum(ks_ref)
2619
2620 CALL timestop(handle)
2621
2622 END SUBROUTINE build_subspace_fock_matrix
2623
2624! **************************************************************************************************
2625!> \brief build subspace fockian for unrestricted spins
2626!> \param active_orbitals the active orbital indices
2627!> \param eri_aa two electon integrals in MO with parallel spins
2628!> \param eri_ab two electon integrals in MO with anti-parallel spins
2629!> \param p_a_mat density matrix for up-spin
2630!> \param p_b_mat density matrix for down-spin
2631!> \param ks_a_ref fockian matrix for up-spin
2632!> \param tr_mixed_eri boolean to indicate Coulomb interaction alignment
2633!> \param comm_exchange ...
2634! **************************************************************************************************
2635 SUBROUTINE build_subspace_spin_fock_matrix(active_orbitals, eri_aa, eri_ab, p_a_mat, p_b_mat, ks_a_ref, tr_mixed_eri, &
2636 comm_exchange)
2637 INTEGER, DIMENSION(:, :), INTENT(IN) :: active_orbitals
2638 TYPE(dbcsr_csr_type), INTENT(IN) :: eri_aa, eri_ab
2639 REAL(dp), DIMENSION(:, :), INTENT(IN) :: p_a_mat, p_b_mat
2640 REAL(dp), DIMENSION(:, :), INTENT(INOUT) :: ks_a_ref
2641 LOGICAL, INTENT(IN) :: tr_mixed_eri
2642 TYPE(mp_comm_type), INTENT(IN) :: comm_exchange
2643
2644 CHARACTER(LEN=*), PARAMETER :: routinen = 'build_subspace_spin_fock_matrix'
2645
2646 INTEGER :: handle, i1, i12, i12l, i2, i3, i34, &
2647 i34l, i4, irptr, m1, m2, nindex, &
2648 nmo_total, norb, spin1, spin2
2649 INTEGER, DIMENSION(2) :: irange
2650 REAL(dp) :: erint
2651 TYPE(mp_comm_type) :: mp_group
2652
2653 CALL timeset(routinen, handle)
2654
2655 norb = SIZE(active_orbitals, 1)
2656 nmo_total = SIZE(p_a_mat, 1)
2657 nindex = (nmo_total*(nmo_total + 1))/2
2658 irange = get_irange_csr(nindex, comm_exchange)
2659 IF (tr_mixed_eri) THEN
2660 spin1 = 2
2661 spin2 = 1
2662 ELSE
2663 spin1 = 1
2664 spin2 = 2
2665 END IF
2666 DO m1 = 1, norb
2667 i1 = active_orbitals(m1, spin1)
2668 DO m2 = m1, norb
2669 i2 = active_orbitals(m2, spin1)
2670 i12 = csr_idx_to_combined(i1, i2, nmo_total)
2671 IF (i12 >= irange(1) .AND. i12 <= irange(2)) THEN
2672 i12l = i12 - irange(1) + 1
2673 irptr = eri_aa%rowptr_local(i12l) - 1
2674 DO i34l = 1, eri_aa%nzerow_local(i12l)
2675 i34 = eri_aa%colind_local(irptr + i34l)
2676 CALL csr_idx_from_combined(i34, nmo_total, i3, i4)
2677 erint = eri_aa%nzval_local%r_dp(irptr + i34l)
2678 ! Coulomb
2679 !F_ij += (ij|kl)*d_kl
2680 ks_a_ref(i1, i2) = ks_a_ref(i1, i2) + erint*p_a_mat(i3, i4)
2681 IF (i12 /= i34) THEN
2682 !F_kl += (ij|kl)*d_ij
2683 ks_a_ref(i3, i4) = ks_a_ref(i3, i4) + erint*p_a_mat(i1, i2)
2684 END IF
2685 ! Exchange
2686 erint = -1.0_dp*erint
2687 !F_ik -= (ij|kl)*d_jl
2688 ks_a_ref(i1, i3) = ks_a_ref(i1, i3) + erint*p_a_mat(i2, i4)
2689 IF (i1 /= i2) THEN
2690 !F_jk -= (ij|kl)*d_il
2691 ks_a_ref(i2, i3) = ks_a_ref(i2, i3) + erint*p_a_mat(i1, i4)
2692 END IF
2693 IF (i3 /= i4) THEN
2694 !F_il -= (ij|kl)*d_jk
2695 ks_a_ref(i1, i4) = ks_a_ref(i1, i4) + erint*p_a_mat(i2, i3)
2696 END IF
2697 IF (i1 /= i2 .AND. i3 /= i4) THEN
2698 !F_jl -= (ij|kl)*d_ik
2699 ks_a_ref(i2, i4) = ks_a_ref(i2, i4) + erint*p_a_mat(i1, i3)
2700 END IF
2701 END DO
2702 END IF
2703 END DO
2704 END DO
2705 !
2706
2707 irange = get_irange_csr(nindex, comm_exchange)
2708 DO m1 = 1, norb
2709 i1 = active_orbitals(m1, 1)
2710 DO m2 = m1, norb
2711 i2 = active_orbitals(m2, 1)
2712 i12 = csr_idx_to_combined(i1, i2, nmo_total)
2713 IF (i12 >= irange(1) .AND. i12 <= irange(2)) THEN
2714 i12l = i12 - irange(1) + 1
2715 irptr = eri_ab%rowptr_local(i12l) - 1
2716 DO i34l = 1, eri_ab%nzerow_local(i12l)
2717 i34 = eri_ab%colind_local(irptr + i34l)
2718 CALL csr_idx_from_combined(i34, nmo_total, i3, i4)
2719 erint = eri_ab%nzval_local%r_dp(irptr + i34l)
2720 ! Coulomb
2721 IF (tr_mixed_eri) THEN
2722 !F_kl += (kl beta|ij alpha )*d_alpha_ij
2723 ks_a_ref(i3, i4) = ks_a_ref(i3, i4) + erint*p_b_mat(i1, i2)
2724 ELSE
2725 !F_ij += (ij alpha|kl beta )*d_beta_kl
2726 ks_a_ref(i1, i2) = ks_a_ref(i1, i2) + erint*p_b_mat(i3, i4)
2727 END IF
2728 END DO
2729 END IF
2730 END DO
2731 END DO
2732 !
2733 DO m1 = 1, norb
2734 i1 = active_orbitals(m1, spin1)
2735 DO m2 = m1, norb
2736 i2 = active_orbitals(m2, spin1)
2737 ks_a_ref(i2, i1) = ks_a_ref(i1, i2)
2738 END DO
2739 END DO
2740 CALL mp_group%set_handle(eri_aa%mp_group%get_handle())
2741 CALL mp_group%sum(ks_a_ref)
2742
2743 CALL timestop(handle)
2744
2745 END SUBROUTINE build_subspace_spin_fock_matrix
2746
2747! **************************************************************************************************
2748!> \brief Creates a local basis
2749!> \param pro_basis_set ...
2750!> \param zval ...
2751!> \param ishell ...
2752!> \param nshell ...
2753!> \param lnam ...
2754!> \par History
2755!> 05.2016 created [JGH]
2756! **************************************************************************************************
2757 SUBROUTINE create_pro_basis(pro_basis_set, zval, ishell, nshell, lnam)
2758 TYPE(gto_basis_set_type), POINTER :: pro_basis_set
2759 INTEGER, INTENT(IN) :: zval, ishell
2760 INTEGER, DIMENSION(:), INTENT(IN) :: nshell
2761 CHARACTER(len=*), DIMENSION(:), INTENT(IN) :: lnam
2762
2763 CHARACTER(len=6), DIMENSION(:), POINTER :: sym
2764 INTEGER :: i, l, nj
2765 INTEGER, DIMENSION(4, 7) :: ne
2766 INTEGER, DIMENSION(:), POINTER :: lq, nq
2767 REAL(kind=dp), DIMENSION(:), POINTER :: zet
2768 TYPE(sto_basis_set_type), POINTER :: sto_basis_set
2769
2770 cpassert(.NOT. ASSOCIATED(pro_basis_set))
2771 NULLIFY (sto_basis_set)
2772
2773 ! electronic configuration
2774 ne = 0
2775 DO l = 1, 4 !lq(1)+1
2776 nj = 2*(l - 1) + 1
2777 DO i = l, 7 ! nq(1)
2778 ne(l, i) = ptable(zval)%e_conv(l - 1) - 2*nj*(i - l)
2779 ne(l, i) = max(ne(l, i), 0)
2780 ne(l, i) = min(ne(l, i), 2*nj)
2781 END DO
2782 END DO
2783 ALLOCATE (nq(ishell), lq(ishell), zet(ishell), sym(ishell))
2784 DO i = 1, ishell
2785 nq(i) = nshell(i)
2786 SELECT CASE (lnam(i))
2787 CASE ('S', 's')
2788 lq(i) = 0
2789 CASE ('P', 'p')
2790 lq(i) = 1
2791 CASE ('D', 'd')
2792 lq(i) = 2
2793 CASE ('F', 'f')
2794 lq(i) = 3
2795 CASE DEFAULT
2796 cpabort("Wrong l QN")
2797 END SELECT
2798 sym(i) = lnam(i)
2799 zet(i) = srules(zval, ne, nq(1), lq(1))
2800 END DO
2801 CALL allocate_sto_basis_set(sto_basis_set)
2802 CALL set_sto_basis_set(sto_basis_set, nshell=1, nq=nq, lq=lq, zet=zet, symbol=sym)
2803 CALL create_gto_from_sto_basis(sto_basis_set, pro_basis_set, 6)
2804 pro_basis_set%norm_type = 2
2805 CALL init_orb_basis_set(pro_basis_set)
2806 CALL deallocate_sto_basis_set(sto_basis_set)
2807
2808 END SUBROUTINE create_pro_basis
2809
2810! **************************************************************************************************
2811!> \brief Update the density matrix in AO basis with the active density contribution
2812!> \param active_space_env the active space environment
2813!> \param rho_ao the density matrix in AO basis
2814! **************************************************************************************************
2815 SUBROUTINE update_density_ao(active_space_env, rho_ao)
2816 TYPE(active_space_type), POINTER :: active_space_env
2817 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: rho_ao
2818
2819 INTEGER :: ispin, nao, nmo, nspins
2820 TYPE(cp_fm_type) :: r, u
2821 TYPE(cp_fm_type), POINTER :: c_active, p_active_mo
2822 TYPE(dbcsr_type), POINTER :: p_inactive_ao
2823 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos_active
2824
2825 ! Transform the AS density matrix P_MO to the atomic orbital basis,
2826 ! this is simply C * P_MO * C^T
2827 nspins = active_space_env%nspins
2828 mos_active => active_space_env%mos_active
2829 DO ispin = 1, nspins
2830 ! size of p_inactive_ao is (nao x nao)
2831 p_inactive_ao => active_space_env%pmat_inactive(ispin)%matrix
2832
2833 ! copy p_inactive_ao to rho_ao
2834 CALL dbcsr_copy(rho_ao(ispin)%matrix, p_inactive_ao)
2835
2836 ! size of p_active_mo is (nmo x nmo)
2837 p_active_mo => active_space_env%p_active(ispin)
2838
2839 ! calculate R = p_mo
2840 CALL cp_fm_create(r, p_active_mo%matrix_struct)
2841 CALL cp_fm_to_fm(p_active_mo, r)
2842
2843 ! calculate U = C * p_mo
2844 CALL get_mo_set(mos_active(ispin), mo_coeff=c_active, nao=nao, nmo=nmo)
2845 CALL cp_fm_create(u, c_active%matrix_struct)
2846 CALL parallel_gemm("N", "N", nao, nmo, nmo, 1.0_dp, c_active, r, 0.0_dp, u)
2847
2848 CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=rho_ao(ispin)%matrix, &
2849 matrix_v=u, matrix_g=c_active, ncol=nmo, alpha=1.0_dp)
2850
2851 CALL cp_fm_release(r)
2852 CALL cp_fm_release(u)
2853 END DO
2854
2855 END SUBROUTINE update_density_ao
2856
2857! **************************************************************************************************
2858!> \brief Print each value on the master node
2859!> \param this object reference
2860!> \param i i-index
2861!> \param j j-index
2862!> \param k k-index
2863!> \param l l-index
2864!> \param val value of the integral at (i,j,k.l)
2865!> \return always true to dump all integrals
2866! **************************************************************************************************
2867 LOGICAL FUNCTION eri_fcidump_print_func(this, i, j, k, l, val) RESULT(cont)
2868 CLASS(eri_fcidump_print), INTENT(inout) :: this
2869 INTEGER, INTENT(in) :: i, j, k, l
2870 REAL(kind=dp), INTENT(in) :: val
2871
2872 ! write to the actual file only on the master
2873 IF (this%unit_nr > 0) THEN
2874 WRITE (this%unit_nr, "(ES23.16,4I4)") val, i + this%bra_start - 1, j + this%bra_start - 1, &
2875 & k + this%ket_start - 1, l + this%ket_start - 1
2876 END IF
2877
2878 cont = .true.
2879 END FUNCTION eri_fcidump_print_func
2880
2881! **************************************************************************************************
2882!> \brief checksum each value on the master node
2883!> \param this object reference
2884!> \param i i-index
2885!> \param j j-index
2886!> \param k k-index
2887!> \param l l-index
2888!> \param val value of the integral at (i,j,k.l)
2889!> \return always true to dump all integrals
2890! **************************************************************************************************
2891 LOGICAL FUNCTION eri_fcidump_checksum_func(this, i, j, k, l, val) RESULT(cont)
2892 CLASS(eri_fcidump_checksum), INTENT(inout) :: this
2893 INTEGER, INTENT(in) :: i, j, k, l
2894 REAL(kind=dp), INTENT(in) :: val
2895 mark_used(i)
2896 mark_used(j)
2897 mark_used(k)
2898 mark_used(l)
2899
2900 this%checksum = this%checksum + abs(val)
2901
2902 cont = .true.
2903 END FUNCTION eri_fcidump_checksum_func
2904
2905! **************************************************************************************************
2906!> \brief Update active space density matrix from a fortran array
2907!> \param p_act_mo density matrix in active space MO basis
2908!> \param active_space_env active space environment
2909!> \param ispin spin index
2910!> \author Vladimir Rybkin
2911! **************************************************************************************************
2912 SUBROUTINE update_active_density(p_act_mo, active_space_env, ispin)
2913 REAL(kind=dp), DIMENSION(:) :: p_act_mo
2914 TYPE(active_space_type), POINTER :: active_space_env
2915 INTEGER :: ispin
2916
2917 INTEGER :: i1, i2, m1, m2, nmo_active
2918 REAL(kind=dp) :: alpha, pij_new, pij_old
2919 TYPE(cp_fm_type), POINTER :: p_active
2920
2921 p_active => active_space_env%p_active(ispin)
2922 nmo_active = active_space_env%nmo_active
2923 alpha = active_space_env%alpha
2924
2925 DO i1 = 1, nmo_active
2926 m1 = active_space_env%active_orbitals(i1, ispin)
2927 DO i2 = 1, nmo_active
2928 m2 = active_space_env%active_orbitals(i2, ispin)
2929 CALL cp_fm_get_element(p_active, m1, m2, pij_old)
2930 pij_new = p_act_mo(i2 + (i1 - 1)*nmo_active)
2931 pij_new = alpha*pij_new + (1.0_dp - alpha)*pij_old
2932 CALL cp_fm_set_element(p_active, m1, m2, pij_new)
2933 END DO
2934 END DO
2935
2936 END SUBROUTINE update_active_density
2937
2938! **************************************************************************************************
2939!> \brief Compute and print the AS rdm and the natural orbitals occupation numbers
2940!> \param active_space_env active space environment
2941!> \param iw output unit
2942!> \author Stefano Battaglia
2943! **************************************************************************************************
2944 SUBROUTINE print_pmat_noon(active_space_env, iw)
2945 TYPE(active_space_type), POINTER :: active_space_env
2946 INTEGER :: iw
2947
2948 INTEGER :: i1, i2, ii, ispin, jm, m1, m2, &
2949 nmo_active, nspins
2950 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: noon, pmat
2951 TYPE(cp_fm_type), POINTER :: p_active
2952
2953 nspins = active_space_env%nspins
2954 nmo_active = active_space_env%nmo_active
2955
2956 ALLOCATE (noon(nmo_active, nspins))
2957 ALLOCATE (pmat(nmo_active, nmo_active))
2958
2959 DO ispin = 1, nspins
2960 p_active => active_space_env%p_active(ispin)
2961 noon(:, ispin) = 0.0_dp
2962 pmat = 0.0_dp
2963
2964 DO i1 = 1, nmo_active
2965 m1 = active_space_env%active_orbitals(i1, ispin)
2966 DO i2 = 1, nmo_active
2967 m2 = active_space_env%active_orbitals(i2, ispin)
2968 CALL cp_fm_get_element(p_active, m1, m2, pmat(i1, i2))
2969 END DO
2970 END DO
2971
2972 IF (iw > 0) THEN
2973 WRITE (iw, '(/,T3,A,I2,A)') "Active space density matrix for spin ", ispin
2974 DO i1 = 1, nmo_active
2975 DO ii = 1, nmo_active, 8
2976 jm = min(7, nmo_active - ii)
2977 WRITE (iw, '(T3,6(F9.4))') (pmat(i1, ii + i2), i2=0, jm)
2978 END DO
2979 END DO
2980 END IF
2981
2982 ! diagonalize the density matrix
2983 CALL diamat_all(pmat, noon(:, ispin))
2984
2985 IF (iw > 0) THEN
2986 WRITE (iw, '(/,T3,A,I2,A)') "Natural orbitals occupation numbers for spin ", ispin
2987 DO i1 = 1, nmo_active, 8
2988 jm = min(7, nmo_active - i1)
2989 ! noons are stored in ascending order, so reverse-print them
2990 WRITE (iw, '(T3,6(F9.4))') (noon(nmo_active - i1 - i2 + 1, ispin), i2=0, jm)
2991 END DO
2992 END IF
2993
2994 END DO
2995
2996 DEALLOCATE (noon)
2997 DEALLOCATE (pmat)
2998
2999 END SUBROUTINE print_pmat_noon
3000
3001! **************************************************************************************************
3002!> \brief ...
3003!> \param qs_env ...
3004!> \param active_space_env ...
3005!> \param as_input ...
3006! **************************************************************************************************
3007 SUBROUTINE rsdft_embedding(qs_env, active_space_env, as_input)
3008 TYPE(qs_environment_type), POINTER :: qs_env
3009 TYPE(active_space_type), POINTER :: active_space_env
3010 TYPE(section_vals_type), POINTER :: as_input
3011
3012 CHARACTER(len=*), PARAMETER :: routinen = 'rsdft_embedding'
3013 INTEGER :: handle
3014
3015#ifdef __NO_SOCKETS
3016 CALL timeset(routinen, handle)
3017 cpabort("CP2K was compiled with the __NO_SOCKETS option!")
3018 mark_used(qs_env)
3019 mark_used(active_space_env)
3020 mark_used(as_input)
3021#else
3022
3023 INTEGER :: iw, client_fd, socket_fd, iter, max_iter
3024 LOGICAL :: converged, do_scf_embedding, ionode
3025 REAL(kind=dp) :: delta_e, energy_corr, energy_new, &
3026 energy_old, energy_scf, eps_iter, t1, t2
3027 TYPE(cp_logger_type), POINTER :: logger
3028 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: rho_ao
3029 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos_active
3030 TYPE(mp_para_env_type), POINTER :: para_env
3031 TYPE(qs_energy_type), POINTER :: energy
3032 TYPE(qs_ks_env_type), POINTER :: ks_env
3033 TYPE(qs_rho_type), POINTER :: rho
3034 TYPE(dft_control_type), POINTER :: dft_control
3035
3036 CALL timeset(routinen, handle)
3037
3038 t1 = m_walltime()
3039
3040 logger => cp_get_default_logger()
3041 iw = cp_logger_get_default_io_unit(logger)
3042
3043 CALL get_qs_env(qs_env, para_env=para_env, dft_control=dft_control)
3044 ionode = para_env%is_source()
3045
3046 ! get info from the input
3047 CALL section_vals_val_get(as_input, "SCF_EMBEDDING", l_val=do_scf_embedding)
3048 active_space_env%do_scf_embedding = do_scf_embedding
3049 CALL section_vals_val_get(as_input, "MAX_ITER", i_val=max_iter)
3050 IF (max_iter < 0) cpabort("Specify a non-negative number of max iterations.")
3051 CALL section_vals_val_get(as_input, "EPS_ITER", r_val=eps_iter)
3052 IF (eps_iter < 0.0) cpabort("Specify a non-negative convergence threshold.")
3053
3054 ! create the socket and wait for the client to connect
3055 CALL initialize_socket(socket_fd, client_fd, as_input, ionode)
3056 CALL para_env%sync()
3057
3058 ! send two-electron integrals to the client
3059 CALL send_eri_to_client(client_fd, active_space_env, para_env)
3060
3061 ! get pointer to density in ao basis
3062 CALL get_qs_env(qs_env, rho=rho, energy=energy, ks_env=ks_env)
3063 CALL qs_rho_get(rho, rho_ao=rho_ao)
3064
3065 IF (iw > 0) THEN
3066 WRITE (unit=iw, fmt="(/,T2,A,/)") &
3067 "RANGE-SEPARATED DFT EMBEDDING SELF-CONSISTENT OPTIMIZATION"
3068
3069 WRITE (iw, '(T3,A,T68,I12)') "Max. iterations", max_iter
3070 WRITE (iw, '(T3,A,T68,E12.4)') "Conv. threshold", eps_iter
3071 WRITE (iw, '(T3,A,T66,F14.2)') "Density damping", active_space_env%alpha
3072
3073 WRITE (unit=iw, fmt="(/,T3,A,T11,A,T21,A,T34,A,T55,A,T75,A,/,T3,A)") &
3074 "Iter", "Update", "Time", "Corr. energy", "Total energy", "Change", repeat("-", 78)
3075 END IF
3076 ! CALL cp_add_iter_level(logger%iter_info, "QS_SCF")
3077
3078 iter = 0
3079 converged = .false.
3080 ! store the scf energy
3081 energy_scf = active_space_env%energy_ref
3082 energy_new = energy_scf
3083 mos_active => active_space_env%mos_active
3084 ! CALL set_qs_env(qs_env, active_space=active_space_env)
3085
3086 ! start the self-consistent embedding loop
3087 DO WHILE (iter < max_iter)
3088 iter = iter + 1
3089
3090 ! send V_emb and E_ina to the active space solver and update
3091 ! the active space environment with the new active energy and density
3092 CALL send_fock_to_client(client_fd, active_space_env, para_env)
3093
3094 ! update energies
3095 energy_old = energy_new
3096 energy_new = active_space_env%energy_total
3097 energy_corr = energy_new - energy_scf
3098 delta_e = energy_new - energy_old
3099
3100 ! get timer
3101 t2 = t1
3102 t1 = m_walltime()
3103 ! print out progress
3104 IF ((iw > 0)) THEN
3105 WRITE (unit=iw, &
3106 fmt="(T3,I4,T11,A,T19,F6.1,T28,F18.10,T49,F18.10,T70,ES11.2)") &
3107 iter, 'P_Mix', t1 - t2, energy_corr, energy_new, delta_e
3108 CALL m_flush(iw)
3109 END IF
3110
3111 ! update total density in AO basis with the AS contribution
3112 CALL update_density_ao(active_space_env, rho_ao) ! rho_ao is updated
3113
3114 ! calculate F_ks in AO basis (which contains Vxc) with the new density
3115 CALL qs_rho_update_rho(rho, qs_env=qs_env) ! updates rho_r and rho_g using rho_ao
3116 CALL qs_ks_did_change(qs_env%ks_env, rho_changed=.true.) ! set flags about the change
3117 ! Re-evaluate the traces between the density matrix and the core Hamiltonians
3118 CALL evaluate_core_matrix_traces(qs_env)
3119 ! the ks matrix will be rebuilt so this is fine now
3120 ! CALL set_ks_env(qs_env%ks_env, potential_changed=.FALSE.)
3121 CALL qs_ks_build_kohn_sham_matrix(qs_env, calculate_forces=.false., &
3122 just_energy=.false., &
3123 ext_xc_section=active_space_env%xc_section)
3124
3125 ! update the reference energy
3126 active_space_env%energy_ref = energy%total
3127
3128 ! transform KS/Fock, Vxc and Hcore from AO to MO basis
3129 CALL calculate_operators(mos_active, qs_env, active_space_env)
3130
3131 ! calculate the new inactive energy and embedding potential
3132 CALL subspace_fock_matrix(active_space_env, dft_control%roks)
3133
3134 ! check if it is a one-shot correction
3135 IF (.NOT. active_space_env%do_scf_embedding) THEN
3136 IF (iw > 0) THEN
3137 WRITE (unit=iw, fmt="(/,T3,A,I5,A)") &
3138 "*** one-shot embedding correction finished ***"
3139 END IF
3140 converged = .true.
3141 EXIT
3142 ! check for convergence
3143 ELSEIF (abs(delta_e) <= eps_iter) THEN
3144 IF (iw > 0) THEN
3145 WRITE (unit=iw, fmt="(/,T3,A,I5,A)") &
3146 "*** rs-DFT embedding run converged in ", iter, " iteration(s) ***"
3147 END IF
3148 converged = .true.
3149 EXIT
3150 END IF
3151 END DO
3152
3153 IF (.NOT. converged) THEN
3154 IF (iw > 0) THEN
3155 WRITE (unit=iw, fmt="(/,T3,A,I5,A)") &
3156 "*** rs-DFT embedding did not converged after ", iter, " iteration(s) ***"
3157 END IF
3158 END IF
3159
3160 ! update qs total energy to the final rs-DFT energy
3161 energy%total = active_space_env%energy_total
3162
3163 ! print final energy contributions
3164 IF (iw > 0) THEN
3165 WRITE (unit=iw, fmt="(/,T3,A)") &
3166 "Final energy contributions:"
3167 WRITE (unit=iw, fmt="(T6,A,T56,F20.10)") &
3168 "Inactive energy:", active_space_env%energy_inactive
3169 WRITE (unit=iw, fmt="(T6,A,T56,F20.10)") &
3170 "Active energy:", active_space_env%energy_active
3171 WRITE (unit=iw, fmt="(T6,A,T56,F20.10)") &
3172 "Correlation energy:", energy_corr
3173 WRITE (unit=iw, fmt="(T6,A,T56,F20.10)") &
3174 "Total rs-DFT energy:", active_space_env%energy_total
3175 END IF
3176
3177 ! print the AS rdm and the natural orbital occupation numbers
3178 CALL print_pmat_noon(active_space_env, iw)
3179
3180 CALL finalize_socket(socket_fd, client_fd, as_input, ionode)
3181 CALL para_env%sync()
3182#endif
3183
3184 CALL timestop(handle)
3185
3186 END SUBROUTINE rsdft_embedding
3187
3188#ifndef __NO_SOCKETS
3189! **************************************************************************************************
3190!> \brief Creates the socket, spawns the client and connects to it
3191!> \param socket_fd the socket file descriptor
3192!> \param client_fd the client file descriptor
3193!> \param as_input active space inpute section
3194!> \param ionode logical flag indicating if the process is the master
3195! **************************************************************************************************
3196 SUBROUTINE initialize_socket(socket_fd, client_fd, as_input, ionode)
3197 INTEGER, INTENT(OUT) :: socket_fd, client_fd
3198 TYPE(section_vals_type), INTENT(IN), POINTER :: as_input
3199 LOGICAL, INTENT(IN) :: ionode
3200
3201 CHARACTER(len=*), PARAMETER :: routinen = 'initialize_socket'
3202 INTEGER, PARAMETER :: backlog = 10
3203
3204 CHARACTER(len=default_path_length) :: hostname
3205 INTEGER :: handle, iw, port, protocol
3206 LOGICAL :: inet
3207 TYPE(cp_logger_type), POINTER :: logger
3208
3209 CALL timeset(routinen, handle)
3210
3211 logger => cp_get_default_logger()
3212 iw = cp_logger_get_default_io_unit(logger)
3213
3214 ! protocol == 0 for UNIX, protocol > 0 for INET
3215 CALL section_vals_val_get(as_input, "SOCKET%INET", l_val=inet)
3216 IF (inet) THEN
3217 protocol = 1
3218 ELSE
3219 protocol = 0
3220 END IF
3221 CALL section_vals_val_get(as_input, "SOCKET%HOST", c_val=hostname)
3222 CALL section_vals_val_get(as_input, "SOCKET%PORT", i_val=port)
3223
3224 IF (ionode) THEN
3225 CALL open_bind_socket(socket_fd, protocol, port, trim(hostname)//c_null_char)
3226 WRITE (iw, '(/,T2,A,A)') "@SERVER: Created socket with address ", trim(hostname)
3227 CALL listen_socket(socket_fd, backlog)
3228
3229 ! wait until a connetion request arrives
3230 WRITE (iw, '(T2,A)') "@SERVER: Waiting for requests..."
3231 CALL accept_socket(socket_fd, client_fd)
3232 WRITE (iw, '(T2,A,I2)') "@SERVER: Accepted socket with fd ", client_fd
3233 END IF
3234
3235 CALL timestop(handle)
3236
3237 END SUBROUTINE initialize_socket
3238
3239! **************************************************************************************************
3240!> \brief Closes the connection to the socket and deletes the file
3241!> \param socket_fd the socket file descriptor
3242!> \param client_fd the client file descriptor
3243!> \param as_input active space inpute section
3244!> \param ionode logical flag indicating if the process is the master
3245! **************************************************************************************************
3246 SUBROUTINE finalize_socket(socket_fd, client_fd, as_input, ionode)
3247 INTEGER, INTENT(IN) :: socket_fd, client_fd
3248 TYPE(section_vals_type), INTENT(IN), POINTER :: as_input
3249 LOGICAL, INTENT(IN) :: ionode
3250
3251 CHARACTER(len=*), PARAMETER :: routinen = 'finalize_socket'
3252 INTEGER, PARAMETER :: header_len = 12
3253
3254 CHARACTER(len=default_path_length) :: hostname
3255 INTEGER :: handle
3256
3257 CALL timeset(routinen, handle)
3258
3259 CALL section_vals_val_get(as_input, "SOCKET%HOST", c_val=hostname)
3260
3261 IF (ionode) THEN
3262 ! signal the client to quit
3263 CALL writebuffer(client_fd, "QUIT ", header_len)
3264 ! close the connection
3265 CALL close_socket(client_fd)
3266 CALL close_socket(socket_fd)
3267
3268 ! delete the socket file
3269 IF (file_exists(trim(hostname))) THEN
3270 CALL remove_socket_file(trim(hostname)//c_null_char)
3271 END IF
3272 END IF
3273
3274 CALL timestop(handle)
3275
3276 END SUBROUTINE finalize_socket
3277
3278! **************************************************************************************************
3279!> \brief Sends the two-electron integrals to the client vie the socket
3280!> \param client_fd the client file descriptor
3281!> \param active_space_env active space environment
3282!> \param para_env parallel environment
3283! **************************************************************************************************
3284 SUBROUTINE send_eri_to_client(client_fd, active_space_env, para_env)
3285 INTEGER, INTENT(IN) :: client_fd
3286 TYPE(active_space_type), INTENT(IN), POINTER :: active_space_env
3287 TYPE(mp_para_env_type), INTENT(IN), POINTER :: para_env
3288
3289 CHARACTER(len=*), PARAMETER :: routinen = 'send_eri_to_client'
3290 INTEGER, PARAMETER :: header_len = 12
3291
3292 CHARACTER(len=default_string_length) :: header
3293 INTEGER :: handle, iw
3294 LOGICAL :: ionode
3295 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: eri_aa, eri_ab, eri_bb, s_ab
3296 TYPE(cp_logger_type), POINTER :: logger
3297
3298 CALL timeset(routinen, handle)
3299
3300 logger => cp_get_default_logger()
3301 iw = cp_logger_get_default_io_unit(logger)
3302 ionode = para_env%is_source()
3303
3304 ALLOCATE (eri_aa(active_space_env%nmo_active**4))
3305 CALL eri_to_array(active_space_env%eri, eri_aa, active_space_env%active_orbitals, 1, 1)
3306 IF (active_space_env%nspins == 2) THEN
3307 ALLOCATE (eri_ab(active_space_env%nmo_active**4))
3308 CALL eri_to_array(active_space_env%eri, eri_ab, active_space_env%active_orbitals, 1, 2)
3309 ALLOCATE (eri_bb(active_space_env%nmo_active**4))
3310 CALL eri_to_array(active_space_env%eri, eri_bb, active_space_env%active_orbitals, 2, 2)
3311 ! get the overlap_ab matrix into Fortran array
3312 ALLOCATE (s_ab(active_space_env%nmo_active**2))
3313 associate(act_indices_a => active_space_env%active_orbitals(:, 1), &
3314 act_indices_b => active_space_env%active_orbitals(:, 2))
3315 CALL subspace_matrix_to_array(active_space_env%sab_sub(1), s_ab, act_indices_a, act_indices_b)
3316 END associate
3317 END IF
3318
3319 ! ask the status of the client
3320 IF (ionode) CALL writebuffer(client_fd, "STATUS ", header_len)
3321 DO
3322 header = ""
3323 CALL para_env%sync()
3324 IF (ionode) THEN
3325 ! IF (iw > 0) WRITE(iw, *) "@SERVER: Waiting for messages..."
3326 CALL readbuffer(client_fd, header, header_len)
3327 END IF
3328 CALL para_env%bcast(header, para_env%source)
3329
3330 ! IF (iw > 0) WRITE(iw, *) "@SERVER: Message from client: ", TRIM(header)
3331
3332 IF (trim(header) == "READY") THEN
3333 ! if the client is ready, send the data
3334 CALL para_env%sync()
3335 IF (ionode) THEN
3336 CALL writebuffer(client_fd, "TWOBODY ", header_len)
3337 CALL writebuffer(client_fd, active_space_env%nspins)
3338 CALL writebuffer(client_fd, active_space_env%nmo_active)
3339 CALL writebuffer(client_fd, active_space_env%nelec_active)
3340 CALL writebuffer(client_fd, active_space_env%multiplicity)
3341 ! send the alpha component
3342 CALL writebuffer(client_fd, eri_aa, SIZE(eri_aa))
3343 ! send the beta part for unrestricted calculations
3344 IF (active_space_env%nspins == 2) THEN
3345 CALL writebuffer(client_fd, eri_ab, SIZE(eri_ab))
3346 CALL writebuffer(client_fd, eri_bb, SIZE(eri_bb))
3347 CALL writebuffer(client_fd, s_ab, SIZE(s_ab))
3348 END IF
3349 END IF
3350 ELSE IF (trim(header) == "RECEIVED") THEN
3351 EXIT
3352 END IF
3353 END DO
3354
3355 DEALLOCATE (eri_aa)
3356 IF (active_space_env%nspins == 2) THEN
3357 DEALLOCATE (eri_ab)
3358 DEALLOCATE (eri_bb)
3359 DEALLOCATE (s_ab)
3360 END IF
3361
3362 CALL para_env%sync()
3363
3364 CALL timestop(handle)
3365
3366 END SUBROUTINE send_eri_to_client
3367
3368! **************************************************************************************************
3369!> \brief Sends the one-electron embedding potential and the inactive energy to the client
3370!> \param client_fd the client file descriptor
3371!> \param active_space_env active space environment
3372!> \param para_env parallel environment
3373! **************************************************************************************************
3374 SUBROUTINE send_fock_to_client(client_fd, active_space_env, para_env)
3375 INTEGER, INTENT(IN) :: client_fd
3376 TYPE(active_space_type), INTENT(IN), POINTER :: active_space_env
3377 TYPE(mp_para_env_type), INTENT(IN), POINTER :: para_env
3378
3379 CHARACTER(len=*), PARAMETER :: routinen = 'send_fock_to_client'
3380 INTEGER, PARAMETER :: header_len = 12
3381
3382 CHARACTER(len=default_string_length) :: header
3383 INTEGER :: handle, iw
3384 LOGICAL :: debug, ionode
3385 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: fock_a, fock_b, p_act_mo_a, p_act_mo_b
3386 TYPE(cp_logger_type), POINTER :: logger
3387
3388 CALL timeset(routinen, handle)
3389
3390 ! Set to .TRUE. to activate debug output
3391 debug = .false.
3392
3393 logger => cp_get_default_logger()
3394 iw = cp_logger_get_default_io_unit(logger)
3395 ionode = para_env%is_source()
3396
3397 ALLOCATE (p_act_mo_a(active_space_env%nmo_active**2))
3398 ALLOCATE (fock_a(active_space_env%nmo_active**2))
3399 IF (active_space_env%nspins == 2) THEN
3400 ALLOCATE (p_act_mo_b(active_space_env%nmo_active**2))
3401 ALLOCATE (fock_b(active_space_env%nmo_active**2))
3402 END IF
3403
3404 ! get the fock matrix into Fortran arrays
3405 associate(act_indices => active_space_env%active_orbitals(:, 1))
3406 CALL subspace_matrix_to_array(active_space_env%fock_sub(1), fock_a, act_indices, act_indices)
3407 END associate
3408
3409 IF (active_space_env%nspins == 2) THEN
3410 associate(act_indices => active_space_env%active_orbitals(:, 2))
3411 CALL subspace_matrix_to_array(active_space_env%fock_sub(2), fock_b, act_indices, act_indices)
3412 END associate
3413 END IF
3414
3415 ! ask the status of the client
3416 IF (ionode) CALL writebuffer(client_fd, "STATUS ", header_len)
3417 DO
3418 header = ""
3419
3420 CALL para_env%sync()
3421 IF (ionode) THEN
3422 IF (debug .AND. iw > 0) WRITE (iw, *) "@SERVER: Waiting for messages..."
3423 CALL readbuffer(client_fd, header, header_len)
3424 END IF
3425 CALL para_env%bcast(header, para_env%source)
3426
3427 IF (debug .AND. iw > 0) WRITE (iw, *) "@SERVER: Message from client: ", trim(header)
3428
3429 IF (trim(header) == "READY") THEN
3430 ! if the client is ready, send the data
3431 CALL para_env%sync()
3432 IF (ionode) THEN
3433 CALL writebuffer(client_fd, "ONEBODY ", header_len)
3434 CALL writebuffer(client_fd, active_space_env%energy_inactive)
3435 ! send the alpha component
3436 CALL writebuffer(client_fd, fock_a, SIZE(fock_a))
3437 ! send the beta part for unrestricted calculations
3438 IF (active_space_env%nspins == 2) THEN
3439 CALL writebuffer(client_fd, fock_b, SIZE(fock_b))
3440 END IF
3441 END IF
3442
3443 ELSE IF (trim(header) == "HAVEDATA") THEN
3444 ! qiskit has data to transfer, let them know we want it and wait for it
3445 CALL para_env%sync()
3446 IF (ionode) THEN
3447 IF (debug .AND. iw > 0) WRITE (iw, *) "@SERVER: Qiskit has data to transfer"
3448 CALL writebuffer(client_fd, "GETDENSITY ", header_len)
3449
3450 ! read the active energy and density
3451 CALL readbuffer(client_fd, active_space_env%energy_active)
3452 CALL readbuffer(client_fd, p_act_mo_a, SIZE(p_act_mo_a))
3453 IF (active_space_env%nspins == 2) THEN
3454 CALL readbuffer(client_fd, p_act_mo_b, SIZE(p_act_mo_b))
3455 END IF
3456 END IF
3457
3458 ! broadcast the data to all processors
3459 CALL para_env%bcast(active_space_env%energy_active, para_env%source)
3460 CALL para_env%bcast(p_act_mo_a, para_env%source)
3461 IF (active_space_env%nspins == 2) THEN
3462 CALL para_env%bcast(p_act_mo_b, para_env%source)
3463 END IF
3464
3465 ! update total and reference energies in active space enviornment
3466 active_space_env%energy_total = active_space_env%energy_inactive + active_space_env%energy_active
3467
3468 ! update the active density matrix in the active space environment
3469 CALL update_active_density(p_act_mo_a, active_space_env, 1)
3470 IF (active_space_env%nspins == 2) THEN
3471 CALL update_active_density(p_act_mo_b, active_space_env, 2)
3472 END IF
3473
3474 ! the non-iterative part is done, we can continue
3475 EXIT
3476 END IF
3477
3478 END DO
3479
3480 DEALLOCATE (p_act_mo_a)
3481 DEALLOCATE (fock_a)
3482 IF (active_space_env%nspins == 2) THEN
3483 DEALLOCATE (p_act_mo_b)
3484 DEALLOCATE (fock_b)
3485 END IF
3486
3487 CALL para_env%sync()
3488
3489 CALL timestop(handle)
3490
3491 END SUBROUTINE send_fock_to_client
3492#endif
3493
3494END MODULE qs_active_space_methods
Types and set/get functions for auxiliary density matrix methods.
Definition admm_types.F:15
subroutine, public get_admm_env(admm_env, mo_derivs_aux_fit, mos_aux_fit, sab_aux_fit, sab_aux_fit_asymm, sab_aux_fit_vs_orb, matrix_s_aux_fit, matrix_s_aux_fit_kp, matrix_s_aux_fit_vs_orb, matrix_s_aux_fit_vs_orb_kp, task_list_aux_fit, matrix_ks_aux_fit, matrix_ks_aux_fit_kp, matrix_ks_aux_fit_im, matrix_ks_aux_fit_dft, matrix_ks_aux_fit_hfx, matrix_ks_aux_fit_dft_kp, matrix_ks_aux_fit_hfx_kp, rho_aux_fit, rho_aux_fit_buffer, admm_dm)
Get routine for the ADMM env.
Definition admm_types.F:593
subroutine, public admm_env_release(admm_env)
releases the ADMM environment, cleans up all types
Definition admm_types.F:426
Define the atomic kind types and their sub types.
pure real(dp) function, public srules(z, ne, n, l)
...
subroutine, public deallocate_sto_basis_set(sto_basis_set)
...
subroutine, public allocate_sto_basis_set(sto_basis_set)
...
subroutine, public create_gto_from_sto_basis(sto_basis_set, gto_basis_set, ngauss, ortho)
...
subroutine, public set_sto_basis_set(sto_basis_set, name, nshell, symbol, nq, lq, zet)
...
subroutine, public init_orb_basis_set(gto_basis_set)
Initialise a Gaussian-type orbital (GTO) basis set data set.
Handles all functions related to the CELL.
subroutine, public write_cell_low(cell, unit_str, output_unit, label)
Write the cell parameters to the output unit.
subroutine, public set_cell_param(cell, cell_length, cell_angle, periodic, do_init_cell)
Sets the cell using the internal parameters (a,b,c) (alpha,beta,gamma) using the convention: a parall...
subroutine, public init_cell(cell, hmat, periodic)
Initialise/readjust a simulation cell after hmat has been changed.
Handles all functions related to the CELL.
Definition cell_types.F:15
integer, parameter, public use_perd_xyz
Definition cell_types.F:42
integer, parameter, public use_perd_none
Definition cell_types.F:42
methods related to the blacs parallel environment
integer, parameter, public blacs_grid_square
subroutine, public cp_blacs_env_release(blacs_env)
releases the given blacs_env
subroutine, public cp_blacs_env_create(blacs_env, para_env, blacs_grid_layout, blacs_repeatable, row_major, grid_2d)
allocates and initializes a type that represent a blacs context
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
subroutine, public dbcsr_iterator_next_block(iterator, row, column, block, block_number_argument_has_been_removed, row_size, col_size, row_offset, col_offset)
...
logical function, public dbcsr_iterator_blocks_left(iterator)
...
subroutine, public dbcsr_iterator_stop(iterator)
...
subroutine, public dbcsr_copy(matrix_b, matrix_a, name, keep_sparsity, keep_imaginary)
...
subroutine, public dbcsr_multiply(transa, transb, alpha, matrix_a, matrix_b, beta, matrix_c, first_row, last_row, first_column, last_column, first_k, last_k, retain_sparsity, filter_eps, flop)
...
subroutine, public dbcsr_get_info(matrix, nblkrows_total, nblkcols_total, nfullrows_total, nfullcols_total, nblkrows_local, nblkcols_local, nfullrows_local, nfullcols_local, my_prow, my_pcol, local_rows, local_cols, proc_row_dist, proc_col_dist, row_blk_size, col_blk_size, row_blk_offset, col_blk_offset, distribution, name, matrix_type, group)
...
real(kind=dp) function, public dbcsr_get_occupation(matrix)
...
subroutine, public dbcsr_iterator_start(iterator, matrix, shared, dynamic, dynamic_byrows)
...
subroutine, public dbcsr_set(matrix, alpha)
...
subroutine, public dbcsr_release(matrix)
...
DBCSR operations in CP2K.
subroutine, public cp_dbcsr_sm_fm_multiply(matrix, fm_in, fm_out, ncol, alpha, beta)
multiply a dbcsr with a fm matrix
subroutine, public copy_dbcsr_to_fm(matrix, fm)
Copy a DBCSR matrix to a BLACS matrix.
subroutine, public cp_dbcsr_plus_fm_fm_t(sparse_matrix, matrix_v, matrix_g, ncol, alpha, keep_sparsity, symmetry_mode)
performs the multiplication sparse_matrix+dense_mat*dens_mat^T if matrix_g is not explicitly given,...
subroutine, public cp_dbcsr_m_by_n_from_template(matrix, template, m, n, sym)
Utility function to create an arbitrary shaped dbcsr matrix with the same processor grid as the templ...
DBCSR output in CP2K.
subroutine, public cp_dbcsr_write_sparse_matrix(sparse_matrix, before, after, qs_env, para_env, first_row, last_row, first_col, last_col, scale, output_unit, omit_headers)
...
Utility routines to open and close files. Tracking of preconnections.
Definition cp_files.F:16
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
Definition cp_files.F:311
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
Definition cp_files.F:122
logical function, public file_exists(file_name)
Checks if file exists, considering also the file discovery mechanism.
Definition cp_files.F:504
Basic linear algebra operations for full matrices.
subroutine, public cp_fm_column_scale(matrixa, scaling)
scales column i of matrix a with scaling(i)
represent the structure of a full matrix
subroutine, public cp_fm_struct_create(fmstruct, para_env, context, nrow_global, ncol_global, nrow_block, ncol_block, descriptor, first_p_pos, local_leading_dimension, template_fmstruct, square_blocks, force_block)
allocates and initializes a full matrix structure
subroutine, public cp_fm_struct_release(fmstruct)
releases a full matrix structure
represent a full matrix distributed on many processors
Definition cp_fm_types.F:15
subroutine, public cp_fm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, nrow_locals, ncol_locals, matrix_struct, para_env)
returns all kind of information about the full matrix
subroutine, public cp_fm_create(matrix, matrix_struct, name, use_sp, nrow, ncol, set_zero)
creates a new full matrix with the given structure
subroutine, public cp_fm_get_element(matrix, irow_global, icol_global, alpha, local)
returns an element of a fm this value is valid on every cpu using this call is expensive
subroutine, public cp_fm_set_all(matrix, alpha, beta)
set all elements of a matrix to the same value, and optionally the diagonal to a different one
subroutine, public cp_fm_set_element(matrix, irow_global, icol_global, alpha)
sets an element of a matrix
subroutine, public cp_fm_init_random(matrix, ncol, start_col)
fills a matrix with random numbers
subroutine, public cp_fm_write_formatted(fm, unit, header, value_format)
Write out a full matrix in plain text.
various routines to log and control the output. The idea is that decisions about where to log should ...
integer function, public cp_logger_get_default_io_unit(logger)
returns the unit nr for the ionode (-1 on all other processors) skips as well checks if the procs cal...
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
integer, parameter, public debug_print_level
integer function, public cp_print_key_unit_nr(logger, basis_section, print_key_path, extension, middle_name, local, log_filename, ignore_should_output, file_form, file_position, file_action, file_status, do_backup, on_file, is_new_file, mpi_io, fout)
...
integer, parameter, public low_print_level
integer, parameter, public medium_print_level
subroutine, public cp_print_key_finished_output(unit_nr, logger, basis_section, print_key_path, local, ignore_should_output, on_file, mpi_io)
should be called after you finish working with a unit obtained with cp_print_key_unit_nr,...
integer, parameter, public cp_p_file
integer, parameter, public high_print_level
integer function, public cp_print_key_should_output(iteration_info, basis_section, print_key_path, used_print_key, first_time)
returns what should be done with the given property if btest(res,cp_p_store) then the property should...
integer, parameter, public silent_print_level
A wrapper around pw_to_cube() which accepts particle_list_type.
subroutine, public cp_pw_to_cube(pw, unit_nr, title, particles, zeff, stride, max_file_size_mb, zero_tails, silent, mpi_io)
...
Module to compute the error function of a complex argument.
Definition erf_complex.F:50
elemental complex(kind=dp) function, public erfz_fast(z)
Computes the error function of a complex argument using the Poppe and Wijers algorithm.
Types to describe group distributions.
Types and set/get functions for HFX.
Definition hfx_types.F:15
subroutine, public hfx_create(x_data, para_env, hfx_section, atomic_kind_set, qs_kind_set, particle_set, dft_control, cell, orb_basis, ri_basis, nelectron_total, nkp_grid)
This routine allocates and initializes all types in hfx_data
Definition hfx_types.F:596
subroutine, public hfx_release(x_data)
This routine deallocates all data structures
Definition hfx_types.F:1911
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public eri_operator_erf
integer, parameter, public qiskit_solver
integer, parameter, public no_solver
integer, parameter, public wannier_projection
integer, parameter, public mao_projection
integer, parameter, public eri_method_full_gpw
integer, parameter, public casci_canonical
integer, parameter, public manual_selection
integer, parameter, public eri_operator_gaussian
integer, parameter, public high_spin_roks
integer, parameter, public eri_method_gpw_ht
integer, parameter, public eri_operator_erfc
integer, parameter, public eri_poisson_mt
integer, parameter, public eri_poisson_analytic
integer, parameter, public eri_operator_trunc
integer, parameter, public eri_poisson_periodic
integer, parameter, public eri_operator_coulomb
integer, parameter, public eri_operator_yukawa
integer, parameter, public eri_operator_lr_trunc
objects that represent the structure of input sections and the data contained in an input section
subroutine, public section_vals_val_set(section_vals, keyword_name, i_rep_section, i_rep_val, val, l_val, i_val, r_val, c_val, l_vals_ptr, i_vals_ptr, r_vals_ptr, c_vals_ptr)
sets the requested value
recursive type(section_vals_type) function, pointer, public section_vals_get_subs_vals(section_vals, subsection_name, i_rep_section, can_return_null)
returns the values of the requested subsection
subroutine, public section_vals_get(section_vals, ref_count, n_repetition, n_subs_vals_rep, section, explicit)
returns various attributes about the section_vals
subroutine, public section_vals_set_subs_vals(section_vals, subsection_name, new_section_vals, i_rep_section)
replaces of the requested subsection with the one given
subroutine, public section_vals_val_get(section_vals, keyword_name, i_rep_section, i_rep_val, n_rep_val, val, l_val, i_val, r_val, c_val, l_vals, i_vals, r_vals, c_vals, explicit)
returns the requested value
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public int_8
Definition kinds.F:54
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_string_length
Definition kinds.F:57
integer, parameter, public default_path_length
Definition kinds.F:58
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
subroutine, public m_flush(lunit)
flushes units if the &GLOBAL flag is set accordingly
Definition machine.F:136
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Definition machine.F:153
Definition of mathematical constants and functions.
real(kind=dp), parameter, public pi
real(kind=dp), parameter, public rootpi
real(kind=dp), parameter, public fourpi
real(kind=dp), parameter, public twopi
Collection of simple mathematical functions and subroutines.
Definition mathlib.F:15
subroutine, public diamat_all(a, eigval, dac)
Diagonalize the symmetric n by n matrix a using the LAPACK library. Only the upper triangle of matrix...
Definition mathlib.F:381
Utility routines for the memory handling.
Interface to the message passing library MPI.
subroutine, public mp_para_env_release(para_env)
releases the para object (to be called when you don't want anymore the shared copy of this object)
Calls routines to get RI integrals and calculate total energies.
Definition mp2_gpw.F:14
subroutine, public grep_rows_in_subgroups(para_env, para_env_sub, mo_coeff, gd_array, c)
...
Definition mp2_gpw.F:758
subroutine, public build_dbcsr_from_rows(para_env_sub, mo_coeff_to_build, cread, mat_munu, gd_array, eps_filter)
Encapsulate the building of dbcsr_matrices mo_coeff_(v,o,all)
Definition mp2_gpw.F:886
subroutine, public create_mat_munu(mat_munu, qs_env, eps_grid, blacs_env_sub, do_ri_aux_basis, do_mixed_basis, group_size_prim, do_alloc_blocks_from_nbl, do_kpoints, sab_orb_sub, dbcsr_sym_type)
Encapsulate the building of dbcsr_matrix mat_munu.
Definition mp2_gpw.F:989
integer, parameter, public mt0d
Definition mt_util.F:33
basic linear algebra operations for full matrixes
represent a simple array based list of the given type
Define the data structure for the particle information.
Periodic Table related data definitions.
type(atom), dimension(0:nelem), public ptable
Definition of physical constants:
Definition physcon.F:68
real(kind=dp), parameter, public angstrom
Definition physcon.F:144
real(kind=dp), parameter, public bohr
Definition physcon.F:147
types of preconditioners
computes preconditioners, and implements methods to apply them currently used in qs_ot
methods of pw_env that have dependence on qs_env
subroutine, public pw_env_rebuild(pw_env, qs_env, external_para_env)
rebuilds the pw_env data (necessary if cell or cutoffs change)
subroutine, public pw_env_create(pw_env)
creates a pw_env, if qs_env is given calls pw_env_rebuild
container for various plainwaves related things
subroutine, public pw_env_release(pw_env, para_env)
releases the given pw_env (see doc/ReferenceCounting.html)
subroutine, public pw_env_get(pw_env, pw_pools, cube_info, gridlevel_info, auxbas_pw_pool, auxbas_grid, auxbas_rs_desc, auxbas_rs_grid, rs_descs, rs_grids, xc_pw_pool, vdw_pw_pool, poisson_env, interp_section)
returns the various attributes of the pw env
subroutine, public pw_gauss_damp(pw, omega)
Multiply all data points with a Gaussian damping factor Needed for longrange Coulomb potential V(\vec...
subroutine, public pw_compl_gauss_damp(pw, omega)
Multiply all data points with a Gaussian damping factor Needed for longrange Coulomb potential V(\vec...
functions related to the poisson solver on regular grids
integer, parameter, public pw_poisson_periodic
integer, parameter, public periodic3d
integer, parameter, public analytic0d
integer, parameter, public pw_poisson_analytic
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...
The module to read/write QCSchema HDF5 files for interfacing CP2K with other programs.
Definition qcschema.F:14
subroutine, public qcschema_env_release(qcschema_env)
Releases the allocated memory of a qcschema environment.
Definition qcschema.F:609
subroutine, public qcschema_env_create(qcschema_env, qs_env)
Create and initialize a qcschema object from a quickstep environment.
Definition qcschema.F:272
subroutine, public qcschema_to_hdf5(qcschema_env, filename)
Writes a qcschema object to an hdf5 file.
Definition qcschema.F:739
Determine active space Hamiltonian.
subroutine eri_fcidump_set(this, bra_start, ket_start)
Sets the starting indices of the bra and ket.
subroutine, public active_space_main(qs_env)
Main method for determining the active space Hamiltonian.
The types needed for the calculation of active space Hamiltonians.
subroutine, public csr_idx_from_combined(ij, n, i, j)
extracts indices i and j from combined index ij
integer function, public csr_idx_to_combined(i, j, n)
calculates combined index (ij)
integer function, dimension(2), public get_irange_csr(nindex, mp_group)
calculates index range for processor in group mp_group
subroutine, public create_active_space_type(active_space_env)
Creates an active space environment type, nullifying all quantities.
Contains utility routines for the active space module.
subroutine, public eri_to_array(eri_env, array, active_orbitals, spin1, spin2)
Copy the eri tensor for spins isp1 and isp2 to a standard 1D Fortran array.
subroutine, public subspace_matrix_to_array(source_matrix, target_array, row_index, col_index)
Copy a (square portion) of a cp_fm_type matrix to a standard 1D Fortran array.
Calculate the plane wave density by collocating the primitive Gaussian functions (pgf).
subroutine, public calculate_wavefunction(mo_vectors, ivector, rho, rho_gspace, atomic_kind_set, qs_kind_set, cell, dft_control, particle_set, pw_env, basis_type)
maps a given wavefunction on the grid
collects routines that calculate density matrices
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, mimic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, sab_cneo, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, xcint_weights, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, rhoz_cneo_set, ecoul_1c, rho0_s_rs, rho0_s_gs, rhoz_cneo_s_rs, rhoz_cneo_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs, do_rixs, tb_tblite)
Get the QUICKSTEP environment.
subroutine, public set_qs_env(qs_env, super_cell, mos, qmmm, qmmm_periodic, mimic, ewald_env, ewald_pw, mpools, rho_external, external_vxc, mask, scf_control, rel_control, qs_charges, ks_env, ks_qmmm_env, wf_history, scf_env, active_space, input, oce, rho_atom_set, rho0_atom_set, rho0_mpole, run_rtp, rtp, rhoz_set, rhoz_tot, ecoul_1c, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, efield, rhoz_cneo_set, linres_control, xas_env, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, ls_scf_env, do_transport, transport_env, lri_env, lri_density, exstate_env, ec_env, dispersion_env, harris_env, gcp_env, mp2_env, bs_env, kg_env, force, kpoints, wanniercentres, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs, do_rixs, tb_tblite)
Set the QUICKSTEP environment.
Integrate single or product functions over a potential on a RS grid.
Define the quickstep kind type and their sub types.
routines that build the Kohn-Sham matrix (i.e calculate the coulomb and xc parts
subroutine, public evaluate_core_matrix_traces(qs_env, rho_ao_ext)
Calculates the traces of the core matrices and the density matrix.
subroutine, public qs_ks_update_qs_env(qs_env, calculate_forces, just_energy, print_active)
updates the Kohn Sham matrix of the given qs_env (facility method)
subroutine, public qs_ks_build_kohn_sham_matrix(qs_env, calculate_forces, just_energy, print_active, ext_ks_matrix, ext_xc_section)
routine where the real calculations are made: the KS matrix is calculated
subroutine, public qs_ks_did_change(ks_env, s_mstruct_changed, rho_changed, potential_changed, full_reset)
tells that some of the things relevant to the ks calculation did change. has to be called when change...
subroutine, public set_ks_env(ks_env, v_hartree_rspace, s_mstruct_changed, rho_changed, exc_accint, potential_changed, forces_up_to_date, complex_ks, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, kinetic, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_ks_im_kp, vppl, xcint_weights, rho_core, rho_nlcc, rho_nlcc_g, vee, neighbor_list_id, kpoints, sab_orb, sab_all, sac_ae, sac_ppl, sac_lri, sap_ppnl, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_vdw, sab_scp, sab_almo, sab_kp, sab_kp_nosym, sab_cneo, task_list, task_list_soft, subsys, dft_control, dbcsr_dist, distribution_2d, pw_env, para_env, blacs_env)
...
Definition and initialisation of the mo data type.
Definition qs_mo_io.F:21
subroutine, public write_mo_set_to_output_unit(mo_set, qs_kind_set, particle_set, dft_section, before, kpoint, final_mos, spin, solver_method, rtp, cpart, sim_step, umo_set)
Write MO information to output file (eigenvalues, occupation numbers, coefficients)
Definition qs_mo_io.F:1011
collects routines that perform operations directly related to MOs
Definition and initialisation of the mo data type.
Definition qs_mo_types.F:22
subroutine, public allocate_mo_set(mo_set, nao, nmo, nelectron, n_el_f, maxocc, flexible_electron_count)
Allocates a mo set and partially initializes it (nao,nmo,nelectron, and flexible_electron_count are v...
subroutine, public get_mo_set(mo_set, maxocc, homo, lfomo, nao, nelectron, n_el_f, nmo, eigenvalues, occupation_numbers, mo_coeff, mo_coeff_b, uniform_occupation, kts, mu, flexible_electron_count)
Get the components of a MO set data structure.
subroutine, public init_mo_set(mo_set, fm_pool, fm_ref, fm_struct, name)
initializes an allocated mo_set. eigenvalues, mo_coeff, occupation_numbers are valid only after this ...
Define the neighbor list data types and the corresponding functionality.
subroutine, public release_neighbor_list_sets(nlists)
releases an array of neighbor_list_sets
an eigen-space solver for the generalised symmetric eigenvalue problem for sparse matrices,...
subroutine, public ot_eigensolver(matrix_h, matrix_s, matrix_orthogonal_space_fm, matrix_c_fm, preconditioner, eps_gradient, iter_max, size_ortho_space, silent, ot_settings)
...
methods of the rho structure (defined in qs_rho_types)
subroutine, public qs_rho_update_rho(rho_struct, qs_env, rho_xc_external, local_rho_set, task_list_external, task_list_external_soft, pw_env_external, para_env_external)
updates rho_r and rho_g to the rhorho_ao. if use_kinetic_energy_density also computes tau_r and tau_g...
superstucture that hold various representations of the density and keeps track of which ones are vali...
subroutine, public qs_rho_get(rho_struct, rho_ao, rho_ao_im, rho_ao_kp, rho_ao_im_kp, rho_r, drho_r, rho_g, drho_g, tau_r, tau_g, rho_r_valid, drho_r_valid, rho_g_valid, drho_g_valid, tau_r_valid, tau_g_valid, tot_rho_r, tot_rho_g, rho_r_sccs, soft_valid, complex_rho_ao)
returns info about the density described by this object. If some representation is not available an e...
Utility routines for qs_scf.
subroutine, public qs_scf_compute_properties(qs_env, wf_type, do_mp2)
computes properties for a given hamilonian using the current wfn
types that represent a quickstep subsys
subroutine, public qs_subsys_get(subsys, atomic_kinds, atomic_kind_set, particles, particle_set, local_particles, molecules, molecule_set, molecule_kinds, molecule_kind_set, local_molecules, para_env, colvar_p, shell_particles, core_particles, gci, multipoles, natom, nparticle, ncore, nshell, nkind, atprop, virial, results, cell, cell_ref, use_ref_cell, energy, force, qs_kind_set, cp_subsys, nelectron_total, nelectron_spin)
...
parameters that control an scf iteration
Implements UNIX and INET sockets.
generate the tasks lists used by collocate and integrate routines
subroutine, public generate_qs_task_list(ks_env, task_list, basis_type, reorder_rs_grid_ranks, skip_load_balance_distributed, pw_env_external, sab_orb_external)
...
types for task lists
subroutine, public deallocate_task_list(task_list)
deallocates the components and the object itself
subroutine, public allocate_task_list(task_list)
allocates and initialised the components of the task_list_type
All kind of helpful little routines.
Definition util.F:14
pure integer function, dimension(2), public get_limit(m, n, me)
divide m entries into n parts, return size of part me
Definition util.F:333
void open_bind_socket(int *psockfd, int *inet, int *port, char *host)
Opens and binds a socket.
Definition sockets.c:137
void writebuffer(int *psockfd, char *data, int *plen)
Writes to a socket.
Definition sockets.c:201
void accept_socket(int *psockfd, int *pclientfd)
Listens to a socket.
Definition sockets.c:256
void close_socket(int *psockfd)
Closes a socket.
Definition sockets.c:267
void listen_socket(int *psockfd, int *backlog)
Listens to a socket.
Definition sockets.c:243
void readbuffer(int *psockfd, char *data, int *plen)
Reads from a socket.
Definition sockets.c:219
void remove_socket_file(char *host)
Removes a socket file.
Definition sockets.c:273
stores some data used in wavefunction fitting
Definition admm_types.F:120
Provides all information about an atomic kind.
Type defining parameters related to the simulation cell.
Definition cell_types.F:60
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
keeps the information about the structure of a full matrix
represent a full matrix
type of a logger, at the moment it contains just a print level starting at which level it should be l...
stores all the informations relevant to an mpi environment
contained for different pw related things
contains all the informations needed by the fft based poisson solvers
environment for the poisson solver
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...
The full QCSchema output type. For more information refer to: https://molssi-qc-schema....
Definition qcschema.F:253
Abstract function object for the eri_type_eri_foreach method.
Provides all information about a quickstep kind.
calculation environment to calculate the ks matrix, holds all the needed vars. assumes that the core ...
keeps the density in various representations, keeping track of which ones are valid.