Line data Source code
1 : !--------------------------------------------------------------------------------
2 : ! Copyright (c) 2025 Peter Grünberg Institut, Forschungszentrum Jülich, Germany
3 : ! This file is part of FLEUR and available as free software under the conditions
4 : ! of the MIT license as expressed in the LICENSE file in more detail.
5 : !--------------------------------------------------------------------------------
6 :
7 : module m_eigen_diag
8 : !! Module provides the high level entry point for solving a generalized eigenvalue problem
9 : !! The solver actually used is determined by a call to [[select_solver]] from [[m_available_solvers]].
10 : use m_juDFT
11 : use m_available_solvers
12 : use m_types_mpimat
13 : use m_types_mat
14 : use m_types_solver
15 : use m_lapack
16 : implicit none
17 : private
18 : public :: eigen_diag
19 :
20 : contains
21 :
22 7102 : subroutine eigen_diag(hmat, smat, ne, eig, ev, ikpt)
23 : !! Solve generalized eigenvalue problem
24 : #ifdef CPP_MPI
25 : use mpi
26 : #endif
27 : implicit none
28 : class(t_mat), intent(INOUT) :: smat, hmat !! overlapp matrix and Hamiltonian
29 : class(t_mat), allocatable, intent(OUT) :: ev !! eigenvectors
30 : integer, intent(INOUT) :: ne !! number of eigenpairs searched (and found) on this node
31 : !! on input, overall number of eigenpairs searched,
32 : !! on output, local number of eigenpairs found
33 : real, intent(OUT) :: eig(:) !! eigenvalues (must be allocated to size ne before)
34 : integer, intent(IN) :: ikpt !! The index of the k-point, just to have more information for debugging
35 :
36 : !Locals
37 : logical :: parallel
38 14204 : class(t_solver), allocatable :: solver, transform
39 :
40 : select type (smat)
41 : class IS (t_mpimat)
42 : #ifdef CPP_MPI
43 4592 : parallel = smat%blacsdata%mpi_com /= MPI_COMM_SELF
44 : #endif
45 : class default
46 2510 : parallel = .false.
47 : end select
48 :
49 : call select_solver(parallel, diag_solver=solver, diag_transform=transform)
50 :
51 7102 : if (.not. allocated(transform)) then
52 : ! We solve directly the generalized eigenvalue problem
53 7102 : if (solver%generalized) then
54 7102 : call timestart("Diagonalization")
55 7102 : call solver%solve_gev(hmat, smat, ne, eig, ev, ikpt)
56 7102 : call timestop("Diagonalization")
57 7102 : call redistribute_ev_to_rowcyclic(ev)
58 : else
59 0 : call judft_bug("Generalized solver not available?")
60 : end if
61 : else
62 : ! We do a reduction, to a standard problem, then solve the standard problem and transform back
63 0 : call timestart("Reduction to S-EVP")
64 0 : call transform%to_std(hmat, smat, ne)
65 0 : call timestop("Reduction to S-EVP")
66 0 : call timestart("Diagonalization")
67 0 : print *, "Solver:", solver%name
68 0 : call solver%solve_std(hmat, ne, eig, ev)
69 0 : call timestop("Diagonalization")
70 0 : call timestart("Backtransform of eigenvectors")
71 0 : call transform%backtrans(smat, ev)
72 0 : call timestop("Backtransform of eigenvectors")
73 0 : call redistribute_ev_to_rowcyclic(ev)
74 : end if
75 14204 : end subroutine
76 :
77 7102 : subroutine redistribute_ev_to_rowcyclic(ev)
78 : class(t_mat), allocatable, intent(inout) :: ev
79 7102 : type(t_mpimat) :: row_cyclic_ev
80 :
81 : select type (ev)
82 : type is (t_mpimat)
83 4592 : call row_cyclic_ev%init(ev%l_real, ev%global_size1, ev%global_size1, ev%blacsdata%mpi_com, MPIMAT_ROWCYCLIC)
84 4592 : call row_cyclic_ev%copy(ev, 1, 1)
85 4592 : call ev%free()
86 : call ev%init(row_cyclic_ev%l_real, row_cyclic_ev%global_size1, row_cyclic_ev%global_size2, &
87 4592 : row_cyclic_ev%blacsdata%mpi_com, MPIMAT_ROWCYCLIC)
88 4592 : call ev%copy(row_cyclic_ev, 1, 1)
89 9184 : call row_cyclic_ev%free()
90 : class default
91 : ! Serial output remains unchanged.
92 : end select
93 7102 : end subroutine redistribute_ev_to_rowcyclic
94 :
95 14204 : end module m_eigen_diag
|