SIRIUS 7.5.0
Electronic structure library and applications
diagonalize.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2023 Anton Kozhevnikov, Thomas Schulthess
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
5// the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
8// following disclaimer.
9// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
10// and the following disclaimer in the documentation and/or other materials provided with the distribution.
11//
12// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
13// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
14// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
15// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
16// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
18// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
20/** \file diagonalize.hpp
21 *
22 * \brief Entry point for Hamiltonain diagonalization.
23 */
24
25#ifndef __DIAGONALIZE_HPP__
26#define __DIAGONALIZE_HPP__
27
28#include "diagonalize_fp.hpp"
29#include "diagonalize_pp.hpp"
31
32namespace sirius {
33
35 davidson_result_t davidson_result;
36 double avg_num_iter{0};
37 bool converged;
38};
39
40/// Diagonalize KS Hamiltonian for all k-points in the set.
41/** \tparam T Precision type of the wave-functions
42 * \tparam F Precition type of the Hamiltonian matrix
43 */
44template <typename T, typename F>
45inline auto
46diagonalize(Hamiltonian0<T> const& H0__, K_point_set& kset__, double itsol_tol__)
47{
48 PROFILE("sirius::diagonalize");
49
50 auto& ctx = H0__.ctx();
51 print_memory_usage(ctx.out(),FILE_LINE);
52
54
55 auto& itso = ctx.cfg().iterative_solver();
56
57 double empy_tol{itsol_tol__};
58 if (itso.type() == "davidson") {
59 empy_tol = std::max(itsol_tol__ * ctx.cfg().settings().itsol_tol_ratio(), itso.empty_states_tolerance());
60 RTE_OUT(ctx.out(2)) << "iterative solver tolerance (occupied, empty): " << itsol_tol__ << " "
61 << itsol_tol__ + empy_tol << std::endl;
62 }
63
64 int num_dav_iter{0};
65 bool converged{true};
66 /* solve secular equation and generate wave functions */
67 for (auto it : kset__.spl_num_kpoints()) {
68 auto kp = kset__.get<T>(it.i);
69
70 auto Hk = H0__(*kp);
71 if (ctx.full_potential()) {
72 diagonalize_fp<T>(Hk, *kp, itsol_tol__);
73 } else {
74 if (itso.type() == "exact") {
75 if (ctx.gamma_point() || ctx.num_mag_dims() == 3) {
76 RTE_THROW("not implemented");
77 }
78 for (int ispn = 0; ispn < ctx.num_spins(); ispn++) {
79 diagonalize_pp_exact<T, std::complex<F>>(ispn, Hk, *kp);
80 }
81 } else {
82 if (ctx.gamma_point() && (ctx.so_correction() == false)) {
83 result.davidson_result = diagonalize_pp<T, F>(Hk, *kp, itsol_tol__, empy_tol);
84 } else {
85 result.davidson_result = diagonalize_pp<T, std::complex<F>>(Hk, *kp, itsol_tol__, empy_tol);
86 }
87 num_dav_iter += result.davidson_result.niter;
88 converged = converged & result.davidson_result.converged;
89 }
90 }
91 }
92 kset__.comm().allreduce(&num_dav_iter, 1);
93 kset__.comm().allreduce<bool, mpi::op_t::land>(&converged, 1);
94 ctx.num_itsol_steps(num_dav_iter);
95 result.avg_num_iter = static_cast<double>(num_dav_iter) / kset__.num_kpoints();
96 result.converged = converged;
97 if (!ctx.full_potential()) {
98 RTE_OUT(ctx.out(2)) << "average number of iterations: " << result.avg_num_iter << std::endl;
99 }
100
101 /* synchronize eigen-values */
102 kset__.sync_band<T, sync_band_t::energy>();
103
104 if (ctx.verbosity() >= 2) {
105 std::stringstream s;
106 s << "Lowest band energies" << std::endl;
107 int nbnd = std::min(ctx.cfg().control().num_bands_to_print(), ctx.num_bands());
108 for (int ik = 0; ik < kset__.num_kpoints(); ik++) {
109 s << "ik:" << std::setw(5) << ik;
110 for (int j = 0; j < nbnd; j++) {
111 s << ffmt(12, 6) << kset__.get<T>(ik)->band_energy(j, 0);
112 }
113 if (ctx.num_mag_dims() == 1) {
114 s << std::endl << " ";
115 for (int j = 0; j < nbnd; j++) {
116 s << ffmt(12, 6) << kset__.get<T>(ik)->band_energy(j, 1);
117 }
118 }
119 s << std::endl;
120 }
121 RTE_OUT(ctx.out(2)) << s.str();
122 }
123 print_memory_usage(ctx.out(), FILE_LINE);
124
125 return result;
126}
127
128}
129
130#endif
Represent the k-point independent part of Hamiltonian.
Definition: hamiltonian.hpp:75
Set of k-points.
Definition: k_point_set.hpp:41
int num_kpoints() const
Return total number of k-points.
void sync_band()
Sync band energies or occupancies between all MPI ranks.
Definition: k_point_set.cpp:30
Floating-point formatting (precision and width).
Diagonalize full-potential LAPW Hamiltonian.
Diagonalize pseudo-potential Hamiltonian.
Contains declaration and partial implementation of sirius::K_point_set class.
Namespace of the SIRIUS library.
Definition: sirius.f90:5
auto diagonalize(Hamiltonian0< T > const &H0__, K_point_set &kset__, double itsol_tol__)
Diagonalize KS Hamiltonian for all k-points in the set.
Definition: diagonalize.hpp:46
Result of Davidson solver.
Definition: davidson.hpp:37
bool converged
True if all bands (up and dn) are converged.
Definition: davidson.hpp:43
int niter
Number of iterations.
Definition: davidson.hpp:39