!--------------------------------------------------------------------------------------------------!
!   CP2K: A general program to perform molecular dynamics simulations                              !
!   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
!                                                                                                  !
!   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
!--------------------------------------------------------------------------------------------------!

! **************************************************************************************************
!> \par History
!>      - mo_set_p_type added to qs_env (23.04.02,MK)
!>      - qs_force_type added to qs_env (05.06.02,MK)
!> \author MK (23.01.2002)
! **************************************************************************************************
MODULE qs_environment_types
   USE admm_types,                      ONLY: admm_env_release,&
                                              admm_type
   USE almo_scf_types,                  ONLY: almo_scf_env_release,&
                                              almo_scf_env_type
   USE atomic_kind_types,               ONLY: atomic_kind_type
   USE atprop_types,                    ONLY: atprop_type
   USE cell_types,                      ONLY: cell_release,&
                                              cell_retain,&
                                              cell_type
   USE cp_blacs_env,                    ONLY: cp_blacs_env_type
   USE cp_control_types,                ONLY: dft_control_type
   USE cp_dbcsr_api,                    ONLY: dbcsr_distribution_type,&
                                              dbcsr_p_type,&
                                              dbcsr_release_p
   USE cp_ddapc_types,                  ONLY: cp_ddapc_ewald_release,&
                                              cp_ddapc_ewald_type,&
                                              cp_ddapc_release,&
                                              cp_ddapc_type
   USE cp_fm_types,                     ONLY: cp_fm_release,&
                                              cp_fm_type
   USE cp_result_types,                 ONLY: cp_result_type
   USE cp_subsys_types,                 ONLY: cp_subsys_type
   USE distribution_1d_types,           ONLY: distribution_1d_type
   USE distribution_2d_types,           ONLY: distribution_2d_type
   USE dm_ls_scf_types,                 ONLY: ls_scf_env_type,&
                                              ls_scf_release
   USE ec_env_types,                    ONLY: ec_env_release,&
                                              energy_correction_type
   USE et_coupling_types,               ONLY: et_coupling_release,&
                                              et_coupling_type
   USE ewald_environment_types,         ONLY: ewald_env_release,&
                                              ewald_environment_type
   USE ewald_pw_types,                  ONLY: ewald_pw_release,&
                                              ewald_pw_type
   USE exstates_types,                  ONLY: excited_energy_type,&
                                              exstate_release
   USE fist_nonbond_env_types,          ONLY: fist_nonbond_env_release,&
                                              fist_nonbond_env_type
   USE global_types,                    ONLY: global_environment_type
   USE hartree_local_types,             ONLY: ecoul_1center_type,&
                                              get_hartree_local,&
                                              hartree_local_create,&
                                              hartree_local_release,&
                                              hartree_local_type,&
                                              set_hartree_local
   USE hfx_types,                       ONLY: hfx_release,&
                                              hfx_type
   USE input_constants,                 ONLY: energy_force_run,&
                                              energy_run
   USE input_section_types,             ONLY: section_vals_release,&
                                              section_vals_retain,&
                                              section_vals_type
   USE kg_environment_types,            ONLY: kg_env_release,&
                                              kg_environment_type
   USE kinds,                           ONLY: dp
   USE kpoint_types,                    ONLY: kpoint_type
   USE lri_environment_types,           ONLY: lri_density_release,&
                                              lri_density_type,&
                                              lri_env_release,&
                                              lri_environment_type
   USE message_passing,                 ONLY: mp_para_env_type
   USE molecule_kind_types,             ONLY: molecule_kind_type
   USE molecule_types,                  ONLY: molecule_type
   USE mp2_types,                       ONLY: mp2_env_release,&
                                              mp2_type
   USE mscfg_types,                     ONLY: molecular_scf_guess_env_destroy,&
                                              molecular_scf_guess_env_type
   USE particle_types,                  ONLY: particle_type
   USE post_scf_bandstructure_types,    ONLY: bs_env_release,&
                                              post_scf_bandstructure_type
   USE pw_env_types,                    ONLY: pw_env_type
   USE pw_types,                        ONLY: pw_c1d_gs_type,&
                                              pw_r3d_rs_type
   USE qmmm_types_low,                  ONLY: qmmm_env_qm_type
   USE qs_active_space_types,           ONLY: active_space_type,&
                                              release_active_space_type
   USE qs_charges_types,                ONLY: qs_charges_release,&
                                              qs_charges_type
   USE qs_dftb_types,                   ONLY: qs_dftb_pairpot_release,&
                                              qs_dftb_pairpot_type
   USE qs_dispersion_types,             ONLY: qs_dispersion_release,&
                                              qs_dispersion_type
   USE qs_energy_types,                 ONLY: qs_energy_type
   USE qs_force_types,                  ONLY: qs_force_type
   USE qs_gcp_types,                    ONLY: qs_gcp_release,&
                                              qs_gcp_type
   USE qs_harris_types,                 ONLY: harris_env_release,&
                                              harris_type
   USE qs_kind_types,                   ONLY: qs_kind_type
   USE qs_ks_qmmm_types,                ONLY: qs_ks_qmmm_env_type,&
                                              qs_ks_qmmm_release
   USE qs_ks_types,                     ONLY: get_ks_env,&
                                              qs_ks_env_type,&
                                              qs_ks_part_release,&
                                              qs_ks_release,&
                                              set_ks_env
   USE qs_linres_types,                 ONLY: linres_control_release,&
                                              linres_control_type,&
                                              polar_env_release,&
                                              polar_env_type
   USE qs_local_rho_types,              ONLY: get_local_rho,&
                                              local_rho_set_create,&
                                              local_rho_set_release,&
                                              local_rho_type,&
                                              rhoz_type,&
                                              set_local_rho
   USE qs_matrix_pools,                 ONLY: mpools_release,&
                                              mpools_retain,&
                                              qs_matrix_pools_type
   USE qs_mo_types,                     ONLY: deallocate_mo_set,&
                                              mo_set_type
   USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
   USE qs_oce_types,                    ONLY: deallocate_oce_set,&
                                              oce_matrix_type
   USE qs_period_efield_types,          ONLY: efield_berry_release,&
                                              efield_berry_type
   USE qs_rho0_types,                   ONLY: rho0_atom_type,&
                                              rho0_mpole_type
   USE qs_rho_atom_types,               ONLY: rho_atom_type
   USE qs_rho_types,                    ONLY: qs_rho_p_type,&
                                              qs_rho_release,&
                                              qs_rho_type
   USE qs_scf_types,                    ONLY: qs_scf_env_type,&
                                              scf_env_release
   USE qs_subsys_types,                 ONLY: qs_subsys_set,&
                                              qs_subsys_type
   USE qs_wf_history_types,             ONLY: qs_wf_history_type,&
                                              wfi_release,&
                                              wfi_retain
   USE rel_control_types,               ONLY: rel_c_release,&
                                              rel_control_type
   USE rt_propagation_types,            ONLY: rt_prop_release,&
                                              rt_prop_type
   USE scf_control_types,               ONLY: scf_c_release,&
                                              scf_control_type
   USE semi_empirical_mpole_types,      ONLY: nddo_mpole_release,&
                                              nddo_mpole_type
   USE semi_empirical_store_int_types,  ONLY: semi_empirical_si_release,&
                                              semi_empirical_si_type
   USE semi_empirical_types,            ONLY: se_taper_release,&
                                              se_taper_type
   USE task_list_types,                 ONLY: task_list_type
   USE transport_env_types,             ONLY: transport_env_release,&
                                              transport_env_type
   USE virial_types,                    ONLY: virial_type
   USE wannier_states_types,            ONLY: wannier_centres_type
   USE xas_env_types,                   ONLY: xas_env_release,&
                                              xas_environment_type
#include "./base/base_uses.f90"

   IMPLICIT NONE

   PRIVATE

   CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_environment_types'

! *** Public data types ***

   PUBLIC :: qs_environment_type

! *** Public subroutines ***

   PUBLIC :: get_qs_env, &
             qs_env_create, &
             qs_env_release, &
             qs_env_part_release, &
             set_qs_env

