Loading...
Searching...
No Matches
q3::GPUPlanewaveSubspaceManager Class Reference

#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
 

Detailed Description

Definition at line 39 of file gpu.hpp.

Constructor & Destructor Documentation

◆ GPUPlanewaveSubspaceManager()

q3::GPUPlanewaveSubspaceManager::GPUPlanewaveSubspaceManager ( execution::gpu::blas::GPUBLAS &  gpu_blas,
const execution::ExecutionPolicy &  execution_policy,
std::shared_ptr< execution::gpu::device::GPUDeviceBackend >  device_backend 
)
inline

Construct with GPU math wrappers and execution policy.

Parameters
gpu_blasGPU BLAS wrapper for GEMM operations.
execution_policyExecution policy for band-group collectives.
device_backendGPU device backend for buffer allocation.

Definition at line 48 of file gpu.hpp.

Member Function Documentation

◆ apply_preconditioner()

void q3::GPUPlanewaveSubspaceManager::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 
)
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().

◆ build_correction_vectors()

int q3::GPUPlanewaveSubspaceManager::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 
)
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().

◆ collapse_subspace()

int q3::GPUPlanewaveSubspaceManager::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 
)
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().

◆ diagonalize_subspace()

int q3::GPUPlanewaveSubspaceManager::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 
)
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:

  • a collective solver (ScaLAPACK) must be entered by EVERY rank of the group — gating on the root would deadlock — and returns redundant results, so no broadcast follows;
  • replicated coefficient vectors (group_size() <= 1) mean every rank already holds the same matrices, so each solves its own copy and there is no group to broadcast over. This includes the fallback that disables band distribution AFTER this manager was built, where group_rank_index() keeps its pool-local value and is not necessarily 0;
  • distributed vectors with a non-collective solver: the group root solves and broadcasts.

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().

◆ extract_eigenvectors()

void q3::GPUPlanewaveSubspaceManager::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 
)
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().

◆ orthogonalize_batch()

int q3::GPUPlanewaveSubspaceManager::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 
)
inlineoverridevirtual

◆ set_gamma_origin_is_local()

void q3::GPUPlanewaveSubspaceManager::set_gamma_origin_is_local ( bool  origin_is_local)
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.

Definition at line 63 of file gpu.hpp.

◆ update_subspace_matrices()

void q3::GPUPlanewaveSubspaceManager::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 
)
inlineoverridevirtual

The documentation for this class was generated from the following file: