LCOV - code coverage report
Current view: top level - src - qs_scf_post_gpw.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:1155b05) Lines: 86.7 % 1636 1418
Test Date: 2026-03-21 06:31:29 Functions: 97.1 % 34 33

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

Generated by: LCOV version 2.0-1