! **************************************************************************************************
!> \param local_rho_set contains the atomic, compensations and core densities
!>                       and the local parts of the xc terms
!> \param hartree_local contains the 1, 2 and 3 centers coulomb terms
!> \param requires_mo_derivs logical, true if dE/dC is required (e.g. OT)
!> \param has_unit_metric logical, true if the S matrix is considered unity for the SCF
!> \param mo_derivs the actual derivatives of the total energy wrt to MO coeffs (divided by 2*f_i)
!> \param xas_env temporary information for xas calculation
!> \param dftb_potential pair potentials for use with DFTB
!> \param dispersion_env environment for use with QS dispersion
!>
!>      compatibility get (things that you should get from the subsys):
!> \param atomic_kind_set array with infos about the species (atomic_kinds)
!>        present in the system
!> \param particle_set info on the atoms you simulate, pos,...
!> \param local_particles which particles ar local to this processor
!>      new:
!> \param local_molecules which molecules are local to this processor
!> \param molecule_kind_set description of the molecule kinds
!> \param molecule_set all the molecule description
!> \param rtp all data needed for real time propagation
!> \param x contains data used in Hartree-Fock-Exchange calculations
!> \param task_list the list of tasks used in collocate and integrate
!> \param task_list_soft the list of tasks used in collocate and integrate in case of soft basis functions
!> \param mo_loc_history if a history of localized wfn is kept, they are stored here.
!> \param molecular_scf_guess_env contains inforamation about and results of claculations
!>          on separate molecules
!> \par History
!>      11.2002 added doc and attribute description [fawzi]
!>      08.2004 renamed some of the very short names (s,c,k,h) for easier grepping
!>      06.2018 polar_env added (MK)
!> \author Matthias Krack & fawzi
! **************************************************************************************************

   TYPE qs_environment_type
      LOGICAL :: qmmm = .FALSE., qmmm_periodic = .FALSE.
      LOGICAL :: requires_mo_derivs = .FALSE.
      LOGICAL :: requires_matrix_vxc = .FALSE.
      LOGICAL :: has_unit_metric = .FALSE.
      LOGICAL :: run_rtp = .FALSE.
      LOGICAL :: linres_run = .FALSE.
      LOGICAL :: calc_image_preconditioner = .FALSE.
      LOGICAL :: do_transport = .FALSE.
      LOGICAL :: single_point_run = .FALSE.
      LOGICAL :: given_embed_pot = .FALSE.
      LOGICAL :: energy_correction = .FALSE.
      LOGICAL :: harris_method = .FALSE.
      REAL(KIND=dp)                                         :: sim_time = -1.0_dp
      REAL(KIND=dp) :: start_time = -1.0_dp, target_time = -1.0_dp
      REAL(KIND=dp), DIMENSION(:, :), POINTER               :: image_matrix => NULL()
      REAL(KIND=dp), DIMENSION(:), POINTER                  :: image_coeff => NULL()
      INTEGER, DIMENSION(:), POINTER                        :: ipiv => NULL()
      INTEGER                                               :: sim_step = -1
      TYPE(ls_scf_env_type), POINTER                        :: ls_scf_env => NULL()
      TYPE(almo_scf_env_type), POINTER                      :: almo_scf_env => NULL()
      TYPE(transport_env_type), POINTER                     :: transport_env => NULL()
      TYPE(cell_type), POINTER                              :: super_cell => NULL()
      TYPE(mo_set_type), DIMENSION(:), POINTER              :: mos => NULL()
      TYPE(cp_fm_type), DIMENSION(:), POINTER               :: mo_loc_history => NULL()
      TYPE(dbcsr_p_type), DIMENSION(:), POINTER             :: mo_derivs => NULL()
      TYPE(scf_control_type), POINTER                       :: scf_control => NULL()
      TYPE(rel_control_type), POINTER                       :: rel_control => NULL()
      ! ZMP adding variables
      TYPE(qs_rho_type), POINTER                            :: rho_external => NULL()
      TYPE(pw_r3d_rs_type), POINTER                         :: external_vxc => NULL()
      TYPE(pw_r3d_rs_type), POINTER                         :: mask => NULL()
      TYPE(qs_charges_type), POINTER                        :: qs_charges => NULL()
      TYPE(qs_ks_env_type), POINTER                         :: ks_env => NULL()
      TYPE(qs_ks_qmmm_env_type), POINTER                    :: ks_qmmm_env => NULL()
      TYPE(qmmm_env_qm_type), POINTER                       :: qmmm_env_qm => NULL()
      TYPE(qs_wf_history_type), POINTER                     :: wf_history => NULL()
      TYPE(qs_scf_env_type), POINTER                        :: scf_env => NULL()
      TYPE(qs_matrix_pools_type), POINTER                   :: mpools => NULL()
      TYPE(oce_matrix_type), POINTER                        :: oce => NULL()
      TYPE(local_rho_type), POINTER                         :: local_rho_set => NULL()
      TYPE(hartree_local_type), POINTER                     :: hartree_local => NULL()
      TYPE(section_vals_type), POINTER                      :: input => NULL()
      TYPE(linres_control_type), POINTER                    :: linres_control => NULL()
      TYPE(xas_environment_type), POINTER                   :: xas_env => NULL()
      TYPE(cp_ddapc_type), POINTER                          :: cp_ddapc_env => NULL()
      TYPE(cp_ddapc_ewald_type), POINTER                    :: cp_ddapc_ewald => NULL()
      REAL(KIND=dp), DIMENSION(:, :), POINTER               :: outer_scf_history => NULL()
      INTEGER                                               :: outer_scf_ihistory = -1
      REAL(KIND=dp), DIMENSION(:, :), POINTER               :: gradient_history => NULL(), &
                                                               variable_history => NULL()
      TYPE(hfx_type), DIMENSION(:, :), POINTER              :: x_data => NULL()
      TYPE(et_coupling_type), POINTER                       :: et_coupling => NULL()
      TYPE(qs_dftb_pairpot_type), DIMENSION(:, :), POINTER  :: dftb_potential => NULL()
      TYPE(admm_type), POINTER                              :: admm_env => NULL()
      TYPE(active_space_type), POINTER                      :: active_space => NULL()
      ! LRI
      TYPE(lri_environment_type), POINTER                   :: lri_env => NULL()
      TYPE(lri_density_type), POINTER                       :: lri_density => NULL()
      ! Harris model
      TYPE(harris_type), POINTER                            :: harris_env => NULL()
      ! Energy correction
      TYPE(energy_correction_type), POINTER                 :: ec_env => NULL()
      ! Excited States
      LOGICAL                                               :: excited_state = .FALSE.
      TYPE(excited_energy_type), POINTER                    :: exstate_env => NULL()
      ! Empirical dispersion
      TYPE(qs_dispersion_type), POINTER                     :: dispersion_env => NULL()
      ! Empirical geometrical BSSE correction
      TYPE(qs_gcp_type), POINTER                            :: gcp_env => NULL()
      ! Semi-empirical and DFTB types
      TYPE(ewald_environment_type), POINTER                 :: ewald_env => NULL()
      TYPE(ewald_pw_type), POINTER                          :: ewald_pw => NULL()
      ! Semi-empirical types
      TYPE(se_taper_type), POINTER                          :: se_taper => NULL()
      TYPE(semi_empirical_si_type), POINTER                 :: se_store_int_env => NULL()
      TYPE(nddo_mpole_type), POINTER                        :: se_nddo_mpole => NULL()
      TYPE(fist_nonbond_env_type), POINTER                  :: se_nonbond_env => NULL()
      TYPE(rt_prop_type), POINTER                           :: rtp => NULL()
      TYPE(efield_berry_type), POINTER                      :: efield => NULL()
      ! a history for the broyden ot
      REAL(KIND=dp)                                         :: broyden_adaptive_sigma = -1.0_dp
      TYPE(mp2_type), POINTER                               :: mp2_env => NULL()
      TYPE(post_scf_bandstructure_type), POINTER                                :: bs_env => NULL()
      TYPE(kg_environment_type), POINTER                    :: kg_env => NULL()
      TYPE(wannier_centres_type), POINTER, DIMENSION(:)     :: WannierCentres => NULL()
      TYPE(molecular_scf_guess_env_type), POINTER           :: molecular_scf_guess_env => NULL()
      ! Subsystem densities
      TYPE(qs_rho_p_type), DIMENSION(:), POINTER            :: subsys_dens => NULL()
      ! Embedding potential
      TYPE(pw_r3d_rs_type), POINTER                         :: embed_pot => NULL()
      TYPE(pw_r3d_rs_type), POINTER                         :: spin_embed_pot => NULL()
      ! Polarizability tensor
      TYPE(polar_env_type), POINTER                         :: polar_env => NULL()
      ! Resp charges
      REAL(KIND=dp), DIMENSION(:), POINTER                  :: rhs => NULL()
      REAL(KIND=dp)                                         :: total_zeff_corr = -1.0_dp, surface_dipole_moment = -1.0_dp
      LOGICAL                                               :: surface_dipole_switch_off = .FALSE.
      TYPE(mo_set_type), DIMENSION(:), POINTER              :: mos_last_converged => NULL()
   END TYPE qs_environment_type

CONTAINS

! **************************************************************************************************
!> \brief   Get the QUICKSTEP environment.
!> \param qs_env ...
!> \param atomic_kind_set ...
!> \param qs_kind_set ...
!> \param cell ...
!> \param super_cell ...
!> \param cell_ref ...
!> \param use_ref_cell ...
!> \param kpoints ...
!> \param dft_control ...
!> \param mos ...
!> \param sab_orb ...
!> \param sab_all ...
!> \param qmmm ...
!> \param qmmm_periodic ...
!> \param sac_ae ...
!> \param sac_ppl ...
!> \param sac_lri ...
!> \param sap_ppnl ...
!> \param sab_vdw ...
!> \param sab_scp ...
!> \param sap_oce ...
!> \param sab_lrc ...
!> \param sab_se ...
!> \param sab_xtbe ...
!> \param sab_tbe ...
!> \param sab_core ...
!> \param sab_xb ...
!> \param sab_xtb_pp ...
!> \param sab_xtb_nonbond ...
!> \param sab_almo ...
!> \param sab_kp ...
!> \param sab_kp_nosym ...
!> \param particle_set ...
!> \param energy ...
!> \param force ...
!> \param matrix_h ...
!> \param matrix_h_im ...
!> \param matrix_ks ...
!> \param matrix_ks_im ...
!> \param matrix_vxc ...
!> \param run_rtp ...
!> \param rtp ...
!> \param matrix_h_kp ...
!> \param matrix_h_im_kp ...
!> \param matrix_ks_kp ...
!> \param matrix_ks_im_kp ...
!> \param matrix_vxc_kp ...
!> \param kinetic_kp ...
!> \param matrix_s_kp ...
!> \param matrix_w_kp ...
!> \param matrix_s_RI_aux_kp ...
!> \param matrix_s ...
!> \param matrix_s_RI_aux ...
!> \param matrix_w ...
!> \param matrix_p_mp2 ...
!> \param matrix_p_mp2_admm ...
!> \param rho ...
!> \param rho_xc ...
!> \param pw_env ...
!> \param ewald_env ...
!> \param ewald_pw ...
!> \param active_space ...
!> \param mpools ...
!> \param input ...
!> \param para_env ...
!> \param blacs_env ...
!> \param scf_control ...
!> \param rel_control ...
!> \param kinetic ...
!> \param qs_charges ...
!> \param vppl ...
!> \param rho_core ...
!> \param rho_nlcc ...
!> \param rho_nlcc_g ...
!> \param ks_env ...
!> \param ks_qmmm_env ...
!> \param wf_history ...
!> \param scf_env ...
!> \param local_particles ...
!> \param local_molecules ...
!> \param distribution_2d ...
!> \param dbcsr_dist ...
!> \param molecule_kind_set ...
!> \param molecule_set ...
!> \param subsys ...
!> \param cp_subsys ...
!> \param oce ...
!> \param local_rho_set ...
!> \param rho_atom_set ...
!> \param task_list ...
!> \param task_list_soft ...
!> \param rho0_atom_set ...
!> \param rho0_mpole ...
!> \param rhoz_set ...
!> \param ecoul_1c ...
!> \param rho0_s_rs ...
!> \param rho0_s_gs ...
!> \param do_kpoints ...
!> \param has_unit_metric ...
!> \param requires_mo_derivs ...
!> \param mo_derivs ...
!> \param mo_loc_history ...
!> \param nkind ...
!> \param natom ...
!> \param nelectron_total ...
!> \param nelectron_spin ...
!> \param efield ...
!> \param neighbor_list_id ...
!> \param linres_control ...
!> \param xas_env ...
!> \param virial ...
!> \param cp_ddapc_env ...
!> \param cp_ddapc_ewald ...
!> \param outer_scf_history ...
!> \param outer_scf_ihistory ...
!> \param x_data ...
!> \param et_coupling ...
!> \param dftb_potential ...
!> \param results ...
!> \param se_taper ...
!> \param se_store_int_env ...
!> \param se_nddo_mpole ...
!> \param se_nonbond_env ...
!> \param admm_env ...
!> \param lri_env ...
!> \param lri_density ...
!> \param exstate_env ...
!> \param ec_env ...
!> \param harris_env ...
!> \param dispersion_env ...
!> \param gcp_env ...
!> \param vee ...
!> \param rho_external ...
!> \param external_vxc ...
!> \param mask ...
!> \param mp2_env ...
!> \param bs_env ...
!> \param kg_env ...
!> \param WannierCentres ...
!> \param atprop ...
!> \param ls_scf_env ...
!> \param do_transport ...
!> \param transport_env ...
!> \param v_hartree_rspace ...
!> \param s_mstruct_changed ...
!> \param rho_changed ...
!> \param potential_changed ...
!> \param forces_up_to_date ...
!> \param mscfg_env ...
!> \param almo_scf_env ...
!> \param gradient_history ...
!> \param variable_history ...
!> \param embed_pot ...
!> \param spin_embed_pot ...
!> \param polar_env ...
!> \param mos_last_converged ... [SGh]
!> \param rhs ...
!> \date    23.01.2002
!> \author  MK
!> \version 1.0
! **************************************************************************************************
   SUBROUTINE get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, &
                         dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, sac_ae, sac_ppl, sac_lri, &
                         sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, &
                         sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, &
                         sab_kp, sab_kp_nosym, particle_set, energy, force, &
                         matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, &
                         matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, &
                         matrix_w_kp, matrix_s_RI_aux_kp, matrix_s, matrix_s_RI_aux, matrix_w, &
                         matrix_p_mp2, matrix_p_mp2_admm, rho, &
                         rho_xc, pw_env, ewald_env, ewald_pw, active_space, &
                         mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, &
                         vppl, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, &
                         local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, &
                         molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, &
                         task_list, &
                         task_list_soft, &
                         rho0_atom_set, rho0_mpole, rhoz_set, ecoul_1c, &
                         rho0_s_rs, rho0_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, &
                         mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, &
                         neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, &
                         outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, &
                         se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, &
                         lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, &
                         rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, &
                         WannierCentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, &
                         s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, &
                         gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, rhs)
      TYPE(qs_environment_type), INTENT(IN)              :: qs_env
      TYPE(atomic_kind_type), DIMENSION(:), OPTIONAL, &
         POINTER                                         :: atomic_kind_set
      TYPE(qs_kind_type), DIMENSION(:), OPTIONAL, &
         POINTER                                         :: qs_kind_set
      TYPE(cell_type), OPTIONAL, POINTER                 :: cell, super_cell, cell_ref
      LOGICAL, OPTIONAL                                  :: use_ref_cell
      TYPE(kpoint_type), OPTIONAL, POINTER               :: kpoints
      TYPE(dft_control_type), OPTIONAL, POINTER          :: dft_control
      TYPE(mo_set_type), DIMENSION(:), OPTIONAL, POINTER :: mos
      TYPE(neighbor_list_set_p_type), DIMENSION(:), &
         OPTIONAL, POINTER                               :: sab_orb, sab_all
      LOGICAL, OPTIONAL                                  :: qmmm, qmmm_periodic
      TYPE(neighbor_list_set_p_type), DIMENSION(:), OPTIONAL, POINTER :: sac_ae, sac_ppl, sac_lri, &
         sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, &
         sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym
      TYPE(particle_type), DIMENSION(:), OPTIONAL, &
         POINTER                                         :: particle_set
      TYPE(qs_energy_type), OPTIONAL, POINTER            :: energy
      TYPE(qs_force_type), DIMENSION(:), OPTIONAL, &
         POINTER                                         :: force
      TYPE(dbcsr_p_type), DIMENSION(:), OPTIONAL, &
         POINTER                                         :: matrix_h, matrix_h_im, matrix_ks, &
                                                            matrix_ks_im, matrix_vxc
      LOGICAL, OPTIONAL                                  :: run_rtp
      TYPE(rt_prop_type), OPTIONAL, POINTER              :: rtp
      TYPE(dbcsr_p_type), DIMENSION(:, :), OPTIONAL, POINTER :: matrix_h_kp, matrix_h_im_kp, &
         matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, &
         matrix_s_RI_aux_kp
      TYPE(dbcsr_p_type), DIMENSION(:), OPTIONAL, &
         POINTER                                         :: matrix_s, matrix_s_RI_aux, matrix_w, &
                                                            matrix_p_mp2, matrix_p_mp2_admm
      TYPE(qs_rho_type), OPTIONAL, POINTER               :: rho, rho_xc
      TYPE(pw_env_type), OPTIONAL, POINTER               :: pw_env
      TYPE(ewald_environment_type), OPTIONAL, POINTER    :: ewald_env
      TYPE(ewald_pw_type), OPTIONAL, POINTER             :: ewald_pw
      TYPE(active_space_type), OPTIONAL, POINTER         :: active_space
      TYPE(qs_matrix_pools_type), OPTIONAL, POINTER      :: mpools
      TYPE(section_vals_type), OPTIONAL, POINTER         :: input
      TYPE(mp_para_env_type), OPTIONAL, POINTER          :: para_env
      TYPE(cp_blacs_env_type), OPTIONAL, POINTER         :: blacs_env
      TYPE(scf_control_type), OPTIONAL, POINTER          :: scf_control
      TYPE(rel_control_type), OPTIONAL, POINTER          :: rel_control
      TYPE(dbcsr_p_type), DIMENSION(:), OPTIONAL, &
         POINTER                                         :: kinetic
      TYPE(qs_charges_type), OPTIONAL, POINTER           :: qs_charges
      TYPE(pw_r3d_rs_type), OPTIONAL, POINTER            :: vppl
      TYPE(pw_c1d_gs_type), OPTIONAL, POINTER            :: rho_core
      TYPE(pw_r3d_rs_type), OPTIONAL, POINTER            :: rho_nlcc
      TYPE(pw_c1d_gs_type), OPTIONAL, POINTER            :: rho_nlcc_g
      TYPE(qs_ks_env_type), OPTIONAL, POINTER            :: ks_env
      TYPE(qs_ks_qmmm_env_type), OPTIONAL, POINTER       :: ks_qmmm_env
      TYPE(qs_wf_history_type), OPTIONAL, POINTER        :: wf_history
      TYPE(qs_scf_env_type), OPTIONAL, POINTER           :: scf_env
      TYPE(distribution_1d_type), OPTIONAL, POINTER      :: local_particles, local_molecules
      TYPE(distribution_2d_type), OPTIONAL, POINTER      :: distribution_2d
      TYPE(dbcsr_distribution_type), OPTIONAL, POINTER   :: dbcsr_dist
      TYPE(molecule_kind_type), DIMENSION(:), OPTIONAL, &
         POINTER                                         :: molecule_kind_set
      TYPE(molecule_type), DIMENSION(:), OPTIONAL, &
         POINTER                                         :: molecule_set
      TYPE(qs_subsys_type), OPTIONAL, POINTER            :: subsys
      TYPE(cp_subsys_type), OPTIONAL, POINTER            :: cp_subsys
      TYPE(oce_matrix_type), OPTIONAL, POINTER           :: oce
      TYPE(local_rho_type), OPTIONAL, POINTER            :: local_rho_set
      TYPE(rho_atom_type), DIMENSION(:), OPTIONAL, &
         POINTER                                         :: rho_atom_set
      TYPE(task_list_type), OPTIONAL, POINTER            :: task_list, task_list_soft
      TYPE(rho0_atom_type), DIMENSION(:), OPTIONAL, &
         POINTER                                         :: rho0_atom_set
      TYPE(rho0_mpole_type), OPTIONAL, POINTER           :: rho0_mpole
      TYPE(rhoz_type), DIMENSION(:), OPTIONAL, POINTER   :: rhoz_set
      TYPE(ecoul_1center_type), DIMENSION(:), OPTIONAL, &
         POINTER                                         :: ecoul_1c
      TYPE(pw_r3d_rs_type), OPTIONAL, POINTER            :: rho0_s_rs
      TYPE(pw_c1d_gs_type), OPTIONAL, POINTER            :: rho0_s_gs
      LOGICAL, OPTIONAL                                  :: do_kpoints, has_unit_metric, &
                                                            requires_mo_derivs
      TYPE(dbcsr_p_type), DIMENSION(:), OPTIONAL, &
         POINTER                                         :: mo_derivs
      TYPE(cp_fm_type), DIMENSION(:), OPTIONAL, POINTER  :: mo_loc_history
      INTEGER, OPTIONAL                                  :: nkind, natom, nelectron_total
      INTEGER, DIMENSION(2), OPTIONAL                    :: nelectron_spin
      TYPE(efield_berry_type), OPTIONAL, POINTER         :: efield
      INTEGER, OPTIONAL                                  :: neighbor_list_id
      TYPE(linres_control_type), OPTIONAL, POINTER       :: linres_control
      TYPE(xas_environment_type), OPTIONAL, POINTER      :: xas_env
      TYPE(virial_type), OPTIONAL, POINTER               :: virial
      TYPE(cp_ddapc_type), OPTIONAL, POINTER             :: cp_ddapc_env
      TYPE(cp_ddapc_ewald_type), OPTIONAL, POINTER       :: cp_ddapc_ewald
      REAL(KIND=dp), DIMENSION(:, :), OPTIONAL, POINTER  :: outer_scf_history
      INTEGER, INTENT(out), OPTIONAL                     :: outer_scf_ihistory
      TYPE(hfx_type), DIMENSION(:, :), OPTIONAL, POINTER :: x_data
      TYPE(et_coupling_type), OPTIONAL, POINTER          :: et_coupling
      TYPE(qs_dftb_pairpot_type), DIMENSION(:, :), &
         OPTIONAL, POINTER                               :: dftb_potential
      TYPE(cp_result_type), OPTIONAL, POINTER            :: results
      TYPE(se_taper_type), OPTIONAL, POINTER             :: se_taper
      TYPE(semi_empirical_si_type), OPTIONAL, POINTER    :: se_store_int_env
      TYPE(nddo_mpole_type), OPTIONAL, POINTER           :: se_nddo_mpole
      TYPE(fist_nonbond_env_type), OPTIONAL, POINTER     :: se_nonbond_env
      TYPE(admm_type), OPTIONAL, POINTER                 :: admm_env
      TYPE(lri_environment_type), OPTIONAL, POINTER      :: lri_env
      TYPE(lri_density_type), OPTIONAL, POINTER          :: lri_density
      TYPE(excited_energy_type), OPTIONAL, POINTER       :: exstate_env
      TYPE(energy_correction_type), OPTIONAL, POINTER    :: ec_env
      TYPE(harris_type), OPTIONAL, POINTER               :: harris_env
      TYPE(qs_dispersion_type), OPTIONAL, POINTER        :: dispersion_env
      TYPE(qs_gcp_type), OPTIONAL, POINTER               :: gcp_env
      TYPE(pw_r3d_rs_type), OPTIONAL, POINTER            :: vee
      TYPE(qs_rho_type), OPTIONAL, POINTER               :: rho_external
      TYPE(pw_r3d_rs_type), OPTIONAL, POINTER            :: external_vxc, mask
      TYPE(mp2_type), OPTIONAL, POINTER                  :: mp2_env
      TYPE(post_scf_bandstructure_type), OPTIONAL, &
         POINTER                                         :: bs_env
      TYPE(kg_environment_type), OPTIONAL, POINTER       :: kg_env
      TYPE(wannier_centres_type), DIMENSION(:), &
         OPTIONAL, POINTER                               :: WannierCentres
      TYPE(atprop_type), OPTIONAL, POINTER               :: atprop
      TYPE(ls_scf_env_type), OPTIONAL, POINTER           :: ls_scf_env
      LOGICAL, OPTIONAL                                  :: do_transport
      TYPE(transport_env_type), OPTIONAL, POINTER        :: transport_env
      TYPE(pw_r3d_rs_type), OPTIONAL, POINTER            :: v_hartree_rspace
      LOGICAL, OPTIONAL                                  :: s_mstruct_changed, rho_changed, &
                                                            potential_changed, forces_up_to_date
      TYPE(molecular_scf_guess_env_type), OPTIONAL, &
         POINTER                                         :: mscfg_env
      TYPE(almo_scf_env_type), OPTIONAL, POINTER         :: almo_scf_env
      REAL(KIND=dp), DIMENSION(:, :), OPTIONAL, POINTER  :: gradient_history, variable_history
      TYPE(pw_r3d_rs_type), OPTIONAL, POINTER            :: embed_pot, spin_embed_pot
      TYPE(polar_env_type), OPTIONAL, POINTER            :: polar_env
      TYPE(mo_set_type), DIMENSION(:), OPTIONAL, POINTER :: mos_last_converged
      REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: rhs

      TYPE(rho0_mpole_type), POINTER                     :: rho0_m

      NULLIFY (rho0_m)
      CPASSERT(ASSOCIATED(qs_env%ks_env))

      IF (PRESENT(outer_scf_history)) outer_scf_history => qs_env%outer_scf_history
      IF (PRESENT(outer_scf_ihistory)) outer_scf_ihistory = qs_env%outer_scf_ihistory
      IF (PRESENT(gradient_history)) gradient_history => qs_env%gradient_history
      IF (PRESENT(variable_history)) variable_history => qs_env%variable_history
      IF (PRESENT(mp2_env)) mp2_env => qs_env%mp2_env
      IF (PRESENT(bs_env)) bs_env => qs_env%bs_env
      IF (PRESENT(kg_env)) kg_env => qs_env%kg_env
      IF (PRESENT(super_cell)) super_cell => qs_env%super_cell
      IF (PRESENT(qmmm)) qmmm = qs_env%qmmm
      IF (PRESENT(qmmm_periodic)) qmmm_periodic = qs_env%qmmm_periodic
      IF (PRESENT(mos)) mos => qs_env%mos
      IF (PRESENT(mos_last_converged)) mos_last_converged => qs_env%mos_last_converged
      IF (PRESENT(ewald_env)) ewald_env => qs_env%ewald_env
      IF (PRESENT(ewald_pw)) ewald_pw => qs_env%ewald_pw
      IF (PRESENT(mpools)) mpools => qs_env%mpools
      IF (PRESENT(scf_control)) scf_control => qs_env%scf_control
      IF (PRESENT(rel_control)) rel_control => qs_env%rel_control
      ! ZMP pointing vectors
      IF (PRESENT(rho_external)) rho_external => qs_env%rho_external
      IF (PRESENT(external_vxc)) external_vxc => qs_env%external_vxc
      IF (PRESENT(mask)) mask => qs_env%mask
      IF (PRESENT(qs_charges)) qs_charges => qs_env%qs_charges
      IF (PRESENT(ks_env)) ks_env => qs_env%ks_env
      IF (PRESENT(ks_qmmm_env)) ks_qmmm_env => qs_env%ks_qmmm_env
      IF (PRESENT(wf_history)) wf_history => qs_env%wf_history
      IF (PRESENT(scf_env)) scf_env => qs_env%scf_env
      IF (PRESENT(oce)) oce => qs_env%oce
      IF (PRESENT(requires_mo_derivs)) requires_mo_derivs = qs_env%requires_mo_derivs
      IF (PRESENT(has_unit_metric)) has_unit_metric = qs_env%has_unit_metric
      IF (PRESENT(mo_derivs)) mo_derivs => qs_env%mo_derivs
      IF (PRESENT(mo_loc_history)) mo_loc_history => qs_env%mo_loc_history
      IF (PRESENT(linres_control)) linres_control => qs_env%linres_control
      IF (PRESENT(se_taper)) se_taper => qs_env%se_taper
      IF (PRESENT(se_store_int_env)) se_store_int_env => qs_env%se_store_int_env
      IF (PRESENT(se_nddo_mpole)) se_nddo_mpole => qs_env%se_nddo_mpole
      IF (PRESENT(se_nonbond_env)) se_nonbond_env => qs_env%se_nonbond_env
      IF (PRESENT(lri_env)) lri_env => qs_env%lri_env
      IF (PRESENT(lri_density)) lri_density => qs_env%lri_density
      IF (PRESENT(harris_env)) harris_env => qs_env%harris_env
      IF (PRESENT(ec_env)) ec_env => qs_env%ec_env
      IF (PRESENT(exstate_env)) exstate_env => qs_env%exstate_env
      IF (PRESENT(dispersion_env)) dispersion_env => qs_env%dispersion_env
      IF (PRESENT(gcp_env)) gcp_env => qs_env%gcp_env
      IF (PRESENT(run_rtp)) run_rtp = qs_env%run_rtp
      IF (PRESENT(rtp)) rtp => qs_env%rtp
      IF (PRESENT(ls_scf_env)) ls_scf_env => qs_env%ls_scf_env
      IF (PRESENT(almo_scf_env)) almo_scf_env => qs_env%almo_scf_env
      IF (PRESENT(do_transport)) do_transport = qs_env%do_transport
      IF (PRESENT(transport_env)) transport_env => qs_env%transport_env
      IF (PRESENT(mscfg_env)) mscfg_env => qs_env%molecular_scf_guess_env
      IF (PRESENT(active_space)) active_space => qs_env%active_space
      IF (PRESENT(admm_env)) admm_env => qs_env%admm_env

      ! Embedding potential
      IF (PRESENT(embed_pot)) embed_pot => qs_env%embed_pot
      IF (PRESENT(spin_embed_pot)) spin_embed_pot => qs_env%spin_embed_pot

      ! Polarisability tensor
      IF (PRESENT(polar_env)) polar_env => qs_env%polar_env

      ! Resp charges
      IF (PRESENT(rhs)) rhs => qs_env%rhs

      IF (PRESENT(local_rho_set)) &
         local_rho_set => qs_env%local_rho_set
      IF (PRESENT(rho_atom_set)) &
         CALL get_local_rho(qs_env%local_rho_set, rho_atom_set=rho_atom_set)
      IF (PRESENT(rho0_atom_set)) &
         CALL get_local_rho(qs_env%local_rho_set, rho0_atom_set=rho0_atom_set)
      IF (PRESENT(rho0_mpole)) &
         CALL get_local_rho(qs_env%local_rho_set, rho0_mpole=rho0_mpole)
      IF (PRESENT(rhoz_set)) &
         CALL get_local_rho(qs_env%local_rho_set, rhoz_set=rhoz_set)
      IF (PRESENT(ecoul_1c)) &
         CALL get_hartree_local(qs_env%hartree_local, ecoul_1c=ecoul_1c)
      IF (PRESENT(rho0_s_rs)) THEN
         CALL get_local_rho(qs_env%local_rho_set, rho0_mpole=rho0_m)
         IF (ASSOCIATED(rho0_m)) THEN
            rho0_s_rs => rho0_m%rho0_s_rs
         END IF
      END IF
      IF (PRESENT(rho0_s_gs)) THEN
         CALL get_local_rho(qs_env%local_rho_set, rho0_mpole=rho0_m)
         IF (ASSOCIATED(rho0_m)) THEN
            rho0_s_gs => rho0_m%rho0_s_gs
         END IF
      END IF

      IF (PRESENT(xas_env)) xas_env => qs_env%xas_env
      IF (PRESENT(input)) input => qs_env%input
      IF (PRESENT(cp_ddapc_env)) cp_ddapc_env => qs_env%cp_ddapc_env
      IF (PRESENT(cp_ddapc_ewald)) cp_ddapc_ewald => qs_env%cp_ddapc_ewald
      IF (PRESENT(x_data)) x_data => qs_env%x_data
      IF (PRESENT(et_coupling)) et_coupling => qs_env%et_coupling
      IF (PRESENT(dftb_potential)) dftb_potential => qs_env%dftb_potential
      IF (PRESENT(efield)) efield => qs_env%efield
      IF (PRESENT(WannierCentres)) WannierCentres => qs_env%WannierCentres

      CALL get_ks_env(qs_env%ks_env, &
                      v_hartree_rspace=v_hartree_rspace, &
                      s_mstruct_changed=s_mstruct_changed, &
                      rho_changed=rho_changed, &
                      potential_changed=potential_changed, &
                      forces_up_to_date=forces_up_to_date, &
                      matrix_h=matrix_h, &
                      matrix_h_im=matrix_h_im, &
                      matrix_ks=matrix_ks, &
                      matrix_ks_im=matrix_ks_im, &
                      matrix_vxc=matrix_vxc, &
                      kinetic=kinetic, &
                      matrix_s=matrix_s, &
                      matrix_s_RI_aux=matrix_s_RI_aux, &
                      matrix_ks_im_kp=matrix_ks_im_kp, &
                      matrix_w=matrix_w, &
                      matrix_p_mp2=matrix_p_mp2, &
                      matrix_p_mp2_admm=matrix_p_mp2_admm, &
                      matrix_h_kp=matrix_h_kp, &
                      matrix_h_im_kp=matrix_h_im_kp, &
                      matrix_ks_kp=matrix_ks_kp, &
                      matrix_vxc_kp=matrix_vxc_kp, &
                      kinetic_kp=kinetic_kp, &
                      matrix_s_kp=matrix_s_kp, &
                      matrix_w_kp=matrix_w_kp, &
                      matrix_s_RI_aux_kp=matrix_s_RI_aux_kp, &
                      rho=rho, &
                      rho_xc=rho_xc, &
                      rho_core=rho_core, &
                      rho_nlcc=rho_nlcc, &
                      rho_nlcc_g=rho_nlcc_g, &
                      vppl=vppl, &
                      vee=vee, &
                      neighbor_list_id=neighbor_list_id, &
                      sab_orb=sab_orb, &
                      sab_all=sab_all, &
                      sab_scp=sab_scp, &
                      sab_vdw=sab_vdw, &
                      sac_ae=sac_ae, &
                      sac_ppl=sac_ppl, &
                      sac_lri=sac_lri, &
                      sap_ppnl=sap_ppnl, &
                      sap_oce=sap_oce, &
                      sab_se=sab_se, &
                      sab_lrc=sab_lrc, &
                      sab_tbe=sab_tbe, &
                      sab_xtbe=sab_xtbe, &
                      sab_core=sab_core, &
                      sab_xb=sab_xb, &
                      sab_xtb_pp=sab_xtb_pp, &
                      sab_xtb_nonbond=sab_xtb_nonbond, &
                      sab_almo=sab_almo, &
                      sab_kp=sab_kp, &
                      sab_kp_nosym=sab_kp_nosym, &
                      task_list=task_list, &
                      task_list_soft=task_list_soft, &
                      kpoints=kpoints, &
                      do_kpoints=do_kpoints, &
                      local_molecules=local_molecules, &
                      local_particles=local_particles, &
                      atprop=atprop, &
                      virial=virial, &
                      results=results, &
                      cell=cell, &
                      cell_ref=cell_ref, &
                      use_ref_cell=use_ref_cell, &
                      energy=energy, &
                      force=force, &
                      qs_kind_set=qs_kind_set, &
                      subsys=subsys, &
                      cp_subsys=cp_subsys, &
                      atomic_kind_set=atomic_kind_set, &
                      particle_set=particle_set, &
                      molecule_kind_set=molecule_kind_set, &
                      molecule_set=molecule_set, &
                      natom=natom, &
                      nkind=nkind, &
                      dft_control=dft_control, &
                      dbcsr_dist=dbcsr_dist, &
                      distribution_2d=distribution_2d, &
                      pw_env=pw_env, &
                      para_env=para_env, &
                      blacs_env=blacs_env, &
                      nelectron_total=nelectron_total, &
                      nelectron_spin=nelectron_spin)

   END SUBROUTINE get_qs_env

