LCOV - code coverage report
Current view: top level - src - qs_sccs.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:123285f) Lines: 75.8 % 533 404
Test Date: 2026-11-04 00:58:17 Functions: 88.9 % 9 8

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief   Self-consistent continuum solvation (SCCS) model implementation
      10              : !> \author  Matthias Krack (MK)
      11              : !> \version 1.0
      12              : !> \par Literature:
      13              : !>      - J.-L. Fattebert and F. Gygi,
      14              : !>        Density functional theory for efficient ab initio molecular dynamics
      15              : !>        simulations in solution, J. Comput. Chem. 23, 662-666 (2002)
      16              : !>      - O. Andreussi, I. Dabo, and N. Marzari,
      17              : !>        Revised self-consistent continuum solvation in electronic-structure
      18              : !>        calculations, J. Chem. Phys. 136, 064102-20 (2012)
      19              : !> \par History:
      20              : !>      - Creation (10.10.2013,MK)
      21              : !>      - Derivatives using finite differences (26.11.2013,MK)
      22              : !>      - Cube file dump of the dielectric function (19.12.2013,MK)
      23              : !>      - Cube file dump of the polarisation potential (20.12.2013,MK)
      24              : !>      - Calculation of volume and surface of the cavity (21.12.2013,MK)
      25              : !>      - Functional derivative of the cavitation energy (28.12.2013,MK)
      26              : !>      - Update printout (11.11.2022,MK)
      27              : ! **************************************************************************************************
      28              : 
      29              : MODULE qs_sccs
      30              : 
      31              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      32              :                                               get_atomic_kind
      33              :    USE cp_control_types,                ONLY: dft_control_type,&
      34              :                                               sccs_control_type
      35              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      36              :                                               cp_logger_get_default_io_unit,&
      37              :                                               cp_logger_type
      38              :    USE cp_output_handling,              ONLY: cp_p_file,&
      39              :                                               cp_print_key_finished_output,&
      40              :                                               cp_print_key_should_output,&
      41              :                                               cp_print_key_unit_nr,&
      42              :                                               low_print_level
      43              :    USE cp_realspace_grid_cube,          ONLY: cp_pw_to_cube
      44              :    USE cp_realspace_grid_init,          ONLY: init_input_type
      45              :    USE cp_subsys_types,                 ONLY: cp_subsys_get,&
      46              :                                               cp_subsys_type
      47              :    USE cp_units,                        ONLY: cp_unit_from_cp2k
      48              :    USE input_constants,                 ONLY: sccs_andreussi,&
      49              :                                               sccs_derivative_cd3,&
      50              :                                               sccs_derivative_cd5,&
      51              :                                               sccs_derivative_cd7,&
      52              :                                               sccs_derivative_fft,&
      53              :                                               sccs_fattebert_gygi,&
      54              :                                               sccs_saa_andreussi
      55              :    USE input_section_types,             ONLY: section_get_ivals,&
      56              :                                               section_get_lval,&
      57              :                                               section_vals_get_subs_vals,&
      58              :                                               section_vals_type
      59              :    USE kinds,                           ONLY: default_path_length,&
      60              :                                               default_string_length,&
      61              :                                               dp,&
      62              :                                               int_8
      63              :    USE mathconstants,                   ONLY: fourpi,&
      64              :                                               oorootpi,&
      65              :                                               pi,&
      66              :                                               twopi
      67              :    USE message_passing,                 ONLY: mp_para_env_type
      68              :    USE particle_list_types,             ONLY: particle_list_type
      69              :    USE pw_env_types,                    ONLY: pw_env_get,&
      70              :                                               pw_env_type
      71              :    USE pw_methods,                      ONLY: pw_axpy,&
      72              :                                               pw_copy,&
      73              :                                               pw_derive,&
      74              :                                               pw_integral_ab,&
      75              :                                               pw_integrate_function,&
      76              :                                               pw_scale,&
      77              :                                               pw_transfer,&
      78              :                                               pw_zero
      79              :    USE pw_poisson_methods,              ONLY: pw_func_u_convolution,&
      80              :                                               pw_poisson_solve
      81              :    USE pw_poisson_types,                ONLY: pw_poisson_analytic,&
      82              :                                               pw_poisson_mt,&
      83              :                                               pw_poisson_type
      84              :    USE pw_pool_types,                   ONLY: pw_pool_p_type,&
      85              :                                               pw_pool_type
      86              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      87              :                                               pw_r3d_rs_type
      88              :    USE qs_collocate_density,            ONLY: calculate_rho_core
      89              :    USE qs_energy_types,                 ONLY: qs_energy_type
      90              :    USE qs_environment_types,            ONLY: get_qs_env,&
      91              :                                               qs_environment_type
      92              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      93              :                                               qs_kind_type
      94              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      95              :                                               qs_rho_type
      96              :    USE qs_scf_types,                    ONLY: qs_scf_env_type
      97              :    USE realspace_grid_types,            ONLY: realspace_grid_desc_type,&
      98              :                                               realspace_grid_input_type,&
      99              :                                               realspace_grid_type,&
     100              :                                               rs_grid_create,&
     101              :                                               rs_grid_create_descriptor,&
     102              :                                               rs_grid_release,&
     103              :                                               rs_grid_release_descriptor
     104              :    USE rs_methods,                      ONLY: derive_fdm_cd3,&
     105              :                                               derive_fdm_cd5,&
     106              :                                               derive_fdm_cd7
     107              :    USE string_utilities,                ONLY: uppercase
     108              : #include "./base/base_uses.f90"
     109              : 
     110              :    IMPLICIT NONE
     111              : 
     112              :    PRIVATE
     113              : 
     114              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_sccs'
     115              : 
     116              :    PUBLIC :: print_sccs_results, sccs, sccs_core_fill_coefficients
     117              : 
     118              : CONTAINS
     119              : 
     120              : ! **************************************************************************************************
     121              : !> \brief   Self-consistent continuum solvation (SCCS) model implementation
     122              : !> \param qs_env ...
     123              : !> \param rho_tot_gspace ...
     124              : !> \param v_hartree_gspace ...
     125              : !> \param v_sccs ...
     126              : !> \param h_stress ...
     127              : !> \par History:
     128              : !>      - Creation (10.10.2013,MK)
     129              : !> \author  Matthias Krack (MK)
     130              : !> \version 1.0
     131              : ! **************************************************************************************************
     132              : 
     133          262 :    SUBROUTINE sccs(qs_env, rho_tot_gspace, v_hartree_gspace, v_sccs, h_stress)
     134              : 
     135              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     136              :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: rho_tot_gspace, v_hartree_gspace
     137              :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: v_sccs
     138              :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(OUT), &
     139              :          OPTIONAL                                        :: h_stress
     140              : 
     141              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'sccs'
     142              :       REAL(KIND=dp), PARAMETER                           :: epstol = 1.0E-8_dp
     143              : 
     144              :       CHARACTER(LEN=4*default_string_length)             :: message, my_pos_cube
     145              :       CHARACTER(LEN=default_path_length)                 :: cube_path, filename, mpi_filename, &
     146              :                                                             print_path
     147              :       INTEGER                                            :: cube_unit, handle, i, ispin, iter, j, k, &
     148              :                                                             nspin, output_unit, print_level
     149              :       INTEGER(KIND=int_8)                                :: ngpts
     150              :       INTEGER, DIMENSION(3)                              :: lb, ub
     151              :       LOGICAL                                            :: append_cube, calculate_stress_tensor, &
     152              :                                                             do_kpoints, mpi_io, should_output
     153              :       REAL(KIND=dp) :: alpha_zeta, cavity_surface, cavity_volume, cell_volume, delta_eta, &
     154              :          delta_zeta, dphi2, dvol, e_tot, epsilon_solvent, f, f0, polarisation_charge, r, R_solv, &
     155              :          rho_delta, rho_delta_avg, rho_delta_max, rho_iter_new, tot_rho_elec, tot_rho_solute
     156              :       REAL(KIND=dp), DIMENSION(3)                        :: abc, lxyz, uxyz
     157              :       TYPE(cp_logger_type), POINTER                      :: logger
     158              :       TYPE(cp_subsys_type), POINTER                      :: cp_subsys
     159              :       TYPE(dft_control_type), POINTER                    :: dft_control
     160              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     161              :       TYPE(particle_list_type), POINTER                  :: particles
     162              :       TYPE(pw_env_type), POINTER                         :: pw_env
     163              :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     164          262 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
     165              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     166              :       TYPE(pw_r3d_rs_type)                               :: d_s_rhoel, deps_elec, dtf, eps_elec, ff, &
     167              :                                                             p_e_interface, s, t, tem_convolution, &
     168              :                                                             tem_func, u
     169         1834 :       TYPE(pw_r3d_rs_type), DIMENSION(3)                 :: dln_eps_elec, dphi_tot
     170          262 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_pw_r
     171              :       TYPE(pw_r3d_rs_type), POINTER                      :: rho_pw_r_sccs
     172              :       TYPE(qs_energy_type), POINTER                      :: energy
     173              :       TYPE(qs_rho_type), POINTER                         :: rho
     174              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     175              :       TYPE(sccs_control_type), POINTER                   :: sccs_control
     176              :       TYPE(section_vals_type), POINTER                   :: input
     177              : 
     178          262 :       CALL timeset(routineN, handle)
     179              : 
     180          262 :       NULLIFY (auxbas_pw_pool)
     181          262 :       NULLIFY (cp_subsys)
     182          262 :       NULLIFY (dft_control)
     183          262 :       NULLIFY (energy)
     184          262 :       NULLIFY (input)
     185          262 :       NULLIFY (logger)
     186          262 :       NULLIFY (para_env)
     187          262 :       NULLIFY (particles)
     188          262 :       NULLIFY (poisson_env)
     189          262 :       NULLIFY (pw_env)
     190          262 :       NULLIFY (pw_pools)
     191          262 :       NULLIFY (rho)
     192          262 :       NULLIFY (sccs_control)
     193          262 :       NULLIFY (scf_env)
     194              : 
     195              :       ! Load data from Quickstep environment
     196              :       CALL get_qs_env(qs_env=qs_env, &
     197              :                       cp_subsys=cp_subsys, &
     198              :                       do_kpoints=do_kpoints, &
     199              :                       dft_control=dft_control, &
     200              :                       energy=energy, &
     201              :                       input=input, &
     202              :                       para_env=para_env, &
     203              :                       pw_env=pw_env, &
     204              :                       rho=rho, &
     205          262 :                       scf_env=scf_env)
     206          262 :       CALL cp_subsys_get(cp_subsys, particles=particles)
     207              : 
     208          262 :       sccs_control => dft_control%sccs_control
     209              : 
     210          262 :       CPASSERT(ASSOCIATED(qs_env))
     211              : 
     212          262 :       IF (do_kpoints) THEN
     213            0 :          CPWARN("SCCS with k-points has not yet been fully validated")
     214              :       END IF
     215              : 
     216          262 :       IF (PRESENT(h_stress)) THEN
     217            0 :          calculate_stress_tensor = .TRUE.
     218            0 :          h_stress(:, :) = 0.0_dp
     219            0 :          CPWARN("The stress tensor for SCCS has not yet been fully validated")
     220              :       ELSE
     221              :          calculate_stress_tensor = .FALSE.
     222              :       END IF
     223              : 
     224              :       ! Get access to the PW grid pool
     225              :       CALL pw_env_get(pw_env, &
     226              :                       auxbas_pw_pool=auxbas_pw_pool, &
     227              :                       pw_pools=pw_pools, &
     228          262 :                       poisson_env=poisson_env)
     229              : 
     230          262 :       CALL pw_zero(v_sccs)
     231              : 
     232              :       ! Calculate no SCCS contribution, if the requested SCF convergence threshold is not reached yet
     233          262 :       IF (.NOT. sccs_control%sccs_activated) THEN
     234           86 :          IF (sccs_control%eps_scf > 0.0_dp) THEN
     235           84 :             IF ((scf_env%iter_delta > sccs_control%eps_scf) .OR. &
     236              :                 ((qs_env%scf_env%outer_scf%iter_count == 0) .AND. &
     237              :                  (qs_env%scf_env%iter_count <= 1))) THEN
     238           70 :                IF (calculate_stress_tensor) THEN
     239              :                   ! Request also the calculation of the stress tensor contribution
     240              :                   CALL pw_poisson_solve(poisson_env=poisson_env, &
     241              :                                         density=rho_tot_gspace, &
     242              :                                         ehartree=energy%hartree, &
     243              :                                         vhartree=v_hartree_gspace, &
     244            0 :                                         h_stress=h_stress)
     245              :                ELSE
     246              :                   CALL pw_poisson_solve(poisson_env=poisson_env, &
     247              :                                         density=rho_tot_gspace, &
     248              :                                         ehartree=energy%hartree, &
     249           70 :                                         vhartree=v_hartree_gspace)
     250              :                END IF
     251           70 :                energy%sccs_pol = 0.0_dp
     252           70 :                energy%sccs_cav = 0.0_dp
     253           70 :                energy%sccs_dis = 0.0_dp
     254           70 :                energy%sccs_rep = 0.0_dp
     255           70 :                energy%sccs_sol = 0.0_dp
     256           70 :                energy%sccs_hartree = energy%hartree
     257           70 :                CALL timestop(handle)
     258           70 :                RETURN
     259              :             END IF
     260              :          END IF
     261           16 :          sccs_control%sccs_activated = .TRUE.
     262              :       END IF
     263              : 
     264          192 :       nspin = dft_control%nspins
     265              : 
     266              :       ! Manage print output control
     267          192 :       logger => cp_get_default_logger()
     268          192 :       print_level = logger%iter_info%print_level
     269          192 :       print_path = "DFT%PRINT%SCCS"
     270              :       should_output = (BTEST(cp_print_key_should_output(logger%iter_info, input, &
     271          192 :                                                         TRIM(print_path)), cp_p_file))
     272              :       output_unit = cp_print_key_unit_nr(logger, input, TRIM(print_path), &
     273              :                                          extension=".sccs", &
     274              :                                          ignore_should_output=should_output, &
     275          192 :                                          log_filename=.FALSE.)
     276              : 
     277              :       ! Get rho
     278              :       CALL qs_rho_get(rho_struct=rho, &
     279              :                       rho_r=rho_pw_r, &
     280          192 :                       rho_r_sccs=rho_pw_r_sccs)
     281              : 
     282              :       ! Retrieve the last rho_iter from the previous SCCS cycle if available
     283          192 :       CPASSERT(ASSOCIATED(rho_pw_r_sccs))
     284              : 
     285              :       ! Retrieve the total electronic density in r-space
     286              :       BLOCK
     287              :          TYPE(pw_r3d_rs_type) :: rho_elec
     288          192 :          CALL auxbas_pw_pool%create_pw(rho_elec)
     289              : 
     290              :          ! Retrieve grid parameters
     291          192 :          ngpts = rho_elec%pw_grid%ngpts
     292          192 :          dvol = rho_elec%pw_grid%dvol
     293          192 :          cell_volume = rho_elec%pw_grid%vol
     294          768 :          abc(1:3) = REAL(rho_elec%pw_grid%npts(1:3), KIND=dp)*rho_elec%pw_grid%dr(1:3)
     295          768 :          lb(1:3) = rho_elec%pw_grid%bounds_local(1, 1:3)
     296          768 :          ub(1:3) = rho_elec%pw_grid%bounds_local(2, 1:3)
     297              : 
     298          192 :          CALL pw_copy(rho_pw_r(1), rho_elec)
     299          214 :          DO ispin = 2, nspin
     300          214 :             CALL pw_axpy(rho_pw_r(ispin), rho_elec)
     301              :          END DO
     302          192 :          tot_rho_elec = pw_integrate_function(rho_elec)
     303              : 
     304              :          ! Optionally fill the low valence density region at the nuclei of pseudopotential
     305              :          ! atoms with normalised Gaussians Z_val/(sqrt(pi)*sigma)**3*exp(-r**2/sigma**2)
     306              :          ! (Environ "full" boundary). The filled density is only used for the definition
     307              :          ! of the dielectric function (cavity)
     308          192 :          IF (sccs_control%core_fill) THEN
     309           78 :             BLOCK
     310              :                REAL(KIND=dp)                                      :: tot_rho_fill
     311           78 :                REAL(KIND=dp), DIMENSION(:), ALLOCATABLE           :: calpha, ccore
     312              :                TYPE(pw_r3d_rs_type)                               :: rho_fill
     313           78 :                CALL sccs_core_fill_coefficients(qs_env, calpha, ccore, cp_logger_get_default_io_unit(logger))
     314           78 :                CALL auxbas_pw_pool%create_pw(rho_fill)
     315              :                ! calculate_rho_core collocates -ccore*exp(-calpha*r**2), i.e. the negated fill
     316           78 :                CALL calculate_rho_core(rho_fill, tot_rho_fill, qs_env, calpha=calpha, ccore=ccore)
     317           78 :                CALL pw_axpy(rho_fill, rho_elec, alpha=-1.0_dp)
     318           78 :                CALL auxbas_pw_pool%give_back_pw(rho_fill)
     319          156 :                DEALLOCATE (calpha, ccore)
     320              :             END BLOCK
     321              :          END IF
     322              : 
     323              :          ! Calculate the dielectric (smoothed) function of rho_elec in r-space
     324          192 :          CALL auxbas_pw_pool%create_pw(eps_elec)
     325          192 :          CALL auxbas_pw_pool%create_pw(deps_elec)
     326          192 :          IF (sccs_control%method_id == sccs_saa_andreussi) THEN
     327            0 :             CALL auxbas_pw_pool%create_pw(s)
     328            0 :             CALL auxbas_pw_pool%create_pw(d_s_rhoel)
     329            0 :             CALL auxbas_pw_pool%create_pw(u)
     330            0 :             CALL auxbas_pw_pool%create_pw(ff)
     331            0 :             CALL auxbas_pw_pool%create_pw(t)
     332            0 :             CALL auxbas_pw_pool%create_pw(dtf)
     333            0 :             f0 = sccs_control%f0
     334            0 :             delta_eta = sccs_control%delta_eta
     335            0 :             alpha_zeta = sccs_control%alpha_zeta
     336            0 :             R_solv = sccs_control%R_solv
     337            0 :             delta_zeta = sccs_control%delta_zeta
     338              :          END IF
     339              : 
     340              :          ! Relative permittivity or dielectric constant of the solvent (medium)
     341          192 :          epsilon_solvent = sccs_control%epsilon_solvent
     342          340 :          SELECT CASE (sccs_control%method_id)
     343              :          CASE (sccs_andreussi)
     344              :             CALL andreussi(rho_elec, eps_elec, deps_elec, epsilon_solvent, sccs_control%rho_max, &
     345          148 :                            sccs_control%rho_min)
     346              :          CASE (sccs_fattebert_gygi)
     347              :             CALL fattebert_gygi(rho_elec, eps_elec, deps_elec, epsilon_solvent, sccs_control%beta, &
     348           44 :                                 sccs_control%rho_zero)
     349              :          CASE (sccs_saa_andreussi)
     350              :             CALL sa_andreussi(rho_elec, eps_elec, deps_elec, epsilon_solvent, sccs_control%rho_max, &
     351            0 :                               sccs_control%rho_min, s, d_s_rhoel)
     352              :          CASE DEFAULT
     353          192 :             CPABORT("Invalid method specified for SCCS model")
     354              :          END SELECT
     355              : 
     356          192 :          IF (sccs_control%method_id /= sccs_saa_andreussi) THEN
     357              :             ! Optional output of the dielectric function in cube file format
     358          192 :             filename = "DIELECTRIC_FUNCTION"
     359          192 :             cube_path = TRIM(print_path)//"%"//TRIM(filename)
     360          192 :             IF (BTEST(cp_print_key_should_output(logger%iter_info, input, TRIM(cube_path)), &
     361              :                       cp_p_file)) THEN
     362            4 :                append_cube = section_get_lval(input, TRIM(cube_path)//"%APPEND")
     363            4 :                my_pos_cube = "REWIND"
     364            4 :                IF (append_cube) my_pos_cube = "APPEND"
     365            4 :                mpi_io = .TRUE.
     366              :                cube_unit = cp_print_key_unit_nr(logger, input, TRIM(cube_path), &
     367              :                                                 extension=".cube", middle_name=TRIM(filename), &
     368              :                                                 file_position=my_pos_cube, log_filename=.FALSE., &
     369            4 :                                                 mpi_io=mpi_io, fout=mpi_filename)
     370            4 :                IF (output_unit > 0) THEN
     371            2 :                   IF (.NOT. mpi_io) THEN
     372            0 :                      INQUIRE (UNIT=cube_unit, NAME=filename)
     373              :                   ELSE
     374            2 :                      filename = mpi_filename
     375              :                   END IF
     376              :                   WRITE (UNIT=output_unit, FMT="(T3,A)") &
     377            2 :                      "SCCS| The dielectric function is written in cube file format to the file:", &
     378            4 :                      "SCCS| "//TRIM(filename)
     379              :                END IF
     380              :                CALL cp_pw_to_cube(eps_elec, cube_unit, TRIM(filename), particles=particles, &
     381              :                                   stride=section_get_ivals(input, TRIM(cube_path)//"%STRIDE"), &
     382            4 :                                   mpi_io=mpi_io)
     383            4 :                CALL cp_print_key_finished_output(cube_unit, logger, input, TRIM(cube_path), mpi_io=mpi_io)
     384              :             END IF
     385              :          END IF
     386              : 
     387              :          ! Calculate the (quantum) volume and surface of the solute cavity
     388          192 :          cavity_surface = 0.0_dp
     389          192 :          cavity_volume = 0.0_dp
     390              : 
     391          192 :          IF (ABS(epsilon_solvent - 1.0_dp) > epstol) THEN
     392              : 
     393              :             BLOCK
     394              :                TYPE(pw_r3d_rs_type) :: theta, norm_drho_elec
     395          768 :                TYPE(pw_r3d_rs_type), DIMENSION(3)                        :: drho_elec
     396          192 :                CALL auxbas_pw_pool%create_pw(theta)
     397          192 :                CALL pw_zero(theta)
     398              : 
     399              :                ! Calculate the (quantum) volume of the solute cavity
     400          192 :                f = 1.0_dp/(epsilon_solvent - 1.0_dp)
     401              : !$OMP    PARALLEL DO DEFAULT(NONE) &
     402              : !$OMP                PRIVATE(i,j,k) &
     403          192 : !$OMP                SHARED(epsilon_solvent,eps_elec,f,lb,theta,ub)
     404              :                DO k = lb(3), ub(3)
     405              :                   DO j = lb(2), ub(2)
     406              :                      DO i = lb(1), ub(1)
     407              :                         theta%array(i, j, k) = f*(epsilon_solvent - eps_elec%array(i, j, k))
     408              :                      END DO
     409              :                   END DO
     410              :                END DO
     411              : !$OMP    END PARALLEL DO
     412          192 :                cavity_volume = pw_integrate_function(theta)
     413              : 
     414              :                ! Calculate the derivative of the electronic density in r-space
     415              :                ! TODO: Could be retrieved from the QS environment
     416          768 :                DO i = 1, 3
     417          768 :                   CALL auxbas_pw_pool%create_pw(drho_elec(i))
     418              :                END DO
     419          192 :                CALL derive(rho_elec, drho_elec, sccs_derivative_fft, pw_env, input)
     420              : 
     421          192 :                CALL auxbas_pw_pool%create_pw(norm_drho_elec)
     422              : 
     423              :                ! Calculate the norm of the gradient of the electronic density in r-space
     424              : !$OMP    PARALLEL DO DEFAULT(NONE) &
     425              : !$OMP                PRIVATE(i,j,k) &
     426          192 : !$OMP                SHARED(drho_elec,lb,norm_drho_elec,ub)
     427              :                DO k = lb(3), ub(3)
     428              :                   DO j = lb(2), ub(2)
     429              :                      DO i = lb(1), ub(1)
     430              :                         norm_drho_elec%array(i, j, k) = SQRT(drho_elec(1)%array(i, j, k)* &
     431              :                                                              drho_elec(1)%array(i, j, k) + &
     432              :                                                              drho_elec(2)%array(i, j, k)* &
     433              :                                                              drho_elec(2)%array(i, j, k) + &
     434              :                                                              drho_elec(3)%array(i, j, k)* &
     435              :                                                              drho_elec(3)%array(i, j, k))
     436              :                      END DO
     437              :                   END DO
     438              :                END DO
     439              : !$OMP    END PARALLEL DO
     440              : 
     441              :                ! Optional output of the norm of the density gradient in cube file format
     442          192 :                filename = "DENSITY_GRADIENT"
     443          192 :                cube_path = TRIM(print_path)//"%"//TRIM(filename)
     444          192 :                IF (BTEST(cp_print_key_should_output(logger%iter_info, input, TRIM(cube_path)), &
     445              :                          cp_p_file)) THEN
     446            0 :                   append_cube = section_get_lval(input, TRIM(cube_path)//"%APPEND")
     447            0 :                   my_pos_cube = "REWIND"
     448            0 :                   IF (append_cube) my_pos_cube = "APPEND"
     449            0 :                   mpi_io = .TRUE.
     450              :                   cube_unit = cp_print_key_unit_nr(logger, input, TRIM(cube_path), &
     451              :                                                    extension=".cube", middle_name=TRIM(filename), &
     452              :                                                    file_position=my_pos_cube, log_filename=.FALSE., &
     453            0 :                                                    mpi_io=mpi_io, fout=mpi_filename)
     454            0 :                   IF (output_unit > 0) THEN
     455            0 :                      IF (.NOT. mpi_io) THEN
     456            0 :                         INQUIRE (UNIT=cube_unit, NAME=filename)
     457              :                      ELSE
     458            0 :                         filename = mpi_filename
     459              :                      END IF
     460              :                      WRITE (UNIT=output_unit, FMT="(T3,A)") &
     461            0 :                         "SCCS| The norm of the density gradient is written in cube file format to the file:", &
     462            0 :                         "SCCS| "//TRIM(filename)
     463              :                   END IF
     464              :                   CALL cp_pw_to_cube(norm_drho_elec, cube_unit, TRIM(filename), particles=particles, &
     465              :                                      stride=section_get_ivals(input, TRIM(cube_path)//"%STRIDE"), &
     466            0 :                                      mpi_io=mpi_io)
     467            0 :                   CALL cp_print_key_finished_output(cube_unit, logger, input, TRIM(cube_path), mpi_io=mpi_io)
     468              :                END IF
     469              : 
     470              :                ! Calculate the (quantum) surface of the solute cavity
     471          340 :                SELECT CASE (sccs_control%method_id)
     472              :                CASE (sccs_andreussi)
     473              :                   CALL surface_andreussi(rho_elec, norm_drho_elec, theta, epsilon_solvent, &
     474              :                                          sccs_control%rho_max, sccs_control%rho_min, &
     475          148 :                                          sccs_control%delta_rho)
     476              :                CASE (sccs_fattebert_gygi)
     477              :                   CALL surface_fattebert_gygi(rho_elec, norm_drho_elec, theta, epsilon_solvent, &
     478              :                                               sccs_control%beta, sccs_control%rho_zero, &
     479           44 :                                               sccs_control%delta_rho)
     480              :                CASE (sccs_saa_andreussi)
     481              :                CASE DEFAULT
     482          192 :                   CPABORT("Invalid method specified for SCCS model")
     483              :                END SELECT
     484          192 :                cavity_surface = pw_integrate_function(theta)
     485              : 
     486              :                ! Release storage
     487          192 :                CALL auxbas_pw_pool%give_back_pw(theta)
     488          192 :                CALL auxbas_pw_pool%give_back_pw(norm_drho_elec)
     489          960 :                DO i = 1, 3
     490          768 :                   CALL auxbas_pw_pool%give_back_pw(drho_elec(i))
     491              :                END DO
     492              :             END BLOCK
     493              : 
     494              :          END IF ! epsilon_solvent > 1
     495              : 
     496          192 :          CALL auxbas_pw_pool%give_back_pw(rho_elec)
     497              :       END BLOCK
     498              : 
     499              :       BLOCK
     500              :          TYPE(pw_r3d_rs_type) :: rho_tot, phi_tot, rho_solute, rho_tot_zero
     501              :          ! Retrieve the total charge density (core + elec) of the solute in r-space
     502          192 :          CALL auxbas_pw_pool%create_pw(rho_solute)
     503          192 :          CALL pw_zero(rho_solute)
     504          192 :          CALL pw_transfer(rho_tot_gspace, rho_solute)
     505          192 :          tot_rho_solute = pw_integrate_function(rho_solute)
     506              : 
     507              :          ! Check total charge
     508          192 :          IF (ABS(tot_rho_solute) >= 1.0E-6_dp) THEN
     509          170 :             IF ((poisson_env%parameters%solver /= pw_poisson_analytic) .AND. &
     510              :                 (poisson_env%parameters%solver /= pw_poisson_mt)) THEN
     511              :                WRITE (UNIT=message, FMT="(A,SP,F0.6,A)") &
     512          170 :                   "The system (solute) has a non-negligible charge of ", -tot_rho_solute, &
     513              :                   ". It is recommended to use non-periodic boundary conditions (PERIODIC none) "// &
     514          340 :                   "combined with an appropriate Poisson solver (POISSON_SOLVER MT or analytic)"
     515          170 :                CPWARN(message)
     516              :             END IF
     517              :          END IF
     518              : 
     519              :          ! Reassign work storage to rho_tot_zero, because rho_elec is no longer needed
     520          192 :          CALL auxbas_pw_pool%create_pw(rho_tot_zero)
     521              : 
     522          192 :          IF (sccs_control%method_id /= sccs_saa_andreussi) THEN
     523              : 
     524              :             ! Build the initial (rho_iter = 0) total charge density (solute plus polarisation) in r-space
     525              :             ! eps_elec <- ln(eps_elec)
     526              : !$OMP PARALLEL DO DEFAULT(NONE) &
     527              : !$OMP             PRIVATE(i,j,k) &
     528              : !$OMP             SHARED(eps_elec,lb,message,output_unit,para_env,ub) &
     529          192 : !$OMP             SHARED(rho_solute,rho_tot_zero)
     530              :             DO k = lb(3), ub(3)
     531              :                DO j = lb(2), ub(2)
     532              :                   DO i = lb(1), ub(1)
     533              :                      IF (eps_elec%array(i, j, k) < 1.0_dp) THEN
     534              :                         WRITE (UNIT=message, FMT="(A,ES12.3,A,3(I0,A))") &
     535              :                            "SCCS| Invalid dielectric function value ", eps_elec%array(i, j, k), &
     536              :                            " encountered at grid point (", i, ",", j, ",", k, ")"
     537              :                         CPABORT(message)
     538              :                      END IF
     539              :                      rho_tot_zero%array(i, j, k) = rho_solute%array(i, j, k)/eps_elec%array(i, j, k)
     540              :                      eps_elec%array(i, j, k) = LOG(eps_elec%array(i, j, k))
     541              :                   END DO
     542              :                END DO
     543              :             END DO
     544              : !$OMP END PARALLEL DO
     545              : 
     546              :          ELSE
     547              : 
     548            0 :             lxyz(:) = REAL(u%pw_grid%bounds(1, :), dp)
     549            0 :             uxyz(:) = REAL(u%pw_grid%bounds(2, :), dp)
     550              : !$OMP PARALLEL DO DEFAULT(NONE) &
     551              : !$OMP             PRIVATE(i,j,k,r) &
     552              : !$OMP             SHARED(lb,message,output_unit,para_env,ub,dtf,uxyz,lxyz) &
     553            0 : !$OMP             SHARED(u, alpha_zeta, R_solv, delta_zeta, eps_elec)
     554              :             DO k = lb(3), ub(3)
     555              :                DO j = lb(2), ub(2)
     556              :                   DO i = lb(1), ub(1)
     557              :                      IF (eps_elec%array(i, j, k) < 1.0_dp) THEN
     558              :                         WRITE (UNIT=message, FMT="(A,ES12.3,A,3(I0,A))") &
     559              :                            "SCCS| Invalid dielectric function value ", eps_elec%array(i, j, k), &
     560              :                            " encountered at grid point (", i, ",", j, ",", k, ")"
     561              :                         CPABORT(message)
     562              :                      END IF
     563              :                      IF (i > -1) r = ((REAL(uxyz(1), dp) - REAL(i, dp) + 0.5_dp)*u%pw_grid%dr(1))**2.0_dp
     564              :                      IF (i < 0) r = ((REAL(i, dp) - REAL(lxyz(1), dp) + 0.5_dp)*u%pw_grid%dr(1))**2.0_dp
     565              :                      IF (j > -1) r = ((REAL(uxyz(2), dp) - REAL(j, dp) + 0.5_dp)*u%pw_grid%dr(2))**2.0_dp + r
     566              :                      IF (j < 0) r = ((REAL(j, dp) - REAL(lxyz(2), dp) + 0.5_dp)*u%pw_grid%dr(2))**2.0_dp + r
     567              :                      IF (k > -1) r = ((REAL(uxyz(3), dp) - REAL(k, dp) + 0.5_dp)*u%pw_grid%dr(3))**2.0_dp + r
     568              :                      IF (k < 0) r = ((REAL(k, dp) - REAL(lxyz(3), dp) + 0.5_dp)*u%pw_grid%dr(3))**2.0_dp + r
     569              :                      r = SQRT(r)
     570              :                      u%array(i, j, k) = (1.0_dp/2.0_dp)*erfc((r - alpha_zeta*R_solv)/delta_zeta)
     571              :                      dtf%array(i, j, k) = 1.0_dp
     572              :                   END DO
     573              :                END DO
     574              :             END DO
     575              : !$OMP END PARALLEL DO
     576              : 
     577            0 :             CALL pw_func_u_convolution(poisson_env=poisson_env, func=dtf, convolution=ff, u=u)
     578            0 :             CALL pw_scale(u, 1.0_dp/ff%array(0, 0, 0))
     579            0 :             CALL pw_func_u_convolution(poisson_env=poisson_env, func=s, convolution=ff, u=u)
     580              : 
     581              : !$OMP PARALLEL DO DEFAULT(NONE) &
     582              : !$OMP             PRIVATE(i,j,k) &
     583              : !$OMP             SHARED(lb,para_env,ub, delta_eta, f0, epsilon_solvent) &
     584            0 : !$OMP             SHARED(ff, t, dtf, eps_elec, rho_tot_zero, rho_solute, s)
     585              :             DO k = lb(3), ub(3)
     586              :                DO j = lb(2), ub(2)
     587              :                   DO i = lb(1), ub(1)
     588              :                      t%array(i, j, k) = 0.5_dp*(1.0_dp + erf((ff%array(i, j, k) - f0)/delta_eta))
     589              :                      dtf%array(i, j, k) = oorootpi*EXP(-((ff%array(i, j, k) - f0)/delta_eta)**2)
     590              :                      eps_elec%array(i, j, k) = EXP(LOG(epsilon_solvent)*(1 - (s%array(i, j, k) &
     591              :                                                                               + (1 - s%array(i, j, k))*t%array(i, j, k))))
     592              :                      rho_tot_zero%array(i, j, k) = rho_solute%array(i, j, k)/eps_elec%array(i, j, k)
     593              : !                     eps_elec%array(i, j, k) = LOG(eps_elec%array(i, j, k))
     594              :                   END DO
     595              :                END DO
     596              :             END DO
     597              : !$OMP END PARALLEL DO
     598              : 
     599              :             ! Optional output of the dielectric function in cube file format (solvent aware algorithm case)
     600            0 :             filename = "DIELECTRIC_FUNCTION"
     601            0 :             cube_path = TRIM(print_path)//"%"//TRIM(filename)
     602            0 :             IF (BTEST(cp_print_key_should_output(logger%iter_info, input, TRIM(cube_path)), &
     603              :                       cp_p_file)) THEN
     604            0 :                append_cube = section_get_lval(input, TRIM(cube_path)//"%APPEND")
     605            0 :                my_pos_cube = "REWIND"
     606            0 :                IF (append_cube) my_pos_cube = "APPEND"
     607            0 :                mpi_io = .TRUE.
     608              :                cube_unit = cp_print_key_unit_nr(logger, input, TRIM(cube_path), &
     609              :                                                 extension=".cube", middle_name=TRIM(filename), &
     610              :                                                 file_position=my_pos_cube, log_filename=.FALSE., &
     611            0 :                                                 mpi_io=mpi_io, fout=mpi_filename)
     612            0 :                IF (output_unit > 0) THEN
     613            0 :                   IF (.NOT. mpi_io) THEN
     614            0 :                      INQUIRE (UNIT=cube_unit, NAME=filename)
     615              :                   ELSE
     616            0 :                      filename = mpi_filename
     617              :                   END IF
     618              :                   WRITE (UNIT=output_unit, FMT="(T3,A)") &
     619            0 :                      "SCCS| The dielectric function is written in cube file format to the file:", &
     620            0 :                      "SCCS| "//TRIM(filename)
     621              :                END IF
     622              :                CALL cp_pw_to_cube(eps_elec, cube_unit, TRIM(filename), particles=particles, &
     623              :                                   stride=section_get_ivals(input, TRIM(cube_path)//"%STRIDE"), &
     624            0 :                                   mpi_io=mpi_io)
     625            0 :                CALL cp_print_key_finished_output(cube_unit, logger, input, TRIM(cube_path), mpi_io=mpi_io)
     626              :             END IF
     627              : 
     628              : !$OMP PARALLEL DO DEFAULT(NONE) &
     629              : !$OMP             PRIVATE(i,j,k) &
     630              : !$OMP             SHARED(lb,para_env,ub, delta_eta, f0, epsilon_solvent) &
     631            0 : !$OMP             SHARED(ff, t, dtf, eps_elec, rho_tot_zero, rho_solute, s)
     632              :             DO k = lb(3), ub(3)
     633              :                DO j = lb(2), ub(2)
     634              :                   DO i = lb(1), ub(1)
     635              :                      eps_elec%array(i, j, k) = LOG(eps_elec%array(i, j, k))
     636              :                   END DO
     637              :                END DO
     638              :             END DO
     639              : !$OMP END PARALLEL DO
     640              : 
     641              :          END IF
     642              : 
     643              :          ! Build the derivative of LOG(eps_elec)
     644          768 :          DO i = 1, 3
     645          576 :             CALL auxbas_pw_pool%create_pw(dln_eps_elec(i))
     646          768 :             CALL pw_zero(dln_eps_elec(i))
     647              :          END DO
     648          192 :          CALL derive(eps_elec, dln_eps_elec, sccs_control%derivative_method, pw_env, input)
     649          192 :          IF (sccs_control%method_id /= sccs_saa_andreussi) THEN
     650          192 :             CALL auxbas_pw_pool%give_back_pw(eps_elec)
     651              :          END IF
     652              : 
     653              :          ! Print header for the SCCS cycle
     654          192 :          IF (should_output .AND. (output_unit > 0)) THEN
     655           85 :             IF (print_level > low_print_level) THEN
     656              :                WRITE (UNIT=output_unit, FMT="(T3,A,T56,F25.12)") &
     657           46 :                   "SCCS| Total electronic charge density ", -tot_rho_elec, &
     658           92 :                   "SCCS| Total charge density (solute)   ", -tot_rho_solute
     659              :                WRITE (UNIT=output_unit, FMT="(T3,A,T56,F25.3)") &
     660           46 :                   "SCCS| Volume of the cell           [bohr^3]", cell_volume, &
     661           46 :                   "SCCS|                              [angstrom^3]", &
     662           92 :                   cp_unit_from_cp2k(cell_volume, "angstrom^3")
     663           46 :                IF (ABS(epsilon_solvent - 1.0_dp) > epstol) THEN
     664              :                   WRITE (UNIT=output_unit, FMT="(T3,A,T56,F25.3)") &
     665           46 :                      "SCCS| Volume of the solute cavity  [bohr^3]", cavity_volume, &
     666           46 :                      "SCCS|                              [angstrom^3]", &
     667           46 :                      cp_unit_from_cp2k(cavity_volume, "angstrom^3"), &
     668           46 :                      "SCCS| Surface of the solute cavity [bohr^2]", cavity_surface, &
     669           46 :                      "SCCS|                              [angstrom^2]", &
     670           92 :                      cp_unit_from_cp2k(cavity_surface, "angstrom^2")
     671              :                END IF
     672              :                WRITE (UNIT=output_unit, FMT="(T3,A)") &
     673           46 :                   "SCCS|", &
     674           92 :                   "SCCS|   Step    Average residual    Maximum residual         E(Hartree) [a.u.]"
     675              :             END IF
     676              :          END IF
     677              : 
     678              :          ! Get storage for the derivative of the total potential (field) in r-space
     679          768 :          DO i = 1, 3
     680          768 :             CALL auxbas_pw_pool%create_pw(dphi_tot(i))
     681              :          END DO
     682              : 
     683              :          ! Initialise the total charge density in r-space rho_tot with rho_tot_zero + rho_iter_zero
     684          192 :          CALL auxbas_pw_pool%create_pw(rho_tot)
     685          192 :          CALL pw_copy(rho_tot_zero, rho_tot)
     686          192 :          CALL pw_axpy(rho_pw_r_sccs, rho_tot)
     687              : 
     688          192 :          CALL auxbas_pw_pool%create_pw(phi_tot)
     689          192 :          CALL pw_zero(phi_tot)
     690              : 
     691          192 :          IF (sccs_control%method_id == sccs_saa_andreussi) THEN
     692            0 :             CALL auxbas_pw_pool%create_pw(p_e_interface)
     693            0 :             CALL pw_zero(p_e_interface)
     694              :          END IF
     695              : 
     696              :          ! Main SCCS iteration loop
     697          192 :          iter = 0
     698              : 
     699              :          iter_loop: DO
     700              : 
     701              :             ! Increment iteration counter
     702         1588 :             iter = iter + 1
     703              : 
     704              :             ! Check if the requested maximum number of SCCS iterations is reached
     705         1588 :             IF (iter > sccs_control%max_iter) THEN
     706            0 :                IF (output_unit > 0) THEN
     707              :                   WRITE (UNIT=output_unit, FMT="(T3,A,/,T3,A,I0,A)") &
     708            0 :                      "SCCS| Maximum number of SCCS iterations reached", &
     709            0 :                      "SCCS| Iteration cycle did not converge in ", sccs_control%max_iter, " steps"
     710              :                ELSE
     711              :                   WRITE (UNIT=message, FMT="(A,I0,A)") &
     712            0 :                      "The SCCS iteration cycle did not converge in ", sccs_control%max_iter, " steps"
     713            0 :                   CPWARN(message)
     714              :                END IF
     715              :                EXIT iter_loop
     716              :             END IF
     717              : 
     718              :             ! Calculate derivative of the current total potential in r-space
     719              :             CALL pw_poisson_solve(poisson_env=poisson_env, &
     720              :                                   density=rho_tot, &
     721              :                                   vhartree=phi_tot, &
     722         1588 :                                   dvhartree=dphi_tot)
     723         1588 :             energy%sccs_hartree = 0.5_dp*pw_integral_ab(rho_solute, phi_tot)
     724              : 
     725              :             ! Update total charge density (solute plus polarisation) in r-space
     726              :             ! based on the iterated polarisation charge density
     727         1588 :             f = 1.0_dp/fourpi
     728         1588 :             rho_delta_avg = 0.0_dp
     729         1588 :             rho_delta_max = 0.0_dp
     730              : !$OMP    PARALLEL DO DEFAULT(NONE) &
     731              : !$OMP                PRIVATE(i,j,k,rho_delta,rho_iter_new) &
     732              : !$OMP                SHARED(dln_eps_elec,dphi_tot,f,lb,rho_pw_r_sccs,ub) &
     733              : !$OMP                SHARED(rho_tot,rho_tot_zero,sccs_control) &
     734              : !$OMP                REDUCTION(+:rho_delta_avg) &
     735         1588 : !$OMP                REDUCTION(MAX:rho_delta_max)
     736              :             DO k = lb(3), ub(3)
     737              :                DO j = lb(2), ub(2)
     738              :                   DO i = lb(1), ub(1)
     739              :                      rho_iter_new = (dln_eps_elec(1)%array(i, j, k)*dphi_tot(1)%array(i, j, k) + &
     740              :                                      dln_eps_elec(2)%array(i, j, k)*dphi_tot(2)%array(i, j, k) + &
     741              :                                      dln_eps_elec(3)%array(i, j, k)*dphi_tot(3)%array(i, j, k))*f
     742              :                      rho_iter_new = rho_pw_r_sccs%array(i, j, k) + &
     743              :                                     sccs_control%mixing*(rho_iter_new - rho_pw_r_sccs%array(i, j, k))
     744              :                      rho_delta = ABS(rho_iter_new - rho_pw_r_sccs%array(i, j, k))
     745              :                      rho_delta_max = MAX(rho_delta, rho_delta_max)
     746              :                      rho_delta_avg = rho_delta_avg + rho_delta
     747              :                      rho_tot%array(i, j, k) = rho_tot_zero%array(i, j, k) + rho_iter_new
     748              :                      rho_pw_r_sccs%array(i, j, k) = rho_iter_new
     749              :                   END DO
     750              :                END DO
     751              :             END DO
     752              : !$OMP    END PARALLEL DO
     753              : 
     754         1588 :             CALL para_env%sum(rho_delta_avg)
     755         1588 :             rho_delta_avg = rho_delta_avg/REAL(ngpts, KIND=dp)
     756         1588 :             CALL para_env%max(rho_delta_max)
     757              : 
     758         1588 :             IF (should_output .AND. (output_unit > 0)) THEN
     759          608 :                IF (print_level > low_print_level) THEN
     760          147 :                   IF ((ABS(rho_delta_avg) < 1.0E-8_dp) .OR. &
     761          147 :                       (ABS(rho_delta_avg) >= 1.0E5_dp)) THEN
     762              :                      WRITE (UNIT=output_unit, FMT="(T3,A,I6,4X,ES16.4,4X,ES16.4,1X,F25.12)") &
     763            0 :                         "SCCS| ", iter, rho_delta_avg, rho_delta_max, energy%sccs_hartree
     764              :                   ELSE
     765              :                      WRITE (UNIT=output_unit, FMT="(T3,A,I6,4X,F16.8,4X,F16.8,1X,F25.12)") &
     766          147 :                         "SCCS| ", iter, rho_delta_avg, rho_delta_max, energy%sccs_hartree
     767              :                   END IF
     768              :                END IF
     769              :             END IF
     770              : 
     771              :             ! Check if the SCCS iteration cycle is converged to the requested tolerance
     772         1588 :             IF (rho_delta_max <= sccs_control%eps_sccs) THEN
     773          192 :                IF (should_output .AND. (output_unit > 0)) THEN
     774              :                   WRITE (UNIT=output_unit, FMT="(T3,A,I0,A)") &
     775           85 :                      "SCCS| Iteration cycle converged in ", iter, " steps"
     776              :                END IF
     777              :                EXIT iter_loop
     778              :             END IF
     779              : 
     780              :          END DO iter_loop
     781              : 
     782          192 :          IF (sccs_control%method_id == sccs_saa_andreussi) THEN
     783            0 :             CALL auxbas_pw_pool%create_pw(tem_convolution)
     784            0 :             CALL auxbas_pw_pool%create_pw(tem_func)
     785              : 
     786              : !$OMP PARALLEL DO DEFAULT(NONE) &
     787              : !$OMP                PRIVATE(i,j,k,dphi2) &
     788              : !$OMP                SHARED(lb,ub, tem_func, s, dtf) &
     789            0 : !$OMP                SHARED(dphi_tot, p_e_interface, eps_elec, epsilon_solvent)
     790              :             DO k = lb(3), ub(3)
     791              :                DO j = lb(2), ub(2)
     792              :                   DO i = lb(1), ub(1)
     793              :                      p_e_interface%array(i, j, k) = 1.0_dp/(4.0_dp*twopi)*(EXP(eps_elec%array(i, j, k))*LOG(epsilon_solvent))
     794              :                      dphi2 = dphi_tot(1)%array(i, j, k)*dphi_tot(1)%array(i, j, k) + &
     795              :                              dphi_tot(2)%array(i, j, k)*dphi_tot(2)%array(i, j, k) + &
     796              :                              dphi_tot(3)%array(i, j, k)*dphi_tot(3)%array(i, j, k)
     797              :                      p_e_interface%array(i, j, k) = p_e_interface%array(i, j, k)*dphi2
     798              :                      tem_func%array(i, j, k) = (1.0_dp - s%array(i, j, k))*p_e_interface%array(i, j, k)*dtf%array(i, j, k)
     799              :                   END DO
     800              :                END DO
     801              :             END DO
     802              : !$OMP END PARALLEL DO
     803              : 
     804            0 :             CALL pw_func_u_convolution(poisson_env=poisson_env, func=tem_func, convolution=tem_convolution, u=u)
     805              : 
     806              : !$OMP PARALLEL DO DEFAULT(NONE) &
     807              : !$OMP                PRIVATE(i,j,k) &
     808              : !$OMP                SHARED(lb,ub) &
     809            0 : !$OMP                SHARED(p_e_interface, t, tem_convolution, phi_tot, d_s_rhoel)
     810              :             DO k = lb(3), ub(3)
     811              :                DO j = lb(2), ub(2)
     812              :                   DO i = lb(1), ub(1)
     813              :                      p_e_interface%array(i, j, k) = p_e_interface%array(i, j, k)*(1.0_dp - t%array(i, j, k)) &
     814              :                                                     + tem_convolution%array(i, j, k)
     815              :                   END DO
     816              :                END DO
     817              :             END DO
     818              : !$OMP END PARALLEL DO
     819              : 
     820              :          END IF
     821              : 
     822              :          ! Release work storage which is no longer needed
     823          192 :          CALL auxbas_pw_pool%give_back_pw(rho_tot_zero)
     824          768 :          DO i = 1, 3
     825          768 :             CALL auxbas_pw_pool%give_back_pw(dln_eps_elec(i))
     826              :          END DO
     827              : 
     828              :          ! Optional output of the total charge density in cube file format
     829          192 :          filename = "TOTAL_CHARGE_DENSITY"
     830          192 :          cube_path = TRIM(print_path)//"%"//TRIM(filename)
     831          192 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, input, TRIM(cube_path)), cp_p_file)) THEN
     832            0 :             append_cube = section_get_lval(input, TRIM(cube_path)//"%APPEND")
     833            0 :             my_pos_cube = "REWIND"
     834            0 :             IF (append_cube) my_pos_cube = "APPEND"
     835            0 :             mpi_io = .TRUE.
     836              :             cube_unit = cp_print_key_unit_nr(logger, input, TRIM(cube_path), &
     837              :                                              extension=".cube", middle_name=TRIM(filename), &
     838              :                                              file_position=my_pos_cube, log_filename=.FALSE., &
     839            0 :                                              mpi_io=mpi_io, fout=mpi_filename)
     840            0 :             IF (output_unit > 0) THEN
     841            0 :                IF (.NOT. mpi_io) THEN
     842            0 :                   INQUIRE (UNIT=cube_unit, NAME=filename)
     843              :                ELSE
     844            0 :                   filename = mpi_filename
     845              :                END IF
     846              :                WRITE (UNIT=output_unit, FMT="(T3,A)") &
     847            0 :                   "SCCS| The total SCCS charge density is written in cube file format to the file:", &
     848            0 :                   "SCCS| "//TRIM(filename)
     849              :             END IF
     850              :             CALL cp_pw_to_cube(rho_tot, cube_unit, TRIM(filename), particles=particles, &
     851            0 :                                stride=section_get_ivals(input, TRIM(cube_path)//"%STRIDE"), mpi_io=mpi_io)
     852            0 :             CALL cp_print_key_finished_output(cube_unit, logger, input, TRIM(cube_path), mpi_io=mpi_io)
     853              :          END IF
     854              : 
     855              :          ! Calculate the total SCCS Hartree energy, potential, and its
     856              :          ! derivatives of the solute and the implicit solvent
     857          192 :          CALL pw_transfer(rho_tot, rho_tot_gspace)
     858          192 :          IF (calculate_stress_tensor) THEN
     859              :             ! Request also the calculation of the stress tensor contribution
     860              :             CALL pw_poisson_solve(poisson_env=poisson_env, &
     861              :                                   density=rho_tot_gspace, &
     862              :                                   ehartree=e_tot, &
     863              :                                   vhartree=v_hartree_gspace, &
     864              :                                   dvhartree=dphi_tot, &
     865            0 :                                   h_stress=h_stress)
     866              :          ELSE
     867              :             CALL pw_poisson_solve(poisson_env=poisson_env, &
     868              :                                   density=rho_tot_gspace, &
     869              :                                   ehartree=e_tot, &
     870              :                                   vhartree=v_hartree_gspace, &
     871          192 :                                   dvhartree=dphi_tot)
     872              :          END IF
     873          192 :          CALL pw_transfer(v_hartree_gspace, phi_tot)
     874          192 :          energy%sccs_hartree = 0.5_dp*pw_integral_ab(rho_solute, phi_tot)
     875              : 
     876              :          ! Calculate the Hartree energy and potential of the solute only
     877              :          BLOCK
     878              :             TYPE(pw_r3d_rs_type) :: phi_solute
     879          192 :             CALL auxbas_pw_pool%create_pw(phi_solute)
     880          192 :             CALL pw_zero(phi_solute)
     881              :             CALL pw_poisson_solve(poisson_env=poisson_env, &
     882              :                                   density=rho_solute, &
     883              :                                   ehartree=energy%hartree, &
     884          192 :                                   vhartree=phi_solute)
     885              : 
     886              :             ! Calculate the polarisation potential (store it in phi_tot)
     887              :             ! phi_pol = phi_tot - phi_solute
     888          192 :             CALL pw_axpy(phi_solute, phi_tot, alpha=-1.0_dp)
     889          192 :             CALL auxbas_pw_pool%give_back_pw(phi_solute)
     890              :          END BLOCK
     891              : 
     892              :          ! Optional output of the SCCS polarisation potential in cube file format
     893          192 :          filename = "POLARISATION_POTENTIAL"
     894          192 :          cube_path = TRIM(print_path)//"%"//TRIM(filename)
     895          192 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, input, TRIM(cube_path)), &
     896              :                    cp_p_file)) THEN
     897            4 :             append_cube = section_get_lval(input, TRIM(cube_path)//"%APPEND")
     898            4 :             my_pos_cube = "REWIND"
     899            4 :             IF (append_cube) my_pos_cube = "APPEND"
     900            4 :             mpi_io = .TRUE.
     901              :             cube_unit = cp_print_key_unit_nr(logger, input, TRIM(cube_path), &
     902              :                                              extension=".cube", middle_name=TRIM(filename), &
     903              :                                              file_position=my_pos_cube, log_filename=.FALSE., &
     904            4 :                                              mpi_io=mpi_io, fout=mpi_filename)
     905            4 :             IF (output_unit > 0) THEN
     906            2 :                IF (.NOT. mpi_io) THEN
     907            0 :                   INQUIRE (UNIT=cube_unit, NAME=filename)
     908              :                ELSE
     909            2 :                   filename = mpi_filename
     910              :                END IF
     911              :                WRITE (UNIT=output_unit, FMT="(T3,A)") &
     912            2 :                   "SCCS| The SCCS polarisation potential is written in cube file format to the file:", &
     913            4 :                   "SCCS| "//TRIM(filename)
     914              :             END IF
     915              :             CALL cp_pw_to_cube(phi_tot, cube_unit, TRIM(filename), particles=particles, &
     916            4 :                                stride=section_get_ivals(input, TRIM(cube_path)//"%STRIDE"), mpi_io=mpi_io)
     917            4 :             CALL cp_print_key_finished_output(cube_unit, logger, input, TRIM(cube_path), mpi_io=mpi_io)
     918              :          END IF
     919              : 
     920              :          ! Calculate the polarisation charge (store it in rho_tot)
     921              :          ! rho_pol = rho_tot - rho_solute
     922          192 :          CALL pw_axpy(rho_solute, rho_tot, alpha=-1.0_dp)
     923          192 :          polarisation_charge = pw_integrate_function(rho_tot)
     924              : 
     925              :          ! Optional output of the SCCS polarisation charge in cube file format
     926          192 :          filename = "POLARISATION_CHARGE_DENSITY"
     927          192 :          cube_path = TRIM(print_path)//"%"//TRIM(filename)
     928          192 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, input, TRIM(cube_path)), &
     929              :                    cp_p_file)) THEN
     930            0 :             append_cube = section_get_lval(input, TRIM(cube_path)//"%APPEND")
     931            0 :             my_pos_cube = "REWIND"
     932            0 :             IF (append_cube) my_pos_cube = "APPEND"
     933            0 :             mpi_io = .TRUE.
     934              :             cube_unit = cp_print_key_unit_nr(logger, input, TRIM(cube_path), &
     935              :                                              extension=".cube", middle_name=TRIM(filename), &
     936              :                                              file_position=my_pos_cube, log_filename=.FALSE., &
     937            0 :                                              mpi_io=mpi_io, fout=mpi_filename)
     938            0 :             IF (output_unit > 0) THEN
     939            0 :                IF (.NOT. mpi_io) THEN
     940            0 :                   INQUIRE (UNIT=cube_unit, NAME=filename)
     941              :                ELSE
     942            0 :                   filename = mpi_filename
     943              :                END IF
     944              :                WRITE (UNIT=output_unit, FMT="(T3,A)") &
     945            0 :                   "SCCS| The SCCS polarisation charge density is written in cube file format to the file:", &
     946            0 :                   "SCCS| "//TRIM(filename)
     947              :             END IF
     948              :             CALL cp_pw_to_cube(rho_tot, cube_unit, TRIM(filename), particles=particles, &
     949            0 :                                stride=section_get_ivals(input, TRIM(cube_path)//"%STRIDE"), mpi_io=mpi_io)
     950            0 :             CALL cp_print_key_finished_output(cube_unit, logger, input, TRIM(cube_path), mpi_io=mpi_io)
     951              :          END IF
     952              : 
     953              :          ! Calculate SCCS polarisation energy
     954          192 :          energy%sccs_pol = 0.5_dp*pw_integral_ab(rho_solute, phi_tot)
     955          192 :          CALL auxbas_pw_pool%give_back_pw(rho_solute)
     956          192 :          CALL auxbas_pw_pool%give_back_pw(phi_tot)
     957          192 :          CALL auxbas_pw_pool%give_back_pw(rho_tot)
     958          384 :          IF (sccs_control%method_id == sccs_saa_andreussi) THEN
     959            0 :             CALL auxbas_pw_pool%give_back_pw(s)
     960            0 :             CALL auxbas_pw_pool%give_back_pw(u)
     961            0 :             CALL auxbas_pw_pool%give_back_pw(ff)
     962            0 :             CALL auxbas_pw_pool%give_back_pw(t)
     963            0 :             CALL auxbas_pw_pool%give_back_pw(dtf)
     964            0 :             CALL auxbas_pw_pool%give_back_pw(tem_convolution)
     965            0 :             CALL auxbas_pw_pool%give_back_pw(tem_func)
     966            0 :             CALL auxbas_pw_pool%give_back_pw(eps_elec)
     967              :          END IF
     968              :       END BLOCK
     969              : 
     970              :       ! Calculate additional solvation terms
     971          192 :       energy%sccs_cav = sccs_control%gamma_solvent*cavity_surface
     972          192 :       energy%sccs_dis = sccs_control%beta_solvent*cavity_volume
     973          192 :       energy%sccs_rep = sccs_control%alpha_solvent*cavity_surface
     974              :       ! Calculate solvation free energy: \delta G^el + (alpha + gamma)*S + beta*V
     975          192 :       energy%sccs_sol = energy%sccs_pol + energy%sccs_rep + energy%sccs_cav + energy%sccs_dis
     976              : 
     977          192 :       IF (should_output .AND. (output_unit > 0)) THEN
     978              :          WRITE (UNIT=output_unit, FMT="(T3,A)") &
     979           85 :             "SCCS|"
     980              :          WRITE (UNIT=output_unit, FMT="(T3,A,T56,F25.12)") &
     981           85 :             "SCCS| Polarisation charge", polarisation_charge
     982              :          !MK   "SCCS| Total interaction energy [a.u.]", e_tot
     983              :          WRITE (UNIT=output_unit, FMT="(T3,A)") &
     984           85 :             "SCCS|"
     985           85 :          CALL print_sccs_results(energy, sccs_control, output_unit)
     986              :       END IF
     987              : 
     988              :       ! Calculate SCCS contribution to the Kohn-Sham potential
     989          192 :       IF (sccs_control%method_id /= sccs_saa_andreussi) THEN
     990              : 
     991          192 :          f = -0.5_dp*dvol/fourpi
     992              : !$OMP PARALLEL DO DEFAULT(NONE) &
     993              : !$OMP             PRIVATE(dphi2,i,j,k) &
     994              : !$OMP             SHARED(f,deps_elec,dphi_tot) &
     995          192 : !$OMP             SHARED(lb,ub,v_sccs)
     996              :          DO k = lb(3), ub(3)
     997              :             DO j = lb(2), ub(2)
     998              :                DO i = lb(1), ub(1)
     999              :                   dphi2 = dphi_tot(1)%array(i, j, k)*dphi_tot(1)%array(i, j, k) + &
    1000              :                           dphi_tot(2)%array(i, j, k)*dphi_tot(2)%array(i, j, k) + &
    1001              :                           dphi_tot(3)%array(i, j, k)*dphi_tot(3)%array(i, j, k)
    1002              :                   v_sccs%array(i, j, k) = v_sccs%array(i, j, k) + f*deps_elec%array(i, j, k)*dphi2
    1003              :                END DO
    1004              :             END DO
    1005              :          END DO
    1006              : !$OMP END PARALLEL DO
    1007              : 
    1008              :       ELSE
    1009              : 
    1010              : !$OMP PARALLEL DO DEFAULT(NONE) &
    1011              : !$OMP                PRIVATE(i,j,k) &
    1012              : !$OMP                SHARED(lb,ub, dvol) &
    1013            0 : !$OMP                SHARED(p_E_interface, v_sccs, d_s_rhoel)
    1014              :          DO k = lb(3), ub(3)
    1015              :             DO j = lb(2), ub(2)
    1016              :                DO i = lb(1), ub(1)
    1017              :                   v_sccs%array(i, j, k) = dvol*d_s_rhoel%array(i, j, k)*p_E_interface%array(i, j, k)
    1018              :                END DO
    1019              :             END DO
    1020              :          END DO
    1021              : !$OMP END PARALLEL DO
    1022              : 
    1023            0 :          CALL auxbas_pw_pool%give_back_pw(d_s_rhoel)
    1024            0 :          CALL auxbas_pw_pool%give_back_pw(p_E_interface)
    1025              : 
    1026              :       END IF
    1027              : 
    1028          192 :       CALL auxbas_pw_pool%give_back_pw(deps_elec)
    1029          768 :       DO i = 1, 3
    1030          768 :          CALL auxbas_pw_pool%give_back_pw(dphi_tot(i))
    1031              :       END DO
    1032              : 
    1033              :       ! Release the SCCS printout environment
    1034              :       CALL cp_print_key_finished_output(output_unit, logger, input, TRIM(print_path), &
    1035          192 :                                         ignore_should_output=should_output)
    1036              : 
    1037          192 :       CALL timestop(handle)
    1038              : 
    1039          524 :    END SUBROUTINE sccs
    1040              : 
    1041              : ! **************************************************************************************************
    1042              : !> \brief      Calculate the smoothed dielectric function of Andreussi et al.
    1043              : !> \param rho_elec ...
    1044              : !> \param eps_elec ...
    1045              : !> \param deps_elec ...
    1046              : !> \param epsilon_solvent ...
    1047              : !> \param rho_max ...
    1048              : !> \param rho_min ...
    1049              : !> \par History:
    1050              : !>      - Creation (16.10.2013,MK)
    1051              : !>      - Finite difference of isosurfaces implemented (21.12.2013,MK)
    1052              : !> \author     Matthias Krack (MK)
    1053              : !> \version    1.1
    1054              : ! **************************************************************************************************
    1055          148 :    SUBROUTINE andreussi(rho_elec, eps_elec, deps_elec, epsilon_solvent, rho_max, &
    1056              :                         rho_min)
    1057              : 
    1058              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: rho_elec, eps_elec, deps_elec
    1059              :       REAL(KIND=dp), INTENT(IN)                          :: epsilon_solvent, rho_max, rho_min
    1060              : 
    1061              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'andreussi'
    1062              :       REAL(KIND=dp), PARAMETER                           :: rhotol = 1.0E-12_dp
    1063              : 
    1064              :       INTEGER                                            :: handle, i, j, k
    1065              :       INTEGER, DIMENSION(3)                              :: lb, ub
    1066              :       REAL(KIND=dp)                                      :: diff, dq, dt, f, ln_rho_max, ln_rho_min, &
    1067              :                                                             q, rho, t, x, y
    1068              : 
    1069          148 :       CALL timeset(routineN, handle)
    1070              : 
    1071          148 :       f = LOG(epsilon_solvent)/twopi
    1072          148 :       diff = rho_max - rho_min
    1073          148 :       IF (diff < SQRT(rhotol)) CPABORT("SCCS: Difference between rho(min) and rho(max) is too small")
    1074          148 :       IF (rho_min >= rhotol) THEN
    1075          148 :          ln_rho_max = LOG(rho_max)
    1076          148 :          ln_rho_min = LOG(rho_min)
    1077          148 :          q = twopi/(ln_rho_max - ln_rho_min)
    1078          148 :          dq = -f*q
    1079              :       END IF
    1080              : 
    1081          592 :       lb(1:3) = rho_elec%pw_grid%bounds_local(1, 1:3)
    1082          592 :       ub(1:3) = rho_elec%pw_grid%bounds_local(2, 1:3)
    1083              : 
    1084              :       ! Calculate the dielectric function and its derivative
    1085              : !$OMP PARALLEL DO DEFAULT(NONE) &
    1086              : !$OMP             PRIVATE(dt,i,j,k,rho,t,x,y) &
    1087              : !$OMP             SHARED(deps_elec,dq,eps_elec,epsilon_solvent,f,lb,ub) &
    1088          148 : !$OMP             SHARED(ln_rho_max,rho_elec,q,rho_max,rho_min)
    1089              :       DO k = lb(3), ub(3)
    1090              :          DO j = lb(2), ub(2)
    1091              :             DO i = lb(1), ub(1)
    1092              :                rho = rho_elec%array(i, j, k)
    1093              :                IF (rho < rho_min) THEN
    1094              :                   eps_elec%array(i, j, k) = epsilon_solvent
    1095              :                   deps_elec%array(i, j, k) = 0.0_dp
    1096              :                ELSE IF (rho <= rho_max) THEN
    1097              :                   x = LOG(rho)
    1098              :                   y = q*(ln_rho_max - x)
    1099              :                   t = f*(y - SIN(y))
    1100              :                   eps_elec%array(i, j, k) = EXP(t)
    1101              :                   dt = dq*(1.0_dp - COS(y))
    1102              :                   deps_elec%array(i, j, k) = eps_elec%array(i, j, k)*dt/rho
    1103              :                ELSE
    1104              :                   eps_elec%array(i, j, k) = 1.0_dp
    1105              :                   deps_elec%array(i, j, k) = 0.0_dp
    1106              :                END IF
    1107              :             END DO
    1108              :          END DO
    1109              :       END DO
    1110              : !$OMP END PARALLEL DO
    1111              : 
    1112          148 :       CALL timestop(handle)
    1113              : 
    1114          148 :    END SUBROUTINE andreussi
    1115              : 
    1116              : ! **************************************************************************************************
    1117              : !> \brief      Calculate the smoothed dielectric function of Fattebert and Gygi
    1118              : !> \param rho_elec ...
    1119              : !> \param eps_elec ...
    1120              : !> \param deps_elec ...
    1121              : !> \param epsilon_solvent ...
    1122              : !> \param beta ...
    1123              : !> \param rho_zero ...
    1124              : !> \par History:
    1125              : !>      - Creation (15.10.2013,MK)
    1126              : !> \author     Matthias Krack (MK)
    1127              : !> \version    1.0
    1128              : ! **************************************************************************************************
    1129           44 :    SUBROUTINE fattebert_gygi(rho_elec, eps_elec, deps_elec, epsilon_solvent, beta, &
    1130              :                              rho_zero)
    1131              : 
    1132              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: rho_elec, eps_elec, deps_elec
    1133              :       REAL(KIND=dp), INTENT(IN)                          :: epsilon_solvent, beta, rho_zero
    1134              : 
    1135              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'fattebert_gygi'
    1136              :       REAL(KIND=dp), PARAMETER                           :: rhotol = 1.0E-12_dp
    1137              : 
    1138              :       INTEGER                                            :: handle, i, j, k
    1139              :       INTEGER, DIMENSION(3)                              :: lb, ub
    1140              :       REAL(KIND=dp)                                      :: df, f, p, q, rho, s, t, twobeta
    1141              : 
    1142           44 :       CALL timeset(routineN, handle)
    1143              : 
    1144           44 :       df = (1.0_dp - epsilon_solvent)/rho_zero
    1145           44 :       f = 0.5_dp*(epsilon_solvent - 1.0_dp)
    1146           44 :       q = 1.0_dp/rho_zero
    1147           44 :       twobeta = 2.0_dp*beta
    1148              : 
    1149          176 :       lb(1:3) = rho_elec%pw_grid%bounds_local(1, 1:3)
    1150          176 :       ub(1:3) = rho_elec%pw_grid%bounds_local(2, 1:3)
    1151              : 
    1152              :       ! Calculate the smoothed dielectric function and its derivative
    1153              : !$OMP PARALLEL DO DEFAULT(NONE) &
    1154              : !$OMP             PRIVATE(i,j,k,p,rho,s,t) &
    1155              : !$OMP             SHARED(df,deps_elec,eps_elec,epsilon_solvent,f,lb,ub) &
    1156           44 : !$OMP             SHARED(q,rho_elec,twobeta)
    1157              :       DO k = lb(3), ub(3)
    1158              :          DO j = lb(2), ub(2)
    1159              :             DO i = lb(1), ub(1)
    1160              :                rho = rho_elec%array(i, j, k)
    1161              :                IF (rho < rhotol) THEN
    1162              :                   eps_elec%array(i, j, k) = epsilon_solvent
    1163              :                   deps_elec%array(i, j, k) = 0.0_dp
    1164              :                ELSE
    1165              :                   s = rho*q
    1166              :                   p = s**twobeta
    1167              :                   t = 1.0_dp/(1.0_dp + p)
    1168              :                   eps_elec%array(i, j, k) = 1.0_dp + f*(1.0_dp + (1.0_dp - p)*t)
    1169              :                   deps_elec%array(i, j, k) = df*twobeta*t*t*p/s
    1170              :                END IF
    1171              :             END DO
    1172              :          END DO
    1173              :       END DO
    1174              : !$OMP END PARALLEL DO
    1175              : 
    1176           44 :       CALL timestop(handle)
    1177              : 
    1178           44 :    END SUBROUTINE fattebert_gygi
    1179              : 
    1180              : ! **************************************************************************************************
    1181              : !> \brief      Calculate the smoothed dielectric function of solvent aware algorithm
    1182              : !> \param rho_elec ...
    1183              : !> \param eps_elec ...
    1184              : !> \param deps_elec ...
    1185              : !> \param epsilon_solvent ...
    1186              : !> \param rho_max ...
    1187              : !> \param rho_min ...
    1188              : !> \param s ...
    1189              : !> \param d_s_rhoel ...
    1190              : !> \author     Ziwei Chai
    1191              : !> \version    1.0
    1192              : ! **************************************************************************************************
    1193            0 :    SUBROUTINE sa_andreussi(rho_elec, eps_elec, deps_elec, epsilon_solvent, rho_max, &
    1194              :                            rho_min, s, d_s_rhoel)
    1195              : 
    1196              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: rho_elec, eps_elec, deps_elec
    1197              :       REAL(KIND=dp), INTENT(IN)                          :: epsilon_solvent, rho_max, rho_min
    1198              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: s, d_s_rhoel
    1199              : 
    1200              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'sa_andreussi'
    1201              :       REAL(KIND=dp), PARAMETER                           :: rhotol = 1.0E-12_dp
    1202              : 
    1203              :       INTEGER                                            :: handle, i, j, k
    1204              :       INTEGER, DIMENSION(3)                              :: lb, ub
    1205              :       REAL(KIND=dp)                                      :: diff, dq, dt, f, ln_rho_max, ln_rho_min, &
    1206              :                                                             q, rho, t, x, y
    1207              : 
    1208            0 :       CALL timeset(routineN, handle)
    1209              : 
    1210            0 :       f = LOG(epsilon_solvent)/twopi
    1211            0 :       diff = rho_max - rho_min
    1212            0 :       IF (diff < SQRT(rhotol)) CPABORT("SCCS: Difference between rho(min) and rho(max) is too small")
    1213            0 :       IF (rho_min >= rhotol) THEN
    1214            0 :          ln_rho_max = LOG(rho_max)
    1215            0 :          ln_rho_min = LOG(rho_min)
    1216            0 :          q = twopi/(ln_rho_max - ln_rho_min)
    1217            0 :          dq = -f*q
    1218              :       END IF
    1219              : 
    1220            0 :       lb(1:3) = rho_elec%pw_grid%bounds_local(1, 1:3)
    1221            0 :       ub(1:3) = rho_elec%pw_grid%bounds_local(2, 1:3)
    1222              : 
    1223              :       ! Calculate the dielectric function and its derivative
    1224              : !$OMP PARALLEL DO DEFAULT(NONE) &
    1225              : !$OMP             PRIVATE(dt,i,j,k,rho,t,x,y) &
    1226              : !$OMP             SHARED(deps_elec,dq,eps_elec,epsilon_solvent,f,lb,ub) &
    1227            0 : !$OMP             SHARED(ln_rho_max,rho_elec,q,rho_max,rho_min, s, d_s_rhoel)
    1228              :       DO k = lb(3), ub(3)
    1229              :          DO j = lb(2), ub(2)
    1230              :             DO i = lb(1), ub(1)
    1231              :                rho = rho_elec%array(i, j, k)
    1232              :                IF (rho < rho_min) THEN
    1233              :                   eps_elec%array(i, j, k) = epsilon_solvent
    1234              :                   s%array(i, j, k) = 0.0_dp
    1235              :                   deps_elec%array(i, j, k) = 0.0_dp
    1236              :                   d_s_rhoel%array(i, j, k) = 0.0_dp
    1237              :                ELSE IF (rho <= rho_max) THEN
    1238              :                   x = LOG(rho)
    1239              :                   y = q*(ln_rho_max - x)
    1240              :                   t = f*(y - SIN(y))
    1241              :                   s%array(i, j, k) = 1 - t/(f*twopi)
    1242              :                   eps_elec%array(i, j, k) = EXP(t)
    1243              :                   dt = dq*(1.0_dp - COS(y))
    1244              :                   deps_elec%array(i, j, k) = eps_elec%array(i, j, k)*dt/rho
    1245              :                   d_s_rhoel%array(i, j, k) = deps_elec%array(i, j, k)/(-eps_elec%array(i, j, k)*LOG(epsilon_solvent))
    1246              :                ELSE
    1247              :                   eps_elec%array(i, j, k) = 1.0_dp
    1248              :                   deps_elec%array(i, j, k) = 0.0_dp
    1249              :                   s%array(i, j, k) = 1.0_dp
    1250              :                   d_s_rhoel%array(i, j, k) = 0.0_dp
    1251              :                END IF
    1252              :             END DO
    1253              :          END DO
    1254              :       END DO
    1255              : !$OMP END PARALLEL DO
    1256              : 
    1257            0 :       CALL timestop(handle)
    1258              : 
    1259            0 :    END SUBROUTINE sa_andreussi
    1260              : 
    1261              : ! **************************************************************************************************
    1262              : !> \brief      Build the numerical derivative of a function on realspace grid
    1263              : !> \param f ...
    1264              : !> \param df ...
    1265              : !> \param method ...
    1266              : !> \param pw_env ...
    1267              : !> \param input ...
    1268              : !> \par History:
    1269              : !>      - Creation (15.11.2013,MK)
    1270              : !> \author     Matthias Krack (MK)
    1271              : !> \version    1.0
    1272              : ! **************************************************************************************************
    1273          384 :    SUBROUTINE derive(f, df, method, pw_env, input)
    1274              : 
    1275              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: f
    1276              :       TYPE(pw_r3d_rs_type), DIMENSION(3), INTENT(INOUT)  :: df
    1277              :       INTEGER, INTENT(IN)                                :: method
    1278              :       TYPE(pw_env_type), POINTER                         :: pw_env
    1279              :       TYPE(section_vals_type), POINTER                   :: input
    1280              : 
    1281              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'derive'
    1282              : 
    1283              :       INTEGER                                            :: border_points, handle, i
    1284              :       INTEGER, DIMENSION(3)                              :: lb, n, ub
    1285         1152 :       TYPE(pw_c1d_gs_type), DIMENSION(2)                 :: work_g1d
    1286              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    1287              :       TYPE(realspace_grid_desc_type), POINTER            :: rs_desc
    1288              :       TYPE(realspace_grid_input_type)                    :: input_settings
    1289              :       TYPE(realspace_grid_type), POINTER                 :: rs_grid
    1290              :       TYPE(section_vals_type), POINTER                   :: rs_grid_section
    1291              : 
    1292          384 :       CALL timeset(routineN, handle)
    1293              : 
    1294          384 :       CPASSERT(ASSOCIATED(pw_env))
    1295              : 
    1296              :       ! Perform method specific setup
    1297          540 :       SELECT CASE (method)
    1298              :       CASE (sccs_derivative_cd3, sccs_derivative_cd5, sccs_derivative_cd7)
    1299          156 :          NULLIFY (rs_desc)
    1300          156 :          rs_grid_section => section_vals_get_subs_vals(input, "DFT%MGRID%RS_GRID")
    1301            0 :          SELECT CASE (method)
    1302              :          CASE (sccs_derivative_cd3)
    1303            0 :             border_points = 1
    1304              :          CASE (sccs_derivative_cd5)
    1305          156 :             border_points = 2
    1306              :          CASE (sccs_derivative_cd7)
    1307          156 :             border_points = 3
    1308              :          END SELECT
    1309              :          CALL init_input_type(input_settings, 2*border_points + 1, rs_grid_section, &
    1310          156 :                               1, [-1, -1, -1])
    1311              :          CALL rs_grid_create_descriptor(rs_desc, f%pw_grid, input_settings, &
    1312          156 :                                         border_points=border_points)
    1313         3276 :          ALLOCATE (rs_grid)
    1314          156 :          CALL rs_grid_create(rs_grid, rs_desc)
    1315              : !MK      CALL rs_grid_print(rs_grid, 6)
    1316              :       CASE (sccs_derivative_fft)
    1317          912 :          lb(1:3) = f%pw_grid%bounds_local(1, 1:3)
    1318          912 :          ub(1:3) = f%pw_grid%bounds_local(2, 1:3)
    1319          228 :          NULLIFY (auxbas_pw_pool)
    1320          228 :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    1321              :          ! Get work storage for the 1d grids in g-space (derivative calculation)
    1322         1068 :          DO i = 1, SIZE(work_g1d)
    1323          684 :             CALL auxbas_pw_pool%create_pw(work_g1d(i))
    1324              :          END DO
    1325              :       END SELECT
    1326              : 
    1327              :       ! Calculate the derivatives
    1328            0 :       SELECT CASE (method)
    1329              :       CASE (sccs_derivative_cd3)
    1330            0 :          CALL derive_fdm_cd3(f, df, rs_grid)
    1331              :       CASE (sccs_derivative_cd5)
    1332          156 :          CALL derive_fdm_cd5(f, df, rs_grid)
    1333              :       CASE (sccs_derivative_cd7)
    1334            0 :          CALL derive_fdm_cd7(f, df, rs_grid)
    1335              :       CASE (sccs_derivative_fft)
    1336              :          ! FFT
    1337          228 :          CALL pw_transfer(f, work_g1d(1))
    1338          912 :          DO i = 1, 3
    1339          684 :             n(:) = 0
    1340          684 :             n(i) = 1
    1341          684 :             CALL pw_copy(work_g1d(1), work_g1d(2))
    1342          684 :             CALL pw_derive(work_g1d(2), n(:))
    1343          912 :             CALL pw_transfer(work_g1d(2), df(i))
    1344              :          END DO
    1345              :       CASE DEFAULT
    1346          384 :          CPABORT("Invalid derivative method for SCCS specified")
    1347              :       END SELECT
    1348              : 
    1349              :       ! Perform method specific cleanup
    1350          156 :       SELECT CASE (method)
    1351              :       CASE (sccs_derivative_cd3, sccs_derivative_cd5, sccs_derivative_cd7)
    1352          156 :          CALL rs_grid_release(rs_grid)
    1353          156 :          DEALLOCATE (rs_grid)
    1354          156 :          CALL rs_grid_release_descriptor(rs_desc)
    1355              :       CASE (sccs_derivative_fft)
    1356         1068 :          DO i = 1, SIZE(work_g1d)
    1357          684 :             CALL auxbas_pw_pool%give_back_pw(work_g1d(i))
    1358              :          END DO
    1359              :       END SELECT
    1360              : 
    1361          384 :       CALL timestop(handle)
    1362              : 
    1363         1536 :    END SUBROUTINE derive
    1364              : 
    1365              : ! **************************************************************************************************
    1366              : !> \brief      Calculate the finite difference between two isosurfaces of the
    1367              : !>             electronic density. The smoothed dielectric function of
    1368              : !>             Andreussi et al. is used as switching function eventually
    1369              : !>             defining the quantum volume and surface of the cavity.
    1370              : !> \param rho_elec ...
    1371              : !> \param norm_drho_elec ...
    1372              : !> \param dtheta ...
    1373              : !> \param epsilon_solvent ...
    1374              : !> \param rho_max ...
    1375              : !> \param rho_min ...
    1376              : !> \param delta_rho ...
    1377              : !> \par History:
    1378              : !>      - Creation (21.12.2013,MK)
    1379              : !> \author     Matthias Krack (MK)
    1380              : !> \version    1.0
    1381              : ! **************************************************************************************************
    1382          148 :    SUBROUTINE surface_andreussi(rho_elec, norm_drho_elec, dtheta, &
    1383              :                                 epsilon_solvent, rho_max, rho_min, delta_rho)
    1384              : 
    1385              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: rho_elec, norm_drho_elec, dtheta
    1386              :       REAL(KIND=dp), INTENT(IN)                          :: epsilon_solvent, rho_max, rho_min, &
    1387              :                                                             delta_rho
    1388              : 
    1389              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'surface_andreussi'
    1390              :       REAL(KIND=dp), PARAMETER                           :: rhotol = 1.0E-12_dp
    1391              : 
    1392              :       INTEGER                                            :: handle, i, j, k, l
    1393              :       INTEGER, DIMENSION(3)                              :: lb, ub
    1394              :       REAL(KIND=dp)                                      :: diff, e, eps_elec, f, ln_rho_max, &
    1395              :                                                             ln_rho_min, q, rho, t, x, y
    1396              :       REAL(KIND=dp), DIMENSION(2)                        :: theta
    1397              : 
    1398          148 :       CALL timeset(routineN, handle)
    1399              : 
    1400          148 :       e = epsilon_solvent - 1.0_dp
    1401          148 :       f = LOG(epsilon_solvent)/twopi
    1402          148 :       diff = rho_max - rho_min
    1403          148 :       IF (diff < SQRT(rhotol)) CPABORT("SCCS: Difference between rho(min) and rho(max) is too small")
    1404          148 :       IF (rho_min >= rhotol) THEN
    1405          148 :          ln_rho_max = LOG(rho_max)
    1406          148 :          ln_rho_min = LOG(rho_min)
    1407          148 :          q = twopi/(ln_rho_max - ln_rho_min)
    1408              :       END IF
    1409              : 
    1410          592 :       lb(1:3) = rho_elec%pw_grid%bounds_local(1, 1:3)
    1411          592 :       ub(1:3) = rho_elec%pw_grid%bounds_local(2, 1:3)
    1412              : 
    1413              :       ! Calculate finite difference between two isosurfaces
    1414              : !$OMP PARALLEL DO DEFAULT(NONE) &
    1415              : !$OMP             PRIVATE(eps_elec,i,j,k,l,rho,t,theta,x,y) &
    1416              : !$OMP             SHARED(delta_rho,dtheta,e,epsilon_solvent,f,lb) &
    1417          148 : !$OMP             SHARED(ln_rho_max,norm_drho_elec,rho_elec,q,rho_max,rho_min,ub)
    1418              :       DO k = lb(3), ub(3)
    1419              :          DO j = lb(2), ub(2)
    1420              :             DO i = lb(1), ub(1)
    1421              :                DO l = 1, 2
    1422              :                   rho = rho_elec%array(i, j, k) + (REAL(l, KIND=dp) - 1.5_dp)*delta_rho
    1423              :                   IF (rho < rho_min) THEN
    1424              :                      eps_elec = epsilon_solvent
    1425              :                   ELSE IF (rho <= rho_max) THEN
    1426              :                      x = LOG(rho)
    1427              :                      y = q*(ln_rho_max - x)
    1428              :                      t = f*(y - SIN(y))
    1429              :                      eps_elec = EXP(t)
    1430              :                   ELSE
    1431              :                      eps_elec = 1.0_dp
    1432              :                   END IF
    1433              :                   theta(l) = (epsilon_solvent - eps_elec)/e
    1434              :                END DO
    1435              :                dtheta%array(i, j, k) = (theta(2) - theta(1))*norm_drho_elec%array(i, j, k)/delta_rho
    1436              :             END DO
    1437              :          END DO
    1438              :       END DO
    1439              : !$OMP END PARALLEL DO
    1440              : 
    1441          148 :       CALL timestop(handle)
    1442              : 
    1443          148 :    END SUBROUTINE surface_andreussi
    1444              : 
    1445              : ! **************************************************************************************************
    1446              : !> \brief      Calculate the finite difference between two isosurfaces of the
    1447              : !>             the electronic density. The smoothed dielectric function of
    1448              : !>             Fattebert and Gygi is used as switching function eventually
    1449              : !>             defining the quantum volume and surface of the cavity.
    1450              : !> \param rho_elec ...
    1451              : !> \param norm_drho_elec ...
    1452              : !> \param dtheta ...
    1453              : !> \param epsilon_solvent ...
    1454              : !> \param beta ...
    1455              : !> \param rho_zero ...
    1456              : !> \param delta_rho ...
    1457              : !> \par History:
    1458              : !>      - Creation (21.12.2013,MK)
    1459              : !> \author     Matthias Krack (MK)
    1460              : !> \version    1.0
    1461              : ! **************************************************************************************************
    1462           44 :    SUBROUTINE surface_fattebert_gygi(rho_elec, norm_drho_elec, dtheta, &
    1463              :                                      epsilon_solvent, beta, rho_zero, delta_rho)
    1464              : 
    1465              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: rho_elec, norm_drho_elec, dtheta
    1466              :       REAL(KIND=dp), INTENT(IN)                          :: epsilon_solvent, beta, rho_zero, &
    1467              :                                                             delta_rho
    1468              : 
    1469              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'surface_fattebert_gygi'
    1470              :       REAL(KIND=dp), PARAMETER                           :: rhotol = 1.0E-12_dp
    1471              : 
    1472              :       INTEGER                                            :: handle, i, j, k, l
    1473              :       INTEGER, DIMENSION(3)                              :: lb, ub
    1474              :       REAL(KIND=dp)                                      :: e, eps_elec, f, p, q, rho, s, t, twobeta
    1475              :       REAL(KIND=dp), DIMENSION(2)                        :: theta
    1476              : 
    1477           44 :       CALL timeset(routineN, handle)
    1478              : 
    1479           44 :       e = epsilon_solvent - 1.0_dp
    1480           44 :       f = 0.5_dp*e
    1481           44 :       q = 1.0_dp/rho_zero
    1482           44 :       twobeta = 2.0_dp*beta
    1483              : 
    1484          176 :       lb(1:3) = rho_elec%pw_grid%bounds_local(1, 1:3)
    1485          176 :       ub(1:3) = rho_elec%pw_grid%bounds_local(2, 1:3)
    1486              : 
    1487              :       ! Calculate finite difference between two isosurfaces
    1488              : !$OMP PARALLEL DO DEFAULT(NONE) &
    1489              : !$OMP             PRIVATE(eps_elec,i,j,k,l,p,rho,s,t,theta) &
    1490              : !$OMP             SHARED(delta_rho,dtheta,e,epsilon_solvent,f,lb) &
    1491           44 : !$OMP             SHARED(norm_drho_elec,q,rho_elec,twobeta,ub)
    1492              :       DO k = lb(3), ub(3)
    1493              :          DO j = lb(2), ub(2)
    1494              :             DO i = lb(1), ub(1)
    1495              :                DO l = 1, 2
    1496              :                   rho = rho_elec%array(i, j, k) + (REAL(l, KIND=dp) - 1.5_dp)*delta_rho
    1497              :                   IF (rho < rhotol) THEN
    1498              :                      eps_elec = epsilon_solvent
    1499              :                   ELSE
    1500              :                      s = rho*q
    1501              :                      p = s**twobeta
    1502              :                      t = 1.0_dp/(1.0_dp + p)
    1503              :                      eps_elec = 1.0_dp + f*(1.0_dp + (1.0_dp - p)*t)
    1504              :                   END IF
    1505              :                   theta(l) = (epsilon_solvent - eps_elec)/e
    1506              :                END DO
    1507              :                dtheta%array(i, j, k) = (theta(2) - theta(1))*norm_drho_elec%array(i, j, k)/delta_rho
    1508              :             END DO
    1509              :          END DO
    1510              :       END DO
    1511              : !$OMP END PARALLEL DO
    1512              : 
    1513           44 :       CALL timestop(handle)
    1514              : 
    1515           44 :    END SUBROUTINE surface_fattebert_gygi
    1516              : 
    1517              : ! **************************************************************************************************
    1518              : !> \brief      Print SCCS results
    1519              : !> \param energy ...
    1520              : !> \param sccs_control ...
    1521              : !> \param output_unit ...
    1522              : !> \par History:
    1523              : !>      - Creation (11.11.2022,MK)
    1524              : !> \author     Matthias Krack (MK)
    1525              : !> \version    1.0
    1526              : ! **************************************************************************************************
    1527           96 :    SUBROUTINE print_sccs_results(energy, sccs_control, output_unit)
    1528              : 
    1529              :       TYPE(qs_energy_type), POINTER                      :: energy
    1530              :       TYPE(sccs_control_type), POINTER                   :: sccs_control
    1531              :       INTEGER, INTENT(IN)                                :: output_unit
    1532              : 
    1533           96 :       IF (output_unit > 0) THEN
    1534           96 :          CPASSERT(ASSOCIATED(energy))
    1535           96 :          CPASSERT(ASSOCIATED(sccs_control))
    1536              :          WRITE (UNIT=output_unit, FMT="(T3,A,T56,F25.14)") &
    1537           96 :             "SCCS| Hartree energy of solute and solvent [Hartree]", energy%sccs_hartree, &
    1538          192 :             "SCCS| Hartree energy of the solute only    [Hartree]", energy%hartree
    1539              :          WRITE (UNIT=output_unit, FMT="(T3,A,T56,F25.14,/,T3,A,T61,F20.3)") &
    1540           96 :             "SCCS| Polarisation energy                  [Hartree]", energy%sccs_pol, &
    1541           96 :             "SCCS|                                      [kcal/mol]", &
    1542           96 :             cp_unit_from_cp2k(energy%sccs_pol, "kcalmol"), &
    1543           96 :             "SCCS| Cavitation energy                    [Hartree]", energy%sccs_cav, &
    1544           96 :             "SCCS|                                      [kcal/mol]", &
    1545           96 :             cp_unit_from_cp2k(energy%sccs_cav, "kcalmol"), &
    1546           96 :             "SCCS| Dispersion free energy               [Hartree]", energy%sccs_dis, &
    1547           96 :             "SCCS|                                      [kcal/mol]", &
    1548           96 :             cp_unit_from_cp2k(energy%sccs_dis, "kcalmol"), &
    1549           96 :             "SCCS| Repulsion free energy                [Hartree]", energy%sccs_rep, &
    1550           96 :             "SCCS|                                      [kcal/mol]", &
    1551           96 :             cp_unit_from_cp2k(energy%sccs_rep, "kcalmol"), &
    1552           96 :             "SCCS| Solvation free energy                [Hartree]", energy%sccs_sol, &
    1553           96 :             "SCCS|                                      [kcal/mol]", &
    1554          192 :             cp_unit_from_cp2k(energy%sccs_sol, "kcalmol")
    1555              :       END IF
    1556              : 
    1557           96 :    END SUBROUTINE print_sccs_results
    1558              : 
    1559              : ! **************************************************************************************************
    1560              : !> \brief Exponents and coefficients of the SCCS core fill Gaussians per atomic kind, such that
    1561              : !>        the fill density of an atom is ccore*exp(-calpha*r**2) = Z_val/(sqrt(pi)*sigma)**3*
    1562              : !>        exp(-r**2/sigma**2). A zero coefficient means that the kind is not filled.
    1563              : !> \param qs_env ...
    1564              : !> \param calpha Gaussian exponents 1/sigma**2 per kind
    1565              : !> \param ccore Gaussian coefficients per kind
    1566              : !> \param output_unit if > 0, the fill parameters are printed once
    1567              : ! **************************************************************************************************
    1568           80 :    SUBROUTINE sccs_core_fill_coefficients(qs_env, calpha, ccore, output_unit)
    1569              : 
    1570              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1571              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
    1572              :          INTENT(OUT)                                     :: calpha, ccore
    1573              :       INTEGER, INTENT(IN), OPTIONAL                      :: output_unit
    1574              : 
    1575              :       CHARACTER(LEN=default_string_length)               :: kind_name
    1576              :       INTEGER                                            :: ikind, iover, nkind, z
    1577              :       LOGICAL                                            :: found
    1578           80 :       LOGICAL, ALLOCATABLE, DIMENSION(:)                 :: used
    1579              :       REAL(KIND=dp)                                      :: r_thr, rho_thr, sigma, zeff
    1580           80 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1581              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1582           80 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1583              :       TYPE(sccs_control_type), POINTER                   :: sccs_control
    1584              : 
    1585           80 :       NULLIFY (atomic_kind_set, dft_control, qs_kind_set)
    1586              :       CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, qs_kind_set=qs_kind_set, &
    1587           80 :                       dft_control=dft_control)
    1588           80 :       sccs_control => dft_control%sccs_control
    1589           80 :       nkind = SIZE(atomic_kind_set)
    1590          422 :       ALLOCATE (calpha(nkind), ccore(nkind), used(SIZE(sccs_control%core_fill_kind_label)))
    1591           80 :       used(:) = .FALSE.
    1592              : 
    1593              :       ! Density threshold used only for the diagnostic radius of the fill:
    1594              :       ! the onset of the dielectric transition of the chosen method
    1595          138 :       SELECT CASE (sccs_control%method_id)
    1596              :       CASE (sccs_andreussi, sccs_saa_andreussi)
    1597           58 :          rho_thr = sccs_control%rho_min
    1598              :       CASE (sccs_fattebert_gygi)
    1599           22 :          rho_thr = sccs_control%rho_zero
    1600              :       CASE DEFAULT
    1601           80 :          rho_thr = 0.0_dp
    1602              :       END SELECT
    1603              : 
    1604           80 :       IF (PRESENT(output_unit)) THEN
    1605           78 :          IF ((output_unit > 0) .AND. (.NOT. sccs_control%core_fill_printed)) THEN
    1606              :             WRITE (UNIT=output_unit, FMT="(/,T3,A,/,T3,A,ES10.3,/,T3,A)") &
    1607            2 :                "SCCS| Core fill: Z_val/(sqrt(pi)*sigma)**3*exp(-r**2/sigma**2) added for the cavity", &
    1608            2 :                "SCCS| r_thr: radius at which the fill density drops to rho_thr =", rho_thr, &
    1609            4 :                "SCCS|   Kind        Z   Z_val   sigma [bohr]   r_thr [Angstrom]"
    1610              :          END IF
    1611              :       END IF
    1612              : 
    1613          240 :       DO ikind = 1, nkind
    1614          160 :          CALL get_atomic_kind(atomic_kind_set(ikind), name=kind_name, z=z)
    1615          160 :          CALL get_qs_kind(qs_kind_set(ikind), zeff=zeff)
    1616          160 :          CALL uppercase(kind_name)
    1617              :          ! Default spread. Kinds without removed core electrons (Z_val = Z, e.g. H-q1, He-q2,
    1618              :          ! Li-q3, Be-q4) have no core hole in the valence density and are not filled
    1619              :          ! (generalises the hydrogen exception of Environ)
    1620          160 :          sigma = sccs_control%core_fill_spread
    1621          160 :          IF (zeff >= REAL(z, KIND=dp) - 0.5_dp) sigma = 0.0_dp
    1622          160 :          found = .FALSE.
    1623          248 :          DO iover = 1, SIZE(sccs_control%core_fill_kind_label)
    1624          248 :             IF (TRIM(sccs_control%core_fill_kind_label(iover)) == TRIM(kind_name)) THEN
    1625           44 :                sigma = sccs_control%core_fill_kind_spread(iover)
    1626           44 :                used(iover) = .TRUE.
    1627           44 :                found = .TRUE.
    1628              :             END IF
    1629              :          END DO
    1630          160 :          IF ((sigma > 0.0_dp) .AND. (zeff > 0.0_dp)) THEN
    1631          102 :             calpha(ikind) = 1.0_dp/(sigma*sigma)
    1632          102 :             ccore(ikind) = zeff*(calpha(ikind)/pi)**1.5_dp
    1633              :          ELSE
    1634           58 :             calpha(ikind) = 0.0_dp
    1635           58 :             ccore(ikind) = 0.0_dp
    1636              :          END IF
    1637          400 :          IF (PRESENT(output_unit)) THEN
    1638          156 :             IF ((output_unit > 0) .AND. (.NOT. sccs_control%core_fill_printed)) THEN
    1639            4 :                IF ((ccore(ikind) > 0.0_dp) .AND. (rho_thr > 0.0_dp)) THEN
    1640            3 :                   r_thr = 0.0_dp
    1641            3 :                   IF (ccore(ikind) > rho_thr) THEN
    1642            3 :                      r_thr = SQRT(LOG(ccore(ikind)/rho_thr)/calpha(ikind))
    1643              :                   END IF
    1644              :                   WRITE (UNIT=output_unit, FMT="(T3,A,T10,A,T18,I3,T24,F6.2,T34,F8.4,T50,F8.4,A)") &
    1645            3 :                      "SCCS|", TRIM(kind_name), z, zeff, sigma, cp_unit_from_cp2k(r_thr, "angstrom"), &
    1646            7 :                      MERGE(" (input)", "        ", found)
    1647            1 :                ELSE IF (ccore(ikind) > 0.0_dp) THEN
    1648              :                   WRITE (UNIT=output_unit, FMT="(T3,A,T10,A,T18,I3,T24,F6.2,T34,F8.4,T50,A)") &
    1649            0 :                      "SCCS|", TRIM(kind_name), z, zeff, sigma, "-"//MERGE(" (input)", "        ", found)
    1650              :                ELSE
    1651              :                   WRITE (UNIT=output_unit, FMT="(T3,A,T10,A,T18,I3,T24,F6.2,T34,A)") &
    1652            2 :                      "SCCS|", TRIM(kind_name), z, zeff, "no fill"//MERGE(" (input)", "        ", found)
    1653              :                END IF
    1654              :             END IF
    1655              :          END IF
    1656              :       END DO
    1657              : 
    1658          124 :       DO iover = 1, SIZE(used)
    1659          124 :          IF (.NOT. used(iover)) THEN
    1660              :             CALL cp_abort(__LOCATION__, "SCCS| CORE_FILL_KIND: unknown kind label "// &
    1661            0 :                           TRIM(sccs_control%core_fill_kind_label(iover)))
    1662              :          END IF
    1663              :       END DO
    1664           80 :       IF (PRESENT(output_unit)) THEN
    1665           78 :          IF (output_unit > 0) sccs_control%core_fill_printed = .TRUE.
    1666              :       END IF
    1667           80 :       DEALLOCATE (used)
    1668              : 
    1669           80 :    END SUBROUTINE sccs_core_fill_coefficients
    1670              : 
    1671              : END MODULE qs_sccs
        

Generated by: LCOV version 2.0-1