LCOV - code coverage report
Current view: top level - src - qs_scf_post_gpw.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:4c33f95) Lines: 1353 1530 88.4 %
Date: 2025-01-30 06:53:08 Functions: 23 23 100.0 %

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

Generated by: LCOV version 1.15