! **************************************************************************************************
!> \brief  Initialise the QUICKSTEP environment.
!> \param qs_env ...
!> \param globenv ...
!> \date    25.01.2002
!> \author  MK
!> \version 1.0
! **************************************************************************************************
   SUBROUTINE init_qs_env(qs_env, globenv)

      TYPE(qs_environment_type), INTENT(INOUT)           :: qs_env
      TYPE(global_environment_type), OPTIONAL, POINTER   :: globenv

      NULLIFY (qs_env%ls_scf_env)
      NULLIFY (qs_env%almo_scf_env)
      NULLIFY (qs_env%transport_env)
      NULLIFY (qs_env%image_matrix)
      NULLIFY (qs_env%ipiv)
      NULLIFY (qs_env%image_coeff)
      NULLIFY (qs_env%super_cell)
      NULLIFY (qs_env%mos)
      NULLIFY (qs_env%mos_last_converged)
      NULLIFY (qs_env%mpools)
      NULLIFY (qs_env%ewald_env)
      NULLIFY (qs_env%ewald_pw)
      NULLIFY (qs_env%scf_control)
      NULLIFY (qs_env%rel_control)
      NULLIFY (qs_env%qs_charges)
      ! ZMP initializing arrays
      NULLIFY (qs_env%rho_external)
      NULLIFY (qs_env%external_vxc)
      NULLIFY (qs_env%mask)
      ! Embedding potential
      NULLIFY (qs_env%embed_pot)
      NULLIFY (qs_env%spin_embed_pot)

      ! Polarisability tensor
      NULLIFY (qs_env%polar_env)

      NULLIFY (qs_env%ks_env)
      NULLIFY (qs_env%ks_qmmm_env)
      NULLIFY (qs_env%wf_history)
      NULLIFY (qs_env%scf_env)
      NULLIFY (qs_env%oce)
      NULLIFY (qs_env%local_rho_set)
      NULLIFY (qs_env%hartree_local)
      NULLIFY (qs_env%input)
      NULLIFY (qs_env%linres_control)
      NULLIFY (qs_env%xas_env)
      NULLIFY (qs_env%cp_ddapc_env)
      NULLIFY (qs_env%cp_ddapc_ewald)
      NULLIFY (qs_env%outer_scf_history)
      NULLIFY (qs_env%gradient_history)
      NULLIFY (qs_env%variable_history)
      NULLIFY (qs_env%x_data)
      NULLIFY (qs_env%et_coupling)
      NULLIFY (qs_env%dftb_potential)
      NULLIFY (qs_env%active_space)

      NULLIFY (qs_env%se_taper)
      NULLIFY (qs_env%se_store_int_env)
      NULLIFY (qs_env%se_nddo_mpole)
      NULLIFY (qs_env%se_nonbond_env)
      NULLIFY (qs_env%admm_env)
      NULLIFY (qs_env%efield)
      NULLIFY (qs_env%lri_env)
      NULLIFY (qs_env%harris_env)
      NULLIFY (qs_env%ec_env)
      NULLIFY (qs_env%exstate_env)
      NULLIFY (qs_env%lri_density)
      NULLIFY (qs_env%gcp_env)
      NULLIFY (qs_env%rtp)
      NULLIFY (qs_env%mp2_env)
      NULLIFY (qs_env%bs_env)
      NULLIFY (qs_env%kg_env)
      NULLIFY (qs_env%WannierCentres)

      qs_env%outer_scf_ihistory = 0
      qs_env%broyden_adaptive_sigma = -1.0_dp

      CALL local_rho_set_create(qs_env%local_rho_set)
      CALL hartree_local_create(qs_env%hartree_local)
      qs_env%run_rtp = .FALSE.
      qs_env%linres_run = .FALSE.
      qs_env%single_point_run = .FALSE.
      qs_env%qmmm = .FALSE.
      qs_env%qmmm_periodic = .FALSE.
      qs_env%requires_mo_derivs = .FALSE.
      qs_env%requires_matrix_vxc = .FALSE.
      qs_env%has_unit_metric = .FALSE.
      qs_env%calc_image_preconditioner = .TRUE.
      qs_env%do_transport = .FALSE.
      qs_env%given_embed_pot = .FALSE.
      IF (PRESENT(globenv)) THEN
         qs_env%target_time = globenv%cp2k_target_time
         qs_env%start_time = globenv%cp2k_start_time
         qs_env%single_point_run = (globenv%run_type_id == energy_run .OR. &
                                    globenv%run_type_id == energy_force_run)
      ELSE
         qs_env%target_time = 0.0_dp
         qs_env%start_time = 0.0_dp
      END IF

      qs_env%sim_time = 0._dp
      qs_env%sim_step = 0

      qs_env%total_zeff_corr = 0.0_dp
      qs_env%surface_dipole_moment = 0.0_dp
      qs_env%surface_dipole_switch_off = .FALSE.

      ! Zero all variables containing results
      NULLIFY (qs_env%mo_derivs)
      NULLIFY (qs_env%mo_loc_history)

      IF (.NOT. ASSOCIATED(qs_env%molecular_scf_guess_env)) ALLOCATE (qs_env%molecular_scf_guess_env)

   END SUBROUTINE init_qs_env

