! This Source Code Form is subject to the terms of the Mozilla Public ! License, v. 2.0. If a copy of the MPL was not distributed with this ! file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef DO_COMPLEX_TYPE module mbd_elsi use elsi, only: elsi_handle, elsi_init, elsi_set_mpi, elsi_set_blacs, & elsi_set_unit_ovlp, elsi_finalize, elsi_ev_real, elsi_ev_complex use mbd_constants use mbd_blacs, only: blacs_desc_t use mbd_utils, only: exception_t, is_true implicit none private public :: elsi_eigh, elsi_eigvalsh interface elsi_eigh module procedure elsi_eigh_real module procedure elsi_eigh_complex end interface interface elsi_eigvalsh module procedure elsi_eigvalsh_real module procedure elsi_eigvalsh_complex end interface contains #endif #ifndef DO_COMPLEX_TYPE subroutine elsi_eigh_real(A, blacs_desc, eigs, exc, src, vals_only) real(dp), intent(inout) :: A(:, :) real(dp), intent(in), optional :: src(:, :) #else subroutine elsi_eigh_complex(A, blacs_desc, eigs, exc, src, vals_only) complex(dp), intent(inout) :: A(:, :) complex(dp), intent(in), optional :: src(:, :) #endif type(blacs_desc_t), intent(in) :: blacs_desc real(dp), intent(out) :: eigs(:) type(exception_t), intent(out), optional :: exc logical, intent(in), optional :: vals_only integer :: n_vecs, n type(elsi_handle) :: handle #ifndef DO_COMPLEX_TYPE real(dp) :: DUMMY_MATRIX(1, 1) real(dp), allocatable :: vecs(:, :) #else complex(dp) :: DUMMY_MATRIX(1, 1) complex(dp), allocatable :: vecs(:, :) #endif n = 3 * blacs_desc%n_atoms if (present(src)) A = src if (is_true(vals_only)) then n_vecs = 0 else n_vecs = n end if call elsi_init(handle, 1, 1, 0, n, 0d0, n_vecs) call elsi_set_mpi(handle, blacs_desc%comm) call elsi_set_blacs(handle, blacs_desc%ctx, blacs_desc%blocksize) call elsi_set_unit_ovlp(handle, 1) allocate (vecs(size(A, 1), size(A, 2))) #ifndef DO_COMPLEX_TYPE call elsi_ev_real(handle, A, DUMMY_MATRIX, eigs, vecs) #else call elsi_ev_complex(handle, A, DUMMY_MATRIX, eigs, vecs) #endif A = vecs call elsi_finalize(handle) end subroutine #ifndef DO_COMPLEX_TYPE function elsi_eigvalsh_real(A, blacs_desc, exc, destroy) result(eigs) real(dp), allocatable, intent(inout) :: A(:, :) #else function elsi_eigvalsh_complex(A, blacs_desc, exc, destroy) result(eigs) complex(dp), allocatable, intent(inout) :: A(:, :) #endif type(blacs_desc_t), intent(in) :: blacs_desc type(exception_t), intent(out), optional :: exc logical, intent(in), optional :: destroy real(dp) :: eigs(3 * blacs_desc%n_atoms) #ifndef DO_COMPLEX_TYPE real(dp), allocatable :: A_(:, :) #else complex(dp), allocatable :: A_(:, :) #endif if (is_true(destroy)) then call move_alloc(A, A_) else A_ = A end if call elsi_eigh(A_, blacs_desc, eigs, exc, vals_only=.true.) end function #ifndef DO_COMPLEX_TYPE # define DO_COMPLEX_TYPE # include "mbd_elsi.F90" end module #endif