#include <gpu.hpp>
Inheritance diagram for q3::GPUPlanewaveSubspaceManager:Public Member Functions | |
| GPUPlanewaveSubspaceManager (execution::gpu::blas::GPUBLAS &gpu_blas, const execution::ExecutionPolicy &execution_policy, std::shared_ptr< execution::gpu::device::GPUDeviceBackend > device_backend) | |
| 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) override |
| 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) override |
| 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) override |
| 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) override |
| 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) override |
| 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) override |
| void | set_gamma_origin_is_local (bool origin_is_local) override |
| 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) override |
Public Member Functions inherited from q3::PlanewaveSubspaceManager | |
| virtual | ~PlanewaveSubspaceManager ()=default |
|
inline |
|
inlineoverridevirtual |
Apply Davidson preconditioner to residual wavefunctions.
std::vector<bool> is bit-packed and has no contiguous bool storage, so stage through a byte-per-flag vector for the device upload.
Implements q3::PlanewaveSubspaceManager.
Definition at line 1086 of file gpu.hpp.
References q3::execution::gpu::device::GPUDeviceBuffer< T >::data(), q3::diagonalizer::planewave::gpu::launch_apply_preconditioner(), and q3::math::tolerances::preconditioner_denominator_floor.
Referenced by build_correction_vectors().
|
inlineoverridevirtual |
Collapse subspace via GPU GEMM rotation.
Same formulation as the CPU path: R = (HV)c - eps (SV)c, two GEMMs writing straight into the free basis columns, so no Ritz vectors and no residual array are held. The device path is single-process, so there is no band partition to apply.
The preconditioner kernel dereferences the eigenvalues on the device, so stage them there rather than hand over a host vector.
Implements q3::PlanewaveSubspaceManager.
Definition at line 793 of file gpu.hpp.
References apply_preconditioner(), q3::execution::gpu::device::GPUDeviceBuffer< T >::data(), q3::execution::gpu::blas::GPUBLAS::gemm(), and q3::execution::gpu::blas::GPUBLAS::scale().
|
inlineoverridevirtual |
Collapse the subspace back to number_of_bands vectors by rotating the basis with the eigenvector matrix.
The rotation needs somewhere to build its result before overwriting the array it is reading, and the caller supplies one buffer of at least number_of_bands * number_of_plane_waves. One is enough because each rotation reads a different array than it writes. These used to be three members sized by maximum_basis_size, which made the collapse as expensive in memory as the basis it collapses.
The rotation matrix is the eigenvector matrix of the current subspace, and the caller already holds that subspace: subspace_hamiltonian and subspace_overlap are the incrementally updated matrices with leading dimension maximum_basis_size, complete through basis_size. Diagonalising them costs basis_size cubed; rebuilding them from the vectors first – which is what this used to do – costs two products of basis_size squared by number_of_plane_waves on top, and was the largest single compute term of a restart. Pass nullptr for either to force that rebuild, which is also the fallback when the passed matrices cannot be diagonalised: the Davidson loop asks for a collapse precisely when its own diagonalisation of them has just failed.
Returns the new basis size (= number_of_bands).
As on the CPU path: the caller's subspace is complete through basis_size, so diagonalise it; rebuild from the vectors only as the fallback for the recovery collapse.
As on the CPU path: only number_of_bands columns are rotated and copied back, and the destination is the caller's scratch rather than three more device buffers the size of the whole basis.
One scratch buffer serves all three rotations: each reads a different array than it writes, and the overlap needs no rotation at all when it aliases the basis.
Skip the overlap rotation only when the overlap array is the basis itself. An identity overlap is not enough: the CPU workspace aliases S|V> to |V> for it, so rotating the basis has already rotated S|V>, but the device workspace keeps S|V> in a buffer of its own. Keying the skip on the flag left that buffer unrotated after every collapse, so the next orthogonalisation and subspace update read stale S|V>, and a run that collapsed often converged to the wrong answer – 1.77 Ry low on the two-atom silicon deck at expansion factor 2, which collapses every iteration. Factor 4 hid it: small decks converge before the basis fills.
Implements q3::PlanewaveSubspaceManager.
Definition at line 906 of file gpu.hpp.
References q3::execution::gpu::device::GPUDeviceBuffer< T >::data(), diagonalize_subspace(), and q3::execution::gpu::blas::GPUBLAS::gemm().
|
inlineoverridevirtual |
Diagonalize subspace via CPU LAPACK (small matrix — GPU not beneficial).
The solver overwrites both inputs, and the caller's matrices carry the next iteration's incremental update, so it works on copies. The Hamiltonian's copy is the eigenvector buffer itself – the solver returns the eigenvectors where the matrix was – and only the overlap needs a buffer of its own. Both are compacted from the caller's leading dimension to basis_size. That is two matrices of basis_size squared here rather than three, on every rank.
Which ranks run the eigensolver, in three cases:
The two conditions must agree. Testing group_rank_index() == 0 to solve but group_size() > 1 to broadcast leaves the non-root ranks of a replicated group with neither a result nor a broadcast, and they then diverge from the root at the next collective.
Implements q3::PlanewaveSubspaceManager.
Definition at line 711 of file gpu.hpp.
References q3::execution::ExecutionPolicy::broadcast_from_group_root(), q3::execution::ExecutionPolicy::group_rank_index(), q3::execution::ExecutionPolicy::group_size(), and q3::log::warn().
Referenced by collapse_subspace().
|
inlineoverridevirtual |
Extract eigenvectors using GPU GEMM rotation.
The rotation lands in the caller's scratch, which on this path is a device buffer already sized for it, so the extra device allocation this used to make is gone. The host copy stays: band data is written to the quantum system one band at a time from host memory.
Implements q3::PlanewaveSubspaceManager.
Definition at line 1024 of file gpu.hpp.
References q3::execution::gpu::device::GPUDeviceBuffer< T >::data(), q3::execution::gpu::blas::GPUBLAS::gemm(), q3::PlanewaveKohnShamQuantumSystem::set_eigenvalue(), and q3::PlanewaveKohnShamQuantumSystem::wavefunction_band_data().
|
inlineoverridevirtual |
S-orthogonalize and normalize a batch of candidate vectors against the existing basis using modified Gram-Schmidt with S inner product.
Returns the number of accepted (linearly independent) vectors.
Implements q3::PlanewaveSubspaceManager.
Definition at line 67 of file gpu.hpp.
References q3::OverlapOperator::apply_batch(), q3::execution::gpu::device::GPUDeviceBuffer< T >::data(), q3::execution::gpu::blas::GPUBLAS::dgemm(), q3::blas::dgemm_(), q3::blas::dgemv_(), q3::blas::dpotrf_(), q3::blas::dtrsm_(), q3::execution::gpu::blas::GPUBLAS::gemm(), q3::math::tolerances::iterative_solver_norm_threshold, q3::execution::ExecutionPolicy::reduce_within_group(), q3::blas::zdscal_(), q3::blas::zgemm_(), q3::blas::zgemv_(), q3::blas::zpotrf_(), and q3::blas::ztrsm_().
|
inlineoverridevirtual |
S-orthogonalize and normalize candidates using GPU BLAS.
Uses GPU GEMM for computing overlap coefficients and applying projections. Falls back to modified Gram-Schmidt if Cholesky fails.
Implements q3::PlanewaveSubspaceManager.
|
inlineoverridevirtual |
Incrementally update subspace matrices via GPU GEMM.
Implements q3::PlanewaveSubspaceManager.
Definition at line 576 of file gpu.hpp.
References q3::execution::gpu::device::GPUDeviceBuffer< T >::data(), q3::execution::gpu::blas::GPUBLAS::dgemm(), q3::execution::gpu::blas::GPUBLAS::gemm(), and q3::execution::ExecutionPolicy::reduce_within_group().