! **************************************************************************************************
!> \brief   Set the QUICKSTEP environment.
!> \param qs_env ...
!> \param super_cell ...
!> \param mos ...
!> \param qmmm ...
!> \param qmmm_periodic ...
!> \param ewald_env ...
!> \param ewald_pw ...
!> \param mpools ...
!> \param rho_external ...
!> \param external_vxc ...
!> \param mask ...
!> \param scf_control ...
!> \param rel_control ...
!> \param qs_charges ...
!> \param ks_env ...
!> \param ks_qmmm_env ...
!> \param wf_history ...
!> \param scf_env ...
!> \param active_space ...
!> \param input ...
!> \param oce ...
!> \param rho_atom_set ...
!> \param rho0_atom_set ...
!> \param rho0_mpole ...
!> \param run_rtp ...
!> \param rtp ...
!> \param rhoz_set ...
!> \param rhoz_tot ...
!> \param ecoul_1c ...
!> \param has_unit_metric ...
!> \param requires_mo_derivs ...
!> \param mo_derivs ...
!> \param mo_loc_history ...
!> \param efield ...
!> \param linres_control ...
!> \param xas_env ...
!> \param cp_ddapc_env ...
!> \param cp_ddapc_ewald ...
!> \param outer_scf_history ...
!> \param outer_scf_ihistory ...
!> \param x_data ...
!> \param et_coupling ...
!> \param dftb_potential ...
!> \param se_taper ...
!> \param se_store_int_env ...
!> \param se_nddo_mpole ...
!> \param se_nonbond_env ...
!> \param admm_env ...
!> \param ls_scf_env ...
!> \param do_transport ...
!> \param transport_env ...
!> \param lri_env ...
!> \param lri_density ...
!> \param exstate_env ...
!> \param ec_env ...
!> \param dispersion_env ...
!> \param harris_env ...
!> \param gcp_env ...
!> \param mp2_env ...
!> \param bs_env ...
!> \param kg_env ...
!> \param force ...
!> \param kpoints ...
!> \param WannierCentres ...
!> \param almo_scf_env ...
!> \param gradient_history ...
!> \param variable_history ...
!> \param embed_pot ...
!> \param spin_embed_pot ...
!> \param polar_env ...
!> \param mos_last_converged ... [SGh]
!> \param rhs ...
!> \date    23.01.2002
!> \author  MK
!> \version 1.0
! **************************************************************************************************
   SUBROUTINE set_qs_env(qs_env, super_cell, &
                         mos, qmmm, qmmm_periodic, &
                         ewald_env, ewald_pw, mpools, &
                         rho_external, external_vxc, mask, &
                         scf_control, rel_control, qs_charges, ks_env, &
                         ks_qmmm_env, wf_history, scf_env, active_space, &
                         input, oce, rho_atom_set, rho0_atom_set, rho0_mpole, run_rtp, rtp, &
                         rhoz_set, rhoz_tot, ecoul_1c, has_unit_metric, requires_mo_derivs, mo_derivs, &
                         mo_loc_history, efield, &
                         linres_control, xas_env, cp_ddapc_env, cp_ddapc_ewald, &
                         outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, &
                         se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, ls_scf_env, &
                         do_transport, transport_env, lri_env, lri_density, exstate_env, ec_env, dispersion_env, &
                         harris_env, gcp_env, mp2_env, bs_env, kg_env, force, &
                         kpoints, WannierCentres, almo_scf_env, gradient_history, variable_history, embed_pot, &
                         spin_embed_pot, polar_env, mos_last_converged, rhs)

      TYPE(qs_environment_type), INTENT(INOUT)           :: qs_env
      TYPE(cell_type), OPTIONAL, POINTER                 :: super_cell
      TYPE(mo_set_type), DIMENSION(:), OPTIONAL, POINTER :: mos
      LOGICAL, OPTIONAL                                  :: qmmm, qmmm_periodic
      TYPE(ewald_environment_type), OPTIONAL, POINTER    :: ewald_env
      TYPE(ewald_pw_type), OPTIONAL, POINTER             :: ewald_pw
      TYPE(qs_matrix_pools_type), OPTIONAL, POINTER      :: mpools
      TYPE(qs_rho_type), OPTIONAL, POINTER               :: rho_external
      TYPE(pw_r3d_rs_type), OPTIONAL, POINTER            :: external_vxc, mask
      TYPE(scf_control_type), OPTIONAL, POINTER          :: scf_control
      TYPE(rel_control_type), OPTIONAL, POINTER          :: rel_control
      TYPE(qs_charges_type), OPTIONAL, POINTER           :: qs_charges
      TYPE(qs_ks_env_type), OPTIONAL, POINTER            :: ks_env
      TYPE(qs_ks_qmmm_env_type), OPTIONAL, POINTER       :: ks_qmmm_env
      TYPE(qs_wf_history_type), OPTIONAL, POINTER        :: wf_history
      TYPE(qs_scf_env_type), OPTIONAL, POINTER           :: scf_env
      TYPE(active_space_type), OPTIONAL, POINTER         :: active_space
      TYPE(section_vals_type), OPTIONAL, POINTER         :: input
      TYPE(oce_matrix_type), OPTIONAL, POINTER           :: oce
      TYPE(rho_atom_type), DIMENSION(:), OPTIONAL, &
         POINTER                                         :: rho_atom_set
      TYPE(rho0_atom_type), DIMENSION(:), OPTIONAL, &
         POINTER                                         :: rho0_atom_set
      TYPE(rho0_mpole_type), OPTIONAL, POINTER           :: rho0_mpole
      LOGICAL, OPTIONAL                                  :: run_rtp
      TYPE(rt_prop_type), OPTIONAL, POINTER              :: rtp
      TYPE(rhoz_type), DIMENSION(:), OPTIONAL, POINTER   :: rhoz_set
      REAL(dp), OPTIONAL                                 :: rhoz_tot
      TYPE(ecoul_1center_type), DIMENSION(:), OPTIONAL, &
         POINTER                                         :: ecoul_1c
      LOGICAL, OPTIONAL                                  :: has_unit_metric, requires_mo_derivs
      TYPE(dbcsr_p_type), DIMENSION(:), OPTIONAL, &
         POINTER                                         :: mo_derivs
      TYPE(cp_fm_type), DIMENSION(:), OPTIONAL, POINTER  :: mo_loc_history
      TYPE(efield_berry_type), OPTIONAL, POINTER         :: efield
      TYPE(linres_control_type), OPTIONAL, POINTER       :: linres_control
      TYPE(xas_environment_type), OPTIONAL, POINTER      :: xas_env
      TYPE(cp_ddapc_type), OPTIONAL, POINTER             :: cp_ddapc_env
      TYPE(cp_ddapc_ewald_type), OPTIONAL, POINTER       :: cp_ddapc_ewald
      REAL(KIND=dp), DIMENSION(:, :), OPTIONAL, POINTER  :: outer_scf_history
      INTEGER, INTENT(IN), OPTIONAL                      :: outer_scf_ihistory
      TYPE(hfx_type), DIMENSION(:, :), OPTIONAL, POINTER :: x_data
      TYPE(et_coupling_type), OPTIONAL, POINTER          :: et_coupling
      TYPE(qs_dftb_pairpot_type), DIMENSION(:, :), &
         OPTIONAL, POINTER                               :: dftb_potential
      TYPE(se_taper_type), OPTIONAL, POINTER             :: se_taper
      TYPE(semi_empirical_si_type), OPTIONAL, POINTER    :: se_store_int_env
      TYPE(nddo_mpole_type), OPTIONAL, POINTER           :: se_nddo_mpole
      TYPE(fist_nonbond_env_type), OPTIONAL, POINTER     :: se_nonbond_env
      TYPE(admm_type), OPTIONAL, POINTER                 :: admm_env
      TYPE(ls_scf_env_type), OPTIONAL, POINTER           :: ls_scf_env
      LOGICAL, OPTIONAL                                  :: do_transport
      TYPE(transport_env_type), OPTIONAL, POINTER        :: transport_env
      TYPE(lri_environment_type), OPTIONAL, POINTER      :: lri_env
      TYPE(lri_density_type), OPTIONAL, POINTER          :: lri_density
      TYPE(excited_energy_type), OPTIONAL, POINTER       :: exstate_env
      TYPE(energy_correction_type), OPTIONAL, POINTER    :: ec_env
      TYPE(qs_dispersion_type), OPTIONAL, POINTER        :: dispersion_env
      TYPE(harris_type), OPTIONAL, POINTER               :: harris_env
      TYPE(qs_gcp_type), OPTIONAL, POINTER               :: gcp_env
      TYPE(mp2_type), OPTIONAL, POINTER                  :: mp2_env
      TYPE(post_scf_bandstructure_type), OPTIONAL, &
         POINTER                                         :: bs_env
      TYPE(kg_environment_type), OPTIONAL, POINTER       :: kg_env
      TYPE(qs_force_type), DIMENSION(:), OPTIONAL, &
         POINTER                                         :: force
      TYPE(kpoint_type), OPTIONAL, POINTER               :: kpoints
      TYPE(wannier_centres_type), DIMENSION(:), &
         OPTIONAL, POINTER                               :: WannierCentres
      TYPE(almo_scf_env_type), OPTIONAL, POINTER         :: almo_scf_env
      REAL(KIND=dp), DIMENSION(:, :), OPTIONAL, POINTER  :: gradient_history, variable_history
      TYPE(pw_r3d_rs_type), OPTIONAL, POINTER            :: embed_pot, spin_embed_pot
      TYPE(polar_env_type), OPTIONAL, POINTER            :: polar_env
      TYPE(mo_set_type), DIMENSION(:), OPTIONAL, POINTER :: mos_last_converged
      REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: rhs

      TYPE(qs_subsys_type), POINTER                      :: subsys

      IF (PRESENT(mp2_env)) qs_env%mp2_env => mp2_env
      IF (PRESENT(bs_env)) qs_env%bs_env => bs_env
      IF (PRESENT(kg_env)) qs_env%kg_env => kg_env
      IF (PRESENT(super_cell)) THEN
         CALL cell_retain(super_cell)
         CALL cell_release(qs_env%super_cell)
         qs_env%super_cell => super_cell
      END IF
      !
      IF (PRESENT(qmmm)) qs_env%qmmm = qmmm
      IF (PRESENT(qmmm_periodic)) qs_env%qmmm_periodic = qmmm_periodic
      IF (PRESENT(mos)) qs_env%mos => mos
      IF (PRESENT(mos_last_converged)) qs_env%mos_last_converged => mos_last_converged
      IF (PRESENT(ls_scf_env)) qs_env%ls_scf_env => ls_scf_env
      IF (PRESENT(almo_scf_env)) qs_env%almo_scf_env => almo_scf_env
      IF (PRESENT(do_transport)) qs_env%do_transport = do_transport
      IF (PRESENT(transport_env)) qs_env%transport_env => transport_env
      ! if intels checking (-C) complains here, you have rediscovered a bug in the intel
      ! compiler (present in at least 10.0.025). A testcase has been submitted to intel.
      IF (PRESENT(oce)) qs_env%oce => oce
      IF (PRESENT(outer_scf_history)) qs_env%outer_scf_history => outer_scf_history
      IF (PRESENT(gradient_history)) qs_env%gradient_history => gradient_history
      IF (PRESENT(variable_history)) qs_env%variable_history => variable_history
      IF (PRESENT(outer_scf_ihistory)) qs_env%outer_scf_ihistory = outer_scf_ihistory
      IF (PRESENT(requires_mo_derivs)) qs_env%requires_mo_derivs = requires_mo_derivs
      IF (PRESENT(has_unit_metric)) qs_env%has_unit_metric = has_unit_metric
      IF (PRESENT(mo_derivs)) qs_env%mo_derivs => mo_derivs
      IF (PRESENT(mo_loc_history)) qs_env%mo_loc_history => mo_loc_history
      IF (PRESENT(run_rtp)) qs_env%run_rtp = run_rtp
      IF (PRESENT(rtp)) qs_env%rtp => rtp
      IF (PRESENT(efield)) qs_env%efield => efield
      IF (PRESENT(active_space)) qs_env%active_space => active_space

      IF (PRESENT(ewald_env)) THEN ! accept also null pointers?
         IF (ASSOCIATED(qs_env%ewald_env)) THEN
         IF (.NOT. ASSOCIATED(qs_env%ewald_env, ewald_env)) THEN
            CALL ewald_env_release(qs_env%ewald_env)
            DEALLOCATE (qs_env%ewald_env)
         END IF
         END IF
         qs_env%ewald_env => ewald_env
      END IF
      IF (PRESENT(ewald_pw)) THEN ! accept also null pointers?
         IF (ASSOCIATED(qs_env%ewald_pw)) THEN
            IF (.NOT. ASSOCIATED(ewald_pw, qs_env%ewald_pw)) THEN
               CALL ewald_pw_release(qs_env%ewald_pw)
               DEALLOCATE (qs_env%ewald_pw)
            END IF
         END IF
         qs_env%ewald_pw => ewald_pw
      END IF
      IF (PRESENT(scf_control)) THEN ! accept also null pointers?
         IF (ASSOCIATED(qs_env%scf_control)) THEN
            IF (.NOT. ASSOCIATED(qs_env%scf_control, scf_control)) THEN
               CALL scf_c_release(qs_env%scf_control)
               DEALLOCATE (qs_env%scf_control)
            END IF
         END IF
         qs_env%scf_control => scf_control
      END IF
      IF (PRESENT(rel_control)) THEN ! accept also null pointers?
         IF (ASSOCIATED(qs_env%rel_control)) THEN
            IF (.NOT. ASSOCIATED(qs_env%rel_control, rel_control)) THEN
               CALL rel_c_release(qs_env%rel_control)
               DEALLOCATE (qs_env%rel_control)
            END IF
         END IF
         qs_env%rel_control => rel_control
      END IF
      IF (PRESENT(linres_control)) THEN ! accept also null pointers?
         IF (ASSOCIATED(qs_env%linres_control)) THEN
         IF (.NOT. ASSOCIATED(qs_env%linres_control, linres_control)) THEN
            CALL linres_control_release(qs_env%linres_control)
            DEALLOCATE (qs_env%linres_control)
         END IF
         END IF
         qs_env%linres_control => linres_control
      END IF
      ! ZMP associating variables
      IF (PRESENT(rho_external)) THEN
         IF (ASSOCIATED(qs_env%rho_external)) THEN
         IF (.NOT. ASSOCIATED(qs_env%rho_external, rho_external)) THEN
            CALL qs_rho_release(qs_env%rho_external)
            DEALLOCATE (qs_env%rho_external)
         END IF
         END IF
         qs_env%rho_external => rho_external
      END IF
      IF (PRESENT(external_vxc)) qs_env%external_vxc => external_vxc
      IF (PRESENT(mask)) qs_env%mask => mask
      ! Embedding potential
      IF (PRESENT(embed_pot)) qs_env%embed_pot => embed_pot
      IF (PRESENT(spin_embed_pot)) qs_env%spin_embed_pot => spin_embed_pot

      ! Polarisability tensor
      IF (PRESENT(polar_env)) qs_env%polar_env => polar_env

      IF (PRESENT(qs_charges)) THEN
         IF (ASSOCIATED(qs_env%qs_charges)) THEN
            IF (.NOT. ASSOCIATED(qs_env%qs_charges, qs_charges)) THEN
               CALL qs_charges_release(qs_env%qs_charges)
               DEALLOCATE (qs_env%qs_charges)
            END IF
         END IF
         qs_env%qs_charges => qs_charges
      END IF
      IF (PRESENT(ks_qmmm_env)) THEN
         IF (ASSOCIATED(qs_env%ks_qmmm_env)) THEN
            IF (.NOT. ASSOCIATED(qs_env%ks_qmmm_env, ks_qmmm_env)) THEN
               CALL qs_ks_qmmm_release(qs_env%ks_qmmm_env)
               DEALLOCATE (qs_env%ks_qmmm_env)
            END IF
         END IF
         qs_env%ks_qmmm_env => ks_qmmm_env
      END IF
      IF (PRESENT(ks_env)) THEN ! accept also null pointers?
         IF (ASSOCIATED(qs_env%ks_env)) THEN
            IF (.NOT. ASSOCIATED(qs_env%ks_env, ks_env)) THEN
               CALL qs_ks_release(qs_env%ks_env)
               DEALLOCATE (qs_env%ks_env)
            END IF
         END IF
         qs_env%ks_env => ks_env
      END IF
      IF (PRESENT(wf_history)) THEN ! accept also null pointers ?
         CALL wfi_retain(wf_history)
         CALL wfi_release(qs_env%wf_history)
         qs_env%wf_history => wf_history
      END IF
      IF (PRESENT(scf_env)) THEN ! accept also null pointers ?
         IF (ASSOCIATED(qs_env%scf_env)) THEN
         IF (.NOT. ASSOCIATED(qs_env%scf_env, scf_env)) THEN
            CALL scf_env_release(qs_env%scf_env)
            DEALLOCATE (qs_env%scf_env)
         END IF
         END IF
         qs_env%scf_env => scf_env
      END IF
      IF (PRESENT(xas_env)) THEN ! accept also null pointers?
         IF (ASSOCIATED(qs_env%xas_env)) THEN
            IF (.NOT. ASSOCIATED(qs_env%xas_env, xas_env)) THEN
               CALL xas_env_release(qs_env%xas_env)
               DEALLOCATE (qs_env%xas_env)
            END IF
         END IF
         qs_env%xas_env => xas_env
      END IF
      IF (PRESENT(mpools)) THEN
         CALL mpools_retain(mpools)
         CALL mpools_release(qs_env%mpools)
         qs_env%mpools => mpools
      END IF
      IF (PRESENT(rho_atom_set)) THEN
         CALL set_local_rho(qs_env%local_rho_set, rho_atom_set=rho_atom_set)
      END IF
      IF (PRESENT(rho0_atom_set)) THEN
         CALL set_local_rho(qs_env%local_rho_set, rho0_atom_set=rho0_atom_set)
      END IF
      IF (PRESENT(rho0_mpole)) THEN
         CALL set_local_rho(qs_env%local_rho_set, rho0_mpole=rho0_mpole)
      END IF
      IF (PRESENT(rhoz_set)) THEN
         CALL set_local_rho(qs_env%local_rho_set, rhoz_set=rhoz_set)
      END IF
      IF (PRESENT(rhoz_tot)) qs_env%local_rho_set%rhoz_tot = rhoz_tot
      IF (PRESENT(ecoul_1c)) THEN
         CALL set_hartree_local(qs_env%hartree_local, ecoul_1c=ecoul_1c)
      END IF
      IF (PRESENT(input)) THEN
         CALL section_vals_retain(input)
         CALL section_vals_release(qs_env%input)
         qs_env%input => input
      END IF
      IF (PRESENT(cp_ddapc_env)) THEN
         IF (ASSOCIATED(qs_env%cp_ddapc_env)) THEN
            IF (.NOT. ASSOCIATED(qs_env%cp_ddapc_env, cp_ddapc_env)) THEN
               CALL cp_ddapc_release(qs_env%cp_ddapc_env)
               DEALLOCATE (qs_env%cp_ddapc_env)
            END IF
         END IF
         qs_env%cp_ddapc_env => cp_ddapc_env
      END IF
      IF (PRESENT(cp_ddapc_ewald)) THEN
         qs_env%cp_ddapc_ewald => cp_ddapc_ewald
      END IF
      IF (PRESENT(x_data)) qs_env%x_data => x_data
      IF (PRESENT(et_coupling)) qs_env%et_coupling => et_coupling
      IF (PRESENT(dftb_potential)) qs_env%dftb_potential => dftb_potential
      IF (PRESENT(se_taper)) THEN
         CALL se_taper_release(qs_env%se_taper)
         qs_env%se_taper => se_taper
      END IF
      IF (PRESENT(se_store_int_env)) THEN
         CALL semi_empirical_si_release(qs_env%se_store_int_env)
         qs_env%se_store_int_env => se_store_int_env
      END IF
      IF (PRESENT(se_nddo_mpole)) THEN
         CALL nddo_mpole_release(qs_env%se_nddo_mpole)
         qs_env%se_nddo_mpole => se_nddo_mpole
      END IF
      IF (PRESENT(se_nonbond_env)) THEN
         IF (ASSOCIATED(qs_env%se_nonbond_env)) THEN
         IF (.NOT. ASSOCIATED(qs_env%se_nonbond_env, se_nonbond_env)) THEN
            CALL fist_nonbond_env_release(qs_env%se_nonbond_env)
            DEALLOCATE (qs_env%se_nonbond_env)
         END IF
         END IF
         qs_env%se_nonbond_env => se_nonbond_env
      END IF
      IF (PRESENT(admm_env)) qs_env%admm_env => admm_env
      IF (PRESENT(lri_env)) qs_env%lri_env => lri_env
      IF (PRESENT(lri_density)) qs_env%lri_density => lri_density
      IF (PRESENT(harris_env)) qs_env%harris_env => harris_env
      IF (PRESENT(ec_env)) qs_env%ec_env => ec_env
      IF (PRESENT(exstate_env)) qs_env%exstate_env => exstate_env
      IF (PRESENT(dispersion_env)) qs_env%dispersion_env => dispersion_env
      IF (PRESENT(gcp_env)) qs_env%gcp_env => gcp_env
      IF (PRESENT(WannierCentres)) qs_env%WannierCentres => WannierCentres
      IF (PRESENT(kpoints)) CALL set_ks_env(qs_env%ks_env, kpoints=kpoints)

      ! Resp charges
      IF (PRESENT(rhs)) qs_env%rhs => rhs

      IF (PRESENT(force)) THEN
         CALL get_qs_env(qs_env, subsys=subsys)
         CALL qs_subsys_set(subsys, force=force)
      END IF

   END SUBROUTINE set_qs_env

