LCOV - code coverage report
Current view: top level - src - ri_environment_methods.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:3130539) Lines: 0 250 0.0 %
Date: 2025-05-14 06:57:18 Functions: 0 7 0.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief Calculates integral matrices for RIGPW method
      10             : !> \par History
      11             : !>      created JGH [08.2012]
      12             : !>      Dorothea Golze [02.2014] (1) extended, re-structured, cleaned
      13             : !>                               (2) heavily debugged
      14             : !>      updated for RI JGH [08.2017]
      15             : !> \authors JGH
      16             : !>          Dorothea Golze
      17             : ! **************************************************************************************************
      18             : MODULE ri_environment_methods
      19             :    USE arnoldi_api,                     ONLY: arnoldi_conjugate_gradient
      20             :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      21             :                                               get_atomic_kind_set
      22             :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      23             :    USE cp_control_types,                ONLY: dft_control_type
      24             :    USE cp_dbcsr_api,                    ONLY: &
      25             :         dbcsr_add, dbcsr_create, dbcsr_get_info, dbcsr_iterator_blocks_left, &
      26             :         dbcsr_iterator_next_block, dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, &
      27             :         dbcsr_multiply, dbcsr_p_type, dbcsr_release, dbcsr_set, dbcsr_type, &
      28             :         dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, dbcsr_type_symmetric
      29             :    USE cp_dbcsr_contrib,                ONLY: dbcsr_dot,&
      30             :                                               dbcsr_scale_by_vector
      31             :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      32             :    USE cp_dbcsr_diag,                   ONLY: cp_dbcsr_syevd
      33             :    USE cp_dbcsr_operations,             ONLY: dbcsr_allocate_matrix_set
      34             :    USE iterate_matrix,                  ONLY: invert_Hotelling
      35             :    USE kinds,                           ONLY: dp
      36             :    USE lri_environment_types,           ONLY: allocate_lri_coefs,&
      37             :                                               lri_density_create,&
      38             :                                               lri_density_release,&
      39             :                                               lri_density_type,&
      40             :                                               lri_environment_type,&
      41             :                                               lri_kind_type
      42             :    USE message_passing,                 ONLY: mp_comm_type,&
      43             :                                               mp_para_env_type
      44             :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      45             :                                               pw_r3d_rs_type
      46             :    USE qs_collocate_density,            ONLY: calculate_lri_rho_elec
      47             :    USE qs_environment_types,            ONLY: get_qs_env,&
      48             :                                               qs_environment_type,&
      49             :                                               set_qs_env
      50             :    USE qs_ks_types,                     ONLY: qs_ks_env_type
      51             :    USE qs_o3c_methods,                  ONLY: calculate_o3c_integrals,&
      52             :                                               contract12_o3c
      53             :    USE qs_o3c_types,                    ONLY: get_o3c_iterator_info,&
      54             :                                               init_o3c_container,&
      55             :                                               o3c_container_type,&
      56             :                                               o3c_iterate,&
      57             :                                               o3c_iterator_create,&
      58             :                                               o3c_iterator_release,&
      59             :                                               o3c_iterator_type,&
      60             :                                               release_o3c_container
      61             :    USE qs_overlap,                      ONLY: build_overlap_matrix
      62             :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      63             :                                               qs_rho_type
      64             :    USE util,                            ONLY: get_limit
      65             : 
      66             : !$ USE OMP_LIB, ONLY: omp_get_max_threads, omp_get_thread_num
      67             : #include "./base/base_uses.f90"
      68             : 
      69             :    IMPLICIT NONE
      70             : 
      71             :    PRIVATE
      72             : 
      73             : ! **************************************************************************************************
      74             : 
      75             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ri_environment_methods'
      76             : 
      77             :    PUBLIC :: build_ri_matrices, calculate_ri_densities, ri_metric_solver
      78             : 
      79             : ! **************************************************************************************************
      80             : 
      81             : CONTAINS
      82             : 
      83             : ! **************************************************************************************************
      84             : !> \brief creates and initializes an lri_env
      85             : !> \param lri_env the lri_environment you want to create
      86             : !> \param qs_env ...
      87             : !> \param calculate_forces ...
      88             : ! **************************************************************************************************
      89           0 :    SUBROUTINE build_ri_matrices(lri_env, qs_env, calculate_forces)
      90             : 
      91             :       TYPE(lri_environment_type), POINTER                :: lri_env
      92             :       TYPE(qs_environment_type), POINTER                 :: qs_env
      93             :       LOGICAL, INTENT(IN)                                :: calculate_forces
      94             : 
      95           0 :       CALL calculate_ri_integrals(lri_env, qs_env, calculate_forces)
      96             : 
      97           0 :    END SUBROUTINE build_ri_matrices
      98             : 
      99             : ! **************************************************************************************************
     100             : !> \brief calculates integrals needed for the RI density fitting,
     101             : !>        integrals are calculated once, before the SCF starts
     102             : !> \param lri_env ...
     103             : !> \param qs_env ...
     104             : !> \param calculate_forces ...
     105             : ! **************************************************************************************************
     106           0 :    SUBROUTINE calculate_ri_integrals(lri_env, qs_env, calculate_forces)
     107             : 
     108             :       TYPE(lri_environment_type), POINTER                :: lri_env
     109             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     110             :       LOGICAL, INTENT(IN)                                :: calculate_forces
     111             : 
     112             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_ri_integrals'
     113             :       REAL(KIND=dp), DIMENSION(2), PARAMETER             :: fx = (/0.0_dp, 1.0_dp/)
     114             : 
     115             :       INTEGER                                            :: handle, i, i1, i2, iatom, ispin, izero, &
     116             :                                                             j, j1, j2, jatom, m, n, nbas
     117           0 :       INTEGER, DIMENSION(:, :), POINTER                  :: bas_ptr
     118             :       REAL(KIND=dp)                                      :: fpre
     119           0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eval
     120           0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: avec, fblk, fout
     121             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     122             :       TYPE(dbcsr_iterator_type)                          :: iter
     123           0 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_p
     124             :       TYPE(dbcsr_type)                                   :: emat
     125             :       TYPE(dbcsr_type), POINTER                          :: fmat
     126             :       TYPE(dft_control_type), POINTER                    :: dft_control
     127             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     128             :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     129             :       TYPE(qs_rho_type), POINTER                         :: rho
     130             : 
     131           0 :       CALL timeset(routineN, handle)
     132             : 
     133           0 :       CPASSERT(ASSOCIATED(lri_env))
     134           0 :       CPASSERT(ASSOCIATED(qs_env))
     135             : 
     136             :       ! overlap matrices
     137           0 :       CALL get_qs_env(qs_env=qs_env, ks_env=ks_env)
     138           0 :       CALL get_qs_env(qs_env=qs_env, dft_control=dft_control)
     139           0 :       NULLIFY (rho, matrix_p)
     140             :       ! orbital overlap matrix (needed for N constraints and forces)
     141             :       ! we replicate this in order to not directly interact qith qs_env
     142           0 :       IF (calculate_forces) THEN
     143             :          ! charge constraint forces are calculated here
     144           0 :          CALL get_qs_env(qs_env=qs_env, rho=rho)
     145           0 :          CALL qs_rho_get(rho, rho_ao=matrix_p)
     146           0 :          ALLOCATE (fmat)
     147           0 :          CALL dbcsr_create(fmat, template=matrix_p(1)%matrix)
     148           0 :          DO ispin = 1, dft_control%nspins
     149           0 :             fpre = lri_env%ri_fit%ftrm1n(ispin)/lri_env%ri_fit%ntrm1n
     150           0 :             CALL dbcsr_add(fmat, matrix_p(ispin)%matrix, fx(ispin), -fpre)
     151             :          END DO
     152             :          CALL build_overlap_matrix(ks_env=ks_env, matrix_s=lri_env%ob_smat, nderivative=0, &
     153             :                                    basis_type_a="ORB", basis_type_b="ORB", sab_nl=lri_env%soo_list, &
     154           0 :                                    calculate_forces=.TRUE., matrix_p=fmat)
     155           0 :          CALL dbcsr_release(fmat)
     156           0 :          DEALLOCATE (fmat)
     157             :       ELSE
     158             :          CALL build_overlap_matrix(ks_env=ks_env, matrix_s=lri_env%ob_smat, nderivative=0, &
     159           0 :                                    basis_type_a="ORB", basis_type_b="ORB", sab_nl=lri_env%soo_list)
     160             :       END IF
     161             :       ! RI overlap matrix
     162             :       CALL build_overlap_matrix(ks_env=ks_env, matrix_s=lri_env%ri_smat, nderivative=0, &
     163           0 :                                 basis_type_a="RI_HXC", basis_type_b="RI_HXC", sab_nl=lri_env%saa_list)
     164           0 :       IF (calculate_forces) THEN
     165             :          ! calculate f*a(T) pseudo density matrix for forces
     166           0 :          bas_ptr => lri_env%ri_fit%bas_ptr
     167           0 :          avec => lri_env%ri_fit%avec
     168           0 :          fout => lri_env%ri_fit%fout
     169           0 :          ALLOCATE (fmat)
     170           0 :          CALL dbcsr_create(fmat, template=lri_env%ri_smat(1)%matrix)
     171           0 :          CALL cp_dbcsr_alloc_block_from_nbl(fmat, lri_env%saa_list)
     172           0 :          CALL dbcsr_set(fmat, 0.0_dp)
     173           0 :          CALL dbcsr_iterator_start(iter, fmat)
     174           0 :          DO WHILE (dbcsr_iterator_blocks_left(iter))
     175           0 :             CALL dbcsr_iterator_next_block(iter, iatom, jatom, fblk)
     176           0 :             i1 = bas_ptr(1, iatom)
     177           0 :             i2 = bas_ptr(2, iatom)
     178           0 :             j1 = bas_ptr(1, jatom)
     179           0 :             j2 = bas_ptr(2, jatom)
     180           0 :             IF (iatom <= jatom) THEN
     181           0 :                DO ispin = 1, dft_control%nspins
     182           0 :                   DO j = j1, j2
     183           0 :                      m = j - j1 + 1
     184           0 :                      DO i = i1, i2
     185           0 :                         n = i - i1 + 1
     186           0 :                         fblk(n, m) = fblk(n, m) + fout(i, ispin)*avec(j, ispin) + avec(i, ispin)*fout(j, ispin)
     187             :                      END DO
     188             :                   END DO
     189             :                END DO
     190             :             ELSE
     191           0 :                DO ispin = 1, dft_control%nspins
     192           0 :                   DO i = i1, i2
     193           0 :                      n = i - i1 + 1
     194           0 :                      DO j = j1, j2
     195           0 :                         m = j - j1 + 1
     196           0 :                         fblk(m, n) = fblk(m, n) + fout(i, ispin)*avec(j, ispin) + avec(i, ispin)*fout(j, ispin)
     197             :                      END DO
     198             :                   END DO
     199             :                END DO
     200             :             END IF
     201           0 :             IF (iatom == jatom) THEN
     202           0 :                fblk(:, :) = 0.25_dp*fblk(:, :)
     203             :             ELSE
     204           0 :                fblk(:, :) = 0.5_dp*fblk(:, :)
     205             :             END IF
     206             :          END DO
     207           0 :          CALL dbcsr_iterator_stop(iter)
     208             :          !
     209             :          CALL build_overlap_matrix(ks_env=ks_env, matrix_s=lri_env%ri_smat, nderivative=0, &
     210             :                                    basis_type_a="RI_HXC", basis_type_b="RI_HXC", sab_nl=lri_env%saa_list, &
     211           0 :                                    calculate_forces=.TRUE., matrix_p=fmat)
     212           0 :          CALL dbcsr_release(fmat)
     213           0 :          DEALLOCATE (fmat)
     214             :       END IF
     215             :       ! approximation (preconditioner) or exact inverse of RI overlap
     216           0 :       CALL dbcsr_allocate_matrix_set(lri_env%ri_sinv, 1)
     217           0 :       ALLOCATE (lri_env%ri_sinv(1)%matrix)
     218           0 :       SELECT CASE (lri_env%ri_sinv_app)
     219             :       CASE ("NONE")
     220             :          !
     221             :       CASE ("INVS")
     222           0 :          CALL dbcsr_create(lri_env%ri_sinv(1)%matrix, template=lri_env%ri_smat(1)%matrix)
     223             :          CALL invert_Hotelling(lri_env%ri_sinv(1)%matrix, lri_env%ri_smat(1)%matrix, &
     224             :                                threshold=1.e-10_dp, use_inv_as_guess=.FALSE., &
     225           0 :                                norm_convergence=1.e-10_dp, filter_eps=1.e-12_dp, silent=.FALSE.)
     226             :       CASE ("INVF")
     227           0 :          CALL dbcsr_create(emat, matrix_type=dbcsr_type_no_symmetry, template=lri_env%ri_smat(1)%matrix)
     228           0 :          CALL get_qs_env(qs_env=qs_env, para_env=para_env, blacs_env=blacs_env)
     229           0 :          CALL dbcsr_get_info(lri_env%ri_smat(1)%matrix, nfullrows_total=nbas)
     230           0 :          ALLOCATE (eval(nbas))
     231           0 :          CALL cp_dbcsr_syevd(lri_env%ri_smat(1)%matrix, emat, eval, para_env, blacs_env)
     232           0 :          izero = 0
     233           0 :          DO i = 1, nbas
     234           0 :             IF (eval(i) < 1.0e-10_dp) THEN
     235           0 :                eval(i) = 0.0_dp
     236           0 :                izero = izero + 1
     237             :             ELSE
     238           0 :                eval(i) = SQRT(1.0_dp/eval(i))
     239             :             END IF
     240             :          END DO
     241           0 :          CALL dbcsr_scale_by_vector(emat, eval, side='right')
     242           0 :          CALL dbcsr_create(lri_env%ri_sinv(1)%matrix, template=lri_env%ri_smat(1)%matrix)
     243           0 :          CALL dbcsr_multiply("N", "T", 1.0_dp, emat, emat, 0.0_dp, lri_env%ri_sinv(1)%matrix)
     244           0 :          DEALLOCATE (eval)
     245           0 :          CALL dbcsr_release(emat)
     246             :       CASE ("AINV")
     247           0 :          CALL dbcsr_create(lri_env%ri_sinv(1)%matrix, template=lri_env%ri_smat(1)%matrix)
     248             :          CALL invert_Hotelling(lri_env%ri_sinv(1)%matrix, lri_env%ri_smat(1)%matrix, &
     249             :                                threshold=1.e-5_dp, use_inv_as_guess=.FALSE., &
     250           0 :                                norm_convergence=1.e-4_dp, filter_eps=1.e-4_dp, silent=.FALSE.)
     251             :       CASE DEFAULT
     252           0 :          CPABORT("Unknown RI_SINV type")
     253             :       END SELECT
     254             : 
     255             :       ! solve Rx=n
     256             :       CALL ri_metric_solver(mat=lri_env%ri_smat(1)%matrix, &
     257             :                             vecr=lri_env%ri_fit%nvec, &
     258             :                             vecx=lri_env%ri_fit%rm1n, &
     259             :                             matp=lri_env%ri_sinv(1)%matrix, &
     260             :                             solver=lri_env%ri_sinv_app, &
     261           0 :                             ptr=lri_env%ri_fit%bas_ptr)
     262             : 
     263             :       ! calculate n(t)x
     264           0 :       lri_env%ri_fit%ntrm1n = SUM(lri_env%ri_fit%nvec(:)*lri_env%ri_fit%rm1n(:))
     265             : 
     266             :       ! calculate 3c-overlap integrals
     267           0 :       IF (ASSOCIATED(lri_env%o3c)) THEN
     268           0 :          CALL release_o3c_container(lri_env%o3c)
     269             :       ELSE
     270           0 :          ALLOCATE (lri_env%o3c)
     271             :       END IF
     272             :       CALL init_o3c_container(lri_env%o3c, dft_control%nspins, &
     273             :                               lri_env%orb_basis, lri_env%orb_basis, lri_env%ri_basis, &
     274           0 :                               lri_env%soo_list, lri_env%soa_list)
     275             : 
     276           0 :       CALL calculate_o3c_integrals(lri_env%o3c, calculate_forces, matrix_p)
     277             : 
     278           0 :       CALL timestop(handle)
     279             : 
     280           0 :    END SUBROUTINE calculate_ri_integrals
     281             : ! **************************************************************************************************
     282             : !> \brief solver for RI systems (R*x=n)
     283             : !> \param mat ...
     284             : !> \param vecr ...
     285             : !> \param vecx ...
     286             : !> \param matp ...
     287             : !> \param solver ...
     288             : !> \param ptr ...
     289             : ! **************************************************************************************************
     290           0 :    SUBROUTINE ri_metric_solver(mat, vecr, vecx, matp, solver, ptr)
     291             : 
     292             :       TYPE(dbcsr_type)                                   :: mat
     293             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: vecr
     294             :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: vecx
     295             :       TYPE(dbcsr_type)                                   :: matp
     296             :       CHARACTER(LEN=*), INTENT(IN)                       :: solver
     297             :       INTEGER, DIMENSION(:, :), INTENT(IN)               :: ptr
     298             : 
     299             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'ri_metric_solver'
     300             : 
     301             :       INTEGER                                            :: handle, max_iter, n
     302             :       LOGICAL                                            :: converged
     303             :       REAL(KIND=dp)                                      :: rerror, threshold
     304           0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: vect
     305             : 
     306           0 :       CALL timeset(routineN, handle)
     307             : 
     308           0 :       threshold = 1.e-10_dp
     309           0 :       max_iter = 100
     310             : 
     311           0 :       vecx(:) = vecr(:)
     312             : 
     313           0 :       SELECT CASE (solver)
     314             :       CASE ("NONE")
     315             :          CALL arnoldi_conjugate_gradient(mat, vecx, &
     316           0 :                                          converged=converged, threshold=threshold, max_iter=max_iter)
     317             :       CASE ("INVS", "INVF")
     318           0 :          converged = .FALSE.
     319           0 :          CALL ri_matvec(matp, vecr, vecx, ptr)
     320             :       CASE ("AINV")
     321             :          CALL arnoldi_conjugate_gradient(mat, vecx, matrix_p=matp, &
     322           0 :                                          converged=converged, threshold=threshold, max_iter=max_iter)
     323             :       CASE DEFAULT
     324           0 :          CPABORT("Unknown RI solver")
     325             :       END SELECT
     326             : 
     327           0 :       IF (.NOT. converged) THEN
     328             :          ! get error
     329           0 :          rerror = 0.0_dp
     330           0 :          n = SIZE(vecr)
     331           0 :          ALLOCATE (vect(n))
     332           0 :          CALL ri_matvec(mat, vecx, vect, ptr)
     333           0 :          vect(:) = vect(:) - vecr(:)
     334           0 :          rerror = MAXVAL(ABS(vect(:)))
     335           0 :          DEALLOCATE (vect)
     336           0 :          CPWARN_IF(rerror > threshold, "RI solver: CG did not converge properly")
     337             :       END IF
     338             : 
     339           0 :       CALL timestop(handle)
     340             : 
     341           0 :    END SUBROUTINE ri_metric_solver
     342             : 
     343             : ! **************************************************************************************************
     344             : !> \brief performs the fitting of the density and distributes the fitted
     345             : !>        density on the grid
     346             : !> \param lri_env the lri environment
     347             : !>        lri_density the environment for the fitting
     348             : !>        pmatrix density matrix
     349             : !>        lri_rho_struct where the fitted density is stored
     350             : !> \param qs_env ...
     351             : !> \param pmatrix ...
     352             : !> \param lri_rho_struct ...
     353             : !> \param atomic_kind_set ...
     354             : !> \param para_env ...
     355             : ! **************************************************************************************************
     356           0 :    SUBROUTINE calculate_ri_densities(lri_env, qs_env, pmatrix, &
     357             :                                      lri_rho_struct, atomic_kind_set, para_env)
     358             : 
     359             :       TYPE(lri_environment_type), POINTER                :: lri_env
     360             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     361             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: pmatrix
     362             :       TYPE(qs_rho_type), INTENT(IN)                      :: lri_rho_struct
     363             :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     364             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     365             : 
     366             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_ri_densities'
     367             : 
     368             :       INTEGER                                            :: atom_a, handle, i1, i2, iatom, ikind, &
     369             :                                                             ispin, n, natom, nspin
     370           0 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_of_kind, kind_of
     371           0 :       INTEGER, DIMENSION(:, :), POINTER                  :: bas_ptr
     372           0 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: tot_rho_r
     373           0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: avec
     374             :       TYPE(lri_density_type), POINTER                    :: lri_density
     375           0 :       TYPE(lri_kind_type), DIMENSION(:), POINTER         :: lri_coef
     376           0 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: rho_g
     377           0 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r
     378             : 
     379           0 :       CALL timeset(routineN, handle)
     380             : 
     381           0 :       nspin = SIZE(pmatrix, 1)
     382           0 :       CALL contract12_o3c(lri_env%o3c, pmatrix)
     383           0 :       CALL calculate_tvec_ri(lri_env, lri_env%o3c, para_env)
     384           0 :       CALL calculate_avec_ri(lri_env, pmatrix)
     385             :       !
     386           0 :       CALL get_qs_env(qs_env, lri_density=lri_density, natom=natom)
     387           0 :       IF (ASSOCIATED(lri_density)) THEN
     388           0 :          CALL lri_density_release(lri_density)
     389             :       ELSE
     390           0 :          ALLOCATE (lri_density)
     391             :       END IF
     392           0 :       CALL lri_density_create(lri_density)
     393           0 :       lri_density%nspin = nspin
     394             :       ! allocate the arrays to hold RI expansion coefficients lri_coefs
     395           0 :       CALL allocate_lri_coefs(lri_env, lri_density, atomic_kind_set)
     396             :       ! reassign avec
     397           0 :       avec => lri_env%ri_fit%avec
     398           0 :       bas_ptr => lri_env%ri_fit%bas_ptr
     399           0 :       ALLOCATE (atom_of_kind(natom), kind_of(natom))
     400           0 :       CALL get_atomic_kind_set(atomic_kind_set, atom_of_kind=atom_of_kind, kind_of=kind_of)
     401           0 :       DO ispin = 1, nspin
     402           0 :          lri_coef => lri_density%lri_coefs(ispin)%lri_kinds
     403           0 :          DO iatom = 1, natom
     404           0 :             ikind = kind_of(iatom)
     405           0 :             atom_a = atom_of_kind(iatom)
     406           0 :             i1 = bas_ptr(1, iatom)
     407           0 :             i2 = bas_ptr(2, iatom)
     408           0 :             n = i2 - i1 + 1
     409           0 :             lri_coef(ikind)%acoef(atom_a, 1:n) = avec(i1:i2, ispin)
     410             :          END DO
     411             :       END DO
     412           0 :       CALL set_qs_env(qs_env, lri_density=lri_density)
     413           0 :       DEALLOCATE (atom_of_kind, kind_of)
     414             :       !
     415           0 :       CALL qs_rho_get(lri_rho_struct, rho_r=rho_r, rho_g=rho_g, tot_rho_r=tot_rho_r)
     416           0 :       DO ispin = 1, nspin
     417           0 :          lri_coef => lri_density%lri_coefs(ispin)%lri_kinds
     418             :          CALL calculate_lri_rho_elec(rho_g(ispin), rho_r(ispin), qs_env, &
     419           0 :                                      lri_coef, tot_rho_r(ispin), "RI_HXC", .FALSE.)
     420             :       END DO
     421             : 
     422           0 :       CALL timestop(handle)
     423             : 
     424           0 :    END SUBROUTINE calculate_ri_densities
     425             : 
     426             : ! **************************************************************************************************
     427             : !> \brief assembles the global vector t=<P.T>
     428             : !> \param lri_env the lri environment
     429             : !> \param o3c ...
     430             : !> \param para_env ...
     431             : ! **************************************************************************************************
     432           0 :    SUBROUTINE calculate_tvec_ri(lri_env, o3c, para_env)
     433             : 
     434             :       TYPE(lri_environment_type), POINTER                :: lri_env
     435             :       TYPE(o3c_container_type), POINTER                  :: o3c
     436             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     437             : 
     438             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'calculate_tvec_ri'
     439             :       INTEGER, PARAMETER                                 :: msweep = 32
     440             : 
     441             :       INTEGER                                            :: handle, i1, i2, ibl, ibu, il, ispin, &
     442             :                                                             isweep, it, iu, katom, m, ma, mba, &
     443             :                                                             mepos, natom, nspin, nsweep, nthread
     444             :       INTEGER, DIMENSION(2, msweep)                      :: nlimit
     445           0 :       INTEGER, DIMENSION(:, :), POINTER                  :: bas_ptr
     446           0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: ta
     447           0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: rm1t, tvec, tvl
     448             :       TYPE(o3c_iterator_type)                            :: o3c_iterator
     449             : 
     450           0 :       CALL timeset(routineN, handle)
     451             : 
     452           0 :       nspin = SIZE(lri_env%ri_fit%tvec, 2)
     453           0 :       bas_ptr => lri_env%ri_fit%bas_ptr
     454           0 :       tvec => lri_env%ri_fit%tvec
     455           0 :       tvec = 0.0_dp
     456           0 :       natom = SIZE(bas_ptr, 2)
     457             :       nthread = 1
     458           0 : !$    nthread = omp_get_max_threads()
     459             : 
     460           0 :       IF (natom < 1000) THEN
     461           0 :          nsweep = 1
     462             :       ELSE
     463           0 :          nsweep = MIN(nthread, msweep)
     464             :       END IF
     465             : 
     466           0 :       nlimit = 0
     467           0 :       DO isweep = 1, nsweep
     468           0 :          nlimit(1:2, isweep) = get_limit(natom, nsweep, isweep - 1)
     469             :       END DO
     470             : 
     471           0 :       DO ispin = 1, nspin
     472           0 :          DO isweep = 1, nsweep
     473           0 :             il = nlimit(1, isweep)
     474           0 :             iu = nlimit(2, isweep)
     475           0 :             ma = iu - il + 1
     476           0 :             IF (ma < 1) CYCLE
     477           0 :             ibl = bas_ptr(1, il)
     478           0 :             ibu = bas_ptr(2, iu)
     479           0 :             mba = ibu - ibl + 1
     480           0 :             ALLOCATE (ta(mba, nthread))
     481           0 :             ta = 0.0_dp
     482             : 
     483           0 :             CALL o3c_iterator_create(o3c, o3c_iterator, nthread=nthread)
     484             : 
     485             : !$OMP PARALLEL DEFAULT(NONE)&
     486             : !$OMP SHARED (nthread,o3c_iterator,ispin,il,iu,ibl,ta,bas_ptr)&
     487           0 : !$OMP PRIVATE (mepos,katom,tvl,i1,i2,m)
     488             : 
     489             :             mepos = 0
     490             : !$          mepos = omp_get_thread_num()
     491             : 
     492             :             DO WHILE (o3c_iterate(o3c_iterator, mepos=mepos) == 0)
     493             :                CALL get_o3c_iterator_info(o3c_iterator, mepos=mepos, katom=katom, tvec=tvl)
     494             :                IF (katom < il .OR. katom > iu) CYCLE
     495             :                i1 = bas_ptr(1, katom) - ibl + 1
     496             :                i2 = bas_ptr(2, katom) - ibl + 1
     497             :                m = i2 - i1 + 1
     498             :                ta(i1:i2, mepos + 1) = ta(i1:i2, mepos + 1) + tvl(1:m, ispin)
     499             :             END DO
     500             : !$OMP END PARALLEL
     501           0 :             CALL o3c_iterator_release(o3c_iterator)
     502             : 
     503             :             ! sum over threads
     504           0 :             DO it = 1, nthread
     505           0 :                tvec(ibl:ibu, ispin) = tvec(ibl:ibu, ispin) + ta(1:mba, it)
     506             :             END DO
     507           0 :             DEALLOCATE (ta)
     508             :          END DO
     509             :       END DO
     510             : 
     511             :       ! global summation
     512           0 :       CALL para_env%sum(tvec)
     513             : 
     514           0 :       rm1t => lri_env%ri_fit%rm1t
     515           0 :       DO ispin = 1, nspin
     516             :          ! solve Rx=t
     517             :          CALL ri_metric_solver(mat=lri_env%ri_smat(1)%matrix, &
     518             :                                vecr=tvec(:, ispin), &
     519             :                                vecx=rm1t(:, ispin), &
     520             :                                matp=lri_env%ri_sinv(1)%matrix, &
     521             :                                solver=lri_env%ri_sinv_app, &
     522           0 :                                ptr=bas_ptr)
     523             :       END DO
     524             : 
     525           0 :       CALL timestop(handle)
     526             : 
     527           0 :    END SUBROUTINE calculate_tvec_ri
     528             : ! **************************************************************************************************
     529             : !> \brief performs the fitting of the density in the RI method
     530             : !> \param lri_env the lri environment
     531             : !>        lri_density the environment for the fitting
     532             : !>        pmatrix density matrix
     533             : !> \param pmatrix ...
     534             : ! **************************************************************************************************
     535           0 :    SUBROUTINE calculate_avec_ri(lri_env, pmatrix)
     536             : 
     537             :       TYPE(lri_environment_type), POINTER                :: lri_env
     538             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: pmatrix
     539             : 
     540             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'calculate_avec_ri'
     541             : 
     542             :       INTEGER                                            :: handle, ispin, nspin
     543             :       REAL(KIND=dp)                                      :: etr, nelec, nrm1t
     544           0 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: nvec, rm1n
     545           0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: avec, rm1t, tvec
     546           0 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: smatrix
     547             : 
     548           0 :       CALL timeset(routineN, handle)
     549             : 
     550           0 :       nspin = SIZE(pmatrix)
     551             :       ! number of electrons
     552           0 :       smatrix => lri_env%ob_smat
     553           0 :       DO ispin = 1, nspin
     554             :          etr = 0.0_dp
     555           0 :          CALL dbcsr_dot(smatrix(1)%matrix, pmatrix(ispin)%matrix, etr)
     556           0 :          lri_env%ri_fit%echarge(ispin) = etr
     557             :       END DO
     558             : 
     559           0 :       tvec => lri_env%ri_fit%tvec
     560           0 :       rm1t => lri_env%ri_fit%rm1t
     561           0 :       nvec => lri_env%ri_fit%nvec
     562           0 :       rm1n => lri_env%ri_fit%rm1n
     563             : 
     564             :       ! calculate lambda
     565           0 :       DO ispin = 1, nspin
     566           0 :          nelec = lri_env%ri_fit%echarge(ispin)
     567           0 :          nrm1t = SUM(nvec(:)*rm1t(:, ispin))
     568           0 :          lri_env%ri_fit%lambda(ispin) = 2.0_dp*(nrm1t - nelec)/lri_env%ri_fit%ntrm1n
     569             :       END DO
     570             : 
     571             :       ! calculate avec = rm1t - lambda/2 * rm1n
     572           0 :       avec => lri_env%ri_fit%avec
     573           0 :       DO ispin = 1, nspin
     574           0 :          avec(:, ispin) = rm1t(:, ispin) - 0.5_dp*lri_env%ri_fit%lambda(ispin)*rm1n(:)
     575             :       END DO
     576             : 
     577           0 :       CALL timestop(handle)
     578             : 
     579           0 :    END SUBROUTINE calculate_avec_ri
     580             : 
     581             : ! **************************************************************************************************
     582             : !> \brief Mutiplies a replicated vector with a DBCSR matrix: vo = mat*vi
     583             : !> \param mat ...
     584             : !> \param vi ...
     585             : !> \param vo ...
     586             : !> \param ptr ...
     587             : ! **************************************************************************************************
     588           0 :    SUBROUTINE ri_matvec(mat, vi, vo, ptr)
     589             : 
     590             :       TYPE(dbcsr_type)                                   :: mat
     591             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: vi
     592             :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: vo
     593             :       INTEGER, DIMENSION(:, :), INTENT(IN)               :: ptr
     594             : 
     595             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'ri_matvec'
     596             : 
     597             :       CHARACTER                                          :: matrix_type
     598             :       INTEGER                                            :: handle, iatom, jatom, m1, m2, mb, n1, &
     599             :                                                             n2, nb
     600             :       LOGICAL                                            :: symm
     601           0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
     602             :       TYPE(dbcsr_iterator_type)                          :: iter
     603             :       TYPE(mp_comm_type)                                 :: group
     604             : 
     605           0 :       CALL timeset(routineN, handle)
     606             : 
     607           0 :       CALL dbcsr_get_info(mat, matrix_type=matrix_type, group=group)
     608             : 
     609             :       SELECT CASE (matrix_type)
     610             :       CASE (dbcsr_type_no_symmetry)
     611           0 :          symm = .FALSE.
     612             :       CASE (dbcsr_type_symmetric)
     613           0 :          symm = .TRUE.
     614             :       CASE (dbcsr_type_antisymmetric)
     615           0 :          CPABORT("NYI, antisymmetric matrix not permitted")
     616             :       CASE DEFAULT
     617           0 :          CPABORT("Unknown matrix type, ...")
     618             :       END SELECT
     619             : 
     620           0 :       vo(:) = 0.0_dp
     621           0 :       CALL dbcsr_iterator_start(iter, mat)
     622           0 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     623           0 :          CALL dbcsr_iterator_next_block(iter, iatom, jatom, block)
     624           0 :          n1 = ptr(1, iatom)
     625           0 :          n2 = ptr(2, iatom)
     626           0 :          nb = n2 - n1 + 1
     627           0 :          m1 = ptr(1, jatom)
     628           0 :          m2 = ptr(2, jatom)
     629           0 :          mb = m2 - m1 + 1
     630           0 :          CPASSERT(nb == SIZE(block, 1))
     631           0 :          CPASSERT(mb == SIZE(block, 2))
     632           0 :          vo(n1:n2) = vo(n1:n2) + MATMUL(block, vi(m1:m2))
     633           0 :          IF (symm .AND. (iatom /= jatom)) THEN
     634           0 :             vo(m1:m2) = vo(m1:m2) + MATMUL(TRANSPOSE(block), vi(n1:n2))
     635             :          END IF
     636             :       END DO
     637           0 :       CALL dbcsr_iterator_stop(iter)
     638             : 
     639           0 :       CALL group%sum(vo)
     640             : 
     641           0 :       CALL timestop(handle)
     642             : 
     643           0 :    END SUBROUTINE ri_matvec
     644             : 
     645           0 : END MODULE ri_environment_methods

Generated by: LCOV version 1.15