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