! **************************************************************************************************
!> \brief allocates and intitializes a qs_env
!> \param qs_env the object to create
!> \param globenv ...
!> \par History
!>      12.2002 created [fawzi]
!> \author Fawzi Mohamed
! **************************************************************************************************
   SUBROUTINE qs_env_create(qs_env, globenv)
      TYPE(qs_environment_type), INTENT(OUT)             :: qs_env
      TYPE(global_environment_type), OPTIONAL, POINTER   :: globenv

      CALL init_qs_env(qs_env, globenv=globenv)
   END SUBROUTINE qs_env_create

! **************************************************************************************************
!> \brief releases the given qs_env (see doc/ReferenceCounting.html)
!> \param qs_env the object to release
!> \par History
!>      12.2002 created [fawzi]
!>      06.2018 polar_env added (MK)
!> \author Fawzi Mohamed
! **************************************************************************************************
   SUBROUTINE qs_env_release(qs_env)
      TYPE(qs_environment_type), INTENT(INOUT)           :: qs_env

      INTEGER                                            :: i

      CALL cell_release(qs_env%super_cell)
      IF (ASSOCIATED(qs_env%mos)) THEN
         DO i = 1, SIZE(qs_env%mos)
            CALL deallocate_mo_set(qs_env%mos(i))
         END DO
         DEALLOCATE (qs_env%mos)
      END IF
      IF (ASSOCIATED(qs_env%mos_last_converged)) THEN
         DO i = 1, SIZE(qs_env%mos_last_converged)
            CALL deallocate_mo_set(qs_env%mos_last_converged(i))
         END DO
         DEALLOCATE (qs_env%mos_last_converged)
      END IF

      IF (ASSOCIATED(qs_env%mo_derivs)) THEN
         DO I = 1, SIZE(qs_env%mo_derivs)
            CALL dbcsr_release_p(qs_env%mo_derivs(I)%matrix)
         END DO
         DEALLOCATE (qs_env%mo_derivs)
      END IF

      CALL cp_fm_release(qs_env%mo_loc_history)

      IF (ASSOCIATED(qs_env%rtp)) THEN
         CALL rt_prop_release(qs_env%rtp)
         DEALLOCATE (qs_env%rtp)
      END IF
      IF (ASSOCIATED(qs_env%outer_scf_history)) THEN
         DEALLOCATE (qs_env%outer_scf_history)
         qs_env%outer_scf_ihistory = 0
      END IF
      IF (ASSOCIATED(qs_env%gradient_history)) &
         DEALLOCATE (qs_env%gradient_history)
      IF (ASSOCIATED(qs_env%variable_history)) &
         DEALLOCATE (qs_env%variable_history)
      IF (ASSOCIATED(qs_env%oce)) CALL deallocate_oce_set(qs_env%oce)
      IF (ASSOCIATED(qs_env%local_rho_set)) THEN
         CALL local_rho_set_release(qs_env%local_rho_set)
      END IF
      IF (ASSOCIATED(qs_env%hartree_local)) THEN
         CALL hartree_local_release(qs_env%hartree_local)
      END IF
      IF (ASSOCIATED(qs_env%scf_control)) THEN
         CALL scf_c_release(qs_env%scf_control)
         DEALLOCATE (qs_env%scf_control)
      END IF
      IF (ASSOCIATED(qs_env%rel_control)) THEN
         CALL rel_c_release(qs_env%rel_control)
         DEALLOCATE (qs_env%rel_control)
      END IF

      IF (ASSOCIATED(qs_env%linres_control)) THEN
         CALL linres_control_release(qs_env%linres_control)
         DEALLOCATE (qs_env%linres_control)
      END IF

      IF (ASSOCIATED(qs_env%almo_scf_env)) THEN
         CALL almo_scf_env_release(qs_env%almo_scf_env)
      END IF

      IF (ASSOCIATED(qs_env%ls_scf_env)) THEN
         CALL ls_scf_release(qs_env%ls_scf_env)
      END IF
      IF (ASSOCIATED(qs_env%molecular_scf_guess_env)) THEN
         CALL molecular_scf_guess_env_destroy(qs_env%molecular_scf_guess_env)
         DEALLOCATE (qs_env%molecular_scf_guess_env)
      END IF

      IF (ASSOCIATED(qs_env%transport_env)) THEN
         CALL transport_env_release(qs_env%transport_env)
      END IF

      !Only if do_xas_calculation
      IF (ASSOCIATED(qs_env%xas_env)) THEN
         CALL xas_env_release(qs_env%xas_env)
         DEALLOCATE (qs_env%xas_env)
      END IF
      IF (ASSOCIATED(qs_env%ewald_env)) THEN
         CALL ewald_env_release(qs_env%ewald_env)
         DEALLOCATE (qs_env%ewald_env)
      END IF
      IF (ASSOCIATED(qs_env%ewald_pw)) THEN
         CALL ewald_pw_release(qs_env%ewald_pw)
         DEALLOCATE (qs_env%ewald_pw)
      END IF
      IF (ASSOCIATED(qs_env%image_matrix)) THEN
         DEALLOCATE (qs_env%image_matrix)
      END IF
      IF (ASSOCIATED(qs_env%ipiv)) THEN
         DEALLOCATE (qs_env%ipiv)
      END IF
      IF (ASSOCIATED(qs_env%image_coeff)) THEN
         DEALLOCATE (qs_env%image_coeff)
      END IF
      ! ZMP
      IF (ASSOCIATED(qs_env%rho_external)) THEN
         CALL qs_rho_release(qs_env%rho_external)
         DEALLOCATE (qs_env%rho_external)
      END IF
      IF (ASSOCIATED(qs_env%external_vxc)) THEN
         CALL qs_env%external_vxc%release()
         DEALLOCATE (qs_env%external_vxc)
      END IF
      IF (ASSOCIATED(qs_env%mask)) THEN
         CALL qs_env%mask%release()
         DEALLOCATE (qs_env%mask)
      END IF
      IF (ASSOCIATED(qs_env%active_space)) THEN
         CALL release_active_space_type(qs_env%active_space)
      END IF
      ! Embedding potentials if provided as input
      IF (qs_env%given_embed_pot) THEN
         CALL qs_env%embed_pot%release()
         DEALLOCATE (qs_env%embed_pot)
         IF (ASSOCIATED(qs_env%spin_embed_pot)) THEN
            CALL qs_env%spin_embed_pot%release()
            DEALLOCATE (qs_env%spin_embed_pot)
         END IF
      END IF

      ! Polarisability tensor
      CALL polar_env_release(qs_env%polar_env)

      IF (ASSOCIATED(qs_env%qs_charges)) THEN
         CALL qs_charges_release(qs_env%qs_charges)
         DEALLOCATE (qs_env%qs_charges)
      END IF
      IF (ASSOCIATED(qs_env%ks_env)) THEN
         CALL qs_ks_release(qs_env%ks_env)
         DEALLOCATE (qs_env%ks_env)
      END IF
      IF (ASSOCIATED(qs_env%ks_qmmm_env)) THEN
         CALL qs_ks_qmmm_release(qs_env%ks_qmmm_env)
         DEALLOCATE (qs_env%ks_qmmm_env)
      END IF
      CALL wfi_release(qs_env%wf_history)
      IF (ASSOCIATED(qs_env%scf_env)) THEN
         CALL scf_env_release(qs_env%scf_env)
         DEALLOCATE (qs_env%scf_env)
      END IF
      CALL mpools_release(qs_env%mpools)
      CALL section_vals_release(qs_env%input)
      IF (ASSOCIATED(qs_env%cp_ddapc_env)) THEN
         CALL cp_ddapc_release(qs_env%cp_ddapc_env)
         DEALLOCATE (qs_env%cp_ddapc_env)
      END IF
      CALL cp_ddapc_ewald_release(qs_env%cp_ddapc_ewald)
      CALL efield_berry_release(qs_env%efield)
      IF (ASSOCIATED(qs_env%x_data)) THEN
         CALL hfx_release(qs_env%x_data)
      END IF
      IF (ASSOCIATED(qs_env%et_coupling)) THEN
         CALL et_coupling_release(qs_env%et_coupling)
      END IF
      IF (ASSOCIATED(qs_env%dftb_potential)) THEN
         CALL qs_dftb_pairpot_release(qs_env%dftb_potential)
      END IF
      IF (ASSOCIATED(qs_env%se_taper)) THEN
         CALL se_taper_release(qs_env%se_taper)
      END IF
      IF (ASSOCIATED(qs_env%se_store_int_env)) THEN
         CALL semi_empirical_si_release(qs_env%se_store_int_env)
      END IF
      IF (ASSOCIATED(qs_env%se_nddo_mpole)) THEN
         CALL nddo_mpole_release(qs_env%se_nddo_mpole)
      END IF
      IF (ASSOCIATED(qs_env%se_nonbond_env)) THEN
         CALL fist_nonbond_env_release(qs_env%se_nonbond_env)
         DEALLOCATE (qs_env%se_nonbond_env)
      END IF
      IF (ASSOCIATED(qs_env%admm_env)) THEN
         CALL admm_env_release(qs_env%admm_env)
      END IF
      IF (ASSOCIATED(qs_env%lri_env)) THEN
         CALL lri_env_release(qs_env%lri_env)
         DEALLOCATE (qs_env%lri_env)
      END IF
      IF (ASSOCIATED(qs_env%lri_density)) THEN
         CALL lri_density_release(qs_env%lri_density)
         DEALLOCATE (qs_env%lri_density)
      END IF
      IF (ASSOCIATED(qs_env%harris_env)) THEN
         CALL harris_env_release(qs_env%harris_env)
      END IF
      IF (ASSOCIATED(qs_env%ec_env)) THEN
         CALL ec_env_release(qs_env%ec_env)
      END IF
      IF (ASSOCIATED(qs_env%exstate_env)) THEN
         CALL exstate_release(qs_env%exstate_env)
      END IF
      IF (ASSOCIATED(qs_env%mp2_env)) THEN
         CALL mp2_env_release(qs_env%mp2_env)
         DEALLOCATE (qs_env%mp2_env)
         NULLIFY (qs_env%mp2_env)
      END IF
      IF (ASSOCIATED(qs_env%bs_env)) THEN
         CALL bs_env_release(qs_env%bs_env)
      END IF
      IF (ASSOCIATED(qs_env%kg_env)) THEN
         CALL kg_env_release(qs_env%kg_env)
      END IF

      ! dispersion
      CALL qs_dispersion_release(qs_env%dispersion_env)
      ! gCP
      IF (ASSOCIATED(qs_env%gcp_env)) THEN
         CALL qs_gcp_release(qs_env%gcp_env)
      END IF

      IF (ASSOCIATED(qs_env%WannierCentres)) THEN
         DO i = 1, SIZE(qs_env%WannierCentres)
            DEALLOCATE (qs_env%WannierCentres(i)%WannierHamDiag)
            DEALLOCATE (qs_env%WannierCentres(i)%centres)
         END DO
         DEALLOCATE (qs_env%WannierCentres)
      END IF
      ! Resp charges
      IF (ASSOCIATED(qs_env%rhs)) DEALLOCATE (qs_env%rhs)

   END SUBROUTINE qs_env_release

