Commit a8b4ae57 authored by Victor Yu's avatar Victor Yu

Merge branch 'generic_coo' into 'master'

Generic COO

See merge request elsi-devel/elsi-interface!87
parents 9da4affe 0ead9766
......@@ -11,6 +11,9 @@
* Fixed single precision calculations with an externally linked ELPA.
* Fixed libOMM Cholesky flavor with random initial guess.
New Matrix Storage Format:
* Added arbitrarily distributed coordinate (GENERIC_COO) format.
NTPoly:
* Updated redistributed NTPoly source code to version 2.1.
......
......@@ -7,7 +7,7 @@ SET(elsi_URL "http://elsi-interchange.org")
SET(elsi_EMAIL "elsi-team@duke.edu")
SET(elsi_LICENSE "BSD 3")
SET(elsi_DESCRIPTION "Electronic Structure Infrastructure")
SET(elsi_DATESTAMP "20181120")
SET(elsi_DATESTAMP "20181207")
### CMake modules ###
LIST(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
......
No preview for this file type
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -54,6 +54,12 @@ void c_elsi_set_csc(elsi_handle handle_c,
int *row_ind,
int *col_ptr);
void c_elsi_set_coo(elsi_handle handle_c,
int nnz,
int nnz_l,
int *row_ind,
int *col_ind);
void c_elsi_reinit(elsi_handle handle_c);
void c_elsi_finalize(elsi_handle handle_c);
......@@ -312,28 +318,6 @@ void c_elsi_extrapolate_dm_complex(elsi_handle handle_c,
double _Complex *ovlp,
double _Complex *dm);
void c_elsi_construct_dm_real(elsi_handle handle_c,
double *occ,
double *evec,
double *dm);
void c_elsi_construct_dm_complex(elsi_handle handle_c,
double *occ,
double _Complex *evec,
double _Complex *dm);
void c_elsi_construct_edm_real(elsi_handle handle_c,
double *occ,
double *eval,
double *evec,
double *edm);
void c_elsi_construct_edm_complex(elsi_handle handle_c,
double *occ,
double *eval,
double _Complex *evec,
double _Complex *edm);
void c_elsi_init_rw(elsi_rw_handle *handle_c,
int rw_task,
int parallel_mode,
......
......@@ -197,6 +197,25 @@ subroutine elsi_set_csc_c_wrapper(h_c,nnz_g,nnz_l,n_lcol,row_ind,col_ptr)&
end subroutine
subroutine elsi_set_coo_c_wrapper(h_c,nnz_g,nnz_l,row_ind,col_ind)&
bind(C,name="c_elsi_set_coo")
implicit none
type(c_ptr), value, intent(in) :: h_c
integer(kind=c_int), value, intent(in) :: nnz_g
integer(kind=c_int), value, intent(in) :: nnz_l
integer(kind=c_int), intent(in) :: row_ind(nnz_l)
integer(kind=c_int), intent(in) :: col_ind(nnz_l)
type(elsi_handle), pointer :: h_f
call c_f_pointer(h_c,h_f)
call elsi_set_coo(h_f,nnz_g,nnz_l,row_ind,col_ind)
end subroutine
subroutine elsi_reinit_c_wrapper(h_c)&
bind(C,name="c_elsi_reinit")
......@@ -1617,144 +1636,6 @@ subroutine elsi_extrapolate_dm_complex_c_wrapper(h_c,ovlp_c,dm_c)&
end subroutine
subroutine elsi_construct_dm_real_c_wrapper(h_c,occ_c,evec_c,dm_c)&
bind(C,name="c_elsi_construct_dm_real")
implicit none
type(c_ptr), value, intent(in) :: h_c
type(c_ptr), value, intent(in) :: occ_c
type(c_ptr), value, intent(in) :: evec_c
type(c_ptr), value, intent(in) :: dm_c
type(elsi_handle), pointer :: h_f
real(kind=c_double), pointer :: occ_f(:)
real(kind=c_double), pointer :: evec_f(:,:)
real(kind=c_double), pointer :: dm_f(:,:)
integer(kind=c_int) :: n_state
integer(kind=c_int) :: lrow
integer(kind=c_int) :: lcol
call c_f_pointer(h_c,h_f)
n_state = h_f%ph%n_states
lrow = h_f%bh%n_lrow
lcol = h_f%bh%n_lcol
call c_f_pointer(occ_c,occ_f,shape=[n_state])
call c_f_pointer(evec_c,evec_f,shape=[lrow,lcol])
call c_f_pointer(dm_c,dm_f,shape=[lrow,lcol])
call elsi_construct_dm_real(h_f,occ_f,evec_f,dm_f)
end subroutine
subroutine elsi_construct_dm_complex_c_wrapper(h_c,occ_c,evec_c,dm_c)&
bind(C,name="c_elsi_construct_dm_complex")
implicit none
type(c_ptr), value, intent(in) :: h_c
type(c_ptr), value, intent(in) :: occ_c
type(c_ptr), value, intent(in) :: evec_c
type(c_ptr), value, intent(in) :: dm_c
type(elsi_handle), pointer :: h_f
real(kind=c_double), pointer :: occ_f(:)
complex(kind=c_double), pointer :: evec_f(:,:)
complex(kind=c_double), pointer :: dm_f(:,:)
integer(kind=c_int) :: n_state
integer(kind=c_int) :: lrow
integer(kind=c_int) :: lcol
call c_f_pointer(h_c,h_f)
n_state = h_f%ph%n_states
lrow = h_f%bh%n_lrow
lcol = h_f%bh%n_lcol
call c_f_pointer(occ_c,occ_f,shape=[n_state])
call c_f_pointer(evec_c,evec_f,shape=[lrow,lcol])
call c_f_pointer(dm_c,dm_f,shape=[lrow,lcol])
call elsi_construct_dm_complex(h_f,occ_f,evec_f,dm_f)
end subroutine
subroutine elsi_construct_edm_real_c_wrapper(h_c,occ_c,eval_c,evec_c,edm_c)&
bind(C,name="c_elsi_construct_edm_real")
implicit none
type(c_ptr), value, intent(in) :: h_c
type(c_ptr), value, intent(in) :: occ_c
type(c_ptr), value, intent(in) :: eval_c
type(c_ptr), value, intent(in) :: evec_c
type(c_ptr), value, intent(in) :: edm_c
type(elsi_handle), pointer :: h_f
real(kind=c_double), pointer :: occ_f(:)
real(kind=c_double), pointer :: eval_f(:)
real(kind=c_double), pointer :: evec_f(:,:)
real(kind=c_double), pointer :: edm_f(:,:)
integer(kind=c_int) :: n_state
integer(kind=c_int) :: lrow
integer(kind=c_int) :: lcol
call c_f_pointer(h_c,h_f)
n_state = h_f%ph%n_states
lrow = h_f%bh%n_lrow
lcol = h_f%bh%n_lcol
call c_f_pointer(occ_c,occ_f,shape=[n_state])
call c_f_pointer(eval_c,eval_f,shape=[n_state])
call c_f_pointer(evec_c,evec_f,shape=[lrow,lcol])
call c_f_pointer(edm_c,edm_f,shape=[lrow,lcol])
call elsi_construct_edm_real(h_f,occ_f,eval_f,evec_f,edm_f)
end subroutine
subroutine elsi_construct_edm_complex_c_wrapper(h_c,occ_c,eval_c,evec_c,edm_c)&
bind(C,name="c_elsi_construct_edm_complex")
implicit none
type(c_ptr), value, intent(in) :: h_c
type(c_ptr), value, intent(in) :: occ_c
type(c_ptr), value, intent(in) :: eval_c
type(c_ptr), value, intent(in) :: evec_c
type(c_ptr), value, intent(in) :: edm_c
type(elsi_handle), pointer :: h_f
real(kind=c_double), pointer :: occ_f(:)
real(kind=c_double), pointer :: eval_f(:)
complex(kind=c_double), pointer :: evec_f(:,:)
complex(kind=c_double), pointer :: edm_f(:,:)
integer(kind=c_int) :: n_state
integer(kind=c_int) :: lrow
integer(kind=c_int) :: lcol
call c_f_pointer(h_c,h_f)
n_state = h_f%ph%n_states
lrow = h_f%bh%n_lrow
lcol = h_f%bh%n_lcol
call c_f_pointer(occ_c,occ_f,shape=[n_state])
call c_f_pointer(eval_c,eval_f,shape=[n_state])
call c_f_pointer(evec_c,evec_f,shape=[lrow,lcol])
call c_f_pointer(edm_c,edm_f,shape=[lrow,lcol])
call elsi_construct_edm_complex(h_f,occ_f,eval_f,evec_f,edm_f)
end subroutine
subroutine elsi_init_rw_c_wrapper(h_c,rw_task,parallel_mode,n_basis,n_electron)&
bind(C,name="c_elsi_init_rw")
......
......@@ -18,7 +18,7 @@ module ELSI_CONSTANTS
integer(kind=i4), parameter :: UNSET = -910910
integer(kind=i4), parameter :: N_SOLVERS = 7
integer(kind=i4), parameter :: N_MATRIX_FORMATS = 3
integer(kind=i4), parameter :: N_MATRIX_FORMATS = 4
integer(kind=i4), parameter :: N_PARALLEL_MODES = 2
! Method names
......@@ -37,6 +37,7 @@ module ELSI_CONSTANTS
integer(kind=i4), parameter :: BLACS_DENSE = 0
integer(kind=i4), parameter :: PEXSI_CSC = 1
integer(kind=i4), parameter :: SIESTA_CSC = 2
integer(kind=i4), parameter :: GENERIC_COO = 3
! Triangular matrix
integer(kind=i4), parameter :: FULL_MAT = 0
......
......@@ -72,6 +72,10 @@ module ELSI_DATATYPE
integer(kind=i4) :: blk_sp2
logical :: siesta_csc_ready = .false.
! Sparse matrix information (generic)
integer(kind=i4) :: nnz_l_sp3 ! Local number of nonzeros
logical :: generic_coo_ready = .false.
end type
type, public :: elsi_param_t
......@@ -121,6 +125,9 @@ module ELSI_DATATYPE
logical :: first_blacs_to_ntpoly
logical :: first_blacs_to_pexsi
logical :: first_blacs_to_sips
logical :: first_generic_to_blacs
logical :: first_generic_to_ntpoly
logical :: first_generic_to_pexsi
logical :: first_siesta_to_blacs
logical :: first_siesta_to_pexsi
logical :: first_sips_to_blacs
......@@ -196,6 +203,7 @@ module ELSI_DATATYPE
type(Matrix_ps) :: nt_ovlp
type(Matrix_ps) :: nt_ovlp_copy
type(Matrix_ps) :: nt_dm
type(Matrix_ps) :: nt_map
type(SolverParameters_t) :: nt_options
type(Permutation_t) :: nt_perm
type(ProcessGrid_t) :: nt_pgrid
......@@ -220,16 +228,18 @@ module ELSI_DATATYPE
complex(kind=r8), allocatable :: dm_cmplx_den(:,:)
! Sparse
real(kind=r8), allocatable :: ham_real_csc(:)
complex(kind=r8), allocatable :: ham_cmplx_csc(:)
real(kind=r8), allocatable :: ovlp_real_csc(:)
complex(kind=r8), allocatable :: ovlp_cmplx_csc(:)
real(kind=r8), allocatable :: dm_real_csc(:)
complex(kind=r8), allocatable :: dm_cmplx_csc(:)
real(kind=r8), allocatable :: ham_real_sp(:)
complex(kind=r8), allocatable :: ham_cmplx_sp(:)
real(kind=r8), allocatable :: ovlp_real_sp(:)
complex(kind=r8), allocatable :: ovlp_cmplx_sp(:)
real(kind=r8), allocatable :: dm_real_sp(:)
complex(kind=r8), allocatable :: dm_cmplx_sp(:)
integer(kind=i4), allocatable :: row_ind_sp1(:)
integer(kind=i4), allocatable :: col_ptr_sp1(:)
integer(kind=i4), allocatable :: row_ind_sp2(:)
integer(kind=i4), allocatable :: col_ptr_sp2(:)
integer(kind=i4), allocatable :: row_ind_sp3(:)
integer(kind=i4), allocatable :: col_ind_sp3(:)
! Auxiliary
real(kind=r8), allocatable :: ovlp_real_copy(:,:)
......@@ -237,6 +247,9 @@ module ELSI_DATATYPE
real(kind=r8), allocatable :: occ(:,:,:)
integer(kind=i4), allocatable :: row_map(:)
integer(kind=i4), allocatable :: col_map(:)
integer(kind=i4), allocatable :: map_den(:,:)
integer(kind=i4), allocatable :: map_sp1(:)
integer(kind=i4), allocatable :: perm_sp3(:)
real(kind=r8), allocatable :: omm_c_real(:,:)
complex(kind=r8), allocatable :: omm_c_cmplx(:,:)
real(kind=r8), allocatable :: pexsi_ne_vec(:)
......
......@@ -34,6 +34,7 @@ module ELSI
public :: elsi_set_kpoint
public :: elsi_set_blacs
public :: elsi_set_csc
public :: elsi_set_coo
public :: elsi_reinit
public :: elsi_finalize
......@@ -123,10 +124,6 @@ module ELSI
public :: elsi_orthonormalize_ev_complex
public :: elsi_extrapolate_dm_real
public :: elsi_extrapolate_dm_complex
public :: elsi_construct_dm_real
public :: elsi_construct_dm_complex
public :: elsi_construct_edm_real
public :: elsi_construct_edm_complex
public :: elsi_compute_mu_and_occ
public :: elsi_compute_entropy
......
......@@ -10,7 +10,8 @@
module ELSI_IO
use ELSI_CONSTANTS, only: MULTI_PROC,SINGLE_PROC,BLACS_DENSE,PEXSI_CSC,&
SIESTA_CSC,ELPA_SOLVER,PEXSI_SOLVER,SIPS_SOLVER,OMM_SOLVER,NTPOLY_SOLVER
SIESTA_CSC,GENERIC_COO,ELPA_SOLVER,PEXSI_SOLVER,SIPS_SOLVER,OMM_SOLVER,&
NTPOLY_SOLVER
use ELSI_DATATYPE, only: elsi_param_t,elsi_basic_t
use ELSI_PRECISION, only: r8,i4,i8
use FORTJSON, only: fjson_write_name_value,fjson_reset_fj_handle,&
......@@ -156,9 +157,9 @@ subroutine elsi_add_log(ph,bh,jh,dt0,t0,caller)
end select
if(ph%matrix_format == BLACS_DENSE) then
call elsi_print_den_settings(bh,jh)
call elsi_print_dense_settings(bh,jh)
else
call elsi_print_csc_settings(bh,jh)
call elsi_print_sparse_settings(bh,jh)
end if
call fjson_finish_object(jh)
......@@ -198,6 +199,8 @@ subroutine elsi_print_handle_summary(ph,bh,jh)
call fjson_write_name_value(jh,"matrix_format","PEXSI_CSC")
else if(ph%matrix_format == SIESTA_CSC) then
call fjson_write_name_value(jh,"matrix_format","SIESTA_CSC")
else if(ph%matrix_format == GENERIC_COO) then
call fjson_write_name_value(jh,"matrix_format","GENERIC_COO")
end if
call fjson_write_name_value(jh,"n_basis",ph%n_basis)
......@@ -389,14 +392,14 @@ end subroutine
!>
!! This routine prints out settings for the dense matrix format.
!!
subroutine elsi_print_den_settings(bh,jh)
subroutine elsi_print_dense_settings(bh,jh)
implicit none
type(elsi_basic_t), intent(in) :: bh
type(fjson_handle), intent(inout) :: jh
character(len=*), parameter :: caller = "elsi_print_den_settings"
character(len=*), parameter :: caller = "elsi_print_dense_settings"
call fjson_start_name_object(jh,"matrix_format_settings")
call fjson_write_name_value(jh,"blk",bh%blk)
......@@ -410,20 +413,21 @@ end subroutine
!>
!! This routine prints out settings for the sparse matrix format.
!!
subroutine elsi_print_csc_settings(bh,jh)
subroutine elsi_print_sparse_settings(bh,jh)
implicit none
type(elsi_basic_t), intent(in) :: bh
type(fjson_handle), intent(inout) :: jh
character(len=*), parameter :: caller = "elsi_print_csc_settings"
character(len=*), parameter :: caller = "elsi_print_sparse_settings"
call fjson_start_name_object(jh,"matrix_format_settings")
call fjson_write_name_value(jh,"def0",bh%def0)
call fjson_write_name_value(jh,"blk_sp2",bh%blk_sp2)
call fjson_write_name_value(jh,"pexsi_csc_ready",bh%pexsi_csc_ready)
call fjson_write_name_value(jh,"siesta_csc_ready",bh%siesta_csc_ready)
call fjson_write_name_value(jh,"generic_coo_ready",bh%generic_coo_ready)
call fjson_finish_object(jh)
end subroutine
......@@ -489,6 +493,9 @@ subroutine elsi_final_print(ph,bh)
else if(ph%matrix_format == SIESTA_CSC) then
write(msg,"(2X,A,A22)") "| Matrix format :","SIESTA_CSC"
call elsi_say(bh,msg)
else if(ph%matrix_format == GENERIC_COO) then
write(msg,"(2X,A,A22)") "| Matrix format :","GENERIC_COO"
call elsi_say(bh,msg)
end if
write(msg,"(2X,A,I22)") "| Number of basis functions :",ph%n_basis
......@@ -717,7 +724,6 @@ subroutine elsi_init_random_seed()
real(kind=r8) :: wtime
integer(kind=i4) :: i
integer(kind=i4) :: n
integer(kind=i4) :: dt(8)
integer(kind=i8) :: t
integer(kind=i4), allocatable :: seed(:)
......
This diff is collapsed.
......@@ -274,6 +274,7 @@ subroutine elsi_cleanup_ntpoly(ph)
call DestructMatrix(ph%nt_ovlp)
call DestructMatrix(ph%nt_ovlp_copy)
call DestructMatrix(ph%nt_dm)
call DestructMatrix(ph%nt_map)
call DestructPermutation(ph%nt_perm)
call DestructProcessGrid(ph%nt_pgrid)
end if
......
......@@ -169,7 +169,6 @@ subroutine elsi_solve_pexsi_real(ph,bh,row_ind,col_ptr,ne_vec,ham,ovlp,dm)
real(kind=r8), intent(in) :: ovlp(bh%nnz_l_sp1)
real(kind=r8), intent(out) :: dm(bh%nnz_l_sp1)
real(kind=r8) :: ne_drv
real(kind=r8) :: mu_range
real(kind=r8) :: shift_width
real(kind=r8) :: local_energy
......
This diff is collapsed.
......@@ -691,7 +691,7 @@ subroutine elsi_read_mat_real_mp(rwh,f_name,mat)
eh%bh%n_lcol_sp = rwh%bh%n_lcol_sp
eh%bh%n_lcol_sp1 = rwh%bh%n_lcol_sp
call elsi_sips_to_blacs_dm(eh%ph,eh%bh,row_ind,col_ptr,nnz_val,mat)
call elsi_sips_to_blacs_dm(eh%ph,eh%bh,nnz_val,row_ind,col_ptr,mat)
call elsi_deallocate(rwh%bh,col_ptr,"col_ptr")
call elsi_deallocate(rwh%bh,row_ind,"row_ind")
......@@ -875,7 +875,7 @@ subroutine elsi_read_mat_complex_mp(rwh,f_name,mat)
eh%bh%n_lcol_sp = rwh%bh%n_lcol_sp
eh%bh%n_lcol_sp1 = rwh%bh%n_lcol_sp
call elsi_sips_to_blacs_dm(eh%ph,eh%bh,row_ind,col_ptr,nnz_val,mat)
call elsi_sips_to_blacs_dm(eh%ph,eh%bh,nnz_val,row_ind,col_ptr,mat)
call elsi_deallocate(rwh%bh,col_ptr,"col_ptr")
call elsi_deallocate(rwh%bh,row_ind,"row_ind")
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -10,7 +10,7 @@
!!
module ELSI_TOOLS
use ELSI_CONSTANTS, only: ELPA_SOLVER,OMM_SOLVER,SIPS_SOLVER,NTPOLY_SOLVER
use ELSI_CONSTANTS, only: ELPA_SOLVER
use ELSI_DATATYPE, only: elsi_handle
use ELSI_ELPA, only: elsi_update_dm_elpa
use ELSI_MALLOC, only: elsi_allocate
......@@ -18,8 +18,7 @@ module ELSI_TOOLS
use ELSI_OCC, only: elsi_mu_and_occ,elsi_entropy
use ELSI_PRECISION, only: i4,r8
use ELSI_REDIST, only: elsi_blacs_to_ntpoly_hs,elsi_ntpoly_to_blacs_dm
use ELSI_UTILS, only: elsi_check_init,elsi_set_full_mat,elsi_build_dm,&
elsi_build_edm,elsi_gram_schmidt
use ELSI_UTILS, only: elsi_check_init,elsi_gram_schmidt
implicit none
......@@ -29,10 +28,6 @@ module ELSI_TOOLS
public :: elsi_orthonormalize_ev_complex
public :: elsi_extrapolate_dm_real
public :: elsi_extrapolate_dm_complex
public :: elsi_construct_dm_real
public :: elsi_construct_dm_complex
public :: elsi_construct_edm_real
public :: elsi_construct_edm_complex
public :: elsi_compute_mu_and_occ
public :: elsi_compute_entropy
......@@ -87,8 +82,6 @@ subroutine elsi_extrapolate_dm_real(eh,ovlp,dm)
real(kind=r8), intent(inout) :: ovlp(eh%bh%n_lrow,eh%bh%n_lcol) !< New overlap
real(kind=r8), intent(inout) :: dm(eh%bh%n_lrow,eh%bh%n_lcol) !< Density matrix
logical :: unit_ovlp_save
character(len=*), parameter :: caller = "elsi_extrapolate_dm_real"
call elsi_check_init(eh%bh,eh%handle_init,caller)
......@@ -100,7 +93,6 @@ subroutine elsi_extrapolate_dm_real(eh,ovlp,dm)
eh%ovlp_real_copy = ovlp
case default
unit_ovlp_save = eh%ph%unit_ovlp
eh%ph%unit_ovlp = .true.
call elsi_blacs_to_ntpoly_hs(eh%ph,eh%bh,dm,ovlp,eh%ph%nt_ham,eh%ph%nt_dm)
......@@ -110,7 +102,7 @@ subroutine elsi_extrapolate_dm_real(eh,ovlp,dm)
call elsi_blacs_to_ntpoly_hs(eh%ph,eh%bh,ovlp,dm,eh%ph%nt_ovlp,&
eh%ph%nt_dm)
eh%ph%unit_ovlp = unit_ovlp_save
eh%ph%unit_ovlp = .false.
call elsi_update_dm_ntpoly(eh%ph,eh%bh,eh%ph%nt_ovlp_copy,eh%ph%nt_ovlp,&
eh%ph%nt_ham,eh%ph%nt_dm)
......@@ -131,8 +123,6 @@ subroutine elsi_extrapolate_dm_complex(eh,ovlp,dm)
complex(kind=r8), intent(inout) :: ovlp(eh%bh%n_lrow,eh%bh%n_lcol) !< New overlap
complex(kind=r8), intent(inout) :: dm(eh%bh%n_lrow,eh%bh%n_lcol) !< Density matrix
logical :: unit_ovlp_save
character(len=*), parameter :: caller = "elsi_extrapolate_dm_complex"
call elsi_check_init(eh%bh,eh%handle_init,caller)
......@@ -144,7 +134,6 @@ subroutine elsi_extrapolate_dm_complex(eh,ovlp,dm)
eh%ovlp_cmplx_copy = ovlp
case default
unit_ovlp_save = eh%ph%unit_ovlp
eh%ph%unit_ovlp = .true.
call elsi_blacs_to_ntpoly_hs(eh%ph,eh%bh,dm,ovlp,eh%ph%nt_ham,eh%ph%nt_dm)
......@@ -154,7 +143,7 @@ subroutine elsi_extrapolate_dm_complex(eh,ovlp,dm)
call elsi_blacs_to_ntpoly_hs(eh%ph,eh%bh,ovlp,dm,eh%ph%nt_ovlp,&
eh%ph%nt_dm)
eh%ph%unit_ovlp = unit_ovlp_save
eh%ph%unit_ovlp = .false.
call elsi_update_dm_ntpoly(eh%ph,eh%bh,eh%ph%nt_ovlp_copy,eh%ph%nt_ovlp,&
eh%ph%nt_ham,eh%ph%nt_dm)
......@@ -164,92 +153,6 @@ subroutine elsi_extrapolate_dm_complex(eh,ovlp,dm)
end subroutine
!>
!! This routine constructs density matrix from occupation numbers and
!! eigenvectors.
!!
subroutine elsi_construct_dm_real(eh,occ,evec,dm)
implicit none
type(elsi_handle), intent(in) :: eh !< Handle
real(kind=r8), intent(in) :: occ(eh%ph%n_states) !< Occupation numbers
real(kind=r8), intent(in) :: evec(eh%bh%n_lrow,eh%bh%n_lcol) !< Eigenvectors
real(kind=r8), intent(out) :: dm(eh%bh%n_lrow,eh%bh%n_lcol) !< Density matrix
character(len=*), parameter :: caller = "elsi_construct_dm_real"
call elsi_check_init(eh%bh,eh%handle_init,caller)
call elsi_build_dm(eh%ph,eh%bh,eh%row_map,eh%col_map,occ,evec,dm)
end subroutine
!>
!! This routine constructs density matrix from occupation numbers and
!! eigenvectors.
!!
subroutine elsi_construct_dm_complex(eh,occ,evec,dm)
implicit none
type(elsi_handle), intent(in) :: eh !< Handle
real(kind=r8), intent(in) :: occ(eh%ph%n_states) !< Occupation numbers
complex(kind=r8), intent(in) :: evec(eh%bh%n_lrow,eh%bh%n_lcol) !< Eigenvectors
complex(kind=r8), intent(out) :: dm(eh%bh%n_lrow,eh%bh%n_lcol) !< Density matrix
character(len=*), parameter :: caller = "elsi_construct_dm_complex"
call elsi_check_init(eh%bh,eh%handle_init,caller)
call elsi_build_dm(eh%ph,eh%bh,eh%row_map,eh%col_map,occ,evec,dm)
end subroutine
!>
!! This routine constructs energy-weighted density matrix from occupation
!! numbers, eigenvalues, and eigenvectors.
!!
subroutine elsi_construct_edm_real(eh,occ,eval,evec,edm)
implicit none
type(elsi_handle), intent(in) :: eh !< Handle
real(kind=r8), intent(in) :: occ(eh%ph%n_states) !< Occupation numbers
real(kind=r8), intent(in) :: eval(eh%ph%n_states) !< Eigenvalues
real(kind=r8), intent(in) :: evec(eh%bh%n_lrow,eh%bh%n_lcol) !< Eigenvectors
real(kind=r8), intent(out) :: edm(eh%bh%n_lrow,eh%bh%n_lcol) !< Density matrix
character(len=*), parameter :: caller = "elsi_construct_dm_real"
call elsi_check_init(eh%bh,eh%handle_init,caller)
call elsi_build_edm(eh%ph,eh%bh,eh%row_map,eh%col_map,occ,eval,evec,edm)
end subroutine
!>