LCOV - code coverage report
Current view: top level - src - qs_sccs.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:06f838d) Lines: 85.2 % 393 335
Test Date: 2026-06-05 07:04:50 Functions: 100.0 % 7 7

            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 cp_control_types,                ONLY: dft_control_type,&
      32              :                                               sccs_control_type
      33              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      34              :                                               cp_logger_type
      35              :    USE cp_output_handling,              ONLY: cp_p_file,&
      36              :                                               cp_print_key_finished_output,&
      37              :                                               cp_print_key_should_output,&
      38              :                                               cp_print_key_unit_nr,&
      39              :                                               low_print_level
      40              :    USE cp_realspace_grid_cube,          ONLY: cp_pw_to_cube
      41              :    USE cp_realspace_grid_init,          ONLY: init_input_type
      42              :    USE cp_subsys_types,                 ONLY: cp_subsys_get,&
      43              :                                               cp_subsys_type
      44              :    USE cp_units,                        ONLY: cp_unit_from_cp2k
      45              :    USE input_constants,                 ONLY: sccs_andreussi,&
      46              :                                               sccs_derivative_cd3,&
      47              :                                               sccs_derivative_cd5,&
      48              :                                               sccs_derivative_cd7,&
      49              :                                               sccs_derivative_fft,&
      50              :                                               sccs_fattebert_gygi
      51              :    USE input_section_types,             ONLY: section_get_ivals,&
      52              :                                               section_get_lval,&
      53              :                                               section_vals_get_subs_vals,&
      54              :                                               section_vals_type
      55              :    USE kinds,                           ONLY: default_path_length,&
      56              :                                               default_string_length,&
      57              :                                               dp,&
      58              :                                               int_8
      59              :    USE mathconstants,                   ONLY: fourpi,&
      60              :                                               twopi
      61              :    USE message_passing,                 ONLY: mp_para_env_type
      62              :    USE particle_list_types,             ONLY: particle_list_type
      63              :    USE pw_env_types,                    ONLY: pw_env_get,&
      64              :                                               pw_env_type
      65              :    USE pw_methods,                      ONLY: pw_axpy,&
      66              :                                               pw_copy,&
      67              :                                               pw_derive,&
      68              :                                               pw_integral_ab,&
      69              :                                               pw_integrate_function,&
      70              :                                               pw_transfer,&
      71              :                                               pw_zero
      72              :    USE pw_poisson_methods,              ONLY: pw_poisson_solve
      73              :    USE pw_poisson_types,                ONLY: pw_poisson_analytic,&
      74              :                                               pw_poisson_mt,&
      75              :                                               pw_poisson_type
      76              :    USE pw_pool_types,                   ONLY: pw_pool_p_type,&
      77              :                                               pw_pool_type
      78              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      79              :                                               pw_r3d_rs_type
      80              :    USE qs_energy_types,                 ONLY: qs_energy_type
      81              :    USE qs_environment_types,            ONLY: get_qs_env,&
      82              :                                               qs_environment_type
      83              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      84              :                                               qs_rho_type
      85              :    USE qs_scf_types,                    ONLY: qs_scf_env_type
      86              :    USE realspace_grid_types,            ONLY: realspace_grid_desc_type,&
      87              :                                               realspace_grid_input_type,&
      88              :                                               realspace_grid_type,&
      89              :                                               rs_grid_create,&
      90              :                                               rs_grid_create_descriptor,&
      91              :                                               rs_grid_release,&
      92              :                                               rs_grid_release_descriptor
      93              :    USE rs_methods,                      ONLY: derive_fdm_cd3,&
      94              :                                               derive_fdm_cd5,&
      95              :                                               derive_fdm_cd7
      96              : #include "./base/base_uses.f90"
      97              : 
      98              :    IMPLICIT NONE
      99              : 
     100              :    PRIVATE
     101              : 
     102              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_sccs'
     103              : 
     104              :    PUBLIC :: print_sccs_results, sccs
     105              : 
     106              : CONTAINS
     107              : 
     108              : ! **************************************************************************************************
     109              : !> \brief   Self-consistent continuum solvation (SCCS) model implementation
     110              : !> \param qs_env ...
     111              : !> \param rho_tot_gspace ...
     112              : !> \param v_hartree_gspace ...
     113              : !> \param v_sccs ...
     114              : !> \param h_stress ...
     115              : !> \par History:
     116              : !>      - Creation (10.10.2013,MK)
     117              : !> \author  Matthias Krack (MK)
     118              : !> \version 1.0
     119              : ! **************************************************************************************************
     120              : 
     121          132 :    SUBROUTINE sccs(qs_env, rho_tot_gspace, v_hartree_gspace, v_sccs, h_stress)
     122              : 
     123              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     124              :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: rho_tot_gspace, v_hartree_gspace
     125              :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: v_sccs
     126              :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(OUT), &
     127              :          OPTIONAL                                        :: h_stress
     128              : 
     129              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'sccs'
     130              :       REAL(KIND=dp), PARAMETER                           :: epstol = 1.0E-8_dp
     131              : 
     132              :       CHARACTER(LEN=4*default_string_length)             :: message, my_pos_cube
     133              :       CHARACTER(LEN=default_path_length)                 :: cube_path, filename, mpi_filename, &
     134              :                                                             print_path
     135              :       INTEGER                                            :: cube_unit, handle, i, ispin, iter, j, k, &
     136              :                                                             nspin, output_unit, print_level
     137              :       INTEGER(KIND=int_8)                                :: ngpts
     138              :       INTEGER, DIMENSION(3)                              :: lb, ub
     139              :       LOGICAL                                            :: append_cube, calculate_stress_tensor, &
     140              :                                                             do_kpoints, mpi_io, should_output
     141              :       REAL(KIND=dp) :: cavity_surface, cavity_volume, cell_volume, dphi2, dvol, e_tot, &
     142              :          epsilon_solvent, f, polarisation_charge, rho_delta, rho_delta_avg, rho_delta_max, &
     143              :          rho_iter_new, tot_rho_elec, tot_rho_solute
     144              :       REAL(KIND=dp), DIMENSION(3)                        :: abc
     145              :       TYPE(cp_logger_type), POINTER                      :: logger
     146              :       TYPE(cp_subsys_type), POINTER                      :: cp_subsys
     147              :       TYPE(dft_control_type), POINTER                    :: dft_control
     148              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     149              :       TYPE(particle_list_type), POINTER                  :: particles
     150              :       TYPE(pw_env_type), POINTER                         :: pw_env
     151              :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     152          132 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
     153              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     154              :       TYPE(pw_r3d_rs_type)                               :: deps_elec, eps_elec
     155          924 :       TYPE(pw_r3d_rs_type), DIMENSION(3)                 :: dln_eps_elec, dphi_tot
     156          132 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_pw_r
     157              :       TYPE(pw_r3d_rs_type), POINTER                      :: rho_pw_r_sccs
     158              :       TYPE(qs_energy_type), POINTER                      :: energy
     159              :       TYPE(qs_rho_type), POINTER                         :: rho
     160              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     161              :       TYPE(sccs_control_type), POINTER                   :: sccs_control
     162              :       TYPE(section_vals_type), POINTER                   :: input
     163              : 
     164          132 :       CALL timeset(routineN, handle)
     165              : 
     166          132 :       NULLIFY (auxbas_pw_pool)
     167          132 :       NULLIFY (cp_subsys)
     168          132 :       NULLIFY (dft_control)
     169          132 :       NULLIFY (energy)
     170          132 :       NULLIFY (input)
     171          132 :       NULLIFY (logger)
     172          132 :       NULLIFY (para_env)
     173          132 :       NULLIFY (particles)
     174          132 :       NULLIFY (poisson_env)
     175          132 :       NULLIFY (pw_env)
     176          132 :       NULLIFY (pw_pools)
     177          132 :       NULLIFY (rho)
     178          132 :       NULLIFY (sccs_control)
     179          132 :       NULLIFY (scf_env)
     180              : 
     181              :       ! Load data from Quickstep environment
     182              :       CALL get_qs_env(qs_env=qs_env, &
     183              :                       cp_subsys=cp_subsys, &
     184              :                       dft_control=dft_control, &
     185              :                       do_kpoints=do_kpoints, &
     186              :                       energy=energy, &
     187              :                       input=input, &
     188              :                       para_env=para_env, &
     189              :                       pw_env=pw_env, &
     190              :                       rho=rho, &
     191          132 :                       scf_env=scf_env)
     192          132 :       CALL cp_subsys_get(cp_subsys, particles=particles)
     193              : 
     194          132 :       sccs_control => dft_control%sccs_control
     195              : 
     196          132 :       CPASSERT(ASSOCIATED(qs_env))
     197              : 
     198          132 :       IF (do_kpoints) THEN
     199            0 :          CPWARN("SCCS with k-points has not yet been fully validated")
     200              :       END IF
     201              : 
     202          132 :       IF (PRESENT(h_stress)) THEN
     203            0 :          calculate_stress_tensor = .TRUE.
     204            0 :          h_stress(:, :) = 0.0_dp
     205            0 :          CPWARN("The stress tensor for SCCS has not yet been fully validated")
     206              :       ELSE
     207              :          calculate_stress_tensor = .FALSE.
     208              :       END IF
     209              : 
     210              :       ! Get access to the PW grid pool
     211              :       CALL pw_env_get(pw_env, &
     212              :                       auxbas_pw_pool=auxbas_pw_pool, &
     213              :                       pw_pools=pw_pools, &
     214          132 :                       poisson_env=poisson_env)
     215              : 
     216          132 :       CALL pw_zero(v_sccs)
     217              : 
     218              :       ! Calculate no SCCS contribution, if the requested SCF convergence threshold is not reached yet
     219          132 :       IF (.NOT. sccs_control%sccs_activated) THEN
     220           50 :          IF (sccs_control%eps_scf > 0.0_dp) THEN
     221           48 :             IF ((scf_env%iter_delta > sccs_control%eps_scf) .OR. &
     222              :                 ((qs_env%scf_env%outer_scf%iter_count == 0) .AND. &
     223              :                  (qs_env%scf_env%iter_count <= 1))) THEN
     224           40 :                IF (calculate_stress_tensor) THEN
     225              :                   ! Request also the calculation of the stress tensor contribution
     226              :                   CALL pw_poisson_solve(poisson_env=poisson_env, &
     227              :                                         density=rho_tot_gspace, &
     228              :                                         ehartree=energy%hartree, &
     229              :                                         vhartree=v_hartree_gspace, &
     230            0 :                                         h_stress=h_stress)
     231              :                ELSE
     232              :                   CALL pw_poisson_solve(poisson_env=poisson_env, &
     233              :                                         density=rho_tot_gspace, &
     234              :                                         ehartree=energy%hartree, &
     235           40 :                                         vhartree=v_hartree_gspace)
     236              :                END IF
     237           40 :                energy%sccs_pol = 0.0_dp
     238           40 :                energy%sccs_cav = 0.0_dp
     239           40 :                energy%sccs_dis = 0.0_dp
     240           40 :                energy%sccs_rep = 0.0_dp
     241           40 :                energy%sccs_sol = 0.0_dp
     242           40 :                energy%sccs_hartree = energy%hartree
     243           40 :                CALL timestop(handle)
     244           40 :                RETURN
     245              :             END IF
     246              :          END IF
     247           10 :          sccs_control%sccs_activated = .TRUE.
     248              :       END IF
     249              : 
     250           92 :       nspin = dft_control%nspins
     251              : 
     252              :       ! Manage print output control
     253           92 :       logger => cp_get_default_logger()
     254           92 :       print_level = logger%iter_info%print_level
     255           92 :       print_path = "DFT%PRINT%SCCS"
     256              :       should_output = (BTEST(cp_print_key_should_output(logger%iter_info, input, &
     257           92 :                                                         TRIM(print_path)), cp_p_file))
     258              :       output_unit = cp_print_key_unit_nr(logger, input, TRIM(print_path), &
     259              :                                          extension=".sccs", &
     260              :                                          ignore_should_output=should_output, &
     261           92 :                                          log_filename=.FALSE.)
     262              : 
     263              :       ! Get rho
     264              :       CALL qs_rho_get(rho_struct=rho, &
     265              :                       rho_r=rho_pw_r, &
     266           92 :                       rho_r_sccs=rho_pw_r_sccs)
     267              : 
     268              :       ! Retrieve the last rho_iter from the previous SCCS cycle if available
     269           92 :       CPASSERT(ASSOCIATED(rho_pw_r_sccs))
     270              : 
     271              :       ! Retrieve the total electronic density in r-space
     272              :       BLOCK
     273              :          TYPE(pw_r3d_rs_type) :: rho_elec
     274           92 :          CALL auxbas_pw_pool%create_pw(rho_elec)
     275              : 
     276              :          ! Retrieve grid parameters
     277           92 :          ngpts = rho_elec%pw_grid%ngpts
     278           92 :          dvol = rho_elec%pw_grid%dvol
     279           92 :          cell_volume = rho_elec%pw_grid%vol
     280          368 :          abc(1:3) = REAL(rho_elec%pw_grid%npts(1:3), KIND=dp)*rho_elec%pw_grid%dr(1:3)
     281          368 :          lb(1:3) = rho_elec%pw_grid%bounds_local(1, 1:3)
     282          368 :          ub(1:3) = rho_elec%pw_grid%bounds_local(2, 1:3)
     283              : 
     284           92 :          CALL pw_copy(rho_pw_r(1), rho_elec)
     285           92 :          DO ispin = 2, nspin
     286           92 :             CALL pw_axpy(rho_pw_r(ispin), rho_elec)
     287              :          END DO
     288           92 :          tot_rho_elec = pw_integrate_function(rho_elec)
     289              : 
     290              :          ! Calculate the dielectric (smoothed) function of rho_elec in r-space
     291           92 :          CALL auxbas_pw_pool%create_pw(eps_elec)
     292           92 :          CALL auxbas_pw_pool%create_pw(deps_elec)
     293              :          ! Relative permittivity or dielectric constant of the solvent (medium)
     294           92 :          epsilon_solvent = sccs_control%epsilon_solvent
     295          162 :          SELECT CASE (sccs_control%method_id)
     296              :          CASE (sccs_andreussi)
     297              :             CALL andreussi(rho_elec, eps_elec, deps_elec, epsilon_solvent, sccs_control%rho_max, &
     298           70 :                            sccs_control%rho_min)
     299              :          CASE (sccs_fattebert_gygi)
     300              :             CALL fattebert_gygi(rho_elec, eps_elec, deps_elec, epsilon_solvent, sccs_control%beta, &
     301           22 :                                 sccs_control%rho_zero)
     302              :          CASE DEFAULT
     303           92 :             CPABORT("Invalid method specified for SCCS model")
     304              :          END SELECT
     305              : 
     306              :          ! Optional output of the dielectric function in cube file format
     307           92 :          filename = "DIELECTRIC_FUNCTION"
     308           92 :          cube_path = TRIM(print_path)//"%"//TRIM(filename)
     309           92 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, input, TRIM(cube_path)), &
     310              :                    cp_p_file)) THEN
     311            4 :             append_cube = section_get_lval(input, TRIM(cube_path)//"%APPEND")
     312            4 :             my_pos_cube = "REWIND"
     313            4 :             IF (append_cube) my_pos_cube = "APPEND"
     314            4 :             mpi_io = .TRUE.
     315              :             cube_unit = cp_print_key_unit_nr(logger, input, TRIM(cube_path), &
     316              :                                              extension=".cube", middle_name=TRIM(filename), &
     317              :                                              file_position=my_pos_cube, log_filename=.FALSE., &
     318            4 :                                              mpi_io=mpi_io, fout=mpi_filename)
     319            4 :             IF (output_unit > 0) THEN
     320            2 :                IF (.NOT. mpi_io) THEN
     321            0 :                   INQUIRE (UNIT=cube_unit, NAME=filename)
     322              :                ELSE
     323            2 :                   filename = mpi_filename
     324              :                END IF
     325              :                WRITE (UNIT=output_unit, FMT="(T3,A)") &
     326            2 :                   "SCCS| The dielectric function is written in cube file format to the file:", &
     327            4 :                   "SCCS| "//TRIM(filename)
     328              :             END IF
     329              :             CALL cp_pw_to_cube(eps_elec, cube_unit, TRIM(filename), particles=particles, &
     330              :                                stride=section_get_ivals(input, TRIM(cube_path)//"%STRIDE"), &
     331            4 :                                mpi_io=mpi_io)
     332            4 :             CALL cp_print_key_finished_output(cube_unit, logger, input, TRIM(cube_path), mpi_io=mpi_io)
     333              :          END IF
     334              : 
     335              :          ! Calculate the (quantum) volume and surface of the solute cavity
     336           92 :          cavity_surface = 0.0_dp
     337           92 :          cavity_volume = 0.0_dp
     338              : 
     339           92 :          IF (ABS(epsilon_solvent - 1.0_dp) > epstol) THEN
     340              : 
     341              :             BLOCK
     342              :                TYPE(pw_r3d_rs_type) :: theta, norm_drho_elec
     343          368 :                TYPE(pw_r3d_rs_type), DIMENSION(3)                        :: drho_elec
     344           92 :                CALL auxbas_pw_pool%create_pw(theta)
     345           92 :                CALL pw_zero(theta)
     346              : 
     347              :                ! Calculate the (quantum) volume of the solute cavity
     348           92 :                f = 1.0_dp/(epsilon_solvent - 1.0_dp)
     349              : !$OMP    PARALLEL DO DEFAULT(NONE) &
     350              : !$OMP                PRIVATE(i,j,k) &
     351           92 : !$OMP                SHARED(epsilon_solvent,eps_elec,f,lb,theta,ub)
     352              :                DO k = lb(3), ub(3)
     353              :                   DO j = lb(2), ub(2)
     354              :                      DO i = lb(1), ub(1)
     355              :                         theta%array(i, j, k) = f*(epsilon_solvent - eps_elec%array(i, j, k))
     356              :                      END DO
     357              :                   END DO
     358              :                END DO
     359              : !$OMP    END PARALLEL DO
     360           92 :                cavity_volume = pw_integrate_function(theta)
     361              : 
     362              :                ! Calculate the derivative of the electronic density in r-space
     363              :                ! TODO: Could be retrieved from the QS environment
     364          368 :                DO i = 1, 3
     365          368 :                   CALL auxbas_pw_pool%create_pw(drho_elec(i))
     366              :                END DO
     367           92 :                CALL derive(rho_elec, drho_elec, sccs_derivative_fft, pw_env, input)
     368              : 
     369           92 :                CALL auxbas_pw_pool%create_pw(norm_drho_elec)
     370              : 
     371              :                ! Calculate the norm of the gradient of the electronic density in r-space
     372              : !$OMP    PARALLEL DO DEFAULT(NONE) &
     373              : !$OMP                PRIVATE(i,j,k) &
     374           92 : !$OMP                SHARED(drho_elec,lb,norm_drho_elec,ub)
     375              :                DO k = lb(3), ub(3)
     376              :                   DO j = lb(2), ub(2)
     377              :                      DO i = lb(1), ub(1)
     378              :                         norm_drho_elec%array(i, j, k) = SQRT(drho_elec(1)%array(i, j, k)* &
     379              :                                                              drho_elec(1)%array(i, j, k) + &
     380              :                                                              drho_elec(2)%array(i, j, k)* &
     381              :                                                              drho_elec(2)%array(i, j, k) + &
     382              :                                                              drho_elec(3)%array(i, j, k)* &
     383              :                                                              drho_elec(3)%array(i, j, k))
     384              :                      END DO
     385              :                   END DO
     386              :                END DO
     387              : !$OMP    END PARALLEL DO
     388              : 
     389              :                ! Optional output of the norm of the density gradient in cube file format
     390           92 :                filename = "DENSITY_GRADIENT"
     391           92 :                cube_path = TRIM(print_path)//"%"//TRIM(filename)
     392           92 :                IF (BTEST(cp_print_key_should_output(logger%iter_info, input, TRIM(cube_path)), &
     393              :                          cp_p_file)) THEN
     394            0 :                   append_cube = section_get_lval(input, TRIM(cube_path)//"%APPEND")
     395            0 :                   my_pos_cube = "REWIND"
     396            0 :                   IF (append_cube) my_pos_cube = "APPEND"
     397            0 :                   mpi_io = .TRUE.
     398              :                   cube_unit = cp_print_key_unit_nr(logger, input, TRIM(cube_path), &
     399              :                                                    extension=".cube", middle_name=TRIM(filename), &
     400              :                                                    file_position=my_pos_cube, log_filename=.FALSE., &
     401            0 :                                                    mpi_io=mpi_io, fout=mpi_filename)
     402            0 :                   IF (output_unit > 0) THEN
     403            0 :                      IF (.NOT. mpi_io) THEN
     404            0 :                         INQUIRE (UNIT=cube_unit, NAME=filename)
     405              :                      ELSE
     406            0 :                         filename = mpi_filename
     407              :                      END IF
     408              :                      WRITE (UNIT=output_unit, FMT="(T3,A)") &
     409            0 :                         "SCCS| The norm of the density gradient is written in cube file format to the file:", &
     410            0 :                         "SCCS| "//TRIM(filename)
     411              :                   END IF
     412              :                   CALL cp_pw_to_cube(norm_drho_elec, cube_unit, TRIM(filename), particles=particles, &
     413              :                                      stride=section_get_ivals(input, TRIM(cube_path)//"%STRIDE"), &
     414            0 :                                      mpi_io=mpi_io)
     415            0 :                   CALL cp_print_key_finished_output(cube_unit, logger, input, TRIM(cube_path), mpi_io=mpi_io)
     416              :                END IF
     417              : 
     418              :                ! Calculate the (quantum) surface of the solute cavity
     419          162 :                SELECT CASE (sccs_control%method_id)
     420              :                CASE (sccs_andreussi)
     421              :                   CALL surface_andreussi(rho_elec, norm_drho_elec, theta, epsilon_solvent, &
     422              :                                          sccs_control%rho_max, sccs_control%rho_min, &
     423           70 :                                          sccs_control%delta_rho)
     424              :                CASE (sccs_fattebert_gygi)
     425              :                   CALL surface_fattebert_gygi(rho_elec, norm_drho_elec, theta, epsilon_solvent, &
     426              :                                               sccs_control%beta, sccs_control%rho_zero, &
     427           22 :                                               sccs_control%delta_rho)
     428              :                CASE DEFAULT
     429           92 :                   CPABORT("Invalid method specified for SCCS model")
     430              :                END SELECT
     431           92 :                cavity_surface = pw_integrate_function(theta)
     432              : 
     433              :                ! Release storage
     434           92 :                CALL auxbas_pw_pool%give_back_pw(theta)
     435           92 :                CALL auxbas_pw_pool%give_back_pw(norm_drho_elec)
     436          460 :                DO i = 1, 3
     437          368 :                   CALL auxbas_pw_pool%give_back_pw(drho_elec(i))
     438              :                END DO
     439              :             END BLOCK
     440              : 
     441              :          END IF ! epsilon_solvent > 1
     442              : 
     443           92 :          CALL auxbas_pw_pool%give_back_pw(rho_elec)
     444              :       END BLOCK
     445              : 
     446              :       BLOCK
     447              :          TYPE(pw_r3d_rs_type) :: rho_tot, phi_tot, rho_solute, rho_tot_zero
     448              :          ! Retrieve the total charge density (core + elec) of the solute in r-space
     449           92 :          CALL auxbas_pw_pool%create_pw(rho_solute)
     450           92 :          CALL pw_zero(rho_solute)
     451           92 :          CALL pw_transfer(rho_tot_gspace, rho_solute)
     452           92 :          tot_rho_solute = pw_integrate_function(rho_solute)
     453              : 
     454              :          ! Check total charge
     455           92 :          IF (ABS(tot_rho_solute) >= 1.0E-6_dp) THEN
     456           92 :             IF ((poisson_env%parameters%solver /= pw_poisson_analytic) .AND. &
     457              :                 (poisson_env%parameters%solver /= pw_poisson_mt)) THEN
     458              :                WRITE (UNIT=message, FMT="(A,SP,F0.6,A)") &
     459           92 :                   "The system (solute) has a non-negligible charge of ", -tot_rho_solute, &
     460              :                   ". It is recommended to use non-periodic boundary conditions (PERIODIC none) "// &
     461          184 :                   "combined with an appropriate Poisson solver (POISSON_SOLVER MT or analytic)"
     462           92 :                CPWARN(message)
     463              :             END IF
     464              :          END IF
     465              : 
     466              :          ! Reassign work storage to rho_tot_zero, because rho_elec is no longer needed
     467           92 :          CALL auxbas_pw_pool%create_pw(rho_tot_zero)
     468              : 
     469              :          ! Build the initial (rho_iter = 0) total charge density (solute plus polarisation) in r-space
     470              :          ! eps_elec <- ln(eps_elec)
     471              : !$OMP PARALLEL DO DEFAULT(NONE) &
     472              : !$OMP             PRIVATE(i,j,k) &
     473              : !$OMP             SHARED(eps_elec,lb,message,output_unit,para_env,ub) &
     474           92 : !$OMP             SHARED(rho_solute,rho_tot_zero)
     475              :          DO k = lb(3), ub(3)
     476              :             DO j = lb(2), ub(2)
     477              :                DO i = lb(1), ub(1)
     478              :                   IF (eps_elec%array(i, j, k) < 1.0_dp) THEN
     479              :                      WRITE (UNIT=message, FMT="(A,ES12.3,A,3(I0,A))") &
     480              :                         "SCCS| Invalid dielectric function value ", eps_elec%array(i, j, k), &
     481              :                         " encountered at grid point (", i, ",", j, ",", k, ")"
     482              :                      CPABORT(message)
     483              :                   END IF
     484              :                   rho_tot_zero%array(i, j, k) = rho_solute%array(i, j, k)/eps_elec%array(i, j, k)
     485              :                   eps_elec%array(i, j, k) = LOG(eps_elec%array(i, j, k))
     486              :                END DO
     487              :             END DO
     488              :          END DO
     489              : !$OMP END PARALLEL DO
     490              : 
     491              :          ! Build the derivative of LOG(eps_elec)
     492          368 :          DO i = 1, 3
     493          276 :             CALL auxbas_pw_pool%create_pw(dln_eps_elec(i))
     494          368 :             CALL pw_zero(dln_eps_elec(i))
     495              :          END DO
     496           92 :          CALL derive(eps_elec, dln_eps_elec, sccs_control%derivative_method, pw_env, input)
     497           92 :          CALL auxbas_pw_pool%give_back_pw(eps_elec)
     498              : 
     499              :          ! Print header for the SCCS cycle
     500           92 :          IF (should_output .AND. (output_unit > 0)) THEN
     501           46 :             IF (print_level > low_print_level) THEN
     502              :                WRITE (UNIT=output_unit, FMT="(T3,A,T56,F25.12)") &
     503           46 :                   "SCCS| Total electronic charge density ", -tot_rho_elec, &
     504           92 :                   "SCCS| Total charge density (solute)   ", -tot_rho_solute
     505              :                WRITE (UNIT=output_unit, FMT="(T3,A,T56,F25.3)") &
     506           46 :                   "SCCS| Volume of the cell           [bohr^3]", cell_volume, &
     507           46 :                   "SCCS|                              [angstrom^3]", &
     508           92 :                   cp_unit_from_cp2k(cell_volume, "angstrom^3")
     509           46 :                IF (ABS(epsilon_solvent - 1.0_dp) > epstol) THEN
     510              :                   WRITE (UNIT=output_unit, FMT="(T3,A,T56,F25.3)") &
     511           46 :                      "SCCS| Volume of the solute cavity  [bohr^3]", cavity_volume, &
     512           46 :                      "SCCS|                              [angstrom^3]", &
     513           46 :                      cp_unit_from_cp2k(cavity_volume, "angstrom^3"), &
     514           46 :                      "SCCS| Surface of the solute cavity [bohr^2]", cavity_surface, &
     515           46 :                      "SCCS|                              [angstrom^2]", &
     516           92 :                      cp_unit_from_cp2k(cavity_surface, "angstrom^2")
     517              :                END IF
     518              :                WRITE (UNIT=output_unit, FMT="(T3,A)") &
     519           46 :                   "SCCS|", &
     520           92 :                   "SCCS|   Step    Average residual    Maximum residual         E(Hartree) [a.u.]"
     521              :             END IF
     522              :          END IF
     523              : 
     524              :          ! Get storage for the derivative of the total potential (field) in r-space
     525          368 :          DO i = 1, 3
     526          368 :             CALL auxbas_pw_pool%create_pw(dphi_tot(i))
     527              :          END DO
     528              : 
     529              :          ! Initialise the total charge density in r-space rho_tot with rho_tot_zero + rho_iter_zero
     530           92 :          CALL auxbas_pw_pool%create_pw(rho_tot)
     531           92 :          CALL pw_copy(rho_tot_zero, rho_tot)
     532           92 :          CALL pw_axpy(rho_pw_r_sccs, rho_tot)
     533              : 
     534           92 :          CALL auxbas_pw_pool%create_pw(phi_tot)
     535           92 :          CALL pw_zero(phi_tot)
     536              : 
     537              :          ! Main SCCS iteration loop
     538           92 :          iter = 0
     539              : 
     540              :          iter_loop: DO
     541              : 
     542              :             ! Increment iteration counter
     543          294 :             iter = iter + 1
     544              : 
     545              :             ! Check if the requested maximum number of SCCS iterations is reached
     546          294 :             IF (iter > sccs_control%max_iter) THEN
     547            0 :                IF (output_unit > 0) THEN
     548              :                   WRITE (UNIT=output_unit, FMT="(T3,A,/,T3,A,I0,A)") &
     549            0 :                      "SCCS| Maximum number of SCCS iterations reached", &
     550            0 :                      "SCCS| Iteration cycle did not converge in ", sccs_control%max_iter, " steps"
     551              :                ELSE
     552              :                   WRITE (UNIT=message, FMT="(A,I0,A)") &
     553            0 :                      "The SCCS iteration cycle did not converge in ", sccs_control%max_iter, " steps"
     554            0 :                   CPWARN(message)
     555              :                END IF
     556              :                EXIT iter_loop
     557              :             END IF
     558              : 
     559              :             ! Calculate derivative of the current total potential in r-space
     560              :             CALL pw_poisson_solve(poisson_env=poisson_env, &
     561              :                                   density=rho_tot, &
     562              :                                   vhartree=phi_tot, &
     563          294 :                                   dvhartree=dphi_tot)
     564          294 :             energy%sccs_hartree = 0.5_dp*pw_integral_ab(rho_solute, phi_tot)
     565              : 
     566              :             ! Update total charge density (solute plus polarisation) in r-space
     567              :             ! based on the iterated polarisation charge density
     568          294 :             f = 1.0_dp/fourpi
     569          294 :             rho_delta_avg = 0.0_dp
     570          294 :             rho_delta_max = 0.0_dp
     571              : !$OMP    PARALLEL DO DEFAULT(NONE) &
     572              : !$OMP                PRIVATE(i,j,k,rho_delta,rho_iter_new) &
     573              : !$OMP                SHARED(dln_eps_elec,dphi_tot,f,lb,rho_pw_r_sccs,ub) &
     574              : !$OMP                SHARED(rho_tot,rho_tot_zero,sccs_control) &
     575              : !$OMP                REDUCTION(+:rho_delta_avg) &
     576          294 : !$OMP                REDUCTION(MAX:rho_delta_max)
     577              :             DO k = lb(3), ub(3)
     578              :                DO j = lb(2), ub(2)
     579              :                   DO i = lb(1), ub(1)
     580              :                      rho_iter_new = (dln_eps_elec(1)%array(i, j, k)*dphi_tot(1)%array(i, j, k) + &
     581              :                                      dln_eps_elec(2)%array(i, j, k)*dphi_tot(2)%array(i, j, k) + &
     582              :                                      dln_eps_elec(3)%array(i, j, k)*dphi_tot(3)%array(i, j, k))*f
     583              :                      rho_iter_new = rho_pw_r_sccs%array(i, j, k) + &
     584              :                                     sccs_control%mixing*(rho_iter_new - rho_pw_r_sccs%array(i, j, k))
     585              :                      rho_delta = ABS(rho_iter_new - rho_pw_r_sccs%array(i, j, k))
     586              :                      rho_delta_max = MAX(rho_delta, rho_delta_max)
     587              :                      rho_delta_avg = rho_delta_avg + rho_delta
     588              :                      rho_tot%array(i, j, k) = rho_tot_zero%array(i, j, k) + rho_iter_new
     589              :                      rho_pw_r_sccs%array(i, j, k) = rho_iter_new
     590              :                   END DO
     591              :                END DO
     592              :             END DO
     593              : !$OMP    END PARALLEL DO
     594              : 
     595          294 :             CALL para_env%sum(rho_delta_avg)
     596          294 :             rho_delta_avg = rho_delta_avg/REAL(ngpts, KIND=dp)
     597          294 :             CALL para_env%max(rho_delta_max)
     598              : 
     599          294 :             IF (should_output .AND. (output_unit > 0)) THEN
     600          147 :                IF (print_level > low_print_level) THEN
     601          147 :                   IF ((ABS(rho_delta_avg) < 1.0E-8_dp) .OR. &
     602          147 :                       (ABS(rho_delta_avg) >= 1.0E5_dp)) THEN
     603              :                      WRITE (UNIT=output_unit, FMT="(T3,A,I6,4X,ES16.4,4X,ES16.4,1X,F25.12)") &
     604            0 :                         "SCCS| ", iter, rho_delta_avg, rho_delta_max, energy%sccs_hartree
     605              :                   ELSE
     606              :                      WRITE (UNIT=output_unit, FMT="(T3,A,I6,4X,F16.8,4X,F16.8,1X,F25.12)") &
     607          147 :                         "SCCS| ", iter, rho_delta_avg, rho_delta_max, energy%sccs_hartree
     608              :                   END IF
     609              :                END IF
     610              :             END IF
     611              : 
     612              :             ! Check if the SCCS iteration cycle is converged to the requested tolerance
     613          294 :             IF (rho_delta_max <= sccs_control%eps_sccs) THEN
     614           92 :                IF (should_output .AND. (output_unit > 0)) THEN
     615              :                   WRITE (UNIT=output_unit, FMT="(T3,A,I0,A)") &
     616           46 :                      "SCCS| Iteration cycle converged in ", iter, " steps"
     617              :                END IF
     618              :                EXIT iter_loop
     619              :             END IF
     620              : 
     621              :          END DO iter_loop
     622              : 
     623              :          ! Release work storage which is no longer needed
     624           92 :          CALL auxbas_pw_pool%give_back_pw(rho_tot_zero)
     625          368 :          DO i = 1, 3
     626          368 :             CALL auxbas_pw_pool%give_back_pw(dln_eps_elec(i))
     627              :          END DO
     628              : 
     629              :          ! Optional output of the total charge density in cube file format
     630           92 :          filename = "TOTAL_CHARGE_DENSITY"
     631           92 :          cube_path = TRIM(print_path)//"%"//TRIM(filename)
     632           92 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, input, TRIM(cube_path)), cp_p_file)) THEN
     633            0 :             append_cube = section_get_lval(input, TRIM(cube_path)//"%APPEND")
     634            0 :             my_pos_cube = "REWIND"
     635            0 :             IF (append_cube) my_pos_cube = "APPEND"
     636            0 :             mpi_io = .TRUE.
     637              :             cube_unit = cp_print_key_unit_nr(logger, input, TRIM(cube_path), &
     638              :                                              extension=".cube", middle_name=TRIM(filename), &
     639              :                                              file_position=my_pos_cube, log_filename=.FALSE., &
     640            0 :                                              mpi_io=mpi_io, fout=mpi_filename)
     641            0 :             IF (output_unit > 0) THEN
     642            0 :                IF (.NOT. mpi_io) THEN
     643            0 :                   INQUIRE (UNIT=cube_unit, NAME=filename)
     644              :                ELSE
     645            0 :                   filename = mpi_filename
     646              :                END IF
     647              :                WRITE (UNIT=output_unit, FMT="(T3,A)") &
     648            0 :                   "SCCS| The total SCCS charge density is written in cube file format to the file:", &
     649            0 :                   "SCCS| "//TRIM(filename)
     650              :             END IF
     651              :             CALL cp_pw_to_cube(rho_tot, cube_unit, TRIM(filename), particles=particles, &
     652            0 :                                stride=section_get_ivals(input, TRIM(cube_path)//"%STRIDE"), mpi_io=mpi_io)
     653            0 :             CALL cp_print_key_finished_output(cube_unit, logger, input, TRIM(cube_path), mpi_io=mpi_io)
     654              :          END IF
     655              : 
     656              :          ! Calculate the total SCCS Hartree energy, potential, and its
     657              :          ! derivatives of the solute and the implicit solvent
     658           92 :          CALL pw_transfer(rho_tot, rho_tot_gspace)
     659           92 :          IF (calculate_stress_tensor) THEN
     660              :             ! Request also the calculation of the stress tensor contribution
     661              :             CALL pw_poisson_solve(poisson_env=poisson_env, &
     662              :                                   density=rho_tot_gspace, &
     663              :                                   ehartree=e_tot, &
     664              :                                   vhartree=v_hartree_gspace, &
     665              :                                   dvhartree=dphi_tot, &
     666            0 :                                   h_stress=h_stress)
     667              :          ELSE
     668              :             CALL pw_poisson_solve(poisson_env=poisson_env, &
     669              :                                   density=rho_tot_gspace, &
     670              :                                   ehartree=e_tot, &
     671              :                                   vhartree=v_hartree_gspace, &
     672           92 :                                   dvhartree=dphi_tot)
     673              :          END IF
     674           92 :          CALL pw_transfer(v_hartree_gspace, phi_tot)
     675           92 :          energy%sccs_hartree = 0.5_dp*pw_integral_ab(rho_solute, phi_tot)
     676              : 
     677              :          ! Calculate the Hartree energy and potential of the solute only
     678              :          BLOCK
     679              :             TYPE(pw_r3d_rs_type) :: phi_solute
     680           92 :             CALL auxbas_pw_pool%create_pw(phi_solute)
     681           92 :             CALL pw_zero(phi_solute)
     682              :             CALL pw_poisson_solve(poisson_env=poisson_env, &
     683              :                                   density=rho_solute, &
     684              :                                   ehartree=energy%hartree, &
     685           92 :                                   vhartree=phi_solute)
     686              : 
     687              :             ! Calculate the polarisation potential (store it in phi_tot)
     688              :             ! phi_pol = phi_tot - phi_solute
     689           92 :             CALL pw_axpy(phi_solute, phi_tot, alpha=-1.0_dp)
     690           92 :             CALL auxbas_pw_pool%give_back_pw(phi_solute)
     691              :          END BLOCK
     692              : 
     693              :          ! Optional output of the SCCS polarisation potential in cube file format
     694           92 :          filename = "POLARISATION_POTENTIAL"
     695           92 :          cube_path = TRIM(print_path)//"%"//TRIM(filename)
     696           92 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, input, TRIM(cube_path)), &
     697              :                    cp_p_file)) THEN
     698            4 :             append_cube = section_get_lval(input, TRIM(cube_path)//"%APPEND")
     699            4 :             my_pos_cube = "REWIND"
     700            4 :             IF (append_cube) my_pos_cube = "APPEND"
     701            4 :             mpi_io = .TRUE.
     702              :             cube_unit = cp_print_key_unit_nr(logger, input, TRIM(cube_path), &
     703              :                                              extension=".cube", middle_name=TRIM(filename), &
     704              :                                              file_position=my_pos_cube, log_filename=.FALSE., &
     705            4 :                                              mpi_io=mpi_io, fout=mpi_filename)
     706            4 :             IF (output_unit > 0) THEN
     707            2 :                IF (.NOT. mpi_io) THEN
     708            0 :                   INQUIRE (UNIT=cube_unit, NAME=filename)
     709              :                ELSE
     710            2 :                   filename = mpi_filename
     711              :                END IF
     712              :                WRITE (UNIT=output_unit, FMT="(T3,A)") &
     713            2 :                   "SCCS| The SCCS polarisation potential is written in cube file format to the file:", &
     714            4 :                   "SCCS| "//TRIM(filename)
     715              :             END IF
     716              :             CALL cp_pw_to_cube(phi_tot, cube_unit, TRIM(filename), particles=particles, &
     717            4 :                                stride=section_get_ivals(input, TRIM(cube_path)//"%STRIDE"), mpi_io=mpi_io)
     718            4 :             CALL cp_print_key_finished_output(cube_unit, logger, input, TRIM(cube_path), mpi_io=mpi_io)
     719              :          END IF
     720              : 
     721              :          ! Calculate the polarisation charge (store it in rho_tot)
     722              :          ! rho_pol = rho_tot - rho_solute
     723           92 :          CALL pw_axpy(rho_solute, rho_tot, alpha=-1.0_dp)
     724           92 :          polarisation_charge = pw_integrate_function(rho_tot)
     725              : 
     726              :          ! Optional output of the SCCS polarisation charge in cube file format
     727           92 :          filename = "POLARISATION_CHARGE_DENSITY"
     728           92 :          cube_path = TRIM(print_path)//"%"//TRIM(filename)
     729           92 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, input, TRIM(cube_path)), &
     730              :                    cp_p_file)) THEN
     731            0 :             append_cube = section_get_lval(input, TRIM(cube_path)//"%APPEND")
     732            0 :             my_pos_cube = "REWIND"
     733            0 :             IF (append_cube) my_pos_cube = "APPEND"
     734            0 :             mpi_io = .TRUE.
     735              :             cube_unit = cp_print_key_unit_nr(logger, input, TRIM(cube_path), &
     736              :                                              extension=".cube", middle_name=TRIM(filename), &
     737              :                                              file_position=my_pos_cube, log_filename=.FALSE., &
     738            0 :                                              mpi_io=mpi_io, fout=mpi_filename)
     739            0 :             IF (output_unit > 0) THEN
     740            0 :                IF (.NOT. mpi_io) THEN
     741            0 :                   INQUIRE (UNIT=cube_unit, NAME=filename)
     742              :                ELSE
     743            0 :                   filename = mpi_filename
     744              :                END IF
     745              :                WRITE (UNIT=output_unit, FMT="(T3,A)") &
     746            0 :                   "SCCS| The SCCS polarisation charge density is written in cube file format to the file:", &
     747            0 :                   "SCCS| "//TRIM(filename)
     748              :             END IF
     749              :             CALL cp_pw_to_cube(rho_tot, cube_unit, TRIM(filename), particles=particles, &
     750            0 :                                stride=section_get_ivals(input, TRIM(cube_path)//"%STRIDE"), mpi_io=mpi_io)
     751            0 :             CALL cp_print_key_finished_output(cube_unit, logger, input, TRIM(cube_path), mpi_io=mpi_io)
     752              :          END IF
     753              : 
     754              :          ! Calculate SCCS polarisation energy
     755           92 :          energy%sccs_pol = 0.5_dp*pw_integral_ab(rho_solute, phi_tot)
     756           92 :          CALL auxbas_pw_pool%give_back_pw(rho_solute)
     757           92 :          CALL auxbas_pw_pool%give_back_pw(phi_tot)
     758          184 :          CALL auxbas_pw_pool%give_back_pw(rho_tot)
     759              :       END BLOCK
     760              : 
     761              :       ! Calculate additional solvation terms
     762           92 :       energy%sccs_cav = sccs_control%gamma_solvent*cavity_surface
     763           92 :       energy%sccs_dis = sccs_control%beta_solvent*cavity_volume
     764           92 :       energy%sccs_rep = sccs_control%alpha_solvent*cavity_surface
     765              :       ! Calculate solvation free energy: \delta G^el + (alpha + gamma)*S + beta*V
     766           92 :       energy%sccs_sol = energy%sccs_pol + energy%sccs_rep + energy%sccs_cav + energy%sccs_dis
     767              : 
     768           92 :       IF (should_output .AND. (output_unit > 0)) THEN
     769              :          WRITE (UNIT=output_unit, FMT="(T3,A)") &
     770           46 :             "SCCS|"
     771              :          WRITE (UNIT=output_unit, FMT="(T3,A,T56,F25.12)") &
     772           46 :             "SCCS| Polarisation charge", polarisation_charge
     773              :          !MK   "SCCS| Total interaction energy [a.u.]", e_tot
     774              :          WRITE (UNIT=output_unit, FMT="(T3,A)") &
     775           46 :             "SCCS|"
     776           46 :          CALL print_sccs_results(energy, sccs_control, output_unit)
     777              :       END IF
     778              : 
     779              :       ! Calculate SCCS contribution to the Kohn-Sham potential
     780           92 :       f = -0.5_dp*dvol/fourpi
     781              : !$OMP PARALLEL DO DEFAULT(NONE) &
     782              : !$OMP             PRIVATE(dphi2,i,j,k) &
     783              : !$OMP             SHARED(f,deps_elec,dphi_tot) &
     784           92 : !$OMP             SHARED(lb,ub,v_sccs)
     785              :       DO k = lb(3), ub(3)
     786              :          DO j = lb(2), ub(2)
     787              :             DO i = lb(1), ub(1)
     788              :                dphi2 = dphi_tot(1)%array(i, j, k)*dphi_tot(1)%array(i, j, k) + &
     789              :                        dphi_tot(2)%array(i, j, k)*dphi_tot(2)%array(i, j, k) + &
     790              :                        dphi_tot(3)%array(i, j, k)*dphi_tot(3)%array(i, j, k)
     791              :                v_sccs%array(i, j, k) = v_sccs%array(i, j, k) + f*deps_elec%array(i, j, k)*dphi2
     792              :             END DO
     793              :          END DO
     794              :       END DO
     795              : !$OMP END PARALLEL DO
     796              : 
     797           92 :       CALL auxbas_pw_pool%give_back_pw(deps_elec)
     798          368 :       DO i = 1, 3
     799          368 :          CALL auxbas_pw_pool%give_back_pw(dphi_tot(i))
     800              :       END DO
     801              : 
     802              :       ! Release the SCCS printout environment
     803              :       CALL cp_print_key_finished_output(output_unit, logger, input, TRIM(print_path), &
     804           92 :                                         ignore_should_output=should_output)
     805              : 
     806           92 :       CALL timestop(handle)
     807              : 
     808          264 :    END SUBROUTINE sccs
     809              : 
     810              : ! **************************************************************************************************
     811              : !> \brief      Calculate the smoothed dielectric function of Andreussi et al.
     812              : !> \param rho_elec ...
     813              : !> \param eps_elec ...
     814              : !> \param deps_elec ...
     815              : !> \param epsilon_solvent ...
     816              : !> \param rho_max ...
     817              : !> \param rho_min ...
     818              : !> \par History:
     819              : !>      - Creation (16.10.2013,MK)
     820              : !>      - Finite difference of isosurfaces implemented (21.12.2013,MK)
     821              : !> \author     Matthias Krack (MK)
     822              : !> \version    1.1
     823              : ! **************************************************************************************************
     824           70 :    SUBROUTINE andreussi(rho_elec, eps_elec, deps_elec, epsilon_solvent, rho_max, &
     825              :                         rho_min)
     826              : 
     827              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: rho_elec, eps_elec, deps_elec
     828              :       REAL(KIND=dp), INTENT(IN)                          :: epsilon_solvent, rho_max, rho_min
     829              : 
     830              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'andreussi'
     831              :       REAL(KIND=dp), PARAMETER                           :: rhotol = 1.0E-12_dp
     832              : 
     833              :       INTEGER                                            :: handle, i, j, k
     834              :       INTEGER, DIMENSION(3)                              :: lb, ub
     835              :       REAL(KIND=dp)                                      :: diff, dq, dt, f, ln_rho_max, ln_rho_min, &
     836              :                                                             q, rho, t, x, y
     837              : 
     838           70 :       CALL timeset(routineN, handle)
     839              : 
     840           70 :       f = LOG(epsilon_solvent)/twopi
     841           70 :       diff = rho_max - rho_min
     842           70 :       IF (diff < SQRT(rhotol)) CPABORT("SCCS: Difference between rho(min) and rho(max) is too small")
     843           70 :       IF (rho_min >= rhotol) THEN
     844           70 :          ln_rho_max = LOG(rho_max)
     845           70 :          ln_rho_min = LOG(rho_min)
     846           70 :          q = twopi/(ln_rho_max - ln_rho_min)
     847           70 :          dq = -f*q
     848              :       END IF
     849              : 
     850          280 :       lb(1:3) = rho_elec%pw_grid%bounds_local(1, 1:3)
     851          280 :       ub(1:3) = rho_elec%pw_grid%bounds_local(2, 1:3)
     852              : 
     853              :       ! Calculate the dielectric function and its derivative
     854              : !$OMP PARALLEL DO DEFAULT(NONE) &
     855              : !$OMP             PRIVATE(dt,i,j,k,rho,t,x,y) &
     856              : !$OMP             SHARED(deps_elec,dq,eps_elec,epsilon_solvent,f,lb,ub) &
     857           70 : !$OMP             SHARED(ln_rho_max,rho_elec,q,rho_max,rho_min)
     858              :       DO k = lb(3), ub(3)
     859              :          DO j = lb(2), ub(2)
     860              :             DO i = lb(1), ub(1)
     861              :                rho = rho_elec%array(i, j, k)
     862              :                IF (rho < rho_min) THEN
     863              :                   eps_elec%array(i, j, k) = epsilon_solvent
     864              :                   deps_elec%array(i, j, k) = 0.0_dp
     865              :                ELSE IF (rho <= rho_max) THEN
     866              :                   x = LOG(rho)
     867              :                   y = q*(ln_rho_max - x)
     868              :                   t = f*(y - SIN(y))
     869              :                   eps_elec%array(i, j, k) = EXP(t)
     870              :                   dt = dq*(1.0_dp - COS(y))
     871              :                   deps_elec%array(i, j, k) = eps_elec%array(i, j, k)*dt/rho
     872              :                ELSE
     873              :                   eps_elec%array(i, j, k) = 1.0_dp
     874              :                   deps_elec%array(i, j, k) = 0.0_dp
     875              :                END IF
     876              :             END DO
     877              :          END DO
     878              :       END DO
     879              : !$OMP END PARALLEL DO
     880              : 
     881           70 :       CALL timestop(handle)
     882              : 
     883           70 :    END SUBROUTINE andreussi
     884              : 
     885              : ! **************************************************************************************************
     886              : !> \brief      Calculate the smoothed dielectric function of Fattebert and Gygi
     887              : !> \param rho_elec ...
     888              : !> \param eps_elec ...
     889              : !> \param deps_elec ...
     890              : !> \param epsilon_solvent ...
     891              : !> \param beta ...
     892              : !> \param rho_zero ...
     893              : !> \par History:
     894              : !>      - Creation (15.10.2013,MK)
     895              : !> \author     Matthias Krack (MK)
     896              : !> \version    1.0
     897              : ! **************************************************************************************************
     898           22 :    SUBROUTINE fattebert_gygi(rho_elec, eps_elec, deps_elec, epsilon_solvent, beta, &
     899              :                              rho_zero)
     900              : 
     901              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: rho_elec, eps_elec, deps_elec
     902              :       REAL(KIND=dp), INTENT(IN)                          :: epsilon_solvent, beta, rho_zero
     903              : 
     904              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'fattebert_gygi'
     905              :       REAL(KIND=dp), PARAMETER                           :: rhotol = 1.0E-12_dp
     906              : 
     907              :       INTEGER                                            :: handle, i, j, k
     908              :       INTEGER, DIMENSION(3)                              :: lb, ub
     909              :       REAL(KIND=dp)                                      :: df, f, p, q, rho, s, t, twobeta
     910              : 
     911           22 :       CALL timeset(routineN, handle)
     912              : 
     913           22 :       df = (1.0_dp - epsilon_solvent)/rho_zero
     914           22 :       f = 0.5_dp*(epsilon_solvent - 1.0_dp)
     915           22 :       q = 1.0_dp/rho_zero
     916           22 :       twobeta = 2.0_dp*beta
     917              : 
     918           88 :       lb(1:3) = rho_elec%pw_grid%bounds_local(1, 1:3)
     919           88 :       ub(1:3) = rho_elec%pw_grid%bounds_local(2, 1:3)
     920              : 
     921              :       ! Calculate the smoothed dielectric function and its derivative
     922              : !$OMP PARALLEL DO DEFAULT(NONE) &
     923              : !$OMP             PRIVATE(i,j,k,p,rho,s,t) &
     924              : !$OMP             SHARED(df,deps_elec,eps_elec,epsilon_solvent,f,lb,ub) &
     925           22 : !$OMP             SHARED(q,rho_elec,twobeta)
     926              :       DO k = lb(3), ub(3)
     927              :          DO j = lb(2), ub(2)
     928              :             DO i = lb(1), ub(1)
     929              :                rho = rho_elec%array(i, j, k)
     930              :                IF (rho < rhotol) THEN
     931              :                   eps_elec%array(i, j, k) = epsilon_solvent
     932              :                   deps_elec%array(i, j, k) = 0.0_dp
     933              :                ELSE
     934              :                   s = rho*q
     935              :                   p = s**twobeta
     936              :                   t = 1.0_dp/(1.0_dp + p)
     937              :                   eps_elec%array(i, j, k) = 1.0_dp + f*(1.0_dp + (1.0_dp - p)*t)
     938              :                   deps_elec%array(i, j, k) = df*twobeta*t*t*p/s
     939              :                END IF
     940              :             END DO
     941              :          END DO
     942              :       END DO
     943              : !$OMP END PARALLEL DO
     944              : 
     945           22 :       CALL timestop(handle)
     946              : 
     947           22 :    END SUBROUTINE fattebert_gygi
     948              : 
     949              : ! **************************************************************************************************
     950              : !> \brief      Build the numerical derivative of a function on realspace grid
     951              : !> \param f ...
     952              : !> \param df ...
     953              : !> \param method ...
     954              : !> \param pw_env ...
     955              : !> \param input ...
     956              : !> \par History:
     957              : !>      - Creation (15.11.2013,MK)
     958              : !> \author     Matthias Krack (MK)
     959              : !> \version    1.0
     960              : ! **************************************************************************************************
     961          184 :    SUBROUTINE derive(f, df, method, pw_env, input)
     962              : 
     963              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: f
     964              :       TYPE(pw_r3d_rs_type), DIMENSION(3), INTENT(INOUT)  :: df
     965              :       INTEGER, INTENT(IN)                                :: method
     966              :       TYPE(pw_env_type), POINTER                         :: pw_env
     967              :       TYPE(section_vals_type), POINTER                   :: input
     968              : 
     969              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'derive'
     970              : 
     971              :       INTEGER                                            :: border_points, handle, i
     972              :       INTEGER, DIMENSION(3)                              :: lb, n, ub
     973          552 :       TYPE(pw_c1d_gs_type), DIMENSION(2)                 :: work_g1d
     974              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     975              :       TYPE(realspace_grid_desc_type), POINTER            :: rs_desc
     976              :       TYPE(realspace_grid_input_type)                    :: input_settings
     977              :       TYPE(realspace_grid_type), POINTER                 :: rs_grid
     978              :       TYPE(section_vals_type), POINTER                   :: rs_grid_section
     979              : 
     980          184 :       CALL timeset(routineN, handle)
     981              : 
     982          184 :       CPASSERT(ASSOCIATED(pw_env))
     983              : 
     984              :       ! Perform method specific setup
     985          262 :       SELECT CASE (method)
     986              :       CASE (sccs_derivative_cd3, sccs_derivative_cd5, sccs_derivative_cd7)
     987           78 :          NULLIFY (rs_desc)
     988           78 :          rs_grid_section => section_vals_get_subs_vals(input, "DFT%MGRID%RS_GRID")
     989            0 :          SELECT CASE (method)
     990              :          CASE (sccs_derivative_cd3)
     991            0 :             border_points = 1
     992              :          CASE (sccs_derivative_cd5)
     993           78 :             border_points = 2
     994              :          CASE (sccs_derivative_cd7)
     995           78 :             border_points = 3
     996              :          END SELECT
     997              :          CALL init_input_type(input_settings, 2*border_points + 1, rs_grid_section, &
     998           78 :                               1, [-1, -1, -1])
     999              :          CALL rs_grid_create_descriptor(rs_desc, f%pw_grid, input_settings, &
    1000           78 :                                         border_points=border_points)
    1001         1638 :          ALLOCATE (rs_grid)
    1002           78 :          CALL rs_grid_create(rs_grid, rs_desc)
    1003              : !MK      CALL rs_grid_print(rs_grid, 6)
    1004              :       CASE (sccs_derivative_fft)
    1005          424 :          lb(1:3) = f%pw_grid%bounds_local(1, 1:3)
    1006          424 :          ub(1:3) = f%pw_grid%bounds_local(2, 1:3)
    1007          106 :          NULLIFY (auxbas_pw_pool)
    1008          106 :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
    1009              :          ! Get work storage for the 1d grids in g-space (derivative calculation)
    1010          502 :          DO i = 1, SIZE(work_g1d)
    1011          318 :             CALL auxbas_pw_pool%create_pw(work_g1d(i))
    1012              :          END DO
    1013              :       END SELECT
    1014              : 
    1015              :       ! Calculate the derivatives
    1016            0 :       SELECT CASE (method)
    1017              :       CASE (sccs_derivative_cd3)
    1018            0 :          CALL derive_fdm_cd3(f, df, rs_grid)
    1019              :       CASE (sccs_derivative_cd5)
    1020           78 :          CALL derive_fdm_cd5(f, df, rs_grid)
    1021              :       CASE (sccs_derivative_cd7)
    1022            0 :          CALL derive_fdm_cd7(f, df, rs_grid)
    1023              :       CASE (sccs_derivative_fft)
    1024              :          ! FFT
    1025          106 :          CALL pw_transfer(f, work_g1d(1))
    1026          424 :          DO i = 1, 3
    1027          318 :             n(:) = 0
    1028          318 :             n(i) = 1
    1029          318 :             CALL pw_copy(work_g1d(1), work_g1d(2))
    1030          318 :             CALL pw_derive(work_g1d(2), n(:))
    1031          424 :             CALL pw_transfer(work_g1d(2), df(i))
    1032              :          END DO
    1033              :       CASE DEFAULT
    1034          184 :          CPABORT("Invalid derivative method for SCCS specified")
    1035              :       END SELECT
    1036              : 
    1037              :       ! Perform method specific cleanup
    1038           78 :       SELECT CASE (method)
    1039              :       CASE (sccs_derivative_cd3, sccs_derivative_cd5, sccs_derivative_cd7)
    1040           78 :          CALL rs_grid_release(rs_grid)
    1041           78 :          DEALLOCATE (rs_grid)
    1042           78 :          CALL rs_grid_release_descriptor(rs_desc)
    1043              :       CASE (sccs_derivative_fft)
    1044          502 :          DO i = 1, SIZE(work_g1d)
    1045          318 :             CALL auxbas_pw_pool%give_back_pw(work_g1d(i))
    1046              :          END DO
    1047              :       END SELECT
    1048              : 
    1049          184 :       CALL timestop(handle)
    1050              : 
    1051          736 :    END SUBROUTINE derive
    1052              : 
    1053              : ! **************************************************************************************************
    1054              : !> \brief      Calculate the finite difference between two isosurfaces of the
    1055              : !>             electronic density. The smoothed dielectric function of
    1056              : !>             Andreussi et al. is used as switching function eventually
    1057              : !>             defining the quantum volume and surface of the cavity.
    1058              : !> \param rho_elec ...
    1059              : !> \param norm_drho_elec ...
    1060              : !> \param dtheta ...
    1061              : !> \param epsilon_solvent ...
    1062              : !> \param rho_max ...
    1063              : !> \param rho_min ...
    1064              : !> \param delta_rho ...
    1065              : !> \par History:
    1066              : !>      - Creation (21.12.2013,MK)
    1067              : !> \author     Matthias Krack (MK)
    1068              : !> \version    1.0
    1069              : ! **************************************************************************************************
    1070           70 :    SUBROUTINE surface_andreussi(rho_elec, norm_drho_elec, dtheta, &
    1071              :                                 epsilon_solvent, rho_max, rho_min, delta_rho)
    1072              : 
    1073              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: rho_elec, norm_drho_elec, dtheta
    1074              :       REAL(KIND=dp), INTENT(IN)                          :: epsilon_solvent, rho_max, rho_min, &
    1075              :                                                             delta_rho
    1076              : 
    1077              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'surface_andreussi'
    1078              :       REAL(KIND=dp), PARAMETER                           :: rhotol = 1.0E-12_dp
    1079              : 
    1080              :       INTEGER                                            :: handle, i, j, k, l
    1081              :       INTEGER, DIMENSION(3)                              :: lb, ub
    1082              :       REAL(KIND=dp)                                      :: diff, e, eps_elec, f, ln_rho_max, &
    1083              :                                                             ln_rho_min, q, rho, t, x, y
    1084              :       REAL(KIND=dp), DIMENSION(2)                        :: theta
    1085              : 
    1086           70 :       CALL timeset(routineN, handle)
    1087              : 
    1088           70 :       e = epsilon_solvent - 1.0_dp
    1089           70 :       f = LOG(epsilon_solvent)/twopi
    1090           70 :       diff = rho_max - rho_min
    1091           70 :       IF (diff < SQRT(rhotol)) CPABORT("SCCS: Difference between rho(min) and rho(max) is too small")
    1092           70 :       IF (rho_min >= rhotol) THEN
    1093           70 :          ln_rho_max = LOG(rho_max)
    1094           70 :          ln_rho_min = LOG(rho_min)
    1095           70 :          q = twopi/(ln_rho_max - ln_rho_min)
    1096              :       END IF
    1097              : 
    1098          280 :       lb(1:3) = rho_elec%pw_grid%bounds_local(1, 1:3)
    1099          280 :       ub(1:3) = rho_elec%pw_grid%bounds_local(2, 1:3)
    1100              : 
    1101              :       ! Calculate finite difference between two isosurfaces
    1102              : !$OMP PARALLEL DO DEFAULT(NONE) &
    1103              : !$OMP             PRIVATE(eps_elec,i,j,k,l,rho,t,theta,x,y) &
    1104              : !$OMP             SHARED(delta_rho,dtheta,e,epsilon_solvent,f,lb) &
    1105           70 : !$OMP             SHARED(ln_rho_max,norm_drho_elec,rho_elec,q,rho_max,rho_min,ub)
    1106              :       DO k = lb(3), ub(3)
    1107              :          DO j = lb(2), ub(2)
    1108              :             DO i = lb(1), ub(1)
    1109              :                DO l = 1, 2
    1110              :                   rho = rho_elec%array(i, j, k) + (REAL(l, KIND=dp) - 1.5_dp)*delta_rho
    1111              :                   IF (rho < rho_min) THEN
    1112              :                      eps_elec = epsilon_solvent
    1113              :                   ELSE IF (rho <= rho_max) THEN
    1114              :                      x = LOG(rho)
    1115              :                      y = q*(ln_rho_max - x)
    1116              :                      t = f*(y - SIN(y))
    1117              :                      eps_elec = EXP(t)
    1118              :                   ELSE
    1119              :                      eps_elec = 1.0_dp
    1120              :                   END IF
    1121              :                   theta(l) = (epsilon_solvent - eps_elec)/e
    1122              :                END DO
    1123              :                dtheta%array(i, j, k) = (theta(2) - theta(1))*norm_drho_elec%array(i, j, k)/delta_rho
    1124              :             END DO
    1125              :          END DO
    1126              :       END DO
    1127              : !$OMP END PARALLEL DO
    1128              : 
    1129           70 :       CALL timestop(handle)
    1130              : 
    1131           70 :    END SUBROUTINE surface_andreussi
    1132              : 
    1133              : ! **************************************************************************************************
    1134              : !> \brief      Calculate the finite difference between two isosurfaces of the
    1135              : !>             the electronic density. The smoothed dielectric function of
    1136              : !>             Fattebert and Gygi is used as switching function eventually
    1137              : !>             defining the quantum volume and surface of the cavity.
    1138              : !> \param rho_elec ...
    1139              : !> \param norm_drho_elec ...
    1140              : !> \param dtheta ...
    1141              : !> \param epsilon_solvent ...
    1142              : !> \param beta ...
    1143              : !> \param rho_zero ...
    1144              : !> \param delta_rho ...
    1145              : !> \par History:
    1146              : !>      - Creation (21.12.2013,MK)
    1147              : !> \author     Matthias Krack (MK)
    1148              : !> \version    1.0
    1149              : ! **************************************************************************************************
    1150           22 :    SUBROUTINE surface_fattebert_gygi(rho_elec, norm_drho_elec, dtheta, &
    1151              :                                      epsilon_solvent, beta, rho_zero, delta_rho)
    1152              : 
    1153              :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: rho_elec, norm_drho_elec, dtheta
    1154              :       REAL(KIND=dp), INTENT(IN)                          :: epsilon_solvent, beta, rho_zero, &
    1155              :                                                             delta_rho
    1156              : 
    1157              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'surface_fattebert_gygi'
    1158              :       REAL(KIND=dp), PARAMETER                           :: rhotol = 1.0E-12_dp
    1159              : 
    1160              :       INTEGER                                            :: handle, i, j, k, l
    1161              :       INTEGER, DIMENSION(3)                              :: lb, ub
    1162              :       REAL(KIND=dp)                                      :: e, eps_elec, f, p, q, rho, s, t, twobeta
    1163              :       REAL(KIND=dp), DIMENSION(2)                        :: theta
    1164              : 
    1165           22 :       CALL timeset(routineN, handle)
    1166              : 
    1167           22 :       e = epsilon_solvent - 1.0_dp
    1168           22 :       f = 0.5_dp*e
    1169           22 :       q = 1.0_dp/rho_zero
    1170           22 :       twobeta = 2.0_dp*beta
    1171              : 
    1172           88 :       lb(1:3) = rho_elec%pw_grid%bounds_local(1, 1:3)
    1173           88 :       ub(1:3) = rho_elec%pw_grid%bounds_local(2, 1:3)
    1174              : 
    1175              :       ! Calculate finite difference between two isosurfaces
    1176              : !$OMP PARALLEL DO DEFAULT(NONE) &
    1177              : !$OMP             PRIVATE(eps_elec,i,j,k,l,p,rho,s,t,theta) &
    1178              : !$OMP             SHARED(delta_rho,dtheta,e,epsilon_solvent,f,lb) &
    1179           22 : !$OMP             SHARED(norm_drho_elec,q,rho_elec,twobeta,ub)
    1180              :       DO k = lb(3), ub(3)
    1181              :          DO j = lb(2), ub(2)
    1182              :             DO i = lb(1), ub(1)
    1183              :                DO l = 1, 2
    1184              :                   rho = rho_elec%array(i, j, k) + (REAL(l, KIND=dp) - 1.5_dp)*delta_rho
    1185              :                   IF (rho < rhotol) THEN
    1186              :                      eps_elec = epsilon_solvent
    1187              :                   ELSE
    1188              :                      s = rho*q
    1189              :                      p = s**twobeta
    1190              :                      t = 1.0_dp/(1.0_dp + p)
    1191              :                      eps_elec = 1.0_dp + f*(1.0_dp + (1.0_dp - p)*t)
    1192              :                   END IF
    1193              :                   theta(l) = (epsilon_solvent - eps_elec)/e
    1194              :                END DO
    1195              :                dtheta%array(i, j, k) = (theta(2) - theta(1))*norm_drho_elec%array(i, j, k)/delta_rho
    1196              :             END DO
    1197              :          END DO
    1198              :       END DO
    1199              : !$OMP END PARALLEL DO
    1200              : 
    1201           22 :       CALL timestop(handle)
    1202              : 
    1203           22 :    END SUBROUTINE surface_fattebert_gygi
    1204              : 
    1205              : ! **************************************************************************************************
    1206              : !> \brief      Print SCCS results
    1207              : !> \param energy ...
    1208              : !> \param sccs_control ...
    1209              : !> \param output_unit ...
    1210              : !> \par History:
    1211              : !>      - Creation (11.11.2022,MK)
    1212              : !> \author     Matthias Krack (MK)
    1213              : !> \version    1.0
    1214              : ! **************************************************************************************************
    1215           52 :    SUBROUTINE print_sccs_results(energy, sccs_control, output_unit)
    1216              : 
    1217              :       TYPE(qs_energy_type), POINTER                      :: energy
    1218              :       TYPE(sccs_control_type), POINTER                   :: sccs_control
    1219              :       INTEGER, INTENT(IN)                                :: output_unit
    1220              : 
    1221           52 :       IF (output_unit > 0) THEN
    1222           52 :          CPASSERT(ASSOCIATED(energy))
    1223           52 :          CPASSERT(ASSOCIATED(sccs_control))
    1224              :          WRITE (UNIT=output_unit, FMT="(T3,A,T56,F25.14)") &
    1225           52 :             "SCCS| Hartree energy of solute and solvent [Hartree]", energy%sccs_hartree, &
    1226          104 :             "SCCS| Hartree energy of the solute only    [Hartree]", energy%hartree
    1227              :          WRITE (UNIT=output_unit, FMT="(T3,A,T56,F25.14,/,T3,A,T61,F20.3)") &
    1228           52 :             "SCCS| Polarisation energy                  [Hartree]", energy%sccs_pol, &
    1229           52 :             "SCCS|                                      [kcal/mol]", &
    1230           52 :             cp_unit_from_cp2k(energy%sccs_pol, "kcalmol"), &
    1231           52 :             "SCCS| Cavitation energy                    [Hartree]", energy%sccs_cav, &
    1232           52 :             "SCCS|                                      [kcal/mol]", &
    1233           52 :             cp_unit_from_cp2k(energy%sccs_cav, "kcalmol"), &
    1234           52 :             "SCCS| Dispersion free energy               [Hartree]", energy%sccs_dis, &
    1235           52 :             "SCCS|                                      [kcal/mol]", &
    1236           52 :             cp_unit_from_cp2k(energy%sccs_dis, "kcalmol"), &
    1237           52 :             "SCCS| Repulsion free energy                [Hartree]", energy%sccs_rep, &
    1238           52 :             "SCCS|                                      [kcal/mol]", &
    1239           52 :             cp_unit_from_cp2k(energy%sccs_rep, "kcalmol"), &
    1240           52 :             "SCCS| Solvation free energy                [Hartree]", energy%sccs_sol, &
    1241           52 :             "SCCS|                                      [kcal/mol]", &
    1242          104 :             cp_unit_from_cp2k(energy%sccs_sol, "kcalmol")
    1243              :       END IF
    1244              : 
    1245           52 :    END SUBROUTINE print_sccs_results
    1246              : 
    1247              : END MODULE qs_sccs
        

Generated by: LCOV version 2.0-1