SIRIUS 7.5.0
Electronic structure library and applications
beta_projectors_base.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2017 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 beta_projectors_base.hpp
21 *
22 * \brief Contains declaration and implementation of sirius::Beta_projectors_base class.
23 */
24
25#ifndef __BETA_PROJECTORS_BASE_HPP__
26#define __BETA_PROJECTORS_BASE_HPP__
27
30#include "SDDK/memory.hpp"
32#include <spla/context.hpp>
33
34namespace sirius {
35
36#if defined(SIRIUS_GPU)
37extern "C" {
38
39void create_beta_gk_gpu_float(int num_atoms, int num_gkvec, int const* beta_desc, std::complex<float> const* beta_gk_t,
40 double const* gkvec, double const* atom_pos, std::complex<float>* beta_gk);
41
42void create_beta_gk_gpu_double(int num_atoms, int num_gkvec, int const* beta_desc,
43 std::complex<double> const* beta_gk_t, double const* gkvec, double const* atom_pos,
44 std::complex<double>* beta_gk);
45}
46#endif
47
48/// Named index of a descriptor of beta-projectors. The same order is used by the GPU kernel.
50{
51 /// Number of beta-projector functions for this atom.
52 static const int nbf = 0;
53 /// Offset of beta-projectors in this chunk.
54 static const int offset = 1;
55 /// Offset of beta-projectors in the array for atom types.
56 static const int offset_t = 2;
57 /// Global index of atom.
58 static const int ia = 3;
59};
60
61/// Describe chunk of beta-projectors for a block of atoms.
62/** Beta-projectors are processed in "chunks" to avoid large memory consumption. */
64{
65 /// Number of beta-projectors in the current chunk.
67 /// Number of atoms in the current chunk.
69 /// Offset in the global index of beta projectors.
71 /// Descriptor of block of beta-projectors for an atom.
73 /// Positions of atoms.
75
76 /// Default constructor.
77 beta_chunk_t() = default;
78
79 /// Copy constructor.
81 : desc_{empty_like(src__.desc_)}
82 , atom_pos_{empty_like(src__.atom_pos_)}
83 {
84 // pass
85 num_beta_ = src__.num_beta_;
86 num_atoms_ = src__.num_atoms_;
87 offset_ = src__.offset_;
88
89 auto_copy(desc_, src__.desc_);
91 }
92
93 /// Copy assignment operator.
95 {
96 num_beta_ = rhs__.num_beta_;
97 num_atoms_ = rhs__.num_atoms_;
98 offset_ = rhs__.offset_;
99
100 desc_ = empty_like(rhs__.desc_);
101 auto_copy(desc_, rhs__.desc_);
102
103 atom_pos_ = empty_like(rhs__.atom_pos_);
105 return *this;
106 }
107};
108
109/// Stores a chunk of the beta-projector and metadata.
110/**
111 * \tparam T Precision type (float or double)
112 *
113 */
114template <typename T>
116{
117 using complex_t = std::complex<T>;
118
119 sddk::matrix<complex_t> pw_coeffs_a_;
120 /// Communicator that splits G+k vectors.
122 /// Descriptor of the current beta chunk.
124 /// Buffer (num_max_beta) for pw_coeffs_a_
126
127 /// Beta-projectors are treated as non-magnetic.
129 {
130 return wf::spin_index(0);
131 }
132
133 /// Leading dimension.
134 auto ld() const
135 {
136 return static_cast<int>(pw_coeffs_a_.ld());
137 }
138
139 auto num_md() const
140 {
141 return wf::num_mag_dims(0);
142 }
143
144 auto comm() const -> const mpi::Communicator&
145 {
146 return comm_;
147 }
148
149 auto const* at(sddk::memory_t mem__, int i__, wf::spin_index s__, wf::band_index b__) const
150 {
151 return pw_coeffs_a_.at(mem__, i__, b__.get());
152 }
153};
154
155namespace local {
156
157template <class T>
158void beta_projectors_generate_cpu(sddk::matrix<std::complex<T>>& pw_coeffs_a,
159 sddk::mdarray<std::complex<T>, 3> const& pw_coeffs_t, int ichunk__, int j__,
160 beta_chunk_t const& beta_chunk, Simulation_context const& ctx, fft::Gvec const& gkvec);
161
162template <class T>
163void beta_projectors_generate_gpu(beta_projectors_coeffs_t<T>& out,
164 sddk::mdarray<std::complex<double>, 3> const& pw_coeffs_t_device,
165 sddk::mdarray<std::complex<double>, 3> const& pw_coeffs_t_host, Simulation_context const& ctx,
166 fft::Gvec const& gkvec, sddk::mdarray<double, 2> const& gkvec_coord_, beta_chunk_t const& beta_chunk,
167 std::vector<int> const& igk__, int j__);
168
169} // namespace local
170
171/// Generates beta projector PW coefficients and holds GPU memory phase-factor
172/// independent coefficients of |> functions for atom types.
173template <typename T>
175{
176 public:
177 typedef std::complex<T> complex_t;
179
180 public:
181 Beta_projector_generator(Simulation_context& ctx, array_t const& pw_coeffs_t_host,
182 sddk::matrix<std::complex<T>> const& beta_pw_all, sddk::device_t processing_unit,
183 std::vector<beta_chunk_t> const& beta_chunks, fft::Gvec const& gkvec,
184 sddk::mdarray<double, 2> const& gkvec_coord, int num_gkvec_loc);
185
186 void generate(beta_projectors_coeffs_t<T>& coeffs, int ichunk, int j) const;
187 void generate(beta_projectors_coeffs_t<T>& coeffs, int ichunk) const;
188
189 beta_projectors_coeffs_t<T> prepare() const;
190
191 Simulation_context& ctx()
192 {
193 return ctx_;
194 }
195 int num_chunks() const
196 {
197 return beta_chunks_.size();
198 }
199
200 const auto& chunks() const
201 {
202 return beta_chunks_;
203 }
204
205 auto device_t() const -> sddk::device_t
206 {
207 return processing_unit_;
208 }
209
210 private:
211 /// Simulation context.
213 /// Beta-projectors for atom-types.
215 /// Beta-projectors for atom-types on device.
217 /// Precomputed beta coefficients on CPU.
219 /// Processing unit.
221 /// Chunk descriptors.
222 std::vector<beta_chunk_t> const& beta_chunks_;
223 /// G+k vectors.
225 /// Coordinates of G+k vectors.
227 /// Local number of G+k vectors.
229 /// Maximum number of beta-projectors.
231};
232
233template <typename T>
235 sddk::matrix<std::complex<T>> const& beta_pw_all,
236 sddk::device_t processing_unit,
237 std::vector<beta_chunk_t> const& beta_chunks,
238 fft::Gvec const& gkvec,
239 sddk::mdarray<double, 2> const& gkvec_coord, int num_gkvec_loc)
240 : ctx_(ctx)
241 , pw_coeffs_t_host_(pw_coeffs_t_host)
242 , beta_pw_all_atoms_(beta_pw_all)
243 , processing_unit_(processing_unit)
244 , beta_chunks_(beta_chunks)
245 , gkvec_(gkvec)
246 , gkvec_coord_(gkvec_coord)
247 , num_gkvec_loc_(num_gkvec_loc)
248{
249 if (processing_unit == sddk::device_t::GPU) {
250 pw_coeffs_t_device_ = array_t(pw_coeffs_t_host.size(0), pw_coeffs_t_host.size(1), pw_coeffs_t_host.size(2),
251 sddk::get_memory_pool(sddk::memory_t::device));
252 // copy to device
253 acc::copyin(pw_coeffs_t_device_.device_data(), pw_coeffs_t_host.host_data(), pw_coeffs_t_host.size());
254 }
255
256 int max_num_beta = 0;
257 for (auto& e : beta_chunks_) {
258 max_num_beta = std::max(max_num_beta, e.num_beta_);
259 }
260 this->max_num_beta_ = max_num_beta;
261}
262
263template <typename T>
264beta_projectors_coeffs_t<T>
265Beta_projector_generator<T>::prepare() const
266{
267 beta_projectors_coeffs_t<T> beta_storage;
268 beta_storage.comm_ = gkvec_.comm().duplicate();
269
270 if (processing_unit_ == sddk::device_t::GPU) {
271 beta_storage.pw_coeffs_a_buffer_ =
272 sddk::matrix<std::complex<T>>(num_gkvec_loc_, max_num_beta_, sddk::get_memory_pool(sddk::memory_t::device));
273 }
274
275 return beta_storage;
276}
277
278/// Base class for beta-projectors, gradient of beta-projectors and strain derivatives of beta-projectors.
279/** \tparam T Precision of beta-projectors (float or double).
280 */
281template <typename T>
283{
284 protected:
285 Simulation_context& ctx_;
286
287 /// List of G+k vectors.
289
290 /// Coordinates of G+k vectors used by GPU kernel.
292
293 /// Number of different components: 1 for beta-projectors, 3 for gradient, 9 for strain derivatives.
294 int N_;
295
296 /// Phase-factor independent coefficients of |beta> functions for atom types.
298
299 bool reallocate_pw_coeffs_t_on_gpu_{true};
300
301 /// Set of beta PW coefficients for a chunk of atoms.
303
304 /// Set of beta PW coefficients for all atoms
306
307 std::vector<beta_chunk_t> beta_chunks_;
308
309 int max_num_beta_;
310
311 /// total number of beta-projectors (=number of columns)
313
314 /// Total number of beta-projectors among atom types.
316
317 /// Split beta-projectors into chunks.
318 void split_in_chunks();
319
320 public:
321 Beta_projectors_base(Simulation_context& ctx__, fft::Gvec const& gkvec__, int N__);
322
323 Beta_projector_generator<T> make_generator() const
324 {
325 return make_generator(ctx_.processing_unit());
326 }
327
328 Beta_projector_generator<T> make_generator(sddk::device_t pu) const
329 {
331 beta_chunks_, gkvec_, gkvec_coord_, num_gkvec_loc()};
332 }
333
334 Beta_projector_generator<T> make_generator(sddk::memory_t mem) const
335 {
336 sddk::device_t pu{sddk::device_t::CPU};
337 if (sddk::is_device_memory(mem)) {
338 pu = sddk::device_t::GPU;
339 }
340 return make_generator(pu);
341 }
342
343 auto const& ctx() const
344 {
345 return ctx_;
346 }
347
348 inline auto num_gkvec_loc() const
349 {
350 return gkvec_.count();
351 }
352
353 int num_total_beta() const
354 {
355 return num_total_beta_;
356 }
357
358 inline int num_comp() const
359 {
360 return N_;
361 }
362
363 inline auto const& unit_cell() const
364 {
365 return ctx_.unit_cell();
366 }
367
368 auto& pw_coeffs_t(int ig__, int n__, int j__)
369 {
370 return pw_coeffs_t_(ig__, n__, j__);
371 }
372
373 auto pw_coeffs_t(int j__)
374 {
375 return sddk::matrix<std::complex<T>>(&pw_coeffs_t_(0, 0, j__), num_gkvec_loc(), num_beta_t());
376 }
377
378 auto const& pw_coeffs_a() const
379 {
380 return pw_coeffs_a_;
381 }
382
383 inline int num_beta_t() const
384 {
385 return num_beta_t_;
386 }
387
388 inline int num_chunks() const
389 {
390 return static_cast<int>(beta_chunks_.size());
391 }
392
393 inline int max_num_beta() const
394 {
395 return max_num_beta_;
396 }
397
398 int nrows() const
399 {
400 return gkvec_.num_gvec();
401 }
402
403 const mpi::Communicator& comm() const
404 {
405 return gkvec_.comm();
406 }
407};
408
409/** The following is matrix computed: <beta|phi>
410 *
411 * \tparam F Type of the resulting inner product matrix (float, double, complex<float> or complex<double>).
412 * \tparam T precision type
413 *
414 * \param [in] spla_ctx Context of the SPLA library
415 * \param [in] mem Location of the input arrays (wfc and beta-projectors)
416 * \param [in] host_mem Host memory type for result allocation (pinned, non-pinned memory)
417 * \param [in] result_on_device Copy result to device if true
418 * \param [in] beta_coeffs Beta-projector coefficient array
419 * \param [in] phi Wave-function
420 * \param [in] ispn Spin index (wfc)
421 * \param [in] br Band range
422 * \return inner product
423 */
424template <typename F, typename T>
425std::enable_if_t<std::is_same<T, real_type<F>>::value, la::dmatrix<F>>
426inner_prod_beta(spla::Context& spla_ctx, sddk::memory_t mem__, sddk::memory_t host_mem__, bool result_on_device,
427 beta_projectors_coeffs_t<T>& beta_coeffs__, wf::Wave_functions<T> const& phi__, wf::spin_index ispn__,
428 wf::band_range br__)
429{
430 int nbeta = beta_coeffs__.beta_chunk_.num_beta_;
431
432 la::dmatrix<F> result(nbeta, br__.size(), get_memory_pool(host_mem__), "<beta|phi>");
433 if (result_on_device) {
434 result.allocate(get_memory_pool(sddk::memory_t::device));
435 }
436
437 wf::inner<F>(spla_ctx, mem__, wf::spin_range(ispn__.get()), beta_coeffs__, wf::band_range(0, nbeta), phi__, br__,
438 result, 0, 0);
439
440 return result;
441}
442
443/// computes <beta|beta> and returns result on ctx.processing_unit_memory_t
444template <class T>
445sddk::matrix<std::complex<T>>
447{
448 using complex_t = std::complex<T>;
449 auto generator = beta.make_generator();
450 int num_beta_chunks = beta.num_chunks();
451 auto bcoeffs_row = generator.prepare();
452 auto bcoeffs_col = generator.prepare();
453 auto mem_t = ctx.processing_unit_memory_t();
454
456 if (sddk::is_device_memory(mem_t)) {
458 }
459
460 int size{beta.num_total_beta()};
461
462 sddk::matrix<complex_t> out(size, size, sddk::get_memory_pool(mem_t));
463
464 complex_t one = complex_t(1);
465 complex_t zero = complex_t(0);
466
467 for (int ichunk = 0; ichunk < num_beta_chunks; ++ichunk) {
468 generator.generate(bcoeffs_row, ichunk);
469
470 for (int jchunk = 0; jchunk < num_beta_chunks; ++jchunk) {
471 generator.generate(bcoeffs_col, jchunk);
472 int m = bcoeffs_row.beta_chunk_.num_beta_;
473 int n = bcoeffs_col.beta_chunk_.num_beta_;
474 int k = bcoeffs_col.pw_coeffs_a_.size(0);
475 int dest_row = bcoeffs_row.beta_chunk_.offset_;
476 int dest_col = bcoeffs_col.beta_chunk_.offset_;
477 const complex_t* A = bcoeffs_row.pw_coeffs_a_.at(mem_t);
478 const complex_t* B = bcoeffs_col.pw_coeffs_a_.at(mem_t);
479 complex_t* C = out.at(mem_t, dest_row, dest_col);
480 la::wrap(la).gemm('C', 'N', m, n, k, &one, A, bcoeffs_row.pw_coeffs_a_.ld(), B,
481 bcoeffs_col.pw_coeffs_a_.ld(), &zero, C, out.ld());
482 }
483 }
484
485 if (beta.comm().size() > 1) {
486 RTE_THROW("this needs to be fixed first");
487 beta.comm().allreduce(out.at(sddk::memory_t::host), static_cast<int>(out.size()));
488 }
489
490 return out;
491}
492
493/// inner product <beta|Op|beta>, return resulting dmatrix<complex> in ctx.processing_unit_memory_t
494template <class T, class Op>
495sddk::matrix<std::complex<T>>
497{
498 using complex_t = std::complex<double>;
499 auto generator = beta.make_generator();
500 int num_beta_chunks = beta.num_chunks();
501 auto bcoeffs_row = generator.prepare();
502 auto bcoeffs_col = generator.prepare();
503 auto mem_t = ctx.processing_unit_memory_t();
504
506 if (sddk::is_device_memory(mem_t)) {
508 }
509
510 int size{beta.num_total_beta()};
511
512 sddk::matrix<complex_t> out(size, size, mem_t);
513
514 complex_t one = complex_t(1);
515 complex_t zero = complex_t(0);
516
517 for (int ichunk = 0; ichunk < num_beta_chunks; ++ichunk) {
518 generator.generate(bcoeffs_row, ichunk);
519
520 for (int jchunk = 0; jchunk < num_beta_chunks; ++jchunk) {
521 generator.generate(bcoeffs_col, jchunk);
522
523 int m = bcoeffs_row.beta_chunk_.num_beta_;
524 int n = bcoeffs_col.beta_chunk_.num_beta_;
525 int k = bcoeffs_col.pw_coeffs_a_.size(0);
526 int dest_row = bcoeffs_row.beta_chunk_.offset_;
527 int dest_col = bcoeffs_col.beta_chunk_.offset_;
528 const complex_t* A = bcoeffs_row.pw_coeffs_a_.at(mem_t);
529 // apply Op on |b> (in-place operation)
530 auto G = op(bcoeffs_col.pw_coeffs_a_);
531
532 const complex_t* B2 = G.at(mem_t);
533 complex_t* C = out.at(mem_t, dest_row, dest_col);
534 la::wrap(la).gemm('C', 'N', m, n, k, &one, A, bcoeffs_row.pw_coeffs_a_.ld(), B2, G.ld(), &zero, C, out.ld());
535 }
536 }
537 if (beta.comm().size() > 1) {
538 beta.comm().allreduce(out.at(sddk::memory_t::host), static_cast<int>(out.size()));
539 }
540
541 return out;
542}
543
544} // namespace sirius
545
546#endif
int num_gkvec_loc_
Local number of G+k vectors.
sddk::device_t processing_unit_
Processing unit.
fft::Gvec const & gkvec_
G+k vectors.
std::vector< beta_chunk_t > const & beta_chunks_
Chunk descriptors.
array_t pw_coeffs_t_device_
Beta-projectors for atom-types on device.
Simulation_context & ctx_
Simulation context.
int max_num_beta_
Maximum number of beta-projectors.
sddk::matrix< complex_t > const & beta_pw_all_atoms_
Precomputed beta coefficients on CPU.
array_t const & pw_coeffs_t_host_
Beta-projectors for atom-types.
sddk::mdarray< double, 2 > const & gkvec_coord_
Coordinates of G+k vectors.
Base class for beta-projectors, gradient of beta-projectors and strain derivatives of beta-projectors...
fft::Gvec const & gkvec_
List of G+k vectors.
sddk::mdarray< double, 2 > gkvec_coord_
Coordinates of G+k vectors used by GPU kernel.
int num_total_beta_
total number of beta-projectors (=number of columns)
sddk::matrix< std::complex< T > > pw_coeffs_a_
Set of beta PW coefficients for a chunk of atoms.
sddk::mdarray< std::complex< T >, 3 > pw_coeffs_t_
Phase-factor independent coefficients of |beta> functions for atom types.
int N_
Number of different components: 1 for beta-projectors, 3 for gradient, 9 for strain derivatives.
sddk::matrix< std::complex< T > > beta_pw_all_atoms_
Set of beta PW coefficients for all atoms.
void split_in_chunks()
Split beta-projectors into chunks.
int num_beta_t_
Total number of beta-projectors among atom types.
Simulation context is a set of parameters and objects describing a single simulation.
auto processing_unit_memory_t() const
Return the memory type for processing unit.
A set of G-vectors for FFTs and G+k basis functions.
Definition: gvec.hpp:130
int num_gvec() const
Return the total number of G-vectors within the cutoff.
Definition: gvec.hpp:478
int count() const
Number of G-vectors for a fine-grained distribution for the current MPI rank.
Definition: gvec.hpp:506
Distributed matrix.
Definition: dmatrix.hpp:56
void gemm(char transa, char transb, ftn_int m, ftn_int n, ftn_int k, T const *alpha, T const *A, ftn_int lda, T const *B, ftn_int ldb, T const *beta, T *C, ftn_int ldc, acc::stream_id sid=acc::stream_id(-1)) const
General matrix-matrix multiplication.
MPI communicator wrapper.
int size() const
Size of the communicator (number of ranks).
void allreduce(T *buffer__, int count__) const
Perform the in-place (the output buffer is used as the input buffer) all-to-all reduction.
uint32_t ld() const
Return leading dimension size.
Definition: memory.hpp:1233
mdarray< T, N > & allocate(memory_t memory__)
Allocate memory for array.
Definition: memory.hpp:1057
size_t size() const
Return total size (number of elements) of the array.
Definition: memory.hpp:1207
Wave-functions representation.
Describe a range of bands.
Describe a range of spins.
Contains declaration and implementation of mpi::Communicator class.
Memory management functions and classes.
device_t
Type of the main processing unit.
Definition: memory.hpp:120
memory_t
Memory types where the code can store data.
Definition: memory.hpp:71
void auto_copy(mdarray< T, N > &dst, const mdarray< T, N > &src)
Copy all memory present on destination.
Definition: memory.hpp:1498
void copyin(T *target__, T const *source__, size_t n__)
Copy memory from host to device.
Definition: acc.hpp:337
void zero(T *ptr__, size_t n__)
Zero the device memory.
Definition: acc.hpp:397
lib_t
Type of linear algebra backend library.
Definition: linalg_base.hpp:70
@ gpublas
GPU BLAS (cuBlas or ROCblas)
Namespace of the SIRIUS library.
Definition: sirius.f90:5
std::enable_if_t< std::is_same< T, real_type< F > >::value, la::dmatrix< F > > inner_prod_beta(spla::Context &spla_ctx, sddk::memory_t mem__, sddk::memory_t host_mem__, bool result_on_device, beta_projectors_coeffs_t< T > &beta_coeffs__, wf::Wave_functions< T > const &phi__, wf::spin_index ispn__, wf::band_range br__)
sddk::matrix< std::complex< T > > inner_beta(const Beta_projectors_base< T > &beta, const Simulation_context &ctx)
computes <beta|beta> and returns result on ctx.processing_unit_memory_t
Contains definition and implementation of Simulation_context class.
Describe chunk of beta-projectors for a block of atoms.
sddk::mdarray< int, 2 > desc_
Descriptor of block of beta-projectors for an atom.
int offset_
Offset in the global index of beta projectors.
beta_chunk_t & operator=(beta_chunk_t const &rhs__)
Copy assignment operator.
beta_chunk_t(beta_chunk_t const &src__)
Copy constructor.
int num_atoms_
Number of atoms in the current chunk.
sddk::mdarray< double, 2 > atom_pos_
Positions of atoms.
int num_beta_
Number of beta-projectors in the current chunk.
beta_chunk_t()=default
Default constructor.
Named index of a descriptor of beta-projectors. The same order is used by the GPU kernel.
static const int ia
Global index of atom.
static const int nbf
Number of beta-projector functions for this atom.
static const int offset
Offset of beta-projectors in this chunk.
static const int offset_t
Offset of beta-projectors in the array for atom types.
Stores a chunk of the beta-projector and metadata.
beta_chunk_t beta_chunk_
Descriptor of the current beta chunk.
mpi::Communicator comm_
Communicator that splits G+k vectors.
sddk::matrix< complex_t > pw_coeffs_a_buffer_
Buffer (num_max_beta) for pw_coeffs_a_.
auto actual_spin_index(wf::spin_index s__) const -> wf::spin_index
Beta-projectors are treated as non-magnetic.
auto ld() const
Leading dimension.
Contains declaration and implementation of Wave_functions class.