LCOV - code coverage report
Current view: top level - src - qs_scf_post_gpw.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:fd1133a) Lines: 87.9 % 1543 1356
Test Date: 2025-12-07 06:28:01 Functions: 100.0 % 23 23

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Does all kind of post scf calculations for GPW/GAPW
      10              : !> \par History
      11              : !>      Started as a copy from the relevant part of qs_scf
      12              : !>      Start to adapt for k-points [07.2015, JGH]
      13              : !> \author Joost VandeVondele (10.2003)
      14              : ! **************************************************************************************************
      15              : MODULE qs_scf_post_gpw
      16              :    USE admm_types,                      ONLY: admm_type
      17              :    USE admm_utils,                      ONLY: admm_correct_for_eigenvalues,&
      18              :                                               admm_uncorrect_for_eigenvalues
      19              :    USE ai_onecenter,                    ONLY: sg_overlap
      20              :    USE atom_kind_orbitals,              ONLY: calculate_atomic_density
      21              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      22              :                                               get_atomic_kind
      23              :    USE basis_set_types,                 ONLY: gto_basis_set_p_type,&
      24              :                                               gto_basis_set_type
      25              :    USE cell_types,                      ONLY: cell_type
      26              :    USE cp_array_utils,                  ONLY: cp_1d_r_p_type
      27              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      28              :    USE cp_control_types,                ONLY: dft_control_type
      29              :    USE cp_dbcsr_api,                    ONLY: dbcsr_add,&
      30              :                                               dbcsr_p_type,&
      31              :                                               dbcsr_type
      32              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      33              :                                               dbcsr_deallocate_matrix_set
      34              :    USE cp_dbcsr_output,                 ONLY: cp_dbcsr_write_sparse_matrix
      35              :    USE cp_ddapc_util,                   ONLY: get_ddapc
      36              :    USE cp_fm_diag,                      ONLY: choose_eigv_solver
      37              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      38              :                                               cp_fm_struct_release,&
      39              :                                               cp_fm_struct_type
      40              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      41              :                                               cp_fm_get_info,&
      42              :                                               cp_fm_init_random,&
      43              :                                               cp_fm_release,&
      44              :                                               cp_fm_to_fm,&
      45              :                                               cp_fm_type
      46              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      47              :                                               cp_logger_get_default_io_unit,&
      48              :                                               cp_logger_type,&
      49              :                                               cp_to_string
      50              :    USE cp_output_handling,              ONLY: cp_p_file,&
      51              :                                               cp_print_key_finished_output,&
      52              :                                               cp_print_key_should_output,&
      53              :                                               cp_print_key_unit_nr
      54              :    USE cp_realspace_grid_cube,          ONLY: cp_pw_to_cube
      55              :    USE dct,                             ONLY: pw_shrink
      56              :    USE ed_analysis,                     ONLY: edmf_analysis
      57              :    USE eeq_method,                      ONLY: eeq_print
      58              :    USE et_coupling_types,               ONLY: set_et_coupling_type
      59              :    USE hfx_ri,                          ONLY: print_ri_hfx
      60              :    USE hirshfeld_methods,               ONLY: comp_hirshfeld_charges,&
      61              :                                               comp_hirshfeld_i_charges,&
      62              :                                               create_shape_function,&
      63              :                                               save_hirshfeld_charges,&
      64              :                                               write_hirshfeld_charges
      65              :    USE hirshfeld_types,                 ONLY: create_hirshfeld_type,&
      66              :                                               hirshfeld_type,&
      67              :                                               release_hirshfeld_type,&
      68              :                                               set_hirshfeld_info
      69              :    USE iao_analysis,                    ONLY: iao_wfn_analysis
      70              :    USE iao_types,                       ONLY: iao_env_type,&
      71              :                                               iao_read_input
      72              :    USE input_constants,                 ONLY: &
      73              :         do_loc_both, do_loc_homo, do_loc_jacobi, do_loc_lumo, do_loc_mixed, do_loc_none, &
      74              :         ot_precond_full_all, radius_covalent, radius_user, ref_charge_atomic, ref_charge_mulliken
      75              :    USE input_section_types,             ONLY: section_get_ival,&
      76              :                                               section_get_ivals,&
      77              :                                               section_get_lval,&
      78              :                                               section_get_rval,&
      79              :                                               section_vals_get,&
      80              :                                               section_vals_get_subs_vals,&
      81              :                                               section_vals_type,&
      82              :                                               section_vals_val_get
      83              :    USE kinds,                           ONLY: default_path_length,&
      84              :                                               default_string_length,&
      85              :                                               dp
      86              :    USE kpoint_types,                    ONLY: kpoint_type
      87              :    USE mao_wfn_analysis,                ONLY: mao_analysis
      88              :    USE mathconstants,                   ONLY: pi
      89              :    USE memory_utilities,                ONLY: reallocate
      90              :    USE message_passing,                 ONLY: mp_para_env_type
      91              :    USE minbas_wfn_analysis,             ONLY: minbas_analysis
      92              :    USE molden_utils,                    ONLY: write_mos_molden
      93              :    USE molecule_types,                  ONLY: molecule_type
      94              :    USE mulliken,                        ONLY: mulliken_charges
      95              :    USE orbital_pointers,                ONLY: indso
      96              :    USE particle_list_types,             ONLY: particle_list_type
      97              :    USE particle_types,                  ONLY: particle_type
      98              :    USE physcon,                         ONLY: angstrom,&
      99              :                                               evolt
     100              :    USE population_analyses,             ONLY: lowdin_population_analysis,&
     101              :                                               mulliken_population_analysis
     102              :    USE preconditioner_types,            ONLY: preconditioner_type
     103              :    USE ps_implicit_types,               ONLY: MIXED_BC,&
     104              :                                               MIXED_PERIODIC_BC,&
     105              :                                               NEUMANN_BC,&
     106              :                                               PERIODIC_BC
     107              :    USE pw_env_types,                    ONLY: pw_env_get,&
     108              :                                               pw_env_type
     109              :    USE pw_grids,                        ONLY: get_pw_grid_info
     110              :    USE pw_methods,                      ONLY: pw_axpy,&
     111              :                                               pw_copy,&
     112              :                                               pw_derive,&
     113              :                                               pw_integrate_function,&
     114              :                                               pw_scale,&
     115              :                                               pw_transfer,&
     116              :                                               pw_zero
     117              :    USE pw_poisson_methods,              ONLY: pw_poisson_solve
     118              :    USE pw_poisson_types,                ONLY: pw_poisson_implicit,&
     119              :                                               pw_poisson_type
     120              :    USE pw_pool_types,                   ONLY: pw_pool_p_type,&
     121              :                                               pw_pool_type
     122              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
     123              :                                               pw_r3d_rs_type
     124              :    USE qs_chargemol,                    ONLY: write_wfx
     125              :    USE qs_collocate_density,            ONLY: calculate_rho_resp_all,&
     126              :                                               calculate_wavefunction
     127              :    USE qs_commutators,                  ONLY: build_com_hr_matrix
     128              :    USE qs_core_energies,                ONLY: calculate_ptrace
     129              :    USE qs_dos,                          ONLY: calculate_dos,&
     130              :                                               calculate_dos_kp
     131              :    USE qs_electric_field_gradient,      ONLY: qs_efg_calc
     132              :    USE qs_elf_methods,                  ONLY: qs_elf_calc
     133              :    USE qs_energy_types,                 ONLY: qs_energy_type
     134              :    USE qs_energy_window,                ONLY: energy_windows
     135              :    USE qs_environment_types,            ONLY: get_qs_env,&
     136              :                                               qs_environment_type,&
     137              :                                               set_qs_env
     138              :    USE qs_epr_hyp,                      ONLY: qs_epr_hyp_calc
     139              :    USE qs_grid_atom,                    ONLY: grid_atom_type
     140              :    USE qs_integral_utils,               ONLY: basis_set_list_setup
     141              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
     142              :                                               qs_kind_type
     143              :    USE qs_ks_methods,                   ONLY: calc_rho_tot_gspace,&
     144              :                                               qs_ks_update_qs_env
     145              :    USE qs_ks_types,                     ONLY: qs_ks_did_change
     146              :    USE qs_loc_dipole,                   ONLY: loc_dipole
     147              :    USE qs_loc_states,                   ONLY: get_localization_info
     148              :    USE qs_loc_types,                    ONLY: qs_loc_env_create,&
     149              :                                               qs_loc_env_release,&
     150              :                                               qs_loc_env_type
     151              :    USE qs_loc_utils,                    ONLY: loc_write_restart,&
     152              :                                               qs_loc_control_init,&
     153              :                                               qs_loc_env_init,&
     154              :                                               qs_loc_init,&
     155              :                                               retain_history
     156              :    USE qs_local_properties,             ONLY: qs_local_energy,&
     157              :                                               qs_local_stress
     158              :    USE qs_mo_io,                        ONLY: write_dm_binary_restart
     159              :    USE qs_mo_methods,                   ONLY: calculate_subspace_eigenvalues,&
     160              :                                               make_mo_eig
     161              :    USE qs_mo_occupation,                ONLY: set_mo_occupation
     162              :    USE qs_mo_types,                     ONLY: get_mo_set,&
     163              :                                               mo_set_type
     164              :    USE qs_moments,                      ONLY: qs_moment_berry_phase,&
     165              :                                               qs_moment_locop
     166              :    USE qs_neighbor_list_types,          ONLY: get_iterator_info,&
     167              :                                               get_neighbor_list_set_p,&
     168              :                                               neighbor_list_iterate,&
     169              :                                               neighbor_list_iterator_create,&
     170              :                                               neighbor_list_iterator_p_type,&
     171              :                                               neighbor_list_iterator_release,&
     172              :                                               neighbor_list_set_p_type
     173              :    USE qs_ot_eigensolver,               ONLY: ot_eigensolver
     174              :    USE qs_pdos,                         ONLY: calculate_projected_dos
     175              :    USE qs_resp,                         ONLY: resp_fit
     176              :    USE qs_rho0_types,                   ONLY: get_rho0_mpole,&
     177              :                                               mpole_rho_atom,&
     178              :                                               rho0_mpole_type
     179              :    USE qs_rho_atom_types,               ONLY: rho_atom_type
     180              :    USE qs_rho_methods,                  ONLY: qs_rho_update_rho
     181              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
     182              :                                               qs_rho_type
     183              :    USE qs_scf_csr_write,                ONLY: write_hcore_matrix_csr,&
     184              :                                               write_ks_matrix_csr,&
     185              :                                               write_p_matrix_csr,&
     186              :                                               write_s_matrix_csr
     187              :    USE qs_scf_output,                   ONLY: qs_scf_write_mos
     188              :    USE qs_scf_types,                    ONLY: ot_method_nr,&
     189              :                                               qs_scf_env_type
     190              :    USE qs_scf_wfn_mix,                  ONLY: wfn_mix
     191              :    USE qs_subsys_types,                 ONLY: qs_subsys_get,&
     192              :                                               qs_subsys_type
     193              :    USE qs_wannier90,                    ONLY: wannier90_interface
     194              :    USE s_square_methods,                ONLY: compute_s_square
     195              :    USE scf_control_types,               ONLY: scf_control_type
     196              :    USE stm_images,                      ONLY: th_stm_image
     197              :    USE transport,                       ONLY: qs_scf_post_transport
     198              :    USE trexio_utils,                    ONLY: write_trexio
     199              :    USE virial_types,                    ONLY: virial_type
     200              :    USE voronoi_interface,               ONLY: entry_voronoi_or_bqb
     201              :    USE xray_diffraction,                ONLY: calculate_rhotot_elec_gspace,&
     202              :                                               xray_diffraction_spectrum
     203              : #include "./base/base_uses.f90"
     204              : 
     205              :    IMPLICIT NONE
     206              :    PRIVATE
     207              : 
     208              :    ! Global parameters
     209              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_scf_post_gpw'
     210              :    PUBLIC :: scf_post_calculation_gpw, &
     211              :              qs_scf_post_moments, &
     212              :              write_mo_dependent_results, &
     213              :              write_mo_free_results
     214              : 
     215              :    PUBLIC :: make_lumo_gpw
     216              : 
     217              : ! **************************************************************************************************
     218              : 
     219              : CONTAINS
     220              : 
     221              : ! **************************************************************************************************
     222              : !> \brief collects possible post - scf calculations and prints info / computes properties.
     223              : !> \param qs_env the qs_env in which the qs_env lives
     224              : !> \param wf_type ...
     225              : !> \param do_mp2 ...
     226              : !> \par History
     227              : !>      02.2003 created [fawzi]
     228              : !>      10.2004 moved here from qs_scf [Joost VandeVondele]
     229              : !>              started splitting out different subroutines
     230              : !>      10.2015 added header for wave-function correlated methods [Vladimir Rybkin]
     231              : !> \author fawzi
     232              : !> \note
     233              : !>      this function changes mo_eigenvectors and mo_eigenvalues, depending on the print keys.
     234              : !>      In particular, MO_CUBES causes the MOs to be rotated to make them eigenstates of the KS
     235              : !>      matrix, and mo_eigenvalues is updated accordingly. This can, for unconverged wavefunctions,
     236              : !>      change afterwards slightly the forces (hence small numerical differences between MD
     237              : !>      with and without the debug print level). Ideally this should not happen...
     238              : ! **************************************************************************************************
     239        10053 :    SUBROUTINE scf_post_calculation_gpw(qs_env, wf_type, do_mp2)
     240              : 
     241              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     242              :       CHARACTER(6), OPTIONAL                             :: wf_type
     243              :       LOGICAL, OPTIONAL                                  :: do_mp2
     244              : 
     245              :       CHARACTER(len=*), PARAMETER :: routineN = 'scf_post_calculation_gpw'
     246              : 
     247              :       INTEGER                                            :: handle, homo, ispin, min_lumos, n_rep, &
     248              :                                                             nchk_nmoloc, nhomo, nlumo, nlumo_stm, &
     249              :                                                             nlumos, nmo, nspins, output_unit, &
     250              :                                                             unit_nr
     251        10053 :       INTEGER, DIMENSION(:, :, :), POINTER               :: marked_states
     252              :       LOGICAL :: check_write, compute_lumos, do_homo, do_kpoints, do_mixed, do_mo_cubes, do_stm, &
     253              :          do_wannier_cubes, has_homo, has_lumo, loc_explicit, loc_print_explicit, my_do_mp2, &
     254              :          my_localized_wfn, p_loc, p_loc_homo, p_loc_lumo, p_loc_mixed
     255              :       REAL(dp)                                           :: e_kin
     256              :       REAL(KIND=dp)                                      :: gap, homo_lumo(2, 2), total_zeff_corr
     257        10053 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mo_eigenvalues
     258              :       TYPE(admm_type), POINTER                           :: admm_env
     259        10053 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     260        10053 :       TYPE(cp_1d_r_p_type), DIMENSION(:), POINTER        :: mixed_evals, occupied_evals, &
     261        10053 :                                                             unoccupied_evals, unoccupied_evals_stm
     262        10053 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: mixed_orbs, occupied_orbs
     263              :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:), &
     264        10053 :          TARGET                                          :: homo_localized, lumo_localized, &
     265        10053 :                                                             mixed_localized
     266        10053 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: lumo_ptr, mo_loc_history, &
     267        10053 :                                                             unoccupied_orbs, unoccupied_orbs_stm
     268              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     269              :       TYPE(cp_logger_type), POINTER                      :: logger
     270        10053 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: ks_rmpv, matrix_p_mp2, matrix_s, &
     271        10053 :                                                             mo_derivs
     272        10053 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: kinetic_m, rho_ao
     273              :       TYPE(dft_control_type), POINTER                    :: dft_control
     274        10053 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     275        10053 :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
     276              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     277              :       TYPE(particle_list_type), POINTER                  :: particles
     278        10053 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     279              :       TYPE(pw_c1d_gs_type)                               :: wf_g
     280              :       TYPE(pw_env_type), POINTER                         :: pw_env
     281        10053 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
     282              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     283              :       TYPE(pw_r3d_rs_type)                               :: wf_r
     284        10053 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     285              :       TYPE(qs_loc_env_type), POINTER                     :: qs_loc_env_homo, qs_loc_env_lumo, &
     286              :                                                             qs_loc_env_mixed
     287              :       TYPE(qs_rho_type), POINTER                         :: rho
     288              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     289              :       TYPE(qs_subsys_type), POINTER                      :: subsys
     290              :       TYPE(scf_control_type), POINTER                    :: scf_control
     291              :       TYPE(section_vals_type), POINTER                   :: dft_section, input, loc_print_section, &
     292              :                                                             localize_section, print_key, &
     293              :                                                             stm_section
     294              : 
     295        10053 :       CALL timeset(routineN, handle)
     296              : 
     297        10053 :       logger => cp_get_default_logger()
     298        10053 :       output_unit = cp_logger_get_default_io_unit(logger)
     299              : 
     300              :       ! Print out the type of wavefunction to distinguish between SCF and post-SCF
     301        10053 :       my_do_mp2 = .FALSE.
     302        10053 :       IF (PRESENT(do_mp2)) my_do_mp2 = do_mp2
     303        10053 :       IF (PRESENT(wf_type)) THEN
     304          322 :          IF (output_unit > 0) THEN
     305          161 :             WRITE (UNIT=output_unit, FMT='(/,(T1,A))') REPEAT("-", 40)
     306          161 :             WRITE (UNIT=output_unit, FMT='(/,(T3,A,T19,A,T25,A))') "Properties from ", wf_type, " density"
     307          161 :             WRITE (UNIT=output_unit, FMT='(/,(T1,A))') REPEAT("-", 40)
     308              :          END IF
     309              :       END IF
     310              : 
     311              :       ! Writes the data that is already available in qs_env
     312        10053 :       CALL get_qs_env(qs_env, scf_env=scf_env)
     313              : 
     314        10053 :       my_localized_wfn = .FALSE.
     315        10053 :       NULLIFY (admm_env, dft_control, pw_env, auxbas_pw_pool, pw_pools, mos, rho, &
     316        10053 :                mo_coeff, ks_rmpv, matrix_s, qs_loc_env_homo, qs_loc_env_lumo, scf_control, &
     317        10053 :                unoccupied_orbs, mo_eigenvalues, unoccupied_evals, &
     318        10053 :                unoccupied_evals_stm, molecule_set, mo_derivs, &
     319        10053 :                subsys, particles, input, print_key, kinetic_m, marked_states, &
     320        10053 :                mixed_evals, qs_loc_env_mixed)
     321        10053 :       NULLIFY (lumo_ptr, rho_ao)
     322              : 
     323        10053 :       has_homo = .FALSE.
     324        10053 :       has_lumo = .FALSE.
     325        10053 :       p_loc = .FALSE.
     326        10053 :       p_loc_homo = .FALSE.
     327        10053 :       p_loc_lumo = .FALSE.
     328        10053 :       p_loc_mixed = .FALSE.
     329              : 
     330        10053 :       CPASSERT(ASSOCIATED(scf_env))
     331        10053 :       CPASSERT(ASSOCIATED(qs_env))
     332              :       ! Here we start with data that needs a postprocessing...
     333              :       CALL get_qs_env(qs_env, &
     334              :                       dft_control=dft_control, &
     335              :                       molecule_set=molecule_set, &
     336              :                       scf_control=scf_control, &
     337              :                       do_kpoints=do_kpoints, &
     338              :                       input=input, &
     339              :                       subsys=subsys, &
     340              :                       rho=rho, &
     341              :                       pw_env=pw_env, &
     342              :                       particle_set=particle_set, &
     343              :                       atomic_kind_set=atomic_kind_set, &
     344        10053 :                       qs_kind_set=qs_kind_set)
     345        10053 :       CALL qs_subsys_get(subsys, particles=particles)
     346              : 
     347        10053 :       CALL qs_rho_get(rho, rho_ao_kp=rho_ao)
     348              : 
     349        10053 :       IF (my_do_mp2) THEN
     350              :          ! Get the HF+MP2 density
     351          322 :          CALL get_qs_env(qs_env, matrix_p_mp2=matrix_p_mp2)
     352          742 :          DO ispin = 1, dft_control%nspins
     353          742 :             CALL dbcsr_add(rho_ao(ispin, 1)%matrix, matrix_p_mp2(ispin)%matrix, 1.0_dp, 1.0_dp)
     354              :          END DO
     355          322 :          CALL qs_rho_update_rho(rho, qs_env=qs_env)
     356          322 :          CALL qs_ks_did_change(qs_env%ks_env, rho_changed=.TRUE.)
     357              :          ! In MP2 case update the Hartree potential
     358          322 :          CALL update_hartree_with_mp2(rho, qs_env)
     359              :       END IF
     360              : 
     361        10053 :       CALL write_available_results(qs_env, scf_env)
     362              : 
     363              :       !    **** the kinetic energy
     364        10053 :       IF (cp_print_key_should_output(logger%iter_info, input, &
     365              :                                      "DFT%PRINT%KINETIC_ENERGY") /= 0) THEN
     366           80 :          CALL get_qs_env(qs_env, kinetic_kp=kinetic_m)
     367           80 :          CPASSERT(ASSOCIATED(kinetic_m))
     368           80 :          CPASSERT(ASSOCIATED(kinetic_m(1, 1)%matrix))
     369           80 :          CALL calculate_ptrace(kinetic_m, rho_ao, e_kin, dft_control%nspins)
     370              :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%KINETIC_ENERGY", &
     371           80 :                                         extension=".Log")
     372           80 :          IF (unit_nr > 0) THEN
     373           40 :             WRITE (unit_nr, '(T3,A,T55,F25.14)') "Electronic kinetic energy:", e_kin
     374              :          END IF
     375              :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
     376           80 :                                            "DFT%PRINT%KINETIC_ENERGY")
     377              :       END IF
     378              : 
     379              :       ! Atomic Charges that require further computation
     380        10053 :       CALL qs_scf_post_charges(input, logger, qs_env)
     381              : 
     382              :       ! Moments of charge distribution
     383        10053 :       CALL qs_scf_post_moments(input, logger, qs_env, output_unit)
     384              : 
     385              :       ! Determine if we need to computer properties using the localized centers
     386        10053 :       dft_section => section_vals_get_subs_vals(input, "DFT")
     387        10053 :       localize_section => section_vals_get_subs_vals(dft_section, "LOCALIZE")
     388        10053 :       loc_print_section => section_vals_get_subs_vals(localize_section, "PRINT")
     389        10053 :       CALL section_vals_get(localize_section, explicit=loc_explicit)
     390        10053 :       CALL section_vals_get(loc_print_section, explicit=loc_print_explicit)
     391              : 
     392              :       ! Print_keys controlled by localization
     393        10053 :       IF (loc_print_explicit) THEN
     394           96 :          print_key => section_vals_get_subs_vals(loc_print_section, "MOLECULAR_DIPOLES")
     395           96 :          p_loc = BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     396           96 :          print_key => section_vals_get_subs_vals(loc_print_section, "TOTAL_DIPOLE")
     397           96 :          p_loc = p_loc .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     398           96 :          print_key => section_vals_get_subs_vals(loc_print_section, "WANNIER_CENTERS")
     399           96 :          p_loc = p_loc .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     400           96 :          print_key => section_vals_get_subs_vals(loc_print_section, "WANNIER_SPREADS")
     401           96 :          p_loc = p_loc .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     402           96 :          print_key => section_vals_get_subs_vals(loc_print_section, "WANNIER_CUBES")
     403           96 :          p_loc = p_loc .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     404           96 :          print_key => section_vals_get_subs_vals(loc_print_section, "MOLECULAR_STATES")
     405           96 :          p_loc = p_loc .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     406           96 :          print_key => section_vals_get_subs_vals(loc_print_section, "MOLECULAR_MOMENTS")
     407           96 :          p_loc = p_loc .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     408           96 :          print_key => section_vals_get_subs_vals(loc_print_section, "WANNIER_STATES")
     409           96 :          p_loc = p_loc .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     410              :       ELSE
     411              :          p_loc = .FALSE.
     412              :       END IF
     413        10053 :       IF (loc_explicit) THEN
     414              :          p_loc_homo = (section_get_ival(localize_section, "STATES") == do_loc_homo .OR. &
     415           96 :                        section_get_ival(localize_section, "STATES") == do_loc_both) .AND. p_loc
     416              :          p_loc_lumo = (section_get_ival(localize_section, "STATES") == do_loc_lumo .OR. &
     417           96 :                        section_get_ival(localize_section, "STATES") == do_loc_both) .AND. p_loc
     418           96 :          p_loc_mixed = (section_get_ival(localize_section, "STATES") == do_loc_mixed) .AND. p_loc
     419           96 :          CALL section_vals_val_get(localize_section, "LIST_UNOCCUPIED", n_rep_val=n_rep)
     420              :       ELSE
     421         9957 :          p_loc_homo = .FALSE.
     422         9957 :          p_loc_lumo = .FALSE.
     423         9957 :          p_loc_mixed = .FALSE.
     424         9957 :          n_rep = 0
     425              :       END IF
     426              : 
     427        10053 :       IF (n_rep == 0 .AND. p_loc_lumo) THEN
     428              :          CALL cp_abort(__LOCATION__, "No LIST_UNOCCUPIED was specified, "// &
     429            0 :                        "therefore localization of unoccupied states will be skipped!")
     430            0 :          p_loc_lumo = .FALSE.
     431              :       END IF
     432              : 
     433              :       ! Control for STM
     434        10053 :       stm_section => section_vals_get_subs_vals(input, "DFT%PRINT%STM")
     435        10053 :       CALL section_vals_get(stm_section, explicit=do_stm)
     436        10053 :       nlumo_stm = 0
     437        10053 :       IF (do_stm) nlumo_stm = section_get_ival(stm_section, "NLUMO")
     438              : 
     439              :       ! check for CUBES (MOs and WANNIERS)
     440              :       do_mo_cubes = BTEST(cp_print_key_should_output(logger%iter_info, dft_section, "PRINT%MO_CUBES") &
     441        10053 :                           , cp_p_file)
     442        10053 :       IF (loc_print_explicit) THEN
     443              :          do_wannier_cubes = BTEST(cp_print_key_should_output(logger%iter_info, loc_print_section, &
     444           96 :                                                              "WANNIER_CUBES"), cp_p_file)
     445              :       ELSE
     446              :          do_wannier_cubes = .FALSE.
     447              :       END IF
     448        10053 :       nlumo = section_get_ival(dft_section, "PRINT%MO_CUBES%NLUMO")
     449        10053 :       nhomo = section_get_ival(dft_section, "PRINT%MO_CUBES%NHOMO")
     450              : 
     451              :       ! Setup the grids needed to compute a wavefunction given a vector..
     452        10053 :       IF (((do_mo_cubes .OR. do_wannier_cubes) .AND. (nlumo /= 0 .OR. nhomo /= 0)) .OR. p_loc) THEN
     453              :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
     454          208 :                          pw_pools=pw_pools)
     455          208 :          CALL auxbas_pw_pool%create_pw(wf_r)
     456          208 :          CALL auxbas_pw_pool%create_pw(wf_g)
     457              :       END IF
     458              : 
     459        10053 :       IF (dft_control%restricted) THEN
     460              :          !For ROKS usefull only first term
     461           74 :          nspins = 1
     462              :       ELSE
     463         9979 :          nspins = dft_control%nspins
     464              :       END IF
     465              :       !Some info about ROKS
     466        10053 :       IF (dft_control%restricted .AND. (do_mo_cubes .OR. p_loc_homo)) THEN
     467            0 :          CALL cp_abort(__LOCATION__, "Unclear how we define MOs / localization in the restricted case ... ")
     468              :          ! It is possible to obtain Wannier centers for ROKS without rotations for SINGLE OCCUPIED ORBITALS
     469              :       END IF
     470              :       ! Makes the MOs eigenstates, computes eigenvalues, write cubes
     471        10053 :       IF (do_kpoints) THEN
     472          220 :          CPWARN_IF(do_mo_cubes, "Print MO cubes not implemented for k-point calculations")
     473              :       ELSE
     474              :          CALL get_qs_env(qs_env, &
     475              :                          mos=mos, &
     476         9833 :                          matrix_ks=ks_rmpv)
     477         9833 :          IF ((do_mo_cubes .AND. nhomo /= 0) .OR. do_stm) THEN
     478          132 :             CALL get_qs_env(qs_env, mo_derivs=mo_derivs)
     479          132 :             IF (dft_control%do_admm) THEN
     480            0 :                CALL get_qs_env(qs_env, admm_env=admm_env)
     481            0 :                CALL make_mo_eig(mos, nspins, ks_rmpv, scf_control, mo_derivs, admm_env=admm_env)
     482              :             ELSE
     483          132 :                IF (dft_control%hairy_probes) THEN
     484            0 :                   scf_control%smear%do_smear = .FALSE.
     485              :                   CALL make_mo_eig(mos, dft_control%nspins, ks_rmpv, scf_control, mo_derivs, &
     486              :                                    hairy_probes=dft_control%hairy_probes, &
     487            0 :                                    probe=dft_control%probe)
     488              :                ELSE
     489          132 :                   CALL make_mo_eig(mos, dft_control%nspins, ks_rmpv, scf_control, mo_derivs)
     490              :                END IF
     491              :             END IF
     492          282 :             DO ispin = 1, dft_control%nspins
     493          150 :                CALL get_mo_set(mo_set=mos(ispin), eigenvalues=mo_eigenvalues, homo=homo)
     494          282 :                homo_lumo(ispin, 1) = mo_eigenvalues(homo)
     495              :             END DO
     496              :             has_homo = .TRUE.
     497              :          END IF
     498         9833 :          IF (do_mo_cubes .AND. nhomo /= 0) THEN
     499          268 :             DO ispin = 1, nspins
     500              :                ! Prints the cube files of OCCUPIED ORBITALS
     501              :                CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, &
     502          142 :                                eigenvalues=mo_eigenvalues, homo=homo, nmo=nmo)
     503              :                CALL qs_scf_post_occ_cubes(input, dft_section, dft_control, logger, qs_env, &
     504          268 :                                           mo_coeff, wf_g, wf_r, particles, homo, ispin)
     505              :             END DO
     506              :          END IF
     507              :       END IF
     508              : 
     509              :       ! Initialize the localization environment, needed e.g. for wannier functions and molecular states
     510              :       ! Gets localization info for the occupied orbs
     511              :       !  - Possibly gets wannier functions
     512              :       !  - Possibly gets molecular states
     513        10053 :       IF (p_loc_homo) THEN
     514           90 :          IF (do_kpoints) THEN
     515            0 :             CPWARN("Localization not implemented for k-point calculations!")
     516              :          ELSEIF (dft_control%restricted &
     517              :                  .AND. (section_get_ival(localize_section, "METHOD") /= do_loc_none) &
     518           90 :                  .AND. (section_get_ival(localize_section, "METHOD") /= do_loc_jacobi)) THEN
     519            0 :             CPABORT("ROKS works only with LOCALIZE METHOD NONE or JACOBI")
     520              :          ELSE
     521          376 :             ALLOCATE (occupied_orbs(dft_control%nspins))
     522          376 :             ALLOCATE (occupied_evals(dft_control%nspins))
     523          376 :             ALLOCATE (homo_localized(dft_control%nspins))
     524          196 :             DO ispin = 1, dft_control%nspins
     525              :                CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, &
     526          106 :                                eigenvalues=mo_eigenvalues)
     527          106 :                occupied_orbs(ispin) = mo_coeff
     528          106 :                occupied_evals(ispin)%array => mo_eigenvalues
     529          106 :                CALL cp_fm_create(homo_localized(ispin), occupied_orbs(ispin)%matrix_struct)
     530          196 :                CALL cp_fm_to_fm(occupied_orbs(ispin), homo_localized(ispin))
     531              :             END DO
     532              : 
     533           90 :             CALL get_qs_env(qs_env, mo_loc_history=mo_loc_history)
     534           90 :             do_homo = .TRUE.
     535              : 
     536          720 :             ALLOCATE (qs_loc_env_homo)
     537           90 :             CALL qs_loc_env_create(qs_loc_env_homo)
     538           90 :             CALL qs_loc_control_init(qs_loc_env_homo, localize_section, do_homo=do_homo)
     539              :             CALL qs_loc_init(qs_env, qs_loc_env_homo, localize_section, homo_localized, do_homo, &
     540           90 :                              do_mo_cubes, mo_loc_history=mo_loc_history)
     541              :             CALL get_localization_info(qs_env, qs_loc_env_homo, localize_section, homo_localized, &
     542           90 :                                        wf_r, wf_g, particles, occupied_orbs, occupied_evals, marked_states)
     543              : 
     544              :             !retain the homo_localized for future use
     545           90 :             IF (qs_loc_env_homo%localized_wfn_control%use_history) THEN
     546           10 :                CALL retain_history(mo_loc_history, homo_localized)
     547           10 :                CALL set_qs_env(qs_env, mo_loc_history=mo_loc_history)
     548              :             END IF
     549              : 
     550              :             !write restart for localization of occupied orbitals
     551              :             CALL loc_write_restart(qs_loc_env_homo, loc_print_section, mos, &
     552           90 :                                    homo_localized, do_homo)
     553           90 :             CALL cp_fm_release(homo_localized)
     554           90 :             DEALLOCATE (occupied_orbs)
     555           90 :             DEALLOCATE (occupied_evals)
     556              :             ! Print Total Dipole if the localization has been performed
     557          180 :             IF (qs_loc_env_homo%do_localize) THEN
     558           74 :                CALL loc_dipole(input, dft_control, qs_loc_env_homo, logger, qs_env)
     559              :             END IF
     560              :          END IF
     561              :       END IF
     562              : 
     563              :       ! Gets the lumos, and eigenvalues for the lumos, and localize them if requested
     564        10053 :       IF (do_kpoints) THEN
     565          220 :          IF (do_mo_cubes .OR. p_loc_lumo) THEN
     566              :             ! nothing at the moment, not implemented
     567            2 :             CPWARN("Localization and MO related output not implemented for k-point calculations!")
     568              :          END IF
     569              :       ELSE
     570         9833 :          compute_lumos = do_mo_cubes .AND. nlumo /= 0
     571         9833 :          compute_lumos = compute_lumos .OR. p_loc_lumo
     572              : 
     573        21556 :          DO ispin = 1, dft_control%nspins
     574        11723 :             CALL get_mo_set(mo_set=mos(ispin), homo=homo, nmo=nmo)
     575        33231 :             compute_lumos = compute_lumos .AND. homo == nmo
     576              :          END DO
     577              : 
     578         9833 :          IF (do_mo_cubes .AND. .NOT. compute_lumos) THEN
     579              : 
     580           94 :             nlumo = section_get_ival(dft_section, "PRINT%MO_CUBES%NLUMO")
     581          188 :             DO ispin = 1, dft_control%nspins
     582              : 
     583           94 :                CALL get_mo_set(mo_set=mos(ispin), homo=homo, nmo=nmo, eigenvalues=mo_eigenvalues)
     584          188 :                IF (nlumo > nmo - homo) THEN
     585              :                   ! this case not yet implemented
     586              :                ELSE
     587           94 :                   IF (nlumo == -1) THEN
     588            0 :                      nlumo = nmo - homo
     589              :                   END IF
     590           94 :                   IF (output_unit > 0) WRITE (output_unit, *) " "
     591           94 :                   IF (output_unit > 0) WRITE (output_unit, *) " Lowest eigenvalues of the unoccupied subspace spin ", ispin
     592           94 :                   IF (output_unit > 0) WRITE (output_unit, *) "---------------------------------------------"
     593           94 :                   IF (output_unit > 0) WRITE (output_unit, '(4(1X,1F16.8))') mo_eigenvalues(homo + 1:homo + nlumo)
     594              : 
     595              :                   ! Prints the cube files of UNOCCUPIED ORBITALS
     596           94 :                   CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff)
     597              :                   CALL qs_scf_post_unocc_cubes(input, dft_section, dft_control, logger, qs_env, &
     598           94 :                                                mo_coeff, wf_g, wf_r, particles, nlumo, homo, ispin, lumo=homo + 1)
     599              :                END IF
     600              :             END DO
     601              : 
     602              :          END IF
     603              : 
     604         9801 :          IF (compute_lumos) THEN
     605           32 :             check_write = .TRUE.
     606           32 :             min_lumos = nlumo
     607           32 :             IF (nlumo == 0) check_write = .FALSE.
     608           32 :             IF (p_loc_lumo) THEN
     609            6 :                do_homo = .FALSE.
     610           48 :                ALLOCATE (qs_loc_env_lumo)
     611            6 :                CALL qs_loc_env_create(qs_loc_env_lumo)
     612            6 :                CALL qs_loc_control_init(qs_loc_env_lumo, localize_section, do_homo=do_homo)
     613           98 :                min_lumos = MAX(MAXVAL(qs_loc_env_lumo%localized_wfn_control%loc_states(:, :)), nlumo)
     614              :             END IF
     615              : 
     616          144 :             ALLOCATE (unoccupied_orbs(dft_control%nspins))
     617          144 :             ALLOCATE (unoccupied_evals(dft_control%nspins))
     618           32 :             CALL make_lumo_gpw(qs_env, scf_env, unoccupied_orbs, unoccupied_evals, min_lumos, nlumos)
     619           32 :             lumo_ptr => unoccupied_orbs
     620           80 :             DO ispin = 1, dft_control%nspins
     621           48 :                has_lumo = .TRUE.
     622           48 :                homo_lumo(ispin, 2) = unoccupied_evals(ispin)%array(1)
     623           48 :                CALL get_mo_set(mo_set=mos(ispin), homo=homo)
     624           80 :                IF (check_write) THEN
     625           48 :                   IF (p_loc_lumo .AND. nlumo /= -1) nlumos = MIN(nlumo, nlumos)
     626              :                   ! Prints the cube files of UNOCCUPIED ORBITALS
     627              :                   CALL qs_scf_post_unocc_cubes(input, dft_section, dft_control, logger, qs_env, &
     628           48 :                                                unoccupied_orbs(ispin), wf_g, wf_r, particles, nlumos, homo, ispin)
     629              :                END IF
     630              :             END DO
     631              : 
     632           64 :             IF (p_loc_lumo) THEN
     633           30 :                ALLOCATE (lumo_localized(dft_control%nspins))
     634           18 :                DO ispin = 1, dft_control%nspins
     635           12 :                   CALL cp_fm_create(lumo_localized(ispin), unoccupied_orbs(ispin)%matrix_struct)
     636           18 :                   CALL cp_fm_to_fm(unoccupied_orbs(ispin), lumo_localized(ispin))
     637              :                END DO
     638              :                CALL qs_loc_init(qs_env, qs_loc_env_lumo, localize_section, lumo_localized, do_homo, do_mo_cubes, &
     639            6 :                                 evals=unoccupied_evals)
     640              :                CALL qs_loc_env_init(qs_loc_env_lumo, qs_loc_env_lumo%localized_wfn_control, qs_env, &
     641            6 :                                     loc_coeff=unoccupied_orbs)
     642              :                CALL get_localization_info(qs_env, qs_loc_env_lumo, localize_section, &
     643              :                                           lumo_localized, wf_r, wf_g, particles, &
     644            6 :                                           unoccupied_orbs, unoccupied_evals, marked_states)
     645              :                CALL loc_write_restart(qs_loc_env_lumo, loc_print_section, mos, homo_localized, do_homo, &
     646            6 :                                       evals=unoccupied_evals)
     647            6 :                lumo_ptr => lumo_localized
     648              :             END IF
     649              :          END IF
     650              : 
     651         9833 :          IF (has_homo .AND. has_lumo) THEN
     652           32 :             IF (output_unit > 0) WRITE (output_unit, *) " "
     653           80 :             DO ispin = 1, dft_control%nspins
     654           80 :                IF (.NOT. scf_control%smear%do_smear) THEN
     655           48 :                   gap = homo_lumo(ispin, 2) - homo_lumo(ispin, 1)
     656           48 :                   IF (output_unit > 0) WRITE (output_unit, '(T2,A,F12.6)') &
     657           24 :                      "HOMO - LUMO gap [eV] :", gap*evolt
     658              :                END IF
     659              :             END DO
     660              :          END IF
     661              :       END IF
     662              : 
     663        10053 :       IF (p_loc_mixed) THEN
     664            2 :          IF (do_kpoints) THEN
     665            0 :             CPWARN("Localization not implemented for k-point calculations!")
     666            2 :          ELSEIF (dft_control%restricted) THEN
     667            0 :             IF (output_unit > 0) WRITE (output_unit, *) &
     668            0 :                " Unclear how we define MOs / localization in the restricted case... skipping"
     669              :          ELSE
     670              : 
     671            8 :             ALLOCATE (mixed_orbs(dft_control%nspins))
     672            8 :             ALLOCATE (mixed_evals(dft_control%nspins))
     673            8 :             ALLOCATE (mixed_localized(dft_control%nspins))
     674            4 :             DO ispin = 1, dft_control%nspins
     675              :                CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, &
     676            2 :                                eigenvalues=mo_eigenvalues)
     677            2 :                mixed_orbs(ispin) = mo_coeff
     678            2 :                mixed_evals(ispin)%array => mo_eigenvalues
     679            2 :                CALL cp_fm_create(mixed_localized(ispin), mixed_orbs(ispin)%matrix_struct)
     680            4 :                CALL cp_fm_to_fm(mixed_orbs(ispin), mixed_localized(ispin))
     681              :             END DO
     682              : 
     683            2 :             CALL get_qs_env(qs_env, mo_loc_history=mo_loc_history)
     684            2 :             do_homo = .FALSE.
     685            2 :             do_mixed = .TRUE.
     686            2 :             total_zeff_corr = scf_env%sum_zeff_corr
     687           16 :             ALLOCATE (qs_loc_env_mixed)
     688            2 :             CALL qs_loc_env_create(qs_loc_env_mixed)
     689            2 :             CALL qs_loc_control_init(qs_loc_env_mixed, localize_section, do_homo=do_homo, do_mixed=do_mixed)
     690              :             CALL qs_loc_init(qs_env, qs_loc_env_mixed, localize_section, mixed_localized, do_homo, &
     691              :                              do_mo_cubes, mo_loc_history=mo_loc_history, tot_zeff_corr=total_zeff_corr, &
     692            2 :                              do_mixed=do_mixed)
     693              : 
     694            4 :             DO ispin = 1, dft_control%nspins
     695            4 :                CALL cp_fm_get_info(mixed_localized(ispin), ncol_global=nchk_nmoloc)
     696              :             END DO
     697              : 
     698              :             CALL get_localization_info(qs_env, qs_loc_env_mixed, localize_section, mixed_localized, &
     699            2 :                                        wf_r, wf_g, particles, mixed_orbs, mixed_evals, marked_states)
     700              : 
     701              :             !retain the homo_localized for future use
     702            2 :             IF (qs_loc_env_mixed%localized_wfn_control%use_history) THEN
     703            0 :                CALL retain_history(mo_loc_history, mixed_localized)
     704            0 :                CALL set_qs_env(qs_env, mo_loc_history=mo_loc_history)
     705              :             END IF
     706              : 
     707              :             !write restart for localization of occupied orbitals
     708              :             CALL loc_write_restart(qs_loc_env_mixed, loc_print_section, mos, &
     709            2 :                                    mixed_localized, do_homo, do_mixed=do_mixed)
     710            2 :             CALL cp_fm_release(mixed_localized)
     711            2 :             DEALLOCATE (mixed_orbs)
     712            4 :             DEALLOCATE (mixed_evals)
     713              :             ! Print Total Dipole if the localization has been performed
     714              : ! Revisit the formalism later
     715              :             !IF (qs_loc_env_mixed%do_localize) THEN
     716              :             !   CALL loc_dipole(input, dft_control, qs_loc_env_mixed, logger, qs_env)
     717              :             !END IF
     718              :          END IF
     719              :       END IF
     720              : 
     721              :       ! Deallocate grids needed to compute wavefunctions
     722        10053 :       IF (((do_mo_cubes .OR. do_wannier_cubes) .AND. (nlumo /= 0 .OR. nhomo /= 0)) .OR. p_loc) THEN
     723          208 :          CALL auxbas_pw_pool%give_back_pw(wf_r)
     724          208 :          CALL auxbas_pw_pool%give_back_pw(wf_g)
     725              :       END IF
     726              : 
     727              :       ! Destroy the localization environment
     728        10053 :       IF (.NOT. do_kpoints) THEN
     729         9833 :          IF (p_loc_homo) THEN
     730           90 :             CALL qs_loc_env_release(qs_loc_env_homo)
     731           90 :             DEALLOCATE (qs_loc_env_homo)
     732              :          END IF
     733         9833 :          IF (p_loc_lumo) THEN
     734            6 :             CALL qs_loc_env_release(qs_loc_env_lumo)
     735            6 :             DEALLOCATE (qs_loc_env_lumo)
     736              :          END IF
     737         9833 :          IF (p_loc_mixed) THEN
     738            2 :             CALL qs_loc_env_release(qs_loc_env_mixed)
     739            2 :             DEALLOCATE (qs_loc_env_mixed)
     740              :          END IF
     741              :       END IF
     742              : 
     743              :       ! generate a mix of wfns, and write to a restart
     744        10053 :       IF (do_kpoints) THEN
     745              :          ! nothing at the moment, not implemented
     746              :       ELSE
     747         9833 :          CALL get_qs_env(qs_env, matrix_s=matrix_s, para_env=para_env)
     748              :          CALL wfn_mix(mos, particle_set, dft_section, qs_kind_set, para_env, &
     749              :                       output_unit, unoccupied_orbs=lumo_ptr, scf_env=scf_env, &
     750         9833 :                       matrix_s=matrix_s, marked_states=marked_states)
     751              : 
     752         9833 :          IF (p_loc_lumo) CALL cp_fm_release(lumo_localized)
     753              :       END IF
     754        10053 :       IF (ASSOCIATED(marked_states)) THEN
     755           16 :          DEALLOCATE (marked_states)
     756              :       END IF
     757              : 
     758              :       ! This is just a deallocation for printing MO_CUBES or TDDFPT
     759        10053 :       IF (.NOT. do_kpoints) THEN
     760         9833 :          IF (compute_lumos) THEN
     761           80 :             DO ispin = 1, dft_control%nspins
     762           48 :                DEALLOCATE (unoccupied_evals(ispin)%array)
     763           80 :                CALL cp_fm_release(unoccupied_orbs(ispin))
     764              :             END DO
     765           32 :             DEALLOCATE (unoccupied_evals)
     766           32 :             DEALLOCATE (unoccupied_orbs)
     767              :          END IF
     768              :       END IF
     769              : 
     770              :       !stm images
     771        10053 :       IF (do_stm) THEN
     772            6 :          IF (do_kpoints) THEN
     773            0 :             CPWARN("STM not implemented for k-point calculations!")
     774              :          ELSE
     775            6 :             NULLIFY (unoccupied_orbs_stm, unoccupied_evals_stm)
     776            6 :             IF (nlumo_stm > 0) THEN
     777            8 :                ALLOCATE (unoccupied_orbs_stm(dft_control%nspins))
     778            8 :                ALLOCATE (unoccupied_evals_stm(dft_control%nspins))
     779              :                CALL make_lumo_gpw(qs_env, scf_env, unoccupied_orbs_stm, unoccupied_evals_stm, &
     780            2 :                                   nlumo_stm, nlumos)
     781              :             END IF
     782              : 
     783              :             CALL th_stm_image(qs_env, stm_section, particles, unoccupied_orbs_stm, &
     784            6 :                               unoccupied_evals_stm)
     785              : 
     786            6 :             IF (nlumo_stm > 0) THEN
     787            4 :                DO ispin = 1, dft_control%nspins
     788            4 :                   DEALLOCATE (unoccupied_evals_stm(ispin)%array)
     789              :                END DO
     790            2 :                DEALLOCATE (unoccupied_evals_stm)
     791            2 :                CALL cp_fm_release(unoccupied_orbs_stm)
     792              :             END IF
     793              :          END IF
     794              :       END IF
     795              : 
     796              :       ! Print coherent X-ray diffraction spectrum
     797        10053 :       CALL qs_scf_post_xray(input, dft_section, logger, qs_env, output_unit)
     798              : 
     799              :       ! Calculation of Electric Field Gradients
     800        10053 :       CALL qs_scf_post_efg(input, logger, qs_env)
     801              : 
     802              :       ! Calculation of ET
     803        10053 :       CALL qs_scf_post_et(input, qs_env, dft_control)
     804              : 
     805              :       ! Calculation of EPR Hyperfine Coupling Tensors
     806        10053 :       CALL qs_scf_post_epr(input, logger, qs_env)
     807              : 
     808              :       ! Calculation of properties needed for BASIS_MOLOPT optimizations
     809        10053 :       CALL qs_scf_post_molopt(input, logger, qs_env)
     810              : 
     811              :       ! Calculate ELF
     812        10053 :       CALL qs_scf_post_elf(input, logger, qs_env)
     813              : 
     814              :       ! Use Wannier90 interface
     815        10053 :       CALL wannier90_interface(input, logger, qs_env)
     816              : 
     817        10053 :       IF (my_do_mp2) THEN
     818              :          ! Get everything back
     819          742 :          DO ispin = 1, dft_control%nspins
     820          742 :             CALL dbcsr_add(rho_ao(ispin, 1)%matrix, matrix_p_mp2(ispin)%matrix, 1.0_dp, -1.0_dp)
     821              :          END DO
     822          322 :          CALL qs_rho_update_rho(rho, qs_env=qs_env)
     823          322 :          CALL qs_ks_did_change(qs_env%ks_env, rho_changed=.TRUE.)
     824              :       END IF
     825              : 
     826        10053 :       CALL timestop(handle)
     827              : 
     828        20106 :    END SUBROUTINE scf_post_calculation_gpw
     829              : 
     830              : ! **************************************************************************************************
     831              : !> \brief Gets the lumos, and eigenvalues for the lumos
     832              : !> \param qs_env ...
     833              : !> \param scf_env ...
     834              : !> \param unoccupied_orbs ...
     835              : !> \param unoccupied_evals ...
     836              : !> \param nlumo ...
     837              : !> \param nlumos ...
     838              : ! **************************************************************************************************
     839           34 :    SUBROUTINE make_lumo_gpw(qs_env, scf_env, unoccupied_orbs, unoccupied_evals, nlumo, nlumos)
     840              : 
     841              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     842              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     843              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(INOUT)      :: unoccupied_orbs
     844              :       TYPE(cp_1d_r_p_type), DIMENSION(:), POINTER        :: unoccupied_evals
     845              :       INTEGER, INTENT(IN)                                :: nlumo
     846              :       INTEGER, INTENT(OUT)                               :: nlumos
     847              : 
     848              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'make_lumo_gpw'
     849              : 
     850              :       INTEGER                                            :: handle, homo, ispin, n, nao, nmo, &
     851              :                                                             output_unit
     852              :       TYPE(admm_type), POINTER                           :: admm_env
     853              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     854              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_tmp
     855              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     856              :       TYPE(cp_logger_type), POINTER                      :: logger
     857           34 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: ks_rmpv, matrix_s
     858              :       TYPE(dft_control_type), POINTER                    :: dft_control
     859           34 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     860              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     861              :       TYPE(preconditioner_type), POINTER                 :: local_preconditioner
     862              :       TYPE(scf_control_type), POINTER                    :: scf_control
     863              : 
     864           34 :       CALL timeset(routineN, handle)
     865              : 
     866           34 :       NULLIFY (mos, ks_rmpv, scf_control, dft_control, admm_env, para_env, blacs_env)
     867              :       CALL get_qs_env(qs_env, &
     868              :                       mos=mos, &
     869              :                       matrix_ks=ks_rmpv, &
     870              :                       scf_control=scf_control, &
     871              :                       dft_control=dft_control, &
     872              :                       matrix_s=matrix_s, &
     873              :                       admm_env=admm_env, &
     874              :                       para_env=para_env, &
     875           34 :                       blacs_env=blacs_env)
     876              : 
     877           34 :       logger => cp_get_default_logger()
     878           34 :       output_unit = cp_logger_get_default_io_unit(logger)
     879              : 
     880           84 :       DO ispin = 1, dft_control%nspins
     881           50 :          NULLIFY (unoccupied_evals(ispin)%array)
     882              :          ! Always write eigenvalues
     883           50 :          IF (output_unit > 0) WRITE (output_unit, *) " "
     884           50 :          IF (output_unit > 0) WRITE (output_unit, *) " Lowest Eigenvalues of the unoccupied subspace spin ", ispin
     885           50 :          IF (output_unit > 0) WRITE (output_unit, FMT='(1X,A)') "-----------------------------------------------------"
     886           50 :          CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, homo=homo, nao=nao, nmo=nmo)
     887           50 :          CALL cp_fm_get_info(mo_coeff, nrow_global=n)
     888           50 :          nlumos = MAX(1, MIN(nlumo, nao - nmo))
     889           50 :          IF (nlumo == -1) nlumos = nao - nmo
     890          150 :          ALLOCATE (unoccupied_evals(ispin)%array(nlumos))
     891              :          CALL cp_fm_struct_create(fm_struct_tmp, para_env=para_env, context=blacs_env, &
     892           50 :                                   nrow_global=n, ncol_global=nlumos)
     893           50 :          CALL cp_fm_create(unoccupied_orbs(ispin), fm_struct_tmp, name="lumos")
     894           50 :          CALL cp_fm_struct_release(fm_struct_tmp)
     895           50 :          CALL cp_fm_init_random(unoccupied_orbs(ispin), nlumos)
     896              : 
     897              :          ! the full_all preconditioner makes not much sense for lumos search
     898           50 :          NULLIFY (local_preconditioner)
     899           50 :          IF (ASSOCIATED(scf_env%ot_preconditioner)) THEN
     900           26 :             local_preconditioner => scf_env%ot_preconditioner(1)%preconditioner
     901              :             ! this one can for sure not be right (as it has to match a given C0)
     902           26 :             IF (local_preconditioner%in_use == ot_precond_full_all) THEN
     903            4 :                NULLIFY (local_preconditioner)
     904              :             END IF
     905              :          END IF
     906              : 
     907              :          ! If we do ADMM, we add have to modify the Kohn-Sham matrix
     908           50 :          IF (dft_control%do_admm) THEN
     909            0 :             CALL admm_correct_for_eigenvalues(ispin, admm_env, ks_rmpv(ispin)%matrix)
     910              :          END IF
     911              : 
     912              :          CALL ot_eigensolver(matrix_h=ks_rmpv(ispin)%matrix, matrix_s=matrix_s(1)%matrix, &
     913              :                              matrix_c_fm=unoccupied_orbs(ispin), &
     914              :                              matrix_orthogonal_space_fm=mo_coeff, &
     915              :                              eps_gradient=scf_control%eps_lumos, &
     916              :                              preconditioner=local_preconditioner, &
     917              :                              iter_max=scf_control%max_iter_lumos, &
     918           50 :                              size_ortho_space=nmo)
     919              : 
     920              :          CALL calculate_subspace_eigenvalues(unoccupied_orbs(ispin), ks_rmpv(ispin)%matrix, &
     921              :                                              unoccupied_evals(ispin)%array, scr=output_unit, &
     922           50 :                                              ionode=output_unit > 0)
     923              : 
     924              :          ! If we do ADMM, we restore the original Kohn-Sham matrix
     925          134 :          IF (dft_control%do_admm) THEN
     926            0 :             CALL admm_uncorrect_for_eigenvalues(ispin, admm_env, ks_rmpv(ispin)%matrix)
     927              :          END IF
     928              : 
     929              :       END DO
     930              : 
     931           34 :       CALL timestop(handle)
     932              : 
     933           34 :    END SUBROUTINE make_lumo_gpw
     934              : ! **************************************************************************************************
     935              : !> \brief Computes and Prints Atomic Charges with several methods
     936              : !> \param input ...
     937              : !> \param logger ...
     938              : !> \param qs_env the qs_env in which the qs_env lives
     939              : ! **************************************************************************************************
     940        10053 :    SUBROUTINE qs_scf_post_charges(input, logger, qs_env)
     941              :       TYPE(section_vals_type), POINTER                   :: input
     942              :       TYPE(cp_logger_type), POINTER                      :: logger
     943              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     944              : 
     945              :       CHARACTER(len=*), PARAMETER :: routineN = 'qs_scf_post_charges'
     946              : 
     947              :       INTEGER                                            :: handle, print_level, unit_nr
     948              :       LOGICAL                                            :: do_kpoints, print_it
     949              :       TYPE(section_vals_type), POINTER                   :: density_fit_section, print_key
     950              : 
     951        10053 :       CALL timeset(routineN, handle)
     952              : 
     953        10053 :       CALL get_qs_env(qs_env=qs_env, do_kpoints=do_kpoints)
     954              : 
     955              :       ! Mulliken charges require no further computation and are printed from write_mo_free_results
     956              : 
     957              :       ! Compute the Lowdin charges
     958        10053 :       print_key => section_vals_get_subs_vals(input, "DFT%PRINT%LOWDIN")
     959        10053 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
     960              :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%LOWDIN", extension=".lowdin", &
     961           82 :                                         log_filename=.FALSE.)
     962           82 :          print_level = 1
     963           82 :          CALL section_vals_val_get(print_key, "PRINT_GOP", l_val=print_it)
     964           82 :          IF (print_it) print_level = 2
     965           82 :          CALL section_vals_val_get(print_key, "PRINT_ALL", l_val=print_it)
     966           82 :          IF (print_it) print_level = 3
     967           82 :          IF (do_kpoints) THEN
     968            2 :             CPWARN("Lowdin charges not implemented for k-point calculations!")
     969              :          ELSE
     970           80 :             CALL lowdin_population_analysis(qs_env, unit_nr, print_level)
     971              :          END IF
     972           82 :          CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%LOWDIN")
     973              :       END IF
     974              : 
     975              :       ! Compute the RESP charges
     976        10053 :       CALL resp_fit(qs_env)
     977              : 
     978              :       ! Compute the Density Derived Atomic Point charges with the Bloechl scheme
     979        10053 :       print_key => section_vals_get_subs_vals(input, "PROPERTIES%FIT_CHARGE")
     980        10053 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
     981              :          unit_nr = cp_print_key_unit_nr(logger, input, "PROPERTIES%FIT_CHARGE", extension=".Fitcharge", &
     982          102 :                                         log_filename=.FALSE.)
     983          102 :          density_fit_section => section_vals_get_subs_vals(input, "DFT%DENSITY_FITTING")
     984          102 :          CALL get_ddapc(qs_env, .FALSE., density_fit_section, iwc=unit_nr)
     985          102 :          CALL cp_print_key_finished_output(unit_nr, logger, input, "PROPERTIES%FIT_CHARGE")
     986              :       END IF
     987              : 
     988        10053 :       CALL timestop(handle)
     989              : 
     990        10053 :    END SUBROUTINE qs_scf_post_charges
     991              : 
     992              : ! **************************************************************************************************
     993              : !> \brief Computes and prints the Cube Files for MO
     994              : !> \param input ...
     995              : !> \param dft_section ...
     996              : !> \param dft_control ...
     997              : !> \param logger ...
     998              : !> \param qs_env the qs_env in which the qs_env lives
     999              : !> \param mo_coeff ...
    1000              : !> \param wf_g ...
    1001              : !> \param wf_r ...
    1002              : !> \param particles ...
    1003              : !> \param homo ...
    1004              : !> \param ispin ...
    1005              : ! **************************************************************************************************
    1006          142 :    SUBROUTINE qs_scf_post_occ_cubes(input, dft_section, dft_control, logger, qs_env, &
    1007              :                                     mo_coeff, wf_g, wf_r, particles, homo, ispin)
    1008              :       TYPE(section_vals_type), POINTER                   :: input, dft_section
    1009              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1010              :       TYPE(cp_logger_type), POINTER                      :: logger
    1011              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1012              :       TYPE(cp_fm_type), INTENT(IN)                       :: mo_coeff
    1013              :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: wf_g
    1014              :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: wf_r
    1015              :       TYPE(particle_list_type), POINTER                  :: particles
    1016              :       INTEGER, INTENT(IN)                                :: homo, ispin
    1017              : 
    1018              :       CHARACTER(len=*), PARAMETER :: routineN = 'qs_scf_post_occ_cubes'
    1019              : 
    1020              :       CHARACTER(LEN=default_path_length)                 :: filename, my_pos_cube, title
    1021              :       INTEGER                                            :: handle, i, ir, ivector, n_rep, nhomo, &
    1022              :                                                             nlist, unit_nr
    1023          142 :       INTEGER, DIMENSION(:), POINTER                     :: list, list_index
    1024              :       LOGICAL                                            :: append_cube, mpi_io
    1025          142 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1026              :       TYPE(cell_type), POINTER                           :: cell
    1027          142 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1028              :       TYPE(pw_env_type), POINTER                         :: pw_env
    1029          142 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1030              : 
    1031          142 :       CALL timeset(routineN, handle)
    1032              : 
    1033          142 :       NULLIFY (list_index)
    1034              : 
    1035              :       IF (BTEST(cp_print_key_should_output(logger%iter_info, dft_section, "PRINT%MO_CUBES") &
    1036          142 :                 , cp_p_file) .AND. section_get_lval(dft_section, "PRINT%MO_CUBES%WRITE_CUBE")) THEN
    1037          104 :          nhomo = section_get_ival(dft_section, "PRINT%MO_CUBES%NHOMO")
    1038          104 :          append_cube = section_get_lval(dft_section, "PRINT%MO_CUBES%APPEND")
    1039          104 :          my_pos_cube = "REWIND"
    1040          104 :          IF (append_cube) THEN
    1041            0 :             my_pos_cube = "APPEND"
    1042              :          END IF
    1043          104 :          CALL section_vals_val_get(dft_section, "PRINT%MO_CUBES%HOMO_LIST", n_rep_val=n_rep)
    1044          104 :          IF (n_rep > 0) THEN ! write the cubes of the list
    1045            0 :             nlist = 0
    1046            0 :             DO ir = 1, n_rep
    1047            0 :                NULLIFY (list)
    1048              :                CALL section_vals_val_get(dft_section, "PRINT%MO_CUBES%HOMO_LIST", i_rep_val=ir, &
    1049            0 :                                          i_vals=list)
    1050            0 :                IF (ASSOCIATED(list)) THEN
    1051            0 :                   CALL reallocate(list_index, 1, nlist + SIZE(list))
    1052            0 :                   DO i = 1, SIZE(list)
    1053            0 :                      list_index(i + nlist) = list(i)
    1054              :                   END DO
    1055            0 :                   nlist = nlist + SIZE(list)
    1056              :                END IF
    1057              :             END DO
    1058              :          ELSE
    1059              : 
    1060          104 :             IF (nhomo == -1) nhomo = homo
    1061          104 :             nlist = homo - MAX(1, homo - nhomo + 1) + 1
    1062          312 :             ALLOCATE (list_index(nlist))
    1063          212 :             DO i = 1, nlist
    1064          212 :                list_index(i) = MAX(1, homo - nhomo + 1) + i - 1
    1065              :             END DO
    1066              :          END IF
    1067          212 :          DO i = 1, nlist
    1068          108 :             ivector = list_index(i)
    1069              :             CALL get_qs_env(qs_env=qs_env, &
    1070              :                             atomic_kind_set=atomic_kind_set, &
    1071              :                             qs_kind_set=qs_kind_set, &
    1072              :                             cell=cell, &
    1073              :                             particle_set=particle_set, &
    1074          108 :                             pw_env=pw_env)
    1075              :             CALL calculate_wavefunction(mo_coeff, ivector, wf_r, wf_g, atomic_kind_set, qs_kind_set, &
    1076          108 :                                         cell, dft_control, particle_set, pw_env)
    1077          108 :             WRITE (filename, '(a4,I5.5,a1,I1.1)') "WFN_", ivector, "_", ispin
    1078          108 :             mpi_io = .TRUE.
    1079              :             unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%MO_CUBES", extension=".cube", &
    1080              :                                            middle_name=TRIM(filename), file_position=my_pos_cube, log_filename=.FALSE., &
    1081          108 :                                            mpi_io=mpi_io)
    1082          108 :             WRITE (title, *) "WAVEFUNCTION ", ivector, " spin ", ispin, " i.e. HOMO - ", ivector - homo
    1083              :             CALL cp_pw_to_cube(wf_r, unit_nr, title, particles=particles, &
    1084          108 :                                stride=section_get_ivals(dft_section, "PRINT%MO_CUBES%STRIDE"), mpi_io=mpi_io)
    1085          212 :             CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%MO_CUBES", mpi_io=mpi_io)
    1086              :          END DO
    1087          104 :          IF (ASSOCIATED(list_index)) DEALLOCATE (list_index)
    1088              :       END IF
    1089              : 
    1090          142 :       CALL timestop(handle)
    1091              : 
    1092          142 :    END SUBROUTINE qs_scf_post_occ_cubes
    1093              : 
    1094              : ! **************************************************************************************************
    1095              : !> \brief Computes and prints the Cube Files for MO
    1096              : !> \param input ...
    1097              : !> \param dft_section ...
    1098              : !> \param dft_control ...
    1099              : !> \param logger ...
    1100              : !> \param qs_env the qs_env in which the qs_env lives
    1101              : !> \param unoccupied_orbs ...
    1102              : !> \param wf_g ...
    1103              : !> \param wf_r ...
    1104              : !> \param particles ...
    1105              : !> \param nlumos ...
    1106              : !> \param homo ...
    1107              : !> \param ispin ...
    1108              : !> \param lumo ...
    1109              : ! **************************************************************************************************
    1110          142 :    SUBROUTINE qs_scf_post_unocc_cubes(input, dft_section, dft_control, logger, qs_env, &
    1111              :                                       unoccupied_orbs, wf_g, wf_r, particles, nlumos, homo, ispin, lumo)
    1112              : 
    1113              :       TYPE(section_vals_type), POINTER                   :: input, dft_section
    1114              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1115              :       TYPE(cp_logger_type), POINTER                      :: logger
    1116              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1117              :       TYPE(cp_fm_type), INTENT(IN)                       :: unoccupied_orbs
    1118              :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: wf_g
    1119              :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: wf_r
    1120              :       TYPE(particle_list_type), POINTER                  :: particles
    1121              :       INTEGER, INTENT(IN)                                :: nlumos, homo, ispin
    1122              :       INTEGER, INTENT(IN), OPTIONAL                      :: lumo
    1123              : 
    1124              :       CHARACTER(len=*), PARAMETER :: routineN = 'qs_scf_post_unocc_cubes'
    1125              : 
    1126              :       CHARACTER(LEN=default_path_length)                 :: filename, my_pos_cube, title
    1127              :       INTEGER                                            :: handle, ifirst, index_mo, ivector, &
    1128              :                                                             unit_nr
    1129              :       LOGICAL                                            :: append_cube, mpi_io
    1130          142 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1131              :       TYPE(cell_type), POINTER                           :: cell
    1132          142 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1133              :       TYPE(pw_env_type), POINTER                         :: pw_env
    1134          142 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1135              : 
    1136          142 :       CALL timeset(routineN, handle)
    1137              : 
    1138              :       IF (BTEST(cp_print_key_should_output(logger%iter_info, dft_section, "PRINT%MO_CUBES"), cp_p_file) &
    1139          142 :           .AND. section_get_lval(dft_section, "PRINT%MO_CUBES%WRITE_CUBE")) THEN
    1140          104 :          NULLIFY (qs_kind_set, particle_set, pw_env, cell)
    1141          104 :          append_cube = section_get_lval(dft_section, "PRINT%MO_CUBES%APPEND")
    1142          104 :          my_pos_cube = "REWIND"
    1143          104 :          IF (append_cube) THEN
    1144            0 :             my_pos_cube = "APPEND"
    1145              :          END IF
    1146          104 :          ifirst = 1
    1147          104 :          IF (PRESENT(lumo)) ifirst = lumo
    1148          242 :          DO ivector = ifirst, ifirst + nlumos - 1
    1149              :             CALL get_qs_env(qs_env=qs_env, &
    1150              :                             atomic_kind_set=atomic_kind_set, &
    1151              :                             qs_kind_set=qs_kind_set, &
    1152              :                             cell=cell, &
    1153              :                             particle_set=particle_set, &
    1154          138 :                             pw_env=pw_env)
    1155              :             CALL calculate_wavefunction(unoccupied_orbs, ivector, wf_r, wf_g, atomic_kind_set, &
    1156          138 :                                         qs_kind_set, cell, dft_control, particle_set, pw_env)
    1157              : 
    1158          138 :             IF (ifirst == 1) THEN
    1159          130 :                index_mo = homo + ivector
    1160              :             ELSE
    1161            8 :                index_mo = ivector
    1162              :             END IF
    1163          138 :             WRITE (filename, '(a4,I5.5,a1,I1.1)') "WFN_", index_mo, "_", ispin
    1164          138 :             mpi_io = .TRUE.
    1165              : 
    1166              :             unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%MO_CUBES", extension=".cube", &
    1167              :                                            middle_name=TRIM(filename), file_position=my_pos_cube, log_filename=.FALSE., &
    1168          138 :                                            mpi_io=mpi_io)
    1169          138 :             WRITE (title, *) "WAVEFUNCTION ", index_mo, " spin ", ispin, " i.e. LUMO + ", ifirst + ivector - 2
    1170              :             CALL cp_pw_to_cube(wf_r, unit_nr, title, particles=particles, &
    1171          138 :                                stride=section_get_ivals(dft_section, "PRINT%MO_CUBES%STRIDE"), mpi_io=mpi_io)
    1172          242 :             CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%MO_CUBES", mpi_io=mpi_io)
    1173              :          END DO
    1174              :       END IF
    1175              : 
    1176          142 :       CALL timestop(handle)
    1177              : 
    1178          142 :    END SUBROUTINE qs_scf_post_unocc_cubes
    1179              : 
    1180              : ! **************************************************************************************************
    1181              : !> \brief Computes and prints electric moments
    1182              : !> \param input ...
    1183              : !> \param logger ...
    1184              : !> \param qs_env the qs_env in which the qs_env lives
    1185              : !> \param output_unit ...
    1186              : ! **************************************************************************************************
    1187        11239 :    SUBROUTINE qs_scf_post_moments(input, logger, qs_env, output_unit)
    1188              :       TYPE(section_vals_type), POINTER                   :: input
    1189              :       TYPE(cp_logger_type), POINTER                      :: logger
    1190              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1191              :       INTEGER, INTENT(IN)                                :: output_unit
    1192              : 
    1193              :       CHARACTER(len=*), PARAMETER :: routineN = 'qs_scf_post_moments'
    1194              : 
    1195              :       CHARACTER(LEN=default_path_length)                 :: filename
    1196              :       INTEGER                                            :: handle, maxmom, reference, unit_nr
    1197              :       LOGICAL                                            :: com_nl, do_kpoints, magnetic, periodic, &
    1198              :                                                             second_ref_point, vel_reprs
    1199        11239 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: ref_point
    1200              :       TYPE(section_vals_type), POINTER                   :: print_key
    1201              : 
    1202        11239 :       CALL timeset(routineN, handle)
    1203              : 
    1204              :       print_key => section_vals_get_subs_vals(section_vals=input, &
    1205        11239 :                                               subsection_name="DFT%PRINT%MOMENTS")
    1206              : 
    1207        11239 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    1208              : 
    1209              :          maxmom = section_get_ival(section_vals=input, &
    1210         1270 :                                    keyword_name="DFT%PRINT%MOMENTS%MAX_MOMENT")
    1211              :          periodic = section_get_lval(section_vals=input, &
    1212         1270 :                                      keyword_name="DFT%PRINT%MOMENTS%PERIODIC")
    1213              :          reference = section_get_ival(section_vals=input, &
    1214         1270 :                                       keyword_name="DFT%PRINT%MOMENTS%REFERENCE")
    1215              :          magnetic = section_get_lval(section_vals=input, &
    1216         1270 :                                      keyword_name="DFT%PRINT%MOMENTS%MAGNETIC")
    1217              :          vel_reprs = section_get_lval(section_vals=input, &
    1218         1270 :                                       keyword_name="DFT%PRINT%MOMENTS%VEL_REPRS")
    1219              :          com_nl = section_get_lval(section_vals=input, &
    1220         1270 :                                    keyword_name="DFT%PRINT%MOMENTS%COM_NL")
    1221              :          second_ref_point = section_get_lval(section_vals=input, &
    1222         1270 :                                              keyword_name="DFT%PRINT%MOMENTS%SECOND_REFERENCE_POINT")
    1223              : 
    1224         1270 :          NULLIFY (ref_point)
    1225         1270 :          CALL section_vals_val_get(input, "DFT%PRINT%MOMENTS%REF_POINT", r_vals=ref_point)
    1226              :          unit_nr = cp_print_key_unit_nr(logger=logger, basis_section=input, &
    1227              :                                         print_key_path="DFT%PRINT%MOMENTS", extension=".dat", &
    1228         1270 :                                         middle_name="moments", log_filename=.FALSE.)
    1229              : 
    1230         1270 :          IF (output_unit > 0) THEN
    1231          645 :             IF (unit_nr /= output_unit) THEN
    1232           33 :                INQUIRE (UNIT=unit_nr, NAME=filename)
    1233              :                WRITE (UNIT=output_unit, FMT="(/,T2,A,2(/,T3,A),/)") &
    1234           33 :                   "MOMENTS", "The electric/magnetic moments are written to file:", &
    1235           66 :                   TRIM(filename)
    1236              :             ELSE
    1237          612 :                WRITE (UNIT=output_unit, FMT="(/,T2,A)") "ELECTRIC/MAGNETIC MOMENTS"
    1238              :             END IF
    1239              :          END IF
    1240              : 
    1241         1270 :          CALL get_qs_env(qs_env, do_kpoints=do_kpoints)
    1242              : 
    1243         1270 :          IF (do_kpoints) THEN
    1244            2 :             CPWARN("Moments not implemented for k-point calculations!")
    1245              :          ELSE
    1246         1268 :             IF (periodic) THEN
    1247          472 :                CALL qs_moment_berry_phase(qs_env, magnetic, maxmom, reference, ref_point, unit_nr)
    1248              :             ELSE
    1249          796 :                CALL qs_moment_locop(qs_env, magnetic, maxmom, reference, ref_point, unit_nr, vel_reprs, com_nl)
    1250              :             END IF
    1251              :          END IF
    1252              : 
    1253              :          CALL cp_print_key_finished_output(unit_nr=unit_nr, logger=logger, &
    1254         1270 :                                            basis_section=input, print_key_path="DFT%PRINT%MOMENTS")
    1255              : 
    1256         1270 :          IF (second_ref_point) THEN
    1257              :             reference = section_get_ival(section_vals=input, &
    1258            0 :                                          keyword_name="DFT%PRINT%MOMENTS%REFERENCE_2")
    1259              : 
    1260            0 :             NULLIFY (ref_point)
    1261            0 :             CALL section_vals_val_get(input, "DFT%PRINT%MOMENTS%REF_POINT_2", r_vals=ref_point)
    1262              :             unit_nr = cp_print_key_unit_nr(logger=logger, basis_section=input, &
    1263              :                                            print_key_path="DFT%PRINT%MOMENTS", extension=".dat", &
    1264            0 :                                            middle_name="moments_refpoint_2", log_filename=.FALSE.)
    1265              : 
    1266            0 :             IF (output_unit > 0) THEN
    1267            0 :                IF (unit_nr /= output_unit) THEN
    1268            0 :                   INQUIRE (UNIT=unit_nr, NAME=filename)
    1269              :                   WRITE (UNIT=output_unit, FMT="(/,T2,A,2(/,T3,A),/)") &
    1270            0 :                      "MOMENTS", "The electric/magnetic moments for the second reference point are written to file:", &
    1271            0 :                      TRIM(filename)
    1272              :                ELSE
    1273            0 :                   WRITE (UNIT=output_unit, FMT="(/,T2,A)") "ELECTRIC/MAGNETIC MOMENTS"
    1274              :                END IF
    1275              :             END IF
    1276            0 :             IF (do_kpoints) THEN
    1277            0 :                CPWARN("Moments not implemented for k-point calculations!")
    1278              :             ELSE
    1279            0 :                IF (periodic) THEN
    1280            0 :                   CALL qs_moment_berry_phase(qs_env, magnetic, maxmom, reference, ref_point, unit_nr)
    1281              :                ELSE
    1282            0 :                   CALL qs_moment_locop(qs_env, magnetic, maxmom, reference, ref_point, unit_nr, vel_reprs, com_nl)
    1283              :                END IF
    1284              :             END IF
    1285              :             CALL cp_print_key_finished_output(unit_nr=unit_nr, logger=logger, &
    1286            0 :                                               basis_section=input, print_key_path="DFT%PRINT%MOMENTS")
    1287              :          END IF
    1288              : 
    1289              :       END IF
    1290              : 
    1291        11239 :       CALL timestop(handle)
    1292              : 
    1293        11239 :    END SUBROUTINE qs_scf_post_moments
    1294              : 
    1295              : ! **************************************************************************************************
    1296              : !> \brief Computes and prints the X-ray diffraction spectrum.
    1297              : !> \param input ...
    1298              : !> \param dft_section ...
    1299              : !> \param logger ...
    1300              : !> \param qs_env the qs_env in which the qs_env lives
    1301              : !> \param output_unit ...
    1302              : ! **************************************************************************************************
    1303        10053 :    SUBROUTINE qs_scf_post_xray(input, dft_section, logger, qs_env, output_unit)
    1304              : 
    1305              :       TYPE(section_vals_type), POINTER                   :: input, dft_section
    1306              :       TYPE(cp_logger_type), POINTER                      :: logger
    1307              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1308              :       INTEGER, INTENT(IN)                                :: output_unit
    1309              : 
    1310              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'qs_scf_post_xray'
    1311              : 
    1312              :       CHARACTER(LEN=default_path_length)                 :: filename
    1313              :       INTEGER                                            :: handle, unit_nr
    1314              :       REAL(KIND=dp)                                      :: q_max
    1315              :       TYPE(section_vals_type), POINTER                   :: print_key
    1316              : 
    1317        10053 :       CALL timeset(routineN, handle)
    1318              : 
    1319              :       print_key => section_vals_get_subs_vals(section_vals=input, &
    1320        10053 :                                               subsection_name="DFT%PRINT%XRAY_DIFFRACTION_SPECTRUM")
    1321              : 
    1322        10053 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    1323              :          q_max = section_get_rval(section_vals=dft_section, &
    1324           30 :                                   keyword_name="PRINT%XRAY_DIFFRACTION_SPECTRUM%Q_MAX")
    1325              :          unit_nr = cp_print_key_unit_nr(logger=logger, &
    1326              :                                         basis_section=input, &
    1327              :                                         print_key_path="DFT%PRINT%XRAY_DIFFRACTION_SPECTRUM", &
    1328              :                                         extension=".dat", &
    1329              :                                         middle_name="xrd", &
    1330           30 :                                         log_filename=.FALSE.)
    1331           30 :          IF (output_unit > 0) THEN
    1332           15 :             INQUIRE (UNIT=unit_nr, NAME=filename)
    1333              :             WRITE (UNIT=output_unit, FMT="(/,/,T2,A)") &
    1334           15 :                "X-RAY DIFFRACTION SPECTRUM"
    1335           15 :             IF (unit_nr /= output_unit) THEN
    1336              :                WRITE (UNIT=output_unit, FMT="(/,T3,A,/,/,T3,A,/)") &
    1337           14 :                   "The coherent X-ray diffraction spectrum is written to the file:", &
    1338           28 :                   TRIM(filename)
    1339              :             END IF
    1340              :          END IF
    1341              :          CALL xray_diffraction_spectrum(qs_env=qs_env, &
    1342              :                                         unit_number=unit_nr, &
    1343           30 :                                         q_max=q_max)
    1344              :          CALL cp_print_key_finished_output(unit_nr=unit_nr, &
    1345              :                                            logger=logger, &
    1346              :                                            basis_section=input, &
    1347           30 :                                            print_key_path="DFT%PRINT%XRAY_DIFFRACTION_SPECTRUM")
    1348              :       END IF
    1349              : 
    1350        10053 :       CALL timestop(handle)
    1351              : 
    1352        10053 :    END SUBROUTINE qs_scf_post_xray
    1353              : 
    1354              : ! **************************************************************************************************
    1355              : !> \brief Computes and prints Electric Field Gradient
    1356              : !> \param input ...
    1357              : !> \param logger ...
    1358              : !> \param qs_env the qs_env in which the qs_env lives
    1359              : ! **************************************************************************************************
    1360        10053 :    SUBROUTINE qs_scf_post_efg(input, logger, qs_env)
    1361              :       TYPE(section_vals_type), POINTER                   :: input
    1362              :       TYPE(cp_logger_type), POINTER                      :: logger
    1363              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1364              : 
    1365              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'qs_scf_post_efg'
    1366              : 
    1367              :       INTEGER                                            :: handle
    1368              :       TYPE(section_vals_type), POINTER                   :: print_key
    1369              : 
    1370        10053 :       CALL timeset(routineN, handle)
    1371              : 
    1372              :       print_key => section_vals_get_subs_vals(section_vals=input, &
    1373        10053 :                                               subsection_name="DFT%PRINT%ELECTRIC_FIELD_GRADIENT")
    1374        10053 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), &
    1375              :                 cp_p_file)) THEN
    1376           30 :          CALL qs_efg_calc(qs_env=qs_env)
    1377              :       END IF
    1378              : 
    1379        10053 :       CALL timestop(handle)
    1380              : 
    1381        10053 :    END SUBROUTINE qs_scf_post_efg
    1382              : 
    1383              : ! **************************************************************************************************
    1384              : !> \brief Computes the Electron Transfer Coupling matrix element
    1385              : !> \param input ...
    1386              : !> \param qs_env the qs_env in which the qs_env lives
    1387              : !> \param dft_control ...
    1388              : ! **************************************************************************************************
    1389        20106 :    SUBROUTINE qs_scf_post_et(input, qs_env, dft_control)
    1390              :       TYPE(section_vals_type), POINTER                   :: input
    1391              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1392              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1393              : 
    1394              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'qs_scf_post_et'
    1395              : 
    1396              :       INTEGER                                            :: handle, ispin
    1397              :       LOGICAL                                            :: do_et
    1398        10053 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: my_mos
    1399              :       TYPE(section_vals_type), POINTER                   :: et_section
    1400              : 
    1401        10053 :       CALL timeset(routineN, handle)
    1402              : 
    1403              :       do_et = .FALSE.
    1404        10053 :       et_section => section_vals_get_subs_vals(input, "PROPERTIES%ET_COUPLING")
    1405        10053 :       CALL section_vals_get(et_section, explicit=do_et)
    1406        10053 :       IF (do_et) THEN
    1407           10 :          IF (qs_env%et_coupling%first_run) THEN
    1408           10 :             NULLIFY (my_mos)
    1409           50 :             ALLOCATE (my_mos(dft_control%nspins))
    1410           50 :             ALLOCATE (qs_env%et_coupling%et_mo_coeff(dft_control%nspins))
    1411           30 :             DO ispin = 1, dft_control%nspins
    1412              :                CALL cp_fm_create(matrix=my_mos(ispin), &
    1413              :                                  matrix_struct=qs_env%mos(ispin)%mo_coeff%matrix_struct, &
    1414           20 :                                  name="FIRST_RUN_COEFF"//TRIM(ADJUSTL(cp_to_string(ispin)))//"MATRIX")
    1415              :                CALL cp_fm_to_fm(qs_env%mos(ispin)%mo_coeff, &
    1416           30 :                                 my_mos(ispin))
    1417              :             END DO
    1418           10 :             CALL set_et_coupling_type(qs_env%et_coupling, et_mo_coeff=my_mos)
    1419           10 :             DEALLOCATE (my_mos)
    1420              :          END IF
    1421              :       END IF
    1422              : 
    1423        10053 :       CALL timestop(handle)
    1424              : 
    1425        10053 :    END SUBROUTINE qs_scf_post_et
    1426              : 
    1427              : ! **************************************************************************************************
    1428              : !> \brief compute the electron localization function
    1429              : !>
    1430              : !> \param input ...
    1431              : !> \param logger ...
    1432              : !> \param qs_env ...
    1433              : !> \par History
    1434              : !>      2012-07 Created [MI]
    1435              : ! **************************************************************************************************
    1436        10053 :    SUBROUTINE qs_scf_post_elf(input, logger, qs_env)
    1437              :       TYPE(section_vals_type), POINTER                   :: input
    1438              :       TYPE(cp_logger_type), POINTER                      :: logger
    1439              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1440              : 
    1441              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'qs_scf_post_elf'
    1442              : 
    1443              :       CHARACTER(LEN=default_path_length)                 :: filename, mpi_filename, my_pos_cube, &
    1444              :                                                             title
    1445              :       INTEGER                                            :: handle, ispin, output_unit, unit_nr
    1446              :       LOGICAL                                            :: append_cube, gapw, mpi_io
    1447              :       REAL(dp)                                           :: rho_cutoff
    1448              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1449              :       TYPE(particle_list_type), POINTER                  :: particles
    1450              :       TYPE(pw_env_type), POINTER                         :: pw_env
    1451        10053 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
    1452              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    1453        10053 :       TYPE(pw_r3d_rs_type), ALLOCATABLE, DIMENSION(:)    :: elf_r
    1454              :       TYPE(qs_subsys_type), POINTER                      :: subsys
    1455              :       TYPE(section_vals_type), POINTER                   :: elf_section
    1456              : 
    1457        10053 :       CALL timeset(routineN, handle)
    1458        10053 :       output_unit = cp_logger_get_default_io_unit(logger)
    1459              : 
    1460        10053 :       elf_section => section_vals_get_subs_vals(input, "DFT%PRINT%ELF_CUBE")
    1461        10053 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    1462              :                                            "DFT%PRINT%ELF_CUBE"), cp_p_file)) THEN
    1463              : 
    1464           80 :          NULLIFY (dft_control, pw_env, auxbas_pw_pool, pw_pools, particles, subsys)
    1465           80 :          CALL get_qs_env(qs_env, dft_control=dft_control, pw_env=pw_env, subsys=subsys)
    1466           80 :          CALL qs_subsys_get(subsys, particles=particles)
    1467              : 
    1468           80 :          gapw = dft_control%qs_control%gapw
    1469           80 :          IF (.NOT. gapw) THEN
    1470              :             ! allocate
    1471          322 :             ALLOCATE (elf_r(dft_control%nspins))
    1472              :             CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
    1473           80 :                             pw_pools=pw_pools)
    1474          162 :             DO ispin = 1, dft_control%nspins
    1475           82 :                CALL auxbas_pw_pool%create_pw(elf_r(ispin))
    1476          162 :                CALL pw_zero(elf_r(ispin))
    1477              :             END DO
    1478              : 
    1479           80 :             IF (output_unit > 0) THEN
    1480              :                WRITE (UNIT=output_unit, FMT="(/,T15,A,/)") &
    1481           40 :                   " ----- ELF is computed on the real space grid -----"
    1482              :             END IF
    1483           80 :             rho_cutoff = section_get_rval(elf_section, "density_cutoff")
    1484           80 :             CALL qs_elf_calc(qs_env, elf_r, rho_cutoff)
    1485              : 
    1486              :             ! write ELF into cube file
    1487           80 :             append_cube = section_get_lval(elf_section, "APPEND")
    1488           80 :             my_pos_cube = "REWIND"
    1489           80 :             IF (append_cube) THEN
    1490            0 :                my_pos_cube = "APPEND"
    1491              :             END IF
    1492              : 
    1493          162 :             DO ispin = 1, dft_control%nspins
    1494           82 :                WRITE (filename, '(a5,I1.1)') "ELF_S", ispin
    1495           82 :                WRITE (title, *) "ELF spin ", ispin
    1496           82 :                mpi_io = .TRUE.
    1497              :                unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%ELF_CUBE", extension=".cube", &
    1498              :                                               middle_name=TRIM(filename), file_position=my_pos_cube, log_filename=.FALSE., &
    1499           82 :                                               mpi_io=mpi_io, fout=mpi_filename)
    1500           82 :                IF (output_unit > 0) THEN
    1501           41 :                   IF (.NOT. mpi_io) THEN
    1502            0 :                      INQUIRE (UNIT=unit_nr, NAME=filename)
    1503              :                   ELSE
    1504           41 :                      filename = mpi_filename
    1505              :                   END IF
    1506              :                   WRITE (UNIT=output_unit, FMT="(/,T2,A,/,/,T2,A)") &
    1507           41 :                      "ELF is written in cube file format to the file:", &
    1508           82 :                      TRIM(filename)
    1509              :                END IF
    1510              : 
    1511              :                CALL cp_pw_to_cube(elf_r(ispin), unit_nr, title, particles=particles, &
    1512           82 :                                   stride=section_get_ivals(elf_section, "STRIDE"), mpi_io=mpi_io)
    1513           82 :                CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%ELF_CUBE", mpi_io=mpi_io)
    1514              : 
    1515          162 :                CALL auxbas_pw_pool%give_back_pw(elf_r(ispin))
    1516              :             END DO
    1517              : 
    1518              :             ! deallocate
    1519           80 :             DEALLOCATE (elf_r)
    1520              : 
    1521              :          ELSE
    1522              :             ! not implemented
    1523            0 :             CPWARN("ELF not implemented for GAPW calculations!")
    1524              :          END IF
    1525              : 
    1526              :       END IF ! print key
    1527              : 
    1528        10053 :       CALL timestop(handle)
    1529              : 
    1530        20106 :    END SUBROUTINE qs_scf_post_elf
    1531              : 
    1532              : ! **************************************************************************************************
    1533              : !> \brief computes the condition number of the overlap matrix and
    1534              : !>      prints the value of the total energy. This is needed
    1535              : !>      for BASIS_MOLOPT optimizations
    1536              : !> \param input ...
    1537              : !> \param logger ...
    1538              : !> \param qs_env the qs_env in which the qs_env lives
    1539              : !> \par History
    1540              : !>      2007-07 Created [Joost VandeVondele]
    1541              : ! **************************************************************************************************
    1542        10053 :    SUBROUTINE qs_scf_post_molopt(input, logger, qs_env)
    1543              :       TYPE(section_vals_type), POINTER                   :: input
    1544              :       TYPE(cp_logger_type), POINTER                      :: logger
    1545              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1546              : 
    1547              :       CHARACTER(len=*), PARAMETER :: routineN = 'qs_scf_post_molopt'
    1548              : 
    1549              :       INTEGER                                            :: handle, nao, unit_nr
    1550              :       REAL(KIND=dp)                                      :: S_cond_number
    1551        10053 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eigenvalues
    1552              :       TYPE(cp_fm_struct_type), POINTER                   :: ao_ao_fmstruct
    1553              :       TYPE(cp_fm_type)                                   :: fm_s, fm_work
    1554              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    1555        10053 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
    1556        10053 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    1557              :       TYPE(qs_energy_type), POINTER                      :: energy
    1558              :       TYPE(section_vals_type), POINTER                   :: print_key
    1559              : 
    1560        10053 :       CALL timeset(routineN, handle)
    1561              : 
    1562              :       print_key => section_vals_get_subs_vals(section_vals=input, &
    1563        10053 :                                               subsection_name="DFT%PRINT%BASIS_MOLOPT_QUANTITIES")
    1564        10053 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), &
    1565              :                 cp_p_file)) THEN
    1566              : 
    1567           28 :          CALL get_qs_env(qs_env, energy=energy, matrix_s=matrix_s, mos=mos)
    1568              : 
    1569              :          ! set up the two needed full matrices, using mo_coeff as a template
    1570           28 :          CALL get_mo_set(mo_set=mos(1), mo_coeff=mo_coeff, nao=nao)
    1571              :          CALL cp_fm_struct_create(fmstruct=ao_ao_fmstruct, &
    1572              :                                   nrow_global=nao, ncol_global=nao, &
    1573           28 :                                   template_fmstruct=mo_coeff%matrix_struct)
    1574              :          CALL cp_fm_create(fm_s, matrix_struct=ao_ao_fmstruct, &
    1575           28 :                            name="fm_s")
    1576              :          CALL cp_fm_create(fm_work, matrix_struct=ao_ao_fmstruct, &
    1577           28 :                            name="fm_work")
    1578           28 :          CALL cp_fm_struct_release(ao_ao_fmstruct)
    1579           84 :          ALLOCATE (eigenvalues(nao))
    1580              : 
    1581           28 :          CALL copy_dbcsr_to_fm(matrix_s(1)%matrix, fm_s)
    1582           28 :          CALL choose_eigv_solver(fm_s, fm_work, eigenvalues)
    1583              : 
    1584           28 :          CALL cp_fm_release(fm_s)
    1585           28 :          CALL cp_fm_release(fm_work)
    1586              : 
    1587         1048 :          S_cond_number = MAXVAL(ABS(eigenvalues))/MAX(MINVAL(ABS(eigenvalues)), EPSILON(0.0_dp))
    1588              : 
    1589              :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%BASIS_MOLOPT_QUANTITIES", &
    1590           28 :                                         extension=".molopt")
    1591              : 
    1592           28 :          IF (unit_nr > 0) THEN
    1593              :             ! please keep this format fixed, needs to be grepable for molopt
    1594              :             ! optimizations
    1595           14 :             WRITE (unit_nr, '(T2,A28,2A25)') "", "Tot. Ener.", "S Cond. Numb."
    1596           14 :             WRITE (unit_nr, '(T2,A28,2E25.17)') "BASIS_MOLOPT_QUANTITIES", energy%total, S_cond_number
    1597              :          END IF
    1598              : 
    1599              :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
    1600           84 :                                            "DFT%PRINT%BASIS_MOLOPT_QUANTITIES")
    1601              : 
    1602              :       END IF
    1603              : 
    1604        10053 :       CALL timestop(handle)
    1605              : 
    1606        20106 :    END SUBROUTINE qs_scf_post_molopt
    1607              : 
    1608              : ! **************************************************************************************************
    1609              : !> \brief Dumps EPR
    1610              : !> \param input ...
    1611              : !> \param logger ...
    1612              : !> \param qs_env the qs_env in which the qs_env lives
    1613              : ! **************************************************************************************************
    1614        10053 :    SUBROUTINE qs_scf_post_epr(input, logger, qs_env)
    1615              :       TYPE(section_vals_type), POINTER                   :: input
    1616              :       TYPE(cp_logger_type), POINTER                      :: logger
    1617              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1618              : 
    1619              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'qs_scf_post_epr'
    1620              : 
    1621              :       INTEGER                                            :: handle
    1622              :       TYPE(section_vals_type), POINTER                   :: print_key
    1623              : 
    1624        10053 :       CALL timeset(routineN, handle)
    1625              : 
    1626              :       print_key => section_vals_get_subs_vals(section_vals=input, &
    1627        10053 :                                               subsection_name="DFT%PRINT%HYPERFINE_COUPLING_TENSOR")
    1628        10053 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), &
    1629              :                 cp_p_file)) THEN
    1630           30 :          CALL qs_epr_hyp_calc(qs_env=qs_env)
    1631              :       END IF
    1632              : 
    1633        10053 :       CALL timestop(handle)
    1634              : 
    1635        10053 :    END SUBROUTINE qs_scf_post_epr
    1636              : 
    1637              : ! **************************************************************************************************
    1638              : !> \brief Interface routine to trigger writing of results available from normal
    1639              : !>        SCF. Can write MO-dependent and MO free results (needed for call from
    1640              : !>        the linear scaling code)
    1641              : !> \param qs_env the qs_env in which the qs_env lives
    1642              : !> \param scf_env ...
    1643              : ! **************************************************************************************************
    1644        10053 :    SUBROUTINE write_available_results(qs_env, scf_env)
    1645              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1646              :       TYPE(qs_scf_env_type), OPTIONAL, POINTER           :: scf_env
    1647              : 
    1648              :       CHARACTER(len=*), PARAMETER :: routineN = 'write_available_results'
    1649              : 
    1650              :       INTEGER                                            :: handle
    1651              : 
    1652        10053 :       CALL timeset(routineN, handle)
    1653              : 
    1654              :       ! those properties that require MOs (not suitable density matrix based methods)
    1655        10053 :       CALL write_mo_dependent_results(qs_env, scf_env)
    1656              : 
    1657              :       ! those that depend only on the density matrix, they should be linear scaling in their implementation
    1658        10053 :       CALL write_mo_free_results(qs_env)
    1659              : 
    1660        10053 :       CALL timestop(handle)
    1661              : 
    1662        10053 :    END SUBROUTINE write_available_results
    1663              : 
    1664              : ! **************************************************************************************************
    1665              : !> \brief Write QS results available if MO's are present (if switched on through the print_keys)
    1666              : !>        Writes only MO dependent results. Split is necessary as ls_scf does not
    1667              : !>        provide MO's
    1668              : !> \param qs_env the qs_env in which the qs_env lives
    1669              : !> \param scf_env ...
    1670              : ! **************************************************************************************************
    1671        10365 :    SUBROUTINE write_mo_dependent_results(qs_env, scf_env)
    1672              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1673              :       TYPE(qs_scf_env_type), OPTIONAL, POINTER           :: scf_env
    1674              : 
    1675              :       CHARACTER(len=*), PARAMETER :: routineN = 'write_mo_dependent_results'
    1676              : 
    1677              :       INTEGER                                            :: handle, homo, ispin, nmo, output_unit
    1678              :       LOGICAL                                            :: all_equal, do_kpoints, explicit
    1679              :       REAL(KIND=dp)                                      :: maxocc, s_square, s_square_ideal, &
    1680              :                                                             total_abs_spin_dens, total_spin_dens
    1681        10365 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mo_eigenvalues, occupation_numbers
    1682              :       TYPE(admm_type), POINTER                           :: admm_env
    1683        10365 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1684              :       TYPE(cell_type), POINTER                           :: cell
    1685              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    1686              :       TYPE(cp_logger_type), POINTER                      :: logger
    1687        10365 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: ks_rmpv, matrix_s
    1688              :       TYPE(dbcsr_type), POINTER                          :: mo_coeff_deriv
    1689              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1690        10365 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    1691        10365 :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
    1692              :       TYPE(particle_list_type), POINTER                  :: particles
    1693        10365 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1694              :       TYPE(pw_env_type), POINTER                         :: pw_env
    1695        10365 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
    1696              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    1697              :       TYPE(pw_r3d_rs_type)                               :: wf_r
    1698        10365 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r
    1699              :       TYPE(qs_energy_type), POINTER                      :: energy
    1700        10365 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1701              :       TYPE(qs_rho_type), POINTER                         :: rho
    1702              :       TYPE(qs_subsys_type), POINTER                      :: subsys
    1703              :       TYPE(scf_control_type), POINTER                    :: scf_control
    1704              :       TYPE(section_vals_type), POINTER                   :: dft_section, input, sprint_section, &
    1705              :                                                             trexio_section
    1706              : 
    1707              : ! TYPE(kpoint_type), POINTER                         :: kpoints
    1708              : 
    1709        10365 :       CALL timeset(routineN, handle)
    1710              : 
    1711        10365 :       NULLIFY (cell, dft_control, pw_env, auxbas_pw_pool, pw_pools, mo_coeff, &
    1712        10365 :                mo_coeff_deriv, mo_eigenvalues, mos, atomic_kind_set, qs_kind_set, &
    1713        10365 :                particle_set, rho, ks_rmpv, matrix_s, scf_control, dft_section, &
    1714        10365 :                molecule_set, input, particles, subsys, rho_r)
    1715              : 
    1716        10365 :       logger => cp_get_default_logger()
    1717        10365 :       output_unit = cp_logger_get_default_io_unit(logger)
    1718              : 
    1719        10365 :       CPASSERT(ASSOCIATED(qs_env))
    1720              :       CALL get_qs_env(qs_env, &
    1721              :                       dft_control=dft_control, &
    1722              :                       molecule_set=molecule_set, &
    1723              :                       atomic_kind_set=atomic_kind_set, &
    1724              :                       particle_set=particle_set, &
    1725              :                       qs_kind_set=qs_kind_set, &
    1726              :                       admm_env=admm_env, &
    1727              :                       scf_control=scf_control, &
    1728              :                       input=input, &
    1729              :                       cell=cell, &
    1730        10365 :                       subsys=subsys)
    1731        10365 :       CALL qs_subsys_get(subsys, particles=particles)
    1732        10365 :       CALL get_qs_env(qs_env, rho=rho)
    1733        10365 :       CALL qs_rho_get(rho, rho_r=rho_r)
    1734              : 
    1735              :       ! k points
    1736        10365 :       CALL get_qs_env(qs_env, do_kpoints=do_kpoints)
    1737              : 
    1738              :       ! Write last MO information to output file if requested
    1739        10365 :       dft_section => section_vals_get_subs_vals(input, "DFT")
    1740        10365 :       IF (.NOT. qs_env%run_rtp) THEN
    1741        10053 :          CALL qs_scf_write_mos(qs_env, scf_env, final_mos=.TRUE.)
    1742        10053 :          trexio_section => section_vals_get_subs_vals(dft_section, "PRINT%TREXIO")
    1743        10053 :          CALL section_vals_get(trexio_section, explicit=explicit)
    1744        10053 :          IF (explicit) THEN
    1745            8 :             CALL write_trexio(qs_env, trexio_section)
    1746              :          END IF
    1747        10053 :          IF (.NOT. do_kpoints) THEN
    1748         9833 :             CALL get_qs_env(qs_env, mos=mos, matrix_ks=ks_rmpv)
    1749         9833 :             CALL write_dm_binary_restart(mos, dft_section, ks_rmpv)
    1750         9833 :             sprint_section => section_vals_get_subs_vals(dft_section, "PRINT%MO_MOLDEN")
    1751         9833 :             CALL write_mos_molden(mos, qs_kind_set, particle_set, sprint_section)
    1752              :             ! Write Chargemol .wfx
    1753         9833 :             IF (BTEST(cp_print_key_should_output(logger%iter_info, &
    1754              :                                                  dft_section, "PRINT%CHARGEMOL"), &
    1755              :                       cp_p_file)) THEN
    1756            2 :                CALL write_wfx(qs_env, dft_section)
    1757              :             END IF
    1758              :          END IF
    1759              : 
    1760              :          ! DOS printout after the SCF cycle is completed
    1761        10053 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, dft_section, "PRINT%DOS") &
    1762              :                    , cp_p_file)) THEN
    1763           42 :             IF (do_kpoints) THEN
    1764            2 :                CALL calculate_dos_kp(qs_env, dft_section)
    1765              :             ELSE
    1766           40 :                CALL get_qs_env(qs_env, mos=mos)
    1767           40 :                CALL calculate_dos(mos, dft_section)
    1768              :             END IF
    1769              :          END IF
    1770              : 
    1771              :          ! Print the projected density of states (pDOS) for each atomic kind
    1772        10053 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, dft_section, "PRINT%PDOS"), &
    1773              :                    cp_p_file)) THEN
    1774           48 :             IF (do_kpoints) THEN
    1775            0 :                CPWARN("Projected density of states (pDOS) is not implemented for k points")
    1776              :             ELSE
    1777              :                CALL get_qs_env(qs_env, &
    1778              :                                mos=mos, &
    1779           48 :                                matrix_ks=ks_rmpv)
    1780           96 :                DO ispin = 1, dft_control%nspins
    1781              :                   ! With ADMM, we have to modify the Kohn-Sham matrix
    1782           48 :                   IF (dft_control%do_admm) THEN
    1783            0 :                      CALL admm_correct_for_eigenvalues(ispin, admm_env, ks_rmpv(ispin)%matrix)
    1784              :                   END IF
    1785           48 :                   IF (PRESENT(scf_env)) THEN
    1786           48 :                      IF (scf_env%method == ot_method_nr) THEN
    1787              :                         CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, &
    1788            8 :                                         eigenvalues=mo_eigenvalues)
    1789            8 :                         IF (ASSOCIATED(qs_env%mo_derivs)) THEN
    1790            8 :                            mo_coeff_deriv => qs_env%mo_derivs(ispin)%matrix
    1791              :                         ELSE
    1792            0 :                            mo_coeff_deriv => NULL()
    1793              :                         END IF
    1794              :                         CALL calculate_subspace_eigenvalues(mo_coeff, ks_rmpv(ispin)%matrix, mo_eigenvalues, &
    1795              :                                                             do_rotation=.TRUE., &
    1796            8 :                                                             co_rotate_dbcsr=mo_coeff_deriv)
    1797            8 :                         CALL set_mo_occupation(mo_set=mos(ispin))
    1798              :                      END IF
    1799              :                   END IF
    1800           48 :                   IF (dft_control%nspins == 2) THEN
    1801              :                      CALL calculate_projected_dos(mos(ispin), atomic_kind_set, &
    1802            0 :                                                   qs_kind_set, particle_set, qs_env, dft_section, ispin=ispin)
    1803              :                   ELSE
    1804              :                      CALL calculate_projected_dos(mos(ispin), atomic_kind_set, &
    1805           48 :                                                   qs_kind_set, particle_set, qs_env, dft_section)
    1806              :                   END IF
    1807              :                   ! With ADMM, we have to undo the modification of the Kohn-Sham matrix
    1808           96 :                   IF (dft_control%do_admm) THEN
    1809            0 :                      CALL admm_uncorrect_for_eigenvalues(ispin, admm_env, ks_rmpv(ispin)%matrix)
    1810              :                   END IF
    1811              :                END DO
    1812              :             END IF
    1813              :          END IF
    1814              :       END IF
    1815              : 
    1816              :       ! Integrated absolute spin density and spin contamination ***
    1817        10365 :       IF (dft_control%nspins == 2) THEN
    1818         1982 :          CALL get_qs_env(qs_env, mos=mos)
    1819         1982 :          CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
    1820              :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
    1821         1982 :                          pw_pools=pw_pools)
    1822         1982 :          CALL auxbas_pw_pool%create_pw(wf_r)
    1823         1982 :          CALL pw_copy(rho_r(1), wf_r)
    1824         1982 :          CALL pw_axpy(rho_r(2), wf_r, alpha=-1._dp)
    1825         1982 :          total_spin_dens = pw_integrate_function(wf_r)
    1826         1982 :          IF (output_unit > 0) WRITE (UNIT=output_unit, FMT='(/,(T3,A,T61,F20.10))') &
    1827         1014 :             "Integrated spin density: ", total_spin_dens
    1828         1982 :          total_abs_spin_dens = pw_integrate_function(wf_r, oprt="ABS")
    1829         1982 :          IF (output_unit > 0) WRITE (UNIT=output_unit, FMT='((T3,A,T61,F20.10))') &
    1830         1014 :             "Integrated absolute spin density: ", total_abs_spin_dens
    1831         1982 :          CALL auxbas_pw_pool%give_back_pw(wf_r)
    1832              :          !
    1833              :          ! XXX Fix Me XXX
    1834              :          ! should be extended to the case where added MOs are present
    1835              :          ! should be extended to the k-point case
    1836              :          !
    1837         1982 :          IF (do_kpoints) THEN
    1838           30 :             CPWARN("Spin contamination estimate not implemented for k-points.")
    1839              :          ELSE
    1840         1952 :             all_equal = .TRUE.
    1841         5856 :             DO ispin = 1, dft_control%nspins
    1842              :                CALL get_mo_set(mo_set=mos(ispin), &
    1843              :                                occupation_numbers=occupation_numbers, &
    1844              :                                homo=homo, &
    1845              :                                nmo=nmo, &
    1846         3904 :                                maxocc=maxocc)
    1847         5856 :                IF (nmo > 0) THEN
    1848              :                   all_equal = all_equal .AND. &
    1849              :                               (ALL(occupation_numbers(1:homo) == maxocc) .AND. &
    1850        22302 :                                ALL(occupation_numbers(homo + 1:nmo) == 0.0_dp))
    1851              :                END IF
    1852              :             END DO
    1853         1952 :             IF (.NOT. all_equal) THEN
    1854          106 :                IF (output_unit > 0) WRITE (UNIT=output_unit, FMT="(T3,A)") &
    1855           53 :                   "WARNING: S**2 computation does not yet treat fractional occupied orbitals"
    1856              :             ELSE
    1857              :                CALL get_qs_env(qs_env=qs_env, &
    1858              :                                matrix_s=matrix_s, &
    1859         1846 :                                energy=energy)
    1860              :                CALL compute_s_square(mos=mos, matrix_s=matrix_s, s_square=s_square, &
    1861         1846 :                                      s_square_ideal=s_square_ideal)
    1862         1846 :                IF (output_unit > 0) WRITE (UNIT=output_unit, FMT='(T3,A,T51,2F15.6)') &
    1863          946 :                   "Ideal and single determinant S**2 : ", s_square_ideal, s_square
    1864         1846 :                energy%s_square = s_square
    1865              :             END IF
    1866              :          END IF
    1867              :       END IF
    1868              : 
    1869        10365 :       CALL timestop(handle)
    1870              : 
    1871        10365 :    END SUBROUTINE write_mo_dependent_results
    1872              : 
    1873              : ! **************************************************************************************************
    1874              : !> \brief Write QS results always available (if switched on through the print_keys)
    1875              : !>        Can be called from ls_scf
    1876              : !> \param qs_env the qs_env in which the qs_env lives
    1877              : ! **************************************************************************************************
    1878        11299 :    SUBROUTINE write_mo_free_results(qs_env)
    1879              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1880              : 
    1881              :       CHARACTER(len=*), PARAMETER :: routineN = 'write_mo_free_results'
    1882              :       CHARACTER(len=1), DIMENSION(3), PARAMETER          :: cdir = ["x", "y", "z"]
    1883              : 
    1884              :       CHARACTER(LEN=2)                                   :: element_symbol
    1885              :       CHARACTER(LEN=default_path_length)                 :: filename, mpi_filename, my_pos_cube, &
    1886              :                                                             my_pos_voro
    1887              :       CHARACTER(LEN=default_string_length)               :: name, print_density
    1888              :       INTEGER :: after, handle, i, iat, iatom, id, ikind, img, iso, ispin, iw, l, n_rep_hf, nat, &
    1889              :          natom, nd(3), ngto, niso, nkind, np, nr, output_unit, print_level, should_print_bqb, &
    1890              :          should_print_voro, unit_nr, unit_nr_voro
    1891              :       LOGICAL :: append_cube, append_voro, do_hfx, do_kpoints, mpi_io, omit_headers, print_it, &
    1892              :          rho_r_valid, voro_print_txt, write_ks, write_xc, xrd_interface
    1893              :       REAL(KIND=dp)                                      :: norm_factor, q_max, rho_hard, rho_soft, &
    1894              :                                                             rho_total, rho_total_rspace, udvol, &
    1895              :                                                             volume, zeff
    1896        11299 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: zcharge
    1897        11299 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: bfun
    1898        11299 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: aedens, ccdens, ppdens
    1899              :       REAL(KIND=dp), DIMENSION(3)                        :: dr
    1900        11299 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: my_Q0
    1901        11299 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1902              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
    1903              :       TYPE(cell_type), POINTER                           :: cell
    1904              :       TYPE(cp_logger_type), POINTER                      :: logger
    1905        11299 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_hr
    1906        11299 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: ks_rmpv, matrix_vxc, rho_ao
    1907              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1908              :       TYPE(grid_atom_type), POINTER                      :: grid_atom
    1909              :       TYPE(iao_env_type)                                 :: iao_env
    1910              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1911              :       TYPE(particle_list_type), POINTER                  :: particles
    1912        11299 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1913              :       TYPE(pw_c1d_gs_type)                               :: aux_g, rho_elec_gspace
    1914              :       TYPE(pw_c1d_gs_type), POINTER                      :: rho0_s_gs, rho_core, rhoz_cneo_s_gs
    1915              :       TYPE(pw_env_type), POINTER                         :: pw_env
    1916        11299 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
    1917              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    1918              :       TYPE(pw_r3d_rs_type)                               :: aux_r, rho_elec_rspace, wf_r
    1919        11299 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r
    1920              :       TYPE(pw_r3d_rs_type), POINTER                      :: mb_rho, v_hartree_rspace, vee
    1921        11299 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1922              :       TYPE(qs_kind_type), POINTER                        :: qs_kind
    1923              :       TYPE(qs_rho_type), POINTER                         :: rho
    1924              :       TYPE(qs_subsys_type), POINTER                      :: subsys
    1925              :       TYPE(rho0_mpole_type), POINTER                     :: rho0_mpole
    1926        11299 :       TYPE(rho_atom_type), DIMENSION(:), POINTER         :: rho_atom_set
    1927              :       TYPE(rho_atom_type), POINTER                       :: rho_atom
    1928              :       TYPE(section_vals_type), POINTER                   :: dft_section, hfx_section, input, &
    1929              :                                                             print_key, print_key_bqb, &
    1930              :                                                             print_key_voro, xc_section
    1931              : 
    1932        11299 :       CALL timeset(routineN, handle)
    1933        11299 :       NULLIFY (cell, dft_control, pw_env, auxbas_pw_pool, pw_pools, hfx_section, &
    1934        11299 :                atomic_kind_set, qs_kind_set, particle_set, rho, ks_rmpv, rho_ao, rho_r, &
    1935        11299 :                dft_section, xc_section, input, particles, subsys, matrix_vxc, v_hartree_rspace, &
    1936        11299 :                vee)
    1937              : 
    1938        11299 :       logger => cp_get_default_logger()
    1939        11299 :       output_unit = cp_logger_get_default_io_unit(logger)
    1940              : 
    1941        11299 :       CPASSERT(ASSOCIATED(qs_env))
    1942              :       CALL get_qs_env(qs_env, &
    1943              :                       atomic_kind_set=atomic_kind_set, &
    1944              :                       qs_kind_set=qs_kind_set, &
    1945              :                       particle_set=particle_set, &
    1946              :                       cell=cell, &
    1947              :                       para_env=para_env, &
    1948              :                       dft_control=dft_control, &
    1949              :                       input=input, &
    1950              :                       do_kpoints=do_kpoints, &
    1951        11299 :                       subsys=subsys)
    1952        11299 :       dft_section => section_vals_get_subs_vals(input, "DFT")
    1953        11299 :       CALL qs_subsys_get(subsys, particles=particles)
    1954              : 
    1955        11299 :       CALL get_qs_env(qs_env, rho=rho)
    1956        11299 :       CALL qs_rho_get(rho, rho_r=rho_r)
    1957              : 
    1958        11299 :       CALL get_qs_env(qs_env, nkind=nkind, natom=natom)
    1959        33897 :       ALLOCATE (zcharge(natom))
    1960        31651 :       DO ikind = 1, nkind
    1961        20352 :          CALL get_qs_kind(qs_kind_set(ikind), zeff=zeff)
    1962        20352 :          CALL get_atomic_kind(atomic_kind_set(ikind), natom=nat)
    1963        74842 :          DO iatom = 1, nat
    1964        43191 :             iat = atomic_kind_set(ikind)%atom_list(iatom)
    1965        63543 :             zcharge(iat) = zeff
    1966              :          END DO
    1967              :       END DO
    1968              : 
    1969              :       ! Print the total density (electronic + core charge)
    1970        11299 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    1971              :                                            "DFT%PRINT%TOT_DENSITY_CUBE"), cp_p_file)) THEN
    1972           82 :          NULLIFY (rho_core, rho0_s_gs, rhoz_cneo_s_gs)
    1973           82 :          append_cube = section_get_lval(input, "DFT%PRINT%TOT_DENSITY_CUBE%APPEND")
    1974           82 :          my_pos_cube = "REWIND"
    1975           82 :          IF (append_cube) THEN
    1976            0 :             my_pos_cube = "APPEND"
    1977              :          END IF
    1978              : 
    1979              :          CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, rho_core=rho_core, &
    1980           82 :                          rho0_s_gs=rho0_s_gs, rhoz_cneo_s_gs=rhoz_cneo_s_gs)
    1981              :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
    1982           82 :                          pw_pools=pw_pools)
    1983           82 :          CALL auxbas_pw_pool%create_pw(wf_r)
    1984           82 :          IF (dft_control%qs_control%gapw) THEN
    1985            0 :             IF (dft_control%qs_control%gapw_control%nopaw_as_gpw) THEN
    1986            0 :                CALL pw_axpy(rho_core, rho0_s_gs)
    1987            0 :                IF (ASSOCIATED(rhoz_cneo_s_gs)) THEN
    1988            0 :                   CALL pw_axpy(rhoz_cneo_s_gs, rho0_s_gs)
    1989              :                END IF
    1990            0 :                CALL pw_transfer(rho0_s_gs, wf_r)
    1991            0 :                CALL pw_axpy(rho_core, rho0_s_gs, -1.0_dp)
    1992            0 :                IF (ASSOCIATED(rhoz_cneo_s_gs)) THEN
    1993            0 :                   CALL pw_axpy(rhoz_cneo_s_gs, rho0_s_gs, -1.0_dp)
    1994              :                END IF
    1995              :             ELSE
    1996            0 :                IF (ASSOCIATED(rhoz_cneo_s_gs)) THEN
    1997            0 :                   CALL pw_axpy(rhoz_cneo_s_gs, rho0_s_gs)
    1998              :                END IF
    1999            0 :                CALL pw_transfer(rho0_s_gs, wf_r)
    2000            0 :                IF (ASSOCIATED(rhoz_cneo_s_gs)) THEN
    2001            0 :                   CALL pw_axpy(rhoz_cneo_s_gs, rho0_s_gs, -1.0_dp)
    2002              :                END IF
    2003              :             END IF
    2004              :          ELSE
    2005           82 :             CALL pw_transfer(rho_core, wf_r)
    2006              :          END IF
    2007          164 :          DO ispin = 1, dft_control%nspins
    2008          164 :             CALL pw_axpy(rho_r(ispin), wf_r)
    2009              :          END DO
    2010           82 :          filename = "TOTAL_DENSITY"
    2011           82 :          mpi_io = .TRUE.
    2012              :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%TOT_DENSITY_CUBE", &
    2013              :                                         extension=".cube", middle_name=TRIM(filename), file_position=my_pos_cube, &
    2014           82 :                                         log_filename=.FALSE., mpi_io=mpi_io)
    2015              :          CALL cp_pw_to_cube(wf_r, unit_nr, "TOTAL DENSITY", &
    2016              :                             particles=particles, zeff=zcharge, &
    2017           82 :                             stride=section_get_ivals(dft_section, "PRINT%TOT_DENSITY_CUBE%STRIDE"), mpi_io=mpi_io)
    2018              :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
    2019           82 :                                            "DFT%PRINT%TOT_DENSITY_CUBE", mpi_io=mpi_io)
    2020           82 :          CALL auxbas_pw_pool%give_back_pw(wf_r)
    2021              :       END IF
    2022              : 
    2023              :       ! Write cube file with electron density
    2024        11299 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    2025              :                                            "DFT%PRINT%E_DENSITY_CUBE"), cp_p_file)) THEN
    2026              :          CALL section_vals_val_get(dft_section, &
    2027              :                                    keyword_name="PRINT%E_DENSITY_CUBE%DENSITY_INCLUDE", &
    2028          150 :                                    c_val=print_density)
    2029              :          print_density = TRIM(print_density)
    2030          150 :          append_cube = section_get_lval(input, "DFT%PRINT%E_DENSITY_CUBE%APPEND")
    2031          150 :          my_pos_cube = "REWIND"
    2032          150 :          IF (append_cube) THEN
    2033            0 :             my_pos_cube = "APPEND"
    2034              :          END IF
    2035              :          ! Write the info on core densities for the interface between cp2k and the XRD code
    2036              :          ! together with the valence density they are used to compute the form factor (Fourier transform)
    2037          150 :          xrd_interface = section_get_lval(input, "DFT%PRINT%E_DENSITY_CUBE%XRD_INTERFACE")
    2038          150 :          IF (xrd_interface) THEN
    2039              :             !cube file only contains soft density (GAPW)
    2040            2 :             IF (dft_control%qs_control%gapw) print_density = "SOFT_DENSITY"
    2041              : 
    2042            2 :             filename = "ELECTRON_DENSITY"
    2043              :             unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%E_DENSITY_CUBE", &
    2044              :                                            extension=".xrd", middle_name=TRIM(filename), &
    2045            2 :                                            file_position=my_pos_cube, log_filename=.FALSE.)
    2046            2 :             ngto = section_get_ival(input, "DFT%PRINT%E_DENSITY_CUBE%NGAUSS")
    2047            2 :             IF (output_unit > 0) THEN
    2048            1 :                INQUIRE (UNIT=unit_nr, NAME=filename)
    2049              :                WRITE (UNIT=output_unit, FMT="(/,T2,A,/,/,T2,A)") &
    2050            1 :                   "The electron density (atomic part) is written to the file:", &
    2051            2 :                   TRIM(filename)
    2052              :             END IF
    2053              : 
    2054            2 :             xc_section => section_vals_get_subs_vals(input, "DFT%XC")
    2055            2 :             nkind = SIZE(atomic_kind_set)
    2056            2 :             IF (unit_nr > 0) THEN
    2057            1 :                WRITE (unit_nr, *) "Atomic (core) densities"
    2058            1 :                WRITE (unit_nr, *) "Unit cell"
    2059            1 :                WRITE (unit_nr, FMT="(3F20.12)") cell%hmat(1, 1), cell%hmat(1, 2), cell%hmat(1, 3)
    2060            1 :                WRITE (unit_nr, FMT="(3F20.12)") cell%hmat(2, 1), cell%hmat(2, 2), cell%hmat(2, 3)
    2061            1 :                WRITE (unit_nr, FMT="(3F20.12)") cell%hmat(3, 1), cell%hmat(3, 2), cell%hmat(3, 3)
    2062            1 :                WRITE (unit_nr, *) "Atomic types"
    2063            1 :                WRITE (unit_nr, *) nkind
    2064              :             END IF
    2065              :             ! calculate atomic density and core density
    2066           16 :             ALLOCATE (ppdens(ngto, 2, nkind), aedens(ngto, 2, nkind), ccdens(ngto, 2, nkind))
    2067            6 :             DO ikind = 1, nkind
    2068            4 :                atomic_kind => atomic_kind_set(ikind)
    2069            4 :                qs_kind => qs_kind_set(ikind)
    2070            4 :                CALL get_atomic_kind(atomic_kind, name=name, element_symbol=element_symbol)
    2071              :                CALL calculate_atomic_density(ppdens(:, :, ikind), atomic_kind, qs_kind, ngto, &
    2072            4 :                                              iunit=output_unit, confine=.TRUE.)
    2073              :                CALL calculate_atomic_density(aedens(:, :, ikind), atomic_kind, qs_kind, ngto, &
    2074            4 :                                              iunit=output_unit, allelectron=.TRUE., confine=.TRUE.)
    2075           52 :                ccdens(:, 1, ikind) = aedens(:, 1, ikind)
    2076           52 :                ccdens(:, 2, ikind) = 0._dp
    2077              :                CALL project_function_a(ccdens(1:ngto, 2, ikind), ccdens(1:ngto, 1, ikind), &
    2078            4 :                                        ppdens(1:ngto, 2, ikind), ppdens(1:ngto, 1, ikind), 0)
    2079           52 :                ccdens(:, 2, ikind) = aedens(:, 2, ikind) - ccdens(:, 2, ikind)
    2080            4 :                IF (unit_nr > 0) THEN
    2081            2 :                   WRITE (unit_nr, FMT="(I6,A10,A20)") ikind, TRIM(element_symbol), TRIM(name)
    2082            2 :                   WRITE (unit_nr, FMT="(I6)") ngto
    2083            2 :                   WRITE (unit_nr, *) "   Total density"
    2084           26 :                   WRITE (unit_nr, FMT="(2G24.12)") (aedens(i, 1, ikind), aedens(i, 2, ikind), i=1, ngto)
    2085            2 :                   WRITE (unit_nr, *) "    Core density"
    2086           26 :                   WRITE (unit_nr, FMT="(2G24.12)") (ccdens(i, 1, ikind), ccdens(i, 2, ikind), i=1, ngto)
    2087              :                END IF
    2088            6 :                NULLIFY (atomic_kind)
    2089              :             END DO
    2090              : 
    2091            2 :             IF (dft_control%qs_control%gapw) THEN
    2092            2 :                CALL get_qs_env(qs_env=qs_env, rho_atom_set=rho_atom_set)
    2093              : 
    2094            2 :                IF (unit_nr > 0) THEN
    2095            1 :                   WRITE (unit_nr, *) "Coordinates and GAPW density"
    2096              :                END IF
    2097            2 :                np = particles%n_els
    2098            6 :                DO iat = 1, np
    2099            4 :                   CALL get_atomic_kind(particles%els(iat)%atomic_kind, kind_number=ikind)
    2100            4 :                   CALL get_qs_kind(qs_kind_set(ikind), grid_atom=grid_atom)
    2101            4 :                   rho_atom => rho_atom_set(iat)
    2102            4 :                   IF (ASSOCIATED(rho_atom%rho_rad_h(1)%r_coef)) THEN
    2103            2 :                      nr = SIZE(rho_atom%rho_rad_h(1)%r_coef, 1)
    2104            2 :                      niso = SIZE(rho_atom%rho_rad_h(1)%r_coef, 2)
    2105              :                   ELSE
    2106            2 :                      nr = 0
    2107            2 :                      niso = 0
    2108              :                   END IF
    2109            4 :                   CALL para_env%sum(nr)
    2110            4 :                   CALL para_env%sum(niso)
    2111              : 
    2112           16 :                   ALLOCATE (bfun(nr, niso))
    2113         1840 :                   bfun = 0._dp
    2114            8 :                   DO ispin = 1, dft_control%nspins
    2115            8 :                      IF (ASSOCIATED(rho_atom%rho_rad_h(1)%r_coef)) THEN
    2116          920 :                         bfun(:, :) = bfun + rho_atom%rho_rad_h(ispin)%r_coef - rho_atom%rho_rad_s(ispin)%r_coef
    2117              :                      END IF
    2118              :                   END DO
    2119            4 :                   CALL para_env%sum(bfun)
    2120           52 :                   ccdens(:, 1, ikind) = ppdens(:, 1, ikind)
    2121           52 :                   ccdens(:, 2, ikind) = 0._dp
    2122            4 :                   IF (unit_nr > 0) THEN
    2123            8 :                      WRITE (unit_nr, '(I10,I5,3f12.6)') iat, ikind, particles%els(iat)%r
    2124              :                   END IF
    2125           40 :                   DO iso = 1, niso
    2126           36 :                      l = indso(1, iso)
    2127           36 :                      CALL project_function_b(ccdens(:, 2, ikind), ccdens(:, 1, ikind), bfun(:, iso), grid_atom, l)
    2128           40 :                      IF (unit_nr > 0) THEN
    2129           18 :                         WRITE (unit_nr, FMT="(3I6)") iso, l, ngto
    2130          234 :                         WRITE (unit_nr, FMT="(2G24.12)") (ccdens(i, 1, ikind), ccdens(i, 2, ikind), i=1, ngto)
    2131              :                      END IF
    2132              :                   END DO
    2133           10 :                   DEALLOCATE (bfun)
    2134              :                END DO
    2135              :             ELSE
    2136            0 :                IF (unit_nr > 0) THEN
    2137            0 :                   WRITE (unit_nr, *) "Coordinates"
    2138            0 :                   np = particles%n_els
    2139            0 :                   DO iat = 1, np
    2140            0 :                      CALL get_atomic_kind(particles%els(iat)%atomic_kind, kind_number=ikind)
    2141            0 :                      WRITE (unit_nr, '(I10,I5,3f12.6)') iat, ikind, particles%els(iat)%r
    2142              :                   END DO
    2143              :                END IF
    2144              :             END IF
    2145              : 
    2146            2 :             DEALLOCATE (ppdens, aedens, ccdens)
    2147              : 
    2148              :             CALL cp_print_key_finished_output(unit_nr, logger, input, &
    2149            2 :                                               "DFT%PRINT%E_DENSITY_CUBE")
    2150              : 
    2151              :          END IF
    2152          150 :          IF (dft_control%qs_control%gapw .AND. print_density == "TOTAL_DENSITY") THEN
    2153              :             ! total density in g-space not implemented for k-points
    2154            4 :             CPASSERT(.NOT. do_kpoints)
    2155              :             ! Print total electronic density
    2156              :             CALL get_qs_env(qs_env=qs_env, &
    2157            4 :                             pw_env=pw_env)
    2158              :             CALL pw_env_get(pw_env=pw_env, &
    2159              :                             auxbas_pw_pool=auxbas_pw_pool, &
    2160            4 :                             pw_pools=pw_pools)
    2161            4 :             CALL auxbas_pw_pool%create_pw(pw=rho_elec_rspace)
    2162            4 :             CALL pw_zero(rho_elec_rspace)
    2163            4 :             CALL auxbas_pw_pool%create_pw(pw=rho_elec_gspace)
    2164            4 :             CALL pw_zero(rho_elec_gspace)
    2165              :             CALL get_pw_grid_info(pw_grid=rho_elec_gspace%pw_grid, &
    2166              :                                   dr=dr, &
    2167            4 :                                   vol=volume)
    2168           16 :             q_max = SQRT(SUM((pi/dr(:))**2))
    2169              :             CALL calculate_rhotot_elec_gspace(qs_env=qs_env, &
    2170              :                                               auxbas_pw_pool=auxbas_pw_pool, &
    2171              :                                               rhotot_elec_gspace=rho_elec_gspace, &
    2172              :                                               q_max=q_max, &
    2173              :                                               rho_hard=rho_hard, &
    2174            4 :                                               rho_soft=rho_soft)
    2175            4 :             rho_total = rho_hard + rho_soft
    2176              :             CALL get_pw_grid_info(pw_grid=rho_elec_gspace%pw_grid, &
    2177            4 :                                   vol=volume)
    2178              :             ! rhotot pw coefficients are by default scaled by grid volume
    2179              :             ! need to undo this to get proper charge from printed cube
    2180            4 :             CALL pw_scale(rho_elec_gspace, 1.0_dp/volume)
    2181              : 
    2182            4 :             CALL pw_transfer(rho_elec_gspace, rho_elec_rspace)
    2183            4 :             rho_total_rspace = pw_integrate_function(rho_elec_rspace, isign=-1)
    2184            4 :             filename = "TOTAL_ELECTRON_DENSITY"
    2185            4 :             mpi_io = .TRUE.
    2186              :             unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%E_DENSITY_CUBE", &
    2187              :                                            extension=".cube", middle_name=TRIM(filename), &
    2188              :                                            file_position=my_pos_cube, log_filename=.FALSE., mpi_io=mpi_io, &
    2189            4 :                                            fout=mpi_filename)
    2190            4 :             IF (output_unit > 0) THEN
    2191            2 :                IF (.NOT. mpi_io) THEN
    2192            0 :                   INQUIRE (UNIT=unit_nr, NAME=filename)
    2193              :                ELSE
    2194            2 :                   filename = mpi_filename
    2195              :                END IF
    2196              :                WRITE (UNIT=output_unit, FMT="(/,T2,A,/,/,T2,A)") &
    2197            2 :                   "The total electron density is written in cube file format to the file:", &
    2198            4 :                   TRIM(filename)
    2199              :                WRITE (UNIT=output_unit, FMT="(/,(T2,A,F20.10))") &
    2200            2 :                   "q(max) [1/Angstrom]              :", q_max/angstrom, &
    2201            2 :                   "Soft electronic charge (G-space) :", rho_soft, &
    2202            2 :                   "Hard electronic charge (G-space) :", rho_hard, &
    2203            2 :                   "Total electronic charge (G-space):", rho_total, &
    2204            4 :                   "Total electronic charge (R-space):", rho_total_rspace
    2205              :             END IF
    2206              :             CALL cp_pw_to_cube(rho_elec_rspace, unit_nr, "TOTAL ELECTRON DENSITY", &
    2207              :                                particles=particles, zeff=zcharge, &
    2208            4 :                                stride=section_get_ivals(dft_section, "PRINT%E_DENSITY_CUBE%STRIDE"), mpi_io=mpi_io)
    2209              :             CALL cp_print_key_finished_output(unit_nr, logger, input, &
    2210            4 :                                               "DFT%PRINT%E_DENSITY_CUBE", mpi_io=mpi_io)
    2211              :             ! Print total spin density for spin-polarized systems
    2212            4 :             IF (dft_control%nspins > 1) THEN
    2213            2 :                CALL pw_zero(rho_elec_gspace)
    2214            2 :                CALL pw_zero(rho_elec_rspace)
    2215              :                CALL calculate_rhotot_elec_gspace(qs_env=qs_env, &
    2216              :                                                  auxbas_pw_pool=auxbas_pw_pool, &
    2217              :                                                  rhotot_elec_gspace=rho_elec_gspace, &
    2218              :                                                  q_max=q_max, &
    2219              :                                                  rho_hard=rho_hard, &
    2220              :                                                  rho_soft=rho_soft, &
    2221            2 :                                                  fsign=-1.0_dp)
    2222            2 :                rho_total = rho_hard + rho_soft
    2223              : 
    2224              :                ! rhotot pw coefficients are by default scaled by grid volume
    2225              :                ! need to undo this to get proper charge from printed cube
    2226            2 :                CALL pw_scale(rho_elec_gspace, 1.0_dp/volume)
    2227              : 
    2228            2 :                CALL pw_transfer(rho_elec_gspace, rho_elec_rspace)
    2229            2 :                rho_total_rspace = pw_integrate_function(rho_elec_rspace, isign=-1)
    2230            2 :                filename = "TOTAL_SPIN_DENSITY"
    2231            2 :                mpi_io = .TRUE.
    2232              :                unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%E_DENSITY_CUBE", &
    2233              :                                               extension=".cube", middle_name=TRIM(filename), &
    2234              :                                               file_position=my_pos_cube, log_filename=.FALSE., mpi_io=mpi_io, &
    2235            2 :                                               fout=mpi_filename)
    2236            2 :                IF (output_unit > 0) THEN
    2237            1 :                   IF (.NOT. mpi_io) THEN
    2238            0 :                      INQUIRE (UNIT=unit_nr, NAME=filename)
    2239              :                   ELSE
    2240            1 :                      filename = mpi_filename
    2241              :                   END IF
    2242              :                   WRITE (UNIT=output_unit, FMT="(/,T2,A,/,/,T2,A)") &
    2243            1 :                      "The total spin density is written in cube file format to the file:", &
    2244            2 :                      TRIM(filename)
    2245              :                   WRITE (UNIT=output_unit, FMT="(/,(T2,A,F20.10))") &
    2246            1 :                      "q(max) [1/Angstrom]                    :", q_max/angstrom, &
    2247            1 :                      "Soft part of the spin density (G-space):", rho_soft, &
    2248            1 :                      "Hard part of the spin density (G-space):", rho_hard, &
    2249            1 :                      "Total spin density (G-space)           :", rho_total, &
    2250            2 :                      "Total spin density (R-space)           :", rho_total_rspace
    2251              :                END IF
    2252              :                CALL cp_pw_to_cube(rho_elec_rspace, unit_nr, "TOTAL SPIN DENSITY", &
    2253              :                                   particles=particles, zeff=zcharge, &
    2254            2 :                                   stride=section_get_ivals(dft_section, "PRINT%E_DENSITY_CUBE%STRIDE"), mpi_io=mpi_io)
    2255              :                CALL cp_print_key_finished_output(unit_nr, logger, input, &
    2256            2 :                                                  "DFT%PRINT%E_DENSITY_CUBE", mpi_io=mpi_io)
    2257              :             END IF
    2258            4 :             CALL auxbas_pw_pool%give_back_pw(rho_elec_gspace)
    2259            4 :             CALL auxbas_pw_pool%give_back_pw(rho_elec_rspace)
    2260              : 
    2261          146 :          ELSE IF (print_density == "SOFT_DENSITY" .OR. .NOT. dft_control%qs_control%gapw) THEN
    2262          142 :             IF (dft_control%nspins > 1) THEN
    2263              :                CALL get_qs_env(qs_env=qs_env, &
    2264           48 :                                pw_env=pw_env)
    2265              :                CALL pw_env_get(pw_env=pw_env, &
    2266              :                                auxbas_pw_pool=auxbas_pw_pool, &
    2267           48 :                                pw_pools=pw_pools)
    2268           48 :                CALL auxbas_pw_pool%create_pw(pw=rho_elec_rspace)
    2269           48 :                CALL pw_copy(rho_r(1), rho_elec_rspace)
    2270           48 :                CALL pw_axpy(rho_r(2), rho_elec_rspace)
    2271           48 :                filename = "ELECTRON_DENSITY"
    2272           48 :                mpi_io = .TRUE.
    2273              :                unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%E_DENSITY_CUBE", &
    2274              :                                               extension=".cube", middle_name=TRIM(filename), &
    2275              :                                               file_position=my_pos_cube, log_filename=.FALSE., mpi_io=mpi_io, &
    2276           48 :                                               fout=mpi_filename)
    2277           48 :                IF (output_unit > 0) THEN
    2278           24 :                   IF (.NOT. mpi_io) THEN
    2279            0 :                      INQUIRE (UNIT=unit_nr, NAME=filename)
    2280              :                   ELSE
    2281           24 :                      filename = mpi_filename
    2282              :                   END IF
    2283              :                   WRITE (UNIT=output_unit, FMT="(/,T2,A,/,/,T2,A)") &
    2284           24 :                      "The sum of alpha and beta density is written in cube file format to the file:", &
    2285           48 :                      TRIM(filename)
    2286              :                END IF
    2287              :                CALL cp_pw_to_cube(rho_elec_rspace, unit_nr, "SUM OF ALPHA AND BETA DENSITY", &
    2288              :                                   particles=particles, zeff=zcharge, &
    2289              :                                   stride=section_get_ivals(dft_section, "PRINT%E_DENSITY_CUBE%STRIDE"), &
    2290           48 :                                   mpi_io=mpi_io)
    2291              :                CALL cp_print_key_finished_output(unit_nr, logger, input, &
    2292           48 :                                                  "DFT%PRINT%E_DENSITY_CUBE", mpi_io=mpi_io)
    2293           48 :                CALL pw_copy(rho_r(1), rho_elec_rspace)
    2294           48 :                CALL pw_axpy(rho_r(2), rho_elec_rspace, alpha=-1.0_dp)
    2295           48 :                filename = "SPIN_DENSITY"
    2296           48 :                mpi_io = .TRUE.
    2297              :                unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%E_DENSITY_CUBE", &
    2298              :                                               extension=".cube", middle_name=TRIM(filename), &
    2299              :                                               file_position=my_pos_cube, log_filename=.FALSE., mpi_io=mpi_io, &
    2300           48 :                                               fout=mpi_filename)
    2301           48 :                IF (output_unit > 0) THEN
    2302           24 :                   IF (.NOT. mpi_io) THEN
    2303            0 :                      INQUIRE (UNIT=unit_nr, NAME=filename)
    2304              :                   ELSE
    2305           24 :                      filename = mpi_filename
    2306              :                   END IF
    2307              :                   WRITE (UNIT=output_unit, FMT="(/,T2,A,/,/,T2,A)") &
    2308           24 :                      "The spin density is written in cube file format to the file:", &
    2309           48 :                      TRIM(filename)
    2310              :                END IF
    2311              :                CALL cp_pw_to_cube(rho_elec_rspace, unit_nr, "SPIN DENSITY", &
    2312              :                                   particles=particles, zeff=zcharge, &
    2313           48 :                                   stride=section_get_ivals(dft_section, "PRINT%E_DENSITY_CUBE%STRIDE"), mpi_io=mpi_io)
    2314              :                CALL cp_print_key_finished_output(unit_nr, logger, input, &
    2315           48 :                                                  "DFT%PRINT%E_DENSITY_CUBE", mpi_io=mpi_io)
    2316           48 :                CALL auxbas_pw_pool%give_back_pw(rho_elec_rspace)
    2317              :             ELSE
    2318           94 :                filename = "ELECTRON_DENSITY"
    2319           94 :                mpi_io = .TRUE.
    2320              :                unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%E_DENSITY_CUBE", &
    2321              :                                               extension=".cube", middle_name=TRIM(filename), &
    2322              :                                               file_position=my_pos_cube, log_filename=.FALSE., mpi_io=mpi_io, &
    2323           94 :                                               fout=mpi_filename)
    2324           94 :                IF (output_unit > 0) THEN
    2325           47 :                   IF (.NOT. mpi_io) THEN
    2326            0 :                      INQUIRE (UNIT=unit_nr, NAME=filename)
    2327              :                   ELSE
    2328           47 :                      filename = mpi_filename
    2329              :                   END IF
    2330              :                   WRITE (UNIT=output_unit, FMT="(/,T2,A,/,/,T2,A)") &
    2331           47 :                      "The electron density is written in cube file format to the file:", &
    2332           94 :                      TRIM(filename)
    2333              :                END IF
    2334              :                CALL cp_pw_to_cube(rho_r(1), unit_nr, "ELECTRON DENSITY", &
    2335              :                                   particles=particles, zeff=zcharge, &
    2336           94 :                                   stride=section_get_ivals(dft_section, "PRINT%E_DENSITY_CUBE%STRIDE"), mpi_io=mpi_io)
    2337              :                CALL cp_print_key_finished_output(unit_nr, logger, input, &
    2338           94 :                                                  "DFT%PRINT%E_DENSITY_CUBE", mpi_io=mpi_io)
    2339              :             END IF ! nspins
    2340              : 
    2341            4 :          ELSE IF (dft_control%qs_control%gapw .AND. print_density == "TOTAL_HARD_APPROX") THEN
    2342            4 :             CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, rho0_mpole=rho0_mpole, natom=natom)
    2343            4 :             CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, pw_pools=pw_pools)
    2344            4 :             CALL auxbas_pw_pool%create_pw(rho_elec_rspace)
    2345              : 
    2346            4 :             NULLIFY (my_Q0)
    2347           12 :             ALLOCATE (my_Q0(natom))
    2348           16 :             my_Q0 = 0.0_dp
    2349              : 
    2350              :             ! (eta/pi)**3: normalization for 3d gaussian of form exp(-eta*r**2)
    2351            4 :             norm_factor = SQRT((rho0_mpole%zet0_h/pi)**3)
    2352              : 
    2353              :             ! store hard part of electronic density in array
    2354           16 :             DO iat = 1, natom
    2355           34 :                my_Q0(iat) = SUM(rho0_mpole%mp_rho(iat)%Q0(1:dft_control%nspins))*norm_factor
    2356              :             END DO
    2357              :             ! multiply coeff with gaussian and put on realspace grid
    2358              :             ! coeff is the gaussian prefactor, eta the gaussian exponent
    2359            4 :             CALL calculate_rho_resp_all(rho_elec_rspace, coeff=my_Q0, natom=natom, eta=rho0_mpole%zet0_h, qs_env=qs_env)
    2360            4 :             rho_hard = pw_integrate_function(rho_elec_rspace, isign=-1)
    2361              : 
    2362            4 :             rho_soft = 0.0_dp
    2363           10 :             DO ispin = 1, dft_control%nspins
    2364            6 :                CALL pw_axpy(rho_r(ispin), rho_elec_rspace)
    2365           10 :                rho_soft = rho_soft + pw_integrate_function(rho_r(ispin), isign=-1)
    2366              :             END DO
    2367              : 
    2368            4 :             rho_total_rspace = rho_soft + rho_hard
    2369              : 
    2370            4 :             filename = "ELECTRON_DENSITY"
    2371            4 :             mpi_io = .TRUE.
    2372              :             unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%E_DENSITY_CUBE", &
    2373              :                                            extension=".cube", middle_name=TRIM(filename), &
    2374              :                                            file_position=my_pos_cube, log_filename=.FALSE., mpi_io=mpi_io, &
    2375            4 :                                            fout=mpi_filename)
    2376            4 :             IF (output_unit > 0) THEN
    2377            2 :                IF (.NOT. mpi_io) THEN
    2378            0 :                   INQUIRE (UNIT=unit_nr, NAME=filename)
    2379              :                ELSE
    2380            2 :                   filename = mpi_filename
    2381              :                END IF
    2382              :                WRITE (UNIT=output_unit, FMT="(/,T2,A,/,/,T2,A)") &
    2383            2 :                   "The electron density is written in cube file format to the file:", &
    2384            4 :                   TRIM(filename)
    2385              :                WRITE (UNIT=output_unit, FMT="(/,(T2,A,F20.10))") &
    2386            2 :                   "Soft electronic charge (R-space) :", rho_soft, &
    2387            2 :                   "Hard electronic charge (R-space) :", rho_hard, &
    2388            4 :                   "Total electronic charge (R-space):", rho_total_rspace
    2389              :             END IF
    2390              :             CALL cp_pw_to_cube(rho_elec_rspace, unit_nr, "ELECTRON DENSITY", &
    2391              :                                particles=particles, zeff=zcharge, &
    2392              :                                stride=section_get_ivals(dft_section, "PRINT%E_DENSITY_CUBE%STRIDE"), &
    2393            4 :                                mpi_io=mpi_io)
    2394              :             CALL cp_print_key_finished_output(unit_nr, logger, input, &
    2395            4 :                                               "DFT%PRINT%E_DENSITY_CUBE", mpi_io=mpi_io)
    2396              : 
    2397              :             !------------
    2398            4 :             IF (dft_control%nspins > 1) THEN
    2399            8 :             DO iat = 1, natom
    2400            8 :                my_Q0(iat) = (rho0_mpole%mp_rho(iat)%Q0(1) - rho0_mpole%mp_rho(iat)%Q0(2))*norm_factor
    2401              :             END DO
    2402            2 :             CALL pw_zero(rho_elec_rspace)
    2403            2 :             CALL calculate_rho_resp_all(rho_elec_rspace, coeff=my_Q0, natom=natom, eta=rho0_mpole%zet0_h, qs_env=qs_env)
    2404            2 :             rho_hard = pw_integrate_function(rho_elec_rspace, isign=-1)
    2405              : 
    2406            2 :             CALL pw_axpy(rho_r(1), rho_elec_rspace)
    2407            2 :             CALL pw_axpy(rho_r(2), rho_elec_rspace, alpha=-1.0_dp)
    2408              :             rho_soft = pw_integrate_function(rho_r(1), isign=-1) &
    2409            2 :                        - pw_integrate_function(rho_r(2), isign=-1)
    2410              : 
    2411            2 :             rho_total_rspace = rho_soft + rho_hard
    2412              : 
    2413            2 :             filename = "SPIN_DENSITY"
    2414            2 :             mpi_io = .TRUE.
    2415              :             unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%E_DENSITY_CUBE", &
    2416              :                                            extension=".cube", middle_name=TRIM(filename), &
    2417              :                                            file_position=my_pos_cube, log_filename=.FALSE., mpi_io=mpi_io, &
    2418            2 :                                            fout=mpi_filename)
    2419            2 :             IF (output_unit > 0) THEN
    2420            1 :                IF (.NOT. mpi_io) THEN
    2421            0 :                   INQUIRE (UNIT=unit_nr, NAME=filename)
    2422              :                ELSE
    2423            1 :                   filename = mpi_filename
    2424              :                END IF
    2425              :                WRITE (UNIT=output_unit, FMT="(/,T2,A,/,/,T2,A)") &
    2426            1 :                   "The spin density is written in cube file format to the file:", &
    2427            2 :                   TRIM(filename)
    2428              :                WRITE (UNIT=output_unit, FMT="(/,(T2,A,F20.10))") &
    2429            1 :                   "Soft part of the spin density          :", rho_soft, &
    2430            1 :                   "Hard part of the spin density          :", rho_hard, &
    2431            2 :                   "Total spin density (R-space)           :", rho_total_rspace
    2432              :             END IF
    2433              :             CALL cp_pw_to_cube(rho_elec_rspace, unit_nr, "SPIN DENSITY", &
    2434              :                                particles=particles, zeff=zcharge, &
    2435            2 :                                stride=section_get_ivals(dft_section, "PRINT%E_DENSITY_CUBE%STRIDE"), mpi_io=mpi_io)
    2436              :             CALL cp_print_key_finished_output(unit_nr, logger, input, &
    2437            2 :                                               "DFT%PRINT%E_DENSITY_CUBE", mpi_io=mpi_io)
    2438              :             END IF ! nspins
    2439            4 :             CALL auxbas_pw_pool%give_back_pw(rho_elec_rspace)
    2440            4 :             DEALLOCATE (my_Q0)
    2441              :          END IF ! print_density
    2442              :       END IF ! print key
    2443              : 
    2444              :       IF (BTEST(cp_print_key_should_output(logger%iter_info, &
    2445        11299 :                                            dft_section, "PRINT%ENERGY_WINDOWS"), cp_p_file) .AND. .NOT. do_kpoints) THEN
    2446           90 :          CALL energy_windows(qs_env)
    2447              :       END IF
    2448              : 
    2449              :       ! Print the hartree potential
    2450        11299 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    2451              :                                            "DFT%PRINT%V_HARTREE_CUBE"), cp_p_file)) THEN
    2452              : 
    2453              :          CALL get_qs_env(qs_env=qs_env, &
    2454              :                          pw_env=pw_env, &
    2455          114 :                          v_hartree_rspace=v_hartree_rspace)
    2456          114 :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    2457          114 :          CALL auxbas_pw_pool%create_pw(aux_r)
    2458              : 
    2459          114 :          append_cube = section_get_lval(input, "DFT%PRINT%V_HARTREE_CUBE%APPEND")
    2460          114 :          my_pos_cube = "REWIND"
    2461          114 :          IF (append_cube) THEN
    2462            0 :             my_pos_cube = "APPEND"
    2463              :          END IF
    2464          114 :          mpi_io = .TRUE.
    2465          114 :          CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
    2466          114 :          CALL pw_env_get(pw_env)
    2467              :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%V_HARTREE_CUBE", &
    2468          114 :                                         extension=".cube", middle_name="v_hartree", file_position=my_pos_cube, mpi_io=mpi_io)
    2469          114 :          udvol = 1.0_dp/v_hartree_rspace%pw_grid%dvol
    2470              : 
    2471          114 :          CALL pw_copy(v_hartree_rspace, aux_r)
    2472          114 :          CALL pw_scale(aux_r, udvol)
    2473              : 
    2474              :          CALL cp_pw_to_cube(aux_r, unit_nr, "HARTREE POTENTIAL", particles=particles, zeff=zcharge, &
    2475              :                             stride=section_get_ivals(dft_section, &
    2476          114 :                                                      "PRINT%V_HARTREE_CUBE%STRIDE"), mpi_io=mpi_io)
    2477              :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
    2478          114 :                                            "DFT%PRINT%V_HARTREE_CUBE", mpi_io=mpi_io)
    2479              : 
    2480          114 :          CALL auxbas_pw_pool%give_back_pw(aux_r)
    2481              :       END IF
    2482              : 
    2483              :       ! Print the external potential
    2484        11299 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    2485              :                                            "DFT%PRINT%EXTERNAL_POTENTIAL_CUBE"), cp_p_file)) THEN
    2486           86 :          IF (dft_control%apply_external_potential) THEN
    2487            4 :             CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, vee=vee)
    2488            4 :             CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    2489            4 :             CALL auxbas_pw_pool%create_pw(aux_r)
    2490              : 
    2491            4 :             append_cube = section_get_lval(input, "DFT%PRINT%EXTERNAL_POTENTIAL_CUBE%APPEND")
    2492            4 :             my_pos_cube = "REWIND"
    2493            4 :             IF (append_cube) THEN
    2494            0 :                my_pos_cube = "APPEND"
    2495              :             END IF
    2496            4 :             mpi_io = .TRUE.
    2497            4 :             CALL pw_env_get(pw_env)
    2498              :             unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%EXTERNAL_POTENTIAL_CUBE", &
    2499            4 :                                            extension=".cube", middle_name="ext_pot", file_position=my_pos_cube, mpi_io=mpi_io)
    2500              : 
    2501            4 :             CALL pw_copy(vee, aux_r)
    2502              : 
    2503              :             CALL cp_pw_to_cube(aux_r, unit_nr, "EXTERNAL POTENTIAL", particles=particles, zeff=zcharge, &
    2504              :                                stride=section_get_ivals(dft_section, &
    2505            4 :                                                         "PRINT%EXTERNAL_POTENTIAL_CUBE%STRIDE"), mpi_io=mpi_io)
    2506              :             CALL cp_print_key_finished_output(unit_nr, logger, input, &
    2507            4 :                                               "DFT%PRINT%EXTERNAL_POTENTIAL_CUBE", mpi_io=mpi_io)
    2508              : 
    2509            4 :             CALL auxbas_pw_pool%give_back_pw(aux_r)
    2510              :          END IF
    2511              :       END IF
    2512              : 
    2513              :       ! Print the Electrical Field Components
    2514        11299 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    2515              :                                            "DFT%PRINT%EFIELD_CUBE"), cp_p_file)) THEN
    2516              : 
    2517           82 :          CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
    2518           82 :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    2519           82 :          CALL auxbas_pw_pool%create_pw(aux_r)
    2520           82 :          CALL auxbas_pw_pool%create_pw(aux_g)
    2521              : 
    2522           82 :          append_cube = section_get_lval(input, "DFT%PRINT%EFIELD_CUBE%APPEND")
    2523           82 :          my_pos_cube = "REWIND"
    2524           82 :          IF (append_cube) THEN
    2525            0 :             my_pos_cube = "APPEND"
    2526              :          END IF
    2527              :          CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, &
    2528           82 :                          v_hartree_rspace=v_hartree_rspace)
    2529           82 :          CALL pw_env_get(pw_env)
    2530           82 :          udvol = 1.0_dp/v_hartree_rspace%pw_grid%dvol
    2531          328 :          DO id = 1, 3
    2532          246 :             mpi_io = .TRUE.
    2533              :             unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%EFIELD_CUBE", &
    2534              :                                            extension=".cube", middle_name="efield_"//cdir(id), file_position=my_pos_cube, &
    2535          246 :                                            mpi_io=mpi_io)
    2536              : 
    2537          246 :             CALL pw_transfer(v_hartree_rspace, aux_g)
    2538          246 :             nd = 0
    2539          246 :             nd(id) = 1
    2540          246 :             CALL pw_derive(aux_g, nd)
    2541          246 :             CALL pw_transfer(aux_g, aux_r)
    2542          246 :             CALL pw_scale(aux_r, udvol)
    2543              : 
    2544              :             CALL cp_pw_to_cube(aux_r, &
    2545              :                                unit_nr, "ELECTRIC FIELD", particles=particles, zeff=zcharge, &
    2546              :                                stride=section_get_ivals(dft_section, &
    2547          246 :                                                         "PRINT%EFIELD_CUBE%STRIDE"), mpi_io=mpi_io)
    2548              :             CALL cp_print_key_finished_output(unit_nr, logger, input, &
    2549          328 :                                               "DFT%PRINT%EFIELD_CUBE", mpi_io=mpi_io)
    2550              :          END DO
    2551              : 
    2552           82 :          CALL auxbas_pw_pool%give_back_pw(aux_r)
    2553           82 :          CALL auxbas_pw_pool%give_back_pw(aux_g)
    2554              :       END IF
    2555              : 
    2556              :       ! Write cube files from the local energy
    2557        11299 :       CALL qs_scf_post_local_energy(input, logger, qs_env)
    2558              : 
    2559              :       ! Write cube files from the local stress tensor
    2560        11299 :       CALL qs_scf_post_local_stress(input, logger, qs_env)
    2561              : 
    2562              :       ! Write cube files from the implicit Poisson solver
    2563        11299 :       CALL qs_scf_post_ps_implicit(input, logger, qs_env)
    2564              : 
    2565              :       ! post SCF Transport
    2566        11299 :       CALL qs_scf_post_transport(qs_env)
    2567              : 
    2568        11299 :       CALL section_vals_val_get(input, "DFT%PRINT%AO_MATRICES%OMIT_HEADERS", l_val=omit_headers)
    2569              :       ! Write the density matrices
    2570        11299 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    2571              :                                            "DFT%PRINT%AO_MATRICES/DENSITY"), cp_p_file)) THEN
    2572              :          iw = cp_print_key_unit_nr(logger, input, "DFT%PRINT%AO_MATRICES/DENSITY", &
    2573            4 :                                    extension=".Log")
    2574            4 :          CALL section_vals_val_get(input, "DFT%PRINT%AO_MATRICES%NDIGITS", i_val=after)
    2575            4 :          CALL qs_rho_get(rho, rho_ao_kp=rho_ao)
    2576            4 :          after = MIN(MAX(after, 1), 16)
    2577            8 :          DO ispin = 1, dft_control%nspins
    2578           12 :             DO img = 1, dft_control%nimages
    2579              :                CALL cp_dbcsr_write_sparse_matrix(rho_ao(ispin, img)%matrix, 4, after, qs_env, &
    2580            8 :                                                  para_env, output_unit=iw, omit_headers=omit_headers)
    2581              :             END DO
    2582              :          END DO
    2583              :          CALL cp_print_key_finished_output(iw, logger, input, &
    2584            4 :                                            "DFT%PRINT%AO_MATRICES/DENSITY")
    2585              :       END IF
    2586              : 
    2587              :       ! Write the Kohn-Sham matrices
    2588              :       write_ks = BTEST(cp_print_key_should_output(logger%iter_info, input, &
    2589        11299 :                                                   "DFT%PRINT%AO_MATRICES/KOHN_SHAM_MATRIX"), cp_p_file)
    2590              :       write_xc = BTEST(cp_print_key_should_output(logger%iter_info, input, &
    2591        11299 :                                                   "DFT%PRINT%AO_MATRICES/MATRIX_VXC"), cp_p_file)
    2592              :       ! we need to update stuff before writing, potentially computing the matrix_vxc
    2593        11299 :       IF (write_ks .OR. write_xc) THEN
    2594            4 :          IF (write_xc) qs_env%requires_matrix_vxc = .TRUE.
    2595            4 :          CALL qs_ks_did_change(qs_env%ks_env, rho_changed=.TRUE.)
    2596              :          CALL qs_ks_update_qs_env(qs_env, calculate_forces=.FALSE., &
    2597            4 :                                   just_energy=.FALSE.)
    2598            4 :          IF (write_xc) qs_env%requires_matrix_vxc = .FALSE.
    2599              :       END IF
    2600              : 
    2601              :       ! Write the Kohn-Sham matrices
    2602        11299 :       IF (write_ks) THEN
    2603              :          iw = cp_print_key_unit_nr(logger, input, "DFT%PRINT%AO_MATRICES/KOHN_SHAM_MATRIX", &
    2604            4 :                                    extension=".Log")
    2605            4 :          CALL get_qs_env(qs_env=qs_env, matrix_ks_kp=ks_rmpv)
    2606            4 :          CALL section_vals_val_get(input, "DFT%PRINT%AO_MATRICES%NDIGITS", i_val=after)
    2607            4 :          after = MIN(MAX(after, 1), 16)
    2608            8 :          DO ispin = 1, dft_control%nspins
    2609           12 :             DO img = 1, dft_control%nimages
    2610              :                CALL cp_dbcsr_write_sparse_matrix(ks_rmpv(ispin, img)%matrix, 4, after, qs_env, &
    2611            8 :                                                  para_env, output_unit=iw, omit_headers=omit_headers)
    2612              :             END DO
    2613              :          END DO
    2614              :          CALL cp_print_key_finished_output(iw, logger, input, &
    2615            4 :                                            "DFT%PRINT%AO_MATRICES/KOHN_SHAM_MATRIX")
    2616              :       END IF
    2617              : 
    2618              :       ! write csr matrices
    2619              :       ! matrices in terms of the PAO basis will be taken care of in pao_post_scf.
    2620        11299 :       IF (.NOT. dft_control%qs_control%pao) THEN
    2621        10787 :          CALL write_ks_matrix_csr(qs_env, input)
    2622        10787 :          CALL write_s_matrix_csr(qs_env, input)
    2623        10787 :          CALL write_hcore_matrix_csr(qs_env, input)
    2624        10787 :          CALL write_p_matrix_csr(qs_env, input)
    2625              :       END IF
    2626              : 
    2627              :       ! write adjacency matrix
    2628        11299 :       CALL write_adjacency_matrix(qs_env, input)
    2629              : 
    2630              :       ! Write the xc matrix
    2631        11299 :       IF (write_xc) THEN
    2632            0 :          CALL get_qs_env(qs_env=qs_env, matrix_vxc_kp=matrix_vxc)
    2633            0 :          CPASSERT(ASSOCIATED(matrix_vxc))
    2634              :          iw = cp_print_key_unit_nr(logger, input, "DFT%PRINT%AO_MATRICES/MATRIX_VXC", &
    2635            0 :                                    extension=".Log")
    2636            0 :          CALL section_vals_val_get(input, "DFT%PRINT%AO_MATRICES%NDIGITS", i_val=after)
    2637            0 :          after = MIN(MAX(after, 1), 16)
    2638            0 :          DO ispin = 1, dft_control%nspins
    2639            0 :             DO img = 1, dft_control%nimages
    2640              :                CALL cp_dbcsr_write_sparse_matrix(matrix_vxc(ispin, img)%matrix, 4, after, qs_env, &
    2641            0 :                                                  para_env, output_unit=iw, omit_headers=omit_headers)
    2642              :             END DO
    2643              :          END DO
    2644              :          CALL cp_print_key_finished_output(iw, logger, input, &
    2645            0 :                                            "DFT%PRINT%AO_MATRICES/MATRIX_VXC")
    2646              :       END IF
    2647              : 
    2648              :       ! Write the [H,r] commutator matrices
    2649        11299 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    2650              :                                            "DFT%PRINT%AO_MATRICES/COMMUTATOR_HR"), cp_p_file)) THEN
    2651              :          iw = cp_print_key_unit_nr(logger, input, "DFT%PRINT%AO_MATRICES/COMMUTATOR_HR", &
    2652            0 :                                    extension=".Log")
    2653            0 :          CALL section_vals_val_get(input, "DFT%PRINT%AO_MATRICES%NDIGITS", i_val=after)
    2654            0 :          NULLIFY (matrix_hr)
    2655            0 :          CALL build_com_hr_matrix(qs_env, matrix_hr)
    2656            0 :          after = MIN(MAX(after, 1), 16)
    2657            0 :          DO img = 1, 3
    2658              :             CALL cp_dbcsr_write_sparse_matrix(matrix_hr(img)%matrix, 4, after, qs_env, &
    2659            0 :                                               para_env, output_unit=iw, omit_headers=omit_headers)
    2660              :          END DO
    2661            0 :          CALL dbcsr_deallocate_matrix_set(matrix_hr)
    2662              :          CALL cp_print_key_finished_output(iw, logger, input, &
    2663            0 :                                            "DFT%PRINT%AO_MATRICES/COMMUTATOR_HR")
    2664              :       END IF
    2665              : 
    2666              :       ! Compute the Mulliken charges
    2667        11299 :       print_key => section_vals_get_subs_vals(input, "DFT%PRINT%MULLIKEN")
    2668        11299 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    2669         4792 :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%MULLIKEN", extension=".mulliken", log_filename=.FALSE.)
    2670         4792 :          print_level = 1
    2671         4792 :          CALL section_vals_val_get(print_key, "PRINT_GOP", l_val=print_it)
    2672         4792 :          IF (print_it) print_level = 2
    2673         4792 :          CALL section_vals_val_get(print_key, "PRINT_ALL", l_val=print_it)
    2674         4792 :          IF (print_it) print_level = 3
    2675         4792 :          CALL mulliken_population_analysis(qs_env, unit_nr, print_level)
    2676         4792 :          CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%MULLIKEN")
    2677              :       END IF
    2678              : 
    2679              :       ! Compute the Hirshfeld charges
    2680        11299 :       print_key => section_vals_get_subs_vals(input, "DFT%PRINT%HIRSHFELD")
    2681        11299 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    2682              :          ! we check if real space density is available
    2683         4864 :          NULLIFY (rho)
    2684         4864 :          CALL get_qs_env(qs_env=qs_env, rho=rho)
    2685         4864 :          CALL qs_rho_get(rho, rho_r_valid=rho_r_valid)
    2686         4864 :          IF (rho_r_valid) THEN
    2687         4790 :             unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%HIRSHFELD", extension=".hirshfeld", log_filename=.FALSE.)
    2688         4790 :             CALL hirshfeld_charges(qs_env, print_key, unit_nr)
    2689         4790 :             CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%HIRSHFELD")
    2690              :          END IF
    2691              :       END IF
    2692              : 
    2693              :       ! Compute EEQ charges
    2694        11299 :       print_key => section_vals_get_subs_vals(input, "DFT%PRINT%EEQ_CHARGES")
    2695        11299 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    2696           30 :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%EEQ_CHARGES", extension=".eeq", log_filename=.FALSE.)
    2697           30 :          print_level = 1
    2698           30 :          CALL eeq_print(qs_env, unit_nr, print_level, ext=.FALSE.)
    2699           30 :          CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%MULLIKEN")
    2700              :       END IF
    2701              : 
    2702              :       ! Do a Voronoi Integration or write a compressed BQB File
    2703        11299 :       print_key_voro => section_vals_get_subs_vals(input, "DFT%PRINT%VORONOI")
    2704        11299 :       print_key_bqb => section_vals_get_subs_vals(input, "DFT%PRINT%E_DENSITY_BQB")
    2705        11299 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key_voro), cp_p_file)) THEN
    2706           24 :          should_print_voro = 1
    2707              :       ELSE
    2708        11275 :          should_print_voro = 0
    2709              :       END IF
    2710        11299 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key_bqb), cp_p_file)) THEN
    2711            2 :          should_print_bqb = 1
    2712              :       ELSE
    2713        11297 :          should_print_bqb = 0
    2714              :       END IF
    2715        11299 :       IF ((should_print_voro /= 0) .OR. (should_print_bqb /= 0)) THEN
    2716              : 
    2717              :          ! we check if real space density is available
    2718           26 :          NULLIFY (rho)
    2719           26 :          CALL get_qs_env(qs_env=qs_env, rho=rho)
    2720           26 :          CALL qs_rho_get(rho, rho_r_valid=rho_r_valid)
    2721           26 :          IF (rho_r_valid) THEN
    2722              : 
    2723           26 :             IF (dft_control%nspins > 1) THEN
    2724              :                CALL get_qs_env(qs_env=qs_env, &
    2725            0 :                                pw_env=pw_env)
    2726              :                CALL pw_env_get(pw_env=pw_env, &
    2727              :                                auxbas_pw_pool=auxbas_pw_pool, &
    2728            0 :                                pw_pools=pw_pools)
    2729            0 :                NULLIFY (mb_rho)
    2730            0 :                ALLOCATE (mb_rho)
    2731            0 :                CALL auxbas_pw_pool%create_pw(pw=mb_rho)
    2732            0 :                CALL pw_copy(rho_r(1), mb_rho)
    2733            0 :                CALL pw_axpy(rho_r(2), mb_rho)
    2734              :                !CALL voronoi_analysis(qs_env, rho_elec_rspace, print_key, unit_nr)
    2735              :             ELSE
    2736           26 :                mb_rho => rho_r(1)
    2737              :                !CALL voronoi_analysis( qs_env, rho_r(1), print_key, unit_nr )
    2738              :             END IF ! nspins
    2739              : 
    2740           26 :             IF (should_print_voro /= 0) THEN
    2741           24 :                CALL section_vals_val_get(print_key_voro, "OUTPUT_TEXT", l_val=voro_print_txt)
    2742           24 :                IF (voro_print_txt) THEN
    2743           24 :                   append_voro = section_get_lval(input, "DFT%PRINT%VORONOI%APPEND")
    2744           24 :                   my_pos_voro = "REWIND"
    2745           24 :                   IF (append_voro) THEN
    2746            0 :                      my_pos_voro = "APPEND"
    2747              :                   END IF
    2748              :                   unit_nr_voro = cp_print_key_unit_nr(logger, input, "DFT%PRINT%VORONOI", extension=".voronoi", &
    2749           24 :                                                       file_position=my_pos_voro, log_filename=.FALSE.)
    2750              :                ELSE
    2751            0 :                   unit_nr_voro = 0
    2752              :                END IF
    2753              :             ELSE
    2754            2 :                unit_nr_voro = 0
    2755              :             END IF
    2756              : 
    2757              :             CALL entry_voronoi_or_bqb(should_print_voro, should_print_bqb, print_key_voro, print_key_bqb, &
    2758           26 :                                       unit_nr_voro, qs_env, mb_rho)
    2759              : 
    2760           26 :             IF (dft_control%nspins > 1) THEN
    2761            0 :                CALL auxbas_pw_pool%give_back_pw(mb_rho)
    2762            0 :                DEALLOCATE (mb_rho)
    2763              :             END IF
    2764              : 
    2765           26 :             IF (unit_nr_voro > 0) THEN
    2766           12 :                CALL cp_print_key_finished_output(unit_nr_voro, logger, input, "DFT%PRINT%VORONOI")
    2767              :             END IF
    2768              : 
    2769              :          END IF
    2770              :       END IF
    2771              : 
    2772              :       ! MAO analysis
    2773        11299 :       print_key => section_vals_get_subs_vals(input, "DFT%PRINT%MAO_ANALYSIS")
    2774        11299 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    2775           38 :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%MAO_ANALYSIS", extension=".mao", log_filename=.FALSE.)
    2776           38 :          CALL mao_analysis(qs_env, print_key, unit_nr)
    2777           38 :          CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%MAO_ANALYSIS")
    2778              :       END IF
    2779              : 
    2780              :       ! MINBAS analysis
    2781        11299 :       print_key => section_vals_get_subs_vals(input, "DFT%PRINT%MINBAS_ANALYSIS")
    2782        11299 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    2783           28 :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%MINBAS_ANALYSIS", extension=".mao", log_filename=.FALSE.)
    2784           28 :          CALL minbas_analysis(qs_env, print_key, unit_nr)
    2785           28 :          CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%MINBAS_ANALYSIS")
    2786              :       END IF
    2787              : 
    2788              :       ! IAO analysis
    2789        11299 :       print_key => section_vals_get_subs_vals(input, "DFT%PRINT%IAO_ANALYSIS")
    2790        11299 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    2791           32 :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%IAO_ANALYSIS", extension=".iao", log_filename=.FALSE.)
    2792           32 :          CALL iao_read_input(iao_env, print_key, cell)
    2793           32 :          IF (iao_env%do_iao) THEN
    2794            4 :             CALL iao_wfn_analysis(qs_env, iao_env, unit_nr)
    2795              :          END IF
    2796           32 :          CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%IAO_ANALYSIS")
    2797              :       END IF
    2798              : 
    2799              :       ! Energy Decomposition Analysis
    2800        11299 :       print_key => section_vals_get_subs_vals(input, "DFT%PRINT%ENERGY_DECOMPOSITION_ANALYSIS")
    2801        11299 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    2802              :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%ENERGY_DECOMPOSITION_ANALYSIS", &
    2803           58 :                                         extension=".mao", log_filename=.FALSE.)
    2804           58 :          CALL edmf_analysis(qs_env, print_key, unit_nr)
    2805           58 :          CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%ENERGY_DECOMPOSITION_ANALYSIS")
    2806              :       END IF
    2807              : 
    2808              :       ! Print the density in the RI-HFX basis
    2809        11299 :       hfx_section => section_vals_get_subs_vals(input, "DFT%XC%HF")
    2810        11299 :       CALL section_vals_get(hfx_section, explicit=do_hfx)
    2811        11299 :       CALL section_vals_get(hfx_section, n_repetition=n_rep_hf)
    2812        11299 :       IF (do_hfx) THEN
    2813         4526 :          DO i = 1, n_rep_hf
    2814         4526 :             IF (qs_env%x_data(i, 1)%do_hfx_ri) CALL print_ri_hfx(qs_env%x_data(i, 1)%ri_data, qs_env)
    2815              :          END DO
    2816              :       END IF
    2817              : 
    2818        11299 :       DEALLOCATE (zcharge)
    2819              : 
    2820        11299 :       CALL timestop(handle)
    2821              : 
    2822        45196 :    END SUBROUTINE write_mo_free_results
    2823              : 
    2824              : ! **************************************************************************************************
    2825              : !> \brief Calculates Hirshfeld charges
    2826              : !> \param qs_env the qs_env where to calculate the charges
    2827              : !> \param input_section the input section for Hirshfeld charges
    2828              : !> \param unit_nr the output unit number
    2829              : ! **************************************************************************************************
    2830         4790 :    SUBROUTINE hirshfeld_charges(qs_env, input_section, unit_nr)
    2831              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2832              :       TYPE(section_vals_type), POINTER                   :: input_section
    2833              :       INTEGER, INTENT(IN)                                :: unit_nr
    2834              : 
    2835              :       INTEGER                                            :: i, iat, ikind, natom, nkind, nspin, &
    2836              :                                                             radius_type, refc, shapef
    2837         4790 :       INTEGER, DIMENSION(:), POINTER                     :: atom_list
    2838              :       LOGICAL                                            :: do_radius, do_sc, paw_atom
    2839              :       REAL(KIND=dp)                                      :: zeff
    2840         4790 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: radii
    2841         4790 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: charges
    2842         4790 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    2843              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
    2844         4790 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_p, matrix_s
    2845              :       TYPE(dft_control_type), POINTER                    :: dft_control
    2846              :       TYPE(hirshfeld_type), POINTER                      :: hirshfeld_env
    2847              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2848         4790 :       TYPE(mpole_rho_atom), DIMENSION(:), POINTER        :: mp_rho
    2849         4790 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    2850         4790 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    2851              :       TYPE(qs_rho_type), POINTER                         :: rho
    2852              :       TYPE(rho0_mpole_type), POINTER                     :: rho0_mpole
    2853              : 
    2854         4790 :       NULLIFY (hirshfeld_env)
    2855         4790 :       NULLIFY (radii)
    2856         4790 :       CALL create_hirshfeld_type(hirshfeld_env)
    2857              :       !
    2858         4790 :       CALL get_qs_env(qs_env, nkind=nkind, natom=natom)
    2859        14370 :       ALLOCATE (hirshfeld_env%charges(natom))
    2860              :       ! input options
    2861         4790 :       CALL section_vals_val_get(input_section, "SELF_CONSISTENT", l_val=do_sc)
    2862         4790 :       CALL section_vals_val_get(input_section, "USER_RADIUS", l_val=do_radius)
    2863         4790 :       CALL section_vals_val_get(input_section, "SHAPE_FUNCTION", i_val=shapef)
    2864         4790 :       CALL section_vals_val_get(input_section, "REFERENCE_CHARGE", i_val=refc)
    2865         4790 :       IF (do_radius) THEN
    2866            0 :          radius_type = radius_user
    2867            0 :          CALL section_vals_val_get(input_section, "ATOMIC_RADII", r_vals=radii)
    2868            0 :          IF (.NOT. SIZE(radii) == nkind) &
    2869              :             CALL cp_abort(__LOCATION__, &
    2870              :                           "Length of keyword HIRSHFELD\ATOMIC_RADII does not "// &
    2871            0 :                           "match number of atomic kinds in the input coordinate file.")
    2872              :       ELSE
    2873         4790 :          radius_type = radius_covalent
    2874              :       END IF
    2875              :       CALL set_hirshfeld_info(hirshfeld_env, shape_function_type=shapef, &
    2876              :                               iterative=do_sc, ref_charge=refc, &
    2877         4790 :                               radius_type=radius_type)
    2878              :       ! shape function
    2879         4790 :       CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set, atomic_kind_set=atomic_kind_set)
    2880              :       CALL create_shape_function(hirshfeld_env, qs_kind_set, atomic_kind_set, &
    2881         4790 :                                  radii_list=radii)
    2882              :       ! reference charges
    2883         4790 :       CALL get_qs_env(qs_env, rho=rho)
    2884         4790 :       CALL qs_rho_get(rho, rho_ao_kp=matrix_p)
    2885         4790 :       nspin = SIZE(matrix_p, 1)
    2886        19160 :       ALLOCATE (charges(natom, nspin))
    2887         4778 :       SELECT CASE (refc)
    2888              :       CASE (ref_charge_atomic)
    2889        13086 :          DO ikind = 1, nkind
    2890         8308 :             CALL get_qs_kind(qs_kind_set(ikind), zeff=zeff)
    2891         8308 :             atomic_kind => atomic_kind_set(ikind)
    2892         8308 :             CALL get_atomic_kind(atomic_kind, atom_list=atom_list)
    2893        41380 :             DO iat = 1, SIZE(atom_list)
    2894        19986 :                i = atom_list(iat)
    2895        28294 :                hirshfeld_env%charges(i) = zeff
    2896              :             END DO
    2897              :          END DO
    2898              :       CASE (ref_charge_mulliken)
    2899           12 :          CALL get_qs_env(qs_env, matrix_s_kp=matrix_s, para_env=para_env)
    2900           12 :          CALL mulliken_charges(matrix_p, matrix_s, para_env, charges)
    2901           48 :          DO iat = 1, natom
    2902          108 :             hirshfeld_env%charges(iat) = SUM(charges(iat, :))
    2903              :          END DO
    2904              :       CASE DEFAULT
    2905         4790 :          CPABORT("Unknown type of reference charge for Hirshfeld partitioning.")
    2906              :       END SELECT
    2907              :       !
    2908        33314 :       charges = 0.0_dp
    2909         4790 :       IF (hirshfeld_env%iterative) THEN
    2910              :          ! Hirshfeld-I charges
    2911           22 :          CALL comp_hirshfeld_i_charges(qs_env, hirshfeld_env, charges, unit_nr)
    2912              :       ELSE
    2913              :          ! Hirshfeld charges
    2914         4768 :          CALL comp_hirshfeld_charges(qs_env, hirshfeld_env, charges)
    2915              :       END IF
    2916         4790 :       CALL get_qs_env(qs_env, particle_set=particle_set, dft_control=dft_control)
    2917         4790 :       IF (dft_control%qs_control%gapw) THEN
    2918              :          ! GAPW: add core charges (rho_hard - rho_soft)
    2919          698 :          CALL get_qs_env(qs_env, rho0_mpole=rho0_mpole)
    2920          698 :          CALL get_rho0_mpole(rho0_mpole, mp_rho=mp_rho)
    2921         3088 :          DO iat = 1, natom
    2922         2390 :             atomic_kind => particle_set(iat)%atomic_kind
    2923         2390 :             CALL get_atomic_kind(atomic_kind, kind_number=ikind)
    2924         2390 :             CALL get_qs_kind(qs_kind_set(ikind), paw_atom=paw_atom)
    2925         3088 :             IF (paw_atom) THEN
    2926         4574 :                charges(iat, 1:nspin) = charges(iat, 1:nspin) + mp_rho(iat)%q0(1:nspin)
    2927              :             END IF
    2928              :          END DO
    2929              :       END IF
    2930              :       !
    2931         4790 :       IF (unit_nr > 0) THEN
    2932              :          CALL write_hirshfeld_charges(charges, hirshfeld_env, particle_set, &
    2933         2409 :                                       qs_kind_set, unit_nr)
    2934              :       END IF
    2935              :       ! Save the charges to the results under the tag [HIRSHFELD-CHARGES]
    2936         4790 :       CALL save_hirshfeld_charges(charges, particle_set, qs_kind_set, qs_env)
    2937              :       !
    2938         4790 :       CALL release_hirshfeld_type(hirshfeld_env)
    2939         4790 :       DEALLOCATE (charges)
    2940              : 
    2941         9580 :    END SUBROUTINE hirshfeld_charges
    2942              : 
    2943              : ! **************************************************************************************************
    2944              : !> \brief ...
    2945              : !> \param ca ...
    2946              : !> \param a ...
    2947              : !> \param cb ...
    2948              : !> \param b ...
    2949              : !> \param l ...
    2950              : ! **************************************************************************************************
    2951            4 :    SUBROUTINE project_function_a(ca, a, cb, b, l)
    2952              :       ! project function cb on ca
    2953              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: ca
    2954              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: a, cb, b
    2955              :       INTEGER, INTENT(IN)                                :: l
    2956              : 
    2957              :       INTEGER                                            :: info, n
    2958            4 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: ipiv
    2959            4 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: smat, tmat, v
    2960              : 
    2961            4 :       n = SIZE(ca)
    2962           40 :       ALLOCATE (smat(n, n), tmat(n, n), v(n, 1), ipiv(n))
    2963              : 
    2964            4 :       CALL sg_overlap(smat, l, a, a)
    2965            4 :       CALL sg_overlap(tmat, l, a, b)
    2966         1252 :       v(:, 1) = MATMUL(tmat, cb)
    2967            4 :       CALL dgesv(n, 1, smat, n, ipiv, v, n, info)
    2968            4 :       CPASSERT(info == 0)
    2969           52 :       ca(:) = v(:, 1)
    2970              : 
    2971            4 :       DEALLOCATE (smat, tmat, v, ipiv)
    2972              : 
    2973            4 :    END SUBROUTINE project_function_a
    2974              : 
    2975              : ! **************************************************************************************************
    2976              : !> \brief ...
    2977              : !> \param ca ...
    2978              : !> \param a ...
    2979              : !> \param bfun ...
    2980              : !> \param grid_atom ...
    2981              : !> \param l ...
    2982              : ! **************************************************************************************************
    2983           36 :    SUBROUTINE project_function_b(ca, a, bfun, grid_atom, l)
    2984              :       ! project function f on ca
    2985              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: ca
    2986              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: a, bfun
    2987              :       TYPE(grid_atom_type), POINTER                      :: grid_atom
    2988              :       INTEGER, INTENT(IN)                                :: l
    2989              : 
    2990              :       INTEGER                                            :: i, info, n, nr
    2991           36 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: ipiv
    2992           36 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: afun
    2993           36 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: smat, v
    2994              : 
    2995           36 :       n = SIZE(ca)
    2996           36 :       nr = grid_atom%nr
    2997          360 :       ALLOCATE (smat(n, n), v(n, 1), ipiv(n), afun(nr))
    2998              : 
    2999           36 :       CALL sg_overlap(smat, l, a, a)
    3000          468 :       DO i = 1, n
    3001        22032 :          afun(:) = grid_atom%rad(:)**l*EXP(-a(i)*grid_atom%rad2(:))
    3002        22068 :          v(i, 1) = SUM(afun(:)*bfun(:)*grid_atom%wr(:))
    3003              :       END DO
    3004           36 :       CALL dgesv(n, 1, smat, n, ipiv, v, n, info)
    3005           36 :       CPASSERT(info == 0)
    3006          468 :       ca(:) = v(:, 1)
    3007              : 
    3008           36 :       DEALLOCATE (smat, v, ipiv, afun)
    3009              : 
    3010           36 :    END SUBROUTINE project_function_b
    3011              : 
    3012              : ! **************************************************************************************************
    3013              : !> \brief Performs printing of cube files from local energy
    3014              : !> \param input input
    3015              : !> \param logger the logger
    3016              : !> \param qs_env the qs_env in which the qs_env lives
    3017              : !> \par History
    3018              : !>      07.2019 created
    3019              : !> \author JGH
    3020              : ! **************************************************************************************************
    3021        11299 :    SUBROUTINE qs_scf_post_local_energy(input, logger, qs_env)
    3022              :       TYPE(section_vals_type), POINTER                   :: input
    3023              :       TYPE(cp_logger_type), POINTER                      :: logger
    3024              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3025              : 
    3026              :       CHARACTER(len=*), PARAMETER :: routineN = 'qs_scf_post_local_energy'
    3027              : 
    3028              :       CHARACTER(LEN=default_path_length)                 :: filename, my_pos_cube
    3029              :       INTEGER                                            :: handle, io_unit, natom, unit_nr
    3030              :       LOGICAL                                            :: append_cube, gapw, gapw_xc, mpi_io
    3031              :       TYPE(dft_control_type), POINTER                    :: dft_control
    3032              :       TYPE(particle_list_type), POINTER                  :: particles
    3033              :       TYPE(pw_env_type), POINTER                         :: pw_env
    3034              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    3035              :       TYPE(pw_r3d_rs_type)                               :: eden
    3036              :       TYPE(qs_subsys_type), POINTER                      :: subsys
    3037              :       TYPE(section_vals_type), POINTER                   :: dft_section
    3038              : 
    3039        11299 :       CALL timeset(routineN, handle)
    3040        11299 :       io_unit = cp_logger_get_default_io_unit(logger)
    3041        11299 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3042              :                                            "DFT%PRINT%LOCAL_ENERGY_CUBE"), cp_p_file)) THEN
    3043           32 :          dft_section => section_vals_get_subs_vals(input, "DFT")
    3044           32 :          CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, natom=natom)
    3045           32 :          gapw = dft_control%qs_control%gapw
    3046           32 :          gapw_xc = dft_control%qs_control%gapw_xc
    3047           32 :          CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, subsys=subsys)
    3048           32 :          CALL qs_subsys_get(subsys, particles=particles)
    3049           32 :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    3050           32 :          CALL auxbas_pw_pool%create_pw(eden)
    3051              :          !
    3052           32 :          CALL qs_local_energy(qs_env, eden)
    3053              :          !
    3054           32 :          append_cube = section_get_lval(input, "DFT%PRINT%LOCAL_ENERGY_CUBE%APPEND")
    3055           32 :          IF (append_cube) THEN
    3056            0 :             my_pos_cube = "APPEND"
    3057              :          ELSE
    3058           32 :             my_pos_cube = "REWIND"
    3059              :          END IF
    3060           32 :          mpi_io = .TRUE.
    3061              :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%LOCAL_ENERGY_CUBE", &
    3062              :                                         extension=".cube", middle_name="local_energy", &
    3063           32 :                                         file_position=my_pos_cube, mpi_io=mpi_io)
    3064              :          CALL cp_pw_to_cube(eden, &
    3065              :                             unit_nr, "LOCAL ENERGY", particles=particles, &
    3066              :                             stride=section_get_ivals(dft_section, &
    3067           32 :                                                      "PRINT%LOCAL_ENERGY_CUBE%STRIDE"), mpi_io=mpi_io)
    3068           32 :          IF (io_unit > 0) THEN
    3069           16 :             INQUIRE (UNIT=unit_nr, NAME=filename)
    3070           16 :             IF (gapw .OR. gapw_xc) THEN
    3071              :                WRITE (UNIT=io_unit, FMT="(/,T3,A,A)") &
    3072            0 :                   "The soft part of the local energy is written to the file: ", TRIM(ADJUSTL(filename))
    3073              :             ELSE
    3074              :                WRITE (UNIT=io_unit, FMT="(/,T3,A,A)") &
    3075           16 :                   "The local energy is written to the file: ", TRIM(ADJUSTL(filename))
    3076              :             END IF
    3077              :          END IF
    3078              :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
    3079           32 :                                            "DFT%PRINT%LOCAL_ENERGY_CUBE", mpi_io=mpi_io)
    3080              :          !
    3081           32 :          CALL auxbas_pw_pool%give_back_pw(eden)
    3082              :       END IF
    3083        11299 :       CALL timestop(handle)
    3084              : 
    3085        11299 :    END SUBROUTINE qs_scf_post_local_energy
    3086              : 
    3087              : ! **************************************************************************************************
    3088              : !> \brief Performs printing of cube files from local energy
    3089              : !> \param input input
    3090              : !> \param logger the logger
    3091              : !> \param qs_env the qs_env in which the qs_env lives
    3092              : !> \par History
    3093              : !>      07.2019 created
    3094              : !> \author JGH
    3095              : ! **************************************************************************************************
    3096        11299 :    SUBROUTINE qs_scf_post_local_stress(input, logger, qs_env)
    3097              :       TYPE(section_vals_type), POINTER                   :: input
    3098              :       TYPE(cp_logger_type), POINTER                      :: logger
    3099              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3100              : 
    3101              :       CHARACTER(len=*), PARAMETER :: routineN = 'qs_scf_post_local_stress'
    3102              : 
    3103              :       CHARACTER(LEN=default_path_length)                 :: filename, my_pos_cube
    3104              :       INTEGER                                            :: handle, io_unit, natom, unit_nr
    3105              :       LOGICAL                                            :: append_cube, gapw, gapw_xc, mpi_io
    3106              :       REAL(KIND=dp)                                      :: beta
    3107              :       TYPE(dft_control_type), POINTER                    :: dft_control
    3108              :       TYPE(particle_list_type), POINTER                  :: particles
    3109              :       TYPE(pw_env_type), POINTER                         :: pw_env
    3110              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    3111              :       TYPE(pw_r3d_rs_type)                               :: stress
    3112              :       TYPE(qs_subsys_type), POINTER                      :: subsys
    3113              :       TYPE(section_vals_type), POINTER                   :: dft_section
    3114              : 
    3115        11299 :       CALL timeset(routineN, handle)
    3116        11299 :       io_unit = cp_logger_get_default_io_unit(logger)
    3117        11299 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3118              :                                            "DFT%PRINT%LOCAL_STRESS_CUBE"), cp_p_file)) THEN
    3119           30 :          dft_section => section_vals_get_subs_vals(input, "DFT")
    3120           30 :          CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, natom=natom)
    3121           30 :          gapw = dft_control%qs_control%gapw
    3122           30 :          gapw_xc = dft_control%qs_control%gapw_xc
    3123           30 :          CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, subsys=subsys)
    3124           30 :          CALL qs_subsys_get(subsys, particles=particles)
    3125           30 :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    3126           30 :          CALL auxbas_pw_pool%create_pw(stress)
    3127              :          !
    3128              :          ! use beta=0: kinetic energy density in symmetric form
    3129           30 :          beta = 0.0_dp
    3130           30 :          CALL qs_local_stress(qs_env, beta=beta)
    3131              :          !
    3132           30 :          append_cube = section_get_lval(input, "DFT%PRINT%LOCAL_STRESS_CUBE%APPEND")
    3133           30 :          IF (append_cube) THEN
    3134            0 :             my_pos_cube = "APPEND"
    3135              :          ELSE
    3136           30 :             my_pos_cube = "REWIND"
    3137              :          END IF
    3138           30 :          mpi_io = .TRUE.
    3139              :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%LOCAL_STRESS_CUBE", &
    3140              :                                         extension=".cube", middle_name="local_stress", &
    3141           30 :                                         file_position=my_pos_cube, mpi_io=mpi_io)
    3142              :          CALL cp_pw_to_cube(stress, &
    3143              :                             unit_nr, "LOCAL STRESS", particles=particles, &
    3144              :                             stride=section_get_ivals(dft_section, &
    3145           30 :                                                      "PRINT%LOCAL_STRESS_CUBE%STRIDE"), mpi_io=mpi_io)
    3146           30 :          IF (io_unit > 0) THEN
    3147           15 :             INQUIRE (UNIT=unit_nr, NAME=filename)
    3148           15 :             WRITE (UNIT=io_unit, FMT="(/,T3,A)") "Write 1/3*Tr(sigma) to cube file"
    3149           15 :             IF (gapw .OR. gapw_xc) THEN
    3150              :                WRITE (UNIT=io_unit, FMT="(T3,A,A)") &
    3151            0 :                   "The soft part of the local stress is written to the file: ", TRIM(ADJUSTL(filename))
    3152              :             ELSE
    3153              :                WRITE (UNIT=io_unit, FMT="(T3,A,A)") &
    3154           15 :                   "The local stress is written to the file: ", TRIM(ADJUSTL(filename))
    3155              :             END IF
    3156              :          END IF
    3157              :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
    3158           30 :                                            "DFT%PRINT%LOCAL_STRESS_CUBE", mpi_io=mpi_io)
    3159              :          !
    3160           30 :          CALL auxbas_pw_pool%give_back_pw(stress)
    3161              :       END IF
    3162              : 
    3163        11299 :       CALL timestop(handle)
    3164              : 
    3165        11299 :    END SUBROUTINE qs_scf_post_local_stress
    3166              : 
    3167              : ! **************************************************************************************************
    3168              : !> \brief Performs printing of cube files related to the implicit Poisson solver
    3169              : !> \param input input
    3170              : !> \param logger the logger
    3171              : !> \param qs_env the qs_env in which the qs_env lives
    3172              : !> \par History
    3173              : !>      03.2016 refactored from write_mo_free_results [Hossein Bani-Hashemian]
    3174              : !> \author Mohammad Hossein Bani-Hashemian
    3175              : ! **************************************************************************************************
    3176        11299 :    SUBROUTINE qs_scf_post_ps_implicit(input, logger, qs_env)
    3177              :       TYPE(section_vals_type), POINTER                   :: input
    3178              :       TYPE(cp_logger_type), POINTER                      :: logger
    3179              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3180              : 
    3181              :       CHARACTER(len=*), PARAMETER :: routineN = 'qs_scf_post_ps_implicit'
    3182              : 
    3183              :       CHARACTER(LEN=default_path_length)                 :: filename, my_pos_cube
    3184              :       INTEGER                                            :: boundary_condition, handle, i, j, &
    3185              :                                                             n_cstr, n_tiles, unit_nr
    3186              :       LOGICAL :: append_cube, do_cstr_charge_cube, do_dielectric_cube, do_dirichlet_bc_cube, &
    3187              :          has_dirichlet_bc, has_implicit_ps, mpi_io, tile_cubes
    3188              :       TYPE(particle_list_type), POINTER                  :: particles
    3189              :       TYPE(pw_env_type), POINTER                         :: pw_env
    3190              :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
    3191              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    3192              :       TYPE(pw_r3d_rs_type)                               :: aux_r
    3193              :       TYPE(pw_r3d_rs_type), POINTER                      :: dirichlet_tile
    3194              :       TYPE(qs_subsys_type), POINTER                      :: subsys
    3195              :       TYPE(section_vals_type), POINTER                   :: dft_section
    3196              : 
    3197        11299 :       CALL timeset(routineN, handle)
    3198              : 
    3199        11299 :       NULLIFY (pw_env, auxbas_pw_pool, dft_section, particles)
    3200              : 
    3201        11299 :       dft_section => section_vals_get_subs_vals(input, "DFT")
    3202        11299 :       CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, subsys=subsys)
    3203        11299 :       CALL qs_subsys_get(subsys, particles=particles)
    3204        11299 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    3205              : 
    3206        11299 :       has_implicit_ps = .FALSE.
    3207        11299 :       CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
    3208        11299 :       IF (pw_env%poisson_env%parameters%solver == pw_poisson_implicit) has_implicit_ps = .TRUE.
    3209              : 
    3210              :       ! Write the dielectric constant into a cube file
    3211              :       do_dielectric_cube = BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3212        11299 :                                                             "DFT%PRINT%IMPLICIT_PSOLVER%DIELECTRIC_CUBE"), cp_p_file)
    3213        11299 :       IF (has_implicit_ps .AND. do_dielectric_cube) THEN
    3214            0 :          append_cube = section_get_lval(input, "DFT%PRINT%IMPLICIT_PSOLVER%DIELECTRIC_CUBE%APPEND")
    3215            0 :          my_pos_cube = "REWIND"
    3216            0 :          IF (append_cube) THEN
    3217            0 :             my_pos_cube = "APPEND"
    3218              :          END IF
    3219            0 :          mpi_io = .TRUE.
    3220              :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%IMPLICIT_PSOLVER%DIELECTRIC_CUBE", &
    3221              :                                         extension=".cube", middle_name="DIELECTRIC_CONSTANT", file_position=my_pos_cube, &
    3222            0 :                                         mpi_io=mpi_io)
    3223            0 :          CALL pw_env_get(pw_env, poisson_env=poisson_env, auxbas_pw_pool=auxbas_pw_pool)
    3224            0 :          CALL auxbas_pw_pool%create_pw(aux_r)
    3225              : 
    3226            0 :          boundary_condition = pw_env%poisson_env%parameters%ps_implicit_params%boundary_condition
    3227            0 :          SELECT CASE (boundary_condition)
    3228              :          CASE (PERIODIC_BC, MIXED_PERIODIC_BC)
    3229            0 :             CALL pw_copy(poisson_env%implicit_env%dielectric%eps, aux_r)
    3230              :          CASE (MIXED_BC, NEUMANN_BC)
    3231              :             CALL pw_shrink(pw_env%poisson_env%parameters%ps_implicit_params%neumann_directions, &
    3232              :                            pw_env%poisson_env%implicit_env%dct_env%dests_shrink, &
    3233              :                            pw_env%poisson_env%implicit_env%dct_env%srcs_shrink, &
    3234              :                            pw_env%poisson_env%implicit_env%dct_env%bounds_local_shftd, &
    3235            0 :                            poisson_env%implicit_env%dielectric%eps, aux_r)
    3236              :          END SELECT
    3237              : 
    3238              :          CALL cp_pw_to_cube(aux_r, unit_nr, "DIELECTRIC CONSTANT", particles=particles, &
    3239              :                             stride=section_get_ivals(dft_section, "PRINT%IMPLICIT_PSOLVER%DIELECTRIC_CUBE%STRIDE"), &
    3240            0 :                             mpi_io=mpi_io)
    3241              :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
    3242            0 :                                            "DFT%PRINT%IMPLICIT_PSOLVER%DIELECTRIC_CUBE", mpi_io=mpi_io)
    3243              : 
    3244            0 :          CALL auxbas_pw_pool%give_back_pw(aux_r)
    3245              :       END IF
    3246              : 
    3247              :       ! Write Dirichlet constraint charges into a cube file
    3248              :       do_cstr_charge_cube = BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3249        11299 :                                                              "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_CSTR_CHARGE_CUBE"), cp_p_file)
    3250              : 
    3251        11299 :       has_dirichlet_bc = .FALSE.
    3252        11299 :       IF (has_implicit_ps) THEN
    3253           86 :          boundary_condition = pw_env%poisson_env%parameters%ps_implicit_params%boundary_condition
    3254           86 :          IF (boundary_condition == MIXED_PERIODIC_BC .OR. boundary_condition == MIXED_BC) THEN
    3255           60 :             has_dirichlet_bc = .TRUE.
    3256              :          END IF
    3257              :       END IF
    3258              : 
    3259        11299 :       IF (has_implicit_ps .AND. do_cstr_charge_cube .AND. has_dirichlet_bc) THEN
    3260              :          append_cube = section_get_lval(input, &
    3261            0 :                                         "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_CSTR_CHARGE_CUBE%APPEND")
    3262            0 :          my_pos_cube = "REWIND"
    3263            0 :          IF (append_cube) THEN
    3264            0 :             my_pos_cube = "APPEND"
    3265              :          END IF
    3266            0 :          mpi_io = .TRUE.
    3267              :          unit_nr = cp_print_key_unit_nr(logger, input, &
    3268              :                                         "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_CSTR_CHARGE_CUBE", &
    3269              :                                         extension=".cube", middle_name="dirichlet_cstr_charge", file_position=my_pos_cube, &
    3270            0 :                                         mpi_io=mpi_io)
    3271            0 :          CALL pw_env_get(pw_env, poisson_env=poisson_env, auxbas_pw_pool=auxbas_pw_pool)
    3272            0 :          CALL auxbas_pw_pool%create_pw(aux_r)
    3273              : 
    3274            0 :          boundary_condition = pw_env%poisson_env%parameters%ps_implicit_params%boundary_condition
    3275            0 :          SELECT CASE (boundary_condition)
    3276              :          CASE (MIXED_PERIODIC_BC)
    3277            0 :             CALL pw_copy(poisson_env%implicit_env%cstr_charge, aux_r)
    3278              :          CASE (MIXED_BC)
    3279              :             CALL pw_shrink(pw_env%poisson_env%parameters%ps_implicit_params%neumann_directions, &
    3280              :                            pw_env%poisson_env%implicit_env%dct_env%dests_shrink, &
    3281              :                            pw_env%poisson_env%implicit_env%dct_env%srcs_shrink, &
    3282              :                            pw_env%poisson_env%implicit_env%dct_env%bounds_local_shftd, &
    3283            0 :                            poisson_env%implicit_env%cstr_charge, aux_r)
    3284              :          END SELECT
    3285              : 
    3286              :          CALL cp_pw_to_cube(aux_r, unit_nr, "DIRICHLET CONSTRAINT CHARGE", particles=particles, &
    3287              :                             stride=section_get_ivals(dft_section, "PRINT%IMPLICIT_PSOLVER%DIRICHLET_CSTR_CHARGE_CUBE%STRIDE"), &
    3288            0 :                             mpi_io=mpi_io)
    3289              :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
    3290            0 :                                            "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_CSTR_CHARGE_CUBE", mpi_io=mpi_io)
    3291              : 
    3292            0 :          CALL auxbas_pw_pool%give_back_pw(aux_r)
    3293              :       END IF
    3294              : 
    3295              :       ! Write Dirichlet type constranits into cube files
    3296              :       do_dirichlet_bc_cube = BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3297        11299 :                                                               "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE"), cp_p_file)
    3298        11299 :       has_dirichlet_bc = .FALSE.
    3299        11299 :       IF (has_implicit_ps) THEN
    3300           86 :          boundary_condition = pw_env%poisson_env%parameters%ps_implicit_params%boundary_condition
    3301           86 :          IF (boundary_condition == MIXED_PERIODIC_BC .OR. boundary_condition == MIXED_BC) THEN
    3302           60 :             has_dirichlet_bc = .TRUE.
    3303              :          END IF
    3304              :       END IF
    3305              : 
    3306        11299 :       IF (has_implicit_ps .AND. has_dirichlet_bc .AND. do_dirichlet_bc_cube) THEN
    3307            0 :          append_cube = section_get_lval(input, "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE%APPEND")
    3308            0 :          my_pos_cube = "REWIND"
    3309            0 :          IF (append_cube) THEN
    3310            0 :             my_pos_cube = "APPEND"
    3311              :          END IF
    3312            0 :          tile_cubes = section_get_lval(input, "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE%TILE_CUBES")
    3313              : 
    3314            0 :          CALL pw_env_get(pw_env, poisson_env=poisson_env, auxbas_pw_pool=auxbas_pw_pool)
    3315            0 :          CALL auxbas_pw_pool%create_pw(aux_r)
    3316            0 :          CALL pw_zero(aux_r)
    3317              : 
    3318            0 :          IF (tile_cubes) THEN
    3319              :             ! one cube file per tile
    3320            0 :             n_cstr = SIZE(poisson_env%implicit_env%contacts)
    3321            0 :             DO j = 1, n_cstr
    3322            0 :                n_tiles = poisson_env%implicit_env%contacts(j)%dirichlet_bc%n_tiles
    3323            0 :                DO i = 1, n_tiles
    3324              :                   filename = "dirichlet_cstr_"//TRIM(ADJUSTL(cp_to_string(j)))// &
    3325            0 :                              "_tile_"//TRIM(ADJUSTL(cp_to_string(i)))
    3326            0 :                   mpi_io = .TRUE.
    3327              :                   unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE", &
    3328              :                                                  extension=".cube", middle_name=filename, file_position=my_pos_cube, &
    3329            0 :                                                  mpi_io=mpi_io)
    3330              : 
    3331            0 :                   CALL pw_copy(poisson_env%implicit_env%contacts(j)%dirichlet_bc%tiles(i)%tile%tile_pw, aux_r)
    3332              : 
    3333              :                   CALL cp_pw_to_cube(aux_r, unit_nr, "DIRICHLET TYPE CONSTRAINT", particles=particles, &
    3334              :                                      stride=section_get_ivals(dft_section, "PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE%STRIDE"), &
    3335            0 :                                      mpi_io=mpi_io)
    3336              :                   CALL cp_print_key_finished_output(unit_nr, logger, input, &
    3337            0 :                                                     "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE", mpi_io=mpi_io)
    3338              :                END DO
    3339              :             END DO
    3340              :          ELSE
    3341              :             ! a single cube file
    3342            0 :             NULLIFY (dirichlet_tile)
    3343            0 :             ALLOCATE (dirichlet_tile)
    3344            0 :             CALL auxbas_pw_pool%create_pw(dirichlet_tile)
    3345            0 :             CALL pw_zero(dirichlet_tile)
    3346            0 :             mpi_io = .TRUE.
    3347              :             unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE", &
    3348              :                                            extension=".cube", middle_name="DIRICHLET_CSTR", file_position=my_pos_cube, &
    3349            0 :                                            mpi_io=mpi_io)
    3350              : 
    3351            0 :             n_cstr = SIZE(poisson_env%implicit_env%contacts)
    3352            0 :             DO j = 1, n_cstr
    3353            0 :                n_tiles = poisson_env%implicit_env%contacts(j)%dirichlet_bc%n_tiles
    3354            0 :                DO i = 1, n_tiles
    3355            0 :                   CALL pw_copy(poisson_env%implicit_env%contacts(j)%dirichlet_bc%tiles(i)%tile%tile_pw, dirichlet_tile)
    3356            0 :                   CALL pw_axpy(dirichlet_tile, aux_r)
    3357              :                END DO
    3358              :             END DO
    3359              : 
    3360              :             CALL cp_pw_to_cube(aux_r, unit_nr, "DIRICHLET TYPE CONSTRAINT", particles=particles, &
    3361              :                                stride=section_get_ivals(dft_section, "PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE%STRIDE"), &
    3362            0 :                                mpi_io=mpi_io)
    3363              :             CALL cp_print_key_finished_output(unit_nr, logger, input, &
    3364            0 :                                               "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE", mpi_io=mpi_io)
    3365            0 :             CALL auxbas_pw_pool%give_back_pw(dirichlet_tile)
    3366            0 :             DEALLOCATE (dirichlet_tile)
    3367              :          END IF
    3368              : 
    3369            0 :          CALL auxbas_pw_pool%give_back_pw(aux_r)
    3370              :       END IF
    3371              : 
    3372        11299 :       CALL timestop(handle)
    3373              : 
    3374        11299 :    END SUBROUTINE qs_scf_post_ps_implicit
    3375              : 
    3376              : !**************************************************************************************************
    3377              : !> \brief write an adjacency (interaction) matrix
    3378              : !> \param qs_env qs environment
    3379              : !> \param input the input
    3380              : !> \author Mohammad Hossein Bani-Hashemian
    3381              : ! **************************************************************************************************
    3382        11299 :    SUBROUTINE write_adjacency_matrix(qs_env, input)
    3383              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3384              :       TYPE(section_vals_type), POINTER                   :: input
    3385              : 
    3386              :       CHARACTER(len=*), PARAMETER :: routineN = 'write_adjacency_matrix'
    3387              : 
    3388              :       INTEGER                                            :: adjm_size, colind, handle, iatom, ikind, &
    3389              :                                                             ind, jatom, jkind, k, natom, nkind, &
    3390              :                                                             output_unit, rowind, unit_nr
    3391        11299 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: interact_adjm
    3392              :       LOGICAL                                            :: do_adjm_write, do_symmetric
    3393              :       TYPE(cp_logger_type), POINTER                      :: logger
    3394        11299 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list_a, basis_set_list_b
    3395              :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
    3396              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    3397              :       TYPE(neighbor_list_iterator_p_type), &
    3398        11299 :          DIMENSION(:), POINTER                           :: nl_iterator
    3399              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    3400        11299 :          POINTER                                         :: nl
    3401        11299 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    3402              :       TYPE(section_vals_type), POINTER                   :: dft_section
    3403              : 
    3404        11299 :       CALL timeset(routineN, handle)
    3405              : 
    3406        11299 :       NULLIFY (dft_section)
    3407              : 
    3408        11299 :       logger => cp_get_default_logger()
    3409        11299 :       output_unit = cp_logger_get_default_io_unit(logger)
    3410              : 
    3411        11299 :       dft_section => section_vals_get_subs_vals(input, "DFT")
    3412              :       do_adjm_write = BTEST(cp_print_key_should_output(logger%iter_info, dft_section, &
    3413        11299 :                                                        "PRINT%ADJMAT_WRITE"), cp_p_file)
    3414              : 
    3415        11299 :       IF (do_adjm_write) THEN
    3416           28 :          NULLIFY (qs_kind_set, nl_iterator)
    3417           28 :          NULLIFY (basis_set_list_a, basis_set_list_b, basis_set_a, basis_set_b)
    3418              : 
    3419           28 :          CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set, sab_orb=nl, natom=natom, para_env=para_env)
    3420              : 
    3421           28 :          nkind = SIZE(qs_kind_set)
    3422           28 :          CPASSERT(SIZE(nl) > 0)
    3423           28 :          CALL get_neighbor_list_set_p(neighbor_list_sets=nl, symmetric=do_symmetric)
    3424           28 :          CPASSERT(do_symmetric)
    3425          216 :          ALLOCATE (basis_set_list_a(nkind), basis_set_list_b(nkind))
    3426           28 :          CALL basis_set_list_setup(basis_set_list_a, "ORB", qs_kind_set)
    3427           28 :          CALL basis_set_list_setup(basis_set_list_b, "ORB", qs_kind_set)
    3428              : 
    3429           28 :          adjm_size = ((natom + 1)*natom)/2
    3430           84 :          ALLOCATE (interact_adjm(4*adjm_size))
    3431          620 :          interact_adjm = 0
    3432              : 
    3433           28 :          NULLIFY (nl_iterator)
    3434           28 :          CALL neighbor_list_iterator_create(nl_iterator, nl)
    3435         2021 :          DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
    3436              :             CALL get_iterator_info(nl_iterator, &
    3437              :                                    ikind=ikind, jkind=jkind, &
    3438         1993 :                                    iatom=iatom, jatom=jatom)
    3439              : 
    3440         1993 :             basis_set_a => basis_set_list_a(ikind)%gto_basis_set
    3441         1993 :             IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
    3442         1993 :             basis_set_b => basis_set_list_b(jkind)%gto_basis_set
    3443         1993 :             IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
    3444              : 
    3445              :             ! move everything to the upper triangular part
    3446         1993 :             IF (iatom <= jatom) THEN
    3447              :                rowind = iatom
    3448              :                colind = jatom
    3449              :             ELSE
    3450          670 :                rowind = jatom
    3451          670 :                colind = iatom
    3452              :                ! swap the kinds too
    3453              :                ikind = ikind + jkind
    3454          670 :                jkind = ikind - jkind
    3455          670 :                ikind = ikind - jkind
    3456              :             END IF
    3457              : 
    3458              :             ! indexing upper triangular matrix
    3459         1993 :             ind = adjm_size - (natom - rowind + 1)*((natom - rowind + 1) + 1)/2 + colind - rowind + 1
    3460              :             ! convert the upper triangular matrix into a adjm_size x 4 matrix
    3461              :             ! columns are: iatom, jatom, ikind, jkind
    3462         1993 :             interact_adjm((ind - 1)*4 + 1) = rowind
    3463         1993 :             interact_adjm((ind - 1)*4 + 2) = colind
    3464         1993 :             interact_adjm((ind - 1)*4 + 3) = ikind
    3465         1993 :             interact_adjm((ind - 1)*4 + 4) = jkind
    3466              :          END DO
    3467              : 
    3468           28 :          CALL para_env%sum(interact_adjm)
    3469              : 
    3470              :          unit_nr = cp_print_key_unit_nr(logger, dft_section, "PRINT%ADJMAT_WRITE", &
    3471              :                                         extension=".adjmat", file_form="FORMATTED", &
    3472           28 :                                         file_status="REPLACE")
    3473           28 :          IF (unit_nr > 0) THEN
    3474           14 :             WRITE (unit_nr, "(1A,2X,1A,5X,1A,4X,A5,3X,A5)") "#", "iatom", "jatom", "ikind", "jkind"
    3475           88 :             DO k = 1, 4*adjm_size, 4
    3476              :                ! print only the interacting atoms
    3477           88 :                IF (interact_adjm(k) > 0 .AND. interact_adjm(k + 1) > 0) THEN
    3478           74 :                   WRITE (unit_nr, "(I8,2X,I8,3X,I6,2X,I6)") interact_adjm(k:k + 3)
    3479              :                END IF
    3480              :             END DO
    3481              :          END IF
    3482              : 
    3483           28 :          CALL cp_print_key_finished_output(unit_nr, logger, dft_section, "PRINT%ADJMAT_WRITE")
    3484              : 
    3485           28 :          CALL neighbor_list_iterator_release(nl_iterator)
    3486           56 :          DEALLOCATE (basis_set_list_a, basis_set_list_b)
    3487              :       END IF
    3488              : 
    3489        11299 :       CALL timestop(handle)
    3490              : 
    3491        22598 :    END SUBROUTINE write_adjacency_matrix
    3492              : 
    3493              : ! **************************************************************************************************
    3494              : !> \brief Updates Hartree potential with MP2 density. Important for REPEAT charges
    3495              : !> \param rho ...
    3496              : !> \param qs_env ...
    3497              : !> \author Vladimir Rybkin
    3498              : ! **************************************************************************************************
    3499          322 :    SUBROUTINE update_hartree_with_mp2(rho, qs_env)
    3500              :       TYPE(qs_rho_type), POINTER                         :: rho
    3501              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3502              : 
    3503              :       LOGICAL                                            :: use_virial
    3504              :       TYPE(pw_c1d_gs_type)                               :: rho_tot_gspace, v_hartree_gspace
    3505              :       TYPE(pw_c1d_gs_type), POINTER                      :: rho_core
    3506              :       TYPE(pw_env_type), POINTER                         :: pw_env
    3507              :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
    3508              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    3509              :       TYPE(pw_r3d_rs_type), POINTER                      :: v_hartree_rspace
    3510              :       TYPE(qs_energy_type), POINTER                      :: energy
    3511              :       TYPE(virial_type), POINTER                         :: virial
    3512              : 
    3513          322 :       NULLIFY (auxbas_pw_pool, pw_env, poisson_env, energy, rho_core, v_hartree_rspace, virial)
    3514              :       CALL get_qs_env(qs_env, pw_env=pw_env, energy=energy, &
    3515              :                       rho_core=rho_core, virial=virial, &
    3516          322 :                       v_hartree_rspace=v_hartree_rspace)
    3517              : 
    3518          322 :       use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
    3519              : 
    3520              :       IF (.NOT. use_virial) THEN
    3521              : 
    3522              :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
    3523          268 :                          poisson_env=poisson_env)
    3524          268 :          CALL auxbas_pw_pool%create_pw(v_hartree_gspace)
    3525          268 :          CALL auxbas_pw_pool%create_pw(rho_tot_gspace)
    3526              : 
    3527          268 :          CALL calc_rho_tot_gspace(rho_tot_gspace, qs_env, rho)
    3528              :          CALL pw_poisson_solve(poisson_env, rho_tot_gspace, energy%hartree, &
    3529          268 :                                v_hartree_gspace, rho_core=rho_core)
    3530              : 
    3531          268 :          CALL pw_transfer(v_hartree_gspace, v_hartree_rspace)
    3532          268 :          CALL pw_scale(v_hartree_rspace, v_hartree_rspace%pw_grid%dvol)
    3533              : 
    3534          268 :          CALL auxbas_pw_pool%give_back_pw(v_hartree_gspace)
    3535          268 :          CALL auxbas_pw_pool%give_back_pw(rho_tot_gspace)
    3536              :       END IF
    3537              : 
    3538          322 :    END SUBROUTINE update_hartree_with_mp2
    3539              : 
    3540              : END MODULE qs_scf_post_gpw
        

Generated by: LCOV version 2.0-1