LCOV - code coverage report
Current view: top level - src - qs_scf_post_gpw.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:9ccafda) Lines: 91.3 % 1757 1605
Test Date: 2026-10-15 00:55:44 Functions: 97.2 % 36 35

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief 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 casino_utils,                    ONLY: write_casino
      26              :    USE cell_types,                      ONLY: cell_type
      27              :    USE commutator_rpnl,                 ONLY: build_com_mom_nl
      28              :    USE cp_array_utils,                  ONLY: cp_1d_r_p_type
      29              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      30              :    USE cp_control_types,                ONLY: dft_control_type,&
      31              :                                               rtp_control_type
      32              :    USE cp_dbcsr_api,                    ONLY: dbcsr_add,&
      33              :                                               dbcsr_create,&
      34              :                                               dbcsr_p_type,&
      35              :                                               dbcsr_scale,&
      36              :                                               dbcsr_set,&
      37              :                                               dbcsr_type,&
      38              :                                               dbcsr_type_antisymmetric
      39              :    USE cp_dbcsr_contrib,                ONLY: dbcsr_checksum
      40              :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      41              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      42              :                                               dbcsr_allocate_matrix_set,&
      43              :                                               dbcsr_deallocate_matrix_set
      44              :    USE cp_dbcsr_output,                 ONLY: cp_dbcsr_write_sparse_matrix
      45              :    USE cp_ddapc_util,                   ONLY: get_ddapc
      46              :    USE cp_fm_diag,                      ONLY: choose_eigv_solver
      47              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      48              :                                               cp_fm_struct_release,&
      49              :                                               cp_fm_struct_type
      50              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      51              :                                               cp_fm_get_info,&
      52              :                                               cp_fm_init_random,&
      53              :                                               cp_fm_release,&
      54              :                                               cp_fm_to_fm,&
      55              :                                               cp_fm_type
      56              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      57              :                                               cp_logger_get_default_io_unit,&
      58              :                                               cp_logger_type,&
      59              :                                               cp_to_string
      60              :    USE cp_output_handling,              ONLY: cp_iter_string,&
      61              :                                               cp_p_file,&
      62              :                                               cp_print_key_finished_output,&
      63              :                                               cp_print_key_should_output,&
      64              :                                               cp_print_key_unit_nr
      65              :    USE cp_output_handling_openpmd,      ONLY: cp_openpmd_close_iterations,&
      66              :                                               cp_openpmd_print_key_finished_output,&
      67              :                                               cp_openpmd_print_key_unit_nr
      68              :    USE cp_realspace_grid_cube,          ONLY: cp_pw_to_cube
      69              :    USE cp_realspace_grid_openpmd,       ONLY: cp_pw_to_openpmd
      70              :    USE cp_result_methods,               ONLY: get_results
      71              :    USE cp_result_types,                 ONLY: cp_result_type
      72              :    USE dct,                             ONLY: pw_shrink
      73              :    USE ed_analysis,                     ONLY: edmf_analysis
      74              :    USE eeq_method,                      ONLY: eeq_print
      75              :    USE et_coupling_types,               ONLY: set_et_coupling_type
      76              :    USE gapw_gspace_reconstruction,      ONLY: calculate_rhotot_elec_gspace
      77              :    USE hfx_ri,                          ONLY: print_ri_hfx
      78              :    USE hirshfeld_methods,               ONLY: comp_hirshfeld_charges,&
      79              :                                               comp_hirshfeld_i_charges,&
      80              :                                               create_shape_function,&
      81              :                                               save_hirshfeld_charges,&
      82              :                                               write_hirshfeld_charges
      83              :    USE hirshfeld_types,                 ONLY: create_hirshfeld_type,&
      84              :                                               hirshfeld_type,&
      85              :                                               release_hirshfeld_type,&
      86              :                                               set_hirshfeld_info
      87              :    USE iao_analysis,                    ONLY: iao_wfn_analysis
      88              :    USE iao_types,                       ONLY: iao_env_type,&
      89              :                                               iao_read_input
      90              :    USE input_constants,                 ONLY: &
      91              :         do_loc_both, do_loc_homo, do_loc_jacobi, do_loc_lumo, do_loc_mixed, do_loc_none, &
      92              :         moments_format_trajectory, ot_precond_full_all, ot_precond_full_all_covariant, &
      93              :         radius_covalent, radius_user, ref_charge_atomic, ref_charge_mulliken
      94              :    USE input_section_types,             ONLY: section_get_ival,&
      95              :                                               section_get_ivals,&
      96              :                                               section_get_lval,&
      97              :                                               section_get_rval,&
      98              :                                               section_vals_get,&
      99              :                                               section_vals_get_subs_vals,&
     100              :                                               section_vals_type,&
     101              :                                               section_vals_val_get
     102              :    USE kinds,                           ONLY: default_path_length,&
     103              :                                               default_string_length,&
     104              :                                               dp
     105              :    USE kpoint_mo_dump,                  ONLY: write_kpoint_mo_data
     106              :    USE kpoint_types,                    ONLY: kpoint_type
     107              :    USE localized_moments,               ONLY: calculate_kg_moments
     108              :    USE mao_wfn_analysis,                ONLY: mao_analysis
     109              :    USE mathconstants,                   ONLY: pi
     110              :    USE memory_utilities,                ONLY: reallocate
     111              :    USE message_passing,                 ONLY: mp_para_env_type
     112              :    USE minbas_wfn_analysis,             ONLY: minbas_analysis
     113              :    USE molden_utils,                    ONLY: write_mos_molden
     114              :    USE molecule_types,                  ONLY: molecule_type
     115              :    USE mulliken,                        ONLY: mulliken_charges
     116              :    USE orbital_pointers,                ONLY: indso
     117              :    USE particle_list_types,             ONLY: particle_list_type
     118              :    USE particle_types,                  ONLY: particle_type
     119              :    USE physcon,                         ONLY: a_bohr,&
     120              :                                               angstrom,&
     121              :                                               debye,&
     122              :                                               evolt
     123              :    USE population_analyses,             ONLY: lowdin_population_analysis,&
     124              :                                               mulliken_population_analysis
     125              :    USE preconditioner_types,            ONLY: preconditioner_type
     126              :    USE ps_implicit_types,               ONLY: MIXED_BC,&
     127              :                                               MIXED_PERIODIC_BC,&
     128              :                                               NEUMANN_BC,&
     129              :                                               PERIODIC_BC
     130              :    USE pw_env_types,                    ONLY: pw_env_get,&
     131              :                                               pw_env_type
     132              :    USE pw_grids,                        ONLY: get_pw_grid_info
     133              :    USE pw_methods,                      ONLY: pw_axpy,&
     134              :                                               pw_copy,&
     135              :                                               pw_derive,&
     136              :                                               pw_integrate_function,&
     137              :                                               pw_scale,&
     138              :                                               pw_transfer,&
     139              :                                               pw_zero
     140              :    USE pw_poisson_methods,              ONLY: pw_poisson_solve
     141              :    USE pw_poisson_types,                ONLY: pw_poisson_implicit,&
     142              :                                               pw_poisson_type
     143              :    USE pw_pool_types,                   ONLY: pw_pool_p_type,&
     144              :                                               pw_pool_type
     145              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
     146              :                                               pw_r3d_rs_type
     147              :    USE qs_chargemol,                    ONLY: write_wfx
     148              :    USE qs_charges_types,                ONLY: qs_charges_type
     149              :    USE qs_collocate_density,            ONLY: calculate_rho_resp_all,&
     150              :                                               calculate_wavefunction
     151              :    USE qs_core_energies,                ONLY: calculate_ptrace
     152              :    USE qs_dos,                          ONLY: calculate_dos,&
     153              :                                               calculate_dos_kp
     154              :    USE qs_dos_utils,                    ONLY: get_dos_pdos_flags
     155              :    USE qs_electric_field_gradient,      ONLY: qs_efg_calc
     156              :    USE qs_elf_methods,                  ONLY: qs_elf_calc
     157              :    USE qs_energy_types,                 ONLY: qs_energy_type
     158              :    USE qs_energy_window,                ONLY: energy_windows
     159              :    USE qs_environment_types,            ONLY: get_qs_env,&
     160              :                                               qs_environment_type,&
     161              :                                               set_qs_env
     162              :    USE qs_epr_hyp,                      ONLY: qs_epr_hyp_calc
     163              :    USE qs_fod,                          ONLY: qs_scf_post_fod
     164              :    USE qs_grid_atom,                    ONLY: grid_atom_type
     165              :    USE qs_integral_utils,               ONLY: basis_set_list_setup
     166              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
     167              :                                               qs_kind_type
     168              :    USE qs_ks_methods,                   ONLY: calc_rho_tot_gspace,&
     169              :                                               qs_ks_update_qs_env
     170              :    USE qs_ks_types,                     ONLY: qs_ks_did_change
     171              :    USE qs_kubo_transport,               ONLY: qs_scf_post_kubo_transport
     172              :    USE qs_loc_dipole,                   ONLY: loc_dipole
     173              :    USE qs_loc_states,                   ONLY: get_localization_info
     174              :    USE qs_loc_types,                    ONLY: qs_loc_env_create,&
     175              :                                               qs_loc_env_release,&
     176              :                                               qs_loc_env_type
     177              :    USE qs_loc_utils,                    ONLY: loc_write_restart,&
     178              :                                               qs_loc_control_init,&
     179              :                                               qs_loc_env_init,&
     180              :                                               qs_loc_init,&
     181              :                                               retain_history
     182              :    USE qs_local_properties,             ONLY: qs_local_energy,&
     183              :                                               qs_local_stress
     184              :    USE qs_mo_io,                        ONLY: write_dm_binary_restart
     185              :    USE qs_mo_methods,                   ONLY: calculate_subspace_eigenvalues,&
     186              :                                               make_mo_eig
     187              :    USE qs_mo_occupation,                ONLY: set_mo_occupation
     188              :    USE qs_mo_types,                     ONLY: get_mo_set,&
     189              :                                               mo_set_type
     190              :    USE qs_moments,                      ONLY: qs_moment_berry_phase,&
     191              :                                               qs_moment_kpoints,&
     192              :                                               qs_moment_locop
     193              :    USE qs_neighbor_list_types,          ONLY: get_iterator_info,&
     194              :                                               get_neighbor_list_set_p,&
     195              :                                               neighbor_list_iterate,&
     196              :                                               neighbor_list_iterator_create,&
     197              :                                               neighbor_list_iterator_p_type,&
     198              :                                               neighbor_list_iterator_release,&
     199              :                                               neighbor_list_set_p_type
     200              :    USE qs_operators_ao,                 ONLY: build_lin_mom_matrix
     201              :    USE qs_ot_eigensolver,               ONLY: ot_eigensolver
     202              :    USE qs_pdos,                         ONLY: calculate_projected_dos,&
     203              :                                               calculate_projected_dos_kp
     204              :    USE qs_quadratic_pseudospectrum,     ONLY: qs_scf_post_quadratic
     205              :    USE qs_resp,                         ONLY: resp_fit
     206              :    USE qs_rho0_types,                   ONLY: get_rho0_mpole,&
     207              :                                               mpole_rho_atom,&
     208              :                                               rho0_mpole_type
     209              :    USE qs_rho_atom_types,               ONLY: rho_atom_type
     210              :    USE qs_rho_methods,                  ONLY: qs_rho_update_rho
     211              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
     212              :                                               qs_rho_type
     213              :    USE qs_scf_csr_write,                ONLY: write_hcore_matrix_csr,&
     214              :                                               write_ks_matrix_csr,&
     215              :                                               write_p_matrix_csr,&
     216              :                                               write_s_matrix_csr
     217              :    USE qs_scf_output,                   ONLY: qs_scf_write_mos
     218              :    USE qs_scf_types,                    ONLY: ot_method_nr,&
     219              :                                               qs_scf_env_type
     220              :    USE qs_scf_wfn_mix,                  ONLY: wfn_mix
     221              :    USE qs_spectral_localizer,           ONLY: qs_scf_post_localizer
     222              :    USE qs_subsys_types,                 ONLY: qs_subsys_get,&
     223              :                                               qs_subsys_type
     224              :    USE qs_wannier90,                    ONLY: wannier90_interface
     225              :    USE s_square_methods,                ONLY: compute_s_square
     226              :    USE scf_control_types,               ONLY: scf_control_type
     227              :    USE stm_images,                      ONLY: th_stm_image
     228              :    USE transport,                       ONLY: qs_scf_post_transport
     229              :    USE trexio_utils,                    ONLY: write_trexio
     230              :    USE virial_types,                    ONLY: virial_type
     231              :    USE voronoi_interface,               ONLY: entry_voronoi_or_bqb
     232              :    USE xray_diffraction,                ONLY: xray_diffraction_spectrum
     233              : #include "./base/base_uses.f90"
     234              : 
     235              :    IMPLICIT NONE
     236              :    PRIVATE
     237              : 
     238              :    ! Global parameters
     239              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_scf_post_gpw'
     240              :    PUBLIC :: make_lumo_gpw, &
     241              :              scf_post_calculation_gpw, &
     242              :              qs_scf_post_moments, &
     243              :              write_mo_dependent_results, &
     244              :              write_mo_free_results
     245              : 
     246              :    CHARACTER(len=*), PARAMETER :: &
     247              :       str_mo_cubes = "PRINT%MO_CUBES", &
     248              :       str_mo_openpmd = "PRINT%MO_OPENPMD", &
     249              :       str_elf_cubes = "PRINT%ELF_CUBE", &
     250              :       str_elf_openpmd = "PRINT%ELF_OPENPMD", &
     251              :       str_e_density_cubes = "PRINT%E_DENSITY_CUBE", &
     252              :       str_e_density_openpmd = "PRINT%E_DENSITY_OPENPMD"
     253              : 
     254              :    INTEGER, PARAMETER :: grid_output_cubes = 1, grid_output_openpmd = 2
     255              : 
     256              :    REAL(kind=dp), DIMENSION(7), PARAMETER :: openpmd_unit_dimension_density = &
     257              :                                              [-3, 0, 0, 0, 0, 0, 0]
     258              :    REAL(kind=dp), DIMENSION(7), PARAMETER :: openpmd_unit_dimension_dimensionless = &
     259              :                                              [0, 0, 0, 0, 0, 0, 0]
     260              :    REAL(kind=dp), DIMENSION(7), PARAMETER :: openpmd_unit_dimension_wavefunction = &
     261              :                                              [-1.5_dp, 0.0_dp, 0.0_dp, 0.0_dp, 0.0_dp, 0.0_dp, 0.0_dp]
     262              :    REAL(kind=dp), PARAMETER :: openpmd_unit_si_density = a_bohr**(-3)
     263              :    REAL(kind=dp), PARAMETER :: openpmd_unit_si_dimensionless = 1.0_dp
     264              :    REAL(kind=dp), PARAMETER :: openpmd_unit_si_wavefunction = a_bohr**(-1.5_dp)
     265              : 
     266              :    ! Generic information on whether a certain output section has been activated
     267              :    ! or not, and on whether it has been activated in the Cube or openPMD variant.
     268              :    ! Create with function cube_or_openpmd(), see there for further details.
     269              :    TYPE cp_section_key
     270              :       CHARACTER(len=default_string_length) :: relative_section_key = "" ! e.g. PRINT%MO_CUBES
     271              :       CHARACTER(len=default_string_length) :: absolute_section_key = "" ! e.g. DFT%PRINT%MO_CUBES
     272              :       CHARACTER(len=7) :: format_name = "" ! 'openPMD' or 'Cube', for logging
     273              :       INTEGER :: grid_output = -1 ! either 1 for grid_output_cubes or 2 for grid_output_openpmd
     274              :       LOGICAL :: do_output = .FALSE.
     275              :    CONTAINS
     276              :       ! Open a file as either Cube or openPMD
     277              :       PROCEDURE, PUBLIC :: print_key_unit_nr => cp_forward_print_key_unit_nr
     278              :       ! Write either to the Cube or openPMD file
     279              :       PROCEDURE, PUBLIC :: write_pw => cp_forward_write_pw
     280              :       ! Close either the Cube or openPMD file
     281              :       PROCEDURE, PUBLIC :: print_key_finished_output => cp_forward_print_key_finished_output
     282              :       ! Helpers
     283              :       PROCEDURE, PUBLIC :: do_openpmd => cp_section_key_do_openpmd
     284              :       PROCEDURE, PUBLIC :: do_cubes => cp_section_key_do_cubes
     285              :       PROCEDURE, PUBLIC :: concat_to_relative => cp_section_key_concat_to_relative
     286              :       PROCEDURE, PUBLIC :: concat_to_absolute => cp_section_key_concat_to_absolute
     287              :    END TYPE cp_section_key
     288              : 
     289              : CONTAINS
     290              : 
     291              : ! **************************************************************************************************
     292              : !> \brief Collects the effective core charge for every atom in a QS environment
     293              : !> \param qs_env the QS environment
     294              : !> \param zcharge effective core charges ordered by atom index
     295              : ! **************************************************************************************************
     296        14515 :    SUBROUTINE get_effective_core_charges(qs_env, zcharge)
     297              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     298              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
     299              :          INTENT(OUT)                                     :: zcharge
     300              : 
     301              :       INTEGER                                            :: iat, iatom, ikind, nat, natom, nkind
     302              :       REAL(KIND=dp)                                      :: zeff
     303        14515 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     304        14515 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     305              : 
     306              :       CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, qs_kind_set=qs_kind_set, &
     307        14515 :                       nkind=nkind, natom=natom)
     308        43545 :       ALLOCATE (zcharge(natom))
     309        39913 :       DO ikind = 1, nkind
     310        25398 :          CALL get_qs_kind(qs_kind_set(ikind), zeff=zeff)
     311        25398 :          CALL get_atomic_kind(atomic_kind_set(ikind), natom=nat)
     312        93550 :          DO iatom = 1, nat
     313        53637 :             iat = atomic_kind_set(ikind)%atom_list(iatom)
     314        79035 :             zcharge(iat) = zeff
     315              :          END DO
     316              :       END DO
     317        14515 :    END SUBROUTINE get_effective_core_charges
     318              : 
     319              : ! **************************************************************************************************
     320              : !> \brief Append `extend_by` to the absolute path of the base section.
     321              : !> \param self ...
     322              : !> \param extend_by ...
     323              : !> \return ...
     324              : ! **************************************************************************************************
     325          310 :    FUNCTION cp_section_key_concat_to_absolute(self, extend_by) RESULT(res)
     326              :       CLASS(cp_section_key), INTENT(IN) :: self
     327              :       CHARACTER(*), INTENT(IN) :: extend_by
     328              :       CHARACTER(len=default_string_length) :: res
     329              : 
     330          310 :       IF (LEN(TRIM(extend_by)) > 0 .AND. extend_by(1:1) == "%") THEN
     331          310 :          res = TRIM(self%absolute_section_key)//TRIM(extend_by)
     332              :       ELSE
     333            0 :          res = TRIM(self%absolute_section_key)//"%"//TRIM(extend_by)
     334              :       END IF
     335          310 :    END FUNCTION cp_section_key_concat_to_absolute
     336              : 
     337              : ! **************************************************************************************************
     338              : !> \brief Append `extend_by` to the relative path (e.g. without DFT%) of the base section.
     339              : !> \param self ...
     340              : !> \param extend_by ...
     341              : !> \return ...
     342              : ! **************************************************************************************************
     343        27230 :    FUNCTION cp_section_key_concat_to_relative(self, extend_by) RESULT(res)
     344              :       CLASS(cp_section_key), INTENT(IN) :: self
     345              :       CHARACTER(*), INTENT(IN) :: extend_by
     346              :       CHARACTER(len=default_string_length) :: res
     347              : 
     348        27230 :       IF (LEN(TRIM(extend_by)) > 0 .AND. extend_by(1:1) == "%") THEN
     349        27230 :          res = TRIM(self%relative_section_key)//TRIM(extend_by)
     350              :       ELSE
     351            0 :          res = TRIM(self%relative_section_key)//"%"//TRIM(extend_by)
     352              :       END IF
     353        27230 :    END FUNCTION cp_section_key_concat_to_relative
     354              : 
     355              : ! **************************************************************************************************
     356              : !> \brief Is Cube output active for the current base section?
     357              : !> \param self ...
     358              : !> \return ...
     359              : ! **************************************************************************************************
     360         1084 :    FUNCTION cp_section_key_do_cubes(self) RESULT(res)
     361              :       CLASS(cp_section_key) :: self
     362              :       LOGICAL :: res
     363              : 
     364         1084 :       res = self%do_output .AND. self%grid_output == grid_output_cubes
     365         1084 :    END FUNCTION cp_section_key_do_cubes
     366              : 
     367              : ! **************************************************************************************************
     368              : !> \brief Is openPMD output active for the current base section?
     369              : !> \param self ...
     370              : !> \return ...
     371              : ! **************************************************************************************************
     372         1084 :    FUNCTION cp_section_key_do_openpmd(self) RESULT(res)
     373              :       CLASS(cp_section_key) :: self
     374              :       LOGICAL :: res
     375              : 
     376         1084 :       res = self%do_output .AND. self%grid_output == grid_output_openpmd
     377         1084 :    END FUNCTION cp_section_key_do_openpmd
     378              : 
     379              : ! **************************************************************************************************
     380              : !> \brief Forwards to either `cp_print_key_unit_nr` or `cp_openpmd_print_key_unit_nr`,
     381              : !>        depending on the configuration of the current base section.
     382              : !>        Opens either a Cube or openPMD output file
     383              : !> \param self ...
     384              : !> \param logger ...
     385              : !> \param basis_section ...
     386              : !> \param print_key_path ...
     387              : !> \param extension ...
     388              : !> \param middle_name ...
     389              : !> \param local ...
     390              : !> \param log_filename ...
     391              : !> \param ignore_should_output ...
     392              : !> \param file_form ...
     393              : !> \param file_position ...
     394              : !> \param file_action ...
     395              : !> \param file_status ...
     396              : !> \param do_backup ...
     397              : !> \param on_file ...
     398              : !> \param is_new_file ...
     399              : !> \param mpi_io ...
     400              : !> \param fout ...
     401              : !> \param openpmd_basename ...
     402              : !> \param openpmd_unit_dimension ...
     403              : !> \param openpmd_unit_si ...
     404              : !> \param sim_time ...
     405              : !> \return ...
     406              : ! **************************************************************************************************
     407          552 :    FUNCTION cp_forward_print_key_unit_nr( &
     408              :       self, &
     409              :       logger, &
     410              :       basis_section, &
     411              :       print_key_path, &
     412              :       extension, &
     413              :       middle_name, &
     414              :       local, &
     415              :       log_filename, &
     416              :       ignore_should_output, &
     417              :       file_form, &
     418              :       file_position, &
     419              :       file_action, &
     420              :       file_status, &
     421              :       do_backup, &
     422              :       on_file, &
     423              :       is_new_file, &
     424              :       mpi_io, &
     425              :       fout, &
     426              :       openpmd_basename, &
     427              :       openpmd_unit_dimension, &
     428              :       openpmd_unit_si, &
     429              :       sim_time) RESULT(res)
     430              : 
     431              :       CLASS(cp_section_key), INTENT(IN)                  :: self
     432              :       TYPE(cp_logger_type), POINTER                      :: logger
     433              :       TYPE(section_vals_type), INTENT(IN)                :: basis_section
     434              :       CHARACTER(len=*), INTENT(IN), OPTIONAL             :: print_key_path
     435              :       CHARACTER(len=*), INTENT(IN)                       :: extension
     436              :       CHARACTER(len=*), INTENT(IN), OPTIONAL             :: middle_name
     437              :       LOGICAL, INTENT(IN), OPTIONAL                      :: local, log_filename, ignore_should_output
     438              :       CHARACTER(len=*), INTENT(IN), OPTIONAL             :: file_form, file_position, file_action, &
     439              :                                                             file_status
     440              :       LOGICAL, INTENT(IN), OPTIONAL                      :: do_backup, on_file
     441              :       LOGICAL, INTENT(OUT), OPTIONAL                     :: is_new_file
     442              :       LOGICAL, INTENT(INOUT), OPTIONAL                   :: mpi_io
     443              :       CHARACTER(len=default_path_length), INTENT(OUT), &
     444              :          OPTIONAL                                        :: fout
     445              :       CHARACTER(len=*), INTENT(IN), OPTIONAL             :: openpmd_basename
     446              :       REAL(kind=dp), DIMENSION(7), OPTIONAL, INTENT(IN)  :: openpmd_unit_dimension
     447              :       REAL(kind=dp), OPTIONAL, INTENT(IN)                :: openpmd_unit_si
     448              :       REAL(kind=dp), OPTIONAL, INTENT(IN)                :: sim_time
     449              :       INTEGER                                            :: res
     450              : 
     451          552 :       IF (self%grid_output == grid_output_cubes) THEN
     452              :          res = cp_print_key_unit_nr( &
     453              :                logger, basis_section, print_key_path, extension=extension, &
     454              :                middle_name=middle_name, local=local, log_filename=log_filename, &
     455              :                ignore_should_output=ignore_should_output, file_form=file_form, &
     456              :                file_position=file_position, file_action=file_action, &
     457              :                file_status=file_status, do_backup=do_backup, on_file=on_file, &
     458         2466 :                is_new_file=is_new_file, mpi_io=mpi_io, fout=fout)
     459              :       ELSE
     460              :          res = cp_openpmd_print_key_unit_nr( &
     461              :                logger, &
     462              :                basis_section, &
     463              :                print_key_path, &
     464              :                middle_name=middle_name, &
     465              :                ignore_should_output=ignore_should_output, &
     466              :                mpi_io=mpi_io, &
     467              :                fout=fout, &
     468              :                openpmd_basename=openpmd_basename, &
     469              :                openpmd_unit_dimension=openpmd_unit_dimension, &
     470              :                openpmd_unit_si=openpmd_unit_si, &
     471            0 :                sim_time=sim_time)
     472              :       END IF
     473          552 :    END FUNCTION cp_forward_print_key_unit_nr
     474              : 
     475              : ! **************************************************************************************************
     476              : !> \brief Forwards to either `cp_pw_to_cube` or `cp_pw_to_openpmd`,
     477              : !>        depending on the configuration of the current base section.
     478              : !>        Writes data to either a Cube or an openPMD file.
     479              : !> \param self ...
     480              : !> \param pw ...
     481              : !> \param unit_nr ...
     482              : !> \param title ...
     483              : !> \param particles ...
     484              : !> \param zeff ...
     485              : !> \param stride ...
     486              : !> \param max_file_size_mb ...
     487              : !> \param zero_tails ...
     488              : !> \param silent ...
     489              : !> \param mpi_io ...
     490              : ! **************************************************************************************************
     491          552 :    SUBROUTINE cp_forward_write_pw( &
     492              :       self, &
     493              :       pw, &
     494              :       unit_nr, &
     495              :       title, &
     496              :       particles, &
     497          552 :       zeff, &
     498              :       stride, &
     499              :       max_file_size_mb, &
     500              :       zero_tails, &
     501              :       silent, &
     502              :       mpi_io &
     503              :       )
     504              :       CLASS(cp_section_key), INTENT(IN)                  :: self
     505              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: pw
     506              :       INTEGER, INTENT(IN)                                :: unit_nr
     507              :       CHARACTER(*), INTENT(IN), OPTIONAL                 :: title
     508              :       TYPE(particle_list_type), POINTER                  :: particles
     509              :       INTEGER, DIMENSION(:), OPTIONAL, POINTER           :: stride
     510              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: max_file_size_mb
     511              :       LOGICAL, INTENT(IN), OPTIONAL                      :: zero_tails, silent, mpi_io
     512              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL              :: zeff
     513              : 
     514          552 :       IF (self%grid_output == grid_output_cubes) THEN
     515          552 :          CALL cp_pw_to_cube(pw, unit_nr, title, particles, zeff, stride, max_file_size_mb, zero_tails, silent, mpi_io)
     516              :       ELSE
     517            0 :          CALL cp_pw_to_openpmd(pw, unit_nr, title, particles, zeff, stride, zero_tails, silent, mpi_io)
     518              :       END IF
     519          552 :    END SUBROUTINE cp_forward_write_pw
     520              : 
     521              : ! **************************************************************************************************
     522              : !> \brief Forwards to either `cp_print_key_finished_output` or `cp_openpmd_print_key_finished_output`,
     523              : !>        depending on the configuration of the current base section.
     524              : !>        Closes either a Cube file or a reference to a section within an openPMD file.
     525              : !> \param self ...
     526              : !> \param unit_nr ...
     527              : !> \param logger ...
     528              : !> \param basis_section ...
     529              : !> \param print_key_path ...
     530              : !> \param local ...
     531              : !> \param ignore_should_output ...
     532              : !> \param on_file ...
     533              : !> \param mpi_io ...
     534              : ! **************************************************************************************************
     535          552 :    SUBROUTINE cp_forward_print_key_finished_output(self, unit_nr, logger, basis_section, &
     536              :                                                    print_key_path, local, ignore_should_output, on_file, &
     537              :                                                    mpi_io)
     538              :       CLASS(cp_section_key), INTENT(IN)                  :: self
     539              :       INTEGER, INTENT(INOUT)                             :: unit_nr
     540              :       TYPE(cp_logger_type), POINTER                      :: logger
     541              :       TYPE(section_vals_type), INTENT(IN)                :: basis_section
     542              :       CHARACTER(len=*), INTENT(IN), OPTIONAL             :: print_key_path
     543              :       LOGICAL, INTENT(IN), OPTIONAL                      :: local, ignore_should_output, on_file, &
     544              :                                                             mpi_io
     545              : 
     546          552 :       IF (self%grid_output == grid_output_cubes) THEN
     547          552 :      CALL cp_print_key_finished_output(unit_nr, logger, basis_section, print_key_path, local, ignore_should_output, on_file, mpi_io)
     548              :       ELSE
     549            0 :       CALL cp_openpmd_print_key_finished_output(unit_nr, logger, basis_section, print_key_path, local, ignore_should_output, mpi_io)
     550              :       END IF
     551          552 :    END SUBROUTINE cp_forward_print_key_finished_output
     552              : 
     553              :    !
     554              : ! **************************************************************************************************
     555              : !> \brief Decides if a particular output routine will write to openPMD, to Cube or to none.
     556              : !>        Writing to both is not supported.
     557              : !>        The distinction between Cube and openPMD output works such that the output configuration
     558              : !>        sections exist as duplicates: E.g. for DFT%PRINT%MO_CUBES,
     559              : !>        there additionally exists DFT%PRINT%MO_OPENPMD.
     560              : !>        The internal base configuration for such sections is identical; additionally there
     561              : !>        exist format-specific options such as APPEND for Cube or OPENPMD_CFG_FILE for openPMD.
     562              : !>        The routines in this file alternate between using relative section paths without the
     563              : !>        %DFT prefix (e.g. PRINT%MO_CUBES) or absolute section paths with the %DF% prefix
     564              : !>        (e.g. DFT%PRINT%MO_CUBES). Call this routine with the relative paths.
     565              : !> \param input ...
     566              : !> \param str_cubes ...
     567              : !> \param str_openpmd ...
     568              : !> \param logger ...
     569              : !> \return ...
     570              : ! **************************************************************************************************
     571        39921 :    FUNCTION cube_or_openpmd(input, str_cubes, str_openpmd, logger) RESULT(res)
     572              :       TYPE(section_vals_type), POINTER                   :: input
     573              :       CHARACTER(len=*), INTENT(IN)                       :: str_cubes, str_openpmd
     574              :       TYPE(cp_logger_type), POINTER                      :: logger
     575              :       TYPE(cp_section_key)                               :: res
     576              : 
     577              :       LOGICAL                                            :: do_cubes, do_openpmd
     578              : 
     579              :       do_cubes = BTEST(cp_print_key_should_output( &
     580              :                        logger%iter_info, input, &
     581        39921 :                        "DFT%"//TRIM(ADJUSTL(str_cubes))), cp_p_file)
     582              :       do_openpmd = BTEST(cp_print_key_should_output( &
     583              :                          logger%iter_info, input, &
     584        39921 :                          "DFT%"//TRIM(ADJUSTL(str_openpmd))), cp_p_file)
     585              :       ! Having Cube and openPMD output both active should be theoretically possible.
     586              :       ! It would require some extra handling for the unit_nr return values.
     587              :       ! (e.g. returning the Cube unit_nr and internally storing the associated openPMD unit_nr).
     588        39921 :       CPASSERT(.NOT. (do_cubes .AND. do_openpmd))
     589        39921 :       res%do_output = do_cubes .OR. do_openpmd
     590        39921 :       IF (do_openpmd) THEN
     591            0 :          res%grid_output = grid_output_openpmd
     592            0 :          res%relative_section_key = TRIM(ADJUSTL(str_openpmd))
     593            0 :          res%format_name = "openPMD"
     594              :       ELSE
     595        39921 :          res%grid_output = grid_output_cubes
     596        39921 :          res%relative_section_key = TRIM(ADJUSTL(str_cubes))
     597        39921 :          res%format_name = "Cube"
     598              :       END IF
     599        39921 :       res%absolute_section_key = "DFT%"//TRIM(ADJUSTL(res%relative_section_key))
     600        39921 :    END FUNCTION cube_or_openpmd
     601              : 
     602              : ! **************************************************************************************************
     603              : !> \brief This section key is named WRITE_CUBE for Cube which does not make much sense
     604              : !>        for openPMD, so this key name has to be distinguished.
     605              : !> \param grid_output ...
     606              : !> \return ...
     607              : ! **************************************************************************************************
     608          296 :    FUNCTION section_key_do_write(grid_output) RESULT(res)
     609              :       INTEGER, INTENT(IN)                                :: grid_output
     610              :       CHARACTER(len=32)                                  :: res
     611              : 
     612          296 :       IF (grid_output == grid_output_cubes) THEN
     613          296 :          res = "%WRITE_CUBE"
     614            0 :       ELSE IF (grid_output == grid_output_openpmd) THEN
     615            0 :          res = "%WRITE_OPENPMD"
     616              :       END IF
     617          296 :    END FUNCTION section_key_do_write
     618              : 
     619              : ! **************************************************************************************************
     620              : !> \brief Prints the output message for density file writing
     621              : !> \param output_unit Unit number for output
     622              : !> \param prefix The message prefix (e.g., "The total electron density")
     623              : !> \param e_density_section Section key containing grid_output and format_name
     624              : !> \param filename The actual filename or pattern used
     625              : ! **************************************************************************************************
     626          105 :    SUBROUTINE print_density_output_message(output_unit, prefix, e_density_section, filename)
     627              :       INTEGER, INTENT(IN)                                :: output_unit
     628              :       CHARACTER(len=*), INTENT(IN)                       :: prefix
     629              :       TYPE(cp_section_key), INTENT(IN)                   :: e_density_section
     630              :       CHARACTER(len=*), INTENT(IN)                       :: filename
     631              : 
     632          105 :       IF (e_density_section%grid_output == grid_output_openpmd) THEN
     633              :          WRITE (UNIT=output_unit, FMT="(/,T2,A)") &
     634              :             TRIM(prefix)//" is written in " &
     635              :             //e_density_section%format_name &
     636            0 :             //" file format to the file / file pattern:", &
     637            0 :             TRIM(filename)
     638              :       ELSE
     639              :          WRITE (UNIT=output_unit, FMT="(/,T2,A,/,/,T2,A)") &
     640              :             TRIM(prefix)//" is written in " &
     641              :             //e_density_section%format_name &
     642          105 :             //" file format to the file:", &
     643          210 :             TRIM(filename)
     644              :       END IF
     645          105 :    END SUBROUTINE print_density_output_message
     646              : 
     647              : ! **************************************************************************************************
     648              : !> \brief collects possible post - scf calculations and prints info / computes properties.
     649              : !> \param qs_env the qs_env in which the qs_env lives
     650              : !> \param wf_type ...
     651              : !> \param do_mp2 ...
     652              : !> \par History
     653              : !>      02.2003 created [fawzi]
     654              : !>      10.2004 moved here from qs_scf [Joost VandeVondele]
     655              : !>              started splitting out different subroutines
     656              : !>      10.2015 added header for wave-function correlated methods [Vladimir Rybkin]
     657              : !> \author fawzi
     658              : !> \note
     659              : !>      this function changes mo_eigenvectors and mo_eigenvalues, depending on the print keys.
     660              : !>      In particular, MO_CUBES causes the MOs to be rotated to make them eigenstates of the KS
     661              : !>      matrix, and mo_eigenvalues is updated accordingly. This can, for unconverged wavefunctions,
     662              : !>      change afterwards slightly the forces (hence small numerical differences between MD
     663              : !>      with and without the debug print level). Ideally this should not happen...
     664              : ! **************************************************************************************************
     665        12887 :    SUBROUTINE scf_post_calculation_gpw(qs_env, wf_type, do_mp2)
     666              : 
     667              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     668              :       CHARACTER(6), OPTIONAL                             :: wf_type
     669              :       LOGICAL, OPTIONAL                                  :: do_mp2
     670              : 
     671              :       CHARACTER(len=*), PARAMETER :: routineN = 'scf_post_calculation_gpw', &
     672              :          warning_cube_kpoint = "Print MO cubes not implemented for k-point calculations", &
     673              :          warning_openpmd_kpoint = "Writing to openPMD not implemented for k-point calculations"
     674              : 
     675              :       INTEGER                                            :: handle, homo, ispin, min_lumos, n_rep, &
     676              :                                                             nchk_nmoloc, nhomo, nlumo, nlumo_stm, &
     677              :                                                             nlumos, nmo, nspins, output_unit, &
     678              :                                                             unit_nr
     679        12887 :       INTEGER, DIMENSION(:, :, :), POINTER               :: marked_states
     680              :       LOGICAL :: check_write, compute_lumos, do_homo, do_kpoints, do_mixed, do_stm, &
     681              :          do_wannier_cubes, has_homo, has_lumo, loc_explicit, loc_print_explicit, my_do_mp2, &
     682              :          my_localized_wfn, p_loc, p_loc_homo, p_loc_lumo, p_loc_mixed
     683              :       REAL(dp)                                           :: e_kin
     684              :       REAL(KIND=dp)                                      :: gap, homo_lumo(2, 2), total_zeff_corr
     685        12887 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mo_eigenvalues
     686              :       TYPE(admm_type), POINTER                           :: admm_env
     687        12887 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     688        12887 :       TYPE(cp_1d_r_p_type), DIMENSION(:), POINTER        :: mixed_evals, occupied_evals, &
     689        12887 :                                                             unoccupied_evals, unoccupied_evals_stm
     690        12887 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: mixed_orbs, occupied_orbs
     691              :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:), &
     692        12887 :          TARGET                                          :: homo_localized, lumo_localized, &
     693        12887 :                                                             mixed_localized
     694        12887 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: lumo_ptr, mo_loc_history, &
     695        12887 :                                                             unoccupied_orbs, unoccupied_orbs_stm
     696              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     697              :       TYPE(cp_logger_type), POINTER                      :: logger
     698              :       TYPE(cp_section_key)                               :: mo_section
     699        12887 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: ks_rmpv, matrix_p_mp2, matrix_s, &
     700        12887 :                                                             mo_derivs
     701        12887 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: kinetic_m, rho_ao
     702              :       TYPE(dft_control_type), POINTER                    :: dft_control
     703        12887 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     704        12887 :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
     705              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     706              :       TYPE(particle_list_type), POINTER                  :: particles
     707        12887 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     708              :       TYPE(pw_c1d_gs_type)                               :: wf_g
     709              :       TYPE(pw_env_type), POINTER                         :: pw_env
     710        12887 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
     711              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     712              :       TYPE(pw_r3d_rs_type)                               :: wf_r
     713        12887 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     714              :       TYPE(qs_loc_env_type), POINTER                     :: qs_loc_env_homo, qs_loc_env_lumo, &
     715              :                                                             qs_loc_env_mixed
     716              :       TYPE(qs_rho_type), POINTER                         :: rho
     717              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     718              :       TYPE(qs_subsys_type), POINTER                      :: subsys
     719              :       TYPE(rtp_control_type), POINTER                    :: rtp_control
     720              :       TYPE(scf_control_type), POINTER                    :: scf_control
     721              :       TYPE(section_vals_type), POINTER                   :: dft_section, input, loc_print_section, &
     722              :                                                             localize_section, print_key, &
     723              :                                                             stm_section
     724              : 
     725        12887 :       CALL timeset(routineN, handle)
     726              : 
     727        12887 :       logger => cp_get_default_logger()
     728        12887 :       output_unit = cp_logger_get_default_io_unit(logger)
     729              : 
     730              :       ! Print out the type of wavefunction to distinguish between SCF and post-SCF
     731        12887 :       my_do_mp2 = .FALSE.
     732        12887 :       IF (PRESENT(do_mp2)) my_do_mp2 = do_mp2
     733        12887 :       IF (PRESENT(wf_type)) THEN
     734          328 :          IF (output_unit > 0) THEN
     735          164 :             WRITE (UNIT=output_unit, FMT='(/,(T1,A))') REPEAT("-", 40)
     736          164 :             WRITE (UNIT=output_unit, FMT='(/,(T3,A,T19,A,T25,A))') "Properties from ", wf_type, " density"
     737          164 :             WRITE (UNIT=output_unit, FMT='(/,(T1,A))') REPEAT("-", 40)
     738              :          END IF
     739              :       END IF
     740              : 
     741              :       ! Writes the data that is already available in qs_env
     742        12887 :       CALL get_qs_env(qs_env, scf_env=scf_env)
     743              : 
     744        12887 :       my_localized_wfn = .FALSE.
     745        12887 :       NULLIFY (admm_env, dft_control, pw_env, auxbas_pw_pool, pw_pools, mos, rho, &
     746        12887 :                mo_coeff, ks_rmpv, matrix_s, qs_loc_env_homo, qs_loc_env_lumo, scf_control, &
     747        12887 :                unoccupied_orbs, mo_eigenvalues, unoccupied_evals, &
     748        12887 :                unoccupied_evals_stm, molecule_set, mo_derivs, &
     749        12887 :                subsys, particles, input, print_key, kinetic_m, marked_states, &
     750        12887 :                mixed_evals, qs_loc_env_mixed)
     751        12887 :       NULLIFY (lumo_ptr, rho_ao)
     752              : 
     753        12887 :       has_homo = .FALSE.
     754        12887 :       has_lumo = .FALSE.
     755        12887 :       p_loc = .FALSE.
     756        12887 :       p_loc_homo = .FALSE.
     757        12887 :       p_loc_lumo = .FALSE.
     758        12887 :       p_loc_mixed = .FALSE.
     759              : 
     760        12887 :       CPASSERT(ASSOCIATED(scf_env))
     761        12887 :       CPASSERT(ASSOCIATED(qs_env))
     762              :       ! Here we start with data that needs a postprocessing...
     763              :       CALL get_qs_env(qs_env, &
     764              :                       dft_control=dft_control, &
     765              :                       molecule_set=molecule_set, &
     766              :                       scf_control=scf_control, &
     767              :                       do_kpoints=do_kpoints, &
     768              :                       input=input, &
     769              :                       subsys=subsys, &
     770              :                       rho=rho, &
     771              :                       pw_env=pw_env, &
     772              :                       particle_set=particle_set, &
     773              :                       atomic_kind_set=atomic_kind_set, &
     774        12887 :                       qs_kind_set=qs_kind_set)
     775        12887 :       rtp_control => dft_control%rtp_control
     776        12887 :       CALL qs_subsys_get(subsys, particles=particles)
     777              : 
     778        12887 :       CALL qs_rho_get(rho, rho_ao_kp=rho_ao)
     779              : 
     780        12887 :       IF (my_do_mp2) THEN
     781              :          ! Get the HF+MP2 density
     782          322 :          CALL get_qs_env(qs_env, matrix_p_mp2=matrix_p_mp2)
     783          742 :          DO ispin = 1, dft_control%nspins
     784          742 :             CALL dbcsr_add(rho_ao(ispin, 1)%matrix, matrix_p_mp2(ispin)%matrix, 1.0_dp, 1.0_dp)
     785              :          END DO
     786          322 :          CALL qs_rho_update_rho(rho, qs_env=qs_env)
     787          322 :          CALL qs_ks_did_change(qs_env%ks_env, rho_changed=.TRUE.)
     788              :          ! In MP2 case update the Hartree potential
     789          322 :          CALL update_hartree_with_mp2(rho, qs_env)
     790              :       END IF
     791              : 
     792        12887 :       CALL write_available_results(qs_env, scf_env)
     793              : 
     794              :       !    **** the kinetic energy
     795        12887 :       IF (cp_print_key_should_output(logger%iter_info, input, &
     796              :                                      "DFT%PRINT%KINETIC_ENERGY") /= 0) THEN
     797           80 :          CALL get_qs_env(qs_env, kinetic_kp=kinetic_m)
     798           80 :          CPASSERT(ASSOCIATED(kinetic_m))
     799           80 :          CPASSERT(ASSOCIATED(kinetic_m(1, 1)%matrix))
     800           80 :          CALL calculate_ptrace(kinetic_m, rho_ao, e_kin, dft_control%nspins)
     801              :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%KINETIC_ENERGY", &
     802           80 :                                         extension=".Log")
     803           80 :          IF (unit_nr > 0) THEN
     804           40 :             WRITE (unit_nr, '(T3,A,T55,F25.14)') "Electronic kinetic energy:", e_kin
     805              :          END IF
     806              :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
     807           80 :                                            "DFT%PRINT%KINETIC_ENERGY")
     808              :       END IF
     809              : 
     810              :       ! Atomic Charges that require further computation
     811        12887 :       CALL qs_scf_post_charges(input, logger, qs_env)
     812              : 
     813              :       ! Moments of charge distribution
     814        12887 :       CALL qs_scf_post_moments(input, logger, qs_env, output_unit)
     815              : 
     816        12887 :       CALL qs_scf_post_fod(input, logger, qs_env, output_unit)
     817              : 
     818              :       ! Determine if we need to computer properties using the localized centers
     819        12887 :       dft_section => section_vals_get_subs_vals(input, "DFT")
     820        12887 :       localize_section => section_vals_get_subs_vals(dft_section, "LOCALIZE")
     821        12887 :       loc_print_section => section_vals_get_subs_vals(localize_section, "PRINT")
     822        12887 :       CALL section_vals_get(localize_section, explicit=loc_explicit)
     823        12887 :       CALL section_vals_get(loc_print_section, explicit=loc_print_explicit)
     824              : 
     825              :       ! Print_keys controlled by localization
     826        12887 :       IF (loc_print_explicit) THEN
     827          100 :          print_key => section_vals_get_subs_vals(loc_print_section, "MOLECULAR_DIPOLES")
     828          100 :          p_loc = BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     829          100 :          print_key => section_vals_get_subs_vals(loc_print_section, "TOTAL_DIPOLE")
     830          100 :          p_loc = p_loc .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     831          100 :          print_key => section_vals_get_subs_vals(loc_print_section, "WANNIER_CENTERS")
     832          100 :          p_loc = p_loc .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     833          100 :          print_key => section_vals_get_subs_vals(loc_print_section, "WANNIER_SPREADS")
     834          100 :          p_loc = p_loc .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     835          100 :          print_key => section_vals_get_subs_vals(loc_print_section, "WANNIER_CUBES")
     836          100 :          p_loc = p_loc .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     837          100 :          print_key => section_vals_get_subs_vals(loc_print_section, "MOLECULAR_STATES")
     838          100 :          p_loc = p_loc .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     839          100 :          print_key => section_vals_get_subs_vals(loc_print_section, "MOLECULAR_MOMENTS")
     840          100 :          p_loc = p_loc .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     841          100 :          print_key => section_vals_get_subs_vals(loc_print_section, "LOCALIZED_MOMENTS")
     842          100 :          p_loc = p_loc .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     843          100 :          print_key => section_vals_get_subs_vals(loc_print_section, "WANNIER_STATES")
     844          100 :          p_loc = p_loc .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     845              :       ELSE
     846              :          p_loc = .FALSE.
     847              :       END IF
     848        12887 :       IF (loc_explicit) THEN
     849              :          p_loc_homo = (section_get_ival(localize_section, "STATES") == do_loc_homo .OR. &
     850          100 :                        section_get_ival(localize_section, "STATES") == do_loc_both) .AND. p_loc
     851              :          p_loc_lumo = (section_get_ival(localize_section, "STATES") == do_loc_lumo .OR. &
     852          100 :                        section_get_ival(localize_section, "STATES") == do_loc_both) .AND. p_loc
     853          100 :          p_loc_mixed = (section_get_ival(localize_section, "STATES") == do_loc_mixed) .AND. p_loc
     854          100 :          CALL section_vals_val_get(localize_section, "LIST_UNOCCUPIED", n_rep_val=n_rep)
     855              :       ELSE
     856        12787 :          p_loc_homo = .FALSE.
     857        12787 :          p_loc_lumo = .FALSE.
     858        12787 :          p_loc_mixed = .FALSE.
     859        12787 :          n_rep = 0
     860              :       END IF
     861              : 
     862        12887 :       IF (n_rep == 0 .AND. p_loc_lumo) THEN
     863              :          CALL cp_abort(__LOCATION__, "No LIST_UNOCCUPIED was specified, "// &
     864            0 :                        "therefore localization of unoccupied states will be skipped!")
     865            0 :          p_loc_lumo = .FALSE.
     866              :       END IF
     867              : 
     868              :       ! Control for STM
     869        12887 :       stm_section => section_vals_get_subs_vals(input, "DFT%PRINT%STM")
     870        12887 :       CALL section_vals_get(stm_section, explicit=do_stm)
     871        12887 :       nlumo_stm = 0
     872        12887 :       IF (do_stm) nlumo_stm = section_get_ival(stm_section, "NLUMO")
     873              : 
     874              :       ! check for CUBES or openPMD (MOs and WANNIERS)
     875        12887 :       mo_section = cube_or_openpmd(input, str_mo_cubes, str_mo_openpmd, logger)
     876              : 
     877        12887 :       IF (loc_print_explicit) THEN
     878              :          do_wannier_cubes = BTEST(cp_print_key_should_output(logger%iter_info, loc_print_section, &
     879          100 :                                                              "WANNIER_CUBES"), cp_p_file)
     880              :       ELSE
     881              :          do_wannier_cubes = .FALSE.
     882              :       END IF
     883        12887 :       nlumo = section_get_ival(dft_section, mo_section%concat_to_relative("%NLUMO"))
     884        12887 :       nhomo = section_get_ival(dft_section, mo_section%concat_to_relative("%NHOMO"))
     885              : 
     886              :       ! Setup the grids needed to compute a wavefunction given a vector..
     887        12887 :       IF (((mo_section%do_output .OR. do_wannier_cubes) .AND. (nlumo /= 0 .OR. nhomo /= 0)) .OR. p_loc) THEN
     888              :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
     889          216 :                          pw_pools=pw_pools)
     890          216 :          CALL auxbas_pw_pool%create_pw(wf_r)
     891          216 :          CALL auxbas_pw_pool%create_pw(wf_g)
     892              :       END IF
     893              : 
     894        12887 :       IF (dft_control%restricted) THEN
     895              :          !For ROKS useful only first term
     896           74 :          nspins = 1
     897              :       ELSE
     898        12813 :          nspins = dft_control%nspins
     899              :       END IF
     900              :       !Some info about ROKS
     901        12887 :       IF (dft_control%restricted .AND. (mo_section%do_output .OR. p_loc_homo)) THEN
     902            0 :          CALL cp_abort(__LOCATION__, "Unclear how we define MOs / localization in the restricted case ... ")
     903              :          ! It is possible to obtain Wannier centers for ROKS without rotations for SINGLE OCCUPIED ORBITALS
     904              :       END IF
     905              :       ! Makes the MOs eigenstates, computes eigenvalues, write cubes
     906        12887 :       IF (do_kpoints) THEN
     907         1084 :          CPWARN_IF(mo_section%do_cubes(), warning_cube_kpoint)
     908         1084 :          CPWARN_IF(mo_section%do_openpmd(), warning_openpmd_kpoint)
     909              :       ELSE
     910              :          CALL get_qs_env(qs_env, &
     911              :                          mos=mos, &
     912        11803 :                          matrix_ks=ks_rmpv)
     913        11803 :          IF ((mo_section%do_output .AND. nhomo /= 0) .OR. do_stm) THEN
     914          136 :             CALL get_qs_env(qs_env, mo_derivs=mo_derivs)
     915          136 :             IF (dft_control%do_admm) THEN
     916            0 :                CALL get_qs_env(qs_env, admm_env=admm_env)
     917            0 :                CALL make_mo_eig(mos, nspins, ks_rmpv, scf_control, mo_derivs, admm_env=admm_env)
     918              :             ELSE
     919          136 :                IF (dft_control%hairy_probes) THEN
     920            0 :                   scf_control%smear%do_smear = .FALSE.
     921              :                   CALL make_mo_eig(mos, dft_control%nspins, ks_rmpv, scf_control, mo_derivs, &
     922              :                                    hairy_probes=dft_control%hairy_probes, &
     923            0 :                                    probe=dft_control%probe)
     924              :                ELSE
     925          136 :                   CALL make_mo_eig(mos, dft_control%nspins, ks_rmpv, scf_control, mo_derivs)
     926              :                END IF
     927              :             END IF
     928          292 :             DO ispin = 1, dft_control%nspins
     929          156 :                CALL get_mo_set(mo_set=mos(ispin), eigenvalues=mo_eigenvalues, homo=homo)
     930          292 :                homo_lumo(ispin, 1) = mo_eigenvalues(homo)
     931              :             END DO
     932              :             has_homo = .TRUE.
     933              :          END IF
     934        11803 :          IF (mo_section%do_output .AND. nhomo /= 0) THEN
     935          278 :             DO ispin = 1, nspins
     936              :                ! Prints the cube files of OCCUPIED ORBITALS
     937              :                CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, &
     938          148 :                                eigenvalues=mo_eigenvalues, homo=homo, nmo=nmo)
     939              :                CALL qs_scf_post_occ_cubes(input, dft_section, dft_control, logger, qs_env, &
     940          278 :                                           mo_coeff, wf_g, wf_r, particles, homo, ispin, mo_section)
     941              :             END DO
     942              :          END IF
     943              :       END IF
     944              : 
     945              :       ! Initialize the localization environment, needed e.g. for wannier functions and molecular states
     946              :       ! Gets localization info for the occupied orbs
     947              :       !  - Possibly gets wannier functions
     948              :       !  - Possibly gets molecular states
     949        12887 :       IF (p_loc_homo) THEN
     950           94 :          IF (do_kpoints) THEN
     951            0 :             CPWARN("Localization not implemented for k-point calculations!")
     952              :          ELSE IF (dft_control%restricted &
     953              :                   .AND. (section_get_ival(localize_section, "METHOD") /= do_loc_none) &
     954           94 :                   .AND. (section_get_ival(localize_section, "METHOD") /= do_loc_jacobi)) THEN
     955            0 :             CPABORT("ROKS works only with LOCALIZE METHOD NONE or JACOBI")
     956              :          ELSE
     957          392 :             ALLOCATE (occupied_orbs(dft_control%nspins))
     958          392 :             ALLOCATE (occupied_evals(dft_control%nspins))
     959          392 :             ALLOCATE (homo_localized(dft_control%nspins))
     960          204 :             DO ispin = 1, dft_control%nspins
     961              :                CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, &
     962          110 :                                eigenvalues=mo_eigenvalues)
     963          110 :                occupied_orbs(ispin) = mo_coeff
     964          110 :                occupied_evals(ispin)%array => mo_eigenvalues
     965          110 :                CALL cp_fm_create(homo_localized(ispin), occupied_orbs(ispin)%matrix_struct)
     966          204 :                CALL cp_fm_to_fm(occupied_orbs(ispin), homo_localized(ispin))
     967              :             END DO
     968              : 
     969           94 :             CALL get_qs_env(qs_env, mo_loc_history=mo_loc_history)
     970           94 :             do_homo = .TRUE.
     971              : 
     972          752 :             ALLOCATE (qs_loc_env_homo)
     973           94 :             CALL qs_loc_env_create(qs_loc_env_homo)
     974           94 :             CALL qs_loc_control_init(qs_loc_env_homo, localize_section, do_homo=do_homo)
     975              :             CALL qs_loc_init(qs_env, qs_loc_env_homo, localize_section, homo_localized, do_homo, &
     976           94 :                              mo_section%do_output, mo_loc_history=mo_loc_history)
     977              :             CALL get_localization_info(qs_env, qs_loc_env_homo, localize_section, homo_localized, &
     978           94 :                                        wf_r, wf_g, particles, occupied_orbs, occupied_evals, marked_states)
     979              : 
     980              :             !retain the homo_localized for future use
     981           94 :             IF (qs_loc_env_homo%localized_wfn_control%use_history) THEN
     982           10 :                CALL retain_history(mo_loc_history, homo_localized)
     983           10 :                CALL set_qs_env(qs_env, mo_loc_history=mo_loc_history)
     984              :             END IF
     985              : 
     986              :             !write restart for localization of occupied orbitals
     987              :             CALL loc_write_restart(qs_loc_env_homo, loc_print_section, mos, &
     988           94 :                                    homo_localized, do_homo)
     989           94 :             CALL cp_fm_release(homo_localized)
     990           94 :             DEALLOCATE (occupied_orbs)
     991           94 :             DEALLOCATE (occupied_evals)
     992              :             ! Print Total Dipole if the localization has been performed
     993          188 :             IF (qs_loc_env_homo%do_localize) THEN
     994           78 :                CALL loc_dipole(input, dft_control, qs_loc_env_homo, logger, qs_env)
     995              :             END IF
     996              :          END IF
     997              :       END IF
     998              : 
     999              :       ! Gets the lumos, and eigenvalues for the lumos, and localize them if requested
    1000        12887 :       IF (do_kpoints) THEN
    1001         1084 :          IF (mo_section%do_output .OR. p_loc_lumo) THEN
    1002              :             ! nothing at the moment, not implemented
    1003            2 :             CPWARN("Localization and MO related output not implemented for k-point calculations!")
    1004              :          END IF
    1005              :       ELSE
    1006        11803 :          compute_lumos = mo_section%do_output .AND. nlumo /= 0
    1007        11803 :          compute_lumos = compute_lumos .OR. p_loc_lumo
    1008              : 
    1009        26002 :          DO ispin = 1, dft_control%nspins
    1010        14199 :             CALL get_mo_set(mo_set=mos(ispin), homo=homo, nmo=nmo)
    1011        40153 :             compute_lumos = compute_lumos .AND. homo == nmo
    1012              :          END DO
    1013              : 
    1014        11803 :          IF (mo_section%do_output .AND. .NOT. compute_lumos) THEN
    1015              : 
    1016           98 :             nlumo = section_get_ival(dft_section, mo_section%concat_to_relative("%NLUMO"))
    1017          198 :             DO ispin = 1, dft_control%nspins
    1018              : 
    1019          100 :                CALL get_mo_set(mo_set=mos(ispin), homo=homo, nmo=nmo, eigenvalues=mo_eigenvalues)
    1020          198 :                IF (nlumo > nmo - homo) THEN
    1021              :                   ! this case not yet implemented
    1022              :                ELSE
    1023          100 :                   IF (nlumo == -1) THEN
    1024            0 :                      nlumo = nmo - homo
    1025              :                   END IF
    1026          100 :                   IF (output_unit > 0) WRITE (output_unit, *) " "
    1027          100 :                   IF (output_unit > 0) WRITE (output_unit, *) " Lowest eigenvalues of the unoccupied subspace spin ", ispin
    1028          100 :                   IF (output_unit > 0) WRITE (output_unit, *) "---------------------------------------------"
    1029          107 :                   IF (output_unit > 0) WRITE (output_unit, '(4(1X,1F16.8))') mo_eigenvalues(homo + 1:homo + nlumo)
    1030              : 
    1031              :                   ! Prints the cube files of UNOCCUPIED ORBITALS
    1032          100 :                   CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff)
    1033              :                   CALL qs_scf_post_unocc_cubes(input, dft_section, dft_control, logger, qs_env, &
    1034          100 :                                           mo_coeff, wf_g, wf_r, particles, nlumo, homo, ispin, lumo=homo + 1, mo_section=mo_section)
    1035              :                END IF
    1036              :             END DO
    1037              : 
    1038              :          END IF
    1039              : 
    1040        11771 :          IF (compute_lumos) THEN
    1041           32 :             check_write = .TRUE.
    1042           32 :             min_lumos = nlumo
    1043           32 :             IF (nlumo == 0) check_write = .FALSE.
    1044           32 :             IF (p_loc_lumo) THEN
    1045            6 :                do_homo = .FALSE.
    1046           48 :                ALLOCATE (qs_loc_env_lumo)
    1047            6 :                CALL qs_loc_env_create(qs_loc_env_lumo)
    1048            6 :                CALL qs_loc_control_init(qs_loc_env_lumo, localize_section, do_homo=do_homo)
    1049           98 :                min_lumos = MAX(MAXVAL(qs_loc_env_lumo%localized_wfn_control%loc_states(:, :)), nlumo)
    1050              :             END IF
    1051              : 
    1052          144 :             ALLOCATE (unoccupied_orbs(dft_control%nspins))
    1053          144 :             ALLOCATE (unoccupied_evals(dft_control%nspins))
    1054           32 :             CALL make_lumo_gpw(qs_env, scf_env, unoccupied_orbs, unoccupied_evals, min_lumos, nlumos)
    1055           32 :             lumo_ptr => unoccupied_orbs
    1056           80 :             DO ispin = 1, dft_control%nspins
    1057           48 :                has_lumo = .TRUE.
    1058           48 :                homo_lumo(ispin, 2) = unoccupied_evals(ispin)%array(1)
    1059           48 :                CALL get_mo_set(mo_set=mos(ispin), homo=homo)
    1060           80 :                IF (check_write) THEN
    1061           48 :                   IF (p_loc_lumo .AND. nlumo /= -1) nlumos = MIN(nlumo, nlumos)
    1062              :                   ! Prints the cube files of UNOCCUPIED ORBITALS
    1063              :                   CALL qs_scf_post_unocc_cubes(input, dft_section, dft_control, logger, qs_env, &
    1064           48 :                                           unoccupied_orbs(ispin), wf_g, wf_r, particles, nlumos, homo, ispin, mo_section=mo_section)
    1065              :                END IF
    1066              :             END DO
    1067              : 
    1068           64 :             IF (p_loc_lumo) THEN
    1069           30 :                ALLOCATE (lumo_localized(dft_control%nspins))
    1070           18 :                DO ispin = 1, dft_control%nspins
    1071           12 :                   CALL cp_fm_create(lumo_localized(ispin), unoccupied_orbs(ispin)%matrix_struct)
    1072           18 :                   CALL cp_fm_to_fm(unoccupied_orbs(ispin), lumo_localized(ispin))
    1073              :                END DO
    1074              :                CALL qs_loc_init(qs_env, qs_loc_env_lumo, localize_section, lumo_localized, do_homo, mo_section%do_output, &
    1075            6 :                                 evals=unoccupied_evals)
    1076              :                CALL qs_loc_env_init(qs_loc_env_lumo, qs_loc_env_lumo%localized_wfn_control, qs_env, &
    1077            6 :                                     loc_coeff=unoccupied_orbs)
    1078              :                CALL get_localization_info(qs_env, qs_loc_env_lumo, localize_section, &
    1079              :                                           lumo_localized, wf_r, wf_g, particles, &
    1080            6 :                                           unoccupied_orbs, unoccupied_evals, marked_states)
    1081              :                CALL loc_write_restart(qs_loc_env_lumo, loc_print_section, mos, homo_localized, do_homo, &
    1082            6 :                                       evals=unoccupied_evals)
    1083            6 :                lumo_ptr => lumo_localized
    1084              :             END IF
    1085              :          END IF
    1086              : 
    1087           32 :          IF (has_homo .AND. has_lumo) THEN
    1088           32 :             IF (output_unit > 0) WRITE (output_unit, *) " "
    1089           80 :             DO ispin = 1, dft_control%nspins
    1090           80 :                IF (.NOT. scf_control%smear%do_smear) THEN
    1091           48 :                   gap = homo_lumo(ispin, 2) - homo_lumo(ispin, 1)
    1092           48 :                   IF (output_unit > 0) WRITE (output_unit, '(T2,A,F12.6)') &
    1093           24 :                      "HOMO - LUMO gap [eV] :", gap*evolt
    1094              :                END IF
    1095              :             END DO
    1096              :          END IF
    1097              :       END IF
    1098              : 
    1099        12887 :       IF (p_loc_mixed) THEN
    1100            2 :          IF (do_kpoints) THEN
    1101            0 :             CPWARN("Localization not implemented for k-point calculations!")
    1102            2 :          ELSE IF (dft_control%restricted) THEN
    1103            0 :             IF (output_unit > 0) WRITE (output_unit, *) &
    1104            0 :                " Unclear how we define MOs / localization in the restricted case... skipping"
    1105              :          ELSE
    1106              : 
    1107            8 :             ALLOCATE (mixed_orbs(dft_control%nspins))
    1108            8 :             ALLOCATE (mixed_evals(dft_control%nspins))
    1109            8 :             ALLOCATE (mixed_localized(dft_control%nspins))
    1110            4 :             DO ispin = 1, dft_control%nspins
    1111              :                CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, &
    1112            2 :                                eigenvalues=mo_eigenvalues)
    1113            2 :                mixed_orbs(ispin) = mo_coeff
    1114            2 :                mixed_evals(ispin)%array => mo_eigenvalues
    1115            2 :                CALL cp_fm_create(mixed_localized(ispin), mixed_orbs(ispin)%matrix_struct)
    1116            4 :                CALL cp_fm_to_fm(mixed_orbs(ispin), mixed_localized(ispin))
    1117              :             END DO
    1118              : 
    1119            2 :             CALL get_qs_env(qs_env, mo_loc_history=mo_loc_history)
    1120            2 :             do_homo = .FALSE.
    1121            2 :             do_mixed = .TRUE.
    1122            2 :             total_zeff_corr = scf_env%sum_zeff_corr
    1123           16 :             ALLOCATE (qs_loc_env_mixed)
    1124            2 :             CALL qs_loc_env_create(qs_loc_env_mixed)
    1125            2 :             CALL qs_loc_control_init(qs_loc_env_mixed, localize_section, do_homo=do_homo, do_mixed=do_mixed)
    1126              :             CALL qs_loc_init(qs_env, qs_loc_env_mixed, localize_section, mixed_localized, do_homo, &
    1127              :                              mo_section%do_output, mo_loc_history=mo_loc_history, tot_zeff_corr=total_zeff_corr, &
    1128            2 :                              do_mixed=do_mixed)
    1129              : 
    1130            4 :             DO ispin = 1, dft_control%nspins
    1131            4 :                CALL cp_fm_get_info(mixed_localized(ispin), ncol_global=nchk_nmoloc)
    1132              :             END DO
    1133              : 
    1134              :             CALL get_localization_info(qs_env, qs_loc_env_mixed, localize_section, mixed_localized, &
    1135            2 :                                        wf_r, wf_g, particles, mixed_orbs, mixed_evals, marked_states)
    1136              : 
    1137              :             !retain the homo_localized for future use
    1138            2 :             IF (qs_loc_env_mixed%localized_wfn_control%use_history) THEN
    1139            0 :                CALL retain_history(mo_loc_history, mixed_localized)
    1140            0 :                CALL set_qs_env(qs_env, mo_loc_history=mo_loc_history)
    1141              :             END IF
    1142              : 
    1143              :             !write restart for localization of occupied orbitals
    1144              :             CALL loc_write_restart(qs_loc_env_mixed, loc_print_section, mos, &
    1145            2 :                                    mixed_localized, do_homo, do_mixed=do_mixed)
    1146            2 :             CALL cp_fm_release(mixed_localized)
    1147            2 :             DEALLOCATE (mixed_orbs)
    1148            4 :             DEALLOCATE (mixed_evals)
    1149              :          END IF
    1150              :       END IF
    1151              : 
    1152              :       ! Deallocate grids needed to compute wavefunctions
    1153        12887 :       IF (((mo_section%do_output .OR. do_wannier_cubes) .AND. (nlumo /= 0 .OR. nhomo /= 0)) .OR. p_loc) THEN
    1154          216 :          CALL auxbas_pw_pool%give_back_pw(wf_r)
    1155          216 :          CALL auxbas_pw_pool%give_back_pw(wf_g)
    1156              :       END IF
    1157              : 
    1158              :       ! Destroy the localization environment
    1159        12887 :       IF (.NOT. do_kpoints) THEN
    1160        11803 :          IF (p_loc_homo) THEN
    1161           94 :             CALL qs_loc_env_release(qs_loc_env_homo)
    1162           94 :             DEALLOCATE (qs_loc_env_homo)
    1163              :          END IF
    1164        11803 :          IF (p_loc_lumo) THEN
    1165            6 :             CALL qs_loc_env_release(qs_loc_env_lumo)
    1166            6 :             DEALLOCATE (qs_loc_env_lumo)
    1167              :          END IF
    1168        11803 :          IF (p_loc_mixed) THEN
    1169            2 :             CALL qs_loc_env_release(qs_loc_env_mixed)
    1170            2 :             DEALLOCATE (qs_loc_env_mixed)
    1171              :          END IF
    1172              :       END IF
    1173              : 
    1174              :       ! generate a mix of wfns, and write to a restart
    1175        12887 :       IF (do_kpoints) THEN
    1176              :          ! nothing at the moment, not implemented
    1177              :       ELSE
    1178        11803 :          CALL get_qs_env(qs_env, matrix_s=matrix_s, para_env=para_env)
    1179              :          CALL wfn_mix(mos, particle_set, dft_section, qs_kind_set, para_env, &
    1180              :                       output_unit, unoccupied_orbs=lumo_ptr, scf_env=scf_env, &
    1181        11803 :                       matrix_s=matrix_s, marked_states=marked_states)
    1182              : 
    1183        11803 :          IF (p_loc_lumo) CALL cp_fm_release(lumo_localized)
    1184              :       END IF
    1185        12887 :       IF (ASSOCIATED(marked_states)) THEN
    1186           16 :          DEALLOCATE (marked_states)
    1187              :       END IF
    1188              : 
    1189              :       ! This is just a deallocation for printing MO_CUBES or TDDFPT
    1190        12887 :       IF (.NOT. do_kpoints) THEN
    1191        11803 :          IF (compute_lumos) THEN
    1192           80 :             DO ispin = 1, dft_control%nspins
    1193           48 :                DEALLOCATE (unoccupied_evals(ispin)%array)
    1194           80 :                CALL cp_fm_release(unoccupied_orbs(ispin))
    1195              :             END DO
    1196           32 :             DEALLOCATE (unoccupied_evals)
    1197           32 :             DEALLOCATE (unoccupied_orbs)
    1198              :          END IF
    1199              :       END IF
    1200              : 
    1201              :       !stm images
    1202        12887 :       IF (do_stm) THEN
    1203            6 :          IF (do_kpoints) THEN
    1204            0 :             CPWARN("STM not implemented for k-point calculations!")
    1205              :          ELSE
    1206            6 :             NULLIFY (unoccupied_orbs_stm, unoccupied_evals_stm)
    1207            6 :             IF (nlumo_stm > 0) THEN
    1208            8 :                ALLOCATE (unoccupied_orbs_stm(dft_control%nspins))
    1209            8 :                ALLOCATE (unoccupied_evals_stm(dft_control%nspins))
    1210              :                CALL make_lumo_gpw(qs_env, scf_env, unoccupied_orbs_stm, unoccupied_evals_stm, &
    1211            2 :                                   nlumo_stm, nlumos)
    1212              :             END IF
    1213              : 
    1214              :             CALL th_stm_image(qs_env, stm_section, particles, unoccupied_orbs_stm, &
    1215            6 :                               unoccupied_evals_stm)
    1216              : 
    1217            6 :             IF (nlumo_stm > 0) THEN
    1218            4 :                DO ispin = 1, dft_control%nspins
    1219            4 :                   DEALLOCATE (unoccupied_evals_stm(ispin)%array)
    1220              :                END DO
    1221            2 :                DEALLOCATE (unoccupied_evals_stm)
    1222            2 :                CALL cp_fm_release(unoccupied_orbs_stm)
    1223              :             END IF
    1224              :          END IF
    1225              :       END IF
    1226              : 
    1227              :       ! Print coherent X-ray diffraction spectrum
    1228        12887 :       CALL qs_scf_post_xray(input, dft_section, logger, qs_env, output_unit)
    1229              : 
    1230              :       ! Calculation of Electric Field Gradients
    1231        12887 :       CALL qs_scf_post_efg(input, logger, qs_env)
    1232              : 
    1233              :       ! Calculation of ET
    1234        12887 :       CALL qs_scf_post_et(input, qs_env, dft_control)
    1235              : 
    1236              :       ! Calculation of EPR Hyperfine Coupling Tensors
    1237        12887 :       CALL qs_scf_post_epr(input, logger, qs_env)
    1238              : 
    1239              :       ! Calculation of properties needed for BASIS_MOLOPT optimizations
    1240        12887 :       CALL qs_scf_post_molopt(input, logger, qs_env)
    1241              : 
    1242              :       ! Calculate ELF
    1243        12887 :       CALL qs_scf_post_elf(input, logger, qs_env)
    1244              : 
    1245              :       ! Use Wannier90 interface
    1246        12887 :       CALL wannier90_interface(input, logger, qs_env)
    1247              : 
    1248        12887 :       IF (my_do_mp2) THEN
    1249              :          ! Get everything back
    1250          742 :          DO ispin = 1, dft_control%nspins
    1251          742 :             CALL dbcsr_add(rho_ao(ispin, 1)%matrix, matrix_p_mp2(ispin)%matrix, 1.0_dp, -1.0_dp)
    1252              :          END DO
    1253          322 :          CALL qs_rho_update_rho(rho, qs_env=qs_env)
    1254          322 :          CALL qs_ks_did_change(qs_env%ks_env, rho_changed=.TRUE.)
    1255              :       END IF
    1256              : 
    1257        12887 :       CALL cp_openpmd_close_iterations()
    1258              : 
    1259        12887 :       CALL timestop(handle)
    1260              : 
    1261        25774 :    END SUBROUTINE scf_post_calculation_gpw
    1262              : 
    1263              : ! **************************************************************************************************
    1264              : !> \brief Gets the LUMOs and their eigenvalues for all spin channels.
    1265              : !> \param qs_env ...
    1266              : !> \param scf_env ...
    1267              : !> \param unoccupied_orbs ...
    1268              : !> \param unoccupied_evals ...
    1269              : !> \param nlumo ...
    1270              : !> \param nlumos ...
    1271              : ! **************************************************************************************************
    1272           36 :    SUBROUTINE make_lumo_gpw(qs_env, scf_env, unoccupied_orbs, unoccupied_evals, nlumo, nlumos)
    1273              : 
    1274              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1275              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    1276              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(INOUT)      :: unoccupied_orbs
    1277              :       TYPE(cp_1d_r_p_type), DIMENSION(:), POINTER        :: unoccupied_evals
    1278              :       INTEGER, INTENT(IN)                                :: nlumo
    1279              :       INTEGER, INTENT(OUT)                               :: nlumos
    1280              : 
    1281              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'make_lumo_gpw'
    1282              : 
    1283              :       INTEGER                                            :: handle, homo, ispin, n, nao, nmo, &
    1284              :                                                             output_unit
    1285              :       TYPE(admm_type), POINTER                           :: admm_env
    1286              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1287              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_tmp
    1288              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    1289              :       TYPE(cp_logger_type), POINTER                      :: logger
    1290           36 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: ks_rmpv, matrix_s
    1291              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1292           36 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    1293              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1294              :       TYPE(preconditioner_type), POINTER                 :: local_preconditioner
    1295              :       TYPE(scf_control_type), POINTER                    :: scf_control
    1296              : 
    1297           36 :       CALL timeset(routineN, handle)
    1298              : 
    1299           36 :       NULLIFY (ks_rmpv, matrix_s, scf_control, dft_control, admm_env, para_env, blacs_env, mos)
    1300              :       CALL get_qs_env(qs_env, &
    1301              :                       matrix_ks=ks_rmpv, &
    1302              :                       matrix_s=matrix_s, &
    1303              :                       scf_control=scf_control, &
    1304              :                       dft_control=dft_control, &
    1305              :                       admm_env=admm_env, &
    1306              :                       para_env=para_env, &
    1307              :                       blacs_env=blacs_env, &
    1308           36 :                       mos=mos)
    1309              : 
    1310           36 :       logger => cp_get_default_logger()
    1311           36 :       output_unit = cp_logger_get_default_io_unit(logger)
    1312              : 
    1313           88 :       DO ispin = 1, dft_control%nspins
    1314           52 :          NULLIFY (unoccupied_evals(ispin)%array)
    1315           52 :          IF (output_unit > 0) WRITE (output_unit, *) " "
    1316           52 :          IF (output_unit > 0) WRITE (output_unit, *) &
    1317           26 :             " Using OT eigensolver for additional unoccupied orbitals spin ", ispin
    1318           52 :          IF (output_unit > 0) WRITE (output_unit, *) &
    1319           26 :             " Lowest Eigenvalues of the unoccupied subspace spin ", ispin
    1320           52 :          IF (output_unit > 0) WRITE (output_unit, FMT='(1X,A)') "-----------------------------------------------------"
    1321           52 :          CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, homo=homo, nao=nao, nmo=nmo)
    1322           52 :          CALL cp_fm_get_info(mo_coeff, nrow_global=n)
    1323           52 :          nlumos = MAX(1, MIN(nlumo, nao - nmo))
    1324           52 :          IF (nlumo == -1) nlumos = nao - nmo
    1325          156 :          ALLOCATE (unoccupied_evals(ispin)%array(nlumos))
    1326              :          CALL cp_fm_struct_create(fm_struct_tmp, para_env=para_env, context=blacs_env, &
    1327           52 :                                   nrow_global=n, ncol_global=nlumos)
    1328           52 :          CALL cp_fm_create(unoccupied_orbs(ispin), fm_struct_tmp, name="lumos")
    1329           52 :          CALL cp_fm_struct_release(fm_struct_tmp)
    1330           52 :          CALL cp_fm_init_random(unoccupied_orbs(ispin), nlumos)
    1331              : 
    1332              :          ! FULL_ALL has column-dependent occupied-state weights and cannot be reused here.
    1333           52 :          NULLIFY (local_preconditioner)
    1334           52 :          IF (ASSOCIATED(scf_env)) THEN
    1335           52 :             IF (ASSOCIATED(scf_env%ot_preconditioner)) THEN
    1336           28 :                local_preconditioner => scf_env%ot_preconditioner(1)%preconditioner
    1337           28 :                IF (local_preconditioner%in_use == ot_precond_full_all .OR. &
    1338              :                    local_preconditioner%in_use == ot_precond_full_all_covariant) THEN
    1339            4 :                   NULLIFY (local_preconditioner)
    1340              :                END IF
    1341              :             END IF
    1342              :          END IF
    1343              : 
    1344              :          ! If we do ADMM, we add have to modify the Kohn-Sham matrix
    1345           52 :          IF (dft_control%do_admm) THEN
    1346            0 :             CALL admm_correct_for_eigenvalues(ispin, admm_env, ks_rmpv(ispin)%matrix)
    1347              :          END IF
    1348              : 
    1349              :          CALL ot_eigensolver(matrix_h=ks_rmpv(ispin)%matrix, matrix_s=matrix_s(1)%matrix, &
    1350              :                              matrix_c_fm=unoccupied_orbs(ispin), &
    1351              :                              matrix_orthogonal_space_fm=mo_coeff, &
    1352              :                              eps_gradient=scf_control%eps_lumos, &
    1353              :                              preconditioner=local_preconditioner, &
    1354              :                              iter_max=scf_control%max_iter_lumos, &
    1355           52 :                              size_ortho_space=nmo)
    1356              : 
    1357              :          CALL calculate_subspace_eigenvalues(unoccupied_orbs(ispin), ks_rmpv(ispin)%matrix, &
    1358              :                                              unoccupied_evals(ispin)%array, scr=output_unit, &
    1359           52 :                                              ionode=output_unit > 0)
    1360              : 
    1361              :          ! If we do ADMM, we restore the original Kohn-Sham matrix
    1362          140 :          IF (dft_control%do_admm) THEN
    1363            0 :             CALL admm_uncorrect_for_eigenvalues(ispin, admm_env, ks_rmpv(ispin)%matrix)
    1364              :          END IF
    1365              : 
    1366              :       END DO
    1367              : 
    1368           36 :       CALL timestop(handle)
    1369              : 
    1370           36 :    END SUBROUTINE make_lumo_gpw
    1371              : 
    1372              : ! **************************************************************************************************
    1373              : !> \brief Computes and Prints Atomic Charges with several methods
    1374              : !> \param input ...
    1375              : !> \param logger ...
    1376              : !> \param qs_env the qs_env in which the qs_env lives
    1377              : ! **************************************************************************************************
    1378        12887 :    SUBROUTINE qs_scf_post_charges(input, logger, qs_env)
    1379              :       TYPE(section_vals_type), POINTER                   :: input
    1380              :       TYPE(cp_logger_type), POINTER                      :: logger
    1381              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1382              : 
    1383              :       CHARACTER(len=*), PARAMETER :: routineN = 'qs_scf_post_charges'
    1384              : 
    1385              :       INTEGER                                            :: handle, print_level, unit_nr
    1386              :       LOGICAL                                            :: do_kpoints, print_it
    1387              :       TYPE(section_vals_type), POINTER                   :: density_fit_section, print_key
    1388              : 
    1389        12887 :       CALL timeset(routineN, handle)
    1390              : 
    1391        12887 :       CALL get_qs_env(qs_env=qs_env, do_kpoints=do_kpoints)
    1392              : 
    1393              :       ! Mulliken charges require no further computation and are printed from write_mo_free_results
    1394              : 
    1395              :       ! Compute the Lowdin charges
    1396        12887 :       print_key => section_vals_get_subs_vals(input, "DFT%PRINT%LOWDIN")
    1397        12887 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    1398              :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%LOWDIN", extension=".lowdin", &
    1399           92 :                                         log_filename=.FALSE.)
    1400           92 :          print_level = 1
    1401           92 :          CALL section_vals_val_get(print_key, "PRINT_GOP", l_val=print_it)
    1402           92 :          IF (print_it) print_level = 2
    1403           92 :          CALL section_vals_val_get(print_key, "PRINT_ALL", l_val=print_it)
    1404           92 :          IF (print_it) print_level = 3
    1405           92 :          CALL lowdin_population_analysis(qs_env, unit_nr, print_level)
    1406           92 :          CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%LOWDIN")
    1407              :       END IF
    1408              : 
    1409              :       ! Compute the RESP charges
    1410        12887 :       CALL resp_fit(qs_env)
    1411              : 
    1412              :       ! Compute the Density Derived Atomic Point charges with the Bloechl scheme
    1413        12887 :       print_key => section_vals_get_subs_vals(input, "PROPERTIES%FIT_CHARGE")
    1414        12887 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    1415              :          unit_nr = cp_print_key_unit_nr(logger, input, "PROPERTIES%FIT_CHARGE", extension=".Fitcharge", &
    1416          100 :                                         log_filename=.FALSE.)
    1417          100 :          density_fit_section => section_vals_get_subs_vals(input, "DFT%DENSITY_FITTING")
    1418          100 :          CALL get_ddapc(qs_env, .FALSE., density_fit_section, iwc=unit_nr)
    1419          100 :          CALL cp_print_key_finished_output(unit_nr, logger, input, "PROPERTIES%FIT_CHARGE")
    1420              :       END IF
    1421              : 
    1422        12887 :       CALL timestop(handle)
    1423              : 
    1424        12887 :    END SUBROUTINE qs_scf_post_charges
    1425              : 
    1426              : ! **************************************************************************************************
    1427              : !> \brief Computes and prints the Cube Files for MO
    1428              : !> \param input ...
    1429              : !> \param dft_section ...
    1430              : !> \param dft_control ...
    1431              : !> \param logger ...
    1432              : !> \param qs_env the qs_env in which the qs_env lives
    1433              : !> \param mo_coeff ...
    1434              : !> \param wf_g ...
    1435              : !> \param wf_r ...
    1436              : !> \param particles ...
    1437              : !> \param homo ...
    1438              : !> \param ispin ...
    1439              : !> \param mo_section ...
    1440              : ! **************************************************************************************************
    1441          148 :    SUBROUTINE qs_scf_post_occ_cubes(input, dft_section, dft_control, logger, qs_env, &
    1442              :                                     mo_coeff, wf_g, wf_r, particles, homo, ispin, mo_section)
    1443              :       TYPE(section_vals_type), POINTER                   :: input, dft_section
    1444              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1445              :       TYPE(cp_logger_type), POINTER                      :: logger
    1446              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1447              :       TYPE(cp_fm_type), INTENT(IN)                       :: mo_coeff
    1448              :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: wf_g
    1449              :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: wf_r
    1450              :       TYPE(particle_list_type), POINTER                  :: particles
    1451              :       INTEGER, INTENT(IN)                                :: homo, ispin
    1452              :       TYPE(cp_section_key)                               :: mo_section
    1453              : 
    1454              :       CHARACTER(len=*), PARAMETER :: routineN = 'qs_scf_post_occ_cubes'
    1455              : 
    1456              :       CHARACTER(LEN=default_path_length)                 :: filename, my_pos_cube, title
    1457              :       INTEGER                                            :: handle, i, ir, ivector, n_rep, nhomo, &
    1458              :                                                             nlist, unit_nr
    1459          148 :       INTEGER, DIMENSION(:), POINTER                     :: list, list_index
    1460              :       LOGICAL                                            :: append_cube, mpi_io
    1461          148 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: zcharge
    1462          148 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1463              :       TYPE(cell_type), POINTER                           :: cell
    1464          148 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1465              :       TYPE(pw_env_type), POINTER                         :: pw_env
    1466          148 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1467              : 
    1468          148 :       CALL timeset(routineN, handle)
    1469              : 
    1470              : #ifndef __OPENPMD
    1471              :       ! Error should usually be caught earlier as PRINT%MO_OPENPMD is not added to the input section
    1472              :       ! if openPMD is not activated
    1473          148 :       CPASSERT(mo_section%grid_output /= grid_output_openpmd)
    1474              : #endif
    1475              : 
    1476          148 :       NULLIFY (list_index)
    1477              : 
    1478              :       IF (BTEST(cp_print_key_should_output(logger%iter_info, dft_section, mo_section%relative_section_key) &
    1479          148 :  , cp_p_file) .AND. section_get_lval(dft_section, mo_section%concat_to_relative(section_key_do_write(mo_section%grid_output)))) THEN
    1480          110 :          CALL get_effective_core_charges(qs_env, zcharge)
    1481          110 :          nhomo = section_get_ival(dft_section, mo_section%concat_to_relative("%NHOMO"))
    1482              :          ! For openPMD, refer to access modes instead of APPEND key
    1483          110 :          IF (mo_section%grid_output == grid_output_cubes) THEN
    1484          110 :             append_cube = section_get_lval(dft_section, mo_section%concat_to_relative("%APPEND"))
    1485              :          END IF
    1486          110 :          my_pos_cube = "REWIND"
    1487          110 :          IF (append_cube) THEN
    1488            0 :             my_pos_cube = "APPEND"
    1489              :          END IF
    1490          110 :          CALL section_vals_val_get(dft_section, mo_section%concat_to_relative("%HOMO_LIST"), n_rep_val=n_rep)
    1491          110 :          IF (n_rep > 0) THEN ! write the cubes of the list
    1492            0 :             nlist = 0
    1493            0 :             DO ir = 1, n_rep
    1494            0 :                NULLIFY (list)
    1495              :                CALL section_vals_val_get(dft_section, mo_section%concat_to_relative("%HOMO_LIST"), i_rep_val=ir, &
    1496            0 :                                          i_vals=list)
    1497            0 :                IF (ASSOCIATED(list)) THEN
    1498            0 :                   CALL reallocate(list_index, 1, nlist + SIZE(list))
    1499            0 :                   DO i = 1, SIZE(list)
    1500            0 :                      list_index(i + nlist) = list(i)
    1501              :                   END DO
    1502            0 :                   nlist = nlist + SIZE(list)
    1503              :                END IF
    1504              :             END DO
    1505              :          ELSE
    1506              : 
    1507          110 :             IF (nhomo == -1) nhomo = homo
    1508          110 :             nlist = homo - MAX(1, homo - nhomo + 1) + 1
    1509          330 :             ALLOCATE (list_index(nlist))
    1510          224 :             DO i = 1, nlist
    1511          224 :                list_index(i) = MAX(1, homo - nhomo + 1) + i - 1
    1512              :             END DO
    1513              :          END IF
    1514          224 :          DO i = 1, nlist
    1515          114 :             ivector = list_index(i)
    1516              :             CALL get_qs_env(qs_env=qs_env, &
    1517              :                             atomic_kind_set=atomic_kind_set, &
    1518              :                             qs_kind_set=qs_kind_set, &
    1519              :                             cell=cell, &
    1520              :                             particle_set=particle_set, &
    1521          114 :                             pw_env=pw_env)
    1522              :             CALL calculate_wavefunction(mo_coeff, ivector, wf_r, wf_g, atomic_kind_set, qs_kind_set, &
    1523          114 :                                         cell, dft_control, particle_set, pw_env)
    1524          114 :             WRITE (filename, '(a4,I5.5,a1,I1.1)') "WFN_", ivector, "_", ispin
    1525          114 :             mpi_io = .TRUE.
    1526              : 
    1527              :             unit_nr = mo_section%print_key_unit_nr( &
    1528              :                       logger, &
    1529              :                       input, &
    1530              :                       mo_section%absolute_section_key, &
    1531              :                       extension=".cube", &
    1532              :                       middle_name=TRIM(filename), &
    1533              :                       file_position=my_pos_cube, &
    1534              :                       log_filename=.FALSE., &
    1535              :                       mpi_io=mpi_io, &
    1536              :                       openpmd_basename="dft-mo", &
    1537              :                       openpmd_unit_dimension=openpmd_unit_dimension_wavefunction, &
    1538              :                       openpmd_unit_si=openpmd_unit_si_wavefunction, &
    1539          114 :                       sim_time=qs_env%sim_time)
    1540          114 :             WRITE (title, *) "WAVEFUNCTION ", ivector, " spin ", ispin, " i.e. HOMO - ", ivector - homo
    1541              :             CALL mo_section%write_pw(wf_r, unit_nr, title, particles=particles, zeff=zcharge, &
    1542              :                                      stride=section_get_ivals(dft_section, mo_section%concat_to_relative("%STRIDE")), &
    1543              :                                      max_file_size_mb=section_get_rval(dft_section, "PRINT%MO_CUBES%MAX_FILE_SIZE_MB"), &
    1544          114 :                                      mpi_io=mpi_io)
    1545          224 :             CALL mo_section%print_key_finished_output(unit_nr, logger, input, mo_section%absolute_section_key, mpi_io=mpi_io)
    1546              :          END DO
    1547          110 :          IF (ASSOCIATED(list_index)) DEALLOCATE (list_index)
    1548          258 :          DEALLOCATE (zcharge)
    1549              :       END IF
    1550              : 
    1551          148 :       CALL timestop(handle)
    1552              : 
    1553          296 :    END SUBROUTINE qs_scf_post_occ_cubes
    1554              : 
    1555              : ! **************************************************************************************************
    1556              : !> \brief Computes and prints the Cube Files for MO
    1557              : !> \param input ...
    1558              : !> \param dft_section ...
    1559              : !> \param dft_control ...
    1560              : !> \param logger ...
    1561              : !> \param qs_env the qs_env in which the qs_env lives
    1562              : !> \param unoccupied_orbs ...
    1563              : !> \param wf_g ...
    1564              : !> \param wf_r ...
    1565              : !> \param particles ...
    1566              : !> \param nlumos ...
    1567              : !> \param homo ...
    1568              : !> \param ispin ...
    1569              : !> \param lumo ...
    1570              : !> \param mo_section ...
    1571              : ! **************************************************************************************************
    1572          148 :    SUBROUTINE qs_scf_post_unocc_cubes(input, dft_section, dft_control, logger, qs_env, &
    1573              :                                       unoccupied_orbs, wf_g, wf_r, particles, nlumos, homo, ispin, lumo, mo_section)
    1574              : 
    1575              :       TYPE(section_vals_type), POINTER                   :: input, dft_section
    1576              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1577              :       TYPE(cp_logger_type), POINTER                      :: logger
    1578              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1579              :       TYPE(cp_fm_type), INTENT(IN)                       :: unoccupied_orbs
    1580              :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: wf_g
    1581              :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: wf_r
    1582              :       TYPE(particle_list_type), POINTER                  :: particles
    1583              :       INTEGER, INTENT(IN)                                :: nlumos, homo, ispin
    1584              :       INTEGER, INTENT(IN), OPTIONAL                      :: lumo
    1585              :       TYPE(cp_section_key)                               :: mo_section
    1586              : 
    1587              :       CHARACTER(len=*), PARAMETER :: routineN = 'qs_scf_post_unocc_cubes'
    1588              : 
    1589              :       CHARACTER(LEN=default_path_length)                 :: filename, my_pos_cube, title
    1590              :       INTEGER                                            :: handle, ifirst, index_mo, ivector, &
    1591              :                                                             unit_nr
    1592              :       LOGICAL                                            :: append_cube, mpi_io
    1593          148 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: zcharge
    1594          148 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1595              :       TYPE(cell_type), POINTER                           :: cell
    1596          148 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1597              :       TYPE(pw_env_type), POINTER                         :: pw_env
    1598          148 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1599              : 
    1600          148 :       CALL timeset(routineN, handle)
    1601              : 
    1602              : #ifndef __OPENPMD
    1603              :       ! Error should usually be caught earlier as PRINT%MO_OPENPMD is not added to the input section
    1604              :       ! if openPMD is not activated
    1605          148 :       CPASSERT(mo_section%grid_output /= grid_output_openpmd)
    1606              : #endif
    1607              : 
    1608              :       IF (BTEST(cp_print_key_should_output(logger%iter_info, dft_section, mo_section%relative_section_key), cp_p_file) &
    1609          148 :           .AND. section_get_lval(dft_section, mo_section%concat_to_relative(section_key_do_write(mo_section%grid_output)))) THEN
    1610          110 :          CALL get_effective_core_charges(qs_env, zcharge)
    1611          110 :          NULLIFY (qs_kind_set, particle_set, pw_env, cell)
    1612              :          ! For openPMD, refer to access modes instead of APPEND key
    1613          110 :          IF (mo_section%grid_output == grid_output_cubes) THEN
    1614          110 :             append_cube = section_get_lval(dft_section, mo_section%concat_to_relative("%APPEND"))
    1615              :          END IF
    1616          110 :          my_pos_cube = "REWIND"
    1617          110 :          IF (append_cube) THEN
    1618            0 :             my_pos_cube = "APPEND"
    1619              :          END IF
    1620          110 :          ifirst = 1
    1621          110 :          IF (PRESENT(lumo)) ifirst = lumo
    1622          254 :          DO ivector = ifirst, ifirst + nlumos - 1
    1623              :             CALL get_qs_env(qs_env=qs_env, &
    1624              :                             atomic_kind_set=atomic_kind_set, &
    1625              :                             qs_kind_set=qs_kind_set, &
    1626              :                             cell=cell, &
    1627              :                             particle_set=particle_set, &
    1628          144 :                             pw_env=pw_env)
    1629              :             CALL calculate_wavefunction(unoccupied_orbs, ivector, wf_r, wf_g, atomic_kind_set, &
    1630          144 :                                         qs_kind_set, cell, dft_control, particle_set, pw_env)
    1631              : 
    1632          144 :             IF (ifirst == 1) THEN
    1633          130 :                index_mo = homo + ivector
    1634              :             ELSE
    1635           14 :                index_mo = ivector
    1636              :             END IF
    1637          144 :             WRITE (filename, '(a4,I5.5,a1,I1.1)') "WFN_", index_mo, "_", ispin
    1638          144 :             mpi_io = .TRUE.
    1639              : 
    1640              :             unit_nr = mo_section%print_key_unit_nr( &
    1641              :                       logger, &
    1642              :                       input, &
    1643              :                       mo_section%absolute_section_key, &
    1644              :                       extension=".cube", &
    1645              :                       middle_name=TRIM(filename), &
    1646              :                       file_position=my_pos_cube, &
    1647              :                       log_filename=.FALSE., &
    1648              :                       mpi_io=mpi_io, &
    1649              :                       openpmd_basename="dft-mo", &
    1650              :                       openpmd_unit_dimension=openpmd_unit_dimension_wavefunction, &
    1651              :                       openpmd_unit_si=openpmd_unit_si_wavefunction, &
    1652          144 :                       sim_time=qs_env%sim_time)
    1653          144 :             WRITE (title, *) "WAVEFUNCTION ", index_mo, " spin ", ispin, " i.e. LUMO + ", ifirst + ivector - 2
    1654              :             CALL mo_section%write_pw(wf_r, unit_nr, title, particles=particles, zeff=zcharge, &
    1655              :                                      stride=section_get_ivals(dft_section, mo_section%concat_to_relative("%STRIDE")), &
    1656              :                                      max_file_size_mb=section_get_rval(dft_section, "PRINT%MO_CUBES%MAX_FILE_SIZE_MB"), &
    1657          144 :                                      mpi_io=mpi_io)
    1658          254 :             CALL mo_section%print_key_finished_output(unit_nr, logger, input, mo_section%absolute_section_key, mpi_io=mpi_io)
    1659              : 
    1660              :          END DO
    1661          258 :          DEALLOCATE (zcharge)
    1662              :       END IF
    1663              : 
    1664          148 :       CALL timestop(handle)
    1665              : 
    1666          296 :    END SUBROUTINE qs_scf_post_unocc_cubes
    1667              : 
    1668              : ! **************************************************************************************************
    1669              : !> \brief Computes and prints electric moments
    1670              : !> \param input ...
    1671              : !> \param logger ...
    1672              : !> \param qs_env the qs_env in which the qs_env lives
    1673              : !> \param output_unit ...
    1674              : ! **************************************************************************************************
    1675        14087 :    SUBROUTINE qs_scf_post_moments(input, logger, qs_env, output_unit)
    1676              :       TYPE(section_vals_type), POINTER                   :: input
    1677              :       TYPE(cp_logger_type), POINTER                      :: logger
    1678              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1679              :       INTEGER, INTENT(IN)                                :: output_unit
    1680              : 
    1681              :       CHARACTER(len=*), PARAMETER :: routineN = 'qs_scf_post_moments'
    1682              : 
    1683              :       CHARACTER(LEN=default_path_length)                 :: filename
    1684              :       INTEGER                                            :: handle, max_nmo, maxmom, moments_format, &
    1685              :                                                             moments_unit_nr, reference, unit_nr
    1686              :       LOGICAL                                            :: com_nl, do_kg, do_kpoints, magnetic, &
    1687              :                                                             new_file, periodic, second_ref_point, &
    1688              :                                                             vel_reprs
    1689        14087 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: ref_point
    1690              :       TYPE(section_vals_type), POINTER                   :: print_key
    1691              : 
    1692        14087 :       CALL timeset(routineN, handle)
    1693              : 
    1694              :       print_key => section_vals_get_subs_vals(section_vals=input, &
    1695        14087 :                                               subsection_name="DFT%PRINT%MOMENTS")
    1696              : 
    1697        14087 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    1698              : 
    1699              :          maxmom = section_get_ival(section_vals=input, &
    1700         1612 :                                    keyword_name="DFT%PRINT%MOMENTS%MAX_MOMENT")
    1701              :          moments_format = section_get_ival(section_vals=input, &
    1702         1612 :                                            keyword_name="DFT%PRINT%MOMENTS%FORMAT")
    1703              :          periodic = section_get_lval(section_vals=input, &
    1704         1612 :                                      keyword_name="DFT%PRINT%MOMENTS%PERIODIC")
    1705              :          reference = section_get_ival(section_vals=input, &
    1706         1612 :                                       keyword_name="DFT%PRINT%MOMENTS%REFERENCE")
    1707              :          magnetic = section_get_lval(section_vals=input, &
    1708         1612 :                                      keyword_name="DFT%PRINT%MOMENTS%MAGNETIC")
    1709              :          vel_reprs = section_get_lval(section_vals=input, &
    1710         1612 :                                       keyword_name="DFT%PRINT%MOMENTS%VEL_REPRS")
    1711              :          com_nl = section_get_lval(section_vals=input, &
    1712         1612 :                                    keyword_name="DFT%PRINT%MOMENTS%COM_NL")
    1713              :          second_ref_point = section_get_lval(section_vals=input, &
    1714         1612 :                                              keyword_name="DFT%PRINT%MOMENTS%SECOND_REFERENCE_POINT")
    1715              :          do_kg = section_get_lval(section_vals=input, &
    1716         1612 :                                   keyword_name="DFT%PRINT%MOMENTS%KG")
    1717              :          max_nmo = section_get_ival(section_vals=input, &
    1718         1612 :                                     keyword_name="DFT%PRINT%MOMENTS%MAX_NMO")
    1719              : 
    1720         1612 :          NULLIFY (ref_point)
    1721         1612 :          CALL section_vals_val_get(input, "DFT%PRINT%MOMENTS%REF_POINT", r_vals=ref_point)
    1722              :          unit_nr = cp_print_key_unit_nr(logger=logger, basis_section=input, &
    1723              :                                         print_key_path="DFT%PRINT%MOMENTS", extension=".dat", &
    1724              :                                         middle_name="moments", log_filename=.FALSE., &
    1725         1612 :                                         is_new_file=new_file)
    1726              : 
    1727         1612 :          IF (output_unit > 0) THEN
    1728          816 :             IF (unit_nr /= output_unit) THEN
    1729           49 :                INQUIRE (UNIT=unit_nr, NAME=filename)
    1730              :                WRITE (UNIT=output_unit, FMT="(/,T2,A,2(/,T3,A),/)") &
    1731           49 :                   "MOMENTS", "The electric/magnetic moments are written to file:", &
    1732           98 :                   TRIM(filename)
    1733          767 :             ELSE IF (moments_format /= moments_format_trajectory) THEN
    1734          761 :                WRITE (UNIT=output_unit, FMT="(/,T2,A)") "ELECTRIC/MAGNETIC MOMENTS"
    1735              :             END IF
    1736              :          END IF
    1737              : 
    1738         1612 :          CALL get_qs_env(qs_env, do_kpoints=do_kpoints)
    1739              : 
    1740         1612 :          IF (moments_format == moments_format_trajectory) THEN
    1741           12 :             IF (do_kpoints) THEN
    1742            0 :                CPABORT("MOMENTS FORMAT TRAJECTORY is not available for k-point calculations.")
    1743              :             END IF
    1744           12 :             IF (maxmom /= 1) CPABORT("MOMENTS FORMAT TRAJECTORY requires MAX_MOMENT 1.")
    1745           12 :             IF (magnetic) CPABORT("MOMENTS FORMAT TRAJECTORY does not support MAGNETIC moments.")
    1746           12 :             IF (vel_reprs) CPABORT("MOMENTS FORMAT TRAJECTORY does not support VEL_REPRS.")
    1747           12 :             IF (do_kg) CPABORT("MOMENTS FORMAT TRAJECTORY does not support KG moments.")
    1748           12 :             moments_unit_nr = -1
    1749              :          ELSE
    1750         1600 :             moments_unit_nr = unit_nr
    1751              :          END IF
    1752              : 
    1753         1612 :          IF (do_kpoints) THEN
    1754           10 :             CALL qs_moment_kpoints(qs_env, maxmom, reference, ref_point, max_nmo, moments_unit_nr)
    1755              :          ELSE
    1756         1602 :             IF (periodic) THEN
    1757          484 :                CALL qs_moment_berry_phase(qs_env, magnetic, maxmom, reference, ref_point, moments_unit_nr)
    1758              :             ELSE
    1759         1118 :                CALL qs_moment_locop(qs_env, magnetic, maxmom, reference, ref_point, moments_unit_nr, vel_reprs, com_nl)
    1760              :             END IF
    1761         1602 :             IF (do_kg) THEN
    1762            0 :                CALL calculate_kg_moments(qs_env, moments_unit_nr, maxmom, magnetic, vel_reprs, com_nl)
    1763              :             END IF
    1764              :          END IF
    1765         1612 :          IF (moments_format == moments_format_trajectory) THEN
    1766           12 :             CALL write_moments_trajectory(unit_nr, logger, qs_env, periodic, new_file, "MOMENTS|")
    1767              :          END IF
    1768              : 
    1769              :          CALL cp_print_key_finished_output(unit_nr=unit_nr, logger=logger, &
    1770         1612 :                                            basis_section=input, print_key_path="DFT%PRINT%MOMENTS")
    1771              : 
    1772         1612 :          IF (second_ref_point) THEN
    1773              :             reference = section_get_ival(section_vals=input, &
    1774            2 :                                          keyword_name="DFT%PRINT%MOMENTS%REFERENCE_2")
    1775              : 
    1776            2 :             NULLIFY (ref_point)
    1777            2 :             CALL section_vals_val_get(input, "DFT%PRINT%MOMENTS%REF_POINT_2", r_vals=ref_point)
    1778              :             unit_nr = cp_print_key_unit_nr(logger=logger, basis_section=input, &
    1779              :                                            print_key_path="DFT%PRINT%MOMENTS", extension=".dat", &
    1780              :                                            middle_name="moments_refpoint_2", log_filename=.FALSE., &
    1781            2 :                                            is_new_file=new_file)
    1782              : 
    1783            2 :             IF (output_unit > 0) THEN
    1784            1 :                IF (unit_nr /= output_unit) THEN
    1785            0 :                   INQUIRE (UNIT=unit_nr, NAME=filename)
    1786              :                   WRITE (UNIT=output_unit, FMT="(/,T2,A,2(/,T3,A),/)") &
    1787            0 :                      "MOMENTS", "The electric/magnetic moments for the second reference point are written to file:", &
    1788            0 :                      TRIM(filename)
    1789            1 :                ELSE IF (moments_format /= moments_format_trajectory) THEN
    1790            1 :                   WRITE (UNIT=output_unit, FMT="(/,T2,A)") "ELECTRIC/MAGNETIC MOMENTS"
    1791              :                END IF
    1792              :             END IF
    1793            2 :             IF (moments_format /= moments_format_trajectory) moments_unit_nr = unit_nr
    1794            2 :             IF (do_kpoints) THEN
    1795            0 :                CALL qs_moment_kpoints(qs_env, maxmom, reference, ref_point, max_nmo, moments_unit_nr)
    1796              :             ELSE
    1797            2 :                IF (periodic) THEN
    1798            0 :                   CALL qs_moment_berry_phase(qs_env, magnetic, maxmom, reference, ref_point, moments_unit_nr)
    1799              :                ELSE
    1800              :                   CALL qs_moment_locop(qs_env, magnetic, maxmom, reference, ref_point, &
    1801            2 :                                        moments_unit_nr, vel_reprs, com_nl)
    1802              :                END IF
    1803              :             END IF
    1804            2 :             IF (moments_format == moments_format_trajectory) THEN
    1805            0 :                CALL write_moments_trajectory(unit_nr, logger, qs_env, periodic, new_file, "MOMENTS_REF2|")
    1806              :             END IF
    1807              :             CALL cp_print_key_finished_output(unit_nr=unit_nr, logger=logger, &
    1808            2 :                                               basis_section=input, print_key_path="DFT%PRINT%MOMENTS")
    1809              :          END IF
    1810              : 
    1811              :       END IF
    1812              : 
    1813        14087 :       CALL timestop(handle)
    1814              : 
    1815        14087 :    END SUBROUTINE qs_scf_post_moments
    1816              : 
    1817              : ! **************************************************************************************************
    1818              : !> \brief Writes one machine-readable electric-dipole record for the current iteration.
    1819              : !> \param unit_nr output unit
    1820              : !> \param logger logger carrying the current iteration levels
    1821              : !> \param qs_env quantum environment containing the dipole result and cell
    1822              : !> \param periodic whether the Berry-phase operator was used
    1823              : !> \param new_file whether the output file has just been created
    1824              : !> \param label record label
    1825              : ! **************************************************************************************************
    1826           12 :    SUBROUTINE write_moments_trajectory(unit_nr, logger, qs_env, periodic, new_file, label)
    1827              :       INTEGER, INTENT(IN)                                :: unit_nr
    1828              :       TYPE(cp_logger_type), POINTER                      :: logger
    1829              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1830              :       LOGICAL, INTENT(IN)                                :: periodic, new_file
    1831              :       CHARACTER(LEN=*), INTENT(IN)                       :: label
    1832              : 
    1833              :       CHARACTER(LEN=default_string_length)               :: description, iter
    1834              :       REAL(KIND=dp), DIMENSION(3)                        :: dipole
    1835              :       TYPE(cell_type), POINTER                           :: cell
    1836              :       TYPE(cp_result_type), POINTER                      :: results
    1837              : 
    1838           12 :       IF (unit_nr <= 0) RETURN
    1839              : 
    1840            6 :       NULLIFY (cell, results)
    1841            6 :       CALL get_qs_env(qs_env, cell=cell, results=results)
    1842            6 :       description = "[DIPOLE]"
    1843            6 :       CALL get_results(results=results, description=description, values=dipole)
    1844              : 
    1845            6 :       IF (new_file) THEN
    1846            0 :          IF (periodic) THEN
    1847              :             WRITE (unit_nr, "(A)") "# "//TRIM(label)// &
    1848              :                " iter_level dipole_x dipole_y dipole_z dipole_norm cell_xx cell_xy cell_xz"// &
    1849            0 :                " cell_yx cell_yy cell_yz cell_zx cell_zy cell_zz [Debye]"
    1850              :          ELSE
    1851              :             WRITE (unit_nr, "(A)") "# "//TRIM(label)// &
    1852            0 :                " iter_level dipole_x dipole_y dipole_z dipole_norm [Debye]"
    1853              :          END IF
    1854              :       END IF
    1855              : 
    1856            6 :       iter = cp_iter_string(logger%iter_info)
    1857            6 :       IF (periodic) THEN
    1858            6 :          WRITE (unit_nr, "(1X,A,1X,A15,13(1X,ES18.10))") TRIM(label), iter(1:15), &
    1859           42 :             dipole*debye, SQRT(SUM(dipole**2))*debye, &
    1860           66 :             cell%hmat(1, :)*debye, cell%hmat(2, :)*debye, cell%hmat(3, :)*debye
    1861              :       ELSE
    1862            0 :          WRITE (unit_nr, "(1X,A,1X,A15,4(1X,ES18.10))") TRIM(label), iter(1:15), &
    1863            0 :             dipole*debye, SQRT(SUM(dipole**2))*debye
    1864              :       END IF
    1865              : 
    1866              :    END SUBROUTINE write_moments_trajectory
    1867              : 
    1868              : ! **************************************************************************************************
    1869              : !> \brief Computes and prints the X-ray diffraction spectrum.
    1870              : !> \param input ...
    1871              : !> \param dft_section ...
    1872              : !> \param logger ...
    1873              : !> \param qs_env the qs_env in which the qs_env lives
    1874              : !> \param output_unit ...
    1875              : ! **************************************************************************************************
    1876        12887 :    SUBROUTINE qs_scf_post_xray(input, dft_section, logger, qs_env, output_unit)
    1877              : 
    1878              :       TYPE(section_vals_type), POINTER                   :: input, dft_section
    1879              :       TYPE(cp_logger_type), POINTER                      :: logger
    1880              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1881              :       INTEGER, INTENT(IN)                                :: output_unit
    1882              : 
    1883              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'qs_scf_post_xray'
    1884              : 
    1885              :       CHARACTER(LEN=default_path_length)                 :: filename
    1886              :       INTEGER                                            :: handle, unit_nr
    1887              :       REAL(KIND=dp)                                      :: q_max
    1888              :       TYPE(section_vals_type), POINTER                   :: print_key
    1889              : 
    1890        12887 :       CALL timeset(routineN, handle)
    1891              : 
    1892              :       print_key => section_vals_get_subs_vals(section_vals=input, &
    1893        12887 :                                               subsection_name="DFT%PRINT%XRAY_DIFFRACTION_SPECTRUM")
    1894              : 
    1895        12887 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    1896              :          q_max = section_get_rval(section_vals=dft_section, &
    1897           30 :                                   keyword_name="PRINT%XRAY_DIFFRACTION_SPECTRUM%Q_MAX")
    1898              :          unit_nr = cp_print_key_unit_nr(logger=logger, &
    1899              :                                         basis_section=input, &
    1900              :                                         print_key_path="DFT%PRINT%XRAY_DIFFRACTION_SPECTRUM", &
    1901              :                                         extension=".dat", &
    1902              :                                         middle_name="xrd", &
    1903           30 :                                         log_filename=.FALSE.)
    1904           30 :          IF (output_unit > 0) THEN
    1905           15 :             INQUIRE (UNIT=unit_nr, NAME=filename)
    1906              :             WRITE (UNIT=output_unit, FMT="(/,/,T2,A)") &
    1907           15 :                "X-RAY DIFFRACTION SPECTRUM"
    1908           15 :             IF (unit_nr /= output_unit) THEN
    1909              :                WRITE (UNIT=output_unit, FMT="(/,T3,A,/,/,T3,A,/)") &
    1910           14 :                   "The coherent X-ray diffraction spectrum is written to the file:", &
    1911           28 :                   TRIM(filename)
    1912              :             END IF
    1913              :          END IF
    1914              :          CALL xray_diffraction_spectrum(qs_env=qs_env, &
    1915              :                                         unit_number=unit_nr, &
    1916           30 :                                         q_max=q_max)
    1917              :          CALL cp_print_key_finished_output(unit_nr=unit_nr, &
    1918              :                                            logger=logger, &
    1919              :                                            basis_section=input, &
    1920           30 :                                            print_key_path="DFT%PRINT%XRAY_DIFFRACTION_SPECTRUM")
    1921              :       END IF
    1922              : 
    1923        12887 :       CALL timestop(handle)
    1924              : 
    1925        12887 :    END SUBROUTINE qs_scf_post_xray
    1926              : 
    1927              : ! **************************************************************************************************
    1928              : !> \brief Computes and prints Electric Field Gradient
    1929              : !> \param input ...
    1930              : !> \param logger ...
    1931              : !> \param qs_env the qs_env in which the qs_env lives
    1932              : ! **************************************************************************************************
    1933        12887 :    SUBROUTINE qs_scf_post_efg(input, logger, qs_env)
    1934              :       TYPE(section_vals_type), POINTER                   :: input
    1935              :       TYPE(cp_logger_type), POINTER                      :: logger
    1936              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1937              : 
    1938              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'qs_scf_post_efg'
    1939              : 
    1940              :       INTEGER                                            :: handle
    1941              :       TYPE(section_vals_type), POINTER                   :: print_key
    1942              : 
    1943        12887 :       CALL timeset(routineN, handle)
    1944              : 
    1945              :       print_key => section_vals_get_subs_vals(section_vals=input, &
    1946        12887 :                                               subsection_name="DFT%PRINT%ELECTRIC_FIELD_GRADIENT")
    1947        12887 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), &
    1948              :                 cp_p_file)) THEN
    1949           30 :          CALL qs_efg_calc(qs_env=qs_env)
    1950              :       END IF
    1951              : 
    1952        12887 :       CALL timestop(handle)
    1953              : 
    1954        12887 :    END SUBROUTINE qs_scf_post_efg
    1955              : 
    1956              : ! **************************************************************************************************
    1957              : !> \brief Computes the Electron Transfer Coupling matrix element
    1958              : !> \param input ...
    1959              : !> \param qs_env the qs_env in which the qs_env lives
    1960              : !> \param dft_control ...
    1961              : ! **************************************************************************************************
    1962        25774 :    SUBROUTINE qs_scf_post_et(input, qs_env, dft_control)
    1963              :       TYPE(section_vals_type), POINTER                   :: input
    1964              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1965              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1966              : 
    1967              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'qs_scf_post_et'
    1968              : 
    1969              :       INTEGER                                            :: handle, ispin
    1970              :       LOGICAL                                            :: do_et
    1971        12887 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: my_mos
    1972              :       TYPE(section_vals_type), POINTER                   :: et_section
    1973              : 
    1974        12887 :       CALL timeset(routineN, handle)
    1975              : 
    1976              :       do_et = .FALSE.
    1977        12887 :       et_section => section_vals_get_subs_vals(input, "PROPERTIES%ET_COUPLING")
    1978        12887 :       CALL section_vals_get(et_section, explicit=do_et)
    1979        12887 :       IF (do_et) THEN
    1980           10 :          IF (qs_env%et_coupling%first_run) THEN
    1981           10 :             NULLIFY (my_mos)
    1982           50 :             ALLOCATE (my_mos(dft_control%nspins))
    1983           50 :             ALLOCATE (qs_env%et_coupling%et_mo_coeff(dft_control%nspins))
    1984           30 :             DO ispin = 1, dft_control%nspins
    1985              :                CALL cp_fm_create(matrix=my_mos(ispin), &
    1986              :                                  matrix_struct=qs_env%mos(ispin)%mo_coeff%matrix_struct, &
    1987           20 :                                  name="FIRST_RUN_COEFF"//TRIM(ADJUSTL(cp_to_string(ispin)))//"MATRIX")
    1988              :                CALL cp_fm_to_fm(qs_env%mos(ispin)%mo_coeff, &
    1989           30 :                                 my_mos(ispin))
    1990              :             END DO
    1991           10 :             CALL set_et_coupling_type(qs_env%et_coupling, et_mo_coeff=my_mos)
    1992           10 :             DEALLOCATE (my_mos)
    1993              :          END IF
    1994              :       END IF
    1995              : 
    1996        12887 :       CALL timestop(handle)
    1997              : 
    1998        12887 :    END SUBROUTINE qs_scf_post_et
    1999              : 
    2000              : ! **************************************************************************************************
    2001              : !> \brief compute the electron localization function
    2002              : !>
    2003              : !> \param input ...
    2004              : !> \param logger ...
    2005              : !> \param qs_env ...
    2006              : !> \par History
    2007              : !>      2012-07 Created [MI]
    2008              : ! **************************************************************************************************
    2009        12887 :    SUBROUTINE qs_scf_post_elf(input, logger, qs_env)
    2010              :       TYPE(section_vals_type), POINTER                   :: input
    2011              :       TYPE(cp_logger_type), POINTER                      :: logger
    2012              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2013              : 
    2014              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'qs_scf_post_elf'
    2015              : 
    2016              :       CHARACTER(LEN=default_path_length)                 :: filename, mpi_filename, my_pos_cube, &
    2017              :                                                             title
    2018              :       INTEGER                                            :: handle, ispin, output_unit, unit_nr
    2019              :       LOGICAL                                            :: append_cube, gapw, mpi_io
    2020              :       REAL(dp)                                           :: rho_cutoff
    2021        12887 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: zcharge
    2022              :       TYPE(cp_section_key)                               :: elf_section_key
    2023              :       TYPE(dft_control_type), POINTER                    :: dft_control
    2024              :       TYPE(particle_list_type), POINTER                  :: particles
    2025              :       TYPE(pw_env_type), POINTER                         :: pw_env
    2026        12887 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
    2027              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    2028        12887 :       TYPE(pw_r3d_rs_type), ALLOCATABLE, DIMENSION(:)    :: elf_r
    2029              :       TYPE(qs_subsys_type), POINTER                      :: subsys
    2030              :       TYPE(section_vals_type), POINTER                   :: elf_section
    2031              : 
    2032        12887 :       CALL timeset(routineN, handle)
    2033        12887 :       output_unit = cp_logger_get_default_io_unit(logger)
    2034              : 
    2035        12887 :       elf_section_key = cube_or_openpmd(input, str_elf_cubes, str_elf_openpmd, logger)
    2036              : 
    2037        12887 :       elf_section => section_vals_get_subs_vals(input, elf_section_key%absolute_section_key)
    2038        12887 :       IF (elf_section_key%do_output) THEN
    2039              : 
    2040           82 :          NULLIFY (dft_control, pw_env, auxbas_pw_pool, pw_pools, particles, subsys)
    2041           82 :          CALL get_qs_env(qs_env, dft_control=dft_control, pw_env=pw_env, subsys=subsys)
    2042           82 :          CALL qs_subsys_get(subsys, particles=particles)
    2043              : 
    2044           82 :          gapw = dft_control%qs_control%gapw
    2045           82 :          IF (.NOT. gapw) THEN
    2046              :             ! allocate
    2047          330 :             ALLOCATE (elf_r(dft_control%nspins))
    2048              :             CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
    2049           82 :                             pw_pools=pw_pools)
    2050          166 :             DO ispin = 1, dft_control%nspins
    2051           84 :                CALL auxbas_pw_pool%create_pw(elf_r(ispin))
    2052          166 :                CALL pw_zero(elf_r(ispin))
    2053              :             END DO
    2054              : 
    2055           82 :             IF (output_unit > 0) THEN
    2056              :                WRITE (UNIT=output_unit, FMT="(/,T15,A,/)") &
    2057           41 :                   " ----- ELF is computed on the real space grid -----"
    2058              :             END IF
    2059           82 :             rho_cutoff = section_get_rval(elf_section, "density_cutoff")
    2060           82 :             CALL qs_elf_calc(qs_env, elf_r, rho_cutoff)
    2061           82 :             CALL get_effective_core_charges(qs_env, zcharge)
    2062              : 
    2063              :             ! write ELF into cube file
    2064              : 
    2065              :             ! For openPMD, refer to access modes instead of APPEND key
    2066           82 :             IF (elf_section_key%grid_output == grid_output_cubes) THEN
    2067           82 :                append_cube = section_get_lval(elf_section, "APPEND")
    2068              :             END IF
    2069           82 :             my_pos_cube = "REWIND"
    2070           82 :             IF (append_cube) THEN
    2071            0 :                my_pos_cube = "APPEND"
    2072              :             END IF
    2073              : 
    2074          166 :             DO ispin = 1, dft_control%nspins
    2075           84 :                WRITE (filename, '(a5,I1.1)') "ELF_S", ispin
    2076           84 :                WRITE (title, *) "ELF spin ", ispin
    2077           84 :                mpi_io = .TRUE.
    2078              :                unit_nr = elf_section_key%print_key_unit_nr( &
    2079              :                          logger, &
    2080              :                          input, &
    2081              :                          elf_section_key%absolute_section_key, &
    2082              :                          extension=".cube", &
    2083              :                          middle_name=TRIM(filename), &
    2084              :                          file_position=my_pos_cube, &
    2085              :                          log_filename=.FALSE., &
    2086              :                          mpi_io=mpi_io, &
    2087              :                          fout=mpi_filename, &
    2088              :                          openpmd_basename="dft-elf", &
    2089              :                          openpmd_unit_dimension=openpmd_unit_dimension_dimensionless, &
    2090              :                          openpmd_unit_si=openpmd_unit_si_dimensionless, &
    2091           84 :                          sim_time=qs_env%sim_time)
    2092           84 :                IF (output_unit > 0) THEN
    2093           42 :                   IF (.NOT. mpi_io) THEN
    2094            0 :                      INQUIRE (UNIT=unit_nr, NAME=filename)
    2095              :                   ELSE
    2096           42 :                      filename = mpi_filename
    2097              :                   END IF
    2098              :                   WRITE (UNIT=output_unit, FMT="(/,T2,A,/,/,T2,A)") &
    2099           42 :                      "ELF is written in "//elf_section_key%format_name//" file format to the file:", &
    2100           84 :                      TRIM(filename)
    2101              :                END IF
    2102              : 
    2103              :                CALL elf_section_key%write_pw(elf_r(ispin), unit_nr, title, particles=particles, zeff=zcharge, &
    2104           84 :                                              stride=section_get_ivals(elf_section, "STRIDE"), mpi_io=mpi_io)
    2105              :                CALL elf_section_key%print_key_finished_output( &
    2106              :                   unit_nr, &
    2107              :                   logger, &
    2108              :                   input, &
    2109              :                   elf_section_key%absolute_section_key, &
    2110           84 :                   mpi_io=mpi_io)
    2111              : 
    2112          166 :                CALL auxbas_pw_pool%give_back_pw(elf_r(ispin))
    2113              :             END DO
    2114              : 
    2115              :             ! deallocate
    2116           82 :             DEALLOCATE (elf_r, zcharge)
    2117              : 
    2118              :          ELSE
    2119              :             ! not implemented
    2120            0 :             CPWARN("ELF not implemented for GAPW calculations!")
    2121              :          END IF
    2122              : 
    2123              :       END IF ! print key
    2124              : 
    2125        12887 :       CALL timestop(handle)
    2126              : 
    2127        25774 :    END SUBROUTINE qs_scf_post_elf
    2128              : 
    2129              : ! **************************************************************************************************
    2130              : !> \brief computes the condition number of the overlap matrix and
    2131              : !>      prints the value of the total energy. This is needed
    2132              : !>      for BASIS_MOLOPT optimizations
    2133              : !> \param input ...
    2134              : !> \param logger ...
    2135              : !> \param qs_env the qs_env in which the qs_env lives
    2136              : !> \par History
    2137              : !>      2007-07 Created [Joost VandeVondele]
    2138              : ! **************************************************************************************************
    2139        12887 :    SUBROUTINE qs_scf_post_molopt(input, logger, qs_env)
    2140              :       TYPE(section_vals_type), POINTER                   :: input
    2141              :       TYPE(cp_logger_type), POINTER                      :: logger
    2142              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2143              : 
    2144              :       CHARACTER(len=*), PARAMETER :: routineN = 'qs_scf_post_molopt'
    2145              : 
    2146              :       INTEGER                                            :: handle, nao, unit_nr
    2147              :       REAL(KIND=dp)                                      :: S_cond_number
    2148        12887 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eigenvalues
    2149              :       TYPE(cp_fm_struct_type), POINTER                   :: ao_ao_fmstruct
    2150              :       TYPE(cp_fm_type)                                   :: fm_s, fm_work
    2151              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    2152        12887 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
    2153        12887 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    2154              :       TYPE(qs_energy_type), POINTER                      :: energy
    2155              :       TYPE(section_vals_type), POINTER                   :: print_key
    2156              : 
    2157        12887 :       CALL timeset(routineN, handle)
    2158              : 
    2159              :       print_key => section_vals_get_subs_vals(section_vals=input, &
    2160        12887 :                                               subsection_name="DFT%PRINT%BASIS_MOLOPT_QUANTITIES")
    2161        12887 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), &
    2162              :                 cp_p_file)) THEN
    2163              : 
    2164           28 :          CALL get_qs_env(qs_env, energy=energy, matrix_s=matrix_s, mos=mos)
    2165              : 
    2166              :          ! set up the two needed full matrices, using mo_coeff as a template
    2167           28 :          CALL get_mo_set(mo_set=mos(1), mo_coeff=mo_coeff, nao=nao)
    2168              :          CALL cp_fm_struct_create(fmstruct=ao_ao_fmstruct, &
    2169              :                                   nrow_global=nao, ncol_global=nao, &
    2170           28 :                                   template_fmstruct=mo_coeff%matrix_struct)
    2171              :          CALL cp_fm_create(fm_s, matrix_struct=ao_ao_fmstruct, &
    2172           28 :                            name="fm_s")
    2173              :          CALL cp_fm_create(fm_work, matrix_struct=ao_ao_fmstruct, &
    2174           28 :                            name="fm_work")
    2175           28 :          CALL cp_fm_struct_release(ao_ao_fmstruct)
    2176           84 :          ALLOCATE (eigenvalues(nao))
    2177              : 
    2178           28 :          CALL copy_dbcsr_to_fm(matrix_s(1)%matrix, fm_s)
    2179           28 :          CALL choose_eigv_solver(fm_s, fm_work, eigenvalues)
    2180              : 
    2181           28 :          CALL cp_fm_release(fm_s)
    2182           28 :          CALL cp_fm_release(fm_work)
    2183              : 
    2184          992 :          S_cond_number = MAXVAL(ABS(eigenvalues))/MAX(MINVAL(ABS(eigenvalues)), EPSILON(0.0_dp))
    2185              : 
    2186              :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%BASIS_MOLOPT_QUANTITIES", &
    2187           28 :                                         extension=".molopt")
    2188              : 
    2189           28 :          IF (unit_nr > 0) THEN
    2190              :             ! please keep this format fixed, needs to be grepable for molopt
    2191              :             ! optimizations
    2192           14 :             WRITE (unit_nr, '(T2,A28,2A25)') "", "Tot. Ener.", "S Cond. Numb."
    2193           14 :             WRITE (unit_nr, '(T2,A28,2E25.17)') "BASIS_MOLOPT_QUANTITIES", energy%total, S_cond_number
    2194              :          END IF
    2195              : 
    2196              :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
    2197           84 :                                            "DFT%PRINT%BASIS_MOLOPT_QUANTITIES")
    2198              : 
    2199              :       END IF
    2200              : 
    2201        12887 :       CALL timestop(handle)
    2202              : 
    2203        25774 :    END SUBROUTINE qs_scf_post_molopt
    2204              : 
    2205              : ! **************************************************************************************************
    2206              : !> \brief Dumps EPR
    2207              : !> \param input ...
    2208              : !> \param logger ...
    2209              : !> \param qs_env the qs_env in which the qs_env lives
    2210              : ! **************************************************************************************************
    2211        12887 :    SUBROUTINE qs_scf_post_epr(input, logger, qs_env)
    2212              :       TYPE(section_vals_type), POINTER                   :: input
    2213              :       TYPE(cp_logger_type), POINTER                      :: logger
    2214              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2215              : 
    2216              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'qs_scf_post_epr'
    2217              : 
    2218              :       INTEGER                                            :: handle
    2219              :       TYPE(section_vals_type), POINTER                   :: print_key
    2220              : 
    2221        12887 :       CALL timeset(routineN, handle)
    2222              : 
    2223              :       print_key => section_vals_get_subs_vals(section_vals=input, &
    2224        12887 :                                               subsection_name="DFT%PRINT%HYPERFINE_COUPLING_TENSOR")
    2225        12887 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), &
    2226              :                 cp_p_file)) THEN
    2227           30 :          CALL qs_epr_hyp_calc(qs_env=qs_env)
    2228              :       END IF
    2229              : 
    2230        12887 :       CALL timestop(handle)
    2231              : 
    2232        12887 :    END SUBROUTINE qs_scf_post_epr
    2233              : 
    2234              : ! **************************************************************************************************
    2235              : !> \brief Interface routine to trigger writing of results available from normal
    2236              : !>        SCF. Can write MO-dependent and MO free results (needed for call from
    2237              : !>        the linear scaling code)
    2238              : !> \param qs_env the qs_env in which the qs_env lives
    2239              : !> \param scf_env ...
    2240              : ! **************************************************************************************************
    2241        12887 :    SUBROUTINE write_available_results(qs_env, scf_env)
    2242              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2243              :       TYPE(qs_scf_env_type), OPTIONAL, POINTER           :: scf_env
    2244              : 
    2245              :       CHARACTER(len=*), PARAMETER :: routineN = 'write_available_results'
    2246              : 
    2247              :       INTEGER                                            :: handle
    2248              : 
    2249        12887 :       CALL timeset(routineN, handle)
    2250              : 
    2251              :       ! those properties that require MOs (not suitable density matrix based methods)
    2252        12887 :       CALL write_mo_dependent_results(qs_env, scf_env)
    2253              : 
    2254              :       ! those that depend only on the density matrix, they should be linear scaling in their implementation
    2255        12887 :       CALL write_mo_free_results(qs_env)
    2256              : 
    2257        12887 :       CALL timestop(handle)
    2258              : 
    2259        12887 :    END SUBROUTINE write_available_results
    2260              : 
    2261              : ! **************************************************************************************************
    2262              : !> \brief Write QS results available if MO's are present (if switched on through the print_keys)
    2263              : !>        Writes only MO dependent results. Split is necessary as ls_scf does not
    2264              : !>        provide MO's
    2265              : !> \param qs_env the qs_env in which the qs_env lives
    2266              : !> \param scf_env ...
    2267              : ! **************************************************************************************************
    2268        13235 :    SUBROUTINE write_mo_dependent_results(qs_env, scf_env)
    2269              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2270              :       TYPE(qs_scf_env_type), OPTIONAL, POINTER           :: scf_env
    2271              : 
    2272              :       CHARACTER(len=*), PARAMETER :: routineN = 'write_mo_dependent_results'
    2273              : 
    2274              :       INTEGER                                            :: handle, homo, ispin, nlumo_dos, &
    2275              :                                                             nlumo_molden, nlumo_required, nlumos, &
    2276              :                                                             nmo, output_unit
    2277              :       LOGICAL                                            :: all_equal, defer_molden, do_curve, &
    2278              :                                                             do_dos, do_kpoints, do_pdos, &
    2279              :                                                             do_projected_dos, explicit
    2280              :       REAL(KIND=dp)                                      :: maxocc, s_square, s_square_ideal, &
    2281              :                                                             total_abs_spin_dens, total_spin_dens
    2282        13235 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mo_eigenvalues, occupation_numbers
    2283              :       TYPE(admm_type), POINTER                           :: admm_env
    2284        13235 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    2285              :       TYPE(cell_type), POINTER                           :: cell
    2286        13235 :       TYPE(cp_1d_r_p_type), DIMENSION(:), POINTER        :: unoccupied_evals
    2287        13235 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: unoccupied_orbs
    2288              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    2289              :       TYPE(cp_logger_type), POINTER                      :: logger
    2290        13235 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: ks_rmpv, matrix_s
    2291              :       TYPE(dbcsr_type), POINTER                          :: mo_coeff_deriv
    2292              :       TYPE(dft_control_type), POINTER                    :: dft_control
    2293        13235 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    2294        13235 :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
    2295              :       TYPE(particle_list_type), POINTER                  :: particles
    2296        13235 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    2297              :       TYPE(pw_env_type), POINTER                         :: pw_env
    2298        13235 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
    2299              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    2300              :       TYPE(pw_r3d_rs_type)                               :: wf_r
    2301        13235 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r
    2302              :       TYPE(qs_charges_type), POINTER                     :: qs_charges
    2303              :       TYPE(qs_energy_type), POINTER                      :: energy
    2304        13235 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    2305              :       TYPE(qs_rho_type), POINTER                         :: rho
    2306              :       TYPE(qs_subsys_type), POINTER                      :: subsys
    2307              :       TYPE(scf_control_type), POINTER                    :: scf_control
    2308              :       TYPE(section_vals_type), POINTER                   :: casino_section, dft_section, &
    2309              :                                                             dos_section, input, sprint_section, &
    2310              :                                                             trexio_section
    2311              : 
    2312              : ! TYPE(kpoint_type), POINTER                         :: kpoints
    2313              : 
    2314        13235 :       CALL timeset(routineN, handle)
    2315              : 
    2316        13235 :       NULLIFY (cell, dft_control, pw_env, auxbas_pw_pool, pw_pools, mo_coeff, &
    2317        13235 :                mo_coeff_deriv, mo_eigenvalues, mos, atomic_kind_set, qs_kind_set, &
    2318        13235 :                particle_set, rho, ks_rmpv, matrix_s, scf_control, dft_section, &
    2319        13235 :                molecule_set, input, particles, subsys, rho_r, unoccupied_orbs, &
    2320        13235 :                unoccupied_evals, casino_section, dos_section)
    2321              : 
    2322        13235 :       logger => cp_get_default_logger()
    2323        13235 :       output_unit = cp_logger_get_default_io_unit(logger)
    2324              : 
    2325        13235 :       CPASSERT(ASSOCIATED(qs_env))
    2326              :       CALL get_qs_env(qs_env, &
    2327              :                       dft_control=dft_control, &
    2328              :                       molecule_set=molecule_set, &
    2329              :                       atomic_kind_set=atomic_kind_set, &
    2330              :                       particle_set=particle_set, &
    2331              :                       qs_kind_set=qs_kind_set, &
    2332              :                       admm_env=admm_env, &
    2333              :                       scf_control=scf_control, &
    2334              :                       input=input, &
    2335              :                       cell=cell, &
    2336        13235 :                       subsys=subsys)
    2337        13235 :       CALL qs_subsys_get(subsys, particles=particles)
    2338        13235 :       CALL get_qs_env(qs_env, rho=rho)
    2339        13235 :       CALL qs_rho_get(rho, rho_r=rho_r)
    2340              : 
    2341              :       ! k points
    2342        13235 :       CALL get_qs_env(qs_env, do_kpoints=do_kpoints)
    2343              : 
    2344              :       ! Write last MO information to output file if requested
    2345        13235 :       dft_section => section_vals_get_subs_vals(input, "DFT")
    2346        13235 :       IF (.NOT. qs_env%run_rtp) THEN
    2347        12887 :          CALL qs_scf_write_mos(qs_env, scf_env, final_mos=.TRUE.)
    2348        12887 :          trexio_section => section_vals_get_subs_vals(dft_section, "PRINT%TREXIO")
    2349        12887 :          CALL section_vals_get(trexio_section, explicit=explicit)
    2350        12887 :          IF (explicit) THEN
    2351           10 :             CALL write_trexio(qs_env, trexio_section)
    2352              :          END IF
    2353        12887 :          casino_section => section_vals_get_subs_vals(dft_section, "PRINT%CASINO")
    2354        12887 :          CALL section_vals_get(casino_section, explicit=explicit)
    2355        12887 :          IF (explicit) THEN
    2356           12 :             CALL write_casino(qs_env, casino_section)
    2357              :          END IF
    2358        12887 :          sprint_section => section_vals_get_subs_vals(dft_section, "PRINT%MO_MOLDEN")
    2359        12887 :          defer_molden = .FALSE.
    2360        12887 :          IF (.NOT. do_kpoints) THEN
    2361        11803 :             CALL get_qs_env(qs_env, mos=mos, matrix_ks=ks_rmpv)
    2362        11803 :             CALL write_dm_binary_restart(mos, dft_section, ks_rmpv)
    2363              :             ! Check if molden write should be deferred for OT unoccupied orbitals
    2364        11803 :             CALL section_vals_val_get(sprint_section, "NLUMO", i_val=nlumo_molden)
    2365        11803 :             IF (nlumo_molden /= 0 .AND. PRESENT(scf_env)) THEN
    2366            0 :                IF (scf_env%method == ot_method_nr) defer_molden = .TRUE.
    2367              :             END IF
    2368              :             IF (.NOT. defer_molden) THEN
    2369              :                CALL write_mos_molden(mos, qs_kind_set, particle_set, sprint_section, cell=cell, &
    2370        11803 :                                      qs_env=qs_env, calc_energies=.TRUE.)
    2371              :             END IF
    2372              :             ! Write Chargemol .wfx
    2373        11803 :             IF (BTEST(cp_print_key_should_output(logger%iter_info, dft_section, "PRINT%CHARGEMOL"), &
    2374              :                       cp_p_file)) THEN
    2375            6 :                CALL write_wfx(qs_env, dft_section)
    2376              :             END IF
    2377              :          ELSE
    2378         1084 :             IF (BTEST(cp_print_key_should_output(logger%iter_info, sprint_section, ""), cp_p_file)) THEN
    2379            0 :                CPWARN("Molden format output is not possible for k-point calculations.")
    2380              :             END IF
    2381         1084 :             IF (BTEST(cp_print_key_should_output(logger%iter_info, dft_section, "PRINT%CHARGEMOL"), &
    2382              :                       cp_p_file)) THEN
    2383            0 :                CPWARN("Chargemol .wfx format output is not possible for k-point calculations.")
    2384              :             END IF
    2385              :          END IF
    2386              : 
    2387              :          ! K-point MO wavefunction dump
    2388        12887 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, dft_section, "PRINT%MO_KP"), &
    2389              :                    cp_p_file)) THEN
    2390            0 :             IF (do_kpoints) THEN
    2391              :                CALL write_kpoint_mo_data(qs_env, &
    2392            0 :                                          section_vals_get_subs_vals(input, "DFT%PRINT%MO_KP"))
    2393              :             ELSE
    2394            0 :                CPWARN("MO_KP is only available for k-point calculations, ignored for Gamma-only")
    2395              :             END IF
    2396              :          END IF
    2397              : 
    2398        12887 :          dos_section => section_vals_get_subs_vals(dft_section, "PRINT%DOS")
    2399        12887 :          do_dos = BTEST(cp_print_key_should_output(logger%iter_info, dos_section), cp_p_file)
    2400        12887 :          CALL get_dos_pdos_flags(dos_section, do_dos, do_projected_dos, do_pdos, do_curve)
    2401              : 
    2402              :          ! For OT calculations, collect the largest request for additional unoccupied
    2403              :          ! orbitals among DOS, PDOS, and Molden, and generate them only once.
    2404        12887 :          nlumo_required = 0
    2405        12887 :          IF (.NOT. do_kpoints .AND. PRESENT(scf_env)) THEN
    2406        11803 :             IF (scf_env%method == ot_method_nr) THEN
    2407         4469 :                IF (do_dos) THEN
    2408            8 :                   CALL section_vals_val_get(dft_section, "PRINT%DOS%NLUMO", i_val=nlumo_dos)
    2409            8 :                   IF (nlumo_dos == -1) THEN
    2410            0 :                      nlumo_required = -1
    2411              :                   ELSE IF (nlumo_required /= -1) THEN
    2412            8 :                      nlumo_required = MAX(nlumo_required, nlumo_dos)
    2413              :                   END IF
    2414              :                END IF
    2415              : 
    2416         4469 :                IF (defer_molden) THEN
    2417            0 :                   IF (nlumo_molden == -1) THEN
    2418            0 :                      nlumo_required = -1
    2419            0 :                   ELSE IF (nlumo_required /= -1) THEN
    2420            0 :                      nlumo_required = MAX(nlumo_required, nlumo_molden)
    2421              :                   END IF
    2422              :                END IF
    2423         4469 :                IF (nlumo_required /= 0) THEN
    2424            8 :                   ALLOCATE (unoccupied_orbs(dft_control%nspins))
    2425            8 :                   ALLOCATE (unoccupied_evals(dft_control%nspins))
    2426              :                   CALL make_lumo_gpw(qs_env, scf_env, unoccupied_orbs, unoccupied_evals, &
    2427            2 :                                      nlumo_required, nlumos)
    2428              :                END IF
    2429              : 
    2430         4469 :                IF (do_dos .OR. do_projected_dos) THEN
    2431           16 :                   DO ispin = 1, dft_control%nspins
    2432              :                      ! With ADMM, temporarily modify the Kohn-Sham matrix while updating the
    2433              :                      ! eigenvalues and rotating the occupied OT subspace.
    2434            8 :                      IF (dft_control%do_admm) THEN
    2435            0 :                         CALL admm_correct_for_eigenvalues(ispin, admm_env, ks_rmpv(ispin)%matrix)
    2436              :                      END IF
    2437              :                      CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, &
    2438            8 :                                      eigenvalues=mo_eigenvalues)
    2439            8 :                      IF (ASSOCIATED(qs_env%mo_derivs)) THEN
    2440            8 :                         mo_coeff_deriv => qs_env%mo_derivs(ispin)%matrix
    2441              :                      ELSE
    2442            0 :                         mo_coeff_deriv => NULL()
    2443              :                      END IF
    2444              :                      CALL calculate_subspace_eigenvalues(mo_coeff, ks_rmpv(ispin)%matrix, mo_eigenvalues, &
    2445              :                                                          do_rotation=.TRUE., &
    2446            8 :                                                          co_rotate_dbcsr=mo_coeff_deriv)
    2447            8 :                      CALL set_mo_occupation(mo_set=mos(ispin))
    2448         4477 :                      IF (dft_control%do_admm) THEN
    2449            0 :                         CALL admm_uncorrect_for_eigenvalues(ispin, admm_env, ks_rmpv(ispin)%matrix)
    2450              :                      END IF
    2451              :                   END DO
    2452              :                END IF
    2453              :             END IF
    2454              :          END IF
    2455              : 
    2456        12887 :          IF (defer_molden) THEN
    2457            0 :             IF (ASSOCIATED(unoccupied_orbs)) THEN
    2458            0 :                IF (output_unit > 0) THEN
    2459              :                   WRITE (output_unit, '(/,T2,A,I6,A)') &
    2460            0 :                      "MO_MOLDEN| Writing ", nlumos, " unoccupied orbitals to molden file"
    2461              :                END IF
    2462              :                CALL write_mos_molden(mos, qs_kind_set, particle_set, sprint_section, cell=cell, &
    2463              :                                      unoccupied_orbs=unoccupied_orbs, &
    2464              :                                      unoccupied_evals=unoccupied_evals, &
    2465            0 :                                      qs_env=qs_env, calc_energies=.TRUE.)
    2466              :             END IF
    2467              :          END IF
    2468              : 
    2469              :          ! DOS printout after the SCF cycle is completed
    2470        12887 :          IF (do_dos) THEN
    2471           64 :             IF (do_kpoints) THEN
    2472            4 :                CALL calculate_dos_kp(qs_env, dft_section)
    2473            4 :                IF (do_curve) CALL calculate_dos_kp(qs_env, dft_section, write_curve_output=.TRUE.)
    2474              :             ELSE
    2475           60 :                CALL get_qs_env(qs_env, mos=mos)
    2476           60 :                IF (ASSOCIATED(unoccupied_evals)) THEN
    2477              :                   CALL calculate_dos(mos, dft_section, unoccupied_evals=unoccupied_evals, &
    2478            2 :                                      smearing_enabled=dft_control%smear)
    2479            2 :                   IF (do_curve) CALL calculate_dos(mos, dft_section, unoccupied_evals=unoccupied_evals, &
    2480            0 :                                                    smearing_enabled=dft_control%smear, write_curve_output=.TRUE.)
    2481              :                ELSE
    2482           58 :                   CALL calculate_dos(mos, dft_section, smearing_enabled=dft_control%smear)
    2483           58 :                   IF (do_curve) CALL calculate_dos(mos, dft_section, smearing_enabled=dft_control%smear, &
    2484            0 :                                                    write_curve_output=.TRUE.)
    2485              :                END IF
    2486              :             END IF
    2487              :          END IF
    2488              : 
    2489              :          ! Print projected density-of-states outputs
    2490        12887 :          IF (do_projected_dos) THEN
    2491           22 :             IF (do_kpoints) THEN
    2492              :                CALL calculate_projected_dos_kp(qs_env, dft_section, pdos_print_key="PRINT%DOS", &
    2493            2 :                                                write_pdos=do_pdos, write_pdos_curve=do_curve)
    2494              :             ELSE
    2495              :                CALL get_qs_env(qs_env, &
    2496              :                                mos=mos, &
    2497           20 :                                matrix_ks=ks_rmpv)
    2498           40 :                DO ispin = 1, dft_control%nspins
    2499           40 :                   IF (dft_control%nspins == 2) THEN
    2500            0 :                      IF (ASSOCIATED(unoccupied_orbs)) THEN
    2501              :                         CALL calculate_projected_dos(mos(ispin), atomic_kind_set, &
    2502              :                                                      qs_kind_set, particle_set, qs_env, dft_section, ispin=ispin, &
    2503              :                                                      unoccupied_orbs=unoccupied_orbs(ispin), &
    2504              :                                                      unoccupied_evals=unoccupied_evals(ispin), &
    2505            0 :                                                      pdos_print_key="PRINT%DOS", write_pdos=do_pdos, write_pdos_curve=do_curve)
    2506              :                      ELSE
    2507              :                         CALL calculate_projected_dos(mos(ispin), atomic_kind_set, &
    2508              :                                                      qs_kind_set, particle_set, qs_env, dft_section, ispin=ispin, &
    2509            0 :                                                      pdos_print_key="PRINT%DOS", write_pdos=do_pdos, write_pdos_curve=do_curve)
    2510              :                      END IF
    2511              :                   ELSE
    2512           20 :                      IF (ASSOCIATED(unoccupied_orbs)) THEN
    2513              :                         CALL calculate_projected_dos(mos(ispin), atomic_kind_set, &
    2514              :                                                      qs_kind_set, particle_set, qs_env, dft_section, &
    2515              :                                                      unoccupied_orbs=unoccupied_orbs(ispin), &
    2516              :                                                      unoccupied_evals=unoccupied_evals(ispin), &
    2517            2 :                                                      pdos_print_key="PRINT%DOS", write_pdos=do_pdos, write_pdos_curve=do_curve)
    2518              :                      ELSE
    2519              :                         CALL calculate_projected_dos(mos(ispin), atomic_kind_set, &
    2520              :                                                      qs_kind_set, particle_set, qs_env, dft_section, &
    2521           18 :                                                      pdos_print_key="PRINT%DOS", write_pdos=do_pdos, write_pdos_curve=do_curve)
    2522              :                      END IF
    2523              :                   END IF
    2524              :                END DO
    2525              :             END IF
    2526              :          END IF
    2527        12887 :          IF (ASSOCIATED(unoccupied_orbs)) THEN
    2528            4 :             DO ispin = 1, dft_control%nspins
    2529            2 :                DEALLOCATE (unoccupied_evals(ispin)%array)
    2530            4 :                CALL cp_fm_release(unoccupied_orbs(ispin))
    2531              :             END DO
    2532            2 :             DEALLOCATE (unoccupied_evals)
    2533            2 :             DEALLOCATE (unoccupied_orbs)
    2534              :          END IF
    2535              :       END IF
    2536              : 
    2537              :       ! Integrated absolute spin density and spin contamination ***
    2538        13235 :       IF (dft_control%nspins == 2) THEN
    2539         2688 :          total_spin_dens = 0.0_dp
    2540         2688 :          total_abs_spin_dens = 0.0_dp
    2541         2688 :          IF (dft_control%qs_control%gapw) THEN
    2542          406 :             CALL get_qs_env(qs_env, qs_charges=qs_charges)
    2543              :             total_spin_dens = qs_charges%total_rho_hard_spin - &
    2544          406 :                               qs_charges%total_rho_soft_spin
    2545              :             total_abs_spin_dens = qs_charges%total_rho_hard_abs_spin - &
    2546          406 :                                   qs_charges%total_rho_soft_abs_spin
    2547              :          END IF
    2548         2688 :          CALL get_qs_env(qs_env, mos=mos)
    2549         2688 :          CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
    2550              :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
    2551         2688 :                          pw_pools=pw_pools)
    2552         2688 :          CALL auxbas_pw_pool%create_pw(wf_r)
    2553         2688 :          CALL pw_copy(rho_r(1), wf_r)
    2554         2688 :          CALL pw_axpy(rho_r(2), wf_r, alpha=-1._dp)
    2555         2688 :          total_spin_dens = total_spin_dens + pw_integrate_function(wf_r)
    2556         2688 :          IF (output_unit > 0) WRITE (UNIT=output_unit, FMT='(/,(T3,A,T61,F20.10))') &
    2557         1369 :             "Integrated spin density: ", total_spin_dens
    2558         2688 :          total_abs_spin_dens = total_abs_spin_dens + pw_integrate_function(wf_r, oprt="ABS")
    2559         2688 :          IF (output_unit > 0) WRITE (UNIT=output_unit, FMT='((T3,A,T61,F20.10))') &
    2560         1369 :             "Integrated absolute spin density: ", total_abs_spin_dens
    2561         2688 :          CALL auxbas_pw_pool%give_back_pw(wf_r)
    2562              :          !
    2563              :          ! XXX Fix Me XXX
    2564              :          ! should be extended to the case where added MOs are present
    2565              :          ! should be extended to the k-point case
    2566              :          !
    2567         2688 :          IF (.NOT. do_kpoints) THEN
    2568         2466 :             all_equal = .TRUE.
    2569         7398 :             DO ispin = 1, dft_control%nspins
    2570              :                CALL get_mo_set(mo_set=mos(ispin), &
    2571              :                                occupation_numbers=occupation_numbers, &
    2572              :                                homo=homo, &
    2573              :                                nmo=nmo, &
    2574         4932 :                                maxocc=maxocc)
    2575         7398 :                IF (nmo > 0) THEN
    2576              :                   all_equal = all_equal .AND. &
    2577              :                               (ALL(occupation_numbers(1:homo) == maxocc) .AND. &
    2578        26500 :                                ALL(occupation_numbers(homo + 1:nmo) == 0.0_dp))
    2579              :                END IF
    2580              :             END DO
    2581         2466 :             IF (all_equal) THEN
    2582              :                CALL get_qs_env(qs_env=qs_env, &
    2583              :                                matrix_s=matrix_s, &
    2584         2342 :                                energy=energy)
    2585              :                CALL compute_s_square(mos=mos, matrix_s=matrix_s, s_square=s_square, &
    2586         2342 :                                      s_square_ideal=s_square_ideal)
    2587         2342 :                IF (output_unit > 0) WRITE (UNIT=output_unit, FMT='(T3,A,T51,2F15.6)') &
    2588         1196 :                   "Ideal and single determinant S**2 : ", s_square_ideal, s_square
    2589         2342 :                energy%s_square = s_square
    2590              :             END IF
    2591              :          END IF
    2592              :       END IF
    2593              : 
    2594        13235 :       CALL timestop(handle)
    2595              : 
    2596        13235 :    END SUBROUTINE write_mo_dependent_results
    2597              : 
    2598              : ! **************************************************************************************************
    2599              : !> \brief Write QS results always available (if switched on through the print_keys)
    2600              : !>        Can be called from ls_scf
    2601              : !> \param qs_env the qs_env in which the qs_env lives
    2602              : ! **************************************************************************************************
    2603        14147 :    SUBROUTINE write_mo_free_results(qs_env)
    2604              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2605              : 
    2606              :       CHARACTER(len=*), PARAMETER :: routineN = 'write_mo_free_results'
    2607              :       CHARACTER(len=1), DIMENSION(3), PARAMETER          :: cdir = ["x", "y", "z"]
    2608              : 
    2609              :       CHARACTER(LEN=2)                                   :: element_symbol
    2610              :       CHARACTER(LEN=default_path_length)                 :: filename, mpi_filename, my_pos_cube, &
    2611              :                                                             my_pos_voro
    2612              :       CHARACTER(LEN=default_string_length)               :: name, print_density
    2613              :       INTEGER :: after, handle, i, iat, id, ikind, img, iso, ispin, iw, l, n_rep_hf, natom, nd(3), &
    2614              :          ngto, niso, nkind, np, nr, output_unit, print_level, should_print_bqb, should_print_voro, &
    2615              :          unit_nr, unit_nr_voro
    2616              :       LOGICAL :: append_cube, append_voro, do_hfx, do_kpoints, mpi_io, omit_headers, print_it, &
    2617              :          rho_r_valid, voro_print_txt, write_ks, write_xc, xrd_interface
    2618              :       REAL(KIND=dp)                                      :: norm_factor, q_max, rho_hard, rho_soft, &
    2619              :                                                             rho_total, rho_total_rspace, udvol, &
    2620              :                                                             volume
    2621        14147 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: zcharge
    2622        14147 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: bfun
    2623        14147 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: aedens, ccdens, ppdens
    2624              :       REAL(KIND=dp), DIMENSION(3)                        :: checksum_hr, dr
    2625        14147 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: my_Q0
    2626        14147 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    2627              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
    2628              :       TYPE(cell_type), POINTER                           :: cell
    2629              :       TYPE(cp_logger_type), POINTER                      :: logger
    2630              :       TYPE(cp_section_key)                               :: e_density_section
    2631        14147 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_hr
    2632        14147 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: ks_rmpv, matrix_s, matrix_vxc, rho_ao
    2633              :       TYPE(dft_control_type), POINTER                    :: dft_control
    2634              :       TYPE(grid_atom_type), POINTER                      :: grid_atom
    2635              :       TYPE(iao_env_type)                                 :: iao_env
    2636              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2637              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    2638        14147 :          POINTER                                         :: sab_orb, sap_ppnl
    2639              :       TYPE(particle_list_type), POINTER                  :: particles
    2640        14147 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    2641              :       TYPE(pw_c1d_gs_type)                               :: aux_g, rho_elec_gspace
    2642              :       TYPE(pw_c1d_gs_type), POINTER                      :: rho0_s_gs, rho_core, rhoz_cneo_s_gs
    2643              :       TYPE(pw_env_type), POINTER                         :: pw_env
    2644        14147 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
    2645              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    2646              :       TYPE(pw_r3d_rs_type)                               :: aux_r, rho_elec_rspace, wf_r
    2647        14147 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r
    2648              :       TYPE(pw_r3d_rs_type), POINTER                      :: mb_rho, v_hartree_rspace, vee
    2649        14147 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    2650              :       TYPE(qs_kind_type), POINTER                        :: qs_kind
    2651              :       TYPE(qs_rho_type), POINTER                         :: rho
    2652              :       TYPE(qs_subsys_type), POINTER                      :: subsys
    2653              :       TYPE(rho0_mpole_type), POINTER                     :: rho0_mpole
    2654        14147 :       TYPE(rho_atom_type), DIMENSION(:), POINTER         :: rho_atom_set
    2655              :       TYPE(rho_atom_type), POINTER                       :: rho_atom
    2656              :       TYPE(section_vals_type), POINTER                   :: dft_section, hfx_section, input, &
    2657              :                                                             print_key, print_key_bqb, &
    2658              :                                                             print_key_voro, xc_section
    2659              : 
    2660        14147 :       CALL timeset(routineN, handle)
    2661        14147 :       NULLIFY (cell, dft_control, pw_env, auxbas_pw_pool, pw_pools, hfx_section, &
    2662        14147 :                atomic_kind_set, qs_kind_set, particle_set, rho, ks_rmpv, rho_ao, rho_r, &
    2663        14147 :                dft_section, xc_section, input, particles, subsys, matrix_vxc, v_hartree_rspace, &
    2664        14147 :                vee, matrix_hr, matrix_s, sab_orb, sap_ppnl)
    2665              : 
    2666        14147 :       logger => cp_get_default_logger()
    2667        14147 :       output_unit = cp_logger_get_default_io_unit(logger)
    2668              : 
    2669        14147 :       CPASSERT(ASSOCIATED(qs_env))
    2670              :       CALL get_qs_env(qs_env, &
    2671              :                       atomic_kind_set=atomic_kind_set, &
    2672              :                       qs_kind_set=qs_kind_set, &
    2673              :                       nkind=nkind, &
    2674              :                       natom=natom, &
    2675              :                       particle_set=particle_set, &
    2676              :                       cell=cell, &
    2677              :                       para_env=para_env, &
    2678              :                       dft_control=dft_control, &
    2679              :                       input=input, &
    2680              :                       do_kpoints=do_kpoints, &
    2681              :                       subsys=subsys, &
    2682              :                       matrix_s_kp=matrix_s, &
    2683              :                       sab_orb=sab_orb, &
    2684        14147 :                       sap_ppnl=sap_ppnl)
    2685        14147 :       dft_section => section_vals_get_subs_vals(input, "DFT")
    2686        14147 :       CALL qs_subsys_get(subsys, particles=particles)
    2687              : 
    2688        14147 :       CALL get_qs_env(qs_env, rho=rho)
    2689        14147 :       CALL qs_rho_get(rho, rho_r=rho_r)
    2690              : 
    2691        14147 :       CALL get_effective_core_charges(qs_env, zcharge)
    2692              : 
    2693              :       ! Print the total density (electronic + core charge)
    2694        14147 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    2695              :                                            "DFT%PRINT%TOT_DENSITY_CUBE"), cp_p_file)) THEN
    2696           82 :          NULLIFY (rho_core, rho0_s_gs, rhoz_cneo_s_gs)
    2697           82 :          append_cube = section_get_lval(input, "DFT%PRINT%TOT_DENSITY_CUBE%APPEND")
    2698           82 :          my_pos_cube = "REWIND"
    2699           82 :          IF (append_cube) THEN
    2700            0 :             my_pos_cube = "APPEND"
    2701              :          END IF
    2702              : 
    2703              :          CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, rho_core=rho_core, &
    2704           82 :                          rho0_s_gs=rho0_s_gs, rhoz_cneo_s_gs=rhoz_cneo_s_gs)
    2705              :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
    2706           82 :                          pw_pools=pw_pools)
    2707           82 :          CALL auxbas_pw_pool%create_pw(wf_r)
    2708           82 :          IF (dft_control%qs_control%gapw) THEN
    2709            0 :             IF (dft_control%qs_control%gapw_control%nopaw_as_gpw) THEN
    2710            0 :                CALL pw_axpy(rho_core, rho0_s_gs)
    2711            0 :                IF (ASSOCIATED(rhoz_cneo_s_gs)) THEN
    2712            0 :                   CALL pw_axpy(rhoz_cneo_s_gs, rho0_s_gs)
    2713              :                END IF
    2714            0 :                CALL pw_transfer(rho0_s_gs, wf_r)
    2715            0 :                CALL pw_axpy(rho_core, rho0_s_gs, -1.0_dp)
    2716            0 :                IF (ASSOCIATED(rhoz_cneo_s_gs)) THEN
    2717            0 :                   CALL pw_axpy(rhoz_cneo_s_gs, rho0_s_gs, -1.0_dp)
    2718              :                END IF
    2719              :             ELSE
    2720            0 :                IF (ASSOCIATED(rhoz_cneo_s_gs)) THEN
    2721            0 :                   CALL pw_axpy(rhoz_cneo_s_gs, rho0_s_gs)
    2722              :                END IF
    2723            0 :                CALL pw_transfer(rho0_s_gs, wf_r)
    2724            0 :                IF (ASSOCIATED(rhoz_cneo_s_gs)) THEN
    2725            0 :                   CALL pw_axpy(rhoz_cneo_s_gs, rho0_s_gs, -1.0_dp)
    2726              :                END IF
    2727              :             END IF
    2728              :          ELSE
    2729           82 :             CALL pw_transfer(rho_core, wf_r)
    2730              :          END IF
    2731          164 :          DO ispin = 1, dft_control%nspins
    2732          164 :             CALL pw_axpy(rho_r(ispin), wf_r)
    2733              :          END DO
    2734           82 :          filename = "TOTAL_DENSITY"
    2735           82 :          mpi_io = .TRUE.
    2736              :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%TOT_DENSITY_CUBE", &
    2737              :                                         extension=".cube", middle_name=TRIM(filename), file_position=my_pos_cube, &
    2738           82 :                                         log_filename=.FALSE., mpi_io=mpi_io)
    2739              :          CALL cp_pw_to_cube(wf_r, unit_nr, "TOTAL DENSITY", &
    2740              :                             particles=particles, zeff=zcharge, &
    2741              :                             stride=section_get_ivals(dft_section, "PRINT%TOT_DENSITY_CUBE%STRIDE"), &
    2742              :                             max_file_size_mb=section_get_rval(dft_section, "PRINT%TOT_DENSITY_CUBE%MAX_FILE_SIZE_MB"), &
    2743           82 :                             mpi_io=mpi_io)
    2744              :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
    2745           82 :                                            "DFT%PRINT%TOT_DENSITY_CUBE", mpi_io=mpi_io)
    2746           82 :          CALL auxbas_pw_pool%give_back_pw(wf_r)
    2747              :       END IF
    2748              : 
    2749        14147 :       e_density_section = cube_or_openpmd(input, str_e_density_cubes, str_e_density_openpmd, logger)
    2750              : 
    2751              :       ! Write cube file with electron density
    2752        14147 :       IF (e_density_section%do_output) THEN
    2753              :          CALL section_vals_val_get(dft_section, &
    2754              :                                    keyword_name=e_density_section%concat_to_relative("%DENSITY_INCLUDE"), &
    2755          154 :                                    c_val=print_density)
    2756              :          print_density = TRIM(print_density)
    2757              :          ! For openPMD, refer to access modes instead of APPEND key
    2758          154 :          IF (e_density_section%grid_output == grid_output_cubes) THEN
    2759          154 :             append_cube = section_get_lval(input, e_density_section%concat_to_absolute("%APPEND"))
    2760              :          END IF
    2761          154 :          my_pos_cube = "REWIND"
    2762          154 :          IF (append_cube) THEN
    2763            0 :             my_pos_cube = "APPEND"
    2764              :          END IF
    2765              :          ! Write the info on core densities for the interface between cp2k and the XRD code
    2766              :          ! together with the valence density they are used to compute the form factor (Fourier transform)
    2767          154 :          IF (e_density_section%grid_output == grid_output_cubes) THEN
    2768          154 :             xrd_interface = section_get_lval(input, e_density_section%concat_to_absolute("%XRD_INTERFACE"))
    2769              :          ELSE
    2770              :             ! Unimplemented for openPMD, since this does not use the regular routines
    2771              :             xrd_interface = .FALSE.
    2772              :          END IF
    2773              : 
    2774          154 :          IF (xrd_interface) THEN
    2775              :             !cube file only contains soft density (GAPW)
    2776            2 :             IF (dft_control%qs_control%gapw) print_density = "SOFT_DENSITY"
    2777              : 
    2778            2 :             filename = "ELECTRON_DENSITY"
    2779              :             unit_nr = cp_print_key_unit_nr(logger, input, e_density_section%absolute_section_key, &
    2780              :                                            extension=".xrd", middle_name=TRIM(filename), &
    2781            2 :                                            file_position=my_pos_cube, log_filename=.FALSE.)
    2782            2 :             ngto = section_get_ival(input, e_density_section%concat_to_absolute("%NGAUSS"))
    2783            2 :             IF (output_unit > 0) THEN
    2784            1 :                INQUIRE (UNIT=unit_nr, NAME=filename)
    2785              :                WRITE (UNIT=output_unit, FMT="(/,T2,A,/,/,T2,A)") &
    2786            1 :                   "The electron density (atomic part) is written to the file:", &
    2787            2 :                   TRIM(filename)
    2788              :             END IF
    2789              : 
    2790            2 :             xc_section => section_vals_get_subs_vals(input, "DFT%XC")
    2791            2 :             nkind = SIZE(atomic_kind_set)
    2792            2 :             IF (unit_nr > 0) THEN
    2793            1 :                WRITE (unit_nr, *) "Atomic (core) densities"
    2794            1 :                WRITE (unit_nr, *) "Unit cell"
    2795            1 :                WRITE (unit_nr, FMT="(3F20.12)") cell%hmat(1, 1), cell%hmat(1, 2), cell%hmat(1, 3)
    2796            1 :                WRITE (unit_nr, FMT="(3F20.12)") cell%hmat(2, 1), cell%hmat(2, 2), cell%hmat(2, 3)
    2797            1 :                WRITE (unit_nr, FMT="(3F20.12)") cell%hmat(3, 1), cell%hmat(3, 2), cell%hmat(3, 3)
    2798            1 :                WRITE (unit_nr, *) "Atomic types"
    2799            1 :                WRITE (unit_nr, *) nkind
    2800              :             END IF
    2801              :             ! calculate atomic density and core density
    2802           16 :             ALLOCATE (ppdens(ngto, 2, nkind), aedens(ngto, 2, nkind), ccdens(ngto, 2, nkind))
    2803            6 :             DO ikind = 1, nkind
    2804            4 :                atomic_kind => atomic_kind_set(ikind)
    2805            4 :                qs_kind => qs_kind_set(ikind)
    2806            4 :                CALL get_atomic_kind(atomic_kind, name=name, element_symbol=element_symbol)
    2807              :                CALL calculate_atomic_density(ppdens(:, :, ikind), atomic_kind, qs_kind, ngto, &
    2808            4 :                                              iunit=output_unit, confine=.TRUE.)
    2809              :                CALL calculate_atomic_density(aedens(:, :, ikind), atomic_kind, qs_kind, ngto, &
    2810            4 :                                              iunit=output_unit, allelectron=.TRUE., confine=.TRUE.)
    2811           52 :                ccdens(:, 1, ikind) = aedens(:, 1, ikind)
    2812           52 :                ccdens(:, 2, ikind) = 0._dp
    2813              :                CALL project_function_a(ccdens(1:ngto, 2, ikind), ccdens(1:ngto, 1, ikind), &
    2814            4 :                                        ppdens(1:ngto, 2, ikind), ppdens(1:ngto, 1, ikind), 0)
    2815           52 :                ccdens(:, 2, ikind) = aedens(:, 2, ikind) - ccdens(:, 2, ikind)
    2816            4 :                IF (unit_nr > 0) THEN
    2817            2 :                   WRITE (unit_nr, FMT="(I6,A10,A20)") ikind, TRIM(element_symbol), TRIM(name)
    2818            2 :                   WRITE (unit_nr, FMT="(I6)") ngto
    2819            2 :                   WRITE (unit_nr, *) "   Total density"
    2820           26 :                   WRITE (unit_nr, FMT="(2G24.12)") (aedens(i, 1, ikind), aedens(i, 2, ikind), i=1, ngto)
    2821            2 :                   WRITE (unit_nr, *) "    Core density"
    2822           26 :                   WRITE (unit_nr, FMT="(2G24.12)") (ccdens(i, 1, ikind), ccdens(i, 2, ikind), i=1, ngto)
    2823              :                END IF
    2824            6 :                NULLIFY (atomic_kind)
    2825              :             END DO
    2826              : 
    2827            2 :             IF (dft_control%qs_control%gapw) THEN
    2828            2 :                CALL get_qs_env(qs_env=qs_env, rho_atom_set=rho_atom_set)
    2829              : 
    2830            2 :                IF (unit_nr > 0) THEN
    2831            1 :                   WRITE (unit_nr, *) "Coordinates and GAPW density"
    2832              :                END IF
    2833            2 :                np = particles%n_els
    2834            6 :                DO iat = 1, np
    2835            4 :                   CALL get_atomic_kind(particles%els(iat)%atomic_kind, kind_number=ikind)
    2836            4 :                   CALL get_qs_kind(qs_kind_set(ikind), grid_atom=grid_atom)
    2837            4 :                   rho_atom => rho_atom_set(iat)
    2838            4 :                   IF (ASSOCIATED(rho_atom%rho_rad_h(1)%r_coef)) THEN
    2839            2 :                      nr = SIZE(rho_atom%rho_rad_h(1)%r_coef, 1)
    2840            2 :                      niso = SIZE(rho_atom%rho_rad_h(1)%r_coef, 2)
    2841              :                   ELSE
    2842            2 :                      nr = 0
    2843            2 :                      niso = 0
    2844              :                   END IF
    2845            4 :                   CALL para_env%sum(nr)
    2846            4 :                   CALL para_env%sum(niso)
    2847              : 
    2848           16 :                   ALLOCATE (bfun(nr, niso))
    2849            4 :                   bfun = 0._dp
    2850            8 :                   DO ispin = 1, dft_control%nspins
    2851            8 :                      IF (ASSOCIATED(rho_atom%rho_rad_h(1)%r_coef)) THEN
    2852          920 :                         bfun(:, :) = bfun + rho_atom%rho_rad_h(ispin)%r_coef - rho_atom%rho_rad_s(ispin)%r_coef
    2853              :                      END IF
    2854              :                   END DO
    2855            4 :                   CALL para_env%sum(bfun)
    2856           52 :                   ccdens(:, 1, ikind) = ppdens(:, 1, ikind)
    2857           52 :                   ccdens(:, 2, ikind) = 0._dp
    2858            4 :                   IF (unit_nr > 0) THEN
    2859            8 :                      WRITE (unit_nr, '(I10,I5,3f12.6)') iat, ikind, particles%els(iat)%r
    2860              :                   END IF
    2861           40 :                   DO iso = 1, niso
    2862           36 :                      l = indso(1, iso)
    2863           36 :                      CALL project_function_b(ccdens(:, 2, ikind), ccdens(:, 1, ikind), bfun(:, iso), grid_atom, l)
    2864           40 :                      IF (unit_nr > 0) THEN
    2865           18 :                         WRITE (unit_nr, FMT="(3I6)") iso, l, ngto
    2866          234 :                         WRITE (unit_nr, FMT="(2G24.12)") (ccdens(i, 1, ikind), ccdens(i, 2, ikind), i=1, ngto)
    2867              :                      END IF
    2868              :                   END DO
    2869           10 :                   DEALLOCATE (bfun)
    2870              :                END DO
    2871              :             ELSE
    2872            0 :                IF (unit_nr > 0) THEN
    2873            0 :                   WRITE (unit_nr, *) "Coordinates"
    2874            0 :                   np = particles%n_els
    2875            0 :                   DO iat = 1, np
    2876            0 :                      CALL get_atomic_kind(particles%els(iat)%atomic_kind, kind_number=ikind)
    2877            0 :                      WRITE (unit_nr, '(I10,I5,3f12.6)') iat, ikind, particles%els(iat)%r
    2878              :                   END DO
    2879              :                END IF
    2880              :             END IF
    2881              : 
    2882            2 :             DEALLOCATE (ppdens, aedens, ccdens)
    2883              : 
    2884              :             CALL cp_print_key_finished_output(unit_nr, logger, input, &
    2885            2 :                                               e_density_section%absolute_section_key)
    2886              : 
    2887              :          END IF
    2888          154 :          IF (dft_control%qs_control%gapw .AND. print_density == "TOTAL_DENSITY") THEN
    2889              :             ! total density in g-space not implemented for k-points
    2890            8 :             CPASSERT(.NOT. do_kpoints)
    2891              :             ! Print total electronic density
    2892              :             CALL get_qs_env(qs_env=qs_env, &
    2893            8 :                             pw_env=pw_env)
    2894              :             CALL pw_env_get(pw_env=pw_env, &
    2895              :                             auxbas_pw_pool=auxbas_pw_pool, &
    2896            8 :                             pw_pools=pw_pools)
    2897            8 :             CALL auxbas_pw_pool%create_pw(pw=rho_elec_rspace)
    2898            8 :             CALL pw_zero(rho_elec_rspace)
    2899            8 :             CALL auxbas_pw_pool%create_pw(pw=rho_elec_gspace)
    2900            8 :             CALL pw_zero(rho_elec_gspace)
    2901              :             CALL get_pw_grid_info(pw_grid=rho_elec_gspace%pw_grid, &
    2902              :                                   dr=dr, &
    2903            8 :                                   vol=volume)
    2904           32 :             q_max = SQRT(SUM((pi/dr(:))**2))
    2905              :             CALL calculate_rhotot_elec_gspace(qs_env=qs_env, &
    2906              :                                               auxbas_pw_pool=auxbas_pw_pool, &
    2907              :                                               rhotot_elec_gspace=rho_elec_gspace, &
    2908              :                                               q_max=q_max, &
    2909              :                                               rho_hard=rho_hard, &
    2910            8 :                                               rho_soft=rho_soft)
    2911            8 :             rho_total = rho_hard + rho_soft
    2912              :             CALL get_pw_grid_info(pw_grid=rho_elec_gspace%pw_grid, &
    2913            8 :                                   vol=volume)
    2914              :             ! rhotot pw coefficients are by default scaled by grid volume
    2915              :             ! need to undo this to get proper charge from printed cube
    2916            8 :             CALL pw_scale(rho_elec_gspace, 1.0_dp/volume)
    2917              : 
    2918            8 :             CALL pw_transfer(rho_elec_gspace, rho_elec_rspace)
    2919            8 :             rho_total_rspace = pw_integrate_function(rho_elec_rspace, isign=-1)
    2920            8 :             filename = "TOTAL_ELECTRON_DENSITY"
    2921            8 :             mpi_io = .TRUE.
    2922              :             unit_nr = e_density_section%print_key_unit_nr( &
    2923              :                       logger, &
    2924              :                       input, &
    2925              :                       e_density_section%absolute_section_key, &
    2926              :                       extension=".cube", &
    2927              :                       middle_name=TRIM(filename), &
    2928              :                       file_position=my_pos_cube, &
    2929              :                       log_filename=.FALSE., &
    2930              :                       mpi_io=mpi_io, &
    2931              :                       fout=mpi_filename, &
    2932              :                       openpmd_basename="dft-total-electron-density", &
    2933              :                       openpmd_unit_dimension=openpmd_unit_dimension_density, &
    2934              :                       openpmd_unit_si=openpmd_unit_si_density, &
    2935            8 :                       sim_time=qs_env%sim_time)
    2936            8 :             IF (output_unit > 0) THEN
    2937            4 :                IF (.NOT. mpi_io) THEN
    2938            0 :                   INQUIRE (UNIT=unit_nr, NAME=filename)
    2939              :                ELSE
    2940            4 :                   filename = mpi_filename
    2941              :                END IF
    2942              :                CALL print_density_output_message(output_unit, "The total electron density", &
    2943            4 :                                                  e_density_section, filename)
    2944              :                WRITE (UNIT=output_unit, FMT="(/,(T2,A,F20.10))") &
    2945            4 :                   "q(max) [1/Angstrom]              :", q_max/angstrom, &
    2946            4 :                   "Soft electronic charge (G-space) :", rho_soft, &
    2947            4 :                   "Hard electronic charge (G-space) :", rho_hard, &
    2948            4 :                   "Total electronic charge (G-space):", rho_total, &
    2949            8 :                   "Total electronic charge (R-space):", rho_total_rspace
    2950              :             END IF
    2951              :             CALL e_density_section%write_pw(rho_elec_rspace, unit_nr, "TOTAL ELECTRON DENSITY", &
    2952              :                                             particles=particles, zeff=zcharge, &
    2953            8 :                               stride=section_get_ivals(dft_section, e_density_section%concat_to_relative("%STRIDE")), mpi_io=mpi_io)
    2954              :             CALL e_density_section%print_key_finished_output(unit_nr, logger, input, &
    2955            8 :                                                              e_density_section%absolute_section_key, mpi_io=mpi_io)
    2956              :             ! Print total spin density for spin-polarized systems
    2957            8 :             IF (dft_control%nspins > 1) THEN
    2958            6 :                CALL pw_zero(rho_elec_gspace)
    2959            6 :                CALL pw_zero(rho_elec_rspace)
    2960              :                CALL calculate_rhotot_elec_gspace(qs_env=qs_env, &
    2961              :                                                  auxbas_pw_pool=auxbas_pw_pool, &
    2962              :                                                  rhotot_elec_gspace=rho_elec_gspace, &
    2963              :                                                  q_max=q_max, &
    2964              :                                                  rho_hard=rho_hard, &
    2965              :                                                  rho_soft=rho_soft, &
    2966            6 :                                                  fsign=-1.0_dp)
    2967            6 :                rho_total = rho_hard + rho_soft
    2968              : 
    2969              :                ! rhotot pw coefficients are by default scaled by grid volume
    2970              :                ! need to undo this to get proper charge from printed cube
    2971            6 :                CALL pw_scale(rho_elec_gspace, 1.0_dp/volume)
    2972              : 
    2973            6 :                CALL pw_transfer(rho_elec_gspace, rho_elec_rspace)
    2974            6 :                rho_total_rspace = pw_integrate_function(rho_elec_rspace, isign=-1)
    2975            6 :                filename = "TOTAL_SPIN_DENSITY"
    2976            6 :                mpi_io = .TRUE.
    2977              :                unit_nr = e_density_section%print_key_unit_nr( &
    2978              :                          logger, &
    2979              :                          input, &
    2980              :                          e_density_section%absolute_section_key, &
    2981              :                          extension=".cube", &
    2982              :                          middle_name=TRIM(filename), &
    2983              :                          file_position=my_pos_cube, &
    2984              :                          log_filename=.FALSE., &
    2985              :                          mpi_io=mpi_io, &
    2986              :                          fout=mpi_filename, &
    2987              :                          openpmd_basename="dft-total-spin-density", &
    2988              :                          openpmd_unit_dimension=openpmd_unit_dimension_density, &
    2989              :                          openpmd_unit_si=openpmd_unit_si_density, &
    2990            6 :                          sim_time=qs_env%sim_time)
    2991            6 :                IF (output_unit > 0) THEN
    2992            3 :                   IF (.NOT. mpi_io .AND. e_density_section%grid_output == grid_output_cubes) THEN
    2993            0 :                      INQUIRE (UNIT=unit_nr, NAME=filename)
    2994              :                   ELSE
    2995            3 :                      filename = mpi_filename
    2996              :                   END IF
    2997              :                   CALL print_density_output_message(output_unit, "The total spin density", &
    2998            3 :                                                     e_density_section, filename)
    2999              :                   WRITE (UNIT=output_unit, FMT="(/,(T2,A,F20.10))") &
    3000            3 :                      "q(max) [1/Angstrom]                    :", q_max/angstrom, &
    3001            3 :                      "Soft part of the spin density (G-space):", rho_soft, &
    3002            3 :                      "Hard part of the spin density (G-space):", rho_hard, &
    3003            3 :                      "Total spin density (G-space)           :", rho_total, &
    3004            6 :                      "Total spin density (R-space)           :", rho_total_rspace
    3005              :                END IF
    3006              :                CALL e_density_section%write_pw(rho_elec_rspace, unit_nr, "TOTAL SPIN DENSITY", &
    3007              :                                                particles=particles, zeff=zcharge, &
    3008            6 :                               stride=section_get_ivals(dft_section, e_density_section%concat_to_relative("%STRIDE")), mpi_io=mpi_io)
    3009              :                CALL e_density_section%print_key_finished_output(unit_nr, logger, input, &
    3010            6 :                                                                 e_density_section%absolute_section_key, mpi_io=mpi_io)
    3011              :             END IF
    3012            8 :             CALL auxbas_pw_pool%give_back_pw(rho_elec_gspace)
    3013            8 :             CALL auxbas_pw_pool%give_back_pw(rho_elec_rspace)
    3014              : 
    3015          146 :          ELSE IF (print_density == "SOFT_DENSITY" .OR. .NOT. dft_control%qs_control%gapw) THEN
    3016          142 :             IF (dft_control%nspins > 1) THEN
    3017              :                CALL get_qs_env(qs_env=qs_env, &
    3018           48 :                                pw_env=pw_env)
    3019              :                CALL pw_env_get(pw_env=pw_env, &
    3020              :                                auxbas_pw_pool=auxbas_pw_pool, &
    3021           48 :                                pw_pools=pw_pools)
    3022           48 :                CALL auxbas_pw_pool%create_pw(pw=rho_elec_rspace)
    3023           48 :                CALL pw_copy(rho_r(1), rho_elec_rspace)
    3024           48 :                CALL pw_axpy(rho_r(2), rho_elec_rspace)
    3025           48 :                filename = "ELECTRON_DENSITY"
    3026           48 :                mpi_io = .TRUE.
    3027              :                unit_nr = e_density_section%print_key_unit_nr( &
    3028              :                          logger, &
    3029              :                          input, &
    3030              :                          e_density_section%absolute_section_key, &
    3031              :                          extension=".cube", &
    3032              :                          middle_name=TRIM(filename), &
    3033              :                          file_position=my_pos_cube, &
    3034              :                          log_filename=.FALSE., &
    3035              :                          mpi_io=mpi_io, &
    3036              :                          fout=mpi_filename, &
    3037              :                          openpmd_basename="dft-electron-density", &
    3038              :                          openpmd_unit_dimension=openpmd_unit_dimension_density, &
    3039              :                          openpmd_unit_si=openpmd_unit_si_density, &
    3040           48 :                          sim_time=qs_env%sim_time)
    3041           48 :                IF (output_unit > 0) THEN
    3042           24 :                   IF (.NOT. mpi_io .AND. e_density_section%grid_output == grid_output_cubes) THEN
    3043            0 :                      INQUIRE (UNIT=unit_nr, NAME=filename)
    3044              :                   ELSE
    3045           24 :                      filename = mpi_filename
    3046              :                   END IF
    3047              :                   CALL print_density_output_message(output_unit, "The sum of alpha and beta density", &
    3048           24 :                                                     e_density_section, filename)
    3049              :                END IF
    3050              :                CALL e_density_section%write_pw(rho_elec_rspace, unit_nr, "SUM OF ALPHA AND BETA DENSITY", &
    3051              :         particles=particles, zeff=zcharge, stride=section_get_ivals(dft_section, e_density_section%concat_to_relative("%STRIDE")), &
    3052           48 :                                                mpi_io=mpi_io)
    3053              :                CALL e_density_section%print_key_finished_output(unit_nr, logger, input, &
    3054           48 :                                                                 e_density_section%absolute_section_key, mpi_io=mpi_io)
    3055           48 :                CALL pw_copy(rho_r(1), rho_elec_rspace)
    3056           48 :                CALL pw_axpy(rho_r(2), rho_elec_rspace, alpha=-1.0_dp)
    3057           48 :                filename = "SPIN_DENSITY"
    3058           48 :                mpi_io = .TRUE.
    3059              :                unit_nr = e_density_section%print_key_unit_nr( &
    3060              :                          logger, &
    3061              :                          input, &
    3062              :                          e_density_section%absolute_section_key, &
    3063              :                          extension=".cube", &
    3064              :                          middle_name=TRIM(filename), &
    3065              :                          file_position=my_pos_cube, &
    3066              :                          log_filename=.FALSE., &
    3067              :                          mpi_io=mpi_io, &
    3068              :                          fout=mpi_filename, &
    3069              :                          openpmd_basename="dft-spin-density", &
    3070              :                          openpmd_unit_dimension=openpmd_unit_dimension_density, &
    3071              :                          openpmd_unit_si=openpmd_unit_si_density, &
    3072           48 :                          sim_time=qs_env%sim_time)
    3073           48 :                IF (output_unit > 0) THEN
    3074           24 :                   IF (.NOT. mpi_io .AND. e_density_section%grid_output == grid_output_cubes) THEN
    3075            0 :                      INQUIRE (UNIT=unit_nr, NAME=filename)
    3076              :                   ELSE
    3077           24 :                      filename = mpi_filename
    3078              :                   END IF
    3079              :                   CALL print_density_output_message(output_unit, "The spin density", &
    3080           24 :                                                     e_density_section, filename)
    3081              :                END IF
    3082              :                CALL e_density_section%write_pw(rho_elec_rspace, unit_nr, "SPIN DENSITY", &
    3083              :                                                particles=particles, zeff=zcharge, &
    3084           48 :                               stride=section_get_ivals(dft_section, e_density_section%concat_to_relative("%STRIDE")), mpi_io=mpi_io)
    3085              :                CALL e_density_section%print_key_finished_output(unit_nr, logger, input, &
    3086           48 :                                                                 e_density_section%absolute_section_key, mpi_io=mpi_io)
    3087           48 :                CALL auxbas_pw_pool%give_back_pw(rho_elec_rspace)
    3088              :             ELSE
    3089           94 :                filename = "ELECTRON_DENSITY"
    3090           94 :                mpi_io = .TRUE.
    3091              :                unit_nr = e_density_section%print_key_unit_nr( &
    3092              :                          logger, &
    3093              :                          input, &
    3094              :                          e_density_section%absolute_section_key, &
    3095              :                          extension=".cube", &
    3096              :                          middle_name=TRIM(filename), &
    3097              :                          file_position=my_pos_cube, &
    3098              :                          log_filename=.FALSE., &
    3099              :                          mpi_io=mpi_io, &
    3100              :                          fout=mpi_filename, &
    3101              :                          openpmd_basename="dft-electron-density", &
    3102              :                          openpmd_unit_dimension=openpmd_unit_dimension_density, &
    3103              :                          openpmd_unit_si=openpmd_unit_si_density, &
    3104           94 :                          sim_time=qs_env%sim_time)
    3105           94 :                IF (output_unit > 0) THEN
    3106           47 :                   IF (.NOT. mpi_io .AND. e_density_section%grid_output == grid_output_cubes) THEN
    3107            0 :                      INQUIRE (UNIT=unit_nr, NAME=filename)
    3108              :                   ELSE
    3109           47 :                      filename = mpi_filename
    3110              :                   END IF
    3111              :                   CALL print_density_output_message(output_unit, "The electron density", &
    3112           47 :                                                     e_density_section, filename)
    3113              :                END IF
    3114              :                CALL e_density_section%write_pw(rho_r(1), unit_nr, "ELECTRON DENSITY", &
    3115              :                                                particles=particles, zeff=zcharge, &
    3116           94 :                               stride=section_get_ivals(dft_section, e_density_section%concat_to_relative("%STRIDE")), mpi_io=mpi_io)
    3117              :                CALL e_density_section%print_key_finished_output(unit_nr, logger, input, &
    3118           94 :                                                                 e_density_section%absolute_section_key, mpi_io=mpi_io)
    3119              :             END IF ! nspins
    3120              : 
    3121            4 :          ELSE IF (dft_control%qs_control%gapw .AND. print_density == "TOTAL_HARD_APPROX") THEN
    3122            4 :             CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, rho0_mpole=rho0_mpole, natom=natom)
    3123            4 :             CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, pw_pools=pw_pools)
    3124            4 :             CALL auxbas_pw_pool%create_pw(rho_elec_rspace)
    3125              : 
    3126            4 :             NULLIFY (my_Q0)
    3127           12 :             ALLOCATE (my_Q0(natom))
    3128           16 :             my_Q0 = 0.0_dp
    3129              : 
    3130              :             ! (eta/pi)**3: normalization for 3d gaussian of form exp(-eta*r**2)
    3131            4 :             norm_factor = SQRT((rho0_mpole%zet0_h/pi)**3)
    3132              : 
    3133              :             ! store hard part of electronic density in array
    3134           16 :             DO iat = 1, natom
    3135           34 :                my_Q0(iat) = SUM(rho0_mpole%mp_rho(iat)%Q0(1:dft_control%nspins))*norm_factor
    3136              :             END DO
    3137              :             ! multiply coeff with gaussian and put on realspace grid
    3138              :             ! coeff is the gaussian prefactor, eta the gaussian exponent
    3139            4 :             CALL calculate_rho_resp_all(rho_elec_rspace, coeff=my_Q0, natom=natom, eta=rho0_mpole%zet0_h, qs_env=qs_env)
    3140            4 :             rho_hard = pw_integrate_function(rho_elec_rspace, isign=-1)
    3141              : 
    3142            4 :             rho_soft = 0.0_dp
    3143           10 :             DO ispin = 1, dft_control%nspins
    3144            6 :                CALL pw_axpy(rho_r(ispin), rho_elec_rspace)
    3145           10 :                rho_soft = rho_soft + pw_integrate_function(rho_r(ispin), isign=-1)
    3146              :             END DO
    3147              : 
    3148            4 :             rho_total_rspace = rho_soft + rho_hard
    3149              : 
    3150            4 :             filename = "ELECTRON_DENSITY"
    3151            4 :             mpi_io = .TRUE.
    3152              :             unit_nr = e_density_section%print_key_unit_nr( &
    3153              :                       logger, &
    3154              :                       input, &
    3155              :                       e_density_section%absolute_section_key, &
    3156              :                       extension=".cube", &
    3157              :                       middle_name=TRIM(filename), &
    3158              :                       file_position=my_pos_cube, &
    3159              :                       log_filename=.FALSE., &
    3160              :                       mpi_io=mpi_io, &
    3161              :                       fout=mpi_filename, &
    3162              :                       openpmd_basename="dft-electron-density", &
    3163              :                       openpmd_unit_dimension=openpmd_unit_dimension_density, &
    3164              :                       openpmd_unit_si=openpmd_unit_si_density, &
    3165            4 :                       sim_time=qs_env%sim_time)
    3166            4 :             IF (output_unit > 0) THEN
    3167            2 :                IF (.NOT. mpi_io .AND. e_density_section%grid_output == grid_output_cubes) THEN
    3168            0 :                   INQUIRE (UNIT=unit_nr, NAME=filename)
    3169              :                ELSE
    3170            2 :                   filename = mpi_filename
    3171              :                END IF
    3172              :                CALL print_density_output_message(output_unit, "The electron density", &
    3173            2 :                                                  e_density_section, filename)
    3174              :                WRITE (UNIT=output_unit, FMT="(/,(T2,A,F20.10))") &
    3175            2 :                   "Soft electronic charge (R-space) :", rho_soft, &
    3176            2 :                   "Hard electronic charge (R-space) :", rho_hard, &
    3177            4 :                   "Total electronic charge (R-space):", rho_total_rspace
    3178              :             END IF
    3179              :             CALL e_density_section%write_pw(rho_elec_rspace, unit_nr, "ELECTRON DENSITY", &
    3180              :         particles=particles, zeff=zcharge, stride=section_get_ivals(dft_section, e_density_section%concat_to_relative("%STRIDE")), &
    3181            4 :                                             mpi_io=mpi_io)
    3182              :             CALL e_density_section%print_key_finished_output(unit_nr, logger, input, &
    3183            4 :                                                              e_density_section%absolute_section_key, mpi_io=mpi_io)
    3184              : 
    3185              :             !------------
    3186            4 :             IF (dft_control%nspins > 1) THEN
    3187            8 :             DO iat = 1, natom
    3188            8 :                my_Q0(iat) = (rho0_mpole%mp_rho(iat)%Q0(1) - rho0_mpole%mp_rho(iat)%Q0(2))*norm_factor
    3189              :             END DO
    3190            2 :             CALL pw_zero(rho_elec_rspace)
    3191            2 :             CALL calculate_rho_resp_all(rho_elec_rspace, coeff=my_Q0, natom=natom, eta=rho0_mpole%zet0_h, qs_env=qs_env)
    3192            2 :             rho_hard = pw_integrate_function(rho_elec_rspace, isign=-1)
    3193              : 
    3194            2 :             CALL pw_axpy(rho_r(1), rho_elec_rspace)
    3195            2 :             CALL pw_axpy(rho_r(2), rho_elec_rspace, alpha=-1.0_dp)
    3196              :             rho_soft = pw_integrate_function(rho_r(1), isign=-1) &
    3197            2 :                        - pw_integrate_function(rho_r(2), isign=-1)
    3198              : 
    3199            2 :             rho_total_rspace = rho_soft + rho_hard
    3200              : 
    3201            2 :             filename = "SPIN_DENSITY"
    3202            2 :             mpi_io = .TRUE.
    3203              :             unit_nr = e_density_section%print_key_unit_nr( &
    3204              :                       logger, &
    3205              :                       input, &
    3206              :                       e_density_section%absolute_section_key, &
    3207              :                       extension=".cube", &
    3208              :                       middle_name=TRIM(filename), &
    3209              :                       file_position=my_pos_cube, &
    3210              :                       log_filename=.FALSE., &
    3211              :                       mpi_io=mpi_io, &
    3212              :                       fout=mpi_filename, &
    3213              :                       openpmd_basename="dft-spin-density", &
    3214              :                       openpmd_unit_dimension=openpmd_unit_dimension_density, &
    3215              :                       openpmd_unit_si=openpmd_unit_si_density, &
    3216            2 :                       sim_time=qs_env%sim_time)
    3217            2 :             IF (output_unit > 0) THEN
    3218            1 :                IF (.NOT. mpi_io .AND. e_density_section%grid_output == grid_output_cubes) THEN
    3219            0 :                   INQUIRE (UNIT=unit_nr, NAME=filename)
    3220              :                ELSE
    3221            1 :                   filename = mpi_filename
    3222              :                END IF
    3223              :                CALL print_density_output_message(output_unit, "The spin density", &
    3224            1 :                                                  e_density_section, filename)
    3225              :                WRITE (UNIT=output_unit, FMT="(/,(T2,A,F20.10))") &
    3226            1 :                   "Soft part of the spin density          :", rho_soft, &
    3227            1 :                   "Hard part of the spin density          :", rho_hard, &
    3228            2 :                   "Total spin density (R-space)           :", rho_total_rspace
    3229              :             END IF
    3230              :             CALL e_density_section%write_pw(rho_elec_rspace, unit_nr, "SPIN DENSITY", &
    3231              :                                             particles=particles, zeff=zcharge, &
    3232            2 :                               stride=section_get_ivals(dft_section, e_density_section%concat_to_relative("%STRIDE")), mpi_io=mpi_io)
    3233              :             CALL e_density_section%print_key_finished_output(unit_nr, logger, input, &
    3234            2 :                                                              e_density_section%absolute_section_key, mpi_io=mpi_io)
    3235              :             END IF ! nspins
    3236            4 :             CALL auxbas_pw_pool%give_back_pw(rho_elec_rspace)
    3237            4 :             DEALLOCATE (my_Q0)
    3238              :          END IF ! print_density
    3239              :       END IF ! print key
    3240              : 
    3241              :       IF (BTEST(cp_print_key_should_output(logger%iter_info, &
    3242        14147 :                                            dft_section, "PRINT%ENERGY_WINDOWS"), cp_p_file) .AND. .NOT. do_kpoints) THEN
    3243           90 :          CALL energy_windows(qs_env)
    3244              :       END IF
    3245              : 
    3246              :       ! Print the hartree potential
    3247        14147 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3248              :                                            "DFT%PRINT%V_HARTREE_CUBE"), cp_p_file)) THEN
    3249              : 
    3250              :          CALL get_qs_env(qs_env=qs_env, &
    3251              :                          pw_env=pw_env, &
    3252          114 :                          v_hartree_rspace=v_hartree_rspace)
    3253          114 :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    3254          114 :          CALL auxbas_pw_pool%create_pw(aux_r)
    3255              : 
    3256          114 :          append_cube = section_get_lval(input, "DFT%PRINT%V_HARTREE_CUBE%APPEND")
    3257          114 :          my_pos_cube = "REWIND"
    3258          114 :          IF (append_cube) THEN
    3259            0 :             my_pos_cube = "APPEND"
    3260              :          END IF
    3261          114 :          mpi_io = .TRUE.
    3262          114 :          CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
    3263          114 :          CALL pw_env_get(pw_env)
    3264              :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%V_HARTREE_CUBE", &
    3265          114 :                                         extension=".cube", middle_name="v_hartree", file_position=my_pos_cube, mpi_io=mpi_io)
    3266          114 :          udvol = 1.0_dp/v_hartree_rspace%pw_grid%dvol
    3267              : 
    3268          114 :          CALL pw_copy(v_hartree_rspace, aux_r)
    3269          114 :          CALL pw_scale(aux_r, udvol)
    3270              : 
    3271              :          CALL cp_pw_to_cube(aux_r, unit_nr, "HARTREE POTENTIAL", particles=particles, zeff=zcharge, &
    3272              :                             stride=section_get_ivals(dft_section, "PRINT%V_HARTREE_CUBE%STRIDE"), &
    3273              :                             max_file_size_mb=section_get_rval(dft_section, "PRINT%V_HARTREE_CUBE%MAX_FILE_SIZE_MB"), &
    3274          114 :                             mpi_io=mpi_io)
    3275              :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
    3276          114 :                                            "DFT%PRINT%V_HARTREE_CUBE", mpi_io=mpi_io)
    3277              : 
    3278          114 :          CALL auxbas_pw_pool%give_back_pw(aux_r)
    3279              :       END IF
    3280              : 
    3281              :       ! Print the external potential
    3282        14147 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3283              :                                            "DFT%PRINT%EXTERNAL_POTENTIAL_CUBE"), cp_p_file)) THEN
    3284           86 :          IF (dft_control%apply_external_potential) THEN
    3285            4 :             CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, vee=vee)
    3286            4 :             CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    3287            4 :             CALL auxbas_pw_pool%create_pw(aux_r)
    3288              : 
    3289            4 :             append_cube = section_get_lval(input, "DFT%PRINT%EXTERNAL_POTENTIAL_CUBE%APPEND")
    3290            4 :             my_pos_cube = "REWIND"
    3291            4 :             IF (append_cube) THEN
    3292            0 :                my_pos_cube = "APPEND"
    3293              :             END IF
    3294            4 :             mpi_io = .TRUE.
    3295            4 :             CALL pw_env_get(pw_env)
    3296              :             unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%EXTERNAL_POTENTIAL_CUBE", &
    3297            4 :                                            extension=".cube", middle_name="ext_pot", file_position=my_pos_cube, mpi_io=mpi_io)
    3298              : 
    3299            4 :             CALL pw_copy(vee, aux_r)
    3300              : 
    3301              :             CALL cp_pw_to_cube(aux_r, unit_nr, "EXTERNAL POTENTIAL", particles=particles, zeff=zcharge, &
    3302              :                                stride=section_get_ivals(dft_section, "PRINT%EXTERNAL_POTENTIAL_CUBE%STRIDE"), &
    3303              :                                max_file_size_mb=section_get_rval(dft_section, "PRINT%EXTERNAL_POTENTIAL_CUBE%MAX_FILE_SIZE_MB"), &
    3304            4 :                                mpi_io=mpi_io)
    3305              :             CALL cp_print_key_finished_output(unit_nr, logger, input, &
    3306            4 :                                               "DFT%PRINT%EXTERNAL_POTENTIAL_CUBE", mpi_io=mpi_io)
    3307              : 
    3308            4 :             CALL auxbas_pw_pool%give_back_pw(aux_r)
    3309              :          END IF
    3310              :       END IF
    3311              : 
    3312              :       ! Print the Electrical Field Components
    3313        14147 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3314              :                                            "DFT%PRINT%EFIELD_CUBE"), cp_p_file)) THEN
    3315              : 
    3316           82 :          CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
    3317           82 :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    3318           82 :          CALL auxbas_pw_pool%create_pw(aux_r)
    3319           82 :          CALL auxbas_pw_pool%create_pw(aux_g)
    3320              : 
    3321           82 :          append_cube = section_get_lval(input, "DFT%PRINT%EFIELD_CUBE%APPEND")
    3322           82 :          my_pos_cube = "REWIND"
    3323           82 :          IF (append_cube) THEN
    3324            0 :             my_pos_cube = "APPEND"
    3325              :          END IF
    3326              :          CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, &
    3327           82 :                          v_hartree_rspace=v_hartree_rspace)
    3328           82 :          CALL pw_env_get(pw_env)
    3329           82 :          udvol = 1.0_dp/v_hartree_rspace%pw_grid%dvol
    3330          328 :          DO id = 1, 3
    3331          246 :             mpi_io = .TRUE.
    3332              :             unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%EFIELD_CUBE", &
    3333              :                                            extension=".cube", middle_name="efield_"//cdir(id), file_position=my_pos_cube, &
    3334          246 :                                            mpi_io=mpi_io)
    3335              : 
    3336          246 :             CALL pw_transfer(v_hartree_rspace, aux_g)
    3337          246 :             nd = 0
    3338          246 :             nd(id) = 1
    3339          246 :             CALL pw_derive(aux_g, nd)
    3340          246 :             CALL pw_transfer(aux_g, aux_r)
    3341          246 :             CALL pw_scale(aux_r, udvol)
    3342              : 
    3343              :             CALL cp_pw_to_cube(aux_r, unit_nr, "ELECTRIC FIELD", particles=particles, zeff=zcharge, &
    3344              :                                stride=section_get_ivals(dft_section, "PRINT%EFIELD_CUBE%STRIDE"), &
    3345              :                                max_file_size_mb=section_get_rval(dft_section, "PRINT%EFIELD_CUBE%MAX_FILE_SIZE_MB"), &
    3346          246 :                                mpi_io=mpi_io)
    3347              :             CALL cp_print_key_finished_output(unit_nr, logger, input, &
    3348          328 :                                               "DFT%PRINT%EFIELD_CUBE", mpi_io=mpi_io)
    3349              :          END DO
    3350              : 
    3351           82 :          CALL auxbas_pw_pool%give_back_pw(aux_r)
    3352           82 :          CALL auxbas_pw_pool%give_back_pw(aux_g)
    3353              :       END IF
    3354              : 
    3355              :       ! Write cube files from the local energy
    3356        14147 :       CALL qs_scf_post_local_energy(input, logger, qs_env)
    3357              : 
    3358              :       ! Write cube files from the local stress tensor
    3359        14147 :       CALL qs_scf_post_local_stress(input, logger, qs_env)
    3360              : 
    3361              :       ! Write cube files from the implicit Poisson solver
    3362        14147 :       CALL qs_scf_post_ps_implicit(input, logger, qs_env)
    3363              : 
    3364              :       ! post SCF finite-volume Kubo transport
    3365        14147 :       CALL qs_scf_post_kubo_transport(qs_env)
    3366              : 
    3367        14147 :       CALL qs_scf_post_localizer(qs_env)
    3368        14147 :       CALL qs_scf_post_quadratic(qs_env)
    3369              : 
    3370              :       ! post SCF Transport
    3371        14147 :       CALL qs_scf_post_transport(qs_env)
    3372              : 
    3373        14147 :       CALL section_vals_val_get(input, "DFT%PRINT%AO_MATRICES%OMIT_HEADERS", l_val=omit_headers)
    3374              :       ! Write the density matrices
    3375        14147 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3376              :                                            "DFT%PRINT%AO_MATRICES/DENSITY"), cp_p_file)) THEN
    3377              :          iw = cp_print_key_unit_nr(logger, input, "DFT%PRINT%AO_MATRICES/DENSITY", &
    3378            4 :                                    extension=".Log")
    3379            4 :          CALL section_vals_val_get(input, "DFT%PRINT%AO_MATRICES%NDIGITS", i_val=after)
    3380            4 :          CALL qs_rho_get(rho, rho_ao_kp=rho_ao)
    3381            4 :          after = MIN(MAX(after, 1), 16)
    3382            8 :          DO ispin = 1, dft_control%nspins
    3383           12 :             DO img = 1, dft_control%nimages
    3384              :                CALL cp_dbcsr_write_sparse_matrix(rho_ao(ispin, img)%matrix, 4, after, qs_env, &
    3385            8 :                                                  para_env, output_unit=iw, omit_headers=omit_headers)
    3386              :             END DO
    3387              :          END DO
    3388              :          CALL cp_print_key_finished_output(iw, logger, input, &
    3389            4 :                                            "DFT%PRINT%AO_MATRICES/DENSITY")
    3390              :       END IF
    3391              : 
    3392              :       ! Write the Kohn-Sham matrices
    3393              :       write_ks = BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3394        14147 :                                                   "DFT%PRINT%AO_MATRICES/KOHN_SHAM_MATRIX"), cp_p_file)
    3395              :       write_xc = BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3396        14147 :                                                   "DFT%PRINT%AO_MATRICES/MATRIX_VXC"), cp_p_file)
    3397              :       ! we need to update stuff before writing, potentially computing the matrix_vxc
    3398        14147 :       IF (write_ks .OR. write_xc) THEN
    3399           14 :          IF (write_xc) qs_env%requires_matrix_vxc = .TRUE.
    3400           14 :          CALL qs_ks_did_change(qs_env%ks_env, rho_changed=.TRUE.)
    3401              :          CALL qs_ks_update_qs_env(qs_env, calculate_forces=.FALSE., &
    3402           14 :                                   just_energy=.FALSE.)
    3403           14 :          IF (write_xc) qs_env%requires_matrix_vxc = .FALSE.
    3404              :       END IF
    3405              : 
    3406              :       ! Write the Kohn-Sham matrices
    3407        14147 :       IF (write_ks) THEN
    3408              :          iw = cp_print_key_unit_nr(logger, input, "DFT%PRINT%AO_MATRICES/KOHN_SHAM_MATRIX", &
    3409           14 :                                    extension=".Log")
    3410           14 :          CALL get_qs_env(qs_env=qs_env, matrix_ks_kp=ks_rmpv)
    3411           14 :          CALL section_vals_val_get(input, "DFT%PRINT%AO_MATRICES%NDIGITS", i_val=after)
    3412           14 :          after = MIN(MAX(after, 1), 16)
    3413           28 :          DO ispin = 1, dft_control%nspins
    3414           42 :             DO img = 1, dft_control%nimages
    3415              :                CALL cp_dbcsr_write_sparse_matrix(ks_rmpv(ispin, img)%matrix, 4, after, qs_env, &
    3416           28 :                                                  para_env, output_unit=iw, omit_headers=omit_headers)
    3417              :             END DO
    3418              :          END DO
    3419              :          CALL cp_print_key_finished_output(iw, logger, input, &
    3420           14 :                                            "DFT%PRINT%AO_MATRICES/KOHN_SHAM_MATRIX")
    3421              :       END IF
    3422              : 
    3423              :       ! write csr matrices
    3424              :       ! matrices in terms of the PAO basis will be taken care of in pao_post_scf.
    3425        14147 :       IF (.NOT. dft_control%qs_control%pao) THEN
    3426        13735 :          CALL write_ks_matrix_csr(qs_env, input)
    3427        13735 :          CALL write_s_matrix_csr(qs_env, input)
    3428        13735 :          CALL write_hcore_matrix_csr(qs_env, input)
    3429        13735 :          CALL write_p_matrix_csr(qs_env, input)
    3430              :       END IF
    3431              : 
    3432              :       ! write adjacency matrix
    3433        14147 :       CALL write_adjacency_matrix(qs_env, input)
    3434              : 
    3435              :       ! Write the xc matrix
    3436        14147 :       IF (write_xc) THEN
    3437            0 :          CALL get_qs_env(qs_env=qs_env, matrix_vxc_kp=matrix_vxc)
    3438            0 :          CPASSERT(ASSOCIATED(matrix_vxc))
    3439              :          iw = cp_print_key_unit_nr(logger, input, "DFT%PRINT%AO_MATRICES/MATRIX_VXC", &
    3440            0 :                                    extension=".Log")
    3441            0 :          CALL section_vals_val_get(input, "DFT%PRINT%AO_MATRICES%NDIGITS", i_val=after)
    3442            0 :          after = MIN(MAX(after, 1), 16)
    3443            0 :          DO ispin = 1, dft_control%nspins
    3444            0 :             DO img = 1, dft_control%nimages
    3445              :                CALL cp_dbcsr_write_sparse_matrix(matrix_vxc(ispin, img)%matrix, 4, after, qs_env, &
    3446            0 :                                                  para_env, output_unit=iw, omit_headers=omit_headers)
    3447              :             END DO
    3448              :          END DO
    3449              :          CALL cp_print_key_finished_output(iw, logger, input, &
    3450            0 :                                            "DFT%PRINT%AO_MATRICES/MATRIX_VXC")
    3451              :       END IF
    3452              : 
    3453              :       ! Write the [H,r] commutator matrices
    3454        14147 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3455              :                                            "DFT%PRINT%AO_MATRICES/COMMUTATOR_HR"), cp_p_file)) THEN
    3456              :          iw = cp_print_key_unit_nr(logger, input, "DFT%PRINT%AO_MATRICES/COMMUTATOR_HR", &
    3457            2 :                                    extension=".Log")
    3458            2 :          CALL section_vals_val_get(input, "DFT%PRINT%AO_MATRICES%NDIGITS", i_val=after)
    3459            2 :          NULLIFY (matrix_hr)
    3460            2 :          CALL dbcsr_allocate_matrix_set(matrix_hr, 3)
    3461            8 :          DO img = 1, 3
    3462            6 :             ALLOCATE (matrix_hr(img)%matrix)
    3463              :             CALL dbcsr_create(matrix_hr(img)%matrix, template=matrix_s(1, 1)%matrix, &
    3464            6 :                               name="COMMUTATOR", matrix_type=dbcsr_type_antisymmetric)
    3465            6 :             CALL cp_dbcsr_alloc_block_from_nbl(matrix_hr(img)%matrix, sab_orb)
    3466            8 :             CALL dbcsr_set(matrix_hr(img)%matrix, 0._dp)
    3467              :          END DO
    3468              : 
    3469              :          CALL build_com_mom_nl(qs_kind_set, sab_orb, sap_ppnl, dft_control%qs_control%eps_ppnl, &
    3470            2 :                                particle_set, cell, matrix_rv=matrix_hr)
    3471            2 :          CALL build_lin_mom_matrix(qs_env, matrix_hr)
    3472            8 :          DO img = 1, 3
    3473            6 :             CALL dbcsr_scale(matrix_hr(img)%matrix, alpha_scalar=-1._dp)
    3474            8 :             checksum_hr(img) = dbcsr_checksum(matrix_hr(img)%matrix)
    3475              :          END DO
    3476            2 :          IF (output_unit > 0) THEN
    3477            1 :             WRITE (output_unit, '(T2,A,E23.16)') 'COMMUTATOR_HR| CheckSum X =', checksum_hr(1)
    3478            1 :             WRITE (output_unit, '(T2,A,E23.16)') 'COMMUTATOR_HR| CheckSum Y =', checksum_hr(2)
    3479            1 :             WRITE (output_unit, '(T2,A,E23.16)') 'COMMUTATOR_HR| CheckSum Z =', checksum_hr(3)
    3480              :          END IF
    3481            2 :          after = MIN(MAX(after, 1), 16)
    3482            8 :          DO img = 1, 3
    3483              :             CALL cp_dbcsr_write_sparse_matrix(matrix_hr(img)%matrix, 4, after, qs_env, &
    3484            8 :                                               para_env, output_unit=iw, omit_headers=omit_headers)
    3485              :          END DO
    3486            2 :          CALL dbcsr_deallocate_matrix_set(matrix_hr)
    3487              :          CALL cp_print_key_finished_output(iw, logger, input, &
    3488            2 :                                            "DFT%PRINT%AO_MATRICES/COMMUTATOR_HR")
    3489              :       END IF
    3490              : 
    3491              :       ! Compute the Mulliken charges
    3492        14147 :       print_key => section_vals_get_subs_vals(input, "DFT%PRINT%MULLIKEN")
    3493        14147 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    3494         5206 :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%MULLIKEN", extension=".mulliken", log_filename=.FALSE.)
    3495         5206 :          print_level = 1
    3496         5206 :          CALL section_vals_val_get(print_key, "PRINT_GOP", l_val=print_it)
    3497         5206 :          IF (print_it) print_level = 2
    3498         5206 :          CALL section_vals_val_get(print_key, "PRINT_ALL", l_val=print_it)
    3499         5206 :          IF (print_it) print_level = 3
    3500         5206 :          CALL mulliken_population_analysis(qs_env, unit_nr, print_level)
    3501         5206 :          CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%MULLIKEN")
    3502              :       END IF
    3503              : 
    3504              :       ! Compute the Hirshfeld charges
    3505        14147 :       print_key => section_vals_get_subs_vals(input, "DFT%PRINT%HIRSHFELD")
    3506        14147 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    3507              :          ! we check if real space density is available
    3508         5288 :          NULLIFY (rho)
    3509         5288 :          CALL get_qs_env(qs_env=qs_env, rho=rho)
    3510         5288 :          CALL qs_rho_get(rho, rho_r_valid=rho_r_valid)
    3511         5288 :          IF (rho_r_valid) THEN
    3512         5214 :             unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%HIRSHFELD", extension=".hirshfeld", log_filename=.FALSE.)
    3513         5214 :             CALL hirshfeld_charges(qs_env, print_key, unit_nr)
    3514         5214 :             CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%HIRSHFELD")
    3515              :          END IF
    3516              :       END IF
    3517              : 
    3518              :       ! Compute EEQ charges
    3519        14147 :       print_key => section_vals_get_subs_vals(input, "DFT%PRINT%EEQ_CHARGES")
    3520        14147 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    3521           30 :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%EEQ_CHARGES", extension=".eeq", log_filename=.FALSE.)
    3522           30 :          print_level = 1
    3523           30 :          CALL eeq_print(qs_env, unit_nr, print_level, ext=.FALSE.)
    3524           30 :          CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%MULLIKEN")
    3525              :       END IF
    3526              : 
    3527              :       ! Do a Voronoi Integration or write a compressed BQB File
    3528        14147 :       print_key_voro => section_vals_get_subs_vals(input, "DFT%PRINT%VORONOI")
    3529        14147 :       print_key_bqb => section_vals_get_subs_vals(input, "DFT%PRINT%E_DENSITY_BQB")
    3530        14147 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key_voro), cp_p_file)) THEN
    3531           24 :          should_print_voro = 1
    3532              :       ELSE
    3533        14123 :          should_print_voro = 0
    3534              :       END IF
    3535        14147 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key_bqb), cp_p_file)) THEN
    3536            2 :          should_print_bqb = 1
    3537              :       ELSE
    3538        14145 :          should_print_bqb = 0
    3539              :       END IF
    3540        14147 :       IF ((should_print_voro /= 0) .OR. (should_print_bqb /= 0)) THEN
    3541              : 
    3542              :          ! we check if real space density is available
    3543           26 :          NULLIFY (rho)
    3544           26 :          CALL get_qs_env(qs_env=qs_env, rho=rho)
    3545           26 :          CALL qs_rho_get(rho, rho_r_valid=rho_r_valid)
    3546           26 :          IF (rho_r_valid) THEN
    3547              : 
    3548           26 :             IF (dft_control%nspins > 1) THEN
    3549              :                CALL get_qs_env(qs_env=qs_env, &
    3550            0 :                                pw_env=pw_env)
    3551              :                CALL pw_env_get(pw_env=pw_env, &
    3552              :                                auxbas_pw_pool=auxbas_pw_pool, &
    3553            0 :                                pw_pools=pw_pools)
    3554            0 :                NULLIFY (mb_rho)
    3555            0 :                ALLOCATE (mb_rho)
    3556            0 :                CALL auxbas_pw_pool%create_pw(pw=mb_rho)
    3557            0 :                CALL pw_copy(rho_r(1), mb_rho)
    3558            0 :                CALL pw_axpy(rho_r(2), mb_rho)
    3559              :                !CALL voronoi_analysis(qs_env, rho_elec_rspace, print_key, unit_nr)
    3560              :             ELSE
    3561           26 :                mb_rho => rho_r(1)
    3562              :                !CALL voronoi_analysis( qs_env, rho_r(1), print_key, unit_nr )
    3563              :             END IF ! nspins
    3564              : 
    3565           26 :             IF (should_print_voro /= 0) THEN
    3566           24 :                CALL section_vals_val_get(print_key_voro, "OUTPUT_TEXT", l_val=voro_print_txt)
    3567           24 :                IF (voro_print_txt) THEN
    3568           24 :                   append_voro = section_get_lval(input, "DFT%PRINT%VORONOI%APPEND")
    3569           24 :                   my_pos_voro = "REWIND"
    3570           24 :                   IF (append_voro) THEN
    3571            0 :                      my_pos_voro = "APPEND"
    3572              :                   END IF
    3573              :                   unit_nr_voro = cp_print_key_unit_nr(logger, input, "DFT%PRINT%VORONOI", extension=".voronoi", &
    3574           24 :                                                       file_position=my_pos_voro, log_filename=.FALSE.)
    3575              :                ELSE
    3576            0 :                   unit_nr_voro = 0
    3577              :                END IF
    3578              :             ELSE
    3579            2 :                unit_nr_voro = 0
    3580              :             END IF
    3581              : 
    3582              :             CALL entry_voronoi_or_bqb(should_print_voro, should_print_bqb, print_key_voro, print_key_bqb, &
    3583           26 :                                       unit_nr_voro, qs_env, mb_rho)
    3584              : 
    3585           26 :             IF (dft_control%nspins > 1) THEN
    3586            0 :                CALL auxbas_pw_pool%give_back_pw(mb_rho)
    3587            0 :                DEALLOCATE (mb_rho)
    3588              :             END IF
    3589              : 
    3590           26 :             IF (unit_nr_voro > 0) THEN
    3591           12 :                CALL cp_print_key_finished_output(unit_nr_voro, logger, input, "DFT%PRINT%VORONOI")
    3592              :             END IF
    3593              : 
    3594              :          END IF
    3595              :       END IF
    3596              : 
    3597              :       ! MAO analysis
    3598        14147 :       print_key => section_vals_get_subs_vals(input, "DFT%PRINT%MAO_ANALYSIS")
    3599        14147 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    3600           38 :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%MAO_ANALYSIS", extension=".mao", log_filename=.FALSE.)
    3601           38 :          CALL mao_analysis(qs_env, print_key, unit_nr)
    3602           38 :          CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%MAO_ANALYSIS")
    3603              :       END IF
    3604              : 
    3605              :       ! MINBAS analysis
    3606        14147 :       print_key => section_vals_get_subs_vals(input, "DFT%PRINT%MINBAS_ANALYSIS")
    3607        14147 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    3608           28 :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%MINBAS_ANALYSIS", extension=".mao", log_filename=.FALSE.)
    3609           28 :          CALL minbas_analysis(qs_env, print_key, unit_nr)
    3610           28 :          CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%MINBAS_ANALYSIS")
    3611              :       END IF
    3612              : 
    3613              :       ! IAO analysis
    3614        14147 :       print_key => section_vals_get_subs_vals(input, "DFT%PRINT%IAO_ANALYSIS")
    3615        14147 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    3616           34 :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%IAO_ANALYSIS", extension=".iao", log_filename=.FALSE.)
    3617           34 :          CALL iao_read_input(iao_env, print_key, cell)
    3618           34 :          IF (particle_set(1)%fragment_index /= 0) iao_env%do_fragments = .TRUE.
    3619           34 :          IF (iao_env%do_iao) THEN
    3620            6 :             CALL iao_wfn_analysis(qs_env, iao_env, unit_nr)
    3621              :          END IF
    3622           34 :          CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%IAO_ANALYSIS")
    3623              :       END IF
    3624              : 
    3625              :       ! Energy Decomposition Analysis
    3626        14147 :       print_key => section_vals_get_subs_vals(input, "DFT%PRINT%ENERGY_DECOMPOSITION_ANALYSIS")
    3627        14147 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    3628              :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%ENERGY_DECOMPOSITION_ANALYSIS", &
    3629           58 :                                         extension=".mao", log_filename=.FALSE.)
    3630           58 :          CALL edmf_analysis(qs_env, print_key, unit_nr)
    3631           58 :          CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%ENERGY_DECOMPOSITION_ANALYSIS")
    3632              :       END IF
    3633              : 
    3634              :       ! Print the density in the RI-HFX basis
    3635        14147 :       hfx_section => section_vals_get_subs_vals(input, "DFT%XC%HF")
    3636        14147 :       CALL section_vals_get(hfx_section, explicit=do_hfx)
    3637        14147 :       CALL section_vals_get(hfx_section, n_repetition=n_rep_hf)
    3638        14147 :       IF (do_hfx) THEN
    3639         5354 :          DO i = 1, n_rep_hf
    3640         5354 :             IF (qs_env%x_data(i, 1)%do_hfx_ri) CALL print_ri_hfx(qs_env%x_data(i, 1)%ri_data, qs_env)
    3641              :          END DO
    3642              :       END IF
    3643              : 
    3644        14147 :       DEALLOCATE (zcharge)
    3645              : 
    3646        14147 :       CALL timestop(handle)
    3647              : 
    3648        28294 :    END SUBROUTINE write_mo_free_results
    3649              : 
    3650              : ! **************************************************************************************************
    3651              : !> \brief Calculates Hirshfeld charges
    3652              : !> \param qs_env the qs_env where to calculate the charges
    3653              : !> \param input_section the input section for Hirshfeld charges
    3654              : !> \param unit_nr the output unit number
    3655              : ! **************************************************************************************************
    3656         5214 :    SUBROUTINE hirshfeld_charges(qs_env, input_section, unit_nr)
    3657              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3658              :       TYPE(section_vals_type), POINTER                   :: input_section
    3659              :       INTEGER, INTENT(IN)                                :: unit_nr
    3660              : 
    3661              :       INTEGER                                            :: i, iat, ikind, natom, nkind, nspin, &
    3662              :                                                             radius_type, refc, shapef
    3663         5214 :       INTEGER, DIMENSION(:), POINTER                     :: atom_list
    3664              :       LOGICAL                                            :: do_radius, do_sc, paw_atom
    3665              :       REAL(KIND=dp)                                      :: zeff
    3666         5214 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: radii
    3667         5214 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: charges
    3668         5214 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    3669              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
    3670         5214 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_p, matrix_s
    3671              :       TYPE(dft_control_type), POINTER                    :: dft_control
    3672              :       TYPE(hirshfeld_type), POINTER                      :: hirshfeld_env
    3673              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    3674         5214 :       TYPE(mpole_rho_atom), DIMENSION(:), POINTER        :: mp_rho
    3675         5214 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    3676         5214 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    3677              :       TYPE(qs_rho_type), POINTER                         :: rho
    3678              :       TYPE(rho0_mpole_type), POINTER                     :: rho0_mpole
    3679              : 
    3680         5214 :       NULLIFY (hirshfeld_env)
    3681         5214 :       NULLIFY (radii)
    3682         5214 :       CALL create_hirshfeld_type(hirshfeld_env)
    3683              :       !
    3684         5214 :       CALL get_qs_env(qs_env, nkind=nkind, natom=natom)
    3685        15642 :       ALLOCATE (hirshfeld_env%charges(natom))
    3686              :       ! input options
    3687         5214 :       CALL section_vals_val_get(input_section, "SELF_CONSISTENT", l_val=do_sc)
    3688         5214 :       CALL section_vals_val_get(input_section, "USER_RADIUS", l_val=do_radius)
    3689         5214 :       CALL section_vals_val_get(input_section, "SHAPE_FUNCTION", i_val=shapef)
    3690         5214 :       CALL section_vals_val_get(input_section, "REFERENCE_CHARGE", i_val=refc)
    3691         5214 :       IF (do_radius) THEN
    3692            0 :          radius_type = radius_user
    3693            0 :          CALL section_vals_val_get(input_section, "ATOMIC_RADII", r_vals=radii)
    3694            0 :          IF (.NOT. SIZE(radii) == nkind) THEN
    3695              :             CALL cp_abort(__LOCATION__, &
    3696              :                           "Length of keyword HIRSHFELD\ATOMIC_RADII does not "// &
    3697            0 :                           "match number of atomic kinds in the input coordinate file.")
    3698              :          END IF
    3699              :       ELSE
    3700         5214 :          radius_type = radius_covalent
    3701              :       END IF
    3702              :       CALL set_hirshfeld_info(hirshfeld_env, shape_function_type=shapef, &
    3703              :                               iterative=do_sc, ref_charge=refc, &
    3704         5214 :                               radius_type=radius_type)
    3705              :       ! shape function
    3706         5214 :       CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set, atomic_kind_set=atomic_kind_set)
    3707              :       CALL create_shape_function(hirshfeld_env, qs_kind_set, atomic_kind_set, &
    3708         5214 :                                  radii_list=radii)
    3709              :       ! reference charges
    3710         5214 :       CALL get_qs_env(qs_env, rho=rho)
    3711         5214 :       CALL qs_rho_get(rho, rho_ao_kp=matrix_p)
    3712         5214 :       nspin = SIZE(matrix_p, 1)
    3713        20856 :       ALLOCATE (charges(natom, nspin))
    3714         5202 :       SELECT CASE (refc)
    3715              :       CASE (ref_charge_atomic)
    3716        14156 :          DO ikind = 1, nkind
    3717         8954 :             CALL get_qs_kind(qs_kind_set(ikind), zeff=zeff)
    3718         8954 :             atomic_kind => atomic_kind_set(ikind)
    3719         8954 :             CALL get_atomic_kind(atomic_kind, atom_list=atom_list)
    3720        44962 :             DO iat = 1, SIZE(atom_list)
    3721        21852 :                i = atom_list(iat)
    3722        30806 :                hirshfeld_env%charges(i) = zeff
    3723              :             END DO
    3724              :          END DO
    3725              :       CASE (ref_charge_mulliken)
    3726           12 :          CALL get_qs_env(qs_env, matrix_s_kp=matrix_s, para_env=para_env)
    3727           12 :          CALL mulliken_charges(matrix_p, matrix_s, para_env, charges)
    3728           48 :          DO iat = 1, natom
    3729          108 :             hirshfeld_env%charges(iat) = SUM(charges(iat, :))
    3730              :          END DO
    3731              :       CASE DEFAULT
    3732         5214 :          CPABORT("Unknown type of reference charge for Hirshfeld partitioning.")
    3733              :       END SELECT
    3734              :       !
    3735        36088 :       charges = 0.0_dp
    3736         5214 :       IF (hirshfeld_env%iterative) THEN
    3737              :          ! Hirshfeld-I charges
    3738           22 :          CALL comp_hirshfeld_i_charges(qs_env, hirshfeld_env, charges, unit_nr)
    3739              :       ELSE
    3740              :          ! Hirshfeld charges
    3741         5192 :          CALL comp_hirshfeld_charges(qs_env, hirshfeld_env, charges)
    3742              :       END IF
    3743         5214 :       CALL get_qs_env(qs_env, particle_set=particle_set, dft_control=dft_control)
    3744         5214 :       IF (dft_control%qs_control%gapw) THEN
    3745              :          ! GAPW: add core charges (rho_hard - rho_soft)
    3746          960 :          CALL get_qs_env(qs_env, rho0_mpole=rho0_mpole)
    3747          960 :          CALL get_rho0_mpole(rho0_mpole, mp_rho=mp_rho)
    3748         3986 :          DO iat = 1, natom
    3749         3026 :             atomic_kind => particle_set(iat)%atomic_kind
    3750         3026 :             CALL get_atomic_kind(atomic_kind, kind_number=ikind)
    3751         3026 :             CALL get_qs_kind(qs_kind_set(ikind), paw_atom=paw_atom)
    3752         3986 :             IF (paw_atom) THEN
    3753         5650 :                charges(iat, 1:nspin) = charges(iat, 1:nspin) + mp_rho(iat)%q0(1:nspin)
    3754              :             END IF
    3755              :          END DO
    3756              :       END IF
    3757              :       !
    3758         5214 :       IF (unit_nr > 0) THEN
    3759              :          CALL write_hirshfeld_charges(charges, hirshfeld_env, particle_set, &
    3760         2622 :                                       qs_kind_set, unit_nr)
    3761              :       END IF
    3762              :       ! Save the charges to the results under the tag [HIRSHFELD-CHARGES]
    3763         5214 :       CALL save_hirshfeld_charges(charges, particle_set, qs_kind_set, qs_env)
    3764              :       !
    3765         5214 :       CALL release_hirshfeld_type(hirshfeld_env)
    3766         5214 :       DEALLOCATE (charges)
    3767              : 
    3768        10428 :    END SUBROUTINE hirshfeld_charges
    3769              : 
    3770              : ! **************************************************************************************************
    3771              : !> \brief ...
    3772              : !> \param ca ...
    3773              : !> \param a ...
    3774              : !> \param cb ...
    3775              : !> \param b ...
    3776              : !> \param l ...
    3777              : ! **************************************************************************************************
    3778            4 :    SUBROUTINE project_function_a(ca, a, cb, b, l)
    3779              :       ! project function cb on ca
    3780              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: ca
    3781              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: a, cb, b
    3782              :       INTEGER, INTENT(IN)                                :: l
    3783              : 
    3784              :       INTEGER                                            :: info, n
    3785            4 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: ipiv
    3786            4 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: smat, tmat, v
    3787              : 
    3788            4 :       n = SIZE(ca)
    3789           40 :       ALLOCATE (smat(n, n), tmat(n, n), v(n, 1), ipiv(n))
    3790              : 
    3791            4 :       CALL sg_overlap(smat, l, a, a)
    3792            4 :       CALL sg_overlap(tmat, l, a, b)
    3793         1252 :       v(:, 1) = MATMUL(tmat, cb)
    3794            4 :       CALL dgesv(n, 1, smat, n, ipiv, v, n, info)
    3795            4 :       CPASSERT(info == 0)
    3796           52 :       ca(:) = v(:, 1)
    3797              : 
    3798            4 :       DEALLOCATE (smat, tmat, v, ipiv)
    3799              : 
    3800            4 :    END SUBROUTINE project_function_a
    3801              : 
    3802              : ! **************************************************************************************************
    3803              : !> \brief ...
    3804              : !> \param ca ...
    3805              : !> \param a ...
    3806              : !> \param bfun ...
    3807              : !> \param grid_atom ...
    3808              : !> \param l ...
    3809              : ! **************************************************************************************************
    3810           36 :    SUBROUTINE project_function_b(ca, a, bfun, grid_atom, l)
    3811              :       ! project function f on ca
    3812              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: ca
    3813              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: a, bfun
    3814              :       TYPE(grid_atom_type), POINTER                      :: grid_atom
    3815              :       INTEGER, INTENT(IN)                                :: l
    3816              : 
    3817              :       INTEGER                                            :: i, info, n, nr
    3818           36 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: ipiv
    3819           36 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: afun
    3820           36 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: smat, v
    3821              : 
    3822           36 :       n = SIZE(ca)
    3823           36 :       nr = grid_atom%nr
    3824          360 :       ALLOCATE (smat(n, n), v(n, 1), ipiv(n), afun(nr))
    3825              : 
    3826           36 :       CALL sg_overlap(smat, l, a, a)
    3827          468 :       DO i = 1, n
    3828        22032 :          afun(:) = grid_atom%rad(:)**l*EXP(-a(i)*grid_atom%rad2(:))
    3829        22068 :          v(i, 1) = SUM(afun(:)*bfun(:)*grid_atom%wr(:))
    3830              :       END DO
    3831           36 :       CALL dgesv(n, 1, smat, n, ipiv, v, n, info)
    3832           36 :       CPASSERT(info == 0)
    3833          468 :       ca(:) = v(:, 1)
    3834              : 
    3835           36 :       DEALLOCATE (smat, v, ipiv, afun)
    3836              : 
    3837           36 :    END SUBROUTINE project_function_b
    3838              : 
    3839              : ! **************************************************************************************************
    3840              : !> \brief Performs printing of cube files from local energy
    3841              : !> \param input input
    3842              : !> \param logger the logger
    3843              : !> \param qs_env the qs_env in which the qs_env lives
    3844              : !> \par History
    3845              : !>      07.2019 created
    3846              : !> \author JGH
    3847              : ! **************************************************************************************************
    3848        14147 :    SUBROUTINE qs_scf_post_local_energy(input, logger, qs_env)
    3849              :       TYPE(section_vals_type), POINTER                   :: input
    3850              :       TYPE(cp_logger_type), POINTER                      :: logger
    3851              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3852              : 
    3853              :       CHARACTER(len=*), PARAMETER :: routineN = 'qs_scf_post_local_energy'
    3854              : 
    3855              :       CHARACTER(LEN=default_path_length)                 :: filename, my_pos_cube
    3856              :       INTEGER                                            :: handle, io_unit, natom, unit_nr
    3857              :       LOGICAL                                            :: append_cube, gapw, gapw_xc, mpi_io
    3858        14147 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: zcharge
    3859              :       TYPE(dft_control_type), POINTER                    :: dft_control
    3860              :       TYPE(particle_list_type), POINTER                  :: particles
    3861              :       TYPE(pw_env_type), POINTER                         :: pw_env
    3862              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    3863              :       TYPE(pw_r3d_rs_type)                               :: eden
    3864              :       TYPE(qs_subsys_type), POINTER                      :: subsys
    3865              :       TYPE(section_vals_type), POINTER                   :: dft_section
    3866              : 
    3867        14147 :       CALL timeset(routineN, handle)
    3868        14147 :       io_unit = cp_logger_get_default_io_unit(logger)
    3869        14147 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3870              :                                            "DFT%PRINT%LOCAL_ENERGY_CUBE"), cp_p_file)) THEN
    3871           34 :          dft_section => section_vals_get_subs_vals(input, "DFT")
    3872           34 :          CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, natom=natom)
    3873           34 :          gapw = dft_control%qs_control%gapw
    3874           34 :          gapw_xc = dft_control%qs_control%gapw_xc
    3875           34 :          CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, subsys=subsys)
    3876           34 :          CALL qs_subsys_get(subsys, particles=particles)
    3877           34 :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    3878           34 :          CALL auxbas_pw_pool%create_pw(eden)
    3879              :          !
    3880           34 :          CALL qs_local_energy(qs_env, eden)
    3881           34 :          CALL get_effective_core_charges(qs_env, zcharge)
    3882              :          !
    3883           34 :          append_cube = section_get_lval(input, "DFT%PRINT%LOCAL_ENERGY_CUBE%APPEND")
    3884           34 :          IF (append_cube) THEN
    3885            0 :             my_pos_cube = "APPEND"
    3886              :          ELSE
    3887           34 :             my_pos_cube = "REWIND"
    3888              :          END IF
    3889           34 :          mpi_io = .TRUE.
    3890              :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%LOCAL_ENERGY_CUBE", &
    3891              :                                         extension=".cube", middle_name="local_energy", &
    3892           34 :                                         file_position=my_pos_cube, mpi_io=mpi_io)
    3893              :          CALL cp_pw_to_cube(eden, unit_nr, "LOCAL ENERGY", particles=particles, zeff=zcharge, &
    3894              :                             stride=section_get_ivals(dft_section, "PRINT%LOCAL_ENERGY_CUBE%STRIDE"), &
    3895              :                             max_file_size_mb=section_get_rval(dft_section, "PRINT%LOCAL_ENERGY_CUBE%MAX_FILE_SIZE_MB"), &
    3896           34 :                             mpi_io=mpi_io)
    3897           34 :          IF (io_unit > 0) THEN
    3898           17 :             INQUIRE (UNIT=unit_nr, NAME=filename)
    3899           17 :             IF (gapw .OR. gapw_xc) THEN
    3900              :                WRITE (UNIT=io_unit, FMT="(/,T3,A,A)") &
    3901            1 :                   "The soft part of the local energy is written to the file: ", TRIM(ADJUSTL(filename))
    3902              :             ELSE
    3903              :                WRITE (UNIT=io_unit, FMT="(/,T3,A,A)") &
    3904           16 :                   "The local energy is written to the file: ", TRIM(ADJUSTL(filename))
    3905              :             END IF
    3906              :          END IF
    3907              :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
    3908           34 :                                            "DFT%PRINT%LOCAL_ENERGY_CUBE", mpi_io=mpi_io)
    3909              :          !
    3910           34 :          CALL auxbas_pw_pool%give_back_pw(eden)
    3911           34 :          DEALLOCATE (zcharge)
    3912              :       END IF
    3913        14147 :       CALL timestop(handle)
    3914              : 
    3915        28294 :    END SUBROUTINE qs_scf_post_local_energy
    3916              : 
    3917              : ! **************************************************************************************************
    3918              : !> \brief Performs printing of cube files from local energy
    3919              : !> \param input input
    3920              : !> \param logger the logger
    3921              : !> \param qs_env the qs_env in which the qs_env lives
    3922              : !> \par History
    3923              : !>      07.2019 created
    3924              : !> \author JGH
    3925              : ! **************************************************************************************************
    3926        14147 :    SUBROUTINE qs_scf_post_local_stress(input, logger, qs_env)
    3927              :       TYPE(section_vals_type), POINTER                   :: input
    3928              :       TYPE(cp_logger_type), POINTER                      :: logger
    3929              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3930              : 
    3931              :       CHARACTER(len=*), PARAMETER :: routineN = 'qs_scf_post_local_stress'
    3932              : 
    3933              :       CHARACTER(LEN=default_path_length)                 :: filename, my_pos_cube
    3934              :       INTEGER                                            :: handle, io_unit, natom, unit_nr
    3935              :       LOGICAL                                            :: append_cube, gapw, gapw_xc, mpi_io
    3936              :       REAL(KIND=dp)                                      :: beta
    3937        14147 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: zcharge
    3938              :       TYPE(dft_control_type), POINTER                    :: dft_control
    3939              :       TYPE(particle_list_type), POINTER                  :: particles
    3940              :       TYPE(pw_env_type), POINTER                         :: pw_env
    3941              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    3942              :       TYPE(pw_r3d_rs_type)                               :: stress
    3943              :       TYPE(qs_subsys_type), POINTER                      :: subsys
    3944              :       TYPE(section_vals_type), POINTER                   :: dft_section
    3945              : 
    3946        14147 :       CALL timeset(routineN, handle)
    3947        14147 :       io_unit = cp_logger_get_default_io_unit(logger)
    3948        14147 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3949              :                                            "DFT%PRINT%LOCAL_STRESS_CUBE"), cp_p_file)) THEN
    3950              :          CALL cp_warn(__LOCATION__, &
    3951           30 :                       "LOCAL_STRESS_CUBE uses the existing experimental local stress implementation")
    3952           30 :          dft_section => section_vals_get_subs_vals(input, "DFT")
    3953           30 :          CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, natom=natom)
    3954           30 :          gapw = dft_control%qs_control%gapw
    3955           30 :          gapw_xc = dft_control%qs_control%gapw_xc
    3956           30 :          CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, subsys=subsys)
    3957           30 :          CALL qs_subsys_get(subsys, particles=particles)
    3958           30 :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    3959           30 :          CALL auxbas_pw_pool%create_pw(stress)
    3960              :          !
    3961              :          ! use beta=0: kinetic energy density in symmetric form
    3962           30 :          beta = 0.0_dp
    3963           30 :          CALL qs_local_stress(qs_env, beta=beta)
    3964           30 :          CALL get_effective_core_charges(qs_env, zcharge)
    3965              :          !
    3966           30 :          append_cube = section_get_lval(input, "DFT%PRINT%LOCAL_STRESS_CUBE%APPEND")
    3967           30 :          IF (append_cube) THEN
    3968            0 :             my_pos_cube = "APPEND"
    3969              :          ELSE
    3970           30 :             my_pos_cube = "REWIND"
    3971              :          END IF
    3972           30 :          mpi_io = .TRUE.
    3973              :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%LOCAL_STRESS_CUBE", &
    3974              :                                         extension=".cube", middle_name="local_stress", &
    3975           30 :                                         file_position=my_pos_cube, mpi_io=mpi_io)
    3976              :          CALL cp_pw_to_cube(stress, unit_nr, "LOCAL STRESS", particles=particles, zeff=zcharge, &
    3977              :                             stride=section_get_ivals(dft_section, "PRINT%LOCAL_STRESS_CUBE%STRIDE"), &
    3978              :                             max_file_size_mb=section_get_rval(dft_section, "PRINT%LOCAL_STRESS_CUBE%MAX_FILE_SIZE_MB"), &
    3979           30 :                             mpi_io=mpi_io)
    3980           30 :          IF (io_unit > 0) THEN
    3981           15 :             INQUIRE (UNIT=unit_nr, NAME=filename)
    3982           15 :             WRITE (UNIT=io_unit, FMT="(/,T3,A)") "Write 1/3*Tr(sigma) to cube file"
    3983           15 :             IF (gapw .OR. gapw_xc) THEN
    3984              :                WRITE (UNIT=io_unit, FMT="(T3,A,A)") &
    3985            0 :                   "The soft part of the local stress is written to the file: ", TRIM(ADJUSTL(filename))
    3986              :             ELSE
    3987              :                WRITE (UNIT=io_unit, FMT="(T3,A,A)") &
    3988           15 :                   "The local stress is written to the file: ", TRIM(ADJUSTL(filename))
    3989              :             END IF
    3990              :          END IF
    3991              :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
    3992           30 :                                            "DFT%PRINT%LOCAL_STRESS_CUBE", mpi_io=mpi_io)
    3993              :          !
    3994           30 :          CALL auxbas_pw_pool%give_back_pw(stress)
    3995           30 :          DEALLOCATE (zcharge)
    3996              :       END IF
    3997              : 
    3998        14147 :       CALL timestop(handle)
    3999              : 
    4000        28294 :    END SUBROUTINE qs_scf_post_local_stress
    4001              : 
    4002              : ! **************************************************************************************************
    4003              : !> \brief Performs printing of cube files related to the implicit Poisson solver
    4004              : !> \param input input
    4005              : !> \param logger the logger
    4006              : !> \param qs_env the qs_env in which the qs_env lives
    4007              : !> \par History
    4008              : !>      03.2016 refactored from write_mo_free_results [Hossein Bani-Hashemian]
    4009              : !> \author Mohammad Hossein Bani-Hashemian
    4010              : ! **************************************************************************************************
    4011        14147 :    SUBROUTINE qs_scf_post_ps_implicit(input, logger, qs_env)
    4012              :       TYPE(section_vals_type), POINTER                   :: input
    4013              :       TYPE(cp_logger_type), POINTER                      :: logger
    4014              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    4015              : 
    4016              :       CHARACTER(len=*), PARAMETER :: routineN = 'qs_scf_post_ps_implicit'
    4017              : 
    4018              :       CHARACTER(LEN=default_path_length)                 :: filename, my_pos_cube
    4019              :       INTEGER                                            :: boundary_condition, handle, i, j, &
    4020              :                                                             n_cstr, n_tiles, unit_nr
    4021              :       LOGICAL :: append_cube, do_cstr_charge_cube, do_dielectric_cube, do_dirichlet_bc_cube, &
    4022              :          has_dirichlet_bc, has_implicit_ps, mpi_io, tile_cubes
    4023        14147 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: zcharge
    4024              :       TYPE(particle_list_type), POINTER                  :: particles
    4025              :       TYPE(pw_env_type), POINTER                         :: pw_env
    4026              :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
    4027              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    4028              :       TYPE(pw_r3d_rs_type)                               :: aux_r
    4029              :       TYPE(pw_r3d_rs_type), POINTER                      :: dirichlet_tile
    4030              :       TYPE(qs_subsys_type), POINTER                      :: subsys
    4031              :       TYPE(section_vals_type), POINTER                   :: dft_section
    4032              : 
    4033        14147 :       CALL timeset(routineN, handle)
    4034              : 
    4035        14147 :       NULLIFY (pw_env, auxbas_pw_pool, dft_section, particles)
    4036              : 
    4037        14147 :       dft_section => section_vals_get_subs_vals(input, "DFT")
    4038        14147 :       CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, subsys=subsys)
    4039        14147 :       CALL qs_subsys_get(subsys, particles=particles)
    4040        14147 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    4041              : 
    4042        14147 :       has_implicit_ps = .FALSE.
    4043        14147 :       CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
    4044        14147 :       IF (pw_env%poisson_env%parameters%solver == pw_poisson_implicit) has_implicit_ps = .TRUE.
    4045              : 
    4046              :       ! Write the dielectric constant into a cube file
    4047              :       do_dielectric_cube = BTEST(cp_print_key_should_output(logger%iter_info, input, &
    4048        14147 :                                                             "DFT%PRINT%IMPLICIT_PSOLVER%DIELECTRIC_CUBE"), cp_p_file)
    4049        14147 :       IF (has_implicit_ps .AND. do_dielectric_cube) THEN
    4050            2 :          IF (.NOT. ALLOCATED(zcharge)) CALL get_effective_core_charges(qs_env, zcharge)
    4051            2 :          append_cube = section_get_lval(input, "DFT%PRINT%IMPLICIT_PSOLVER%DIELECTRIC_CUBE%APPEND")
    4052            2 :          my_pos_cube = "REWIND"
    4053            2 :          IF (append_cube) THEN
    4054            0 :             my_pos_cube = "APPEND"
    4055              :          END IF
    4056            2 :          mpi_io = .TRUE.
    4057              :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%IMPLICIT_PSOLVER%DIELECTRIC_CUBE", &
    4058              :                                         extension=".cube", middle_name="DIELECTRIC_CONSTANT", file_position=my_pos_cube, &
    4059            2 :                                         mpi_io=mpi_io)
    4060            2 :          CALL pw_env_get(pw_env, poisson_env=poisson_env, auxbas_pw_pool=auxbas_pw_pool)
    4061            2 :          CALL auxbas_pw_pool%create_pw(aux_r)
    4062              : 
    4063            2 :          boundary_condition = pw_env%poisson_env%parameters%ps_implicit_params%boundary_condition
    4064            2 :          SELECT CASE (boundary_condition)
    4065              :          CASE (PERIODIC_BC, MIXED_PERIODIC_BC)
    4066            2 :             CALL pw_copy(poisson_env%implicit_env%dielectric%eps, aux_r)
    4067              :          CASE (MIXED_BC, NEUMANN_BC)
    4068              :             CALL pw_shrink(pw_env%poisson_env%parameters%ps_implicit_params%neumann_directions, &
    4069              :                            pw_env%poisson_env%implicit_env%dct_env%dests_shrink, &
    4070              :                            pw_env%poisson_env%implicit_env%dct_env%srcs_shrink, &
    4071              :                            pw_env%poisson_env%implicit_env%dct_env%bounds_local_shftd, &
    4072            2 :                            poisson_env%implicit_env%dielectric%eps, aux_r)
    4073              :          END SELECT
    4074              : 
    4075              :          CALL cp_pw_to_cube(aux_r, unit_nr, "DIELECTRIC CONSTANT", particles=particles, zeff=zcharge, &
    4076              :                             stride=section_get_ivals(dft_section, "PRINT%IMPLICIT_PSOLVER%DIELECTRIC_CUBE%STRIDE"), &
    4077              :                         max_file_size_mb=section_get_rval(dft_section, "PRINT%IMPLICIT_PSOLVER%DIELECTRIC_CUBE%MAX_FILE_SIZE_MB"), &
    4078            2 :                             mpi_io=mpi_io)
    4079              :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
    4080            2 :                                            "DFT%PRINT%IMPLICIT_PSOLVER%DIELECTRIC_CUBE", mpi_io=mpi_io)
    4081              : 
    4082            2 :          CALL auxbas_pw_pool%give_back_pw(aux_r)
    4083              :       END IF
    4084              : 
    4085              :       ! Write Dirichlet constraint charges into a cube file
    4086              :       do_cstr_charge_cube = BTEST(cp_print_key_should_output(logger%iter_info, input, &
    4087        14147 :                                                              "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_CSTR_CHARGE_CUBE"), cp_p_file)
    4088              : 
    4089        14147 :       has_dirichlet_bc = .FALSE.
    4090        14147 :       IF (has_implicit_ps) THEN
    4091           88 :          boundary_condition = pw_env%poisson_env%parameters%ps_implicit_params%boundary_condition
    4092           88 :          IF (boundary_condition == MIXED_PERIODIC_BC .OR. boundary_condition == MIXED_BC) THEN
    4093           60 :             has_dirichlet_bc = .TRUE.
    4094              :          END IF
    4095              :       END IF
    4096              : 
    4097           88 :       IF (has_implicit_ps .AND. do_cstr_charge_cube .AND. has_dirichlet_bc) THEN
    4098            2 :          IF (.NOT. ALLOCATED(zcharge)) CALL get_effective_core_charges(qs_env, zcharge)
    4099              :          append_cube = section_get_lval(input, &
    4100            2 :                                         "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_CSTR_CHARGE_CUBE%APPEND")
    4101            2 :          my_pos_cube = "REWIND"
    4102            2 :          IF (append_cube) THEN
    4103            0 :             my_pos_cube = "APPEND"
    4104              :          END IF
    4105            2 :          mpi_io = .TRUE.
    4106              :          unit_nr = cp_print_key_unit_nr(logger, input, &
    4107              :                                         "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_CSTR_CHARGE_CUBE", &
    4108              :                                         extension=".cube", middle_name="dirichlet_cstr_charge", file_position=my_pos_cube, &
    4109            2 :                                         mpi_io=mpi_io)
    4110            2 :          CALL pw_env_get(pw_env, poisson_env=poisson_env, auxbas_pw_pool=auxbas_pw_pool)
    4111            2 :          CALL auxbas_pw_pool%create_pw(aux_r)
    4112              : 
    4113            2 :          boundary_condition = pw_env%poisson_env%parameters%ps_implicit_params%boundary_condition
    4114            2 :          SELECT CASE (boundary_condition)
    4115              :          CASE (MIXED_PERIODIC_BC)
    4116            2 :             CALL pw_copy(poisson_env%implicit_env%cstr_charge, aux_r)
    4117              :          CASE (MIXED_BC)
    4118              :             CALL pw_shrink(pw_env%poisson_env%parameters%ps_implicit_params%neumann_directions, &
    4119              :                            pw_env%poisson_env%implicit_env%dct_env%dests_shrink, &
    4120              :                            pw_env%poisson_env%implicit_env%dct_env%srcs_shrink, &
    4121              :                            pw_env%poisson_env%implicit_env%dct_env%bounds_local_shftd, &
    4122            2 :                            poisson_env%implicit_env%cstr_charge, aux_r)
    4123              :          END SELECT
    4124              : 
    4125              :          CALL cp_pw_to_cube(aux_r, unit_nr, "DIRICHLET CONSTRAINT CHARGE", particles=particles, zeff=zcharge, &
    4126              :                             stride=section_get_ivals(dft_section, "PRINT%IMPLICIT_PSOLVER%DIRICHLET_CSTR_CHARGE_CUBE%STRIDE"), &
    4127              :              max_file_size_mb=section_get_rval(dft_section, "PRINT%IMPLICIT_PSOLVER%DIRICHLET_CSTR_CHARGE_CUBE%MAX_FILE_SIZE_MB"), &
    4128            2 :                             mpi_io=mpi_io)
    4129              :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
    4130            2 :                                            "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_CSTR_CHARGE_CUBE", mpi_io=mpi_io)
    4131              : 
    4132            2 :          CALL auxbas_pw_pool%give_back_pw(aux_r)
    4133              :       END IF
    4134              : 
    4135              :       ! Write Dirichlet type constranits into cube files
    4136              :       do_dirichlet_bc_cube = BTEST(cp_print_key_should_output(logger%iter_info, input, &
    4137        14147 :                                                               "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE"), cp_p_file)
    4138        14147 :       has_dirichlet_bc = .FALSE.
    4139        14147 :       IF (has_implicit_ps) THEN
    4140           88 :          boundary_condition = pw_env%poisson_env%parameters%ps_implicit_params%boundary_condition
    4141           88 :          IF (boundary_condition == MIXED_PERIODIC_BC .OR. boundary_condition == MIXED_BC) THEN
    4142              :             has_dirichlet_bc = .TRUE.
    4143              :          END IF
    4144              :       END IF
    4145              : 
    4146           60 :       IF (has_implicit_ps .AND. has_dirichlet_bc .AND. do_dirichlet_bc_cube) THEN
    4147            2 :          IF (.NOT. ALLOCATED(zcharge)) CALL get_effective_core_charges(qs_env, zcharge)
    4148            2 :          append_cube = section_get_lval(input, "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE%APPEND")
    4149            2 :          my_pos_cube = "REWIND"
    4150            2 :          IF (append_cube) THEN
    4151            0 :             my_pos_cube = "APPEND"
    4152              :          END IF
    4153            2 :          tile_cubes = section_get_lval(input, "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE%TILE_CUBES")
    4154              : 
    4155            2 :          CALL pw_env_get(pw_env, poisson_env=poisson_env, auxbas_pw_pool=auxbas_pw_pool)
    4156            2 :          CALL auxbas_pw_pool%create_pw(aux_r)
    4157            2 :          CALL pw_zero(aux_r)
    4158              : 
    4159            2 :          IF (tile_cubes) THEN
    4160              :             ! one cube file per tile
    4161            0 :             n_cstr = SIZE(poisson_env%implicit_env%contacts)
    4162            0 :             DO j = 1, n_cstr
    4163            0 :                n_tiles = poisson_env%implicit_env%contacts(j)%dirichlet_bc%n_tiles
    4164            0 :                DO i = 1, n_tiles
    4165              :                   filename = "dirichlet_cstr_"//TRIM(ADJUSTL(cp_to_string(j)))// &
    4166            0 :                              "_tile_"//TRIM(ADJUSTL(cp_to_string(i)))
    4167            0 :                   mpi_io = .TRUE.
    4168              :                   unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE", &
    4169              :                                                  extension=".cube", middle_name=filename, file_position=my_pos_cube, &
    4170            0 :                                                  mpi_io=mpi_io)
    4171              : 
    4172            0 :                   CALL pw_copy(poisson_env%implicit_env%contacts(j)%dirichlet_bc%tiles(i)%tile%tile_pw, aux_r)
    4173              : 
    4174              :                   CALL cp_pw_to_cube(aux_r, unit_nr, "DIRICHLET TYPE CONSTRAINT", particles=particles, zeff=zcharge, &
    4175              :                                      stride=section_get_ivals(dft_section, "PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE%STRIDE"), &
    4176              :                       max_file_size_mb=section_get_rval(dft_section, "PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE%MAX_FILE_SIZE_MB"), &
    4177            0 :                                      mpi_io=mpi_io)
    4178              :                   CALL cp_print_key_finished_output(unit_nr, logger, input, &
    4179            0 :                                                     "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE", mpi_io=mpi_io)
    4180              :                END DO
    4181              :             END DO
    4182              :          ELSE
    4183              :             ! a single cube file
    4184            2 :             NULLIFY (dirichlet_tile)
    4185            2 :             ALLOCATE (dirichlet_tile)
    4186            2 :             CALL auxbas_pw_pool%create_pw(dirichlet_tile)
    4187            2 :             CALL pw_zero(dirichlet_tile)
    4188            2 :             mpi_io = .TRUE.
    4189              :             unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE", &
    4190              :                                            extension=".cube", middle_name="DIRICHLET_CSTR", file_position=my_pos_cube, &
    4191            2 :                                            mpi_io=mpi_io)
    4192              : 
    4193            2 :             n_cstr = SIZE(poisson_env%implicit_env%contacts)
    4194            6 :             DO j = 1, n_cstr
    4195            4 :                n_tiles = poisson_env%implicit_env%contacts(j)%dirichlet_bc%n_tiles
    4196           10 :                DO i = 1, n_tiles
    4197            4 :                   CALL pw_copy(poisson_env%implicit_env%contacts(j)%dirichlet_bc%tiles(i)%tile%tile_pw, dirichlet_tile)
    4198            8 :                   CALL pw_axpy(dirichlet_tile, aux_r)
    4199              :                END DO
    4200              :             END DO
    4201              : 
    4202              :             CALL cp_pw_to_cube(aux_r, unit_nr, "DIRICHLET TYPE CONSTRAINT", particles=particles, zeff=zcharge, &
    4203              :                                stride=section_get_ivals(dft_section, "PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE%STRIDE"), &
    4204              :                       max_file_size_mb=section_get_rval(dft_section, "PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE%MAX_FILE_SIZE_MB"), &
    4205            2 :                                mpi_io=mpi_io)
    4206              :             CALL cp_print_key_finished_output(unit_nr, logger, input, &
    4207            2 :                                               "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE", mpi_io=mpi_io)
    4208            2 :             CALL auxbas_pw_pool%give_back_pw(dirichlet_tile)
    4209            2 :             DEALLOCATE (dirichlet_tile)
    4210              :          END IF
    4211              : 
    4212            2 :          CALL auxbas_pw_pool%give_back_pw(aux_r)
    4213              :       END IF
    4214              : 
    4215        14147 :       CALL timestop(handle)
    4216              : 
    4217        28294 :    END SUBROUTINE qs_scf_post_ps_implicit
    4218              : 
    4219              : !**************************************************************************************************
    4220              : !> \brief write an adjacency (interaction) matrix
    4221              : !> \param qs_env qs environment
    4222              : !> \param input the input
    4223              : !> \author Mohammad Hossein Bani-Hashemian
    4224              : ! **************************************************************************************************
    4225        14147 :    SUBROUTINE write_adjacency_matrix(qs_env, input)
    4226              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    4227              :       TYPE(section_vals_type), POINTER                   :: input
    4228              : 
    4229              :       CHARACTER(len=*), PARAMETER :: routineN = 'write_adjacency_matrix'
    4230              : 
    4231              :       INTEGER                                            :: adjm_size, colind, handle, iatom, ikind, &
    4232              :                                                             ind, jatom, jkind, k, natom, nkind, &
    4233              :                                                             output_unit, rowind, unit_nr
    4234        14147 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: interact_adjm
    4235              :       LOGICAL                                            :: do_adjm_write, do_symmetric
    4236              :       TYPE(cp_logger_type), POINTER                      :: logger
    4237        14147 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: basis_set_list_a, basis_set_list_b
    4238              :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
    4239              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    4240              :       TYPE(neighbor_list_iterator_p_type), &
    4241        14147 :          DIMENSION(:), POINTER                           :: nl_iterator
    4242              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    4243        14147 :          POINTER                                         :: nl
    4244        14147 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    4245              :       TYPE(section_vals_type), POINTER                   :: dft_section
    4246              : 
    4247        14147 :       CALL timeset(routineN, handle)
    4248              : 
    4249        14147 :       NULLIFY (dft_section)
    4250              : 
    4251        14147 :       logger => cp_get_default_logger()
    4252        14147 :       output_unit = cp_logger_get_default_io_unit(logger)
    4253              : 
    4254        14147 :       dft_section => section_vals_get_subs_vals(input, "DFT")
    4255              :       do_adjm_write = BTEST(cp_print_key_should_output(logger%iter_info, dft_section, &
    4256        14147 :                                                        "PRINT%ADJMAT_WRITE"), cp_p_file)
    4257              : 
    4258        14147 :       IF (do_adjm_write) THEN
    4259           28 :          NULLIFY (qs_kind_set, nl_iterator)
    4260           28 :          NULLIFY (basis_set_list_a, basis_set_list_b, basis_set_a, basis_set_b)
    4261              : 
    4262           28 :          CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set, sab_orb=nl, natom=natom, para_env=para_env)
    4263              : 
    4264           28 :          nkind = SIZE(qs_kind_set)
    4265           28 :          CPASSERT(SIZE(nl) > 0)
    4266           28 :          CALL get_neighbor_list_set_p(neighbor_list_sets=nl, symmetric=do_symmetric)
    4267           28 :          CPASSERT(do_symmetric)
    4268          216 :          ALLOCATE (basis_set_list_a(nkind), basis_set_list_b(nkind))
    4269           28 :          CALL basis_set_list_setup(basis_set_list_a, "ORB", qs_kind_set)
    4270           28 :          CALL basis_set_list_setup(basis_set_list_b, "ORB", qs_kind_set)
    4271              : 
    4272           28 :          adjm_size = ((natom + 1)*natom)/2
    4273           84 :          ALLOCATE (interact_adjm(4*adjm_size))
    4274           28 :          interact_adjm = 0
    4275              : 
    4276           28 :          NULLIFY (nl_iterator)
    4277           28 :          CALL neighbor_list_iterator_create(nl_iterator, nl)
    4278         2021 :          DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
    4279              :             CALL get_iterator_info(nl_iterator, &
    4280              :                                    ikind=ikind, jkind=jkind, &
    4281         1993 :                                    iatom=iatom, jatom=jatom)
    4282              : 
    4283         1993 :             basis_set_a => basis_set_list_a(ikind)%gto_basis_set
    4284         1993 :             IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
    4285         1993 :             basis_set_b => basis_set_list_b(jkind)%gto_basis_set
    4286         1993 :             IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
    4287              : 
    4288              :             ! move everything to the upper triangular part
    4289         1993 :             IF (iatom <= jatom) THEN
    4290              :                rowind = iatom
    4291              :                colind = jatom
    4292              :             ELSE
    4293          670 :                rowind = jatom
    4294          670 :                colind = iatom
    4295              :                ! swap the kinds too
    4296              :                ikind = ikind + jkind
    4297          670 :                jkind = ikind - jkind
    4298          670 :                ikind = ikind - jkind
    4299              :             END IF
    4300              : 
    4301              :             ! indexing upper triangular matrix
    4302         1993 :             ind = adjm_size - (natom - rowind + 1)*((natom - rowind + 1) + 1)/2 + colind - rowind + 1
    4303              :             ! convert the upper triangular matrix into a adjm_size x 4 matrix
    4304              :             ! columns are: iatom, jatom, ikind, jkind
    4305         1993 :             interact_adjm((ind - 1)*4 + 1) = rowind
    4306         1993 :             interact_adjm((ind - 1)*4 + 2) = colind
    4307         1993 :             interact_adjm((ind - 1)*4 + 3) = ikind
    4308         1993 :             interact_adjm((ind - 1)*4 + 4) = jkind
    4309              :          END DO
    4310              : 
    4311           28 :          CALL para_env%sum(interact_adjm)
    4312              : 
    4313              :          unit_nr = cp_print_key_unit_nr(logger, dft_section, "PRINT%ADJMAT_WRITE", &
    4314              :                                         extension=".adjmat", file_form="FORMATTED", &
    4315           28 :                                         file_status="REPLACE")
    4316           28 :          IF (unit_nr > 0) THEN
    4317           14 :             WRITE (unit_nr, "(1A,2X,1A,5X,1A,4X,A5,3X,A5)") "#", "iatom", "jatom", "ikind", "jkind"
    4318           88 :             DO k = 1, 4*adjm_size, 4
    4319              :                ! print only the interacting atoms
    4320           88 :                IF (interact_adjm(k) > 0 .AND. interact_adjm(k + 1) > 0) THEN
    4321           74 :                   WRITE (unit_nr, "(I8,2X,I8,3X,I6,2X,I6)") interact_adjm(k:k + 3)
    4322              :                END IF
    4323              :             END DO
    4324              :          END IF
    4325              : 
    4326           28 :          CALL cp_print_key_finished_output(unit_nr, logger, dft_section, "PRINT%ADJMAT_WRITE")
    4327              : 
    4328           28 :          CALL neighbor_list_iterator_release(nl_iterator)
    4329           56 :          DEALLOCATE (basis_set_list_a, basis_set_list_b)
    4330              :       END IF
    4331              : 
    4332        14147 :       CALL timestop(handle)
    4333              : 
    4334        28294 :    END SUBROUTINE write_adjacency_matrix
    4335              : 
    4336              : ! **************************************************************************************************
    4337              : !> \brief Updates Hartree potential with MP2 density. Important for REPEAT charges
    4338              : !> \param rho ...
    4339              : !> \param qs_env ...
    4340              : !> \author Vladimir Rybkin
    4341              : ! **************************************************************************************************
    4342          322 :    SUBROUTINE update_hartree_with_mp2(rho, qs_env)
    4343              :       TYPE(qs_rho_type), POINTER                         :: rho
    4344              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    4345              : 
    4346              :       LOGICAL                                            :: use_virial
    4347              :       TYPE(pw_c1d_gs_type)                               :: rho_tot_gspace, v_hartree_gspace
    4348              :       TYPE(pw_c1d_gs_type), POINTER                      :: rho_core
    4349              :       TYPE(pw_env_type), POINTER                         :: pw_env
    4350              :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
    4351              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    4352              :       TYPE(pw_r3d_rs_type), POINTER                      :: v_hartree_rspace
    4353              :       TYPE(qs_energy_type), POINTER                      :: energy
    4354              :       TYPE(virial_type), POINTER                         :: virial
    4355              : 
    4356          322 :       NULLIFY (auxbas_pw_pool, pw_env, poisson_env, energy, rho_core, v_hartree_rspace, virial)
    4357              :       CALL get_qs_env(qs_env, pw_env=pw_env, energy=energy, &
    4358              :                       rho_core=rho_core, virial=virial, &
    4359          322 :                       v_hartree_rspace=v_hartree_rspace)
    4360              : 
    4361          322 :       use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
    4362              : 
    4363              :       IF (.NOT. use_virial) THEN
    4364              : 
    4365              :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
    4366          268 :                          poisson_env=poisson_env)
    4367          268 :          CALL auxbas_pw_pool%create_pw(v_hartree_gspace)
    4368          268 :          CALL auxbas_pw_pool%create_pw(rho_tot_gspace)
    4369              : 
    4370          268 :          CALL calc_rho_tot_gspace(rho_tot_gspace, qs_env, rho)
    4371              :          CALL pw_poisson_solve(poisson_env, rho_tot_gspace, energy%hartree, &
    4372          268 :                                v_hartree_gspace, rho_core=rho_core)
    4373              : 
    4374          268 :          CALL pw_transfer(v_hartree_gspace, v_hartree_rspace)
    4375          268 :          CALL pw_scale(v_hartree_rspace, v_hartree_rspace%pw_grid%dvol)
    4376              : 
    4377          268 :          CALL auxbas_pw_pool%give_back_pw(v_hartree_gspace)
    4378          268 :          CALL auxbas_pw_pool%give_back_pw(rho_tot_gspace)
    4379              :       END IF
    4380              : 
    4381          322 :    END SUBROUTINE update_hartree_with_mp2
    4382              : 
    4383            0 : END MODULE qs_scf_post_gpw
        

Generated by: LCOV version 2.0-1