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