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

Generated by: LCOV version 2.0-1