LCOV - code coverage report
Current view: top level - src - optimize_embedding_potential.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:34ef472) Lines: 1065 1312 81.2 %
Date: 2024-04-26 08:30:29 Functions: 38 41 92.7 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : MODULE optimize_embedding_potential
       9             : 
      10             :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      11             :                                               get_atomic_kind,&
      12             :                                               get_atomic_kind_set
      13             :    USE cell_types,                      ONLY: cell_type
      14             :    USE cp_blacs_env,                    ONLY: cp_blacs_env_create,&
      15             :                                               cp_blacs_env_release,&
      16             :                                               cp_blacs_env_type
      17             :    USE cp_control_types,                ONLY: dft_control_type
      18             :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      19             :                                               dbcsr_deallocate_matrix_set
      20             :    USE cp_files,                        ONLY: close_file,&
      21             :                                               open_file
      22             :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale,&
      23             :                                               cp_fm_scale,&
      24             :                                               cp_fm_scale_and_add,&
      25             :                                               cp_fm_trace
      26             :    USE cp_fm_diag,                      ONLY: choose_eigv_solver
      27             :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      28             :                                               cp_fm_struct_release,&
      29             :                                               cp_fm_struct_type
      30             :    USE cp_fm_types,                     ONLY: &
      31             :         cp_fm_copy_general, cp_fm_create, cp_fm_get_element, cp_fm_get_info, cp_fm_release, &
      32             :         cp_fm_set_all, cp_fm_to_fm, cp_fm_to_fm_submat, cp_fm_type, cp_fm_write_unformatted
      33             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      34             :                                               cp_logger_type
      35             :    USE cp_output_handling,              ONLY: cp_p_file,&
      36             :                                               cp_print_key_finished_output,&
      37             :                                               cp_print_key_should_output,&
      38             :                                               cp_print_key_unit_nr
      39             :    USE cp_realspace_grid_cube,          ONLY: cp_cube_to_pw,&
      40             :                                               cp_pw_to_cube,&
      41             :                                               cp_pw_to_simple_volumetric
      42             :    USE dbcsr_api,                       ONLY: dbcsr_p_type
      43             :    USE embed_types,                     ONLY: opt_embed_pot_type
      44             :    USE force_env_types,                 ONLY: force_env_type
      45             :    USE input_constants,                 ONLY: &
      46             :         embed_diff, embed_fa, embed_grid_angstrom, embed_grid_bohr, embed_level_shift, embed_none, &
      47             :         embed_quasi_newton, embed_resp, embed_steep_desc
      48             :    USE input_section_types,             ONLY: section_get_ival,&
      49             :                                               section_get_ivals,&
      50             :                                               section_get_rval,&
      51             :                                               section_vals_get_subs_vals,&
      52             :                                               section_vals_type,&
      53             :                                               section_vals_val_get
      54             :    USE kinds,                           ONLY: default_path_length,&
      55             :                                               dp
      56             :    USE lri_environment_types,           ONLY: lri_kind_type
      57             :    USE mathconstants,                   ONLY: pi
      58             :    USE message_passing,                 ONLY: mp_para_env_type
      59             :    USE mixed_environment_utils,         ONLY: get_subsys_map_index
      60             :    USE parallel_gemm_api,               ONLY: parallel_gemm
      61             :    USE particle_list_types,             ONLY: particle_list_type
      62             :    USE particle_types,                  ONLY: particle_type
      63             :    USE pw_env_types,                    ONLY: pw_env_get,&
      64             :                                               pw_env_type
      65             :    USE pw_methods,                      ONLY: &
      66             :         pw_axpy, pw_copy, pw_derive, pw_dr2, pw_integral_ab, pw_integrate_function, pw_scale, &
      67             :         pw_transfer, pw_zero
      68             :    USE pw_poisson_methods,              ONLY: pw_poisson_solve
      69             :    USE pw_poisson_types,                ONLY: pw_poisson_type
      70             :    USE pw_pool_types,                   ONLY: pw_pool_type
      71             :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      72             :                                               pw_r3d_rs_type
      73             :    USE qs_collocate_density,            ONLY: calculate_rho_resp_all,&
      74             :                                               calculate_wavefunction
      75             :    USE qs_environment_types,            ONLY: get_qs_env,&
      76             :                                               qs_environment_type,&
      77             :                                               set_qs_env
      78             :    USE qs_integrate_potential_single,   ONLY: integrate_v_rspace_one_center
      79             :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      80             :                                               qs_kind_type
      81             :    USE qs_kinetic,                      ONLY: build_kinetic_matrix
      82             :    USE qs_ks_types,                     ONLY: qs_ks_env_type
      83             :    USE qs_mo_types,                     ONLY: get_mo_set,&
      84             :                                               mo_set_type
      85             :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      86             :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      87             :                                               qs_rho_type
      88             :    USE qs_subsys_types,                 ONLY: qs_subsys_get,&
      89             :                                               qs_subsys_type
      90             :    USE xc,                              ONLY: smooth_cutoff
      91             :    USE xc_rho_cflags_types,             ONLY: xc_rho_cflags_setall,&
      92             :                                               xc_rho_cflags_type
      93             :    USE xc_rho_set_types,                ONLY: xc_rho_set_create,&
      94             :                                               xc_rho_set_release,&
      95             :                                               xc_rho_set_type,&
      96             :                                               xc_rho_set_update
      97             : #include "./base/base_uses.f90"
      98             : 
      99             :    IMPLICIT NONE
     100             : 
     101             :    PRIVATE
     102             : 
     103             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'optimize_embedding_potential'
     104             : 
     105             :    PUBLIC :: prepare_embed_opt, init_embed_pot, release_opt_embed, calculate_embed_pot_grad, &
     106             :              opt_embed_step, print_rho_diff, step_control, max_dens_diff, print_emb_opt_info, &
     107             :              conv_check_embed, make_subsys_embed_pot, print_embed_restart, find_aux_dimen, &
     108             :              read_embed_pot, understand_spin_states, given_embed_pot, print_rho_spin_diff, &
     109             :              print_pot_simple_grid, get_prev_density, get_max_subsys_diff, Coulomb_guess
     110             : 
     111             : CONTAINS
     112             : 
     113             : ! **************************************************************************************************
     114             : !> \brief Find out whether we need to swap alpha- and beta- spind densities in the second subsystem
     115             : !> \brief It's only needed because by default alpha-spins go first in a subsystem.
     116             : !> \brief By swapping we impose the constraint:
     117             : !> \brief rho_1(alpha) + rho_2(alpha) = rho_total(alpha)
     118             : !> \brief rho_1(beta) + rho_2(beta) = rho_total(beta)
     119             : !> \param force_env ...
     120             : !> \param ref_subsys_number ...
     121             : !> \param change_spin ...
     122             : !> \param open_shell_embed ...
     123             : !> \param all_nspins ...
     124             : !> \return ...
     125             : !> \author Vladimir Rybkin
     126             : ! **************************************************************************************************
     127          24 :    SUBROUTINE understand_spin_states(force_env, ref_subsys_number, change_spin, open_shell_embed, all_nspins)
     128             :       TYPE(force_env_type), POINTER                      :: force_env
     129             :       INTEGER                                            :: ref_subsys_number
     130             :       LOGICAL                                            :: change_spin, open_shell_embed
     131             :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: all_nspins
     132             : 
     133             :       INTEGER                                            :: i_force_eval, nspins, sub_spin_1, &
     134             :                                                             sub_spin_2, total_spin
     135             :       INTEGER, DIMENSION(2)                              :: nelectron_spin
     136             :       INTEGER, DIMENSION(2, 3)                           :: all_spins
     137             :       TYPE(dft_control_type), POINTER                    :: dft_control
     138             : 
     139          24 :       change_spin = .FALSE.
     140          24 :       open_shell_embed = .FALSE.
     141          72 :       ALLOCATE (all_nspins(ref_subsys_number))
     142          24 :       IF (ref_subsys_number .EQ. 3) THEN
     143          24 :          all_spins = 0
     144          96 :          DO i_force_eval = 1, ref_subsys_number
     145             :             CALL get_qs_env(qs_env=force_env%sub_force_env(i_force_eval)%force_env%qs_env, &
     146          72 :                             nelectron_spin=nelectron_spin, dft_control=dft_control)
     147         216 :             all_spins(:, i_force_eval) = nelectron_spin
     148          72 :             nspins = dft_control%nspins
     149          96 :             all_nspins(i_force_eval) = nspins
     150             :          END DO
     151             : 
     152             :          ! Find out whether we need a spin-dependend embedding potential
     153          24 :          IF (.NOT. ((all_nspins(1) .EQ. 1) .AND. (all_nspins(2) .EQ. 1) .AND. (all_nspins(3) .EQ. 1))) &
     154          12 :             open_shell_embed = .TRUE.
     155             : 
     156             :          ! If it's open shell, we need to check spin states
     157          24 :          IF (open_shell_embed) THEN
     158             : 
     159          12 :             IF (all_nspins(3) .EQ. 1) THEN
     160             :                total_spin = 0
     161             :             ELSE
     162          10 :                total_spin = all_spins(1, 3) - all_spins(2, 3)
     163             :             END IF
     164          12 :             IF (all_nspins(1) .EQ. 1) THEN
     165             :                sub_spin_1 = 0
     166             :             ELSE
     167          12 :                sub_spin_1 = all_spins(1, 1) - all_spins(2, 1)
     168             :             END IF
     169          12 :             IF (all_nspins(2) .EQ. 1) THEN
     170             :                sub_spin_2 = 0
     171             :             ELSE
     172          12 :                sub_spin_2 = all_spins(1, 2) - all_spins(2, 2)
     173             :             END IF
     174          12 :             IF ((sub_spin_1 + sub_spin_2) .EQ. total_spin) THEN
     175          10 :                change_spin = .FALSE.
     176             :             ELSE
     177           2 :                IF (ABS(sub_spin_1 - sub_spin_2) .EQ. total_spin) THEN
     178           2 :                   change_spin = .TRUE.
     179             :                ELSE
     180           0 :                   CPABORT("Spin states of subsystems are not compatible.")
     181             :                END IF
     182             :             END IF
     183             : 
     184             :          END IF ! not open_shell
     185             :       ELSE
     186           0 :          CPABORT("Reference subsystem must be the third FORCE_EVAL.")
     187             :       END IF
     188             : 
     189          24 :    END SUBROUTINE understand_spin_states
     190             : 
     191             : ! **************************************************************************************************
     192             : !> \brief ...
     193             : !> \param qs_env ...
     194             : !> \param embed_pot ...
     195             : !> \param add_const_pot ...
     196             : !> \param Fermi_Amaldi ...
     197             : !> \param const_pot ...
     198             : !> \param open_shell_embed ...
     199             : !> \param spin_embed_pot ...
     200             : !> \param pot_diff ...
     201             : !> \param Coulomb_guess ...
     202             : !> \param grid_opt ...
     203             : ! **************************************************************************************************
     204          24 :    SUBROUTINE init_embed_pot(qs_env, embed_pot, add_const_pot, Fermi_Amaldi, const_pot, open_shell_embed, &
     205             :                              spin_embed_pot, pot_diff, Coulomb_guess, grid_opt)
     206             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     207             :       TYPE(pw_r3d_rs_type), POINTER                      :: embed_pot
     208             :       LOGICAL                                            :: add_const_pot, Fermi_Amaldi
     209             :       TYPE(pw_r3d_rs_type), POINTER                      :: const_pot
     210             :       LOGICAL                                            :: open_shell_embed
     211             :       TYPE(pw_r3d_rs_type), POINTER                      :: spin_embed_pot, pot_diff
     212             :       LOGICAL                                            :: Coulomb_guess, grid_opt
     213             : 
     214             :       INTEGER                                            :: nelectrons
     215             :       INTEGER, DIMENSION(2)                              :: nelectron_spin
     216             :       REAL(KIND=dp)                                      :: factor
     217             :       TYPE(pw_env_type), POINTER                         :: pw_env
     218             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     219             :       TYPE(pw_r3d_rs_type), POINTER                      :: v_hartree_r_space
     220             : 
     221             :       ! Extract  plane waves environment
     222             :       CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, &
     223             :                       nelectron_spin=nelectron_spin, &
     224          24 :                       v_hartree_rspace=v_hartree_r_space)
     225             : 
     226             :       ! Prepare plane-waves pool
     227          24 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
     228             : 
     229             :       ! Create embedding potential and set to zero
     230             :       NULLIFY (embed_pot)
     231          24 :       ALLOCATE (embed_pot)
     232          24 :       CALL auxbas_pw_pool%create_pw(embed_pot)
     233          24 :       CALL pw_zero(embed_pot)
     234             : 
     235             :       ! Spin embedding potential if asked
     236          24 :       IF (open_shell_embed) THEN
     237             :          NULLIFY (spin_embed_pot)
     238          12 :          ALLOCATE (spin_embed_pot)
     239          12 :          CALL auxbas_pw_pool%create_pw(spin_embed_pot)
     240          12 :          CALL pw_zero(spin_embed_pot)
     241             :       END IF
     242             : 
     243             :       ! Coulomb guess/constant potential
     244          24 :       IF (Coulomb_guess) THEN
     245             :          NULLIFY (pot_diff)
     246           2 :          ALLOCATE (pot_diff)
     247           2 :          CALL auxbas_pw_pool%create_pw(pot_diff)
     248           2 :          CALL pw_zero(pot_diff)
     249             :       END IF
     250             : 
     251             :       ! Initialize constant part of the embedding potential
     252          24 :       IF (add_const_pot .AND. (.NOT. grid_opt)) THEN
     253             :          ! Now the constant potential is the Coulomb one
     254             :          NULLIFY (const_pot)
     255           4 :          ALLOCATE (const_pot)
     256           4 :          CALL auxbas_pw_pool%create_pw(const_pot)
     257           4 :          CALL pw_zero(const_pot)
     258             :       END IF
     259             : 
     260             :       ! Add Fermi-Amaldi potential if requested
     261          24 :       IF (Fermi_Amaldi) THEN
     262             : 
     263             :          ! Extract  Hartree potential
     264           6 :          NULLIFY (v_hartree_r_space)
     265             :          CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, &
     266           6 :                          v_hartree_rspace=v_hartree_r_space)
     267           6 :          CALL pw_copy(v_hartree_r_space, embed_pot)
     268             : 
     269             :          ! Calculate the number of electrons
     270           6 :          nelectrons = nelectron_spin(1) + nelectron_spin(2)
     271           6 :          factor = (REAL(nelectrons, dp) - 1.0_dp)/(REAL(nelectrons, dp))
     272             : 
     273             :          ! Scale the Hartree potential to get Fermi-Amaldi
     274           6 :          CALL pw_scale(embed_pot, a=factor)
     275             : 
     276             :          ! Copy Fermi-Amaldi to embedding potential for basis-based optimization
     277           6 :          IF (.NOT. grid_opt) CALL pw_copy(embed_pot, embed_pot)
     278             : 
     279             :       END IF
     280             : 
     281          24 :    END SUBROUTINE init_embed_pot
     282             : 
     283             : ! **************************************************************************************************
     284             : !> \brief Creates and allocates objects for optimization of embedding potential
     285             : !> \param qs_env ...
     286             : !> \param opt_embed ...
     287             : !> \param opt_embed_section ...
     288             : !> \author Vladimir Rybkin
     289             : ! **************************************************************************************************
     290          24 :    SUBROUTINE prepare_embed_opt(qs_env, opt_embed, opt_embed_section)
     291             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     292             :       TYPE(opt_embed_pot_type)                           :: opt_embed
     293             :       TYPE(section_vals_type), POINTER                   :: opt_embed_section
     294             : 
     295             :       INTEGER                                            :: diff_size, i_dens, size_prev_dens
     296             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     297             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
     298             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     299             :       TYPE(pw_env_type), POINTER                         :: pw_env
     300             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     301             : 
     302             :       !TYPE(pw_env_type), POINTER                         :: pw_env
     303             :       !TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     304             : 
     305             :       ! First, read the input
     306             : 
     307          24 :       CALL read_opt_embed_section(opt_embed, opt_embed_section)
     308             : 
     309             :       ! All these are needed for optimization in a finite Gaussian basis
     310          24 :       IF (.NOT. opt_embed%grid_opt) THEN
     311             :          ! Create blacs environment
     312             :          CALL get_qs_env(qs_env=qs_env, &
     313          14 :                          para_env=para_env)
     314          14 :          NULLIFY (blacs_env)
     315          14 :          CALL cp_blacs_env_create(blacs_env=blacs_env, para_env=para_env)
     316             : 
     317             :          ! Reveal the dimension of the RI basis
     318          14 :          CALL find_aux_dimen(qs_env, opt_embed%dimen_aux)
     319             : 
     320             :          ! Prepare the object for integrals
     321          14 :          CALL make_lri_object(qs_env, opt_embed%lri)
     322             : 
     323             :          ! In case if spin embedding potential has to be optimized,
     324             :          ! the dimension of variational space is two times larger
     325          14 :          IF (opt_embed%open_shell_embed) THEN
     326           6 :             opt_embed%dimen_var_aux = 2*opt_embed%dimen_aux
     327             :          ELSE
     328           8 :             opt_embed%dimen_var_aux = opt_embed%dimen_aux
     329             :          END IF
     330             : 
     331             :          ! Allocate expansion coefficients and gradient
     332          14 :          NULLIFY (opt_embed%embed_pot_grad, opt_embed%embed_pot_coef, opt_embed%step, fm_struct)
     333             : 
     334          14 :          NULLIFY (opt_embed%prev_embed_pot_grad, opt_embed%prev_embed_pot_coef, opt_embed%prev_step)
     335             :          CALL cp_fm_struct_create(fm_struct, para_env=para_env, context=blacs_env, &
     336          14 :                                   nrow_global=opt_embed%dimen_var_aux, ncol_global=1)
     337             :          ALLOCATE (opt_embed%embed_pot_grad, opt_embed%embed_pot_coef, &
     338             :                    opt_embed%prev_embed_pot_grad, opt_embed%prev_embed_pot_coef, &
     339          14 :                    opt_embed%step, opt_embed%prev_step)
     340          14 :          CALL cp_fm_create(opt_embed%embed_pot_grad, fm_struct, name="pot_grad")
     341          14 :          CALL cp_fm_create(opt_embed%embed_pot_coef, fm_struct, name="pot_coef")
     342          14 :          CALL cp_fm_create(opt_embed%prev_embed_pot_grad, fm_struct, name="prev_pot_grad")
     343          14 :          CALL cp_fm_create(opt_embed%prev_embed_pot_coef, fm_struct, name="prev_pot_coef")
     344          14 :          CALL cp_fm_create(opt_embed%step, fm_struct, name="step")
     345          14 :          CALL cp_fm_create(opt_embed%prev_step, fm_struct, name="prev_step")
     346             : 
     347          14 :          CALL cp_fm_struct_release(fm_struct)
     348          14 :          CALL cp_fm_set_all(opt_embed%embed_pot_grad, 0.0_dp)
     349          14 :          CALL cp_fm_set_all(opt_embed%prev_embed_pot_grad, 0.0_dp)
     350          14 :          CALL cp_fm_set_all(opt_embed%embed_pot_coef, 0.0_dp)
     351          14 :          CALL cp_fm_set_all(opt_embed%prev_embed_pot_coef, 0.0_dp)
     352          14 :          CALL cp_fm_set_all(opt_embed%step, 0.0_dp)
     353             : 
     354          14 :          CALL cp_fm_set_all(opt_embed%prev_step, 0.0_dp)
     355             : 
     356             :          ! Allocate Hessian
     357          14 :          NULLIFY (opt_embed%embed_pot_hess, opt_embed%prev_embed_pot_hess, fm_struct)
     358             :          CALL cp_fm_struct_create(fm_struct, para_env=para_env, context=blacs_env, &
     359          14 :                                   nrow_global=opt_embed%dimen_var_aux, ncol_global=opt_embed%dimen_var_aux)
     360          14 :          ALLOCATE (opt_embed%embed_pot_hess, opt_embed%prev_embed_pot_hess)
     361          14 :          CALL cp_fm_create(opt_embed%embed_pot_hess, fm_struct, name="pot_Hess")
     362          14 :          CALL cp_fm_create(opt_embed%prev_embed_pot_hess, fm_struct, name="prev_pot_Hess")
     363          14 :          CALL cp_fm_struct_release(fm_struct)
     364             : 
     365             :          ! Special structure for the kinetic energy matrix
     366          14 :          NULLIFY (fm_struct, opt_embed%kinetic_mat)
     367             :          CALL cp_fm_struct_create(fm_struct, para_env=para_env, context=blacs_env, &
     368          14 :                                   nrow_global=opt_embed%dimen_aux, ncol_global=opt_embed%dimen_aux)
     369          14 :          ALLOCATE (opt_embed%kinetic_mat)
     370          14 :          CALL cp_fm_create(opt_embed%kinetic_mat, fm_struct, name="kinetic_mat")
     371          14 :          CALL cp_fm_struct_release(fm_struct)
     372          14 :          CALL cp_fm_set_all(opt_embed%kinetic_mat, 0.0_dp)
     373             : 
     374             :          ! Hessian is set as a unit matrix
     375          14 :          CALL cp_fm_set_all(opt_embed%embed_pot_hess, 0.0_dp, -1.0_dp)
     376          14 :          CALL cp_fm_set_all(opt_embed%prev_embed_pot_hess, 0.0_dp, -1.0_dp)
     377             : 
     378             :          ! Release blacs environment
     379          14 :          CALL cp_blacs_env_release(blacs_env)
     380             : 
     381             :       END IF
     382             : 
     383          24 :       CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
     384          24 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
     385          24 :       NULLIFY (opt_embed%prev_subsys_dens)
     386          72 :       size_prev_dens = SUM(opt_embed%all_nspins(1:(SIZE(opt_embed%all_nspins) - 1)))
     387         144 :       ALLOCATE (opt_embed%prev_subsys_dens(size_prev_dens))
     388          96 :       DO i_dens = 1, size_prev_dens
     389          72 :          CALL auxbas_pw_pool%create_pw(opt_embed%prev_subsys_dens(i_dens))
     390          96 :          CALL pw_zero(opt_embed%prev_subsys_dens(i_dens))
     391             :       END DO
     392          72 :       ALLOCATE (opt_embed%max_subsys_dens_diff(size_prev_dens))
     393             : 
     394             :       ! Array to store functional values
     395          72 :       ALLOCATE (opt_embed%w_func(opt_embed%n_iter))
     396        1136 :       opt_embed%w_func = 0.0_dp
     397             : 
     398             :       ! Allocate max_diff and int_diff
     399          24 :       diff_size = 1
     400          24 :       IF (opt_embed%open_shell_embed) diff_size = 2
     401          72 :       ALLOCATE (opt_embed%max_diff(diff_size))
     402          72 :       ALLOCATE (opt_embed%int_diff(diff_size))
     403          72 :       ALLOCATE (opt_embed%int_diff_square(diff_size))
     404             : 
     405             :       ! FAB update
     406          24 :       IF (opt_embed%fab) THEN
     407             :          NULLIFY (opt_embed%prev_embed_pot)
     408           2 :          ALLOCATE (opt_embed%prev_embed_pot)
     409           2 :          CALL auxbas_pw_pool%create_pw(opt_embed%prev_embed_pot)
     410           2 :          CALL pw_zero(opt_embed%prev_embed_pot)
     411           2 :          IF (opt_embed%open_shell_embed) THEN
     412             :             NULLIFY (opt_embed%prev_spin_embed_pot)
     413           0 :             ALLOCATE (opt_embed%prev_spin_embed_pot)
     414           0 :             CALL auxbas_pw_pool%create_pw(opt_embed%prev_spin_embed_pot)
     415           0 :             CALL pw_zero(opt_embed%prev_spin_embed_pot)
     416             :          END IF
     417             :       END IF
     418             : 
     419             :       ! Set allowed energy decrease parameter
     420          24 :       opt_embed%allowed_decrease = 0.0001_dp
     421             : 
     422             :       ! Regularization contribution is set to zero
     423          24 :       opt_embed%reg_term = 0.0_dp
     424             : 
     425             :       ! Step is accepted in the beginning
     426          24 :       opt_embed%accept_step = .TRUE.
     427          24 :       opt_embed%newton_step = .FALSE.
     428          24 :       opt_embed%last_accepted = 1
     429             : 
     430             :       ! Set maximum and minimum trust radii
     431          24 :       opt_embed%max_trad = opt_embed%trust_rad*7.900_dp
     432          24 :       opt_embed%min_trad = opt_embed%trust_rad*0.125*0.065_dp
     433             : 
     434          24 :    END SUBROUTINE prepare_embed_opt
     435             : 
     436             : ! **************************************************************************************************
     437             : !> \brief ...
     438             : !> \param opt_embed ...
     439             : !> \param opt_embed_section ...
     440             : ! **************************************************************************************************
     441          72 :    SUBROUTINE read_opt_embed_section(opt_embed, opt_embed_section)
     442             :       TYPE(opt_embed_pot_type)                           :: opt_embed
     443             :       TYPE(section_vals_type), POINTER                   :: opt_embed_section
     444             : 
     445             :       INTEGER                                            :: embed_guess, embed_optimizer
     446             : 
     447             :       ! Read keywords
     448             :       CALL section_vals_val_get(opt_embed_section, "REG_LAMBDA", &
     449          24 :                                 r_val=opt_embed%lambda)
     450             : 
     451             :       CALL section_vals_val_get(opt_embed_section, "N_ITER", &
     452          24 :                                 i_val=opt_embed%n_iter)
     453             : 
     454             :       CALL section_vals_val_get(opt_embed_section, "TRUST_RAD", &
     455          24 :                                 r_val=opt_embed%trust_rad)
     456             : 
     457             :       CALL section_vals_val_get(opt_embed_section, "DENS_CONV_MAX", &
     458          24 :                                 r_val=opt_embed%conv_max)
     459             : 
     460             :       CALL section_vals_val_get(opt_embed_section, "DENS_CONV_INT", &
     461          24 :                                 r_val=opt_embed%conv_int)
     462             : 
     463             :       CALL section_vals_val_get(opt_embed_section, "SPIN_DENS_CONV_MAX", &
     464          24 :                                 r_val=opt_embed%conv_max_spin)
     465             : 
     466             :       CALL section_vals_val_get(opt_embed_section, "SPIN_DENS_CONV_INT", &
     467          24 :                                 r_val=opt_embed%conv_int_spin)
     468             : 
     469             :       CALL section_vals_val_get(opt_embed_section, "CHARGE_DISTR_WIDTH", &
     470          24 :                                 r_val=opt_embed%eta)
     471             : 
     472             :       CALL section_vals_val_get(opt_embed_section, "READ_EMBED_POT", &
     473          24 :                                 l_val=opt_embed%read_embed_pot)
     474             : 
     475             :       CALL section_vals_val_get(opt_embed_section, "READ_EMBED_POT_CUBE", &
     476          24 :                                 l_val=opt_embed%read_embed_pot_cube)
     477             : 
     478             :       CALL section_vals_val_get(opt_embed_section, "GRID_OPT", &
     479          24 :                                 l_val=opt_embed%grid_opt)
     480             : 
     481             :       CALL section_vals_val_get(opt_embed_section, "LEEUWEN-BAERENDS", &
     482          24 :                                 l_val=opt_embed%leeuwen)
     483             : 
     484             :       CALL section_vals_val_get(opt_embed_section, "FAB", &
     485          24 :                                 l_val=opt_embed%fab)
     486             : 
     487             :       CALL section_vals_val_get(opt_embed_section, "VW_CUTOFF", &
     488          24 :                                 r_val=opt_embed%vw_cutoff)
     489             : 
     490             :       CALL section_vals_val_get(opt_embed_section, "VW_SMOOTH_CUT_RANGE", &
     491          24 :                                 r_val=opt_embed%vw_smooth_cutoff_range)
     492             : 
     493          24 :       CALL section_vals_val_get(opt_embed_section, "OPTIMIZER", i_val=embed_optimizer)
     494          14 :       SELECT CASE (embed_optimizer)
     495             :       CASE (embed_steep_desc)
     496          14 :          opt_embed%steep_desc = .TRUE.
     497             :       CASE (embed_quasi_newton)
     498           4 :          opt_embed%steep_desc = .FALSE.
     499           4 :          opt_embed%level_shift = .FALSE.
     500             :       CASE (embed_level_shift)
     501           6 :          opt_embed%steep_desc = .FALSE.
     502           6 :          opt_embed%level_shift = .TRUE.
     503             :       CASE DEFAULT
     504          24 :          opt_embed%steep_desc = .TRUE.
     505             :       END SELECT
     506             : 
     507          24 :       CALL section_vals_val_get(opt_embed_section, "POT_GUESS", i_val=embed_guess)
     508          16 :       SELECT CASE (embed_guess)
     509             :       CASE (embed_none)
     510          16 :          opt_embed%add_const_pot = .FALSE.
     511          16 :          opt_embed%Fermi_Amaldi = .FALSE.
     512          16 :          opt_embed%Coulomb_guess = .FALSE.
     513          16 :          opt_embed%diff_guess = .FALSE.
     514             :       CASE (embed_diff)
     515           2 :          opt_embed%add_const_pot = .TRUE.
     516           2 :          opt_embed%Fermi_Amaldi = .FALSE.
     517           2 :          opt_embed%Coulomb_guess = .FALSE.
     518           2 :          opt_embed%diff_guess = .TRUE.
     519             :       CASE (embed_fa)
     520           4 :          opt_embed%add_const_pot = .TRUE.
     521           4 :          opt_embed%Fermi_Amaldi = .TRUE.
     522           4 :          opt_embed%Coulomb_guess = .FALSE.
     523           4 :          opt_embed%diff_guess = .FALSE.
     524             :       CASE (embed_resp)
     525           2 :          opt_embed%add_const_pot = .TRUE.
     526           2 :          opt_embed%Fermi_Amaldi = .TRUE.
     527           2 :          opt_embed%Coulomb_guess = .TRUE.
     528           2 :          opt_embed%diff_guess = .FALSE.
     529             :       CASE DEFAULT
     530           0 :          opt_embed%add_const_pot = .FALSE.
     531           0 :          opt_embed%Fermi_Amaldi = .FALSE.
     532           0 :          opt_embed%Coulomb_guess = .FALSE.
     533          24 :          opt_embed%diff_guess = .FALSE.
     534             :       END SELECT
     535             : 
     536          24 :    END SUBROUTINE read_opt_embed_section
     537             : 
     538             : ! **************************************************************************************************
     539             : !> \brief Find the dimension of the auxiliary basis for the expansion of the embedding potential
     540             : !> \param qs_env ...
     541             : !> \param dimen_aux ...
     542             : ! **************************************************************************************************
     543          18 :    SUBROUTINE find_aux_dimen(qs_env, dimen_aux)
     544             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     545             :       INTEGER                                            :: dimen_aux
     546             : 
     547             :       INTEGER                                            :: iatom, ikind, nsgf
     548          18 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: kind_of
     549          18 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     550          18 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     551          18 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     552             : 
     553             :       ! First, reveal the dimension of the RI basis
     554             :       CALL get_qs_env(qs_env=qs_env, &
     555             :                       particle_set=particle_set, &
     556             :                       qs_kind_set=qs_kind_set, &
     557          18 :                       atomic_kind_set=atomic_kind_set)
     558             : 
     559          18 :       CALL get_atomic_kind_set(atomic_kind_set, kind_of=kind_of)
     560             : 
     561          18 :       dimen_aux = 0
     562          82 :       DO iatom = 1, SIZE(particle_set)
     563          64 :          ikind = kind_of(iatom)
     564          64 :          CALL get_qs_kind(qs_kind=qs_kind_set(ikind), nsgf=nsgf, basis_type="RI_AUX")
     565          82 :          dimen_aux = dimen_aux + nsgf
     566             :       END DO
     567             : 
     568          36 :    END SUBROUTINE find_aux_dimen
     569             : 
     570             : ! **************************************************************************************************
     571             : !> \brief Prepare the lri_kind_type object for integrals between density and aux. basis functions
     572             : !> \param qs_env ...
     573             : !> \param lri ...
     574             : ! **************************************************************************************************
     575          14 :    SUBROUTINE make_lri_object(qs_env, lri)
     576             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     577             :       TYPE(lri_kind_type), DIMENSION(:), POINTER         :: lri
     578             : 
     579             :       INTEGER                                            :: ikind, natom, nkind, nsgf
     580          14 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     581             :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
     582          14 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     583             : 
     584          14 :       NULLIFY (atomic_kind, lri)
     585             :       CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, &
     586          14 :                       qs_kind_set=qs_kind_set)
     587          14 :       nkind = SIZE(atomic_kind_set)
     588             : 
     589          42 :       ALLOCATE (lri(nkind))
     590             :       ! Here we need only v_int and acoef (the latter as dummies)
     591          34 :       DO ikind = 1, nkind
     592          20 :          NULLIFY (lri(ikind)%acoef)
     593          20 :          NULLIFY (lri(ikind)%v_int)
     594          20 :          atomic_kind => atomic_kind_set(ikind)
     595          20 :          CALL get_atomic_kind(atomic_kind=atomic_kind, natom=natom)
     596          20 :          CALL get_qs_kind(qs_kind=qs_kind_set(ikind), nsgf=nsgf, basis_type="RI_AUX")
     597          80 :          ALLOCATE (lri(ikind)%acoef(natom, nsgf))
     598        2672 :          lri(ikind)%acoef = 0._dp
     599          80 :          ALLOCATE (lri(ikind)%v_int(natom, nsgf))
     600        2706 :          lri(ikind)%v_int = 0._dp
     601             :       END DO
     602             : 
     603          14 :    END SUBROUTINE make_lri_object
     604             : 
     605             : ! **************************************************************************************************
     606             : !> \brief Read the external embedding potential, not to be optimized
     607             : !> \param qs_env ...
     608             : ! **************************************************************************************************
     609           2 :    SUBROUTINE given_embed_pot(qs_env)
     610             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     611             : 
     612             :       LOGICAL                                            :: open_shell_embed
     613             :       TYPE(dft_control_type), POINTER                    :: dft_control
     614             :       TYPE(pw_env_type), POINTER                         :: pw_env
     615             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool_subsys
     616             :       TYPE(pw_r3d_rs_type), POINTER                      :: embed_pot, spin_embed_pot
     617             :       TYPE(section_vals_type), POINTER                   :: input, qs_section
     618             : 
     619           2 :       qs_env%given_embed_pot = .TRUE.
     620           2 :       NULLIFY (input, dft_control, embed_pot, spin_embed_pot, embed_pot, spin_embed_pot, &
     621           2 :                qs_section)
     622             :       CALL get_qs_env(qs_env=qs_env, &
     623             :                       input=input, &
     624             :                       dft_control=dft_control, &
     625           2 :                       pw_env=pw_env)
     626           2 :       qs_section => section_vals_get_subs_vals(input, "DFT%QS")
     627           2 :       open_shell_embed = .FALSE.
     628           2 :       IF (dft_control%nspins .EQ. 2) open_shell_embed = .TRUE.
     629             : 
     630             :       ! Prepare plane-waves pool
     631           2 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool_subsys)
     632             : 
     633             :       ! Create embedding potential
     634             :       !CALL get_qs_env(qs_env=qs_env, &
     635             :       !                embed_pot=embed_pot)
     636           2 :       ALLOCATE (embed_pot)
     637           2 :       CALL auxbas_pw_pool_subsys%create_pw(embed_pot)
     638           2 :       IF (open_shell_embed) THEN
     639             :          ! Create spin embedding potential
     640           2 :          ALLOCATE (spin_embed_pot)
     641           2 :          CALL auxbas_pw_pool_subsys%create_pw(spin_embed_pot)
     642             :       END IF
     643             :       ! Read the cubes
     644           2 :       CALL read_embed_pot_cube(embed_pot, spin_embed_pot, qs_section, open_shell_embed)
     645             : 
     646           2 :       IF (.NOT. open_shell_embed) THEN
     647           0 :          CALL set_qs_env(qs_env=qs_env, embed_pot=embed_pot)
     648             :       ELSE
     649           2 :          CALL set_qs_env(qs_env=qs_env, embed_pot=embed_pot, spin_embed_pot=spin_embed_pot)
     650             :       END IF
     651             : 
     652           2 :    END SUBROUTINE given_embed_pot
     653             : 
     654             : ! **************************************************************************************************
     655             : !> \brief ...
     656             : !> \param qs_env ...
     657             : !> \param embed_pot ...
     658             : !> \param spin_embed_pot ...
     659             : !> \param section ...
     660             : !> \param opt_embed ...
     661             : ! **************************************************************************************************
     662           6 :    SUBROUTINE read_embed_pot(qs_env, embed_pot, spin_embed_pot, section, opt_embed)
     663             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     664             :       TYPE(pw_r3d_rs_type), POINTER                      :: embed_pot, spin_embed_pot
     665             :       TYPE(section_vals_type), POINTER                   :: section
     666             :       TYPE(opt_embed_pot_type)                           :: opt_embed
     667             : 
     668             :       ! Read the potential as a vector in the auxiliary basis
     669           6 :       IF (opt_embed%read_embed_pot) &
     670             :          CALL read_embed_pot_vector(qs_env, embed_pot, spin_embed_pot, section, &
     671           4 :                                     opt_embed%embed_pot_coef, opt_embed%open_shell_embed)
     672             :       ! Read the potential as a cube (two cubes for open shell)
     673           6 :       IF (opt_embed%read_embed_pot_cube) &
     674           2 :          CALL read_embed_pot_cube(embed_pot, spin_embed_pot, section, opt_embed%open_shell_embed)
     675             : 
     676           6 :    END SUBROUTINE read_embed_pot
     677             : 
     678             : ! **************************************************************************************************
     679             : !> \brief ...
     680             : !> \param embed_pot ...
     681             : !> \param spin_embed_pot ...
     682             : !> \param section ...
     683             : !> \param open_shell_embed ...
     684             : ! **************************************************************************************************
     685           4 :    SUBROUTINE read_embed_pot_cube(embed_pot, spin_embed_pot, section, open_shell_embed)
     686             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: embed_pot, spin_embed_pot
     687             :       TYPE(section_vals_type), POINTER                   :: section
     688             :       LOGICAL                                            :: open_shell_embed
     689             : 
     690             :       CHARACTER(LEN=default_path_length)                 :: filename
     691             :       LOGICAL                                            :: exist
     692             :       REAL(KIND=dp)                                      :: scaling_factor
     693             : 
     694           4 :       exist = .FALSE.
     695           4 :       CALL section_vals_val_get(section, "EMBED_CUBE_FILE_NAME", c_val=filename)
     696           4 :       INQUIRE (FILE=filename, exist=exist)
     697           4 :       IF (.NOT. exist) &
     698           0 :          CPABORT("Embedding cube file not found. ")
     699             : 
     700           4 :       scaling_factor = 1.0_dp
     701           4 :       CALL cp_cube_to_pw(embed_pot, filename, scaling_factor)
     702             : 
     703             :       ! Spin-dependent part of the potential
     704           4 :       IF (open_shell_embed) THEN
     705           4 :          exist = .FALSE.
     706           4 :          CALL section_vals_val_get(section, "EMBED_SPIN_CUBE_FILE_NAME", c_val=filename)
     707           4 :          INQUIRE (FILE=filename, exist=exist)
     708           4 :          IF (.NOT. exist) &
     709           0 :             CPABORT("Embedding spin cube file not found. ")
     710             : 
     711             :          scaling_factor = 1.0_dp
     712           4 :          CALL cp_cube_to_pw(spin_embed_pot, filename, scaling_factor)
     713             :       END IF
     714             : 
     715           4 :    END SUBROUTINE read_embed_pot_cube
     716             : 
     717             : ! **************************************************************************************************
     718             : !> \brief Read the embedding potential from the binary file
     719             : !> \param qs_env ...
     720             : !> \param embed_pot ...
     721             : !> \param spin_embed_pot ...
     722             : !> \param section ...
     723             : !> \param embed_pot_coef ...
     724             : !> \param open_shell_embed ...
     725             : ! **************************************************************************************************
     726           4 :    SUBROUTINE read_embed_pot_vector(qs_env, embed_pot, spin_embed_pot, section, embed_pot_coef, open_shell_embed)
     727             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     728             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: embed_pot
     729             :       TYPE(pw_r3d_rs_type), INTENT(IN), POINTER          :: spin_embed_pot
     730             :       TYPE(section_vals_type), POINTER                   :: section
     731             :       TYPE(cp_fm_type), INTENT(IN)                       :: embed_pot_coef
     732             :       LOGICAL, INTENT(IN)                                :: open_shell_embed
     733             : 
     734             :       CHARACTER(LEN=default_path_length)                 :: filename
     735             :       INTEGER                                            :: dimen_aux, dimen_restart_basis, &
     736             :                                                             dimen_var_aux, l_global, LLL, &
     737             :                                                             nrow_local, restart_unit
     738           4 :       INTEGER, DIMENSION(:), POINTER                     :: row_indices
     739           4 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: coef, coef_read
     740             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     741             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
     742             :       TYPE(cp_fm_type)                                   :: my_embed_pot_coef
     743             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     744             : 
     745             :       ! Get the vector dimension
     746           4 :       CALL find_aux_dimen(qs_env, dimen_aux)
     747           4 :       IF (open_shell_embed) THEN
     748           2 :          dimen_var_aux = dimen_aux*2
     749             :       ELSE
     750           2 :          dimen_var_aux = dimen_aux
     751             :       END IF
     752             : 
     753             :       ! We need a temporary vector of coefficients
     754             :       CALL get_qs_env(qs_env=qs_env, &
     755           4 :                       para_env=para_env)
     756           4 :       NULLIFY (blacs_env)
     757           4 :       NULLIFY (fm_struct)
     758           4 :       CALL cp_blacs_env_create(blacs_env=blacs_env, para_env=para_env)
     759             :       CALL cp_fm_struct_create(fm_struct, para_env=para_env, context=blacs_env, &
     760           4 :                                nrow_global=dimen_var_aux, ncol_global=1)
     761           4 :       CALL cp_fm_create(my_embed_pot_coef, fm_struct, name="my_pot_coef")
     762             : 
     763           4 :       CALL cp_fm_struct_release(fm_struct)
     764           4 :       CALL cp_fm_set_all(my_embed_pot_coef, 0.0_dp)
     765             : 
     766             :       ! Read the coefficients vector
     767           4 :       restart_unit = -1
     768             : 
     769             :       ! Allocate the attay to read the coefficients
     770          12 :       ALLOCATE (coef(dimen_var_aux))
     771         636 :       coef = 0.0_dp
     772             : 
     773           4 :       IF (para_env%is_source()) THEN
     774             : 
     775             :          ! Get the restart file name
     776           2 :          CALL embed_restart_file_name(filename, section)
     777             : 
     778             :          CALL open_file(file_name=filename, &
     779             :                         file_action="READ", &
     780             :                         file_form="UNFORMATTED", &
     781             :                         file_status="OLD", &
     782           2 :                         unit_number=restart_unit)
     783             : 
     784           2 :          READ (restart_unit) dimen_restart_basis
     785             :          ! Check the dimensions of the bases: the actual and the restart one
     786           2 :          IF (.NOT. (dimen_restart_basis == dimen_aux)) &
     787           0 :             CPABORT("Wrong dimension of the embedding basis in the restart file.")
     788             : 
     789           6 :          ALLOCATE (coef_read(dimen_var_aux))
     790         318 :          coef_read = 0.0_dp
     791             : 
     792           2 :          READ (restart_unit) coef_read
     793         318 :          coef(:) = coef_read(:)
     794           2 :          DEALLOCATE (coef_read)
     795             : 
     796             :          ! Close restart file
     797           2 :          CALL close_file(unit_number=restart_unit)
     798             : 
     799             :       END IF
     800             : 
     801             :       ! Broadcast the coefficients on all processes
     802           4 :       CALL para_env%bcast(coef)
     803             : 
     804             :       ! Copy to fm_type structure
     805             :       ! Information about full matrix gradient
     806             :       CALL cp_fm_get_info(matrix=my_embed_pot_coef, &
     807             :                           nrow_local=nrow_local, &
     808           4 :                           row_indices=row_indices)
     809             : 
     810         320 :       DO LLL = 1, nrow_local
     811         316 :          l_global = row_indices(LLL)
     812         320 :          my_embed_pot_coef%local_data(LLL, 1) = coef(l_global)
     813             :       END DO
     814             : 
     815           4 :       DEALLOCATE (coef)
     816             : 
     817             :       ! Copy to the my_embed_pot_coef to embed_pot_coef
     818           4 :       CALL cp_fm_copy_general(my_embed_pot_coef, embed_pot_coef, para_env)
     819             : 
     820             :       ! Build the embedding potential on the grid
     821             :       CALL update_embed_pot(embed_pot_coef, dimen_aux, embed_pot, spin_embed_pot, &
     822           4 :                             qs_env, .FALSE., open_shell_embed)
     823             : 
     824             :       ! Release my_embed_pot_coef
     825           4 :       CALL cp_fm_release(my_embed_pot_coef)
     826             : 
     827             :       ! Release blacs environment
     828           4 :       CALL cp_blacs_env_release(blacs_env)
     829             : 
     830          12 :    END SUBROUTINE read_embed_pot_vector
     831             : 
     832             : ! **************************************************************************************************
     833             : !> \brief Find the embedding restart file name
     834             : !> \param filename ...
     835             : !> \param section ...
     836             : ! **************************************************************************************************
     837           2 :    SUBROUTINE embed_restart_file_name(filename, section)
     838             :       CHARACTER(LEN=default_path_length), INTENT(OUT)    :: filename
     839             :       TYPE(section_vals_type), POINTER                   :: section
     840             : 
     841             :       LOGICAL                                            :: exist
     842             : 
     843           2 :       exist = .FALSE.
     844           2 :       CALL section_vals_val_get(section, "EMBED_RESTART_FILE_NAME", c_val=filename)
     845           2 :       INQUIRE (FILE=filename, exist=exist)
     846           2 :       IF (.NOT. exist) &
     847           0 :          CPABORT("Embedding restart file not found. ")
     848             : 
     849           2 :    END SUBROUTINE embed_restart_file_name
     850             : 
     851             : ! **************************************************************************************************
     852             : !> \brief Deallocate stuff for optimizing embedding potential
     853             : !> \param opt_embed ...
     854             : ! **************************************************************************************************
     855          24 :    SUBROUTINE release_opt_embed(opt_embed)
     856             :       TYPE(opt_embed_pot_type)                           :: opt_embed
     857             : 
     858             :       INTEGER                                            :: i_dens, i_spin, ikind
     859             : 
     860          24 :       IF (.NOT. opt_embed%grid_opt) THEN
     861          14 :          CALL cp_fm_release(opt_embed%embed_pot_grad)
     862          14 :          CALL cp_fm_release(opt_embed%embed_pot_coef)
     863          14 :          CALL cp_fm_release(opt_embed%step)
     864          14 :          CALL cp_fm_release(opt_embed%prev_step)
     865          14 :          CALL cp_fm_release(opt_embed%embed_pot_hess)
     866          14 :          CALL cp_fm_release(opt_embed%prev_embed_pot_grad)
     867          14 :          CALL cp_fm_release(opt_embed%prev_embed_pot_coef)
     868          14 :          CALL cp_fm_release(opt_embed%prev_embed_pot_hess)
     869          14 :          CALL cp_fm_release(opt_embed%kinetic_mat)
     870           0 :          DEALLOCATE (opt_embed%embed_pot_grad, opt_embed%embed_pot_coef, &
     871           0 :                      opt_embed%step, opt_embed%prev_step, opt_embed%embed_pot_hess, &
     872           0 :                      opt_embed%prev_embed_pot_grad, opt_embed%prev_embed_pot_coef, &
     873          14 :                      opt_embed%prev_embed_pot_hess, opt_embed%kinetic_mat)
     874          14 :          DEALLOCATE (opt_embed%w_func)
     875          14 :          DEALLOCATE (opt_embed%max_diff)
     876          14 :          DEALLOCATE (opt_embed%int_diff)
     877             : 
     878          34 :          DO ikind = 1, SIZE(opt_embed%lri)
     879          20 :             DEALLOCATE (opt_embed%lri(ikind)%v_int)
     880          34 :             DEALLOCATE (opt_embed%lri(ikind)%acoef)
     881             :          END DO
     882          14 :          DEALLOCATE (opt_embed%lri)
     883             :       END IF
     884             : 
     885          24 :       IF (ASSOCIATED(opt_embed%prev_subsys_dens)) THEN
     886          96 :          DO i_dens = 1, SIZE(opt_embed%prev_subsys_dens)
     887          96 :             CALL opt_embed%prev_subsys_dens(i_dens)%release()
     888             :          END DO
     889          24 :          DEALLOCATE (opt_embed%prev_subsys_dens)
     890             :       END IF
     891          24 :       DEALLOCATE (opt_embed%max_subsys_dens_diff)
     892             : 
     893          24 :       DEALLOCATE (opt_embed%all_nspins)
     894             : 
     895          24 :       IF (ASSOCIATED(opt_embed%const_pot)) THEN
     896           4 :          CALL opt_embed%const_pot%release()
     897           4 :          DEALLOCATE (opt_embed%const_pot)
     898             :       END IF
     899             : 
     900          24 :       IF (ASSOCIATED(opt_embed%pot_diff)) THEN
     901           2 :          CALL opt_embed%pot_diff%release()
     902           2 :          DEALLOCATE (opt_embed%pot_diff)
     903             :       END IF
     904             : 
     905          24 :       IF (ASSOCIATED(opt_embed%prev_embed_pot)) THEN
     906           2 :          CALL opt_embed%prev_embed_pot%release()
     907           2 :          DEALLOCATE (opt_embed%prev_embed_pot)
     908             :       END IF
     909          24 :       IF (ASSOCIATED(opt_embed%prev_spin_embed_pot)) THEN
     910           0 :          CALL opt_embed%prev_spin_embed_pot%release()
     911           0 :          DEALLOCATE (opt_embed%prev_spin_embed_pot)
     912             :       END IF
     913          24 :       IF (ASSOCIATED(opt_embed%v_w)) THEN
     914           4 :          DO i_spin = 1, SIZE(opt_embed%v_w)
     915           4 :             CALL opt_embed%v_w(i_spin)%release()
     916             :          END DO
     917           2 :          DEALLOCATE (opt_embed%v_w)
     918             :       END IF
     919             : 
     920          24 :    END SUBROUTINE release_opt_embed
     921             : 
     922             : ! **************************************************************************************************
     923             : !> \brief Calculates subsystem Coulomb potential from the RESP charges of the total system
     924             : !> \param v_rspace ...
     925             : !> \param rhs ...
     926             : !> \param mapping_section ...
     927             : !> \param qs_env ...
     928             : !> \param nforce_eval ...
     929             : !> \param iforce_eval ...
     930             : !> \param eta ...
     931             : ! **************************************************************************************************
     932           4 :    SUBROUTINE Coulomb_guess(v_rspace, rhs, mapping_section, qs_env, nforce_eval, iforce_eval, eta)
     933             :       TYPE(pw_r3d_rs_type)                               :: v_rspace
     934             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: rhs
     935             :       TYPE(section_vals_type), POINTER                   :: mapping_section
     936             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     937             :       INTEGER                                            :: nforce_eval, iforce_eval
     938             :       REAL(KIND=dp)                                      :: eta
     939             : 
     940             :       INTEGER                                            :: iparticle, jparticle, natom
     941           4 :       INTEGER, DIMENSION(:), POINTER                     :: map_index
     942             :       REAL(KIND=dp)                                      :: dvol, normalize_factor
     943           4 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: rhs_subsys
     944             :       TYPE(particle_list_type), POINTER                  :: particles
     945             :       TYPE(pw_c1d_gs_type)                               :: v_resp_gspace
     946             :       TYPE(pw_env_type), POINTER                         :: pw_env
     947             :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     948             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     949             :       TYPE(pw_r3d_rs_type)                               :: rho_resp, v_resp_rspace
     950             :       TYPE(qs_subsys_type), POINTER                      :: subsys
     951             : 
     952             :       ! Get available particles
     953           4 :       NULLIFY (subsys)
     954           4 :       CALL get_qs_env(qs_env=qs_env, subsys=subsys, pw_env=pw_env)
     955           4 :       CALL qs_subsys_get(subsys, particles=particles)
     956           4 :       natom = particles%n_els
     957             : 
     958          12 :       ALLOCATE (rhs_subsys(natom))
     959             : 
     960           4 :       NULLIFY (map_index)
     961             :       CALL get_subsys_map_index(mapping_section, natom, iforce_eval, nforce_eval, &
     962           4 :                                 map_index, .TRUE.)
     963             : 
     964             :       ! Mapping particles from iforce_eval environment to the embed env
     965          14 :       DO iparticle = 1, natom
     966          10 :          jparticle = map_index(iparticle)
     967          14 :          rhs_subsys(iparticle) = rhs(jparticle)
     968             :       END DO
     969             : 
     970             :       ! Prepare plane waves
     971           4 :       NULLIFY (auxbas_pw_pool)
     972             : 
     973             :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
     974           4 :                       poisson_env=poisson_env)
     975             : 
     976           4 :       CALL auxbas_pw_pool%create_pw(v_resp_gspace)
     977             : 
     978           4 :       CALL auxbas_pw_pool%create_pw(v_resp_rspace)
     979             : 
     980           4 :       CALL auxbas_pw_pool%create_pw(rho_resp)
     981             : 
     982             :       ! Calculate charge density
     983           4 :       CALL pw_zero(rho_resp)
     984           4 :       CALL calculate_rho_resp_all(rho_resp, rhs_subsys, natom, eta, qs_env)
     985             : 
     986             :       ! Calculate potential
     987             :       CALL pw_poisson_solve(poisson_env, rho_resp, &
     988           4 :                             vhartree=v_resp_rspace)
     989           4 :       dvol = v_resp_rspace%pw_grid%dvol
     990           4 :       CALL pw_scale(v_resp_rspace, dvol)
     991           4 :       normalize_factor = SQRT((eta/pi)**3)
     992             :       !normalize_factor = -2.0_dp
     993           4 :       CALL pw_scale(v_resp_rspace, normalize_factor)
     994             : 
     995             :       ! Hard copy potential
     996           4 :       CALL pw_copy(v_resp_rspace, v_rspace)
     997             : 
     998             :       ! Release plane waves
     999           4 :       CALL v_resp_gspace%release()
    1000           4 :       CALL v_resp_rspace%release()
    1001           4 :       CALL rho_resp%release()
    1002             : 
    1003             :       ! Deallocate map_index array
    1004           4 :       DEALLOCATE (map_index)
    1005             :       ! Deallocate charges
    1006           4 :       DEALLOCATE (rhs_subsys)
    1007             : 
    1008           4 :    END SUBROUTINE Coulomb_guess
    1009             : 
    1010             : ! **************************************************************************************************
    1011             : !> \brief Creates a subsystem embedding potential
    1012             : !> \param qs_env ...
    1013             : !> \param embed_pot ...
    1014             : !> \param embed_pot_subsys ...
    1015             : !> \param spin_embed_pot ...
    1016             : !> \param spin_embed_pot_subsys ...
    1017             : !> \param open_shell_embed ...
    1018             : !> \param change_spin_sign ...
    1019             : !> \author Vladimir Rybkin
    1020             : ! **************************************************************************************************
    1021         120 :    SUBROUTINE make_subsys_embed_pot(qs_env, embed_pot, embed_pot_subsys, &
    1022             :                                     spin_embed_pot, spin_embed_pot_subsys, open_shell_embed, &
    1023             :                                     change_spin_sign)
    1024             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1025             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: embed_pot
    1026             :       TYPE(pw_r3d_rs_type), POINTER                      :: embed_pot_subsys
    1027             :       TYPE(pw_r3d_rs_type), INTENT(IN), POINTER          :: spin_embed_pot
    1028             :       TYPE(pw_r3d_rs_type), POINTER                      :: spin_embed_pot_subsys
    1029             :       LOGICAL                                            :: open_shell_embed, change_spin_sign
    1030             : 
    1031             :       TYPE(pw_env_type), POINTER                         :: pw_env
    1032             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool_subsys
    1033             : 
    1034             :       ! Extract  plane waves environment
    1035         120 :       CALL get_qs_env(qs_env, pw_env=pw_env)
    1036             : 
    1037             :       ! Prepare plane-waves pool
    1038         120 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool_subsys)
    1039             : 
    1040             :       ! Create embedding potential and set to zero
    1041             :       NULLIFY (embed_pot_subsys)
    1042         120 :       ALLOCATE (embed_pot_subsys)
    1043         120 :       CALL auxbas_pw_pool_subsys%create_pw(embed_pot_subsys)
    1044             : 
    1045             :       ! Hard copy the grid
    1046         120 :       CALL pw_copy(embed_pot, embed_pot_subsys)
    1047             : 
    1048         120 :       IF (open_shell_embed) THEN
    1049             :          NULLIFY (spin_embed_pot_subsys)
    1050          64 :          ALLOCATE (spin_embed_pot_subsys)
    1051          64 :          CALL auxbas_pw_pool_subsys%create_pw(spin_embed_pot_subsys)
    1052             :          ! Hard copy the grid
    1053          64 :          IF (change_spin_sign) THEN
    1054           8 :             CALL pw_axpy(spin_embed_pot, spin_embed_pot_subsys, -1.0_dp, 0.0_dp, allow_noncompatible_grids=.TRUE.)
    1055             :          ELSE
    1056          56 :             CALL pw_copy(spin_embed_pot, spin_embed_pot_subsys)
    1057             :          END IF
    1058             :       END IF
    1059             : 
    1060         120 :    END SUBROUTINE make_subsys_embed_pot
    1061             : 
    1062             : ! **************************************************************************************************
    1063             : !> \brief Calculates the derivative of the embedding potential wrt to the expansion coefficients
    1064             : !> \param qs_env ...
    1065             : !> \param diff_rho_r ...
    1066             : !> \param diff_rho_spin ...
    1067             : !> \param opt_embed ...
    1068             : !> \author Vladimir Rybkin
    1069             : ! **************************************************************************************************
    1070             : 
    1071          16 :    SUBROUTINE calculate_embed_pot_grad(qs_env, diff_rho_r, diff_rho_spin, opt_embed)
    1072             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1073             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: diff_rho_r, diff_rho_spin
    1074             :       TYPE(opt_embed_pot_type)                           :: opt_embed
    1075             : 
    1076             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_embed_pot_grad'
    1077             : 
    1078             :       INTEGER                                            :: handle
    1079             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1080             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
    1081             :       TYPE(cp_fm_type)                                   :: embed_pot_coeff_spin, &
    1082             :                                                             embed_pot_coeff_spinless, &
    1083             :                                                             regular_term, spin_reg, spinless_reg
    1084             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1085             :       TYPE(pw_env_type), POINTER                         :: pw_env
    1086             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    1087             : 
    1088          16 :       CALL timeset(routineN, handle)
    1089             : 
    1090             :       ! We destroy the previous gradient and Hessian:
    1091             :       ! current data are now previous data
    1092          16 :       CALL cp_fm_to_fm(opt_embed%embed_pot_grad, opt_embed%prev_embed_pot_grad)
    1093          16 :       CALL cp_fm_to_fm(opt_embed%embed_pot_Hess, opt_embed%prev_embed_pot_Hess)
    1094             : 
    1095          16 :       NULLIFY (pw_env)
    1096             : 
    1097          16 :       CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, para_env=para_env)
    1098             : 
    1099             :       ! Get plane waves pool
    1100          16 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    1101             : 
    1102             :       ! Calculate potential gradient coefficients
    1103             :       CALL calculate_embed_pot_grad_inner(qs_env, opt_embed%dimen_aux, diff_rho_r, diff_rho_spin, &
    1104             :                                           opt_embed%embed_pot_grad, &
    1105          16 :                                           opt_embed%open_shell_embed, opt_embed%lri)
    1106             : 
    1107             :       ! Add regularization with kinetic matrix
    1108          16 :       IF (opt_embed%i_iter .EQ. 1) THEN ! Else it is kept in memory
    1109          12 :          CALL compute_kinetic_mat(qs_env, opt_embed%kinetic_mat)
    1110             :       END IF
    1111             : 
    1112             :       CALL cp_fm_get_info(matrix=opt_embed%embed_pot_grad, &
    1113          16 :                           matrix_struct=fm_struct)
    1114          16 :       CALL cp_fm_create(regular_term, fm_struct, name="regular_term")
    1115          16 :       CALL cp_fm_set_all(regular_term, 0.0_dp)
    1116             : 
    1117             :       ! In case of open shell embedding we need two terms of dimen_aux=dimen_var_aux/2 for
    1118             :       ! the spinless and the spin parts
    1119          16 :       IF (opt_embed%open_shell_embed) THEN
    1120             :          ! Prepare auxiliary full matrices
    1121          10 :          NULLIFY (fm_struct, blacs_env)
    1122             : 
    1123             :          !CALL cp_blacs_env_create(blacs_env=blacs_env, para_env=para_env)
    1124             : 
    1125          10 :          CALL cp_fm_get_info(matrix=opt_embed%embed_pot_coef, context=blacs_env)
    1126             :          CALL cp_fm_struct_create(fm_struct, para_env=para_env, context=blacs_env, &
    1127          10 :                                   nrow_global=opt_embed%dimen_aux, ncol_global=1)
    1128          10 :          CALL cp_fm_create(embed_pot_coeff_spinless, fm_struct, name="pot_coeff_spinless")
    1129          10 :          CALL cp_fm_create(embed_pot_coeff_spin, fm_struct, name="pot_coeff_spin")
    1130          10 :          CALL cp_fm_create(spinless_reg, fm_struct, name="spinless_reg")
    1131          10 :          CALL cp_fm_create(spin_reg, fm_struct, name="spin_reg")
    1132          10 :          CALL cp_fm_set_all(embed_pot_coeff_spinless, 0.0_dp)
    1133          10 :          CALL cp_fm_set_all(embed_pot_coeff_spin, 0.0_dp)
    1134          10 :          CALL cp_fm_set_all(spinless_reg, 0.0_dp)
    1135          10 :          CALL cp_fm_set_all(spin_reg, 0.0_dp)
    1136          10 :          CALL cp_fm_struct_release(fm_struct)
    1137             : 
    1138             :          ! Copy coefficients to the auxiliary structures
    1139             :          CALL cp_fm_to_fm_submat(msource=opt_embed%embed_pot_coef, &
    1140             :                                  mtarget=embed_pot_coeff_spinless, &
    1141             :                                  nrow=opt_embed%dimen_aux, ncol=1, &
    1142             :                                  s_firstrow=1, s_firstcol=1, &
    1143          10 :                                  t_firstrow=1, t_firstcol=1)
    1144             :          CALL cp_fm_to_fm_submat(msource=opt_embed%embed_pot_coef, &
    1145             :                                  mtarget=embed_pot_coeff_spin, &
    1146             :                                  nrow=opt_embed%dimen_aux, ncol=1, &
    1147             :                                  s_firstrow=opt_embed%dimen_aux + 1, s_firstcol=1, &
    1148          10 :                                  t_firstrow=1, t_firstcol=1)
    1149             :          ! Multiply
    1150             :          CALL parallel_gemm(transa="N", transb="N", m=opt_embed%dimen_aux, n=1, &
    1151             :                             k=opt_embed%dimen_aux, alpha=1.0_dp, &
    1152             :                             matrix_a=opt_embed%kinetic_mat, matrix_b=embed_pot_coeff_spinless, &
    1153          10 :                             beta=0.0_dp, matrix_c=spinless_reg)
    1154             :          CALL parallel_gemm(transa="N", transb="N", m=opt_embed%dimen_aux, n=1, &
    1155             :                             k=opt_embed%dimen_aux, alpha=1.0_dp, &
    1156             :                             matrix_a=opt_embed%kinetic_mat, matrix_b=embed_pot_coeff_spin, &
    1157          10 :                             beta=0.0_dp, matrix_c=spin_reg)
    1158             :          ! Copy from the auxiliary structures to the full regularization term
    1159             :          CALL cp_fm_to_fm_submat(msource=spinless_reg, &
    1160             :                                  mtarget=regular_term, &
    1161             :                                  nrow=opt_embed%dimen_aux, ncol=1, &
    1162             :                                  s_firstrow=1, s_firstcol=1, &
    1163          10 :                                  t_firstrow=1, t_firstcol=1)
    1164             :          CALL cp_fm_to_fm_submat(msource=spin_reg, &
    1165             :                                  mtarget=regular_term, &
    1166             :                                  nrow=opt_embed%dimen_aux, ncol=1, &
    1167             :                                  s_firstrow=1, s_firstcol=1, &
    1168          10 :                                  t_firstrow=opt_embed%dimen_aux + 1, t_firstcol=1)
    1169             :          ! Release internally used auxiliary structures
    1170          10 :          CALL cp_fm_release(embed_pot_coeff_spinless)
    1171          10 :          CALL cp_fm_release(embed_pot_coeff_spin)
    1172          10 :          CALL cp_fm_release(spin_reg)
    1173          10 :          CALL cp_fm_release(spinless_reg)
    1174             : 
    1175             :       ELSE ! Simply multiply
    1176             :          CALL parallel_gemm(transa="N", transb="N", m=opt_embed%dimen_var_aux, n=1, &
    1177             :                             k=opt_embed%dimen_var_aux, alpha=1.0_dp, &
    1178             :                             matrix_a=opt_embed%kinetic_mat, matrix_b=opt_embed%embed_pot_coef, &
    1179           6 :                             beta=0.0_dp, matrix_c=regular_term)
    1180             :       END IF
    1181             : 
    1182             :       ! Scale by the regularization parameter and add to the gradient
    1183          16 :       CALL cp_fm_scale_and_add(1.0_dp, opt_embed%embed_pot_grad, 4.0_dp*opt_embed%lambda, regular_term)
    1184             : 
    1185             :       ! Calculate the regularization contribution to the energy functional
    1186          16 :       CALL cp_fm_trace(opt_embed%embed_pot_coef, regular_term, opt_embed%reg_term)
    1187          16 :       opt_embed%reg_term = 2.0_dp*opt_embed%lambda*opt_embed%reg_term
    1188             : 
    1189             :       ! Deallocate regular term
    1190          16 :       CALL cp_fm_release(regular_term)
    1191             : 
    1192          16 :       CALL timestop(handle)
    1193             : 
    1194          16 :    END SUBROUTINE calculate_embed_pot_grad
    1195             : 
    1196             : ! **************************************************************************************************
    1197             : !> \brief Performs integration for the embedding potential gradient
    1198             : !> \param qs_env ...
    1199             : !> \param dimen_aux ...
    1200             : !> \param rho_r ...
    1201             : !> \param rho_spin ...
    1202             : !> \param embed_pot_grad ...
    1203             : !> \param open_shell_embed ...
    1204             : !> \param lri ...
    1205             : !> \author Vladimir Rybkin
    1206             : ! **************************************************************************************************
    1207          16 :    SUBROUTINE calculate_embed_pot_grad_inner(qs_env, dimen_aux, rho_r, rho_spin, embed_pot_grad, &
    1208             :                                              open_shell_embed, lri)
    1209             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1210             :       INTEGER                                            :: dimen_aux
    1211             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: rho_r, rho_spin
    1212             :       TYPE(cp_fm_type), INTENT(IN)                       :: embed_pot_grad
    1213             :       LOGICAL                                            :: open_shell_embed
    1214             :       TYPE(lri_kind_type), DIMENSION(:), POINTER         :: lri
    1215             : 
    1216             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_embed_pot_grad_inner'
    1217             : 
    1218             :       INTEGER                                            :: handle, iatom, ikind, l_global, LLL, &
    1219             :                                                             nrow_local, nsgf, start_pos
    1220          16 :       INTEGER, DIMENSION(:), POINTER                     :: row_indices
    1221          16 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: pot_grad
    1222          16 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1223             :       TYPE(cell_type), POINTER                           :: cell
    1224             :       TYPE(dft_control_type), POINTER                    :: dft_control
    1225             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1226          16 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1227          16 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1228             : 
    1229             : ! Needed to store integrals
    1230             : 
    1231          16 :       CALL timeset(routineN, handle)
    1232             : 
    1233             :       CALL get_qs_env(qs_env=qs_env, &
    1234             :                       particle_set=particle_set, &
    1235             :                       qs_kind_set=qs_kind_set, &
    1236             :                       dft_control=dft_control, &
    1237             :                       cell=cell, &
    1238             :                       atomic_kind_set=atomic_kind_set, &
    1239          16 :                       para_env=para_env)
    1240             : 
    1241             :       ! Create wf_vector and gradient
    1242          16 :       IF (open_shell_embed) THEN
    1243          30 :          ALLOCATE (pot_grad(dimen_aux*2))
    1244             :       ELSE
    1245          18 :          ALLOCATE (pot_grad(dimen_aux))
    1246             :       END IF
    1247             : 
    1248             :       ! Use lri subroutine
    1249          38 :       DO ikind = 1, SIZE(lri)
    1250        2750 :          lri(ikind)%v_int = 0.0_dp
    1251             :       END DO
    1252             : 
    1253             :       CALL integrate_v_rspace_one_center(rho_r, qs_env, lri, &
    1254          16 :                                          .FALSE., "RI_AUX")
    1255          38 :       DO ikind = 1, SIZE(lri)
    1256        5462 :          CALL para_env%sum(lri(ikind)%v_int)
    1257             :       END DO
    1258             : 
    1259        2392 :       pot_grad = 0.0_dp
    1260          16 :       start_pos = 1
    1261          38 :       DO ikind = 1, SIZE(lri)
    1262          88 :          DO iatom = 1, SIZE(lri(ikind)%v_int, DIM=1)
    1263          50 :             nsgf = SIZE(lri(ikind)%v_int(iatom, :))
    1264        1826 :             pot_grad(start_pos:start_pos + nsgf - 1) = lri(ikind)%v_int(iatom, :)
    1265          72 :             start_pos = start_pos + nsgf
    1266             :          END DO
    1267             :       END DO
    1268             : 
    1269             :       ! Open-shell embedding
    1270          16 :       IF (open_shell_embed) THEN
    1271          20 :          DO ikind = 1, SIZE(lri)
    1272         920 :             lri(ikind)%v_int = 0.0_dp
    1273             :          END DO
    1274             : 
    1275             :          CALL integrate_v_rspace_one_center(rho_spin, qs_env, lri, &
    1276          10 :                                             .FALSE., "RI_AUX")
    1277          20 :          DO ikind = 1, SIZE(lri)
    1278        1820 :             CALL para_env%sum(lri(ikind)%v_int)
    1279             :          END DO
    1280             : 
    1281          10 :          start_pos = dimen_aux + 1
    1282          20 :          DO ikind = 1, SIZE(lri)
    1283          40 :             DO iatom = 1, SIZE(lri(ikind)%v_int, DIM=1)
    1284          20 :                nsgf = SIZE(lri(ikind)%v_int(iatom, :))
    1285         620 :                pot_grad(start_pos:start_pos + nsgf - 1) = lri(ikind)%v_int(iatom, :)
    1286          30 :                start_pos = start_pos + nsgf
    1287             :             END DO
    1288             :          END DO
    1289             :       END IF
    1290             : 
    1291             :       ! Scale by the cell volume
    1292        2392 :       pot_grad = pot_grad*rho_r%pw_grid%dvol
    1293             : 
    1294             :       ! Information about full matrix gradient
    1295             :       CALL cp_fm_get_info(matrix=embed_pot_grad, &
    1296             :                           nrow_local=nrow_local, &
    1297          16 :                           row_indices=row_indices)
    1298             : 
    1299             :       ! Copy the gradient into the full matrix
    1300        1204 :       DO LLL = 1, nrow_local
    1301        1188 :          l_global = row_indices(LLL)
    1302        1204 :          embed_pot_grad%local_data(LLL, 1) = pot_grad(l_global)
    1303             :       END DO
    1304             : 
    1305          16 :       DEALLOCATE (pot_grad)
    1306             : 
    1307          16 :       CALL timestop(handle)
    1308             : 
    1309          16 :    END SUBROUTINE calculate_embed_pot_grad_inner
    1310             : 
    1311             : ! **************************************************************************************************
    1312             : !> \brief Calculates kinetic energy matrix in auxiliary basis in the fm format
    1313             : !> \param qs_env ...
    1314             : !> \param kinetic_mat ...
    1315             : !> \author Vladimir Rybkin
    1316             : ! **************************************************************************************************
    1317          12 :    SUBROUTINE compute_kinetic_mat(qs_env, kinetic_mat)
    1318             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1319             :       TYPE(cp_fm_type), INTENT(IN)                       :: kinetic_mat
    1320             : 
    1321             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_kinetic_mat'
    1322             : 
    1323             :       INTEGER                                            :: handle
    1324          12 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_t
    1325             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1326          12 :          POINTER                                         :: sab_orb
    1327             :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
    1328             : 
    1329          12 :       CALL timeset(routineN, handle)
    1330             : 
    1331          12 :       NULLIFY (ks_env, sab_orb, matrix_t)
    1332             : 
    1333             :       ! First, get the dbcsr structure from the overlap matrix
    1334          12 :       CALL get_qs_env(qs_env=qs_env, ks_env=ks_env, sab_orb=sab_orb)
    1335             : 
    1336             :       ! Calculate kinetic matrix
    1337             :       CALL build_kinetic_matrix(ks_env, matrix_t=matrix_t, &
    1338             :                                 matrix_name="KINETIC ENERGY MATRIX", &
    1339             :                                 basis_type="RI_AUX", &
    1340          12 :                                 sab_nl=sab_orb, calculate_forces=.FALSE.)
    1341             : 
    1342             :       ! Change to the fm format
    1343          12 :       CALL copy_dbcsr_to_fm(matrix_t(1)%matrix, kinetic_mat)
    1344             : 
    1345             :       ! Release memory
    1346          12 :       CALL dbcsr_deallocate_matrix_set(matrix_t)
    1347             : 
    1348          12 :       CALL timestop(handle)
    1349             : 
    1350          12 :    END SUBROUTINE compute_kinetic_mat
    1351             : 
    1352             : ! **************************************************************************************************
    1353             : !> \brief Regularizes the Wu-Yang potential on the grid
    1354             : !> \param potential ...
    1355             : !> \param pw_env ...
    1356             : !> \param lambda ...
    1357             : !> \param reg_term ...
    1358             : ! **************************************************************************************************
    1359           6 :    SUBROUTINE grid_regularize(potential, pw_env, lambda, reg_term)
    1360             : 
    1361             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: potential
    1362             :       TYPE(pw_env_type), POINTER                         :: pw_env
    1363             :       REAL(KIND=dp)                                      :: lambda, reg_term
    1364             : 
    1365             :       INTEGER                                            :: i, j, k
    1366             :       INTEGER, DIMENSION(3)                              :: lb, n, ub
    1367             :       TYPE(pw_c1d_gs_type)                               :: dr2_pot, grid_reg_g, potential_g
    1368          24 :       TYPE(pw_c1d_gs_type), DIMENSION(3)                 :: dpot_g
    1369             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    1370             :       TYPE(pw_r3d_rs_type)                               :: grid_reg, square_norm_dpot
    1371          24 :       TYPE(pw_r3d_rs_type), DIMENSION(3)                 :: dpot
    1372             : 
    1373             :       !
    1374             :       ! First, the contribution to the gradient
    1375             :       !
    1376             : 
    1377             :       ! Get some of the grids ready
    1378           6 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    1379             : 
    1380           6 :       CALL auxbas_pw_pool%create_pw(potential_g)
    1381             : 
    1382           6 :       CALL auxbas_pw_pool%create_pw(dr2_pot)
    1383             : 
    1384           6 :       CALL auxbas_pw_pool%create_pw(grid_reg)
    1385             : 
    1386           6 :       CALL auxbas_pw_pool%create_pw(grid_reg_g)
    1387           6 :       CALL pw_zero(grid_reg_g)
    1388             : 
    1389             :       ! Transfer potential to the reciprocal space
    1390           6 :       CALL pw_transfer(potential, potential_g)
    1391             : 
    1392             :       ! Calculate second derivatives: dx^2, dy^2, dz^2
    1393          24 :       DO i = 1, 3
    1394          18 :          CALL pw_dr2(potential_g, dr2_pot, i, i)
    1395          24 :          CALL pw_axpy(dr2_pot, grid_reg_g, 1.0_dp)
    1396             :       END DO
    1397             :       ! Transfer potential to the real space
    1398           6 :       CALL pw_transfer(grid_reg_g, grid_reg)
    1399             : 
    1400             :       ! Update the potential with a regularization term
    1401           6 :       CALL pw_axpy(grid_reg, potential, -4.0_dp*lambda)
    1402             : 
    1403             :       !
    1404             :       ! Second, the contribution to the functional
    1405             :       !
    1406          24 :       DO i = 1, 3
    1407          18 :          CALL auxbas_pw_pool%create_pw(dpot(i))
    1408          24 :          CALL auxbas_pw_pool%create_pw(dpot_g(i))
    1409             :       END DO
    1410             : 
    1411           6 :       CALL auxbas_pw_pool%create_pw(square_norm_dpot)
    1412             : 
    1413          24 :       DO i = 1, 3
    1414          18 :          n(:) = 0
    1415          18 :          n(i) = 1
    1416          18 :          CALL pw_copy(potential_g, dpot_g(i))
    1417          18 :          CALL pw_derive(dpot_g(i), n(:))
    1418          24 :          CALL pw_transfer(dpot_g(i), dpot(i))
    1419             :       END DO
    1420             : 
    1421          24 :       lb(1:3) = square_norm_dpot%pw_grid%bounds_local(1, 1:3)
    1422          24 :       ub(1:3) = square_norm_dpot%pw_grid%bounds_local(2, 1:3)
    1423             : !$OMP PARALLEL DO DEFAULT(NONE) &
    1424             : !$OMP             PRIVATE(i,j,k) &
    1425           6 : !$OMP             SHARED(dpot, lb, square_norm_dpot, ub)
    1426             :       DO k = lb(3), ub(3)
    1427             :          DO j = lb(2), ub(2)
    1428             :             DO i = lb(1), ub(1)
    1429             :                square_norm_dpot%array(i, j, k) = (dpot(1)%array(i, j, k)* &
    1430             :                                                   dpot(1)%array(i, j, k) + &
    1431             :                                                   dpot(2)%array(i, j, k)* &
    1432             :                                                   dpot(2)%array(i, j, k) + &
    1433             :                                                   dpot(3)%array(i, j, k)* &
    1434             :                                                   dpot(3)%array(i, j, k))
    1435             :             END DO
    1436             :          END DO
    1437             :       END DO
    1438             : !$OMP END PARALLEL DO
    1439             : 
    1440           6 :       reg_term = 2*lambda*pw_integrate_function(fun=square_norm_dpot)
    1441             : 
    1442             :       ! Release
    1443           6 :       CALL auxbas_pw_pool%give_back_pw(potential_g)
    1444           6 :       CALL auxbas_pw_pool%give_back_pw(dr2_pot)
    1445           6 :       CALL auxbas_pw_pool%give_back_pw(grid_reg)
    1446           6 :       CALL auxbas_pw_pool%give_back_pw(grid_reg_g)
    1447           6 :       CALL auxbas_pw_pool%give_back_pw(square_norm_dpot)
    1448          24 :       DO i = 1, 3
    1449          18 :          CALL auxbas_pw_pool%give_back_pw(dpot(i))
    1450          24 :          CALL auxbas_pw_pool%give_back_pw(dpot_g(i))
    1451             :       END DO
    1452             : 
    1453           6 :    END SUBROUTINE grid_regularize
    1454             : 
    1455             : ! **************************************************************************************************
    1456             : !> \brief Takes maximization step in embedding potential optimization
    1457             : !> \param diff_rho_r ...
    1458             : !> \param diff_rho_spin ...
    1459             : !> \param opt_embed ...
    1460             : !> \param embed_pot ...
    1461             : !> \param spin_embed_pot ...
    1462             : !> \param rho_r_ref ...
    1463             : !> \param qs_env ...
    1464             : !> \author Vladimir Rybkin
    1465             : ! **************************************************************************************************
    1466          24 :    SUBROUTINE opt_embed_step(diff_rho_r, diff_rho_spin, opt_embed, embed_pot, spin_embed_pot, rho_r_ref, qs_env)
    1467             : 
    1468             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: diff_rho_r, diff_rho_spin
    1469             :       TYPE(opt_embed_pot_type)                           :: opt_embed
    1470             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: embed_pot
    1471             :       TYPE(pw_r3d_rs_type), INTENT(IN), POINTER          :: spin_embed_pot
    1472             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r_ref
    1473             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1474             : 
    1475             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'opt_embed_step'
    1476             :       REAL(KIND=dp), PARAMETER                           :: thresh = 0.000001_dp
    1477             : 
    1478             :       INTEGER                                            :: handle, l_global, LLL, nrow_local
    1479          24 :       INTEGER, DIMENSION(:), POINTER                     :: row_indices
    1480          24 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eigenval
    1481             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
    1482             :       TYPE(cp_fm_type)                                   :: diag_grad, diag_step, fm_U, fm_U_scale
    1483             :       TYPE(pw_env_type), POINTER                         :: pw_env
    1484             : 
    1485          24 :       CALL timeset(routineN, handle)
    1486             : 
    1487          24 :       IF (opt_embed%grid_opt) THEN ! Grid based optimization
    1488             : 
    1489           8 :          opt_embed%step_len = opt_embed%trust_rad
    1490           8 :          CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
    1491           8 :          IF (opt_embed%leeuwen) THEN
    1492             :             CALL Leeuwen_Baerends_potential_update(pw_env, embed_pot, spin_embed_pot, diff_rho_r, diff_rho_spin, &
    1493           2 :                                                    rho_r_ref, opt_embed%open_shell_embed, opt_embed%trust_rad)
    1494             :          ELSE
    1495           6 :             IF (opt_embed%fab) THEN
    1496             :                CALL FAB_update(qs_env, rho_r_ref, opt_embed%prev_embed_pot, opt_embed%prev_spin_embed_pot, &
    1497             :                                embed_pot, spin_embed_pot, &
    1498             :                                diff_rho_r, diff_rho_spin, opt_embed%v_w, opt_embed%i_iter, opt_embed%trust_rad, &
    1499           2 :                                opt_embed%open_shell_embed, opt_embed%vw_cutoff, opt_embed%vw_smooth_cutoff_range)
    1500             :             ELSE
    1501           4 :                CALL grid_based_step(diff_rho_r, diff_rho_spin, pw_env, opt_embed, embed_pot, spin_embed_pot)
    1502             :             END IF
    1503             :          END IF
    1504             : 
    1505             :       ELSE ! Finite basis optimization
    1506             :          ! If the previous step has been rejected, we go back to the previous expansion coefficients
    1507          16 :          IF (.NOT. opt_embed%accept_step) &
    1508           0 :             CALL cp_fm_scale_and_add(1.0_dp, opt_embed%embed_pot_coef, -1.0_dp, opt_embed%step)
    1509             : 
    1510             :          ! Do a simple steepest descent
    1511          16 :          IF (opt_embed%steep_desc) THEN
    1512           6 :             IF (opt_embed%i_iter .GT. 2) &
    1513             :                opt_embed%trust_rad = Barzilai_Borwein(opt_embed%step, opt_embed%prev_step, &
    1514           0 :                                                       opt_embed%embed_pot_grad, opt_embed%prev_embed_pot_grad)
    1515           6 :             IF (ABS(opt_embed%trust_rad) .GT. opt_embed%max_trad) THEN
    1516           0 :                IF (opt_embed%trust_rad .GT. 0.0_dp) THEN
    1517           0 :                   opt_embed%trust_rad = opt_embed%max_trad
    1518             :                ELSE
    1519           0 :                   opt_embed%trust_rad = -opt_embed%max_trad
    1520             :                END IF
    1521             :             END IF
    1522             : 
    1523           6 :             CALL cp_fm_to_fm(opt_embed%step, opt_embed%prev_step)
    1524           6 :             CALL cp_fm_scale_and_add(0.0_dp, opt_embed%prev_step, 1.0_dp, opt_embed%step)
    1525           6 :             CALL cp_fm_set_all(opt_embed%step, 0.0_dp)
    1526           6 :             CALL cp_fm_scale_and_add(1.0_dp, opt_embed%step, opt_embed%trust_rad, opt_embed%embed_pot_grad)
    1527           6 :             opt_embed%step_len = opt_embed%trust_rad
    1528             :          ELSE
    1529             : 
    1530             :             ! First, update the Hessian inverse if needed
    1531          10 :             IF (opt_embed%i_iter > 1) THEN
    1532           2 :                IF (opt_embed%accept_step) & ! We don't update Hessian if the step has been rejected
    1533             :                   CALL symm_rank_one_update(opt_embed%embed_pot_grad, opt_embed%prev_embed_pot_grad, &
    1534           2 :                                             opt_embed%step, opt_embed%prev_embed_pot_Hess, opt_embed%embed_pot_Hess)
    1535             :             END IF
    1536             : 
    1537             :             ! Add regularization term to the Hessian
    1538             :             !CALL cp_fm_scale_and_add(1.0_dp, opt_embed%embed_pot_Hess, 4.0_dp*opt_embed%lambda, &
    1539             :             !                         opt_embed%kinetic_mat)
    1540             : 
    1541             :             ! Else use the first initial Hessian. Now it's just the unit matrix: embed_pot_hess
    1542             :             ! Second, invert the Hessian
    1543          30 :             ALLOCATE (eigenval(opt_embed%dimen_var_aux))
    1544        1666 :             eigenval = 0.0_dp
    1545             :             CALL cp_fm_get_info(matrix=opt_embed%embed_pot_hess, &
    1546          10 :                                 matrix_struct=fm_struct)
    1547          10 :             CALL cp_fm_create(fm_U, fm_struct, name="fm_U")
    1548          10 :             CALL cp_fm_create(fm_U_scale, fm_struct, name="fm_U")
    1549          10 :             CALL cp_fm_set_all(fm_U, 0.0_dp)
    1550          10 :             CALL cp_fm_set_all(fm_U_scale, 0.0_dp)
    1551             :             CALL cp_fm_get_info(matrix=opt_embed%embed_pot_grad, &
    1552          10 :                                 matrix_struct=fm_struct)
    1553          10 :             CALL cp_fm_create(diag_grad, fm_struct, name="diag_grad")
    1554          10 :             CALL cp_fm_set_all(diag_grad, 0.0_dp)
    1555          10 :             CALL cp_fm_create(diag_step, fm_struct, name="diag_step")
    1556          10 :             CALL cp_fm_set_all(diag_step, 0.0_dp)
    1557             : 
    1558             :             ! Store the Hessian as it will be destroyed in diagonalization: use fm_U_scal for it
    1559          10 :             CALL cp_fm_to_fm(opt_embed%embed_pot_hess, fm_U_scale)
    1560             : 
    1561             :             ! Diagonalize Hessian
    1562          10 :             CALL choose_eigv_solver(opt_embed%embed_pot_hess, fm_U, eigenval)
    1563             : 
    1564             :             ! Copy the Hessian back
    1565          10 :             CALL cp_fm_to_fm(fm_U_scale, opt_embed%embed_pot_hess)
    1566             : 
    1567             :             ! Find the step in diagonal representation, begin with gradient
    1568             :             CALL parallel_gemm(transa="T", transb="N", m=opt_embed%dimen_var_aux, n=1, &
    1569             :                                k=opt_embed%dimen_var_aux, alpha=1.0_dp, &
    1570             :                                matrix_a=fm_U, matrix_b=opt_embed%embed_pot_grad, beta=0.0_dp, &
    1571          10 :                                matrix_c=diag_grad)
    1572             : 
    1573             :             CALL cp_fm_get_info(matrix=opt_embed%embed_pot_coef, &
    1574             :                                 nrow_local=nrow_local, &
    1575          10 :                                 row_indices=row_indices)
    1576             : 
    1577         838 :             DO LLL = 1, nrow_local
    1578         828 :                l_global = row_indices(LLL)
    1579         838 :                IF (ABS(eigenval(l_global)) .GE. thresh) THEN
    1580             :                   diag_step%local_data(LLL, 1) = &
    1581         828 :                      -diag_grad%local_data(LLL, 1)/(eigenval(l_global))
    1582             :                ELSE
    1583           0 :                   diag_step%local_data(LLL, 1) = 0.0_dp
    1584             :                END IF
    1585             :             END DO
    1586          10 :             CALL cp_fm_trace(diag_step, diag_step, opt_embed%step_len)
    1587             : 
    1588             :             ! Transform step to a non-diagonal representation
    1589             :             CALL parallel_gemm(transa="N", transb="N", m=opt_embed%dimen_var_aux, n=1, &
    1590             :                                k=opt_embed%dimen_var_aux, alpha=1.0_dp, &
    1591             :                                matrix_a=fm_U, matrix_b=diag_step, beta=0.0_dp, &
    1592          10 :                                matrix_c=opt_embed%step)
    1593             : 
    1594             :             ! Now use fm_U_scale for scaled eigenvectors
    1595          10 :             CALL cp_fm_to_fm(fm_U, fm_U_scale)
    1596          10 :             CALL cp_fm_column_scale(fm_U_scale, eigenval)
    1597             : 
    1598          10 :             CALL cp_fm_release(fm_U_scale)
    1599             : 
    1600             :             ! Scale the step to fit within the trust radius: it it's less already,
    1601             :             ! then take the Newton step
    1602          10 :             CALL cp_fm_trace(opt_embed%step, opt_embed%step, opt_embed%step_len)
    1603          10 :             IF (opt_embed%step_len .GT. opt_embed%trust_rad) THEN
    1604             : 
    1605           2 :                IF (opt_embed%level_shift) THEN
    1606             :                   ! Find a level shift parameter and apply it
    1607           2 :                   CALL level_shift(opt_embed, diag_grad, eigenval, diag_step)
    1608             :                ELSE ! Just scale
    1609           0 :                   CALL cp_fm_trace(diag_step, diag_step, opt_embed%step_len)
    1610           0 :                   CALL cp_fm_scale(opt_embed%trust_rad/opt_embed%step_len, diag_step)
    1611             :                END IF
    1612           2 :                CALL cp_fm_trace(diag_step, diag_step, opt_embed%step_len)
    1613             :                ! Transform step to a non-diagonal representation
    1614             :                CALL parallel_gemm(transa="N", transb="N", m=opt_embed%dimen_var_aux, n=1, &
    1615             :                                   k=opt_embed%dimen_var_aux, alpha=1.0_dp, &
    1616             :                                   matrix_a=fm_U, matrix_b=diag_step, beta=0.0_dp, &
    1617           2 :                                   matrix_c=opt_embed%step)
    1618           2 :                CALL cp_fm_trace(opt_embed%step, opt_embed%step, opt_embed%step_len)
    1619             : 
    1620             :                ! Recalculate step in diagonal representation
    1621           2 :                opt_embed%newton_step = .FALSE.
    1622             :             ELSE
    1623           8 :                opt_embed%newton_step = .TRUE.
    1624             :             END IF
    1625             : 
    1626             :             ! Release some memory
    1627          10 :             DEALLOCATE (eigenval)
    1628             :             ! Release more memory
    1629          10 :             CALL cp_fm_release(diag_grad)
    1630          10 :             CALL cp_fm_release(diag_step)
    1631          20 :             CALL cp_fm_release(fm_U)
    1632             : 
    1633             :          END IF ! grad_descent
    1634             : 
    1635             :          ! Update the coefficients
    1636          16 :          CALL cp_fm_scale_and_add(1.0_dp, opt_embed%embed_pot_coef, 1.0_dp, opt_embed%step)
    1637             : 
    1638             :          ! Update the embedding potential
    1639             :          CALL update_embed_pot(opt_embed%embed_pot_coef, opt_embed%dimen_aux, embed_pot, &
    1640             :                                spin_embed_pot, qs_env, opt_embed%add_const_pot, &
    1641          16 :                                opt_embed%open_shell_embed, opt_embed%const_pot)
    1642             :       END IF ! Grid-based optimization
    1643             : 
    1644          24 :       CALL timestop(handle)
    1645             : 
    1646          48 :    END SUBROUTINE opt_embed_step
    1647             : 
    1648             : !
    1649             : ! **************************************************************************************************
    1650             : !> \brief ...
    1651             : !> \param diff_rho_r ...
    1652             : !> \param diff_rho_spin ...
    1653             : !> \param pw_env ...
    1654             : !> \param opt_embed ...
    1655             : !> \param embed_pot ...
    1656             : !> \param spin_embed_pot ...
    1657             : ! **************************************************************************************************
    1658           4 :    SUBROUTINE grid_based_step(diff_rho_r, diff_rho_spin, pw_env, opt_embed, embed_pot, spin_embed_pot)
    1659             : 
    1660             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: diff_rho_r, diff_rho_spin
    1661             :       TYPE(pw_env_type), POINTER                         :: pw_env
    1662             :       TYPE(opt_embed_pot_type)                           :: opt_embed
    1663             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: embed_pot
    1664             :       TYPE(pw_r3d_rs_type), POINTER                      :: spin_embed_pot
    1665             : 
    1666             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'grid_based_step'
    1667             : 
    1668             :       INTEGER                                            :: handle
    1669             :       REAL(KIND=dp)                                      :: my_reg_term
    1670             : 
    1671           4 :       CALL timeset(routineN, handle)
    1672             : 
    1673             :       ! Take the step for spin-free part
    1674           4 :       CALL pw_axpy(diff_rho_r, embed_pot, opt_embed%step_len)
    1675             :       ! Regularize
    1676           4 :       CALL grid_regularize(embed_pot, pw_env, opt_embed%lambda, my_reg_term)
    1677           4 :       opt_embed%reg_term = opt_embed%reg_term + my_reg_term
    1678             : 
    1679           4 :       IF (opt_embed%open_shell_embed) THEN
    1680           2 :          CALL pw_axpy(diff_rho_spin, spin_embed_pot, opt_embed%step_len)
    1681           2 :          CALL grid_regularize(spin_embed_pot, pw_env, opt_embed%lambda, my_reg_term)
    1682           2 :          opt_embed%reg_term = opt_embed%reg_term + my_reg_term
    1683             :       END IF
    1684             : 
    1685           4 :       CALL timestop(handle)
    1686             : 
    1687           4 :    END SUBROUTINE grid_based_step
    1688             : 
    1689             : ! **************************************************************************************************
    1690             : !> \brief ... Adds variable part of to the embedding potential
    1691             : !> \param embed_pot_coef ...
    1692             : !> \param dimen_aux ...
    1693             : !> \param embed_pot ...
    1694             : !> \param spin_embed_pot ...
    1695             : !> \param qs_env ...
    1696             : !> \param add_const_pot ...
    1697             : !> \param open_shell_embed ...
    1698             : !> \param const_pot ...
    1699             : !> \author Vladimir Rybkin
    1700             : ! **************************************************************************************************
    1701             : 
    1702          20 :    SUBROUTINE update_embed_pot(embed_pot_coef, dimen_aux, embed_pot, spin_embed_pot, &
    1703             :                                qs_env, add_const_pot, open_shell_embed, const_pot)
    1704             :       TYPE(cp_fm_type), INTENT(IN)                       :: embed_pot_coef
    1705             :       INTEGER                                            :: dimen_aux
    1706             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: embed_pot
    1707             :       TYPE(pw_r3d_rs_type), INTENT(IN), POINTER          :: spin_embed_pot
    1708             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1709             :       LOGICAL                                            :: add_const_pot, open_shell_embed
    1710             :       TYPE(pw_r3d_rs_type), INTENT(IN), OPTIONAL         :: const_pot
    1711             : 
    1712             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'update_embed_pot'
    1713             : 
    1714             :       INTEGER                                            :: handle, l_global, LLL, nrow_local
    1715          20 :       INTEGER, DIMENSION(:), POINTER                     :: row_indices
    1716             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: wf_vector
    1717          20 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1718             :       TYPE(cell_type), POINTER                           :: cell
    1719             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1720             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
    1721             :       TYPE(cp_fm_type)                                   :: embed_pot_coef_spin, &
    1722             :                                                             embed_pot_coef_spinless
    1723             :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    1724             :       TYPE(dft_control_type), POINTER                    :: dft_control
    1725          20 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    1726             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1727          20 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1728             :       TYPE(pw_c1d_gs_type)                               :: rho_g
    1729             :       TYPE(pw_env_type), POINTER                         :: pw_env
    1730             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    1731             :       TYPE(pw_r3d_rs_type)                               :: psi_L
    1732          20 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1733             : 
    1734          20 :       CALL timeset(routineN, handle)
    1735             :       ! Get MO coefficients: we need only the structure, therefore don't care about the spin
    1736             :       CALL get_qs_env(qs_env=qs_env, &
    1737             :                       particle_set=particle_set, &
    1738             :                       qs_kind_set=qs_kind_set, &
    1739             :                       dft_control=dft_control, &
    1740             :                       cell=cell, &
    1741             :                       atomic_kind_set=atomic_kind_set, &
    1742          20 :                       pw_env=pw_env, mos=mos, para_env=para_env)
    1743          20 :       CALL get_mo_set(mo_set=mos(1), mo_coeff=mo_coeff)
    1744             : 
    1745             :       ! Get plane waves pool
    1746          20 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    1747             : 
    1748             :       ! get some of the grids ready
    1749          20 :       CALL auxbas_pw_pool%create_pw(rho_g)
    1750             : 
    1751          20 :       CALL auxbas_pw_pool%create_pw(psi_L)
    1752             : 
    1753             :       ! Create wf_vector and auxiliary wave functions
    1754          60 :       ALLOCATE (wf_vector(dimen_aux))
    1755        2308 :       wf_vector = 0.0_dp
    1756             : 
    1757             :       ! Create auxiliary full matrices for open-shell case
    1758          20 :       IF (open_shell_embed) THEN
    1759          12 :          NULLIFY (blacs_env)
    1760          12 :          CALL cp_fm_get_info(matrix=embed_pot_coef, context=blacs_env)
    1761             :          CALL cp_fm_struct_create(fm_struct, para_env=para_env, context=blacs_env, &
    1762          12 :                                   nrow_global=dimen_aux, ncol_global=1)
    1763          12 :          CALL cp_fm_create(embed_pot_coef_spinless, fm_struct, name="pot_coeff_spinless")
    1764          12 :          CALL cp_fm_create(embed_pot_coef_spin, fm_struct, name="pot_coeff_spin")
    1765          12 :          CALL cp_fm_set_all(embed_pot_coef_spinless, 0.0_dp)
    1766          12 :          CALL cp_fm_set_all(embed_pot_coef_spin, 0.0_dp)
    1767          12 :          CALL cp_fm_struct_release(fm_struct)
    1768             : 
    1769             :          ! Copy coefficients to the auxiliary structures
    1770             :          CALL cp_fm_to_fm_submat(embed_pot_coef, &
    1771             :                                  mtarget=embed_pot_coef_spinless, &
    1772             :                                  nrow=dimen_aux, ncol=1, &
    1773             :                                  s_firstrow=1, s_firstcol=1, &
    1774          12 :                                  t_firstrow=1, t_firstcol=1)
    1775             :          CALL cp_fm_to_fm_submat(embed_pot_coef, &
    1776             :                                  mtarget=embed_pot_coef_spin, &
    1777             :                                  nrow=dimen_aux, ncol=1, &
    1778             :                                  s_firstrow=dimen_aux + 1, s_firstcol=1, &
    1779          12 :                                  t_firstrow=1, t_firstcol=1)
    1780             : 
    1781             :          ! Spinless potential
    1782             :          CALL cp_fm_get_info(matrix=embed_pot_coef_spinless, &
    1783             :                              nrow_local=nrow_local, &
    1784          12 :                              row_indices=row_indices)
    1785             : 
    1786             :          ! Copy fm_coeff to an array
    1787         372 :          DO LLL = 1, nrow_local
    1788         360 :             l_global = row_indices(LLL)
    1789         372 :             wf_vector(l_global) = embed_pot_coef_spinless%local_data(LLL, 1)
    1790             :          END DO
    1791          12 :          CALL para_env%sum(wf_vector)
    1792             : 
    1793             :          ! Calculate the variable part of the embedding potential
    1794             :          CALL calculate_wavefunction(mo_coeff, 1, psi_L, rho_g, atomic_kind_set, &
    1795             :                                      qs_kind_set, cell, dft_control, particle_set, pw_env, &
    1796             :                                      basis_type="RI_AUX", &
    1797          12 :                                      external_vector=wf_vector)
    1798             :          ! Update the full embedding potential
    1799          12 :          IF (add_const_pot) THEN
    1800           0 :             CALL pw_copy(const_pot, embed_pot)
    1801             :          ELSE
    1802          12 :             CALL pw_zero(embed_pot)
    1803             :          END IF
    1804             : 
    1805          12 :          CALL pw_axpy(psi_L, embed_pot)
    1806             : 
    1807             :          ! Spin-dependent potential
    1808         732 :          wf_vector = 0.0_dp
    1809             :          CALL cp_fm_get_info(matrix=embed_pot_coef_spin, &
    1810             :                              nrow_local=nrow_local, &
    1811          12 :                              row_indices=row_indices)
    1812             : 
    1813             :          ! Copy fm_coeff to an array
    1814         372 :          DO LLL = 1, nrow_local
    1815         360 :             l_global = row_indices(LLL)
    1816         372 :             wf_vector(l_global) = embed_pot_coef_spin%local_data(LLL, 1)
    1817             :          END DO
    1818          12 :          CALL para_env%sum(wf_vector)
    1819             : 
    1820             :          ! Calculate the variable part of the embedding potential
    1821             :          CALL calculate_wavefunction(mo_coeff, 1, psi_L, rho_g, atomic_kind_set, &
    1822             :                                      qs_kind_set, cell, dft_control, particle_set, pw_env, &
    1823             :                                      basis_type="RI_AUX", &
    1824          12 :                                      external_vector=wf_vector)
    1825             :          ! No constant potential for spin-dependent potential
    1826          12 :          CALL pw_zero(spin_embed_pot)
    1827          12 :          CALL pw_axpy(psi_L, spin_embed_pot)
    1828             : 
    1829             :       ELSE ! Closed shell
    1830             : 
    1831             :          CALL cp_fm_get_info(matrix=embed_pot_coef, &
    1832             :                              nrow_local=nrow_local, &
    1833           8 :                              row_indices=row_indices)
    1834             : 
    1835             :          ! Copy fm_coeff to an array
    1836         792 :          DO LLL = 1, nrow_local
    1837         784 :             l_global = row_indices(LLL)
    1838         792 :             wf_vector(l_global) = embed_pot_coef%local_data(LLL, 1)
    1839             :          END DO
    1840           8 :          CALL para_env%sum(wf_vector)
    1841             : 
    1842             :          ! Calculate the variable part of the embedding potential
    1843             :          CALL calculate_wavefunction(mo_coeff, 1, psi_L, rho_g, atomic_kind_set, &
    1844           8 :                                      qs_kind_set, cell, dft_control, particle_set, pw_env)
    1845             : 
    1846             :          CALL calculate_wavefunction(mo_coeff, 1, psi_L, rho_g, atomic_kind_set, &
    1847             :                                      qs_kind_set, cell, dft_control, particle_set, pw_env, &
    1848             :                                      basis_type="RI_AUX", &
    1849           8 :                                      external_vector=wf_vector)
    1850             : 
    1851             :          ! Update the full embedding potential
    1852           8 :          IF (add_const_pot) THEN
    1853           2 :             CALL pw_copy(const_pot, embed_pot)
    1854             :          ELSE
    1855           6 :             CALL pw_zero(embed_pot)
    1856             :          END IF
    1857             : 
    1858           8 :          CALL pw_axpy(psi_L, embed_pot)
    1859             :       END IF ! Open/closed shell
    1860             : 
    1861             :       ! Deallocate memory and release objects
    1862          20 :       DEALLOCATE (wf_vector)
    1863          20 :       CALL auxbas_pw_pool%give_back_pw(psi_L)
    1864          20 :       CALL auxbas_pw_pool%give_back_pw(rho_g)
    1865             : 
    1866          20 :       IF (open_shell_embed) THEN
    1867          12 :          CALL cp_fm_release(embed_pot_coef_spin)
    1868          12 :          CALL cp_fm_release(embed_pot_coef_spinless)
    1869             :       END IF
    1870             : 
    1871          20 :       CALL timestop(handle)
    1872             : 
    1873          20 :    END SUBROUTINE update_embed_pot
    1874             : 
    1875             : ! **************************************************************************************************
    1876             : !> \brief BFGS update of the inverse Hessian in the full matrix format
    1877             : !> \param grad ...
    1878             : !> \param prev_grad ...
    1879             : !> \param step ...
    1880             : !> \param prev_inv_Hess ...
    1881             : !> \param inv_Hess ...
    1882             : !> \author Vladimir Rybkin
    1883             : ! **************************************************************************************************
    1884           0 :    SUBROUTINE inv_Hessian_update(grad, prev_grad, step, prev_inv_Hess, inv_Hess)
    1885             :       TYPE(cp_fm_type), INTENT(IN)                       :: grad, prev_grad, step, prev_inv_Hess, &
    1886             :                                                             inv_Hess
    1887             : 
    1888             :       INTEGER                                            :: mat_size
    1889             :       REAL(KIND=dp)                                      :: factor1, s_dot_y, y_dot_B_inv_y
    1890             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_mat, fm_struct_vec
    1891             :       TYPE(cp_fm_type)                                   :: B_inv_y, B_inv_y_s, s_s, s_y, s_y_B_inv, &
    1892             :                                                             y
    1893             : 
    1894             :       ! Recover the dimension
    1895             :       CALL cp_fm_get_info(matrix=inv_Hess, &
    1896           0 :                           nrow_global=mat_size)
    1897             : 
    1898           0 :       CALL cp_fm_set_all(inv_Hess, 0.0_dp)
    1899           0 :       CALL cp_fm_to_fm(prev_inv_Hess, inv_Hess)
    1900             : 
    1901             :       ! Get full matrix structures
    1902           0 :       NULLIFY (fm_struct_mat, fm_struct_vec)
    1903             : 
    1904             :       CALL cp_fm_get_info(matrix=prev_inv_Hess, &
    1905           0 :                           matrix_struct=fm_struct_mat)
    1906             :       CALL cp_fm_get_info(matrix=grad, &
    1907           0 :                           matrix_struct=fm_struct_vec)
    1908             : 
    1909             :       ! Allocate intermediates
    1910           0 :       CALL cp_fm_create(B_inv_y, fm_struct_vec, name="B_inv_y")
    1911           0 :       CALL cp_fm_create(y, fm_struct_vec, name="y")
    1912             : 
    1913           0 :       CALL cp_fm_create(s_s, fm_struct_mat, name="s_s")
    1914           0 :       CALL cp_fm_create(s_y, fm_struct_mat, name="s_y")
    1915           0 :       CALL cp_fm_create(B_inv_y_s, fm_struct_mat, name="B_inv_y_s")
    1916           0 :       CALL cp_fm_create(s_y_B_inv, fm_struct_mat, name="s_y_B_inv")
    1917             : 
    1918           0 :       CALL cp_fm_set_all(B_inv_y, 0.0_dp)
    1919           0 :       CALL cp_fm_set_all(s_s, 0.0_dp)
    1920           0 :       CALL cp_fm_set_all(s_y, 0.0_dp)
    1921           0 :       CALL cp_fm_set_all(B_inv_y_s, 0.0_dp)
    1922           0 :       CALL cp_fm_set_all(s_y_B_inv, 0.0_dp)
    1923             : 
    1924             :       ! Calculate intermediates
    1925             :       ! y the is gradient difference
    1926           0 :       CALL cp_fm_get_info(matrix=grad)
    1927           0 :       CALL cp_fm_to_fm(grad, y)
    1928           0 :       CALL cp_fm_scale_and_add(1.0_dp, y, -1.0_dp, prev_grad)
    1929             : 
    1930             :       ! First term
    1931             :       CALL parallel_gemm(transa="N", transb="N", m=mat_size, n=1, &
    1932             :                          k=mat_size, alpha=1.0_dp, &
    1933             :                          matrix_a=prev_inv_Hess, matrix_b=y, beta=0.0_dp, &
    1934           0 :                          matrix_c=B_inv_y)
    1935             : 
    1936             :       CALL parallel_gemm(transa="N", transb="T", m=mat_size, n=mat_size, &
    1937             :                          k=1, alpha=1.0_dp, &
    1938             :                          matrix_a=step, matrix_b=step, beta=0.0_dp, &
    1939           0 :                          matrix_c=s_s)
    1940             : 
    1941             :       CALL parallel_gemm(transa="N", transb="T", m=mat_size, n=mat_size, &
    1942             :                          k=1, alpha=1.0_dp, &
    1943             :                          matrix_a=step, matrix_b=y, beta=0.0_dp, &
    1944           0 :                          matrix_c=s_y)
    1945             : 
    1946           0 :       CALL cp_fm_trace(step, y, s_dot_y)
    1947             : 
    1948           0 :       CALL cp_fm_trace(y, y, s_dot_y)
    1949           0 :       CALL cp_fm_trace(step, step, s_dot_y)
    1950             : 
    1951           0 :       CALL cp_fm_trace(y, B_inv_y, y_dot_B_inv_y)
    1952             : 
    1953           0 :       factor1 = (s_dot_y + y_dot_B_inv_y)/(s_dot_y)**2
    1954             : 
    1955           0 :       CALL cp_fm_scale_and_add(1.0_dp, inv_Hess, factor1, s_s)
    1956             : 
    1957             :       ! Second term
    1958             :       CALL parallel_gemm(transa="N", transb="T", m=mat_size, n=mat_size, &
    1959             :                          k=1, alpha=1.0_dp, &
    1960             :                          matrix_a=B_inv_y, matrix_b=step, beta=0.0_dp, &
    1961           0 :                          matrix_c=B_inv_y_s)
    1962             : 
    1963             :       CALL parallel_gemm(transa="N", transb="N", m=mat_size, n=mat_size, &
    1964             :                          k=mat_size, alpha=1.0_dp, &
    1965             :                          matrix_a=s_y, matrix_b=prev_inv_Hess, beta=0.0_dp, &
    1966           0 :                          matrix_c=s_y_B_inv)
    1967             : 
    1968           0 :       CALL cp_fm_scale_and_add(1.0_dp, B_inv_y_s, 1.0_dp, s_y_B_inv)
    1969             : 
    1970             :       ! Assemble the new inverse Hessian
    1971           0 :       CALL cp_fm_scale_and_add(1.0_dp, inv_Hess, -s_dot_y, B_inv_y_s)
    1972             : 
    1973             :       ! Deallocate intermediates
    1974           0 :       CALL cp_fm_release(y)
    1975           0 :       CALL cp_fm_release(B_inv_y)
    1976           0 :       CALL cp_fm_release(s_s)
    1977           0 :       CALL cp_fm_release(s_y)
    1978           0 :       CALL cp_fm_release(B_inv_y_s)
    1979           0 :       CALL cp_fm_release(s_y_B_inv)
    1980             : 
    1981           0 :    END SUBROUTINE inv_Hessian_update
    1982             : 
    1983             : ! **************************************************************************************************
    1984             : !> \brief ...
    1985             : !> \param grad ...
    1986             : !> \param prev_grad ...
    1987             : !> \param step ...
    1988             : !> \param prev_Hess ...
    1989             : !> \param Hess ...
    1990             : ! **************************************************************************************************
    1991           0 :    SUBROUTINE Hessian_update(grad, prev_grad, step, prev_Hess, Hess)
    1992             :       TYPE(cp_fm_type), INTENT(IN)                       :: grad, prev_grad, step, prev_Hess, Hess
    1993             : 
    1994             :       INTEGER                                            :: mat_size
    1995             :       REAL(KIND=dp)                                      :: s_b_s, y_t_s
    1996             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1997             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_mat, fm_struct_vec, &
    1998             :                                                             fm_struct_vec_t
    1999             :       TYPE(cp_fm_type)                                   :: B_s, B_s_s_B, s_t_B, y, y_y_t
    2000             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2001             : 
    2002             :       ! Recover the dimension
    2003             :       CALL cp_fm_get_info(matrix=Hess, &
    2004           0 :                           nrow_global=mat_size, para_env=para_env)
    2005             : 
    2006           0 :       CALL cp_fm_set_all(Hess, 0.0_dp)
    2007           0 :       CALL cp_fm_to_fm(prev_Hess, Hess)
    2008             : 
    2009             :       ! WARNING: our Hessian must be negative-definite, whereas BFGS makes it positive-definite!
    2010             :       ! Therefore, we change sign in the beginning and in the end.
    2011           0 :       CALL cp_fm_scale(-1.0_dp, Hess)
    2012             : 
    2013             :       ! Create blacs environment
    2014           0 :       NULLIFY (blacs_env)
    2015           0 :       CALL cp_blacs_env_create(blacs_env=blacs_env, para_env=para_env)
    2016             : 
    2017             :       ! Get full matrix structures
    2018           0 :       NULLIFY (fm_struct_mat, fm_struct_vec, fm_struct_vec_t)
    2019             : 
    2020             :       CALL cp_fm_get_info(matrix=prev_Hess, &
    2021           0 :                           matrix_struct=fm_struct_mat)
    2022             :       CALL cp_fm_get_info(matrix=grad, &
    2023           0 :                           matrix_struct=fm_struct_vec)
    2024             :       CALL cp_fm_struct_create(fm_struct_vec_t, para_env=para_env, context=blacs_env, &
    2025           0 :                                nrow_global=1, ncol_global=mat_size)
    2026             : 
    2027             :       ! Allocate intermediates
    2028           0 :       CALL cp_fm_create(B_s, fm_struct_vec, name="B_s")
    2029           0 :       CALL cp_fm_create(s_t_B, fm_struct_vec_t, name="s_t_B")
    2030           0 :       CALL cp_fm_create(y, fm_struct_vec, name="y")
    2031             : 
    2032           0 :       CALL cp_fm_create(y_y_t, fm_struct_mat, name="y_y_t")
    2033           0 :       CALL cp_fm_create(B_s_s_B, fm_struct_mat, name="B_s_s_B")
    2034             : 
    2035           0 :       CALL cp_fm_set_all(y_y_t, 0.0_dp)
    2036           0 :       CALL cp_fm_set_all(y, 0.0_dp)
    2037           0 :       CALL cp_fm_set_all(B_s_s_B, 0.0_dp)
    2038           0 :       CALL cp_fm_set_all(B_s, 0.0_dp)
    2039           0 :       CALL cp_fm_set_all(s_t_B, 0.0_dp)
    2040             : 
    2041             :       ! Release the structure created only here
    2042           0 :       CALL cp_fm_struct_release(fm_struct_vec_t)
    2043             : 
    2044             :       ! Calculate intermediates
    2045             :       ! y the is gradient difference
    2046           0 :       CALL cp_fm_to_fm(grad, y)
    2047           0 :       CALL cp_fm_scale_and_add(1.0_dp, y, -1.0_dp, prev_grad)
    2048             : 
    2049             :       ! First term
    2050             :       CALL parallel_gemm(transa="N", transb="T", m=mat_size, n=mat_size, &
    2051             :                          k=1, alpha=1.0_dp, &
    2052             :                          matrix_a=y, matrix_b=y, beta=0.0_dp, &
    2053           0 :                          matrix_c=y_y_t)
    2054             : 
    2055           0 :       CALL cp_fm_trace(y, step, y_t_s)
    2056             : 
    2057           0 :       CALL cp_fm_scale_and_add(1.0_dp, Hess, (1.0_dp/y_t_s), y_y_t)
    2058             : 
    2059             :       ! Second term
    2060             :       CALL parallel_gemm(transa="N", transb="N", m=mat_size, n=1, &
    2061             :                          k=mat_size, alpha=1.0_dp, &
    2062             :                          matrix_a=Hess, matrix_b=step, beta=0.0_dp, &
    2063           0 :                          matrix_c=B_s)
    2064             : 
    2065           0 :       CALL cp_fm_trace(B_s, step, s_B_s)
    2066             : 
    2067             :       CALL parallel_gemm(transa="T", transb="N", m=1, n=mat_size, &
    2068             :                          k=mat_size, alpha=1.0_dp, &
    2069             :                          matrix_a=step, matrix_b=Hess, beta=0.0_dp, &
    2070           0 :                          matrix_c=s_t_B)
    2071             : 
    2072             :       CALL parallel_gemm(transa="N", transb="N", m=mat_size, n=mat_size, &
    2073             :                          k=1, alpha=1.0_dp, &
    2074             :                          matrix_a=B_s, matrix_b=s_t_B, beta=0.0_dp, &
    2075           0 :                          matrix_c=B_s_s_B)
    2076             : 
    2077           0 :       CALL cp_fm_scale_and_add(1.0_dp, Hess, -(1.0_dp/s_B_s), B_s_s_B)
    2078             : 
    2079             :       ! WARNING: our Hessian must be negative-definite, whereas BFGS makes it positive-definite!
    2080             :       ! Therefore, we change sign in the beginning and in the end.
    2081           0 :       CALL cp_fm_scale(-1.0_dp, Hess)
    2082             : 
    2083             :       ! Release blacs environment
    2084           0 :       CALL cp_blacs_env_release(blacs_env)
    2085             : 
    2086             :       ! Deallocate intermediates
    2087           0 :       CALL cp_fm_release(y_y_t)
    2088           0 :       CALL cp_fm_release(B_s_s_B)
    2089           0 :       CALL cp_fm_release(B_s)
    2090           0 :       CALL cp_fm_release(s_t_B)
    2091           0 :       CALL cp_fm_release(y)
    2092             : 
    2093           0 :    END SUBROUTINE Hessian_update
    2094             : 
    2095             : ! **************************************************************************************************
    2096             : !> \brief ...
    2097             : !> \param grad ...
    2098             : !> \param prev_grad ...
    2099             : !> \param step ...
    2100             : !> \param prev_Hess ...
    2101             : !> \param Hess ...
    2102             : ! **************************************************************************************************
    2103           4 :    SUBROUTINE symm_rank_one_update(grad, prev_grad, step, prev_Hess, Hess)
    2104             :       TYPE(cp_fm_type), INTENT(IN)                       :: grad, prev_grad, step, prev_Hess, Hess
    2105             : 
    2106             :       INTEGER                                            :: mat_size
    2107             :       REAL(KIND=dp)                                      :: factor
    2108             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_mat, fm_struct_vec
    2109             :       TYPE(cp_fm_type)                                   :: B_x, y, y_B_x_y_B_x
    2110             : 
    2111             :       ! Recover the dimension
    2112           2 :       CALL cp_fm_get_info(matrix=Hess, nrow_global=mat_size)
    2113             : 
    2114           2 :       CALL cp_fm_set_all(Hess, 0.0_dp)
    2115           2 :       CALL cp_fm_to_fm(prev_Hess, Hess)
    2116             : 
    2117             :       ! Get full matrix structures
    2118           2 :       NULLIFY (fm_struct_mat, fm_struct_vec)
    2119             : 
    2120             :       CALL cp_fm_get_info(matrix=prev_Hess, &
    2121           2 :                           matrix_struct=fm_struct_mat)
    2122             :       CALL cp_fm_get_info(matrix=grad, &
    2123           2 :                           matrix_struct=fm_struct_vec)
    2124             : 
    2125             :       ! Allocate intermediates
    2126           2 :       CALL cp_fm_create(y, fm_struct_vec, name="y")
    2127           2 :       CALL cp_fm_create(B_x, fm_struct_vec, name="B_x")
    2128           2 :       CALL cp_fm_create(y_B_x_y_B_x, fm_struct_mat, name="y_B_x_y_B_x")
    2129             : 
    2130           2 :       CALL cp_fm_set_all(y, 0.0_dp)
    2131           2 :       CALL cp_fm_set_all(B_x, 0.0_dp)
    2132           2 :       CALL cp_fm_set_all(y_B_x_y_B_x, 0.0_dp)
    2133             : 
    2134             :       ! Calculate intermediates
    2135             :       ! y the is gradient difference
    2136           2 :       CALL cp_fm_to_fm(grad, y)
    2137           2 :       CALL cp_fm_scale_and_add(1.0_dp, y, -1.0_dp, prev_grad)
    2138             : 
    2139             :       CALL parallel_gemm(transa="N", transb="N", m=mat_size, n=1, &
    2140             :                          k=mat_size, alpha=1.0_dp, &
    2141             :                          matrix_a=Hess, matrix_b=step, beta=0.0_dp, &
    2142           2 :                          matrix_c=B_x)
    2143             : 
    2144           2 :       CALL cp_fm_scale_and_add(1.0_dp, y, -1.0_dp, B_x)
    2145             : 
    2146             :       CALL parallel_gemm(transa="N", transb="T", m=mat_size, n=mat_size, &
    2147             :                          k=1, alpha=1.0_dp, &
    2148             :                          matrix_a=y, matrix_b=y, beta=0.0_dp, &
    2149           2 :                          matrix_c=y_B_x_y_B_x)
    2150             : 
    2151             :       ! Scaling factor
    2152           2 :       CALL cp_fm_trace(y, step, factor)
    2153             : 
    2154             :       ! Assemble the Hessian
    2155           2 :       CALL cp_fm_scale_and_add(1.0_dp, Hess, (1.0_dp/factor), y_B_x_y_B_x)
    2156             : 
    2157             :       ! Deallocate intermediates
    2158           2 :       CALL cp_fm_release(y)
    2159           2 :       CALL cp_fm_release(B_x)
    2160           2 :       CALL cp_fm_release(y_B_x_y_B_x)
    2161             : 
    2162           2 :    END SUBROUTINE symm_rank_one_update
    2163             : 
    2164             : ! **************************************************************************************************
    2165             : !> \brief Controls the step, changes the trust radius if needed in maximization of the V_emb
    2166             : !> \param opt_embed ...
    2167             : !> \author Vladimir Rybkin
    2168             : ! **************************************************************************************************
    2169           6 :    SUBROUTINE step_control(opt_embed)
    2170             :       TYPE(opt_embed_pot_type)                           :: opt_embed
    2171             : 
    2172             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'step_control'
    2173             : 
    2174             :       INTEGER                                            :: handle
    2175             :       REAL(KIND=dp)                                      :: actual_ener_change, ener_ratio, &
    2176             :                                                             lin_term, pred_ener_change, quad_term
    2177             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
    2178             :       TYPE(cp_fm_type)                                   :: H_b
    2179             : 
    2180           2 :       CALL timeset(routineN, handle)
    2181             : 
    2182           2 :       NULLIFY (fm_struct)
    2183             :       CALL cp_fm_get_info(matrix=opt_embed%embed_pot_grad, &
    2184           2 :                           matrix_struct=fm_struct)
    2185           2 :       CALL cp_fm_create(H_b, fm_struct, name="H_b")
    2186           2 :       CALL cp_fm_set_all(H_b, 0.0_dp)
    2187             : 
    2188             :       ! Calculate the quadratic estimate for the energy
    2189             :       ! Linear term
    2190           2 :       CALL cp_fm_trace(opt_embed%step, opt_embed%embed_pot_grad, lin_term)
    2191             : 
    2192             :       ! Quadratic term
    2193             :       CALL parallel_gemm(transa="N", transb="N", m=opt_embed%dimen_aux, n=1, &
    2194             :                          k=opt_embed%dimen_aux, alpha=1.0_dp, &
    2195             :                          matrix_a=opt_embed%embed_pot_Hess, matrix_b=opt_embed%step, &
    2196           2 :                          beta=0.0_dp, matrix_c=H_b)
    2197           2 :       CALL cp_fm_trace(opt_embed%step, H_b, quad_term)
    2198             : 
    2199           2 :       pred_ener_change = lin_term + 0.5_dp*quad_term
    2200             : 
    2201             :       ! Reveal actual energy change
    2202             :       actual_ener_change = opt_embed%w_func(opt_embed%i_iter) - &
    2203           2 :                            opt_embed%w_func(opt_embed%last_accepted)
    2204             : 
    2205           2 :       ener_ratio = actual_ener_change/pred_ener_change
    2206             : 
    2207           2 :       CALL cp_fm_release(H_b)
    2208             : 
    2209           2 :       IF (actual_ener_change .GT. 0.0_dp) THEN ! If energy increases
    2210             :          ! We accept step
    2211           2 :          opt_embed%accept_step = .TRUE.
    2212             :          ! If energy change is larger than the predicted one, increase trust radius twice
    2213             :          ! Else (between 0 and 1) leave as it is, unless Newton step has been taken and if the step is less than max
    2214           2 :          IF ((ener_ratio .GT. 1.0_dp) .AND. (.NOT. opt_embed%newton_step) .AND. &
    2215             :              (opt_embed%trust_rad .LT. opt_embed%max_trad)) &
    2216           0 :             opt_embed%trust_rad = 2.0_dp*opt_embed%trust_rad
    2217             :       ELSE ! Energy decreases
    2218             :          ! If the decrease is not too large we allow this step to be taken
    2219             :          ! Otherwise, the step is rejected
    2220           0 :          IF (ABS(actual_ener_change) .GE. opt_embed%allowed_decrease) THEN
    2221           0 :             opt_embed%accept_step = .FALSE.
    2222             :          END IF
    2223             :          ! Trust radius is decreased 4 times unless it's smaller than the minimal allowed value
    2224           0 :          IF (opt_embed%trust_rad .GE. opt_embed%min_trad) &
    2225           0 :             opt_embed%trust_rad = 0.25_dp*opt_embed%trust_rad
    2226             :       END IF
    2227             : 
    2228           2 :       IF (opt_embed%accept_step) opt_embed%last_accepted = opt_embed%i_iter
    2229             : 
    2230           2 :       CALL timestop(handle)
    2231             : 
    2232           2 :    END SUBROUTINE step_control
    2233             : 
    2234             : ! **************************************************************************************************
    2235             : !> \brief ...
    2236             : !> \param opt_embed ...
    2237             : !> \param diag_grad ...
    2238             : !> \param eigenval ...
    2239             : !> \param diag_step ...
    2240             : ! **************************************************************************************************
    2241           2 :    SUBROUTINE level_shift(opt_embed, diag_grad, eigenval, diag_step)
    2242             :       TYPE(opt_embed_pot_type)                           :: opt_embed
    2243             :       TYPE(cp_fm_type), INTENT(IN)                       :: diag_grad
    2244             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eigenval
    2245             :       TYPE(cp_fm_type), INTENT(IN)                       :: diag_step
    2246             : 
    2247             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'level_shift'
    2248             :       INTEGER, PARAMETER                                 :: max_iter = 25
    2249             :       REAL(KIND=dp), PARAMETER                           :: thresh = 0.00001_dp
    2250             : 
    2251             :       INTEGER                                            :: handle, i_iter, l_global, LLL, &
    2252             :                                                             min_index, nrow_local
    2253           2 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: red_eigenval_map
    2254           2 :       INTEGER, DIMENSION(:), POINTER                     :: row_indices
    2255             :       LOGICAL                                            :: converged, do_shift
    2256             :       REAL(KIND=dp) :: diag_grad_norm, grad_min, hess_min, shift, shift_max, shift_min, step_len, &
    2257             :          step_minus_trad, step_minus_trad_first, step_minus_trad_max, step_minus_trad_min
    2258             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2259             : 
    2260           2 :       CALL timeset(routineN, handle)
    2261             : 
    2262             :       ! Array properties
    2263             :       CALL cp_fm_get_info(matrix=opt_embed%embed_pot_coef, &
    2264             :                           nrow_local=nrow_local, &
    2265             :                           row_indices=row_indices, &
    2266           2 :                           para_env=para_env)
    2267             : 
    2268         242 :       min_index = MINLOC(ABS(eigenval), dim=1)
    2269           2 :       hess_min = eigenval(min_index)
    2270           2 :       CALL cp_fm_get_element(diag_grad, min_index, 1, grad_min)
    2271             : 
    2272           2 :       CALL cp_fm_trace(diag_grad, diag_grad, diag_grad_norm)
    2273             : 
    2274           2 :       IF (hess_min .LT. 0.0_dp) THEN
    2275             :          !shift_min = -2.0_dp*(diag_grad_norm/opt_embed%trust_rad - min(hess_min, 0.0_dp))
    2276             :          !shift_max = max(0.0_dp, -hess_min + 0.5_dp*grad_min/opt_embed%trust_rad)
    2277             :          !shift_max = MIN(-hess_min+0.5_dp*grad_min/opt_embed%trust_rad, 0.0_dp)
    2278           2 :          shift_max = hess_min + 0.1
    2279             :          shift_min = diag_grad_norm/opt_embed%trust_rad
    2280           2 :          shift_min = 10.0_dp
    2281             :          !If (abs(shift_max) .LE. thresh) then
    2282             :          !   shift_min = -20.0_dp*(diag_grad_norm/opt_embed%trust_rad - min(hess_min, 0.0_dp))
    2283             :          !Else
    2284             :          !   shift_min = 20.0_dp*shift_max
    2285             :          !Endif
    2286             : 
    2287             :          ! The boundary values
    2288           2 :          step_minus_trad_max = shifted_step(diag_grad, eigenval, shift_max, opt_embed%trust_rad)
    2289           2 :          step_minus_trad_min = shifted_step(diag_grad, eigenval, shift_min, opt_embed%trust_rad)
    2290             : 
    2291             :          ! Find zero by bisection
    2292           2 :          converged = .FALSE.
    2293           2 :          do_shift = .FALSE.
    2294           2 :          IF (ABS(step_minus_trad_max) .LE. thresh) THEN
    2295           0 :             shift = shift_max
    2296             :          ELSE
    2297           2 :             IF (ABS(step_minus_trad_min) .LE. thresh) THEN
    2298           0 :                shift = shift_min
    2299             :             ELSE
    2300          28 :                DO i_iter = 1, max_iter
    2301          28 :                   shift = 0.5_dp*(shift_max + shift_min)
    2302          28 :                   step_minus_trad = shifted_step(diag_grad, eigenval, shift, opt_embed%trust_rad)
    2303          28 :                   IF (i_iter .EQ. 1) step_minus_trad_first = step_minus_trad
    2304          28 :                   IF (step_minus_trad .GT. 0.0_dp) shift_max = shift
    2305          28 :                   IF (step_minus_trad .LT. 0.0_dp) shift_min = shift
    2306             :                   !IF (ABS(shift_max-shift_min) .LT. thresh) converged = .TRUE.
    2307          28 :                   IF (ABS(step_minus_trad) .LT. thresh) converged = .TRUE.
    2308          26 :                   IF (converged) EXIT
    2309             :                END DO
    2310           2 :                IF (ABS(step_minus_trad) .LT. ABS(step_minus_trad_first)) do_shift = .TRUE.
    2311             :             END IF
    2312             :          END IF
    2313             :          ! Apply level-shifting
    2314           2 :          IF (converged .OR. do_shift) THEN
    2315         122 :             DO LLL = 1, nrow_local
    2316         120 :                l_global = row_indices(LLL)
    2317         122 :                IF (ABS(eigenval(l_global)) .GE. thresh) THEN
    2318             :                   diag_step%local_data(LLL, 1) = &
    2319         120 :                      -diag_grad%local_data(LLL, 1)/(eigenval(l_global) - shift)
    2320             :                ELSE
    2321           0 :                   diag_step%local_data(LLL, 1) = 0.0_dp
    2322             :                END IF
    2323             :             END DO
    2324             :          END IF
    2325           2 :          IF (.NOT. converged) THEN ! Scale if shift has not been found
    2326           0 :             CALL cp_fm_trace(diag_step, diag_step, step_len)
    2327           0 :             CALL cp_fm_scale(opt_embed%trust_rad/step_len, diag_step)
    2328             :          END IF
    2329             : 
    2330             :          ! Special case
    2331             :       ELSE ! Hess min .LT. 0.0_dp
    2332             :          ! First, find all positive eigenvalues
    2333           0 :          ALLOCATE (red_eigenval_map(opt_embed%dimen_var_aux))
    2334           0 :          red_eigenval_map = 0
    2335           0 :          DO LLL = 1, nrow_local
    2336           0 :             l_global = row_indices(LLL)
    2337           0 :             IF (eigenval(l_global) .GE. 0.0_dp) THEN
    2338           0 :                red_eigenval_map(l_global) = 1
    2339             :             END IF
    2340             :          END DO
    2341           0 :          CALL para_env%sum(red_eigenval_map)
    2342             : 
    2343             :          ! Set shift as -hess_min and find step on the reduced space of negative-value
    2344             :          ! eigenvectors
    2345           0 :          shift = -hess_min
    2346           0 :          DO LLL = 1, nrow_local
    2347           0 :             l_global = row_indices(LLL)
    2348           0 :             IF (red_eigenval_map(l_global) .EQ. 0) THEN
    2349           0 :                IF (ABS(eigenval(l_global)) .GE. thresh) THEN
    2350             :                   diag_step%local_data(LLL, 1) = &
    2351           0 :                      -diag_grad%local_data(LLL, 1)/(eigenval(l_global) - shift)
    2352             :                ELSE
    2353           0 :                   diag_step%local_data(LLL, 1) = 0.0_dp
    2354             :                END IF
    2355             :             ELSE
    2356           0 :                diag_step%local_data(LLL, 1) = 0.0_dp
    2357             :             END IF
    2358             :          END DO
    2359             : 
    2360             :          ! Find the step length of such a step
    2361           0 :          CALL cp_fm_trace(diag_step, diag_step, step_len)
    2362             : 
    2363             :       END IF
    2364             : 
    2365           2 :       CALL timestop(handle)
    2366             : 
    2367           4 :    END SUBROUTINE level_shift
    2368             : 
    2369             : ! **************************************************************************************************
    2370             : !> \brief ...
    2371             : !> \param diag_grad ...
    2372             : !> \param eigenval ...
    2373             : !> \param shift ...
    2374             : !> \param trust_rad ...
    2375             : !> \return ...
    2376             : ! **************************************************************************************************
    2377          32 :    FUNCTION shifted_step(diag_grad, eigenval, shift, trust_rad) RESULT(step_minus_trad)
    2378             :       TYPE(cp_fm_type), INTENT(IN)                       :: diag_grad
    2379             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
    2380             :          INTENT(IN)                                      :: eigenval
    2381             :       REAL(KIND=dp), INTENT(IN)                          :: shift, trust_rad
    2382             :       REAL(KIND=dp)                                      :: step_minus_trad
    2383             : 
    2384             :       REAL(KIND=dp), PARAMETER                           :: thresh = 0.000001_dp
    2385             : 
    2386             :       INTEGER                                            :: l_global, LLL, nrow_local
    2387          32 :       INTEGER, DIMENSION(:), POINTER                     :: row_indices
    2388             :       REAL(KIND=dp)                                      :: step, step_1d
    2389             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2390             : 
    2391             :       CALL cp_fm_get_info(matrix=diag_grad, &
    2392             :                           nrow_local=nrow_local, &
    2393             :                           row_indices=row_indices, &
    2394          32 :                           para_env=para_env)
    2395             : 
    2396          32 :       step = 0.0_dp
    2397        1952 :       DO LLL = 1, nrow_local
    2398        1920 :          l_global = row_indices(LLL)
    2399        1952 :          IF ((ABS(eigenval(l_global)) .GE. thresh) .AND. (ABS(diag_grad%local_data(LLL, 1)) .GE. thresh)) THEN
    2400          16 :             step_1d = -diag_grad%local_data(LLL, 1)/(eigenval(l_global) + shift)
    2401          16 :             step = step + step_1d**2
    2402             :          END IF
    2403             :       END DO
    2404             : 
    2405          32 :       CALL para_env%sum(step)
    2406             : 
    2407          32 :       step_minus_trad = SQRT(step) - trust_rad
    2408             : 
    2409          32 :    END FUNCTION shifted_step
    2410             : 
    2411             : ! **************************************************************************************************
    2412             : !> \brief ...
    2413             : !> \param step ...
    2414             : !> \param prev_step ...
    2415             : !> \param grad ...
    2416             : !> \param prev_grad ...
    2417             : !> \return ...
    2418             : !> \retval length ...
    2419             : ! **************************************************************************************************
    2420           0 :    FUNCTION Barzilai_Borwein(step, prev_step, grad, prev_grad) RESULT(length)
    2421             :       TYPE(cp_fm_type), INTENT(IN)                       :: step, prev_step, grad, prev_grad
    2422             :       REAL(KIND=dp)                                      :: length
    2423             : 
    2424             :       REAL(KIND=dp)                                      :: denominator, numerator
    2425             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
    2426             :       TYPE(cp_fm_type)                                   :: grad_diff, step_diff
    2427             : 
    2428             :       ! Get full matrix structures
    2429           0 :       NULLIFY (fm_struct)
    2430             : 
    2431             :       CALL cp_fm_get_info(matrix=grad, &
    2432           0 :                           matrix_struct=fm_struct)
    2433             : 
    2434             :       ! Allocate intermediates
    2435           0 :       CALL cp_fm_create(grad_diff, fm_struct, name="grad_diff")
    2436           0 :       CALL cp_fm_create(step_diff, fm_struct, name="step_diff")
    2437             : 
    2438             :       ! Calculate intermediates
    2439           0 :       CALL cp_fm_to_fm(grad, grad_diff)
    2440           0 :       CALL cp_fm_to_fm(step, step_diff)
    2441             : 
    2442           0 :       CALL cp_fm_scale_and_add(1.0_dp, grad_diff, -1.0_dp, prev_grad)
    2443           0 :       CALL cp_fm_scale_and_add(1.0_dp, step_diff, -1.0_dp, prev_step)
    2444             : 
    2445           0 :       CALL cp_fm_trace(step_diff, grad_diff, numerator)
    2446           0 :       CALL cp_fm_trace(grad_diff, grad_diff, denominator)
    2447             : 
    2448             :       ! Release intermediates
    2449           0 :       CALL cp_fm_release(grad_diff)
    2450           0 :       CALL cp_fm_release(step_diff)
    2451             : 
    2452           0 :       length = numerator/denominator
    2453             : 
    2454           0 :    END FUNCTION Barzilai_Borwein
    2455             : 
    2456             : ! **************************************************************************************************
    2457             : !> \brief ...
    2458             : !> \param pw_env ...
    2459             : !> \param embed_pot ...
    2460             : !> \param spin_embed_pot ...
    2461             : !> \param diff_rho_r ...
    2462             : !> \param diff_rho_spin ...
    2463             : !> \param rho_r_ref ...
    2464             : !> \param open_shell_embed ...
    2465             : !> \param step_len ...
    2466             : ! **************************************************************************************************
    2467           2 :    SUBROUTINE Leeuwen_Baerends_potential_update(pw_env, embed_pot, spin_embed_pot, diff_rho_r, diff_rho_spin, &
    2468             :                                                 rho_r_ref, open_shell_embed, step_len)
    2469             :       TYPE(pw_env_type), POINTER                         :: pw_env
    2470             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: embed_pot
    2471             :       TYPE(pw_r3d_rs_type), INTENT(IN), POINTER          :: spin_embed_pot
    2472             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: diff_rho_r, diff_rho_spin
    2473             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r_ref
    2474             :       LOGICAL, INTENT(IN)                                :: open_shell_embed
    2475             :       REAL(KIND=dp), INTENT(IN)                          :: step_len
    2476             : 
    2477             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'Leeuwen_Baerends_potential_update'
    2478             : 
    2479             :       INTEGER                                            :: handle, i, i_spin, j, k, nspins
    2480             :       INTEGER, DIMENSION(3)                              :: lb, ub
    2481             :       REAL(KIND=dp)                                      :: my_rho, rho_cutoff
    2482             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    2483           2 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: new_embed_pot, rho_n_1, temp_embed_pot
    2484             : 
    2485           2 :       CALL timeset(routineN, handle)
    2486             : 
    2487           2 :       rho_cutoff = EPSILON(0.0_dp)
    2488             : 
    2489             :       ! Prepare plane-waves pool
    2490           2 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    2491           2 :       NULLIFY (new_embed_pot)
    2492             : 
    2493           2 :       nspins = 1
    2494           2 :       IF (open_shell_embed) nspins = 2
    2495             :       NULLIFY (new_embed_pot)
    2496          10 :       ALLOCATE (new_embed_pot(nspins))
    2497           6 :       DO i_spin = 1, nspins
    2498           4 :          CALL auxbas_pw_pool%create_pw(new_embed_pot(i_spin))
    2499           6 :          CALL pw_zero(new_embed_pot(i_spin))
    2500             :       END DO
    2501             : 
    2502           8 :       lb(1:3) = embed_pot%pw_grid%bounds_local(1, 1:3)
    2503           8 :       ub(1:3) = embed_pot%pw_grid%bounds_local(2, 1:3)
    2504             : 
    2505           2 :       IF (.NOT. open_shell_embed) THEN
    2506             : !$OMP    PARALLEL DO DEFAULT(NONE) &
    2507             : !$OMP                PRIVATE(i,j,k, my_rho) &
    2508           0 : !$OMP                SHARED(new_embed_pot, embed_pot, diff_rho_r, rho_r_ref, lb, ub, rho_cutoff, step_len)
    2509             :          DO k = lb(3), ub(3)
    2510             :             DO j = lb(2), ub(2)
    2511             :                DO i = lb(1), ub(1)
    2512             :                   IF (rho_r_ref(1)%array(i, j, k) .GT. rho_cutoff) THEN
    2513             :                      my_rho = rho_r_ref(1)%array(i, j, k)
    2514             :                   ELSE
    2515             :                      my_rho = rho_cutoff
    2516             :                   END IF
    2517             :                   new_embed_pot(1)%array(i, j, k) = step_len*embed_pot%array(i, j, k)* &
    2518             :                                                     (diff_rho_r%array(i, j, k) + rho_r_ref(1)%array(i, j, k))/my_rho
    2519             :                END DO
    2520             :             END DO
    2521             :          END DO
    2522             : !$OMP    END PARALLEL DO
    2523           0 :          CALL pw_copy(new_embed_pot(1), embed_pot)
    2524             : 
    2525             :       ELSE
    2526             :          ! One has to work with spin components rather than with total and spin density
    2527           2 :          NULLIFY (rho_n_1)
    2528          10 :          ALLOCATE (rho_n_1(nspins))
    2529           2 :          NULLIFY (temp_embed_pot)
    2530          10 :          ALLOCATE (temp_embed_pot(nspins))
    2531           6 :          DO i_spin = 1, nspins
    2532           4 :             CALL auxbas_pw_pool%create_pw(rho_n_1(i_spin))
    2533           4 :             CALL pw_zero(rho_n_1(i_spin))
    2534           4 :             CALL auxbas_pw_pool%create_pw(temp_embed_pot(i_spin))
    2535           6 :             CALL pw_zero(temp_embed_pot(i_spin))
    2536             :          END DO
    2537           2 :          CALL pw_copy(diff_rho_r, rho_n_1(1))
    2538           2 :          CALL pw_copy(diff_rho_r, rho_n_1(2))
    2539           2 :          CALL pw_axpy(diff_rho_spin, rho_n_1(1), 1.0_dp)
    2540           2 :          CALL pw_axpy(diff_rho_spin, rho_n_1(2), -1.0_dp)
    2541           2 :          CALL pw_scale(rho_n_1(1), a=0.5_dp)
    2542           2 :          CALL pw_scale(rho_n_1(2), a=0.5_dp)
    2543             : 
    2544           2 :          CALL pw_copy(embed_pot, temp_embed_pot(1))
    2545           2 :          CALL pw_copy(embed_pot, temp_embed_pot(2))
    2546           2 :          CALL pw_axpy(spin_embed_pot, temp_embed_pot(1), 1.0_dp)
    2547           2 :          CALL pw_axpy(spin_embed_pot, temp_embed_pot(2), -1.0_dp)
    2548             : 
    2549           2 :          IF (SIZE(rho_r_ref) .EQ. 2) THEN
    2550           2 :             CALL pw_axpy(rho_r_ref(1), rho_n_1(1), 1.0_dp)
    2551           2 :             CALL pw_axpy(rho_r_ref(2), rho_n_1(2), 1.0_dp)
    2552             : 
    2553             : !$OMP    PARALLEL DO DEFAULT(NONE) &
    2554             : !$OMP                PRIVATE(i,j,k, my_rho) &
    2555           2 : !$OMP                SHARED(new_embed_pot, temp_embed_pot, rho_r_ref, rho_n_1, lb, ub, rho_cutoff, step_len)
    2556             :             DO k = lb(3), ub(3)
    2557             :                DO j = lb(2), ub(2)
    2558             :                   DO i = lb(1), ub(1)
    2559             :                      IF (rho_r_ref(1)%array(i, j, k) .GT. rho_cutoff) THEN
    2560             :                         my_rho = rho_r_ref(1)%array(i, j, k)
    2561             :                      ELSE
    2562             :                         my_rho = rho_cutoff
    2563             :                      END IF
    2564             :                      new_embed_pot(1)%array(i, j, k) = step_len*temp_embed_pot(1)%array(i, j, k)* &
    2565             :                                                        (rho_n_1(1)%array(i, j, k))/my_rho
    2566             :                      IF (rho_r_ref(2)%array(i, j, k) .GT. rho_cutoff) THEN
    2567             :                         my_rho = rho_r_ref(2)%array(i, j, k)
    2568             :                      ELSE
    2569             :                         my_rho = rho_cutoff
    2570             :                      END IF
    2571             :                      new_embed_pot(2)%array(i, j, k) = step_len*temp_embed_pot(2)%array(i, j, k)* &
    2572             :                                                        (rho_n_1(2)%array(i, j, k))/my_rho
    2573             :                   END DO
    2574             :                END DO
    2575             :             END DO
    2576             : !$OMP    END PARALLEL DO
    2577             : 
    2578             :          ELSE ! Reference system is closed-shell
    2579           0 :             CALL pw_axpy(rho_r_ref(1), rho_n_1(1), 1.0_dp)
    2580             :             ! The beta spin component is here equal to the difference: nothing to do
    2581             : 
    2582             : !$OMP    PARALLEL DO DEFAULT(NONE) &
    2583             : !$OMP                PRIVATE(i,j,k, my_rho) &
    2584           0 : !$OMP                SHARED(new_embed_pot, rho_r_ref, temp_embed_pot, rho_n_1, lb, ub, rho_cutoff, step_len)
    2585             :             DO k = lb(3), ub(3)
    2586             :                DO j = lb(2), ub(2)
    2587             :                   DO i = lb(1), ub(1)
    2588             :                      IF (rho_r_ref(1)%array(i, j, k) .GT. rho_cutoff) THEN
    2589             :                         my_rho = 0.5_dp*rho_r_ref(1)%array(i, j, k)
    2590             :                      ELSE
    2591             :                         my_rho = rho_cutoff
    2592             :                      END IF
    2593             :                      new_embed_pot(1)%array(i, j, k) = step_len*temp_embed_pot(1)%array(i, j, k)* &
    2594             :                                                        (rho_n_1(1)%array(i, j, k))/my_rho
    2595             :                      new_embed_pot(2)%array(i, j, k) = step_len*temp_embed_pot(2)%array(i, j, k)* &
    2596             :                                                        (rho_n_1(2)%array(i, j, k))/my_rho
    2597             :                   END DO
    2598             :                END DO
    2599             :             END DO
    2600             : !$OMP    END PARALLEL DO
    2601             :          END IF
    2602             : 
    2603           2 :          CALL pw_copy(new_embed_pot(1), embed_pot)
    2604           2 :          CALL pw_axpy(new_embed_pot(2), embed_pot, 1.0_dp)
    2605           2 :          CALL pw_scale(embed_pot, a=0.5_dp)
    2606           2 :          CALL pw_copy(new_embed_pot(1), spin_embed_pot)
    2607           2 :          CALL pw_axpy(new_embed_pot(2), spin_embed_pot, -1.0_dp)
    2608           2 :          CALL pw_scale(spin_embed_pot, a=0.5_dp)
    2609             : 
    2610           6 :          DO i_spin = 1, nspins
    2611           4 :             CALL rho_n_1(i_spin)%release()
    2612           6 :             CALL temp_embed_pot(i_spin)%release()
    2613             :          END DO
    2614           2 :          DEALLOCATE (rho_n_1)
    2615           2 :          DEALLOCATE (temp_embed_pot)
    2616             :       END IF
    2617             : 
    2618           6 :       DO i_spin = 1, nspins
    2619           6 :          CALL new_embed_pot(i_spin)%release()
    2620             :       END DO
    2621             : 
    2622           2 :       DEALLOCATE (new_embed_pot)
    2623             : 
    2624           2 :       CALL timestop(handle)
    2625             : 
    2626           2 :    END SUBROUTINE Leeuwen_Baerends_potential_update
    2627             : 
    2628             : ! **************************************************************************************************
    2629             : !> \brief ...
    2630             : !> \param qs_env ...
    2631             : !> \param rho_r_ref ...
    2632             : !> \param prev_embed_pot ...
    2633             : !> \param prev_spin_embed_pot ...
    2634             : !> \param embed_pot ...
    2635             : !> \param spin_embed_pot ...
    2636             : !> \param diff_rho_r ...
    2637             : !> \param diff_rho_spin ...
    2638             : !> \param v_w_ref ...
    2639             : !> \param i_iter ...
    2640             : !> \param step_len ...
    2641             : !> \param open_shell_embed ...
    2642             : !> \param vw_cutoff ...
    2643             : !> \param vw_smooth_cutoff_range ...
    2644             : ! **************************************************************************************************
    2645           2 :    SUBROUTINE FAB_update(qs_env, rho_r_ref, prev_embed_pot, prev_spin_embed_pot, embed_pot, spin_embed_pot, &
    2646             :                          diff_rho_r, diff_rho_spin, v_w_ref, i_iter, step_len, open_shell_embed, &
    2647             :                          vw_cutoff, vw_smooth_cutoff_range)
    2648             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2649             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r_ref
    2650             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: prev_embed_pot
    2651             :       TYPE(pw_r3d_rs_type), INTENT(IN), POINTER          :: prev_spin_embed_pot
    2652             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: embed_pot
    2653             :       TYPE(pw_r3d_rs_type), INTENT(IN), POINTER          :: spin_embed_pot
    2654             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: diff_rho_r, diff_rho_spin
    2655             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: v_w_ref
    2656             :       INTEGER, INTENT(IN)                                :: i_iter
    2657             :       REAL(KIND=dp)                                      :: step_len
    2658             :       LOGICAL                                            :: open_shell_embed
    2659             :       REAL(KIND=dp)                                      :: vw_cutoff, vw_smooth_cutoff_range
    2660             : 
    2661             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'FAB_update'
    2662             : 
    2663             :       INTEGER                                            :: handle, i_spin, nspins
    2664             :       TYPE(pw_env_type), POINTER                         :: pw_env
    2665             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    2666           2 :       TYPE(pw_r3d_rs_type), ALLOCATABLE, DIMENSION(:)    :: new_embed_pot, temp_embed_pot, v_w
    2667           2 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: curr_rho
    2668             : 
    2669           2 :       CALL timeset(routineN, handle)
    2670             : 
    2671             :       ! Update formula: v(n+1) = v(n-1) - v_w(ref) + v_w(n)
    2672             : 
    2673             :       CALL get_qs_env(qs_env=qs_env, &
    2674           2 :                       pw_env=pw_env)
    2675             :       ! Get plane waves pool
    2676           2 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    2677             : 
    2678             :       ! We calculate von Weizsaecker potential for the reference density
    2679             :       ! only at the first iteration
    2680           2 :       IF (i_iter .LE. 1) THEN
    2681           2 :          nspins = SIZE(rho_r_ref)
    2682           2 :          NULLIFY (v_w_ref)
    2683           8 :          ALLOCATE (v_w_ref(nspins))
    2684           4 :          DO i_spin = 1, nspins
    2685           4 :             CALL auxbas_pw_pool%create_pw(v_w_ref(i_spin))
    2686             :          END DO
    2687           2 :          CALL Von_Weizsacker(rho_r_ref, v_w_ref, qs_env, vw_cutoff, vw_smooth_cutoff_range)
    2688             :          ! For the first step previous are set to current
    2689           2 :          CALL pw_copy(embed_pot, prev_embed_pot)
    2690           2 :          CALL pw_axpy(diff_rho_r, embed_pot, 0.5_dp)
    2691           2 :          IF (open_shell_embed) THEN
    2692           0 :             CALL pw_copy(spin_embed_pot, prev_spin_embed_pot)
    2693           0 :             CALL pw_axpy(diff_rho_r, embed_pot, 0.5_dp)
    2694             :          END IF
    2695             : 
    2696             :       ELSE
    2697             : 
    2698             :          ! Reference can be closed shell, but total embedding - open shell:
    2699             :          ! redefine nspins
    2700           0 :          nspins = 1
    2701           0 :          IF (open_shell_embed) nspins = 2
    2702           0 :          ALLOCATE (new_embed_pot(nspins))
    2703           0 :          ALLOCATE (v_w(nspins))
    2704           0 :          NULLIFY (curr_rho)
    2705           0 :          ALLOCATE (curr_rho(nspins))
    2706           0 :          DO i_spin = 1, nspins
    2707           0 :             CALL auxbas_pw_pool%create_pw(new_embed_pot(i_spin))
    2708           0 :             CALL pw_zero(new_embed_pot(i_spin))
    2709             : 
    2710           0 :             CALL auxbas_pw_pool%create_pw(v_w(i_spin))
    2711           0 :             CALL pw_zero(v_w(i_spin))
    2712             : 
    2713           0 :             CALL auxbas_pw_pool%create_pw(curr_rho(i_spin))
    2714           0 :             CALL pw_zero(curr_rho(i_spin))
    2715             :          END DO
    2716             : 
    2717             :          ! Now, deal with the current density
    2718             : 
    2719           0 :          IF (.NOT. open_shell_embed) THEN
    2720             :             ! Reconstruct current density
    2721           0 :             CALL pw_copy(diff_rho_r, curr_rho(1))
    2722           0 :             CALL pw_axpy(rho_r_ref(1), curr_rho(1), 1.0_dp)
    2723             :             ! Compute von Weizsaecker potential
    2724           0 :             CALL Von_Weizsacker(curr_rho, v_w, qs_env, vw_cutoff, vw_smooth_cutoff_range)
    2725             :             ! Compute new embedding potential
    2726           0 :             CALL pw_copy(prev_embed_pot, new_embed_pot(1))
    2727           0 :             CALL pw_axpy(v_w(1), new_embed_pot(1), step_len)
    2728           0 :             CALL pw_axpy(v_w_ref(1), new_embed_pot(1), -step_len)
    2729             :             ! Copy the potentials
    2730             : 
    2731           0 :             CALL pw_copy(embed_pot, prev_embed_pot)
    2732           0 :             CALL pw_copy(new_embed_pot(1), embed_pot)
    2733             : 
    2734             :          ELSE
    2735             :             ! Reconstruct current density
    2736           0 :             CALL pw_copy(diff_rho_r, curr_rho(1))
    2737           0 :             CALL pw_copy(diff_rho_r, curr_rho(2))
    2738           0 :             CALL pw_axpy(diff_rho_spin, curr_rho(1), 1.0_dp)
    2739           0 :             CALL pw_axpy(diff_rho_spin, curr_rho(2), -1.0_dp)
    2740           0 :             CALL pw_scale(curr_rho(1), a=0.5_dp)
    2741           0 :             CALL pw_scale(curr_rho(2), a=0.5_dp)
    2742             : 
    2743           0 :             IF (SIZE(rho_r_ref) .EQ. 1) THEN ! If reference system is closed-shell
    2744           0 :                CALL pw_axpy(rho_r_ref(1), curr_rho(1), 0.5_dp)
    2745           0 :                CALL pw_axpy(rho_r_ref(1), curr_rho(2), 0.5_dp)
    2746             :             ELSE ! If reference system is open-shell
    2747           0 :                CALL pw_axpy(rho_r_ref(1), curr_rho(1), 1.0_dp)
    2748           0 :                CALL pw_axpy(rho_r_ref(2), curr_rho(2), 1.0_dp)
    2749             :             END IF
    2750             : 
    2751             :             ! Compute von Weizsaecker potential
    2752           0 :             CALL Von_Weizsacker(curr_rho, v_w, qs_env, vw_cutoff, vw_smooth_cutoff_range)
    2753             : 
    2754             :             ! Reconstruct corrent spin components of the potential
    2755           0 :             ALLOCATE (temp_embed_pot(nspins))
    2756           0 :             DO i_spin = 1, nspins
    2757           0 :                CALL auxbas_pw_pool%create_pw(temp_embed_pot(i_spin))
    2758           0 :                CALL pw_zero(temp_embed_pot(i_spin))
    2759             :             END DO
    2760           0 :             CALL pw_copy(embed_pot, temp_embed_pot(1))
    2761           0 :             CALL pw_copy(embed_pot, temp_embed_pot(2))
    2762           0 :             CALL pw_axpy(spin_embed_pot, temp_embed_pot(1), 1.0_dp)
    2763           0 :             CALL pw_axpy(spin_embed_pot, temp_embed_pot(2), -1.0_dp)
    2764             : 
    2765             :             ! Compute new embedding potential
    2766           0 :             IF (SIZE(v_w_ref) .EQ. 1) THEN ! Reference system is closed-shell
    2767           0 :                CALL pw_copy(temp_embed_pot(1), new_embed_pot(1))
    2768           0 :                CALL pw_axpy(v_w(1), new_embed_pot(1), 0.5_dp*step_len)
    2769           0 :                CALL pw_axpy(v_w_ref(1), new_embed_pot(1), -0.5_dp*step_len)
    2770             : 
    2771           0 :                CALL pw_copy(temp_embed_pot(2), new_embed_pot(2))
    2772           0 :                CALL pw_axpy(v_w(2), new_embed_pot(2), 0.5_dp)
    2773           0 :                CALL pw_axpy(v_w_ref(1), new_embed_pot(2), -0.5_dp)
    2774             : 
    2775             :             ELSE ! Reference system is open-shell
    2776             : 
    2777           0 :                DO i_spin = 1, nspins
    2778           0 :                   CALL pw_copy(temp_embed_pot(i_spin), new_embed_pot(i_spin))
    2779           0 :                   CALL pw_axpy(v_w(1), new_embed_pot(i_spin), step_len)
    2780           0 :                   CALL pw_axpy(v_w_ref(i_spin), new_embed_pot(i_spin), -step_len)
    2781             :                END DO
    2782             :             END IF
    2783             : 
    2784             :             ! Update embedding potentials
    2785           0 :             CALL pw_copy(embed_pot, prev_embed_pot)
    2786           0 :             CALL pw_copy(spin_embed_pot, prev_spin_embed_pot)
    2787             : 
    2788           0 :             CALL pw_copy(new_embed_pot(1), embed_pot)
    2789           0 :             CALL pw_axpy(new_embed_pot(2), embed_pot, 1.0_dp)
    2790           0 :             CALL pw_scale(embed_pot, a=0.5_dp)
    2791           0 :             CALL pw_copy(new_embed_pot(1), spin_embed_pot)
    2792           0 :             CALL pw_axpy(new_embed_pot(2), spin_embed_pot, -1.0_dp)
    2793           0 :             CALL pw_scale(spin_embed_pot, a=0.5_dp)
    2794             : 
    2795           0 :             DO i_spin = 1, nspins
    2796           0 :                CALL temp_embed_pot(i_spin)%release()
    2797             :             END DO
    2798           0 :             DEALLOCATE (temp_embed_pot)
    2799             : 
    2800             :          END IF
    2801             : 
    2802           0 :          DO i_spin = 1, nspins
    2803           0 :             CALL curr_rho(i_spin)%release()
    2804           0 :             CALL new_embed_pot(i_spin)%release()
    2805           0 :             CALL v_w(i_spin)%release()
    2806             :          END DO
    2807             : 
    2808           0 :          DEALLOCATE (new_embed_pot)
    2809           0 :          DEALLOCATE (v_w)
    2810           0 :          DEALLOCATE (curr_rho)
    2811             : 
    2812             :       END IF
    2813             : 
    2814           2 :       CALL timestop(handle)
    2815             : 
    2816           4 :    END SUBROUTINE FAB_update
    2817             : 
    2818             : ! **************************************************************************************************
    2819             : !> \brief ...
    2820             : !> \param rho_r ...
    2821             : !> \param v_w ...
    2822             : !> \param qs_env ...
    2823             : !> \param vw_cutoff ...
    2824             : !> \param vw_smooth_cutoff_range ...
    2825             : ! **************************************************************************************************
    2826           2 :    SUBROUTINE Von_Weizsacker(rho_r, v_w, qs_env, vw_cutoff, vw_smooth_cutoff_range)
    2827             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r
    2828             :       TYPE(pw_r3d_rs_type), DIMENSION(:), INTENT(IN)     :: v_w
    2829             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2830             :       REAL(KIND=dp), INTENT(IN)                          :: vw_cutoff, vw_smooth_cutoff_range
    2831             : 
    2832             :       REAL(KIND=dp), PARAMETER                           :: one_4 = 0.25_dp, one_8 = 0.125_dp
    2833             : 
    2834             :       INTEGER                                            :: i, i_spin, j, k, nspins
    2835             :       INTEGER, DIMENSION(3)                              :: lb, ub
    2836             :       REAL(KIND=dp)                                      :: density_smooth_cut_range, my_rho, &
    2837             :                                                             rho_cutoff
    2838           2 :       REAL(kind=dp), DIMENSION(:, :, :), POINTER         :: rhoa, rhob
    2839           2 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: rho_g
    2840             :       TYPE(pw_env_type), POINTER                         :: pw_env
    2841             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    2842           2 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: tau
    2843             :       TYPE(section_vals_type), POINTER                   :: input, xc_section
    2844             :       TYPE(xc_rho_cflags_type)                           :: needs
    2845             :       TYPE(xc_rho_set_type)                              :: rho_set
    2846             : 
    2847           2 :       rho_cutoff = EPSILON(0.0_dp)
    2848             : 
    2849           2 :       nspins = SIZE(rho_r)
    2850             : 
    2851           2 :       NULLIFY (xc_section)
    2852             : 
    2853             :       CALL get_qs_env(qs_env=qs_env, &
    2854             :                       pw_env=pw_env, &
    2855           2 :                       input=input)
    2856             : 
    2857             :       ! Get plane waves pool
    2858           2 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    2859             : 
    2860             :       ! get some of the grids ready
    2861           2 :       NULLIFY (rho_g)
    2862           8 :       ALLOCATE (rho_g(nspins))
    2863           4 :       DO i_spin = 1, nspins
    2864           2 :          CALL auxbas_pw_pool%create_pw(rho_g(i_spin))
    2865           4 :          CALL pw_transfer(rho_r(i_spin), rho_g(i_spin))
    2866             :       END DO
    2867             : 
    2868           2 :       xc_section => section_vals_get_subs_vals(input, "DFT%XC")
    2869             : 
    2870             :       CALL xc_rho_set_create(rho_set, &
    2871             :                              rho_r(1)%pw_grid%bounds_local, &
    2872             :                              rho_cutoff=section_get_rval(xc_section, "density_cutoff"), &
    2873             :                              drho_cutoff=section_get_rval(xc_section, "gradient_cutoff"), &
    2874           2 :                              tau_cutoff=section_get_rval(xc_section, "tau_cutoff"))
    2875             : 
    2876           2 :       CALL xc_rho_cflags_setall(needs, .FALSE.)
    2877             : 
    2878           2 :       IF (nspins .EQ. 2) THEN
    2879           0 :          needs%rho_spin = .TRUE.
    2880           0 :          needs%norm_drho_spin = .TRUE.
    2881           0 :          needs%laplace_rho_spin = .TRUE.
    2882             :       ELSE
    2883           2 :          needs%rho = .TRUE.
    2884           2 :          needs%norm_drho = .TRUE.
    2885           2 :          needs%laplace_rho = .TRUE.
    2886             :       END IF
    2887             : 
    2888             :       CALL xc_rho_set_update(rho_set, rho_r, rho_g, tau, needs, &
    2889             :                              section_get_ival(xc_section, "XC_GRID%XC_DERIV"), &
    2890             :                              section_get_ival(xc_section, "XC_GRID%XC_SMOOTH_RHO"), &
    2891           2 :                              auxbas_pw_pool)
    2892             : 
    2893             :       CALL section_vals_val_get(xc_section, "DENSITY_CUTOFF", &
    2894           2 :                                 r_val=rho_cutoff)
    2895             :       CALL section_vals_val_get(xc_section, "DENSITY_SMOOTH_CUTOFF_RANGE", &
    2896           2 :                                 r_val=density_smooth_cut_range)
    2897             : 
    2898           8 :       lb(1:3) = rho_r(1)%pw_grid%bounds_local(1, 1:3)
    2899           8 :       ub(1:3) = rho_r(1)%pw_grid%bounds_local(2, 1:3)
    2900             : 
    2901           2 :       IF (nspins .EQ. 2) THEN
    2902             : !$OMP    PARALLEL DO DEFAULT(NONE) &
    2903             : !$OMP                PRIVATE(i,j,k, my_rho) &
    2904           0 : !$OMP                SHARED(v_w, rho_r, rho_set, lb, ub, rho_cutoff)
    2905             :          DO k = lb(3), ub(3)
    2906             :             DO j = lb(2), ub(2)
    2907             :                DO i = lb(1), ub(1)
    2908             :                   IF (rho_r(1)%array(i, j, k) .GT. rho_cutoff) THEN
    2909             :                      my_rho = rho_r(1)%array(i, j, k)
    2910             :                   ELSE
    2911             :                      my_rho = rho_cutoff
    2912             :                   END IF
    2913             :                   v_w(1)%array(i, j, k) = one_8*rho_set%norm_drhoa(i, j, k)**2/my_rho**2 - &
    2914             :                                           one_4*rho_set%laplace_rhoa(i, j, k)/my_rho
    2915             : 
    2916             :                   IF (rho_r(2)%array(i, j, k) .GT. rho_cutoff) THEN
    2917             :                      my_rho = rho_r(2)%array(i, j, k)
    2918             :                   ELSE
    2919             :                      my_rho = rho_cutoff
    2920             :                   END IF
    2921             :                   v_w(2)%array(i, j, k) = one_8*rho_set%norm_drhob(i, j, k)**2/my_rho**2 - &
    2922             :                                           one_4*rho_set%laplace_rhob(i, j, k)/my_rho
    2923             :                END DO
    2924             :             END DO
    2925             :          END DO
    2926             : !$OMP    END PARALLEL DO
    2927             :       ELSE
    2928             : !$OMP    PARALLEL DO DEFAULT(NONE) &
    2929             : !$OMP                PRIVATE(i,j,k, my_rho) &
    2930           2 : !$OMP                SHARED(v_w, rho_r, rho_set, lb, ub, rho_cutoff)
    2931             :          DO k = lb(3), ub(3)
    2932             :             DO j = lb(2), ub(2)
    2933             :                DO i = lb(1), ub(1)
    2934             :                   IF (rho_r(1)%array(i, j, k) .GT. rho_cutoff) THEN
    2935             :                      my_rho = rho_r(1)%array(i, j, k)
    2936             :                      v_w(1)%array(i, j, k) = one_8*rho_set%norm_drho(i, j, k)**2/my_rho**2 - &
    2937             :                                              one_4*rho_set%laplace_rho(i, j, k)/my_rho
    2938             :                   ELSE
    2939             :                      v_w(1)%array(i, j, k) = 0.0_dp
    2940             :                   END IF
    2941             :                END DO
    2942             :             END DO
    2943             :          END DO
    2944             : !$OMP    END PARALLEL DO
    2945             : 
    2946             :       END IF
    2947             : 
    2948             :       ! Smoothen the von Weizsaecker potential
    2949           2 :       IF (nspins == 2) THEN
    2950           0 :          density_smooth_cut_range = 0.5_dp*density_smooth_cut_range
    2951           0 :          rho_cutoff = 0.5_dp*rho_cutoff
    2952             :       END IF
    2953           4 :       DO i_spin = 1, nspins
    2954             :          CALL smooth_cutoff(pot=v_w(i_spin)%array, rho=rho_r(i_spin)%array, rhoa=rhoa, rhob=rhob, &
    2955             :                             rho_cutoff=vw_cutoff, &
    2956           4 :                             rho_smooth_cutoff_range=vw_smooth_cutoff_range)
    2957             :       END DO
    2958             : 
    2959           2 :       CALL xc_rho_set_release(rho_set, pw_pool=auxbas_pw_pool)
    2960             : 
    2961           4 :       DO i_spin = 1, nspins
    2962           4 :          CALL rho_g(i_spin)%release()
    2963             :       END DO
    2964           2 :       DEALLOCATE (rho_g)
    2965             : 
    2966          46 :    END SUBROUTINE Von_Weizsacker
    2967             : 
    2968             : ! **************************************************************************************************
    2969             : !> \brief ...
    2970             : !> \param diff_rho_r ...
    2971             : !> \return ...
    2972             : ! **************************************************************************************************
    2973         222 :    FUNCTION max_dens_diff(diff_rho_r) RESULT(total_max_diff)
    2974             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: diff_rho_r
    2975             :       REAL(KIND=dp)                                      :: total_max_diff
    2976             : 
    2977             :       INTEGER                                            :: size_x, size_y, size_z
    2978             :       REAL(KIND=dp)                                      :: max_diff
    2979         222 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: grid_3d
    2980             : 
    2981             :       !, i_x, i_y, i_z
    2982             : 
    2983             :       ! Get the sizes
    2984         222 :       size_x = SIZE(diff_rho_r%array, 1)
    2985         222 :       size_y = SIZE(diff_rho_r%array, 2)
    2986         222 :       size_z = SIZE(diff_rho_r%array, 3)
    2987             : 
    2988             :       ! Allocate the density
    2989        1110 :       ALLOCATE (grid_3d(size_x, size_y, size_z))
    2990             : 
    2991             :       ! Copy density
    2992     4589181 :       grid_3d(:, :, :) = diff_rho_r%array(:, :, :)
    2993             : 
    2994             :       ! Find the maximum absolute value
    2995     4589181 :       max_diff = MAXVAL(ABS(grid_3d))
    2996         222 :       total_max_diff = max_diff
    2997         222 :       CALL diff_rho_r%pw_grid%para%group%max(total_max_diff)
    2998             : 
    2999             :       ! Deallocate the density
    3000         222 :       DEALLOCATE (grid_3d)
    3001             : 
    3002         222 :    END FUNCTION max_dens_diff
    3003             : 
    3004             : ! **************************************************************************************************
    3005             : !> \brief Prints a cube for the (rho_A + rho_B - rho_ref) to be minimized in embedding
    3006             : !> \param diff_rho_r ...
    3007             : !> \param i_iter ...
    3008             : !> \param qs_env ...
    3009             : !> \param final_one ...
    3010             : !> \author Vladimir Rybkin
    3011             : ! **************************************************************************************************
    3012          48 :    SUBROUTINE print_rho_diff(diff_rho_r, i_iter, qs_env, final_one)
    3013             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: diff_rho_r
    3014             :       INTEGER, INTENT(IN)                                :: i_iter
    3015             :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
    3016             :       LOGICAL, INTENT(IN)                                :: final_one
    3017             : 
    3018             :       CHARACTER(LEN=default_path_length)                 :: filename, my_pos_cube, title
    3019             :       INTEGER                                            :: unit_nr
    3020             :       TYPE(cp_logger_type), POINTER                      :: logger
    3021             :       TYPE(particle_list_type), POINTER                  :: particles
    3022             :       TYPE(qs_subsys_type), POINTER                      :: subsys
    3023             :       TYPE(section_vals_type), POINTER                   :: dft_section, input
    3024             : 
    3025          48 :       NULLIFY (subsys, input)
    3026             : 
    3027             :       CALL get_qs_env(qs_env=qs_env, &
    3028             :                       subsys=subsys, &
    3029          48 :                       input=input)
    3030          48 :       dft_section => section_vals_get_subs_vals(input, "DFT")
    3031          48 :       CALL qs_subsys_get(subsys, particles=particles)
    3032             : 
    3033          48 :       logger => cp_get_default_logger()
    3034          48 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3035             :                                            "DFT%QS%OPT_EMBED%EMBED_DENS_DIFF"), cp_p_file)) THEN
    3036          10 :          my_pos_cube = "REWIND"
    3037          10 :          IF (.NOT. final_one) THEN
    3038          10 :             WRITE (filename, '(a5,I3.3,a1,I1.1)') "DIFF_", i_iter
    3039             :          ELSE
    3040           0 :             WRITE (filename, '(a5,I3.3,a1,I1.1)') "DIFF"
    3041             :          END IF
    3042             :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%QS%OPT_EMBED%EMBED_DENS_DIFF", &
    3043             :                                         extension=".cube", middle_name=TRIM(filename), file_position=my_pos_cube, &
    3044          10 :                                         log_filename=.FALSE.)
    3045             : 
    3046          10 :          WRITE (title, *) "EMBEDDING DENSITY DIFFERENCE ", " optimization step ", i_iter
    3047             :          CALL cp_pw_to_cube(diff_rho_r, unit_nr, title, particles=particles, &
    3048          10 :                             stride=section_get_ivals(dft_section, "QS%OPT_EMBED%EMBED_DENS_DIFF%STRIDE"))
    3049             :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
    3050          10 :                                            "DFT%QS%OPT_EMBED%EMBED_DENS_DIFF")
    3051             :       END IF
    3052             : 
    3053          48 :    END SUBROUTINE print_rho_diff
    3054             : 
    3055             : ! **************************************************************************************************
    3056             : !> \brief Prints a cube for the (spin_rho_A + spin_rho_B - spin_rho_ref) to be minimized in embedding
    3057             : !> \param spin_diff_rho_r ...
    3058             : !> \param i_iter ...
    3059             : !> \param qs_env ...
    3060             : !> \param final_one ...
    3061             : !> \author Vladimir Rybkin
    3062             : ! **************************************************************************************************
    3063          38 :    SUBROUTINE print_rho_spin_diff(spin_diff_rho_r, i_iter, qs_env, final_one)
    3064             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: spin_diff_rho_r
    3065             :       INTEGER, INTENT(IN)                                :: i_iter
    3066             :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
    3067             :       LOGICAL, INTENT(IN)                                :: final_one
    3068             : 
    3069             :       CHARACTER(LEN=default_path_length)                 :: filename, my_pos_cube, title
    3070             :       INTEGER                                            :: unit_nr
    3071             :       TYPE(cp_logger_type), POINTER                      :: logger
    3072             :       TYPE(particle_list_type), POINTER                  :: particles
    3073             :       TYPE(qs_subsys_type), POINTER                      :: subsys
    3074             :       TYPE(section_vals_type), POINTER                   :: dft_section, input
    3075             : 
    3076          38 :       NULLIFY (subsys, input)
    3077             : 
    3078             :       CALL get_qs_env(qs_env=qs_env, &
    3079             :                       subsys=subsys, &
    3080          38 :                       input=input)
    3081          38 :       dft_section => section_vals_get_subs_vals(input, "DFT")
    3082          38 :       CALL qs_subsys_get(subsys, particles=particles)
    3083             : 
    3084          38 :       logger => cp_get_default_logger()
    3085          38 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3086             :                                            "DFT%QS%OPT_EMBED%EMBED_DENS_DIFF"), cp_p_file)) THEN
    3087           0 :          my_pos_cube = "REWIND"
    3088           0 :          IF (.NOT. final_one) THEN
    3089           0 :             WRITE (filename, '(a5,I3.3,a1,I1.1)') "SPIN_DIFF_", i_iter
    3090             :          ELSE
    3091           0 :             WRITE (filename, '(a9,I3.3,a1,I1.1)') "SPIN_DIFF"
    3092             :          END IF
    3093             :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%QS%OPT_EMBED%EMBED_DENS_DIFF", &
    3094             :                                         extension=".cube", middle_name=TRIM(filename), file_position=my_pos_cube, &
    3095           0 :                                         log_filename=.FALSE.)
    3096             : 
    3097           0 :          WRITE (title, *) "EMBEDDING SPIN DENSITY DIFFERENCE ", " optimization step ", i_iter
    3098             :          CALL cp_pw_to_cube(spin_diff_rho_r, unit_nr, title, particles=particles, &
    3099           0 :                             stride=section_get_ivals(dft_section, "QS%OPT_EMBED%EMBED_DENS_DIFF%STRIDE"))
    3100             :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
    3101           0 :                                            "DFT%QS%OPT_EMBED%EMBED_DENS_DIFF")
    3102             :       END IF
    3103             : 
    3104          38 :    END SUBROUTINE print_rho_spin_diff
    3105             : ! **************************************************************************************************
    3106             : !> \brief Print embedding potential as a cube and as a binary (for restarting)
    3107             : !> \param qs_env ...
    3108             : !> \param dimen_aux ...
    3109             : !> \param embed_pot_coef ...
    3110             : !> \param embed_pot ...
    3111             : !> \param i_iter ...
    3112             : !> \param embed_pot_spin ...
    3113             : !> \param open_shell_embed ...
    3114             : !> \param grid_opt ...
    3115             : !> \param final_one ...
    3116             : ! **************************************************************************************************
    3117          72 :    SUBROUTINE print_embed_restart(qs_env, dimen_aux, embed_pot_coef, embed_pot, i_iter, &
    3118             :                                   embed_pot_spin, open_shell_embed, grid_opt, final_one)
    3119             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3120             :       INTEGER                                            :: dimen_aux
    3121             :       TYPE(cp_fm_type), INTENT(IN), POINTER              :: embed_pot_coef
    3122             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: embed_pot
    3123             :       INTEGER                                            :: i_iter
    3124             :       TYPE(pw_r3d_rs_type), INTENT(IN), POINTER          :: embed_pot_spin
    3125             :       LOGICAL                                            :: open_shell_embed, grid_opt, final_one
    3126             : 
    3127             :       CHARACTER(LEN=default_path_length)                 :: filename, my_pos_cube, title
    3128             :       INTEGER                                            :: unit_nr
    3129             :       TYPE(cp_logger_type), POINTER                      :: logger
    3130             :       TYPE(particle_list_type), POINTER                  :: particles
    3131             :       TYPE(qs_subsys_type), POINTER                      :: subsys
    3132             :       TYPE(section_vals_type), POINTER                   :: dft_section, input
    3133             : 
    3134          72 :       NULLIFY (input)
    3135             :       CALL get_qs_env(qs_env=qs_env, subsys=subsys, &
    3136          72 :                       input=input)
    3137             : 
    3138             :       ! First we print an unformatted file
    3139          72 :       IF (.NOT. grid_opt) THEN ! Only for finite basis optimization
    3140          44 :          logger => cp_get_default_logger()
    3141          44 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3142             :                                               "DFT%QS%OPT_EMBED%EMBED_POT_VECTOR"), cp_p_file)) THEN
    3143          44 :             IF (.NOT. final_one) THEN
    3144          30 :                WRITE (filename, '(a10,I3.3)') "embed_pot_", i_iter
    3145             :             ELSE
    3146          14 :                WRITE (filename, '(a10,I3.3)') "embed_pot"
    3147             :             END IF
    3148             :             unit_nr = cp_print_key_unit_nr(logger, input, "DFT%QS%OPT_EMBED%EMBED_POT_VECTOR", extension=".wfn", &
    3149          44 :                                            file_form="UNFORMATTED", middle_name=TRIM(filename), file_position="REWIND")
    3150          44 :             IF (unit_nr > 0) THEN
    3151          22 :                WRITE (unit_nr) dimen_aux
    3152             :             END IF
    3153          44 :             CALL cp_fm_write_unformatted(embed_pot_coef, unit_nr)
    3154          44 :             IF (unit_nr > 0) THEN
    3155          22 :                CALL close_file(unit_nr)
    3156             :             END IF
    3157             :          END IF
    3158             :       END IF
    3159             : 
    3160             :       ! Second, cube files
    3161          72 :       dft_section => section_vals_get_subs_vals(input, "DFT")
    3162          72 :       CALL qs_subsys_get(subsys, particles=particles)
    3163             : 
    3164          72 :       logger => cp_get_default_logger()
    3165          72 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3166             :                                            "DFT%QS%OPT_EMBED%EMBED_POT_CUBE"), cp_p_file)) THEN
    3167          32 :          my_pos_cube = "REWIND"
    3168          32 :          IF (.NOT. final_one) THEN
    3169          20 :             WRITE (filename, '(a10,I3.3)') "embed_pot_", i_iter
    3170             :          ELSE
    3171          12 :             WRITE (filename, '(a10,I3.3)') "embed_pot"
    3172             :          END IF
    3173             :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%QS%OPT_EMBED%EMBED_POT_CUBE", &
    3174             :                                         extension=".cube", middle_name=TRIM(filename), file_position=my_pos_cube, &
    3175          32 :                                         log_filename=.FALSE.)
    3176             : 
    3177          32 :          WRITE (title, *) "EMBEDDING POTENTIAL at optimization step ", i_iter
    3178          32 :          CALL cp_pw_to_cube(embed_pot, unit_nr, title, particles=particles)
    3179             : !, &
    3180             : !                            stride=section_get_ivals(dft_section, "QS%OPT_EMBED%EMBED_POT_CUBE%STRIDE"))
    3181             :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
    3182          32 :                                            "DFT%QS%OPT_EMBED%EMBED_POT_CUBE")
    3183          32 :          IF (open_shell_embed) THEN ! Print spin part of the embedding potential
    3184          16 :             my_pos_cube = "REWIND"
    3185          16 :             IF (.NOT. final_one) THEN
    3186          10 :                WRITE (filename, '(a15,I3.3)') "spin_embed_pot_", i_iter
    3187             :             ELSE
    3188           6 :                WRITE (filename, '(a15,I3.3)') "spin_embed_pot"
    3189             :             END IF
    3190             :             unit_nr = cp_print_key_unit_nr(logger, input, "DFT%QS%OPT_EMBED%EMBED_POT_CUBE", &
    3191             :                                            extension=".cube", middle_name=TRIM(filename), file_position=my_pos_cube, &
    3192          16 :                                            log_filename=.FALSE.)
    3193             : 
    3194          16 :             WRITE (title, *) "SPIN EMBEDDING POTENTIAL at optimization step ", i_iter
    3195          16 :             CALL cp_pw_to_cube(embed_pot_spin, unit_nr, title, particles=particles)
    3196             : !,  &
    3197             : !                               stride=section_get_ivals(dft_section, "QS%OPT_EMBED%EMBED_POT_CUBE%STRIDE"))
    3198             :             CALL cp_print_key_finished_output(unit_nr, logger, input, &
    3199          16 :                                               "DFT%QS%OPT_EMBED%EMBED_POT_CUBE")
    3200             :          END IF
    3201             :       END IF
    3202             : 
    3203          72 :    END SUBROUTINE print_embed_restart
    3204             : 
    3205             : ! **************************************************************************************************
    3206             : !> \brief Prints a volumetric file: X Y Z value for interfacing with external programs.
    3207             : !> \param qs_env ...
    3208             : !> \param embed_pot ...
    3209             : !> \param embed_pot_spin ...
    3210             : !> \param i_iter ...
    3211             : !> \param open_shell_embed ...
    3212             : !> \param final_one ...
    3213             : !> \param qs_env_cluster ...
    3214             : ! **************************************************************************************************
    3215          72 :    SUBROUTINE print_pot_simple_grid(qs_env, embed_pot, embed_pot_spin, i_iter, open_shell_embed, &
    3216             :                                     final_one, qs_env_cluster)
    3217             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3218             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: embed_pot
    3219             :       TYPE(pw_r3d_rs_type), INTENT(IN), POINTER          :: embed_pot_spin
    3220             :       INTEGER                                            :: i_iter
    3221             :       LOGICAL                                            :: open_shell_embed, final_one
    3222             :       TYPE(qs_environment_type), POINTER                 :: qs_env_cluster
    3223             : 
    3224             :       CHARACTER(LEN=default_path_length)                 :: filename
    3225             :       INTEGER                                            :: my_units, unit_nr
    3226             :       LOGICAL                                            :: angstrom, bohr
    3227             :       TYPE(cp_logger_type), POINTER                      :: logger
    3228             :       TYPE(pw_env_type), POINTER                         :: pw_env
    3229             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    3230             :       TYPE(pw_r3d_rs_type)                               :: pot_alpha, pot_beta
    3231             :       TYPE(section_vals_type), POINTER                   :: dft_section, input
    3232             : 
    3233          72 :       NULLIFY (input)
    3234          72 :       CALL get_qs_env(qs_env=qs_env, input=input, pw_env=pw_env)
    3235             : 
    3236             :       ! Second, cube files
    3237          72 :       dft_section => section_vals_get_subs_vals(input, "DFT")
    3238             : 
    3239          72 :       NULLIFY (logger)
    3240          72 :       logger => cp_get_default_logger()
    3241          72 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3242             :                                            "DFT%QS%OPT_EMBED%WRITE_SIMPLE_GRID"), cp_p_file)) THEN
    3243             : 
    3244             :          ! Figure out the units
    3245          16 :          angstrom = .FALSE.
    3246          16 :          bohr = .TRUE.
    3247          16 :          CALL section_vals_val_get(dft_section, "QS%OPT_EMBED%WRITE_SIMPLE_GRID%UNITS", i_val=my_units)
    3248             :          SELECT CASE (my_units)
    3249             :          CASE (embed_grid_bohr)
    3250          16 :             bohr = .TRUE.
    3251          16 :             angstrom = .FALSE.
    3252             :          CASE (embed_grid_angstrom)
    3253             :             bohr = .FALSE.
    3254             :             angstrom = .TRUE.
    3255             :          CASE DEFAULT
    3256             :             bohr = .TRUE.
    3257             :             angstrom = .FALSE.
    3258             :          END SELECT
    3259             : 
    3260             :          ! Get alpha and beta potentials
    3261             :          ! Prepare plane-waves pool
    3262          16 :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    3263             : 
    3264             :          ! Create embedding potential and set to zero
    3265          16 :          CALL auxbas_pw_pool%create_pw(pot_alpha)
    3266          16 :          CALL pw_zero(pot_alpha)
    3267             : 
    3268          16 :          CALL pw_copy(embed_pot, pot_alpha)
    3269             : 
    3270          16 :          IF (open_shell_embed) THEN
    3271           0 :             CALL auxbas_pw_pool%create_pw(pot_beta)
    3272           0 :             CALL pw_copy(embed_pot, pot_beta)
    3273             :             ! Add spin potential to the alpha, and subtract from the beta part
    3274           0 :             CALL pw_axpy(embed_pot_spin, pot_alpha, 1.0_dp)
    3275           0 :             CALL pw_axpy(embed_pot_spin, pot_beta, -1.0_dp)
    3276             :          END IF
    3277             : 
    3278          16 :          IF (.NOT. final_one) THEN
    3279          10 :             WRITE (filename, '(a10,I3.3)') "embed_pot_", i_iter
    3280             :          ELSE
    3281           6 :             WRITE (filename, '(a10,I3.3)') "embed_pot"
    3282             :          END IF
    3283             :          unit_nr = cp_print_key_unit_nr(logger, input, "DFT%QS%OPT_EMBED%WRITE_SIMPLE_GRID", extension=".dat", &
    3284          16 :                                         middle_name=TRIM(filename), file_form="FORMATTED", file_position="REWIND")
    3285             : 
    3286          16 :          IF (open_shell_embed) THEN ! Print spin part of the embedding potential
    3287             :             CALL cp_pw_to_simple_volumetric(pw=pot_alpha, unit_nr=unit_nr, &
    3288             :                                             stride=section_get_ivals(dft_section, "QS%OPT_EMBED%WRITE_SIMPLE_GRID%STRIDE"), &
    3289           0 :                                             pw2=pot_beta)
    3290             :          ELSE
    3291             :             CALL cp_pw_to_simple_volumetric(pot_alpha, unit_nr, &
    3292          16 :                                             stride=section_get_ivals(dft_section, "QS%OPT_EMBED%WRITE_SIMPLE_GRID%STRIDE"))
    3293             :          END IF
    3294             : 
    3295             :          CALL cp_print_key_finished_output(unit_nr, logger, input, &
    3296          16 :                                            "DFT%QS%OPT_EMBED%WRITE_SIMPLE_GRID")
    3297             :          ! Release structures
    3298          16 :          CALL pot_alpha%release()
    3299          16 :          IF (open_shell_embed) THEN
    3300           0 :             CALL pot_beta%release()
    3301             :          END IF
    3302             : 
    3303             :       END IF
    3304             : 
    3305             :       ! Fold the coordinates and write into separate file: needed to have the grid correspond to coordinates
    3306             :       ! Needed for external software.
    3307          72 :       CALL print_folded_coordinates(qs_env_cluster, input)
    3308             : 
    3309          72 :    END SUBROUTINE print_pot_simple_grid
    3310             : 
    3311             : ! **************************************************************************************************
    3312             : !> \brief ...
    3313             : !> \param qs_env ...
    3314             : !> \param input ...
    3315             : ! **************************************************************************************************
    3316          72 :    SUBROUTINE print_folded_coordinates(qs_env, input)
    3317             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3318             :       TYPE(section_vals_type), POINTER                   :: input
    3319             : 
    3320          72 :       CHARACTER(LEN=2), ALLOCATABLE, DIMENSION(:)        :: particles_el
    3321             :       CHARACTER(LEN=default_path_length)                 :: filename
    3322             :       INTEGER                                            :: iat, n, unit_nr
    3323          72 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: particles_r
    3324             :       REAL(KIND=dp), DIMENSION(3)                        :: center, r_pbc, s
    3325             :       TYPE(cell_type), POINTER                           :: cell
    3326             :       TYPE(cp_logger_type), POINTER                      :: logger
    3327             :       TYPE(particle_list_type), POINTER                  :: particles
    3328             :       TYPE(qs_subsys_type), POINTER                      :: subsys
    3329             : 
    3330          72 :       NULLIFY (logger)
    3331          72 :       logger => cp_get_default_logger()
    3332          72 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
    3333             :                                            "DFT%QS%OPT_EMBED%WRITE_SIMPLE_GRID/FOLD_COORD"), cp_p_file)) THEN
    3334          16 :          CALL get_qs_env(qs_env=qs_env, cell=cell, subsys=subsys)
    3335          16 :          CALL qs_subsys_get(subsys=subsys, particles=particles)
    3336             : 
    3337             :          ! Prepare the file
    3338          16 :          WRITE (filename, '(a14)') "folded_cluster"
    3339             :          unit_nr = cp_print_key_unit_nr(logger, input, &
    3340             :                                         "DFT%QS%OPT_EMBED%WRITE_SIMPLE_GRID/FOLD_COORD", extension=".dat", &
    3341          16 :                                         middle_name=TRIM(filename), file_form="FORMATTED", file_position="REWIND")
    3342          16 :          IF (unit_nr > 0) THEN
    3343             : 
    3344           8 :             n = particles%n_els
    3345          16 :             ALLOCATE (particles_el(n))
    3346          24 :             ALLOCATE (particles_r(3, n))
    3347          24 :             DO iat = 1, n
    3348          16 :                CALL get_atomic_kind(particles%els(iat)%atomic_kind, element_symbol=particles_el(iat))
    3349          72 :                particles_r(:, iat) = particles%els(iat)%r(:)
    3350             :             END DO
    3351             : 
    3352             :             ! Fold the coordinates
    3353          32 :             center(:) = cell%hmat(:, 1)/2.0_dp + cell%hmat(:, 2)/2.0_dp + cell%hmat(:, 3)/2.0_dp
    3354             : 
    3355             :             ! Print folded coordinates to file
    3356          24 :             DO iat = 1, SIZE(particles_el)
    3357          64 :                r_pbc(:) = particles_r(:, iat) - center
    3358         208 :                s = MATMUL(cell%h_inv, r_pbc)
    3359          64 :                s = s - ANINT(s)
    3360         208 :                r_pbc = MATMUL(cell%hmat, s)
    3361          64 :                r_pbc = r_pbc + center
    3362          24 :                WRITE (unit_nr, '(a4,4f12.6)') particles_el(iat), r_pbc(:)
    3363             :             END DO
    3364             : 
    3365             :             CALL cp_print_key_finished_output(unit_nr, logger, input, &
    3366           8 :                                               "DFT%QS%OPT_EMBED%WRITE_SIMPLE_GRID/FOLD_COORD")
    3367             : 
    3368           8 :             DEALLOCATE (particles_el)
    3369           8 :             DEALLOCATE (particles_r)
    3370             :          END IF
    3371             : 
    3372             :       END IF ! Should output
    3373             : 
    3374          72 :    END SUBROUTINE print_folded_coordinates
    3375             : 
    3376             : ! **************************************************************************************************
    3377             : !> \brief ...
    3378             : !> \param output_unit ...
    3379             : !> \param step_num ...
    3380             : !> \param opt_embed ...
    3381             : ! **************************************************************************************************
    3382          48 :    SUBROUTINE print_emb_opt_info(output_unit, step_num, opt_embed)
    3383             :       INTEGER                                            :: output_unit, step_num
    3384             :       TYPE(opt_embed_pot_type)                           :: opt_embed
    3385             : 
    3386          48 :       IF (output_unit > 0) THEN
    3387             :          WRITE (UNIT=output_unit, FMT="(/,T2,8('-'),A,I5,1X,12('-'))") &
    3388          24 :             "  Optimize embedding potential info at step = ", step_num
    3389             :          WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
    3390          24 :             " Functional value         = ", opt_embed%w_func(step_num)
    3391          24 :          IF (step_num .GT. 1) THEN
    3392             :             WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
    3393          12 :                " Real energy change         = ", opt_embed%w_func(step_num) - &
    3394          24 :                opt_embed%w_func(step_num - 1)
    3395             : 
    3396             :             WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
    3397          12 :                " Step size                  = ", opt_embed%step_len
    3398             : 
    3399             :          END IF
    3400             : 
    3401             :          WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
    3402          24 :             " Trust radius               = ", opt_embed%trust_rad
    3403             : 
    3404          24 :          WRITE (UNIT=output_unit, FMT="(T2,51('-'))")
    3405             :       END IF
    3406             : 
    3407          48 :    END SUBROUTINE print_emb_opt_info
    3408             : 
    3409             : ! **************************************************************************************************
    3410             : !> \brief ...
    3411             : !> \param opt_embed ...
    3412             : !> \param force_env ...
    3413             : !> \param subsys_num ...
    3414             : ! **************************************************************************************************
    3415          96 :    SUBROUTINE get_prev_density(opt_embed, force_env, subsys_num)
    3416             :       TYPE(opt_embed_pot_type)                           :: opt_embed
    3417             :       TYPE(force_env_type), POINTER                      :: force_env
    3418             :       INTEGER                                            :: subsys_num
    3419             : 
    3420             :       INTEGER                                            :: i_dens_start, i_spin, nspins
    3421          96 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r
    3422             :       TYPE(qs_rho_type), POINTER                         :: rho
    3423             : 
    3424          96 :       NULLIFY (rho_r, rho)
    3425          96 :       CALL get_qs_env(force_env%qs_env, rho=rho)
    3426          96 :       CALL qs_rho_get(rho_struct=rho, rho_r=rho_r)
    3427             : 
    3428          96 :       nspins = opt_embed%all_nspins(subsys_num)
    3429             : 
    3430         240 :       i_dens_start = SUM(opt_embed%all_nspins(1:subsys_num)) - nspins + 1
    3431             : 
    3432         244 :       DO i_spin = 1, nspins
    3433             :          opt_embed%prev_subsys_dens(i_dens_start + i_spin - 1)%array(:, :, :) = &
    3434     3059550 :             rho_r(i_spin)%array(:, :, :)
    3435             :       END DO
    3436             : 
    3437          96 :    END SUBROUTINE get_prev_density
    3438             : 
    3439             : ! **************************************************************************************************
    3440             : !> \brief ...
    3441             : !> \param opt_embed ...
    3442             : !> \param force_env ...
    3443             : !> \param subsys_num ...
    3444             : ! **************************************************************************************************
    3445          96 :    SUBROUTINE get_max_subsys_diff(opt_embed, force_env, subsys_num)
    3446             :       TYPE(opt_embed_pot_type)                           :: opt_embed
    3447             :       TYPE(force_env_type), POINTER                      :: force_env
    3448             :       INTEGER                                            :: subsys_num
    3449             : 
    3450             :       INTEGER                                            :: i_dens_start, i_spin, nspins
    3451          96 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r
    3452             :       TYPE(qs_rho_type), POINTER                         :: rho
    3453             : 
    3454          96 :       NULLIFY (rho_r, rho)
    3455          96 :       CALL get_qs_env(force_env%qs_env, rho=rho)
    3456          96 :       CALL qs_rho_get(rho_struct=rho, rho_r=rho_r)
    3457             : 
    3458          96 :       nspins = opt_embed%all_nspins(subsys_num)
    3459             : 
    3460         240 :       i_dens_start = SUM(opt_embed%all_nspins(1:subsys_num)) - nspins + 1
    3461             : 
    3462         244 :       DO i_spin = 1, nspins
    3463             :          CALL pw_axpy(rho_r(i_spin), opt_embed%prev_subsys_dens(i_dens_start + i_spin - 1), 1.0_dp, -1.0_dp, &
    3464         148 :                       allow_noncompatible_grids=.TRUE.)
    3465             :          opt_embed%max_subsys_dens_diff(i_dens_start + i_spin - 1) = &
    3466         244 :             max_dens_diff(opt_embed%prev_subsys_dens(i_dens_start + i_spin - 1))
    3467             :       END DO
    3468             : 
    3469          96 :    END SUBROUTINE get_max_subsys_diff
    3470             : 
    3471             : ! **************************************************************************************************
    3472             : !> \brief ...
    3473             : !> \param opt_embed ...
    3474             : !> \param diff_rho_r ...
    3475             : !> \param diff_rho_spin ...
    3476             : !> \param output_unit ...
    3477             : ! **************************************************************************************************
    3478          48 :    SUBROUTINE conv_check_embed(opt_embed, diff_rho_r, diff_rho_spin, output_unit)
    3479             :       TYPE(opt_embed_pot_type)                           :: opt_embed
    3480             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: diff_rho_r, diff_rho_spin
    3481             :       INTEGER                                            :: output_unit
    3482             : 
    3483             :       INTEGER                                            :: i_dens, i_dens_start, i_spin
    3484             :       LOGICAL                                            :: conv_int_diff, conv_max_diff
    3485             :       REAL(KIND=dp)                                      :: int_diff, int_diff_spin, &
    3486             :                                                             int_diff_square, int_diff_square_spin, &
    3487             :                                                             max_diff, max_diff_spin
    3488             : 
    3489             :       ! Calculate the convergence target values
    3490          48 :       opt_embed%max_diff(1) = max_dens_diff(diff_rho_r)
    3491          48 :       opt_embed%int_diff(1) = pw_integrate_function(fun=diff_rho_r, oprt='ABS')
    3492          48 :       opt_embed%int_diff_square(1) = pw_integral_ab(diff_rho_r, diff_rho_r)
    3493          48 :       IF (opt_embed%open_shell_embed) THEN
    3494          26 :          opt_embed%max_diff(2) = max_dens_diff(diff_rho_spin)
    3495          26 :          opt_embed%int_diff(2) = pw_integrate_function(fun=diff_rho_spin, oprt='ABS')
    3496          26 :          opt_embed%int_diff_square(2) = pw_integral_ab(diff_rho_spin, diff_rho_spin)
    3497             :       END IF
    3498             : 
    3499             :       ! Find out the convergence
    3500          48 :       max_diff = opt_embed%max_diff(1)
    3501             : 
    3502             :       ! Maximum value criterium
    3503             :       ! Open shell
    3504          48 :       IF (opt_embed%open_shell_embed) THEN
    3505          26 :          max_diff_spin = opt_embed%max_diff(2)
    3506          26 :          IF ((max_diff .LE. opt_embed%conv_max) .AND. (max_diff_spin .LE. opt_embed%conv_max_spin)) THEN
    3507             :             conv_max_diff = .TRUE.
    3508             :          ELSE
    3509          12 :             conv_max_diff = .FALSE.
    3510             :          END IF
    3511             :       ELSE
    3512             :          ! Closed shell
    3513          22 :          IF (max_diff .LE. opt_embed%conv_max) THEN
    3514             :             conv_max_diff = .TRUE.
    3515             :          ELSE
    3516           8 :             conv_max_diff = .FALSE.
    3517             :          END IF
    3518             :       END IF
    3519             : 
    3520             :       ! Integrated value criterium
    3521          48 :       int_diff = opt_embed%int_diff(1)
    3522             :       ! Open shell
    3523          48 :       IF (opt_embed%open_shell_embed) THEN
    3524          26 :          int_diff_spin = opt_embed%int_diff(2)
    3525          26 :          IF ((int_diff .LE. opt_embed%conv_int) .AND. (int_diff_spin .LE. opt_embed%conv_int_spin)) THEN
    3526             :             conv_int_diff = .TRUE.
    3527             :          ELSE
    3528           6 :             conv_int_diff = .FALSE.
    3529             :          END IF
    3530             :       ELSE
    3531             :          ! Closed shell
    3532          22 :          IF (int_diff .LE. opt_embed%conv_int) THEN
    3533             :             conv_int_diff = .TRUE.
    3534             :          ELSE
    3535          10 :             conv_int_diff = .FALSE.
    3536             :          END IF
    3537             :       END IF
    3538             : 
    3539             :       ! Integrated squared value criterium
    3540          48 :       int_diff_square = opt_embed%int_diff_square(1)
    3541             :       ! Open shell
    3542          48 :       IF (opt_embed%open_shell_embed) int_diff_square_spin = opt_embed%int_diff_square(2)
    3543             : 
    3544          48 :       IF ((conv_max_diff) .AND. (conv_int_diff)) THEN
    3545          24 :          opt_embed%converged = .TRUE.
    3546             :       ELSE
    3547          24 :          opt_embed%converged = .FALSE.
    3548             :       END IF
    3549             : 
    3550             :       ! Print the information
    3551          48 :       IF (output_unit > 0) THEN
    3552             :          WRITE (UNIT=output_unit, FMT="(/,T2,A)") &
    3553          24 :             " Convergence check :"
    3554             : 
    3555             :          ! Maximum value of density
    3556             :          WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
    3557          24 :             " Maximum density difference                = ", max_diff
    3558             :          WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
    3559          24 :             " Convergence limit for max. density diff.  = ", opt_embed%conv_max
    3560             : 
    3561          24 :          IF (opt_embed%open_shell_embed) THEN
    3562             : 
    3563             :             WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
    3564          13 :                " Maximum spin density difference           = ", max_diff_spin
    3565             :             WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
    3566          13 :                " Convergence limit for max. spin dens.diff.= ", opt_embed%conv_max_spin
    3567             : 
    3568             :          END IF
    3569             : 
    3570          24 :          IF (conv_max_diff) THEN
    3571             :             WRITE (UNIT=output_unit, FMT="(T2,2A)") &
    3572          14 :                " Convergence in max. density diff.    =     ", &
    3573          28 :                "             YES"
    3574             :          ELSE
    3575             :             WRITE (UNIT=output_unit, FMT="(T2,2A)") &
    3576          10 :                " Convergence in max. density diff.    =     ", &
    3577          20 :                "              NO"
    3578             :          END IF
    3579             : 
    3580             :          ! Integrated abs. value of density
    3581             :          WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
    3582          24 :             " Integrated density difference             = ", int_diff
    3583             :          WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
    3584          24 :             " Conv. limit for integrated density diff.  = ", opt_embed%conv_int
    3585          24 :          IF (opt_embed%open_shell_embed) THEN
    3586             :             WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
    3587          13 :                " Integrated spin density difference        = ", int_diff_spin
    3588             :             WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
    3589          13 :                " Conv. limit for integrated spin dens.diff.= ", opt_embed%conv_int_spin
    3590             :          END IF
    3591             : 
    3592          24 :          IF (conv_int_diff) THEN
    3593             :             WRITE (UNIT=output_unit, FMT="(T2,2A)") &
    3594          16 :                " Convergence in integrated density diff.    =     ", &
    3595          32 :                "             YES"
    3596             :          ELSE
    3597             :             WRITE (UNIT=output_unit, FMT="(T2,2A)") &
    3598           8 :                " Convergence in integrated density diff.    =     ", &
    3599          16 :                "              NO"
    3600             :          END IF
    3601             : 
    3602             :          ! Integrated squared value of density
    3603             :          WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
    3604          24 :             " Integrated squared density difference     = ", int_diff_square
    3605          24 :          IF (opt_embed%open_shell_embed) THEN
    3606             :             WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
    3607          13 :                " Integrated squared spin density difference= ", int_diff_square_spin
    3608             :          END IF
    3609             : 
    3610             :          ! Maximum subsystem density change
    3611             :          WRITE (UNIT=output_unit, FMT="(/,T2,A)") &
    3612          24 :             " Maximum density change in:"
    3613          72 :          DO i_dens = 1, (SIZE(opt_embed%all_nspins) - 1)
    3614         120 :             i_dens_start = SUM(opt_embed%all_nspins(1:i_dens)) - opt_embed%all_nspins(i_dens) + 1
    3615         146 :             DO i_spin = 1, opt_embed%all_nspins(i_dens)
    3616             :                WRITE (UNIT=output_unit, FMT="(T4,A10,I3,A6,I3,A1,F20.10)") &
    3617          74 :                   " subsystem ", i_dens, ', spin', i_spin, ":", &
    3618         196 :                   opt_embed%max_subsys_dens_diff(i_dens_start + i_spin - 1)
    3619             :             END DO
    3620             :          END DO
    3621             : 
    3622             :       END IF
    3623             : 
    3624          48 :       IF ((opt_embed%converged) .AND. (output_unit > 0)) THEN
    3625          12 :          WRITE (UNIT=output_unit, FMT="(/,T2,A)") REPEAT("*", 79)
    3626             :          WRITE (UNIT=output_unit, FMT="(T2,A,T25,A,T78,A)") &
    3627          12 :             "***", "EMBEDDING POTENTIAL OPTIMIZATION COMPLETED", "***"
    3628          12 :          WRITE (UNIT=output_unit, FMT="(T2,A)") REPEAT("*", 79)
    3629             :       END IF
    3630             : 
    3631          48 :    END SUBROUTINE conv_check_embed
    3632             : 
    3633             : END MODULE optimize_embedding_potential

Generated by: LCOV version 1.15