LCOV - code coverage report
Current view: top level - src - sirius_interface.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:cccd2f3) Lines: 86.6 % 411 356
Test Date: 2026-05-06 07:07:47 Functions: 100.0 % 8 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 Interface to the SIRIUS Library
      10              : !> \par History
      11              : !>      07.2018 initial create
      12              : !> \author JHU
      13              : !***************************************************************************************************
      14              : #if defined(__SIRIUS)
      15              : MODULE sirius_interface
      16              :    USE ISO_C_BINDING,                   ONLY: C_DOUBLE,&
      17              :                                               C_INT,&
      18              :                                               C_LOC
      19              :    USE atom_kind_orbitals,              ONLY: calculate_atomic_orbitals,&
      20              :                                               gth_potential_conversion
      21              :    USE atom_types,                      ONLY: atom_gthpot_type
      22              :    USE atom_upf,                        ONLY: atom_upfpot_type
      23              :    USE atom_utils,                      ONLY: atom_local_potential
      24              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      25              :                                               get_atomic_kind
      26              :    USE cell_types,                      ONLY: cell_type,&
      27              :                                               real_to_scaled
      28              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      29              :                                               cp_logger_get_default_io_unit,&
      30              :                                               cp_logger_type
      31              :    USE cp_output_handling,              ONLY: cp_p_file,&
      32              :                                               cp_print_key_finished_output,&
      33              :                                               cp_print_key_should_output,&
      34              :                                               cp_print_key_unit_nr
      35              :    USE external_potential_types,        ONLY: gth_potential_type
      36              :    USE input_constants,                 ONLY: do_gapw_log
      37              :    USE input_cp2k_pwdft,                ONLY: SIRIUS_FUNC_VDWDF,&
      38              :                                               SIRIUS_FUNC_VDWDF2,&
      39              :                                               SIRIUS_FUNC_VDWDFCX
      40              :    USE input_section_types,             ONLY: section_vals_get,&
      41              :                                               section_vals_get_subs_vals,&
      42              :                                               section_vals_get_subs_vals2,&
      43              :                                               section_vals_type,&
      44              :                                               section_vals_val_get
      45              :    USE kinds,                           ONLY: default_string_length,&
      46              :                                               dp
      47              :    USE machine,                         ONLY: m_flush
      48              :    USE mathconstants,                   ONLY: fourpi,&
      49              :                                               gamma1
      50              :    USE message_passing,                 ONLY: mp_para_env_type
      51              :    USE particle_types,                  ONLY: particle_type
      52              :    USE physcon,                         ONLY: massunit
      53              :    USE pwdft_environment_types,         ONLY: pwdft_energy_type,&
      54              :                                               pwdft_env_get,&
      55              :                                               pwdft_env_set,&
      56              :                                               pwdft_environment_type
      57              :    USE qs_grid_atom,                    ONLY: allocate_grid_atom,&
      58              :                                               create_grid_atom,&
      59              :                                               deallocate_grid_atom,&
      60              :                                               grid_atom_type
      61              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      62              :                                               qs_kind_type
      63              :    USE qs_subsys_types,                 ONLY: qs_subsys_get,&
      64              :                                               qs_subsys_type
      65              :    USE sirius,                          ONLY: &
      66              :         SIRIUS_INTEGER_ARRAY_TYPE, SIRIUS_INTEGER_TYPE, SIRIUS_LOGICAL_ARRAY_TYPE, &
      67              :         SIRIUS_LOGICAL_TYPE, SIRIUS_NUMBER_ARRAY_TYPE, SIRIUS_NUMBER_TYPE, &
      68              :         SIRIUS_STRING_ARRAY_TYPE, SIRIUS_STRING_TYPE, sirius_add_atom, sirius_add_atom_type, &
      69              :         sirius_add_atom_type_radial_function, sirius_add_xc_functional, sirius_context_handler, &
      70              :         sirius_create_context, sirius_create_ground_state, sirius_create_kset_from_grid, &
      71              :         sirius_finalize, sirius_find_ground_state, sirius_get_band_energies, &
      72              :         sirius_get_band_occupancies, sirius_get_energy, sirius_get_forces, &
      73              :         sirius_get_kpoint_properties, sirius_get_num_kpoints, sirius_get_parameters, &
      74              :         sirius_get_stress_tensor, sirius_ground_state_handler, sirius_import_parameters, &
      75              :         sirius_initialize, sirius_initialize_context, sirius_is_initialized, &
      76              :         sirius_kpoint_set_handler, sirius_option_get_info, sirius_option_get_section_length, &
      77              :         sirius_option_set, sirius_set_atom_position, sirius_set_atom_type_dion, &
      78              :         sirius_set_atom_type_hubbard, sirius_set_atom_type_radial_grid, &
      79              :         sirius_set_lattice_vectors, sirius_set_mpi_grid_dims, sirius_update_ground_state
      80              : #include "./base/base_uses.f90"
      81              : 
      82              :    IMPLICIT NONE
      83              : 
      84              :    PRIVATE
      85              : 
      86              :    ! Global parameters
      87              : 
      88              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'sirius_interface'
      89              : 
      90              :    ! Public subroutines
      91              : 
      92              :    PUBLIC :: cp_sirius_create_env, &
      93              :              cp_sirius_energy_force, &
      94              :              cp_sirius_finalize, &
      95              :              cp_sirius_init, &
      96              :              cp_sirius_is_initialized, &
      97              :              cp_sirius_update_context
      98              : 
      99              : CONTAINS
     100              : 
     101              : !***************************************************************************************************
     102              : !> \brief Initialize the Sirius library
     103              : !> \par Creation (07.2018, JHU)
     104              : !> \author JHU
     105              : ! **************************************************************************************************
     106           20 :    SUBROUTINE cp_sirius_init()
     107           20 :       CALL sirius_initialize(.FALSE.)
     108           20 :    END SUBROUTINE cp_sirius_init
     109              : 
     110              : !***************************************************************************************************
     111              : !> \brief Check the initialisation status of the Sirius library
     112              : !> \return Return the initialisation status of the Sirius library as boolean
     113              : !> \par Creation (03.12.2025, MK)
     114              : !> \author Matthias Krack
     115              : ! **************************************************************************************************
     116         9842 :    LOGICAL FUNCTION cp_sirius_is_initialized()
     117         9842 :       CALL sirius_is_initialized(cp_sirius_is_initialized)
     118         9842 :    END FUNCTION cp_sirius_is_initialized
     119              : 
     120              : !***************************************************************************************************
     121              : !> \brief Finalize the Sirius library
     122              : !> \par Creation (07.2018, JHU)
     123              : !> \author JHU
     124              : ! **************************************************************************************************
     125           20 :    SUBROUTINE cp_sirius_finalize()
     126           20 :       CALL sirius_finalize(.FALSE., .FALSE., .FALSE.)
     127           20 :    END SUBROUTINE cp_sirius_finalize
     128              : 
     129              : !***************************************************************************************************
     130              : !> \brief ...
     131              : !> \param pwdft_env ...
     132              : !> \param
     133              : !> \par History
     134              : !>      07.2018 Create the Sirius environment
     135              : !> \author JHU
     136              : ! **************************************************************************************************
     137           20 :    SUBROUTINE cp_sirius_create_env(pwdft_env)
     138              :       TYPE(pwdft_environment_type), POINTER              :: pwdft_env
     139              : #if defined(__SIRIUS)
     140              : 
     141              :       CHARACTER(len=2)                                   :: element_symbol
     142              :       CHARACTER(len=default_string_length)               :: label
     143              :       INTEGER                                            :: i, ii, jj, iatom, ibeta, ifun, ikind, iwf, j, l, &
     144              :                                                             n, ns, natom, nbeta, nbs, nkind, nmesh, &
     145              :                                                             num_mag_dims, sirius_mpi_comm, vdw_func, nu, lu, output_unit
     146           20 :       INTEGER, DIMENSION(:), POINTER                     :: mpi_grid_dims
     147              :       INTEGER(KIND=C_INT), DIMENSION(3)                  :: k_grid, k_shift
     148           20 :       INTEGER, DIMENSION(:), POINTER                     :: kk
     149              :       LOGICAL                                            :: up, use_ref_cell
     150              :       LOGICAL(4)                                         :: use_so, use_symmetry, dft_plus_u_atom
     151           20 :       REAL(KIND=C_DOUBLE), ALLOCATABLE, DIMENSION(:)     :: fun
     152           20 :       REAL(KIND=C_DOUBLE), ALLOCATABLE, DIMENSION(:, :)  :: dion
     153              :       REAL(KIND=C_DOUBLE), DIMENSION(3)                  :: a1, a2, a3, v1, v2
     154              :       REAL(KIND=dp)                                      :: al, angle1, angle2, cval, focc, &
     155              :                                                             magnetization, mass, pf, rl, zeff, alpha_u, beta_u, &
     156              :                                                             J0_u, J_u, U_u, occ_u, u_minus_J, vnlp, vnlm
     157           20 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: beta, corden, ef, fe, locpot, rc, rp
     158              :       REAL(KIND=dp), DIMENSION(3)                        :: vr, vs, j_t
     159           20 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: density
     160           20 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: wavefunction, wfninfo
     161              :       TYPE(atom_gthpot_type), POINTER                    :: gth_atompot
     162              :       TYPE(atom_upfpot_type), POINTER                    :: upf_pot
     163           20 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     164              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
     165              :       TYPE(cell_type), POINTER                           :: my_cell
     166              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     167              :       TYPE(grid_atom_type), POINTER                      :: atom_grid
     168              :       TYPE(gth_potential_type), POINTER                  :: gth_potential
     169           20 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     170           20 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     171              :       TYPE(qs_subsys_type), POINTER                      :: qs_subsys
     172              :       TYPE(section_vals_type), POINTER                   :: pwdft_section, pwdft_sub_section, &
     173              :                                                             xc_fun, xc_section
     174              :       TYPE(sirius_context_handler)                       :: sctx
     175              :       TYPE(sirius_ground_state_handler)                  :: gs_handler
     176              :       TYPE(sirius_kpoint_set_handler)                    :: ks_handler
     177              : 
     178            0 :       CPASSERT(ASSOCIATED(pwdft_env))
     179              : 
     180           20 :       output_unit = cp_logger_get_default_io_unit()
     181              :       ! create context of simulation
     182           20 :       CALL pwdft_env_get(pwdft_env, para_env=para_env)
     183           20 :       sirius_mpi_comm = para_env%get_handle()
     184           20 :       CALL sirius_create_context(sirius_mpi_comm, sctx)
     185              : 
     186              : !     the "fun" starts.
     187              : 
     188           20 :       CALL pwdft_env_get(pwdft_env=pwdft_env, pwdft_input=pwdft_section, xc_input=xc_section)
     189              : 
     190              :       CALL section_vals_val_get(pwdft_section, "ignore_convergence_failure", &
     191           20 :                                 l_val=pwdft_env%ignore_convergence_failure)
     192              :       ! cp2k should *have* a function that return all xc_functionals. Doing
     193              :       ! manually is prone to errors
     194              : 
     195           20 :       IF (ASSOCIATED(xc_section)) THEN
     196           20 :          ifun = 0
     197           38 :          DO
     198           58 :             ifun = ifun + 1
     199           58 :             xc_fun => section_vals_get_subs_vals2(xc_section, i_section=ifun)
     200           58 :             IF (.NOT. ASSOCIATED(xc_fun)) EXIT
     201              :             ! Here, we do not have to check whether the functional name starts with XC_
     202              :             ! because we only allow the shorter form w/o XC_
     203           58 :             CALL sirius_add_xc_functional(sctx, "XC_"//TRIM(xc_fun%section%name))
     204              :          END DO
     205              :       END IF
     206              : 
     207              :       !     import control section
     208           20 :       pwdft_sub_section => section_vals_get_subs_vals(pwdft_section, "control")
     209           20 :       IF (ASSOCIATED(pwdft_sub_section)) THEN
     210           20 :          CALL cp_sirius_fill_in_section(sctx, pwdft_sub_section, "control")
     211           20 :          CALL section_vals_val_get(pwdft_sub_section, "mpi_grid_dims", i_vals=mpi_grid_dims)
     212              :       END IF
     213              : 
     214              : !     import parameters section
     215           20 :       pwdft_sub_section => section_vals_get_subs_vals(pwdft_section, "parameters")
     216              : 
     217           20 :       IF (ASSOCIATED(pwdft_sub_section)) THEN
     218           20 :          CALL cp_sirius_fill_in_section(sctx, pwdft_sub_section, "parameters")
     219           20 :          CALL section_vals_val_get(pwdft_sub_section, "ngridk", i_vals=kk)
     220           20 :          k_grid(1) = kk(1)
     221           20 :          k_grid(2) = kk(2)
     222           20 :          k_grid(3) = kk(3)
     223              : 
     224           20 :          CALL section_vals_val_get(pwdft_sub_section, "shiftk", i_vals=kk)
     225           20 :          k_shift(1) = kk(1)
     226           20 :          k_shift(2) = kk(2)
     227           20 :          k_shift(3) = kk(3)
     228           20 :          CALL section_vals_val_get(pwdft_sub_section, "num_mag_dims", i_val=num_mag_dims)
     229           20 :          CALL section_vals_val_get(pwdft_sub_section, "use_symmetry", l_val=use_symmetry)
     230           20 :          CALL section_vals_val_get(pwdft_sub_section, "so_correction", l_val=use_so)
     231              : 
     232              : ! now check if van der walls corrections are needed
     233              :          vdw_func = -1
     234              : #ifdef __LIBVDWXC
     235           20 :          CALL section_vals_val_get(pwdft_sub_section, "vdw_functional", i_val=vdw_func)
     236            0 :          SELECT CASE (vdw_func)
     237              :          CASE (SIRIUS_FUNC_VDWDF)
     238            0 :             CALL sirius_add_xc_functional(sctx, "XC_FUNC_VDWDF")
     239              :          CASE (SIRIUS_FUNC_VDWDF2)
     240            0 :             CALL sirius_add_xc_functional(sctx, "XC_FUNC_VDWDF2")
     241              :          CASE (SIRIUS_FUNC_VDWDFCX)
     242           20 :             CALL sirius_add_xc_functional(sctx, "XC_FUNC_VDWDFCX")
     243              :          CASE default
     244              :          END SELECT
     245              : #endif
     246              : 
     247              :       END IF
     248              : 
     249              : !     import mixer section
     250           20 :       pwdft_sub_section => section_vals_get_subs_vals(pwdft_section, "mixer")
     251           20 :       IF (ASSOCIATED(pwdft_sub_section)) THEN
     252           20 :          CALL cp_sirius_fill_in_section(sctx, pwdft_sub_section, "mixer")
     253              :       END IF
     254              : 
     255              : !     import settings section
     256           20 :       pwdft_sub_section => section_vals_get_subs_vals(pwdft_section, "settings")
     257           20 :       IF (ASSOCIATED(pwdft_sub_section)) THEN
     258           20 :          CALL cp_sirius_fill_in_section(sctx, pwdft_sub_section, "settings")
     259              :       END IF
     260              : 
     261              :       !     import solver section
     262           20 :       pwdft_sub_section => section_vals_get_subs_vals(pwdft_section, "iterative_solver")
     263           20 :       IF (ASSOCIATED(pwdft_sub_section)) THEN
     264           20 :          CALL cp_sirius_fill_in_section(sctx, pwdft_sub_section, "iterative_solver")
     265              :       END IF
     266              : 
     267              : #if defined(__SIRIUS_DFTD3)
     268              :       ! import dftd3 section
     269              :       pwdft_sub_section => section_vals_get_subs_vals(pwdft_section, "dftd3")
     270              :       IF (ASSOCIATED(pwdft_sub_section)) THEN
     271              :          CALL cp_sirius_fill_in_section(sctx, pwdft_sub_section, "dftd3")
     272              :       END IF
     273              : #endif
     274              : #if defined(__SIRIUS_DFTD4)
     275              :       ! import dftd4 section
     276              :       pwdft_sub_section => section_vals_get_subs_vals(pwdft_section, "dftd4")
     277              :       IF (ASSOCIATED(pwdft_sub_section)) THEN
     278              :          CALL cp_sirius_fill_in_section(sctx, pwdft_sub_section, "dftd4")
     279              :       END IF
     280              : #endif
     281              : 
     282              : #if defined(__SIRIUS_NLCG)
     283              :       !     import nlcg section
     284              :       pwdft_sub_section => section_vals_get_subs_vals(pwdft_section, "nlcg")
     285              :       IF (ASSOCIATED(pwdft_sub_section)) THEN
     286              :          CALL cp_sirius_fill_in_section(sctx, pwdft_sub_section, "nlcg")
     287              :       END IF
     288              : #endif
     289              : 
     290              : #if defined(__SIRIUS_VCSQNM)
     291              :       pwdft_sub_section => section_vals_get_subs_vals(pwdft_section, "vcsqnm")
     292              :       IF (ASSOCIATED(pwdft_sub_section)) THEN
     293              :          CALL cp_sirius_fill_in_section(sctx, pwdft_sub_section, "vcsqnm")
     294              :       END IF
     295              : #endif
     296              : 
     297              :       !CALL sirius_dump_runtime_setup(sctx, "runtime.json")
     298           20 :       CALL sirius_import_parameters(sctx, '{}')
     299              : 
     300              : ! lattice vectors of the unit cell should be in [a.u.] (length is in [a.u.])
     301           20 :       CALL pwdft_env_get(pwdft_env=pwdft_env, qs_subsys=qs_subsys)
     302           20 :       CALL qs_subsys_get(qs_subsys, cell=my_cell, use_ref_cell=use_ref_cell)
     303           80 :       a1(:) = my_cell%hmat(:, 1)
     304           80 :       a2(:) = my_cell%hmat(:, 2)
     305           80 :       a3(:) = my_cell%hmat(:, 3)
     306           20 :       CALL sirius_set_lattice_vectors(sctx, a1(1), a2(1), a3(1))
     307              : 
     308           20 :       IF (use_ref_cell) THEN
     309            0 :          CPWARN("SIRIUS| The specified CELL_REF will be ignored for PW_DFT calculations")
     310              :       END IF
     311              : 
     312              : ! set up the atomic type definitions
     313              :       CALL qs_subsys_get(qs_subsys, &
     314              :                          atomic_kind_set=atomic_kind_set, &
     315              :                          qs_kind_set=qs_kind_set, &
     316           20 :                          particle_set=particle_set)
     317           20 :       nkind = SIZE(atomic_kind_set)
     318           46 :       DO ikind = 1, nkind
     319              :          CALL get_atomic_kind(atomic_kind_set(ikind), &
     320           26 :                               name=label, element_symbol=element_symbol, mass=mass)
     321           26 :          CALL get_qs_kind(qs_kind_set(ikind), zeff=zeff)
     322           26 :          NULLIFY (upf_pot, gth_potential)
     323           26 :          CALL get_qs_kind(qs_kind_set(ikind), upf_potential=upf_pot, gth_potential=gth_potential)
     324              : 
     325           26 :          IF (ASSOCIATED(upf_pot)) THEN
     326              :             CALL sirius_add_atom_type(sctx, label, fname=upf_pot%filename, &
     327              :                                       symbol=element_symbol, &
     328           20 :                                       mass=REAL(mass/massunit, KIND=C_DOUBLE))
     329              : 
     330            6 :          ELSEIF (ASSOCIATED(gth_potential)) THEN
     331              : !
     332            6 :             NULLIFY (atom_grid)
     333            6 :             CALL allocate_grid_atom(atom_grid)
     334            6 :             nmesh = 929
     335            6 :             atom_grid%nr = nmesh
     336            6 :             CALL create_grid_atom(atom_grid, nmesh, 1, 1, 0, do_gapw_log)
     337           24 :             ALLOCATE (rp(nmesh), fun(nmesh))
     338            6 :             IF (atom_grid%rad(1) < atom_grid%rad(nmesh)) THEN
     339              :                up = .TRUE.
     340              :             ELSE
     341              :                up = .FALSE.
     342              :             END IF
     343              :             IF (up) THEN
     344            0 :                rp(1:nmesh) = atom_grid%rad(1:nmesh)
     345              :             ELSE
     346         5580 :                DO i = 1, nmesh
     347         5580 :                   rp(i) = atom_grid%rad(nmesh - i + 1)
     348              :                END DO
     349              :             END IF
     350              : ! add new atom type
     351              :             CALL sirius_add_atom_type(sctx, label, &
     352              :                                       zn=NINT(zeff + 0.001d0), &
     353              :                                       symbol=element_symbol, &
     354              :                                       mass=REAL(mass/massunit, KIND=C_DOUBLE), &
     355            6 :                                       spin_orbit=gth_potential%soc)
     356              : !
     357         2916 :             ALLOCATE (gth_atompot)
     358            6 :             CALL gth_potential_conversion(gth_potential, gth_atompot)
     359              : ! set radial grid
     360         5580 :             fun(1:nmesh) = rp(1:nmesh)
     361            6 :             CALL sirius_set_atom_type_radial_grid(sctx, label, nmesh, fun(1))
     362              : ! set beta-projectors
     363              : ! GTH SOC uses the same projectors, SIRIUS can use the same or different projectors for l+1/2, l-1/2 (l > 0 l+1/2 l < 0 l-/2 )
     364           24 :             ALLOCATE (ef(nmesh), beta(nmesh))
     365            6 :             ibeta = 0
     366           30 :             DO l = 0, 3
     367           24 :                IF (gth_atompot%nl(l) == 0) CYCLE
     368           14 :                rl = gth_atompot%rcnl(l)
     369              : ! we need to multiply by r so that data transferred to sirius are r \beta(r) not beta(r)
     370        13020 :                ef(1:nmesh) = EXP(-0.5_dp*rp(1:nmesh)*rp(1:nmesh)/(rl*rl))
     371           50 :                DO i = 1, gth_atompot%nl(l)
     372           30 :                   pf = rl**(l + 0.5_dp*(4._dp*i - 1._dp))
     373           30 :                   j = l + 2*i - 1
     374           30 :                   pf = SQRT(2._dp)/(pf*SQRT(gamma1(j)))
     375        27900 :                   beta(:) = pf*rp**(l + 2*i - 2)*ef
     376           30 :                   ibeta = ibeta + 1
     377        27900 :                   fun(1:nmesh) = beta(1:nmesh)*rp(1:nmesh)
     378              :                   CALL sirius_add_atom_type_radial_function(sctx, label, &
     379           30 :                                                             "beta", fun(1), nmesh, l=l)
     380              :                   ! we double the number of beta projectors for SO and l>0
     381           54 :                   IF (gth_atompot%soc .AND. l /= 0) THEN
     382              :                      CALL sirius_add_atom_type_radial_function(sctx, label, &
     383           10 :                                                                "beta", fun(1), nmesh, l=-l)
     384              :                   END IF
     385              :                END DO
     386              :             END DO
     387            6 :             DEALLOCATE (ef, beta)
     388            6 :             nbeta = ibeta
     389              : 
     390              : ! nonlocal PP matrix elements
     391            6 :             IF (gth_atompot%soc) THEN
     392            2 :                nbs = 2*nbeta - gth_atompot%nl(0)
     393            8 :                ALLOCATE (dion(nbs, nbs))
     394              :             ELSE
     395           16 :                ALLOCATE (dion(nbeta, nbeta))
     396              :             END IF
     397          458 :             dion = 0.0_dp
     398            6 :             IF (gth_atompot%soc) THEN
     399            2 :                ns = gth_atompot%nl(0)
     400            2 :                IF (ns /= 0) THEN
     401           26 :                   dion(1:ns, 1:ns) = gth_atompot%hnl(1:ns, 1:ns, 0)
     402              :                END IF
     403            8 :                DO l = 1, 3
     404            6 :                   IF (gth_atompot%nl(l) == 0) CYCLE
     405           16 :                   DO i = 1, gth_atompot%nl(l)
     406           14 :                      ii = ns + 2*SUM(gth_atompot%nl(1:l - 1))
     407           10 :                      ii = ii + 2*(i - 1) + 1
     408           42 :                      DO j = 1, gth_atompot%nl(l)
     409           34 :                         jj = ns + 2*SUM(gth_atompot%nl(1:l - 1))
     410           26 :                         jj = jj + 2*(j - 1) + 1
     411           26 :                         vnlp = gth_atompot%hnl(i, j, l) + 0.5_dp*l*gth_atompot%knl(i, j, l)
     412           26 :                         vnlm = gth_atompot%hnl(i, j, l) - 0.5_dp*(l + 1)*gth_atompot%knl(i, j, l)
     413           26 :                         dion(ii, jj) = vnlp
     414           36 :                         dion(ii + 1, jj + 1) = vnlm
     415              :                      END DO
     416              :                   END DO
     417              :                END DO
     418            2 :                CALL sirius_set_atom_type_dion(sctx, label, nbs, dion(1, 1))
     419              :             ELSE
     420           20 :                DO l = 0, 3
     421           16 :                   IF (gth_atompot%nl(l) == 0) CYCLE
     422           14 :                   ibeta = SUM(gth_atompot%nl(0:l - 1)) + 1
     423            8 :                   i = ibeta + gth_atompot%nl(l) - 1
     424           52 :                   dion(ibeta:i, ibeta:i) = gth_atompot%hnl(1:gth_atompot%nl(l), 1:gth_atompot%nl(l), l)
     425              :                END DO
     426            4 :                CALL sirius_set_atom_type_dion(sctx, label, nbeta, dion(1, 1))
     427              :             END IF
     428              : 
     429            6 :             DEALLOCATE (dion)
     430              : 
     431              : ! set non-linear core correction
     432            6 :             IF (gth_atompot%nlcc) THEN
     433            0 :                ALLOCATE (corden(nmesh), fe(nmesh), rc(nmesh))
     434            0 :                corden(:) = 0.0_dp
     435            0 :                n = gth_atompot%nexp_nlcc
     436            0 :                DO i = 1, n
     437            0 :                   al = gth_atompot%alpha_nlcc(i)
     438            0 :                   rc(:) = rp(:)/al
     439            0 :                   fe(:) = EXP(-0.5_dp*rc(:)*rc(:))
     440            0 :                   DO j = 1, gth_atompot%nct_nlcc(i)
     441            0 :                      cval = gth_atompot%cval_nlcc(j, i)
     442            0 :                      corden(:) = corden(:) + fe(:)*rc(:)**(2*j - 2)*cval
     443              :                   END DO
     444              :                END DO
     445            0 :                fun(1:nmesh) = corden(1:nmesh)*rp(1:nmesh)
     446              :                CALL sirius_add_atom_type_radial_function(sctx, label, "ps_rho_core", &
     447            0 :                                                          fun(1), nmesh)
     448            0 :                DEALLOCATE (corden, fe, rc)
     449              :             END IF
     450              : 
     451              : ! local potential
     452           18 :             ALLOCATE (locpot(nmesh))
     453         5580 :             locpot(:) = 0.0_dp
     454            6 :             CALL atom_local_potential(locpot, gth_atompot, rp)
     455         5580 :             fun(1:nmesh) = locpot(1:nmesh)
     456              :             CALL sirius_add_atom_type_radial_function(sctx, label, "vloc", &
     457            6 :                                                       fun(1), nmesh)
     458            6 :             DEALLOCATE (locpot)
     459              : !
     460            6 :             NULLIFY (density, wavefunction, wfninfo)
     461              :             CALL calculate_atomic_orbitals(atomic_kind_set(ikind), qs_kind_set(ikind), &
     462              :                                            density=density, wavefunction=wavefunction, &
     463            6 :                                            wfninfo=wfninfo, agrid=atom_grid)
     464              : 
     465              : ! set the atomic radial functions
     466           22 :             DO iwf = 1, SIZE(wavefunction, 2)
     467           16 :                focc = wfninfo(1, iwf)
     468           16 :                l = NINT(wfninfo(2, iwf))
     469              : ! we can not easily get the principal quantum number
     470           16 :                nu = -1
     471           16 :                IF (up) THEN
     472            0 :                   fun(1:nmesh) = wavefunction(1:nmesh, iwf)*rp(i)
     473              :                ELSE
     474        14880 :                   DO i = 1, nmesh
     475        14880 :                      fun(i) = wavefunction(nmesh - i + 1, iwf)*rp(i)
     476              :                   END DO
     477              :                END IF
     478              :                CALL sirius_add_atom_type_radial_function(sctx, &
     479              :                                                          label, "ps_atomic_wf", &
     480           22 :                                                          fun(1), nmesh, l=l, occ=REAL(focc, KIND=C_DOUBLE), n=nu)
     481              :             END DO
     482              : 
     483              : ! set total charge density of a free atom (to compute initial rho(r))
     484            6 :             IF (up) THEN
     485            0 :                fun(1:nmesh) = fourpi*density(1:nmesh)*atom_grid%rad(1:nmesh)**2
     486              :             ELSE
     487         5580 :                DO i = 1, nmesh
     488         5580 :                   fun(i) = fourpi*density(nmesh - i + 1)*atom_grid%rad(nmesh - i + 1)**2
     489              :                END DO
     490              :             END IF
     491              :             CALL sirius_add_atom_type_radial_function(sctx, label, "ps_rho_total", &
     492            6 :                                                       fun(1), nmesh)
     493              : 
     494            6 :             IF (ASSOCIATED(density)) DEALLOCATE (density)
     495            6 :             IF (ASSOCIATED(wavefunction)) DEALLOCATE (wavefunction)
     496            6 :             IF (ASSOCIATED(wfninfo)) DEALLOCATE (wfninfo)
     497              : 
     498            6 :             CALL deallocate_grid_atom(atom_grid)
     499            6 :             DEALLOCATE (rp, fun)
     500            6 :             DEALLOCATE (gth_atompot)
     501              : !
     502              :          ELSE
     503              :             CALL cp_abort(__LOCATION__, &
     504            0 :                           "CP2K/SIRIUS: atomic kind needs UPF or GTH potential definition")
     505              :          END IF
     506              : 
     507              :          CALL get_qs_kind(qs_kind_set(ikind), &
     508              :                           dft_plus_u_atom=dft_plus_u_atom, &
     509              :                           l_of_dft_plus_u=lu, &
     510              :                           n_of_dft_plus_u=nu, &
     511              :                           u_minus_j_target=u_minus_j, &
     512              :                           U_of_dft_plus_u=U_u, &
     513              :                           J_of_dft_plus_u=J_u, &
     514              :                           alpha_of_dft_plus_u=alpha_u, &
     515              :                           beta_of_dft_plus_u=beta_u, &
     516              :                           J0_of_dft_plus_u=J0_u, &
     517           26 :                           occupation_of_dft_plus_u=occ_u)
     518              : 
     519           72 :          IF (dft_plus_u_atom) THEN
     520            0 :             IF (nu < 1) THEN
     521            0 :                CPABORT("CP2K/SIRIUS (hubbard): principal quantum number not specified")
     522              :             END IF
     523              : 
     524            0 :             IF (lu < 0) THEN
     525            0 :                CPABORT("CP2K/SIRIUS (hubbard): l can not be negative.")
     526              :             END IF
     527              : 
     528            0 :             IF (occ_u < 0.0) THEN
     529            0 :                CPABORT("CP2K/SIRIUS (hubbard): the occupation number can not be negative.")
     530              :             END IF
     531              : 
     532            0 :             j_t(:) = 0.0
     533            0 :             IF (ABS(u_minus_j) < 1e-8) THEN
     534            0 :                j_t(1) = J_u
     535              :                CALL sirius_set_atom_type_hubbard(sctx, label, lu, nu, &
     536            0 :                                                  occ_u, U_u, j_t, alpha_u, beta_u, J0_u)
     537              :             ELSE
     538              :                CALL sirius_set_atom_type_hubbard(sctx, label, lu, nu, &
     539            0 :                                                  occ_u, u_minus_j, j_t, alpha_u, beta_u, J0_u)
     540              :             END IF
     541              :          END IF
     542              : 
     543              :       END DO
     544              : 
     545              : ! add atoms to the unit cell
     546              : ! WARNING: sirius accepts only fractional coordinates;
     547           20 :       natom = SIZE(particle_set)
     548           58 :       DO iatom = 1, natom
     549          152 :          vr(1:3) = particle_set(iatom)%r(1:3)
     550           38 :          CALL real_to_scaled(vs, vr, my_cell)
     551           38 :          atomic_kind => particle_set(iatom)%atomic_kind
     552           38 :          ikind = atomic_kind%kind_number
     553           38 :          CALL get_atomic_kind(atomic_kind, name=label)
     554           38 :          CALL get_qs_kind(qs_kind_set(ikind), zeff=zeff, magnetization=magnetization)
     555              : ! angle of magnetization might come from input Atom x y z mx my mz
     556              : ! or as an angle?
     557              : ! Answer : SIRIUS only accept the magnetization as mx, my, mz
     558           38 :          IF (num_mag_dims == 3) THEN
     559            4 :             angle1 = 0.0_dp
     560            4 :             angle2 = 0.0_dp
     561            4 :             v1(1) = magnetization*SIN(angle1)*COS(angle2)
     562            4 :             v1(2) = magnetization*SIN(angle1)*SIN(angle2)
     563            4 :             v1(3) = magnetization*COS(angle1)
     564              :          ELSE
     565           34 :             v1 = 0._dp
     566           34 :             v1(3) = magnetization
     567              :          END IF
     568           38 :          v2(1:3) = vs(1:3)
     569           96 :          CALL sirius_add_atom(sctx, label, v2(1), v1(1))
     570              :       END DO
     571              : 
     572           20 :       CALL sirius_set_mpi_grid_dims(sctx, 2, mpi_grid_dims)
     573              : 
     574              : ! initialize global variables/indices/arrays/etc. of the simulation
     575           20 :       CALL sirius_initialize_context(sctx)
     576              : 
     577              :       ! strictly speaking the parameter use_symmetry is initialized at the
     578              :       ! beginning but it does no harm to do it that way
     579           20 :       IF (use_symmetry) THEN
     580           16 :          CALL sirius_create_kset_from_grid(sctx, k_grid(1), k_shift(1), use_symmetry=.TRUE., kset_handler=ks_handler)
     581              :       ELSE
     582            4 :          CALL sirius_create_kset_from_grid(sctx, k_grid(1), k_shift(1), use_symmetry=.FALSE., kset_handler=ks_handler)
     583              :       END IF
     584              : ! create ground-state class
     585           20 :       CALL sirius_create_ground_state(ks_handler, gs_handler)
     586              : 
     587           20 :       CALL pwdft_env_set(pwdft_env, sctx=sctx, gs_handler=gs_handler, ks_handler=ks_handler)
     588              : #endif
     589           40 :    END SUBROUTINE cp_sirius_create_env
     590              : 
     591              : !***************************************************************************************************
     592              : !> \brief ...
     593              : !> \param pwdft_env ...
     594              : !> \param
     595              : !> \par History
     596              : !>      07.2018 Update the Sirius environment
     597              : !> \author JHU
     598              : ! **************************************************************************************************
     599           20 :    SUBROUTINE cp_sirius_update_context(pwdft_env)
     600              :       TYPE(pwdft_environment_type), POINTER              :: pwdft_env
     601              : 
     602              :       INTEGER                                            :: iatom, natom
     603              :       REAL(KIND=C_DOUBLE), DIMENSION(3)                  :: a1, a2, a3, v2
     604              :       REAL(KIND=dp), DIMENSION(3)                        :: vr, vs
     605              :       TYPE(cell_type), POINTER                           :: my_cell
     606           20 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     607              :       TYPE(qs_subsys_type), POINTER                      :: qs_subsys
     608              :       TYPE(sirius_context_handler)                       :: sctx
     609              :       TYPE(sirius_ground_state_handler)                  :: gs_handler
     610              : 
     611            0 :       CPASSERT(ASSOCIATED(pwdft_env))
     612           20 :       CALL pwdft_env_get(pwdft_env, sctx=sctx, gs_handler=gs_handler)
     613              : 
     614              : ! get current positions and lattice vectors
     615           20 :       CALL pwdft_env_get(pwdft_env=pwdft_env, qs_subsys=qs_subsys)
     616              : 
     617              : ! lattice vectors of the unit cell should be in [a.u.] (length is in [a.u.])
     618           20 :       CALL qs_subsys_get(qs_subsys, cell=my_cell)
     619           80 :       a1(:) = my_cell%hmat(:, 1)
     620           80 :       a2(:) = my_cell%hmat(:, 2)
     621           80 :       a3(:) = my_cell%hmat(:, 3)
     622           20 :       CALL sirius_set_lattice_vectors(sctx, a1(1), a2(1), a3(1))
     623              : 
     624              : ! new atomic positions
     625           20 :       CALL qs_subsys_get(qs_subsys, particle_set=particle_set)
     626           20 :       natom = SIZE(particle_set)
     627           58 :       DO iatom = 1, natom
     628          152 :          vr(1:3) = particle_set(iatom)%r(1:3)
     629           38 :          CALL real_to_scaled(vs, vr, my_cell)
     630           38 :          v2(1:3) = vs(1:3)
     631           58 :          CALL sirius_set_atom_position(sctx, iatom, v2(1))
     632              :       END DO
     633              : 
     634              : ! update ground-state class
     635           20 :       CALL sirius_update_ground_state(gs_handler)
     636              : 
     637           20 :       CALL pwdft_env_set(pwdft_env, sctx=sctx, gs_handler=gs_handler)
     638              : 
     639           20 :    END SUBROUTINE cp_sirius_update_context
     640              : 
     641              : ! **************************************************************************************************
     642              : !> \brief ...
     643              : !> \param sctx ...
     644              : !> \param section ...
     645              : !> \param section_name ...
     646              : ! **************************************************************************************************
     647          100 :    SUBROUTINE cp_sirius_fill_in_section(sctx, section, section_name)
     648              :       TYPE(sirius_context_handler), INTENT(INOUT)        :: sctx
     649              :       TYPE(section_vals_type), POINTER                   :: section
     650              :       CHARACTER(*), INTENT(in)                           :: section_name
     651              : 
     652              :       CHARACTER(len=256), TARGET                         :: option_name
     653              :       CHARACTER(len=4096)                                :: description, usage
     654          100 :       CHARACTER(len=80), DIMENSION(:), POINTER           :: tmp
     655              :       CHARACTER(len=80), TARGET                          :: str
     656              :       INTEGER                                            :: ctype, elem, ic, j
     657          100 :       INTEGER, DIMENSION(:), POINTER                     :: ivals
     658              :       INTEGER, TARGET                                    :: enum_length, ival, length, &
     659              :                                                             num_possible_values, number_of_options
     660              :       LOGICAL                                            :: explicit
     661          100 :       LOGICAL, DIMENSION(:), POINTER                     :: lvals
     662              :       LOGICAL, TARGET                                    :: found, lval
     663          100 :       REAL(kind=dp), DIMENSION(:), POINTER               :: rvals
     664              :       REAL(kind=dp), TARGET                              :: rval
     665              : 
     666          100 :       NULLIFY (rvals)
     667          100 :       NULLIFY (ivals)
     668          100 :       CALL sirius_option_get_section_length(section_name, number_of_options)
     669              : 
     670         2220 :       DO elem = 1, number_of_options
     671         2120 :          option_name = ''
     672              :          CALL sirius_option_get_info(section_name, &
     673              :                                      elem, &
     674              :                                      option_name, &
     675              :                                      256, &
     676              :                                      ctype, &
     677              :                                      num_possible_values, &
     678              :                                      enum_length, &
     679              :                                      description, &
     680              :                                      4096, &
     681              :                                      usage, &
     682         2120 :                                      4096)
     683              : 
     684              :          ! ignore the keyword parametes for sections dftd3 and dftd4.
     685         2120 :          IF (((section_name == 'dftd3') .OR. (section_name == 'dftd4')) .AND. (option_name == 'parameters')) THEN
     686              :             CYCLE
     687              :          END IF
     688              : 
     689         4340 :          IF ((option_name /= 'memory_usage') .AND. (option_name /= 'xc_functionals') .AND. (option_name /= 'vk')) THEN
     690         2080 :             CALL section_vals_val_get(section, option_name, explicit=found)
     691         2080 :             IF (found) THEN
     692          160 :                SELECT CASE (ctype)
     693              :                CASE (SIRIUS_INTEGER_TYPE)
     694          160 :                   CALL section_vals_val_get(section, option_name, i_val=ival)
     695          160 :                   CALL sirius_option_set(sctx, section_name, option_name, ctype, C_LOC(ival))
     696              :                CASE (SIRIUS_NUMBER_TYPE)
     697          124 :                   CALL section_vals_val_get(section, option_name, r_val=rval)
     698          124 :                   CALL sirius_option_set(sctx, section_name, option_name, ctype, C_LOC(rval))
     699              :                CASE (SIRIUS_LOGICAL_TYPE)
     700           30 :                   CALL section_vals_val_get(section, option_name, l_val=lval)
     701           30 :                   CALL sirius_option_set(sctx, section_name, option_name, ctype, C_LOC(lval))
     702              :                CASE (SIRIUS_STRING_TYPE)      ! string nightmare
     703          124 :                   str = ''
     704          124 :                   CALL section_vals_val_get(section, option_name, explicit=explicit, c_val=str)
     705          124 :                   str = TRIM(ADJUSTL(str))
     706        10044 :                   DO j = 1, LEN(str)
     707         9920 :                      ic = ICHAR(str(j:j))
     708        10044 :                      IF (ic >= 65 .AND. ic < 90) str(j:j) = CHAR(ic + 32)
     709              :                   END DO
     710              : 
     711          124 :                   CALL sirius_option_set(sctx, section_name, option_name, ctype, C_LOC(str), max_length=LEN_TRIM(str))
     712              :                CASE (SIRIUS_INTEGER_ARRAY_TYPE)
     713           20 :                   CALL section_vals_val_get(section, option_name, i_vals=ivals)
     714              :                   CALL sirius_option_set(sctx, section_name, option_name, ctype, C_LOC(ivals(1)), &
     715           20 :                                          max_length=num_possible_values)
     716              :                CASE (SIRIUS_NUMBER_ARRAY_TYPE)
     717            0 :                   CALL section_vals_val_get(section, option_name, r_vals=rvals)
     718              :                   CALL sirius_option_set(sctx, section_name, option_name, ctype, C_LOC(rvals(1)), &
     719            0 :                                          max_length=num_possible_values)
     720              :                CASE (SIRIUS_LOGICAL_ARRAY_TYPE)
     721            0 :                   CALL section_vals_val_get(section, option_name, l_vals=lvals)
     722              :                   CALL sirius_option_set(sctx, section_name, option_name, ctype, C_LOC(lvals(1)), &
     723            0 :                                          max_length=num_possible_values)
     724              :                CASE (SIRIUS_STRING_ARRAY_TYPE)
     725            0 :                   CALL section_vals_val_get(section, option_name, explicit=explicit, n_rep_val=length)
     726          458 :                   DO j = 1, length
     727            0 :                      str = ''
     728            0 :                      CALL section_vals_val_get(section, option_name, i_rep_val=j, explicit=explicit, c_vals=tmp)
     729            0 :                      str = TRIM(ADJUSTL(tmp(j)))
     730              :                      CALL sirius_option_set(sctx, section_name, option_name, ctype, C_LOC(str), &
     731            0 :                                             max_length=LEN_TRIM(str), append=.TRUE.)
     732              :                   END DO
     733              :                CASE DEFAULT
     734              :                END SELECT
     735              :             END IF
     736              :          END IF
     737              :       END DO
     738          100 :    END SUBROUTINE cp_sirius_fill_in_section
     739              : 
     740              : !***************************************************************************************************
     741              : !> \brief ...
     742              : !> \param pwdft_env ...
     743              : !> \param calculate_forces ...
     744              : !> \param calculate_stress_tensor ...
     745              : !> \param
     746              : !> \par History
     747              : !>      07.2018 start the Sirius library
     748              : !> \author JHU
     749              : ! **************************************************************************************************
     750           20 :    SUBROUTINE cp_sirius_energy_force(pwdft_env, calculate_forces, calculate_stress_tensor)
     751              :       TYPE(pwdft_environment_type), INTENT(INOUT), &
     752              :          POINTER                                         :: pwdft_env
     753              :       LOGICAL, INTENT(IN)                                :: calculate_forces, calculate_stress_tensor
     754              : 
     755              :       INTEGER                                            :: iw, n1, n2
     756              :       LOGICAL                                            :: do_print, gs_converged
     757              :       REAL(KIND=C_DOUBLE)                                :: etotal
     758           20 :       REAL(KIND=C_DOUBLE), ALLOCATABLE, DIMENSION(:, :)  :: cforces
     759              :       REAL(KIND=C_DOUBLE), DIMENSION(3, 3)               :: cstress
     760              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: stress
     761           20 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: forces
     762              :       TYPE(cp_logger_type), POINTER                      :: logger
     763              :       TYPE(pwdft_energy_type), POINTER                   :: energy
     764              :       TYPE(section_vals_type), POINTER                   :: print_section, pwdft_input
     765              :       TYPE(sirius_ground_state_handler)                  :: gs_handler
     766              : 
     767            0 :       CPASSERT(ASSOCIATED(pwdft_env))
     768              : 
     769           20 :       NULLIFY (logger)
     770           20 :       logger => cp_get_default_logger()
     771           20 :       iw = cp_logger_get_default_io_unit(logger)
     772              : 
     773           20 :       CALL pwdft_env_get(pwdft_env=pwdft_env, gs_handler=gs_handler)
     774           20 :       CALL sirius_find_ground_state(gs_handler, converged=gs_converged)
     775              : 
     776           20 :       IF (gs_converged) THEN
     777           20 :          IF (iw > 0) WRITE (iw, '(A)') "CP2K/SIRIUS: ground state is converged"
     778              :       ELSE
     779            0 :          IF (pwdft_env%ignore_convergence_failure) THEN
     780            0 :             IF (iw > 0) WRITE (iw, '(A)') "CP2K/SIRIUS Warning: ground state is not converged"
     781              :          ELSE
     782            0 :             CPABORT("CP2K/SIRIUS (ground state): SIRIUS did not converge.")
     783              :          END IF
     784              :       END IF
     785           20 :       IF (iw > 0) CALL m_flush(iw)
     786              : 
     787           20 :       CALL pwdft_env_get(pwdft_env=pwdft_env, energy=energy)
     788              :       etotal = 0.0_C_DOUBLE
     789              : 
     790           20 :       CALL sirius_get_energy(gs_handler, 'band-gap', etotal)
     791           20 :       energy%band_gap = etotal
     792              : 
     793              :       etotal = 0.0_C_DOUBLE
     794           20 :       CALL sirius_get_energy(gs_handler, 'total', etotal)
     795           20 :       energy%etotal = etotal
     796              : 
     797              :       ! extract entropy (TS returned by sirius is always negative, sign
     798              :       ! convention in QE)
     799              :       etotal = 0.0_C_DOUBLE
     800           20 :       CALL sirius_get_energy(gs_handler, 'demet', etotal)
     801           20 :       energy%entropy = -etotal
     802              : 
     803           20 :       IF (calculate_forces) THEN
     804           14 :          CALL pwdft_env_get(pwdft_env=pwdft_env, forces=forces)
     805           14 :          n1 = SIZE(forces, 1)
     806           14 :          n2 = SIZE(forces, 2)
     807              : 
     808           56 :          ALLOCATE (cforces(n2, n1))
     809          142 :          cforces = 0.0_C_DOUBLE
     810           14 :          CALL sirius_get_forces(gs_handler, 'total', cforces)
     811              :          ! Sirius computes the forces but cp2k use the gradient everywhere
     812              :          ! so a minus sign is needed.
     813              :          ! note also that sirius and cp2k store the forces transpose to each other
     814              :          ! sirius : forces(coordinates, atoms)
     815              :          ! cp2k : forces(atoms, coordinates)
     816          152 :          forces = -TRANSPOSE(cforces(:, :))
     817           14 :          DEALLOCATE (cforces)
     818              :       END IF
     819              : 
     820           20 :       IF (calculate_stress_tensor) THEN
     821            0 :          cstress = 0.0_C_DOUBLE
     822            0 :          CALL sirius_get_stress_tensor(gs_handler, 'total', cstress)
     823            0 :          stress(1:3, 1:3) = cstress(1:3, 1:3)
     824            0 :          CALL pwdft_env_set(pwdft_env=pwdft_env, stress=stress)
     825              :       END IF
     826              : 
     827           20 :       CALL pwdft_env_get(pwdft_env=pwdft_env, pwdft_input=pwdft_input)
     828           20 :       print_section => section_vals_get_subs_vals(pwdft_input, "PRINT")
     829           20 :       CALL section_vals_get(print_section, explicit=do_print)
     830           20 :       IF (do_print) THEN
     831            2 :          CALL cp_sirius_print_results(pwdft_env, print_section)
     832              :       END IF
     833           40 :    END SUBROUTINE cp_sirius_energy_force
     834              : 
     835              : !***************************************************************************************************
     836              : !> \brief ...
     837              : !> \param pwdft_env ...
     838              : !> \param print_section ...
     839              : !> \param
     840              : !> \par History
     841              : !>      12.2019 init
     842              : !> \author JHU
     843              : ! **************************************************************************************************
     844            2 :    SUBROUTINE cp_sirius_print_results(pwdft_env, print_section)
     845              :       TYPE(pwdft_environment_type), INTENT(INOUT), &
     846              :          POINTER                                         :: pwdft_env
     847              :       TYPE(section_vals_type), POINTER                   :: print_section
     848              : 
     849              :       CHARACTER(LEN=default_string_length)               :: my_act, my_pos
     850              :       INTEGER                                            :: i, ik, iounit, ispn, iterstep, iv, iw, &
     851              :                                                             nbands, nhist, nkpts, nspins
     852              :       INTEGER(KIND=C_INT)                                :: cint
     853              :       LOGICAL                                            :: append, dos, ionode
     854              :       REAL(KIND=C_DOUBLE)                                :: creal
     855            2 :       REAL(KIND=C_DOUBLE), ALLOCATABLE, DIMENSION(:)     :: slist
     856              :       REAL(KIND=dp)                                      :: de, e_fermi(2), emax, emin, eval
     857            2 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: wkpt
     858            2 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: ehist, hist, occval
     859            2 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: energies, occupations
     860              :       TYPE(cp_logger_type), POINTER                      :: logger
     861              :       TYPE(sirius_context_handler)                       :: sctx
     862              :       TYPE(sirius_ground_state_handler)                  :: gs_handler
     863              :       TYPE(sirius_kpoint_set_handler)                    :: ks_handler
     864              : 
     865            2 :       NULLIFY (logger)
     866            4 :       logger => cp_get_default_logger()
     867              :       ionode = logger%para_env%is_source()
     868            2 :       iounit = cp_logger_get_default_io_unit(logger)
     869              : 
     870              :       ! Density of States
     871            2 :       dos = BTEST(cp_print_key_should_output(logger%iter_info, print_section, "DOS"), cp_p_file)
     872            2 :       IF (dos) THEN
     873            2 :          CALL pwdft_env_get(pwdft_env, ks_handler=ks_handler)
     874            2 :          CALL pwdft_env_get(pwdft_env, gs_handler=gs_handler)
     875            2 :          CALL pwdft_env_get(pwdft_env, sctx=sctx)
     876              : 
     877            2 :          CALL section_vals_val_get(print_section, "DOS%DELTA_E", r_val=de)
     878            2 :          CALL section_vals_val_get(print_section, "DOS%APPEND", l_val=append)
     879              : 
     880            2 :          CALL sirius_get_num_kpoints(ks_handler, cint)
     881            2 :          nkpts = cint
     882            2 :          CALL sirius_get_parameters(sctx, num_bands=cint)
     883            2 :          nbands = cint
     884            2 :          CALL sirius_get_parameters(sctx, num_spins=cint)
     885            2 :          nspins = cint
     886            2 :          e_fermi(:) = 0.0_dp
     887           10 :          ALLOCATE (energies(nbands, nspins, nkpts))
     888          442 :          energies = 0.0_dp
     889            8 :          ALLOCATE (occupations(nbands, nspins, nkpts))
     890          442 :          occupations = 0.0_dp
     891            6 :          ALLOCATE (wkpt(nkpts))
     892            6 :          ALLOCATE (slist(nbands))
     893           10 :          DO ik = 1, nkpts
     894            8 :             CALL sirius_get_kpoint_properties(ks_handler, ik, creal)
     895           10 :             wkpt(ik) = creal
     896              :          END DO
     897           10 :          DO ik = 1, nkpts
     898           26 :             DO ispn = 1, nspins
     899           16 :                CALL sirius_get_band_energies(ks_handler, ik, ispn, slist)
     900          432 :                energies(1:nbands, ispn, ik) = slist(1:nbands)
     901           16 :                CALL sirius_get_band_occupancies(ks_handler, ik, ispn, slist)
     902          440 :                occupations(1:nbands, ispn, ik) = slist(1:nbands)
     903              :             END DO
     904              :          END DO
     905          442 :          emin = MINVAL(energies)
     906          442 :          emax = MAXVAL(energies)
     907            2 :          nhist = NINT((emax - emin)/de) + 1
     908           16 :          ALLOCATE (hist(nhist, nspins), occval(nhist, nspins), ehist(nhist, nspins))
     909        16110 :          hist = 0.0_dp
     910        16110 :          occval = 0.0_dp
     911        16110 :          ehist = 0.0_dp
     912              : 
     913           10 :          DO ik = 1, nkpts
     914           26 :             DO ispn = 1, nspins
     915          440 :                DO i = 1, nbands
     916          416 :                   eval = energies(i, ispn, ik) - emin
     917          416 :                   iv = NINT(eval/de) + 1
     918          416 :                   CPASSERT((iv > 0) .AND. (iv <= nhist))
     919          416 :                   hist(iv, ispn) = hist(iv, ispn) + wkpt(ik)
     920          432 :                   occval(iv, ispn) = occval(iv, ispn) + wkpt(ik)*occupations(i, ispn, ik)
     921              :                END DO
     922              :             END DO
     923              :          END DO
     924        16110 :          hist = hist/REAL(nbands, KIND=dp)
     925         8054 :          DO i = 1, nhist
     926        24158 :             ehist(i, 1:nspins) = emin + (i - 1)*de
     927              :          END DO
     928              : 
     929            2 :          iterstep = logger%iter_info%iteration(logger%iter_info%n_rlevel)
     930            2 :          my_act = "WRITE"
     931            2 :          IF (append .AND. iterstep > 1) THEN
     932            0 :             my_pos = "APPEND"
     933              :          ELSE
     934            2 :             my_pos = "REWIND"
     935              :          END IF
     936              : 
     937              :          iw = cp_print_key_unit_nr(logger, print_section, "DOS", &
     938              :                                    extension=".dos", file_position=my_pos, file_action=my_act, &
     939            2 :                                    file_form="FORMATTED")
     940            2 :          IF (iw > 0) THEN
     941            1 :             IF (nspins == 2) THEN
     942              :                WRITE (UNIT=iw, FMT="(T2,A,I0,A,2F12.6)") &
     943            1 :                   "# DOS at iteration step i = ", iterstep, ", E_Fermi[a.u.] = ", e_fermi(1:2)
     944            1 :                WRITE (UNIT=iw, FMT="(T2,A, A)") "   Energy[a.u.]  Alpha_Density     Occupation", &
     945            2 :                   "   Beta_Density      Occupation"
     946              :             ELSE
     947              :                WRITE (UNIT=iw, FMT="(T2,A,I0,A,F12.6)") &
     948            0 :                   "# DOS at iteration step i = ", iterstep, ", E_Fermi[a.u.] = ", e_fermi(1)
     949            0 :                WRITE (UNIT=iw, FMT="(T2,A)") "   Energy[a.u.]       Density     Occupation"
     950              :             END IF
     951         4027 :             DO i = 1, nhist
     952         4026 :                eval = emin + (i - 1)*de
     953         4027 :                IF (nspins == 2) THEN
     954         4026 :                   WRITE (UNIT=iw, FMT="(F15.8,4F15.4)") eval, hist(i, 1), occval(i, 1), &
     955         8052 :                      hist(i, 2), occval(i, 2)
     956              :                ELSE
     957            0 :                   WRITE (UNIT=iw, FMT="(F15.8,2F15.4)") eval, hist(i, 1), occval(i, 1)
     958              :                END IF
     959              :             END DO
     960              :          END IF
     961            2 :          CALL cp_print_key_finished_output(iw, logger, print_section, "DOS")
     962              : 
     963            2 :          DEALLOCATE (energies, occupations, wkpt, slist)
     964            4 :          DEALLOCATE (hist, occval, ehist)
     965              :       END IF
     966            4 :    END SUBROUTINE cp_sirius_print_results
     967              : 
     968              : END MODULE sirius_interface
     969              : 
     970              : #else
     971              : 
     972              : !***************************************************************************************************
     973              : !> \brief Empty implementation in case SIRIUS is not compiled in.
     974              : !***************************************************************************************************
     975              : MODULE sirius_interface
     976              :    USE pwdft_environment_types, ONLY: pwdft_environment_type
     977              : #include "./base/base_uses.f90"
     978              : 
     979              :    IMPLICIT NONE
     980              : 
     981              :    PRIVATE
     982              : 
     983              :    ! Public subroutines
     984              : 
     985              :    PUBLIC :: cp_sirius_create_env, &
     986              :              cp_sirius_energy_force, &
     987              :              cp_sirius_finalize, &
     988              :              cp_sirius_init, &
     989              :              cp_sirius_is_initialized, &
     990              :              cp_sirius_update_context
     991              : 
     992              : CONTAINS
     993              : 
     994              : ! **************************************************************************************************
     995              : !> \brief Empty implementation in case SIRIUS is not compiled in.
     996              : ! **************************************************************************************************
     997              :    SUBROUTINE cp_sirius_init()
     998              :    END SUBROUTINE cp_sirius_init
     999              : 
    1000              : ! **************************************************************************************************
    1001              : !> \brief Return always .FALSE. because the Sirius library is not compiled in.
    1002              : !> \return Return the initialisation status of the Sirius library as boolean
    1003              : ! **************************************************************************************************
    1004              :    LOGICAL FUNCTION cp_sirius_is_initialized()
    1005              :       cp_sirius_is_initialized = .FALSE.
    1006              :    END FUNCTION cp_sirius_is_initialized
    1007              : 
    1008              : ! **************************************************************************************************
    1009              : !> \brief Empty implementation in case SIRIUS is not compiled in.
    1010              : ! **************************************************************************************************
    1011              :    SUBROUTINE cp_sirius_finalize()
    1012              :    END SUBROUTINE cp_sirius_finalize
    1013              : 
    1014              : ! **************************************************************************************************
    1015              : !> \brief Empty implementation in case SIRIUS is not compiled in.
    1016              : !> \param pwdft_env ...
    1017              : ! **************************************************************************************************
    1018              :    SUBROUTINE cp_sirius_create_env(pwdft_env)
    1019              :       TYPE(pwdft_environment_type), POINTER              :: pwdft_env
    1020              : 
    1021              :       MARK_USED(pwdft_env)
    1022              :       CPABORT("Sirius library is missing")
    1023              :    END SUBROUTINE cp_sirius_create_env
    1024              : 
    1025              : ! **************************************************************************************************
    1026              : !> \brief Empty implementation in case SIRIUS is not compiled in.
    1027              : !> \param pwdft_env ...
    1028              : !> \param calculate_forces ...
    1029              : !> \param calculate_stress ...
    1030              : ! **************************************************************************************************
    1031              :    SUBROUTINE cp_sirius_energy_force(pwdft_env, calculate_forces, calculate_stress)
    1032              :       TYPE(pwdft_environment_type), POINTER              :: pwdft_env
    1033              :       LOGICAL                                            :: calculate_forces, calculate_stress
    1034              : 
    1035              :       MARK_USED(pwdft_env)
    1036              :       MARK_USED(calculate_forces)
    1037              :       MARK_USED(calculate_stress)
    1038              :       CPABORT("Sirius library is missing")
    1039              :    END SUBROUTINE cp_sirius_energy_force
    1040              : 
    1041              : ! **************************************************************************************************
    1042              : !> \brief Empty implementation in case SIRIUS is not compiled in.
    1043              : !> \param pwdft_env ...
    1044              : ! **************************************************************************************************
    1045              :    SUBROUTINE cp_sirius_update_context(pwdft_env)
    1046              :       TYPE(pwdft_environment_type), POINTER              :: pwdft_env
    1047              : 
    1048              :       MARK_USED(pwdft_env)
    1049              :       CPABORT("Sirius library is missing")
    1050              :    END SUBROUTINE cp_sirius_update_context
    1051              : 
    1052              : END MODULE sirius_interface
    1053              : 
    1054              : #endif
        

Generated by: LCOV version 2.0-1