Loading...
Searching...
No Matches
init.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * PlanewaveSubspaceManager — abstract interface for Davidson subspace operations.
5 *
6 * Encapsulates all subspace-level linear algebra that could benefit from
7 * GPU acceleration:
8 * - Gram-Schmidt orthogonalization (with S inner product)
9 * - Subspace matrix construction (V^H · HV, V^H · SV)
10 * - Subspace diagonalization (generalized eigenproblem)
11 * - Ritz vector extraction (full-space eigenvectors from subspace coefficients)
12 * - Subspace collapse (rotation back to number_of_bands vectors)
13 *
14 * The Davidson iteration loop itself remains in PlanewaveDavidsonDiagonalizer;
15 * this interface handles only the per-iteration linear algebra calls.
16 *
17 * GPU implementations override to use cuBLAS/cuSolver for the ZGEMM and
18 * eigensolver calls, keeping data on device between operations.
19 */
20
21#include <vector>
22
27
28namespace q3 {
29
31 public:
32 virtual ~PlanewaveSubspaceManager() = default;
33
34 /**
35 * Whether this rank's plane-wave list begins with G = 0.
36 *
37 * Every gamma-only inner product below is 2 Re over the stored half sphere
38 * with the origin -- held once, counted twice -- removed, and then reduced
39 * across the ranks sharing the coefficients. Under a reciprocal-space
40 * distribution exactly one rank holds the origin, and only that rank may
41 * remove it. Replicated layouts always hold
42 * it, which is the default. Set once per k-point, before the solve.
43 */
44 virtual void set_gamma_origin_is_local(bool origin_is_local) = 0;
45
46 /**
47 * S-orthogonalize and normalize a batch of candidate vectors against
48 * the existing basis using modified Gram-Schmidt with S inner product.
49 *
50 * Returns the number of accepted (linearly independent) vectors.
51 */
52 virtual int orthogonalize_batch(int starting_vector_index,
53 int number_of_candidates,
54 int number_of_plane_waves,
55 bool is_gamma_only,
56 const OverlapOperator* overlap_operator,
57 Complex* basis_vectors,
58 Complex* overlap_basis_vectors) = 0;
59
60 /**
61 * Incrementally update the subspace matrices H_sub and S_sub with
62 * new_columns vectors starting at start_column.
63 */
64 virtual void update_subspace_matrices(int start_column,
65 int new_columns,
66 int total_basis_size,
67 int maximum_basis_size,
68 int number_of_plane_waves,
69 bool is_gamma_only,
70 const Complex* basis_vectors,
71 const Complex* hamiltonian_basis_vectors,
72 const Complex* overlap_basis_vectors,
73 Complex* subspace_hamiltonian,
74 Complex* subspace_overlap) = 0;
75
76 /**
77 * Diagonalize the subspace by solving the generalized eigenvalue problem
78 * H_sub · c = ε · S_sub · c.
79 *
80 * Returns the LAPACK info code (0 = success).
81 */
82 virtual int diagonalize_subspace(int basis_size,
83 int maximum_basis_size,
84 bool is_gamma_only,
85 const Complex* subspace_hamiltonian,
86 const Complex* subspace_overlap,
87 Real* eigenvalues,
88 Complex* eigenvector_matrix) = 0;
89
90 /**
91 * Collapse the subspace back to number_of_bands vectors by rotating
92 * the basis with the eigenvector matrix.
93 *
94 * The rotation needs somewhere to build its result before overwriting the
95 * array it is reading, and the caller supplies one buffer of at least
96 * number_of_bands * number_of_plane_waves. One is enough because each
97 * rotation reads a different array than it writes. These used to be three
98 * members sized by maximum_basis_size, which made the collapse as
99 * expensive in memory as the basis it collapses.
100 *
101 * The rotation matrix is the eigenvector matrix of the current subspace,
102 * and the caller already holds that subspace: subspace_hamiltonian and
103 * subspace_overlap are the incrementally updated matrices with leading
104 * dimension maximum_basis_size, complete through basis_size. Diagonalising
105 * them costs basis_size cubed; rebuilding them from the vectors first --
106 * which is what this used to do -- costs two products of basis_size
107 * squared by number_of_plane_waves on top, and was the largest single
108 * compute term of a restart. Pass nullptr for either to force that rebuild,
109 * which is also the fallback when the passed matrices cannot be
110 * diagonalised: the Davidson loop asks for a collapse precisely when its
111 * own diagonalisation of them has just failed.
112 *
113 * Returns the new basis size (= number_of_bands).
114 */
115 virtual int collapse_subspace(int basis_size,
116 int number_of_plane_waves,
117 int number_of_bands,
118 int maximum_basis_size,
119 bool is_gamma_only,
120 bool is_identity_overlap,
121 const OverlapOperator* overlap_operator,
122 const Complex* subspace_hamiltonian,
123 const Complex* subspace_overlap,
124 Complex* basis_vectors,
125 Complex* hamiltonian_basis_vectors,
126 Complex* overlap_basis_vectors,
127 Complex* rotation_scratch) = 0;
128
129 /**
130 * Extract converged eigenvectors from the subspace representation and
131 * store them in the quantum system.
132 */
133 virtual void extract_eigenvectors(int basis_size,
134 int number_of_plane_waves,
135 int number_of_bands,
136 int kpoint_index_state,
137 bool is_gamma_only,
138 const Complex* eigenvector_matrix,
139 const Complex* basis_vectors,
140 const Real* eigenvalues,
141 Complex* rotated_scratch,
142 PlanewaveKohnShamQuantumSystem& quantum_system) = 0;
143
144 /**
145 * Compute residual vectors: R = Hψ - εSψ.
146 */
147 /**
148 * Build preconditioned correction vectors straight into the free columns
149 * of the basis, and return how many were written.
150 *
151 * R_n = (HV)c_n - eps_n (SV)c_n, formed by two GEMMs whose destination is
152 * the basis itself. Nothing else is materialised: no Ritz vectors, no
153 * H|Ritz>, no separate residual array. That is the layout Quantum
154 * ESPRESSO's Davidson uses, and it is three arrays of number_of_bands x
155 * number_of_plane_waves that Q3 no longer has to hold.
156 *
157 * Only unconverged bands contribute, and they are compacted into
158 * consecutive columns as they are written, so the caller can hand the
159 * block straight to orthogonalize_batch.
160 */
161 virtual int build_correction_vectors(int basis_size,
162 int number_of_plane_waves,
163 int number_of_bands,
164 int maximum_candidates,
165 bool is_gamma_only,
166 const Complex* eigenvector_matrix,
167 int eigenvector_leading_dimension,
168 const Real* eigenvalues,
169 const std::vector<bool>& band_converged,
170 const Real* kinetic_energy_squared,
171 const Complex* hamiltonian_basis_vectors,
172 const Complex* overlap_basis_vectors,
173 Complex* correction_columns) = 0;
174
175 /**
176 * Apply Davidson preconditioner to residual wavefunctions.
177 */
178 virtual void apply_preconditioner(int number_of_bands,
179 int number_of_plane_waves,
180 const Real* kinetic_energy_squared,
181 const Real* eigenvalues,
182 const std::vector<bool>& band_converged,
183 Complex* residual_wavefunctions) = 0;
184};
185
186} // namespace q3
virtual void set_gamma_origin_is_local(bool origin_is_local)=0
virtual void apply_preconditioner(int number_of_bands, int number_of_plane_waves, const Real *kinetic_energy_squared, const Real *eigenvalues, const std::vector< bool > &band_converged, Complex *residual_wavefunctions)=0
virtual int build_correction_vectors(int basis_size, int number_of_plane_waves, int number_of_bands, int maximum_candidates, bool is_gamma_only, const Complex *eigenvector_matrix, int eigenvector_leading_dimension, const Real *eigenvalues, const std::vector< bool > &band_converged, const Real *kinetic_energy_squared, const Complex *hamiltonian_basis_vectors, const Complex *overlap_basis_vectors, Complex *correction_columns)=0
virtual void extract_eigenvectors(int basis_size, int number_of_plane_waves, int number_of_bands, int kpoint_index_state, bool is_gamma_only, const Complex *eigenvector_matrix, const Complex *basis_vectors, const Real *eigenvalues, Complex *rotated_scratch, PlanewaveKohnShamQuantumSystem &quantum_system)=0
virtual int diagonalize_subspace(int basis_size, int maximum_basis_size, bool is_gamma_only, const Complex *subspace_hamiltonian, const Complex *subspace_overlap, Real *eigenvalues, Complex *eigenvector_matrix)=0
virtual void update_subspace_matrices(int start_column, int new_columns, int total_basis_size, int maximum_basis_size, int number_of_plane_waves, bool is_gamma_only, const Complex *basis_vectors, const Complex *hamiltonian_basis_vectors, const Complex *overlap_basis_vectors, Complex *subspace_hamiltonian, Complex *subspace_overlap)=0
virtual ~PlanewaveSubspaceManager()=default
virtual int collapse_subspace(int basis_size, int number_of_plane_waves, int number_of_bands, int maximum_basis_size, bool is_gamma_only, bool is_identity_overlap, const OverlapOperator *overlap_operator, const Complex *subspace_hamiltonian, const Complex *subspace_overlap, Complex *basis_vectors, Complex *hamiltonian_basis_vectors, Complex *overlap_basis_vectors, Complex *rotation_scratch)=0
virtual int orthogonalize_batch(int starting_vector_index, int number_of_candidates, int number_of_plane_waves, bool is_gamma_only, const OverlapOperator *overlap_operator, Complex *basis_vectors, Complex *overlap_basis_vectors)=0
double Real
std::complex< double > Complex