! **************************************************************************************************
!> \brief releases part of the given qs_env in order to save memory
!> \param qs_env the object to release
!> \par History
!>      04.2022 created [JGH]
! **************************************************************************************************
   SUBROUTINE qs_env_part_release(qs_env)
      TYPE(qs_environment_type), INTENT(INOUT)           :: qs_env

      INTEGER                                            :: i

      IF (ASSOCIATED(qs_env%mos_last_converged)) THEN
         DO i = 1, SIZE(qs_env%mos_last_converged)
            CALL deallocate_mo_set(qs_env%mos_last_converged(i))
         END DO
         DEALLOCATE (qs_env%mos_last_converged)
      END IF

      IF (ASSOCIATED(qs_env%mo_derivs)) THEN
         DO I = 1, SIZE(qs_env%mo_derivs)
            CALL dbcsr_release_p(qs_env%mo_derivs(I)%matrix)
         END DO
         DEALLOCATE (qs_env%mo_derivs)
      END IF

      CALL cp_fm_release(qs_env%mo_loc_history)

      IF (ASSOCIATED(qs_env%rtp)) THEN
         CALL rt_prop_release(qs_env%rtp)
         DEALLOCATE (qs_env%rtp)
      END IF
      IF (ASSOCIATED(qs_env%outer_scf_history)) THEN
         DEALLOCATE (qs_env%outer_scf_history)
         qs_env%outer_scf_ihistory = 0
      END IF
      IF (ASSOCIATED(qs_env%gradient_history)) &
         DEALLOCATE (qs_env%gradient_history)
      IF (ASSOCIATED(qs_env%variable_history)) &
         DEALLOCATE (qs_env%variable_history)
      IF (ASSOCIATED(qs_env%oce)) CALL deallocate_oce_set(qs_env%oce)
      IF (ASSOCIATED(qs_env%local_rho_set)) THEN
         CALL local_rho_set_release(qs_env%local_rho_set)
      END IF
      IF (ASSOCIATED(qs_env%hartree_local)) THEN
         CALL hartree_local_release(qs_env%hartree_local)
      END IF
      IF (ASSOCIATED(qs_env%scf_control)) THEN
         CALL scf_c_release(qs_env%scf_control)
         DEALLOCATE (qs_env%scf_control)
      END IF
      IF (ASSOCIATED(qs_env%rel_control)) THEN
         CALL rel_c_release(qs_env%rel_control)
         DEALLOCATE (qs_env%rel_control)
      END IF

      IF (ASSOCIATED(qs_env%linres_control)) THEN
         CALL linres_control_release(qs_env%linres_control)
         DEALLOCATE (qs_env%linres_control)
      END IF

      IF (ASSOCIATED(qs_env%almo_scf_env)) THEN
         CALL almo_scf_env_release(qs_env%almo_scf_env)
      END IF

      IF (ASSOCIATED(qs_env%ls_scf_env)) THEN
         CALL ls_scf_release(qs_env%ls_scf_env)
      END IF
      IF (ASSOCIATED(qs_env%molecular_scf_guess_env)) THEN
         CALL molecular_scf_guess_env_destroy(qs_env%molecular_scf_guess_env)
         DEALLOCATE (qs_env%molecular_scf_guess_env)
      END IF

      IF (ASSOCIATED(qs_env%transport_env)) THEN
         CALL transport_env_release(qs_env%transport_env)
      END IF

      !Only if do_xas_calculation
      IF (ASSOCIATED(qs_env%xas_env)) THEN
         CALL xas_env_release(qs_env%xas_env)
         DEALLOCATE (qs_env%xas_env)
      END IF
      IF (ASSOCIATED(qs_env%ewald_env)) THEN
         CALL ewald_env_release(qs_env%ewald_env)
         DEALLOCATE (qs_env%ewald_env)
      END IF
      IF (ASSOCIATED(qs_env%ewald_pw)) THEN
         CALL ewald_pw_release(qs_env%ewald_pw)
         DEALLOCATE (qs_env%ewald_pw)
      END IF
      IF (ASSOCIATED(qs_env%image_matrix)) THEN
         DEALLOCATE (qs_env%image_matrix)
      END IF
      IF (ASSOCIATED(qs_env%ipiv)) THEN
         DEALLOCATE (qs_env%ipiv)
      END IF
      IF (ASSOCIATED(qs_env%image_coeff)) THEN
         DEALLOCATE (qs_env%image_coeff)
      END IF
      ! ZMP
      IF (ASSOCIATED(qs_env%rho_external)) THEN
         CALL qs_rho_release(qs_env%rho_external)
         DEALLOCATE (qs_env%rho_external)
      END IF
      IF (ASSOCIATED(qs_env%external_vxc)) THEN
         CALL qs_env%external_vxc%release()
         DEALLOCATE (qs_env%external_vxc)
      END IF
      IF (ASSOCIATED(qs_env%mask)) THEN
         CALL qs_env%mask%release()
         DEALLOCATE (qs_env%mask)
      END IF
      IF (ASSOCIATED(qs_env%active_space)) THEN
         CALL release_active_space_type(qs_env%active_space)
      END IF
      ! Embedding potentials if provided as input
      IF (qs_env%given_embed_pot) THEN
         CALL qs_env%embed_pot%release()
         DEALLOCATE (qs_env%embed_pot)
         IF (ASSOCIATED(qs_env%spin_embed_pot)) THEN
            CALL qs_env%spin_embed_pot%release()
            DEALLOCATE (qs_env%spin_embed_pot)
         END IF
      END IF

      ! Polarisability tensor
      CALL polar_env_release(qs_env%polar_env)

      IF (ASSOCIATED(qs_env%qs_charges)) THEN
         CALL qs_charges_release(qs_env%qs_charges)
         DEALLOCATE (qs_env%qs_charges)
      END IF
      CALL qs_ks_part_release(qs_env%ks_env)
      IF (ASSOCIATED(qs_env%ks_qmmm_env)) THEN
         CALL qs_ks_qmmm_release(qs_env%ks_qmmm_env)
         DEALLOCATE (qs_env%ks_qmmm_env)
      END IF
      CALL wfi_release(qs_env%wf_history)
      IF (ASSOCIATED(qs_env%scf_env)) THEN
         CALL scf_env_release(qs_env%scf_env)
         DEALLOCATE (qs_env%scf_env)
      END IF
      IF (ASSOCIATED(qs_env%cp_ddapc_env)) THEN
         CALL cp_ddapc_release(qs_env%cp_ddapc_env)
         DEALLOCATE (qs_env%cp_ddapc_env)
      END IF
      CALL cp_ddapc_ewald_release(qs_env%cp_ddapc_ewald)
      CALL efield_berry_release(qs_env%efield)
      IF (ASSOCIATED(qs_env%x_data)) THEN
         CALL hfx_release(qs_env%x_data)
      END IF
      IF (ASSOCIATED(qs_env%et_coupling)) THEN
         CALL et_coupling_release(qs_env%et_coupling)
      END IF
      IF (ASSOCIATED(qs_env%dftb_potential)) THEN
         CALL qs_dftb_pairpot_release(qs_env%dftb_potential)
      END IF
      IF (ASSOCIATED(qs_env%se_taper)) THEN
         CALL se_taper_release(qs_env%se_taper)
      END IF
      IF (ASSOCIATED(qs_env%se_store_int_env)) THEN
         CALL semi_empirical_si_release(qs_env%se_store_int_env)
      END IF
      IF (ASSOCIATED(qs_env%se_nddo_mpole)) THEN
         CALL nddo_mpole_release(qs_env%se_nddo_mpole)
      END IF
      IF (ASSOCIATED(qs_env%se_nonbond_env)) THEN
         CALL fist_nonbond_env_release(qs_env%se_nonbond_env)
         DEALLOCATE (qs_env%se_nonbond_env)
      END IF
      IF (ASSOCIATED(qs_env%admm_env)) THEN
         CALL admm_env_release(qs_env%admm_env)
      END IF
      IF (ASSOCIATED(qs_env%lri_env)) THEN
         CALL lri_env_release(qs_env%lri_env)
         DEALLOCATE (qs_env%lri_env)
      END IF
      IF (ASSOCIATED(qs_env%lri_density)) THEN
         CALL lri_density_release(qs_env%lri_density)
         DEALLOCATE (qs_env%lri_density)
      END IF
      IF (ASSOCIATED(qs_env%harris_env)) THEN
         CALL harris_env_release(qs_env%harris_env)
      END IF
      IF (ASSOCIATED(qs_env%ec_env)) THEN
         CALL ec_env_release(qs_env%ec_env)
      END IF
      IF (ASSOCIATED(qs_env%exstate_env)) THEN
         CALL exstate_release(qs_env%exstate_env)
      END IF
      IF (ASSOCIATED(qs_env%mp2_env)) THEN
         CALL mp2_env_release(qs_env%mp2_env)
         DEALLOCATE (qs_env%mp2_env)
         NULLIFY (qs_env%mp2_env)
      END IF
      IF (ASSOCIATED(qs_env%kg_env)) THEN
         CALL kg_env_release(qs_env%kg_env)
      END IF

      ! dispersion
      CALL qs_dispersion_release(qs_env%dispersion_env)
      ! gCP
      IF (ASSOCIATED(qs_env%gcp_env)) THEN
         CALL qs_gcp_release(qs_env%gcp_env)
      END IF

      IF (ASSOCIATED(qs_env%WannierCentres)) THEN
         DO i = 1, SIZE(qs_env%WannierCentres)
            DEALLOCATE (qs_env%WannierCentres(i)%WannierHamDiag)
            DEALLOCATE (qs_env%WannierCentres(i)%centres)
         END DO
         DEALLOCATE (qs_env%WannierCentres)
      END IF
      ! Resp charges
      IF (ASSOCIATED(qs_env%rhs)) DEALLOCATE (qs_env%rhs)

   END SUBROUTINE qs_env_part_release

END MODULE qs_environment_types
