LCOV - code coverage report
Current view: top level - src - optimize_embedding_potential.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 81.2 % 1312 1065
Test Date: 2025-12-04 06:27:48 Functions: 92.7 % 41 38

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

Generated by: LCOV version 2.0-1