SIRIUS 7.5.0
Electronic structure library and applications
k_point.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2018 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 k_point.hpp
21 *
22 * \brief Contains definition of sirius::K_point class.
23 */
24
25#ifndef __K_POINT_HPP__
26#define __K_POINT_HPP__
27
31#include "core/fft/fft.hpp"
33
34namespace sirius {
35
36/// K-point related variables and methods.
37/** \image html wf_storage.png "Wave-function storage"
38 * \image html fv_eigen_vectors.png "First-variational eigen vectors"
39 *
40 * \tparam T Precision of the wave-functions (float or double).
41 */
42template <typename T>
44{
45 private:
46 /// Simulation context.
48
49 /// Unit cell object.
51
52 /// Fractional k-point coordinates.
54
55 /// Weight of k-point.
56 double weight_{1.0};
57
58 /// Communicator for parallelization inside k-point.
59 /** This communicator is used to split G+k vectors and wave-functions. */
61
62 /// List of G-vectors with |G+k| < cutoff.
63 std::shared_ptr<fft::Gvec> gkvec_;
64
65 std::shared_ptr<fft::Gvec> gkvec_row_;
66
67 std::shared_ptr<fft::Gvec> gkvec_col_;
68
69 /// G-vector distribution for the FFT transformation.
70 std::shared_ptr<fft::Gvec_fft> gkvec_partition_;
71
72 mutable std::unique_ptr<fft::spfft_transform_type<T>> spfft_transform_;
73
74 /// First-variational eigen values
76
77 /// First-variational eigen vectors, distributed over 2D BLACS grid.
79
80 /// First-variational eigen vectors, distributed in slabs.
81 std::unique_ptr<wf::Wave_functions<T>> fv_eigen_vectors_slab_;
82
83 /// Lowest eigen-vectors of the LAPW overlap matrix with small aigen-values.
84 std::unique_ptr<wf::Wave_functions<T>> singular_components_;
85
86 /// Second-variational eigen vectors.
87 /** Second-variational eigen-vectors are stored as one or two \f$ N_{fv} \times N_{fv} \f$ matrices in
88 * case of non-magnetic or collinear magnetic case or as a single \f$ 2 N_{fv} \times 2 N_{fv} \f$
89 * matrix in case of general non-collinear magnetism. */
90 std::array<la::dmatrix<std::complex<T>>, 2> sv_eigen_vectors_;
91
92 /// Full-diagonalization eigen vectors.
94
95 /// First-variational states.
96 std::unique_ptr<wf::Wave_functions<T>> fv_states_{nullptr};
97
98 /// Two-component (spinor) wave functions describing the bands.
99 std::unique_ptr<wf::Wave_functions<T>> spinor_wave_functions_{nullptr};
100
101 /// Pseudopotential atmoic wave-functions (not orthogonalized).
102 std::unique_ptr<wf::Wave_functions<T>> atomic_wave_functions_{nullptr};
103
104 /// Pseudopotential atmoic wave-functions (not orthogonalized) with S-operator applied.
105 std::unique_ptr<wf::Wave_functions<T>> atomic_wave_functions_S_{nullptr};
106
107 /// Hubbard wave functions.
108 std::unique_ptr<wf::Wave_functions<T>> hubbard_wave_functions_{nullptr};
109
110 /// Hubbard wave functions with S-operator applied.
111 std::unique_ptr<wf::Wave_functions<T>> hubbard_wave_functions_S_{nullptr};
112
113 /// Band occupation numbers.
115
116 /// Band energies.
118
119 /// LAPW matching coefficients for the row G+k vectors.
120 /** Used to setup the distributed LAPW Hamiltonian and overlap matrices. */
121 std::unique_ptr<Matching_coefficients> alm_coeffs_row_{nullptr};
122
123 /// LAPW matching coefficients for the column G+k vectors.
124 /** Used to setup the distributed LAPW Hamiltonian and overlap matrices. */
125 std::unique_ptr<Matching_coefficients> alm_coeffs_col_{nullptr};
126
127 /// LAPW matching coefficients for the local set G+k vectors.
128 std::unique_ptr<Matching_coefficients> alm_coeffs_loc_{nullptr};
129
130 /// Number of G+k vectors distributed along rows of MPI grid
132
133 /// Number of G+k vectors distributed along columns of MPI grid
135
136 /// Basis descriptors distributed between rows of the 2D MPI grid.
137 /** This is a local array. Only MPI ranks belonging to the same column have identical copies of this array. */
138 std::vector<lo_basis_descriptor> lo_basis_descriptors_row_;
139
140 /// Basis descriptors distributed between columns of the 2D MPI grid.
141 /** This is a local array. Only MPI ranks belonging to the same row have identical copies of this array. */
142 std::vector<lo_basis_descriptor> lo_basis_descriptors_col_;
143
144 /// List of columns of the Hamiltonian and overlap matrix lo block (local index) for a given atom.
145 std::vector<std::vector<int>> atom_lo_cols_;
146
147 /// list of rows of the Hamiltonian and overlap matrix lo block (local index) for a given atom
148 std::vector<std::vector<int>> atom_lo_rows_;
149
150 /// Imaginary unit to the power of l.
151 std::vector<std::complex<double>> zil_;
152
153 /// Mapping between lm and l.
154 std::vector<int> l_by_lm_;
155
156 /// Column rank of the processors of ScaLAPACK/ELPA diagonalization grid.
158
159 /// Number of processors along the columns of the diagonalization grid.
161
162 /// Row rank of the processors of ScaLAPACK/ELPA diagonalization grid.
164
165 /// Number of processors along the rows of the diagonalization grid.
167
168 /// Beta projectors for a local set of G+k vectors.
169 std::unique_ptr<Beta_projectors<T>> beta_projectors_{nullptr};
170
171 /// Beta projectors for row G+k vectors.
172 /** Used to setup the full Hamiltonian in PP-PW case (for verification purpose only) */
173 std::unique_ptr<Beta_projectors<T>> beta_projectors_row_{nullptr};
174
175 /// Beta projectors for column G+k vectors.
176 /** Used to setup the full Hamiltonian in PP-PW case (for verification purpose only) */
177 std::unique_ptr<Beta_projectors<T>> beta_projectors_col_{nullptr};
178
179 /// Communicator between(!!) rows.
181
182 /// Communicator between(!!) columns.
184
185 std::array<int, 2> ispn_map_{0, -1};
186
187 /// Generate G+k and local orbital basis sets.
188 void generate_gklo_basis();
189
190 /// Find G+k vectors within the cutoff.
191 void generate_gkvec(double gk_cutoff__);
192
193 inline int get_ispn(int ispn__) const
194 {
195 RTE_ASSERT(ispn__ == 0 || ispn__ == 1);
196 return ispn_map_[ispn__];
197 }
198
199 friend class K_point_set;
200
201 void init0()
202 {
203 band_occupancies_ = sddk::mdarray<double, 2>(ctx_.num_bands(), ctx_.num_spinors(),
204 sddk::memory_t::host, "band_occupancies");
206 band_energies_ = sddk::mdarray<double, 2>(ctx_.num_bands(), ctx_.num_spinors(),
207 sddk::memory_t::host, "band_energies");
209
210 if (ctx_.num_mag_dims() == 1) {
211 ispn_map_[1] = 1;
212 } else if (ctx_.num_mag_dims() == 3) {
213 ispn_map_[1] = 0;
214 }
215 }
216
217 public:
218 /// Constructor
219 K_point(Simulation_context& ctx__, r3::vector<double> vk__, double weight__)
220 : ctx_(ctx__)
221 , unit_cell_(ctx_.unit_cell())
222 , vk_(vk__)
223 , weight_(weight__)
224 , comm_(ctx_.comm_band())
225 , rank_col_(ctx_.blacs_grid().comm_col().rank())
226 , num_ranks_col_(ctx_.blacs_grid().comm_col().size())
227 , rank_row_(ctx_.blacs_grid().comm_row().rank())
228 , num_ranks_row_(ctx_.blacs_grid().comm_row().size())
229 , comm_row_(ctx_.blacs_grid().comm_row())
230 , comm_col_(ctx_.blacs_grid().comm_col())
231 {
232 this->init0();
233 gkvec_ = std::make_shared<fft::Gvec>(vk_, unit_cell_.reciprocal_lattice_vectors(), ctx_.gk_cutoff(), comm_,
234 ctx_.gamma_point());
235 }
236
237 /// Constructor
238 K_point(Simulation_context& ctx__, std::shared_ptr<fft::Gvec> gkvec__, double weight__)
239 : ctx_(ctx__)
240 , unit_cell_(ctx_.unit_cell())
241 , vk_(gkvec__->vk())
242 , weight_(weight__)
243 , comm_(ctx_.comm_band())
244 , gkvec_(gkvec__)
245 , rank_col_(ctx_.blacs_grid().comm_col().rank())
246 , num_ranks_col_(ctx_.blacs_grid().comm_col().size())
247 , rank_row_(ctx_.blacs_grid().comm_row().rank())
248 , num_ranks_row_(ctx_.blacs_grid().comm_row().size())
249 , comm_row_(ctx_.blacs_grid().comm_row())
250 , comm_col_(ctx_.blacs_grid().comm_col())
251 {
252 this->init0();
253 }
254
255 /// Initialize the k-point related arrays and data.
256 void initialize(); // TODO: initialize from HDF5
257
258 /// Update the reciprocal lattice vectors of the G+k array.
259 void update();
260
261 /// Generate first-variational states from eigen-vectors.
262 /** APW+lo basis \f$ \varphi_{\mu {\bf k}}({\bf r}) = \{ \varphi_{\bf G+k}({\bf r}),
263 \varphi_{j{\bf k}}({\bf r}) \} \f$ is used to expand first-variational wave-functions:
264
265 \f[
266 \psi_{i{\bf k}}({\bf r}) = \sum_{\mu} c_{\mu i}^{\bf k} \varphi_{\mu \bf k}({\bf r}) =
267 \sum_{{\bf G}}c_{{\bf G} i}^{\bf k} \varphi_{\bf G+k}({\bf r}) +
268 \sum_{j}c_{j i}^{\bf k}\varphi_{j{\bf k}}({\bf r})
269 \f]
270
271 Inside muffin-tins the expansion is converted into the following form:
272 \f[
273 \psi_{i {\bf k}}({\bf r})= \begin{array}{ll}
274 \displaystyle \sum_{L} \sum_{\lambda=1}^{N_{\ell}^{\alpha}}
275 F_{L \lambda}^{i {\bf k},\alpha}f_{\ell \lambda}^{\alpha}(r)
276 Y_{\ell m}(\hat {\bf r}) & {\bf r} \in MT_{\alpha} \end{array}
277 \f]
278
279 Thus, the total number of coefficients representing a wave-funstion is equal
280 to the number of muffin-tin basis functions of the form \f$ f_{\ell \lambda}^{\alpha}(r)
281 Y_{\ell m}(\hat {\bf r}) \f$ plust the number of G+k plane waves.
282 First-variational states are obtained from the first-variational eigen-vectors and
283 LAPW matching coefficients.
284
285 APW part:
286 \f[
287 \psi_{\xi j}^{\bf k} = \sum_{{\bf G}} Z_{{\bf G} j}^{\bf k} * A_{\xi}({\bf G+k})
288 \f]
289 */
290 void generate_fv_states();
291
292 /// Generate two-component spinor wave functions.
293 /** In case of second-variational diagonalization spinor wave-functions are generated from the first-variational
294 states and second-variational eigen-vectors. */
296
297 /// Generate plane-wave coefficients of the atomic wave-functions.
298 /** Plane-wave coefficients of the atom-centered wave-functions
299 \f$ \varphi^{\alpha}_{\ell m}({\bf r}) = \varphi^{\alpha}_{\ell}(r)R_{\ell m}(\theta, \phi) \f$
300 are computed in the following way:
301 \f[
302 \varphi^{\alpha}_{\ell m}({\bf q}) = \frac{1}{\sqrt{\Omega}}
303 \int e^{-i{\bf q}{\bf r}} \varphi^{\alpha}_{\ell m}({\bf r} - {\bf r}_{\alpha}) d{\bf r} =
304 \frac{e^{-i{\bf q}{\bf r}_{\alpha}}}{\sqrt{\Omega}} \int e^{-i{\bf q}{\bf r}}
305 \varphi^{\alpha}_{\ell}(r)R_{\ell m}(\theta, \phi) r^2 \sin\theta dr d\theta d\phi
306 \f]
307 where \f$ {\bf q} = {\bf G+k} \f$. Using the expansion of the plane wave in terms of spherical Bessel
308 functions and real spherical harmonics:
309 \f[
310 e^{-i{\bf q}{\bf r}}=4\pi \sum_{\ell m} (-i)^\ell j_{\ell}(q r)R_{\ell m}({\bf \hat q})R_{\ell m}({\bf \hat r})
311 \f]
312 we arrive to the following expression:
313 \f[
314 \varphi^{\alpha}_{\ell m}({\bf q}) = e^{-i{\bf q}{\bf r}_{\alpha}} \frac{4\pi}{\sqrt{\Omega}} (-i)^\ell
315 R_{\ell m}({\bf q}) \int \varphi^{\alpha}_{\ell}(r) j_{\ell}(q r) r^2 dr
316 \f]
317
318 \note In the current implementation wave-functions are generated as scalars (without spin index). Spinor atomic
319 wave-functions might be necessary in future for the more advanced LDA+U implementation.
320
321 \param [in] atoms List of atoms, for which the wave-functions are generated.
322 \param [in] indexb Lambda function that returns index of the basis functions for each atom type.
323 \param [in] ri Radial integrals of the product of sperical Bessel functions and atomic functions.
324 \param [out] wf Resulting wave-functions for the list of atoms. Output wave-functions must have
325 sufficient storage space.
326 */
327 void generate_atomic_wave_functions(std::vector<int> atoms__,
328 std::function<basis_functions_index const*(int)> indexb__,
330 void generate_hubbard_orbitals();
331
332 /// Save data to HDF5 file.
333 void save(std::string const& name__, int id__) const;
334
335 void load(HDF5_tree h5in, int id);
336
337 //== void save_wave_functions(int id);
338
339 //== void load_wave_functions(int id);
340
341 /// Collect distributed first-variational vectors into a global array.
342 void get_fv_eigen_vectors(sddk::mdarray<std::complex<T>, 2>& fv_evec__) const;
343
344 /// Collect distributed second-variational vectors into a global array.
345 void get_sv_eigen_vectors(sddk::mdarray<std::complex<T>, 2>& sv_evec__) const
346 {
347 RTE_ASSERT((int)sv_evec__.size(0) == ctx_.num_spins() * ctx_.num_fv_states());
348 RTE_ASSERT((int)sv_evec__.size(1) == ctx_.num_spins() * ctx_.num_fv_states());
349
350 sv_evec__.zero();
351
352 if (!ctx_.need_sv()) {
353 for (int i = 0; i < ctx_.num_fv_states(); i++) {
354 sv_evec__(i, i) = 1;
355 }
356 return;
357 }
358
359 int nsp = (ctx_.num_mag_dims() == 3) ? 1 : ctx_.num_spins();
360
361 for (int ispn = 0; ispn < nsp; ispn++) {
362 int offs = ctx_.num_fv_states() * ispn;
363 for (int jloc = 0; jloc < sv_eigen_vectors_[ispn].num_cols_local(); jloc++) {
364 int j = sv_eigen_vectors_[ispn].icol(jloc);
365 for (int iloc = 0; iloc < sv_eigen_vectors_[ispn].num_rows_local(); iloc++) {
366 int i = sv_eigen_vectors_[ispn].irow(iloc);
367 sv_evec__(i + offs, j + offs) = sv_eigen_vectors_[ispn](iloc, jloc);
368 }
369 }
370 }
371
372 comm().allreduce(sv_evec__.at(sddk::memory_t::host), (int)sv_evec__.size());
373 }
374
375 inline auto const& gkvec() const
376 {
377 return *gkvec_;
378 }
379
380 /// Return shared pointer to gkvec object.
381 inline auto gkvec_sptr() const
382 {
383 return gkvec_;
384 }
385
386 /// Total number of G+k vectors within the cutoff distance
387 inline int num_gkvec() const
388 {
389 return gkvec_->num_gvec();
390 }
391
392 /// Local number of G+k vectors in case of flat distribution.
393 inline int num_gkvec_loc() const
394 {
395 return gkvec().count();
396 }
397
398 /// Get the number of occupied bands for each spin channel.
399 inline int num_occupied_bands(int ispn__ = -1) const
400 {
401 if (ctx_.num_mag_dims() == 3) {
402 ispn__ = 0;
403 }
404 for (int j = ctx_.num_bands() - 1; j >= 0; j--) {
405 if (std::abs(band_occupancy(j, ispn__)) > ctx_.min_occupancy() * ctx_.max_occupancy()) {
406 return j + 1;
407 }
408 }
409 return 0;
410 }
411
412 /// Get band energy.
413 inline double band_energy(int j__, int ispn__) const
414 {
415 return band_energies_(j__, get_ispn(ispn__));
416 }
417
418 /// Set band energy.
419 inline void band_energy(int j__, int ispn__, double e__)
420 {
421 band_energies_(j__, get_ispn(ispn__)) = e__;
422 }
423
424 inline auto band_energies(int ispn__) const
425 {
426 std::vector<double> result(ctx_.num_bands());
427 for (int j = 0; j < ctx_.num_bands(); j++) {
428 result[j] = this->band_energy(j, ispn__);
429 }
430 return result;
431 }
432
433 /// Get band occupancy.
434 inline double band_occupancy(int j__, int ispn__) const
435 {
436 return band_occupancies_(j__, get_ispn(ispn__));
437 }
438
439 /// Set band occupancy.
440 inline void band_occupancy(int j__, int ispn__, double occ__)
441 {
442 band_occupancies_(j__, get_ispn(ispn__)) = occ__;
443 }
444
445 inline double fv_eigen_value(int i) const
446 {
447 return fv_eigen_values_[i];
448 }
449
450 void set_fv_eigen_values(double* eval__)
451 {
452 std::copy(eval__, eval__ + ctx_.num_fv_states(), &fv_eigen_values_[0]);
453 }
454
455 /// Return weight of k-point.
456 inline double weight() const
457 {
458 return weight_;
459 }
460
461 inline auto& fv_states()
462 {
463 RTE_ASSERT(fv_states_ != nullptr);
464 return *fv_states_;
465 }
466
467 inline wf::Wave_functions<T> const& spinor_wave_functions() const
468 {
469 RTE_ASSERT(spinor_wave_functions_ != nullptr);
471 }
472
473 inline wf::Wave_functions<T>& spinor_wave_functions()
474 {
475 RTE_ASSERT(spinor_wave_functions_ != nullptr);
477 // return const_cast<wf::Wave_functions<T>&>(static_cast<K_point const&>(*this).spinor_wave_functions());;
478 }
479
480 inline auto& spinor_wave_functions2()
481 {
482 RTE_ASSERT(spinor_wave_functions_ != nullptr);
484 // return const_cast<wf::Wave_functions<T>&>(static_cast<K_point const&>(*this).spinor_wave_functions());;
485 }
486
487 /// Return the initial atomic orbitals used to compute the hubbard wave functions. The S operator is applied on
488 /// these functions.
489 inline auto const& atomic_wave_functions_S() const
490 {
491 /* the S operator is applied on these functions */
492 RTE_ASSERT(atomic_wave_functions_S_ != nullptr);
494 }
495
496 inline auto& atomic_wave_functions_S()
497 {
498 return const_cast<wf::Wave_functions<T>&>(static_cast<K_point const&>(*this).atomic_wave_functions_S());
499 }
500
501 /// Return the initial atomic orbitals used to compute the hubbard wave functions.
502 inline auto const& atomic_wave_functions() const
503 {
504 RTE_ASSERT(atomic_wave_functions_ != nullptr);
506 }
507
508 /// Return the initial atomic orbitals used to compute the hubbard wave functions.
510 {
511 return const_cast<wf::Wave_functions<T>&>(static_cast<K_point const&>(*this).atomic_wave_functions());
512 }
513
514 /// Return the actual hubbard wave functions used in the calculations.
515 /** The S operator is applied on these functions. */
516 inline auto const& hubbard_wave_functions_S() const
517 {
518 RTE_ASSERT(hubbard_wave_functions_S_ != nullptr);
520 }
521
522 inline auto& singular_components()
523 {
524 return *singular_components_;
525 }
526
527 inline auto vk() const
528 {
529 return vk_;
530 }
531
532 /// Basis size of LAPW+lo method.
533 /** The total LAPW+lo basis size is equal to the sum of the number of LAPW functions and the total number
534 * of the local orbitals. */
535 inline int gklo_basis_size() const
536 {
538 }
539
540 /// Local number of G+k vectors for each MPI rank in the row of the 2D MPI grid.
541 inline int num_gkvec_row() const
542 {
543 return num_gkvec_row_;
544 }
545
546 /// Local number of local orbitals for each MPI rank in the row of the 2D MPI grid.
547 inline int num_lo_row() const
548 {
549 return static_cast<int>(lo_basis_descriptors_row_.size());
550 }
551
552 /// Local number of basis functions for each MPI rank in the row of the 2D MPI grid.
553 inline int gklo_basis_size_row() const
554 {
555 return num_gkvec_row() + num_lo_row();
556 }
557
558 /// Local number of G+k vectors for each MPI rank in the column of the 2D MPI grid.
559 inline int num_gkvec_col() const
560 {
561 return num_gkvec_col_;
562 }
563
564 /// Local number of local orbitals for each MPI rank in the column of the 2D MPI grid.
565 inline int num_lo_col() const
566 {
567 return static_cast<int>(lo_basis_descriptors_col_.size());
568 }
569
570 /// Local number of basis functions for each MPI rank in the column of the 2D MPI grid.
571 inline int gklo_basis_size_col() const
572 {
573 return num_gkvec_col() + num_lo_col();
574 }
575
576 inline lo_basis_descriptor const& lo_basis_descriptor_col(int idx) const
577 {
578 RTE_ASSERT(idx >= 0 && idx < (int)lo_basis_descriptors_col_.size());
579 return lo_basis_descriptors_col_[idx];
580 }
581
582 inline lo_basis_descriptor const& lo_basis_descriptor_row(int idx) const
583 {
584 RTE_ASSERT(idx >= 0 && idx < (int)lo_basis_descriptors_row_.size());
585 return lo_basis_descriptors_row_[idx];
586 }
587
588 inline int num_ranks_row() const
589 {
590 return num_ranks_row_;
591 }
592
593 inline int rank_row() const
594 {
595 return rank_row_;
596 }
597
598 inline int num_ranks_col() const
599 {
600 return num_ranks_col_;
601 }
602
603 inline int rank_col() const
604 {
605 return rank_col_;
606 }
607
608 /// Number of MPI ranks for a given k-point
609 inline int num_ranks() const
610 {
611 return comm_.size();
612 }
613
614 inline int rank() const
615 {
616 return comm_.rank();
617 }
618
619 /// Return number of lo columns for a given atom
620 inline int num_atom_lo_cols(int ia) const
621 {
622 return (int)atom_lo_cols_[ia].size();
623 }
624
625 /// Return local index (for the current MPI rank) of a column for a given atom and column index within an atom
626 inline int lo_col(int ia, int i) const
627 {
628 return atom_lo_cols_[ia][i];
629 }
630
631 /// Return number of lo rows for a given atom
632 inline int num_atom_lo_rows(int ia) const
633 {
634 return (int)atom_lo_rows_[ia].size();
635 }
636
637 /// Return local index (for the current MPI rank) of a row for a given atom and row index within an atom
638 inline int lo_row(int ia, int i) const
639 {
640 return atom_lo_rows_[ia][i];
641 }
642
643 inline auto& fv_eigen_vectors()
644 {
645 return fv_eigen_vectors_;
646 }
647
648 inline auto& fv_eigen_vectors_slab()
649 {
651 }
652
653 inline auto& sv_eigen_vectors(int ispn)
654 {
655 return sv_eigen_vectors_[ispn];
656 }
657
658 inline auto& fd_eigen_vectors()
659 {
660 return fd_eigen_vectors_;
661 }
662
663 void bypass_sv()
664 {
666 }
667
668 inline auto const& alm_coeffs_row() const
669 {
670 return *alm_coeffs_row_;
671 }
672
673 inline auto const& alm_coeffs_col() const
674 {
675 return *alm_coeffs_col_;
676 }
677
678 inline auto const& alm_coeffs_loc() const
679 {
680 return *alm_coeffs_loc_;
681 }
682
683 inline auto const& comm() const
684 {
685 return comm_;
686 }
687
688 inline auto const& comm_row() const
689 {
690 return comm_row_;
691 }
692
693 inline auto const& comm_col() const
694 {
695 return comm_col_;
696 }
697
698 auto beta_projectors() -> Beta_projectors<T>&
699 {
700 RTE_ASSERT(beta_projectors_ != nullptr);
701 return *beta_projectors_;
702 }
703
704 auto beta_projectors() const -> const Beta_projectors<T>&
705 {
706 RTE_ASSERT(beta_projectors_ != nullptr);
707 return *beta_projectors_;
708 }
709
710 auto& beta_projectors_row()
711 {
712 RTE_ASSERT(beta_projectors_ != nullptr);
713 return *beta_projectors_row_;
714 }
715
716 auto& beta_projectors_col()
717 {
718 RTE_ASSERT(beta_projectors_ != nullptr);
719 return *beta_projectors_col_;
720 }
721
722 auto const& ctx() const
723 {
724 return ctx_;
725 }
726
727 /// Return stdout stream for high verbosity output.
728 /** This output will not be passed to a ctx_.out() stream. */
729 std::ostream& out(int level__) const
730 {
731 if (ctx_.verbosity() >= level__ && this->comm().rank() == 0) {
732 return std::cout;
733 } else {
734 return null_stream();
735 }
736 }
737
738 auto& spfft_transform() const
739 {
740 return *spfft_transform_;
741 }
742
743 inline auto const& gkvec_fft() const
744 {
745 return *gkvec_partition_;
746 }
747
748 inline auto gkvec_fft_sptr() const
749 {
750 return gkvec_partition_;
751 }
752
753 inline auto const& gkvec_col() const
754 {
755 return *gkvec_col_;
756 }
757
758 inline auto const& gkvec_row() const
759 {
760 return *gkvec_row_;
761 }
762};
763
764template <typename T>
765inline auto
766wave_function_factory(Simulation_context const& ctx__, K_point<T> const& kp__, wf::num_bands num_wf__,
767 wf::num_mag_dims num_md__, bool mt_part__)
768{
769 using wf_t = wf::Wave_functions<T>;
770 std::unique_ptr<wf_t> wf{nullptr};
771 if (mt_part__) {
772 std::vector<int> num_mt_coeffs(ctx__.unit_cell().num_atoms());
773 for (int ia = 0; ia < ctx__.unit_cell().num_atoms(); ia++) {
774 num_mt_coeffs[ia] = ctx__.unit_cell().atom(ia).mt_lo_basis_size();
775 }
776 wf = std::make_unique<wf_t>(kp__.gkvec_sptr(), num_mt_coeffs, num_md__, num_wf__, ctx__.host_memory_t());
777 } else {
778 wf = std::make_unique<wf_t>(kp__.gkvec_sptr(), num_md__, num_wf__, ctx__.host_memory_t());
779 }
780
781 return wf;
782}
783
784} // namespace sirius
785
786/** \page basis Basis functions for Kohn-Sham wave-functions expansion
787 *
788 * \section basis1 LAPW+lo basis
789 *
790 * LAPW+lo basis consists of two different sets of functions: LAPW functions \f$ \varphi_{{\bf G+k}} \f$ defined over
791 * entire unit cell:
792 * \f[
793 * \varphi_{{\bf G+k}}({\bf r}) = \left\{ \begin{array}{ll}
794 * \displaystyle \sum_{L} \sum_{\nu=1}^{O_{\ell}^{\alpha}} a_{L\nu}^{\alpha}({\bf G+k})u_{\ell \nu}^{\alpha}(r)
795 * Y_{\ell m}(\hat {\bf r}) & {\bf r} \in {\rm MT} \alpha \\
796 * \displaystyle \frac{1}{\sqrt \Omega} e^{i({\bf G+k}){\bf r}} & {\bf r} \in {\rm I} \end{array} \right.
797 * \f]
798 * and Bloch sums of local orbitals defined inside muffin-tin spheres only:
799 * \f[
800 * \begin{array}{ll} \displaystyle \varphi_{j{\bf k}}({\bf r})=\sum_{{\bf T}} e^{i{\bf kT}}
801 * \varphi_{j}({\bf r - T}) & {\rm {\bf r} \in MT} \end{array}
802 * \f]
803 * Each local orbital is composed of radial and angular parts:
804 * \f[
805 * \varphi_{j}({\bf r}) = \phi_{\ell_j}^{\zeta_j,\alpha_j}(r) Y_{\ell_j m_j}(\hat {\bf r})
806 * \f]
807 * Radial part of local orbital is defined as a linear combination of radial functions (minimum two radial functions
808 * are required) such that local orbital vanishes at the sphere boundary:
809 * \f[
810 * \phi_{\ell}^{\zeta, \alpha}(r) = \sum_{p}\gamma_{p}^{\zeta,\alpha} u_{\ell \nu_p}^{\alpha}(r)
811 * \f]
812 *
813 * Arbitrary number of local orbitals can be introduced for each angular quantum number (this is highlighted by
814 * the index \f$ \zeta \f$).
815 *
816 * Radial functions are m-th order (with zero-order being a function itself) energy derivatives of the radial
817 * Schrödinger equation:
818 * \f[
819 * u_{\ell \nu}^{\alpha}(r) = \frac{\partial^{m_{\nu}}}{\partial^{m_{\nu}}E}u_{\ell}^{\alpha}(r,E)\Big|_{E=E_{\nu}}
820 * \f]
821 */
822
823/** \page data_dist K-point data distribution
824 *
825 * \section data_dist1 "Panel" and "full" data storage
826 *
827 * We have to deal with big arrays (matching coefficients, eigen vectors, wave functions, etc.) which may not fit
828 * into the memory of a single node. For some operations we need a "panel" distribution of data, where each
829 * MPI rank gets a local panel of block-cyclic distributed matrix. This way of storing data is necessary for the
830 * distributed PBLAS and ScaLAPACK operations.
831 *
832 */
833
834#endif // __K_POINT_H__
Contains declaration and implementation of sirius::Beta_projectors class.
Interface to the HDF5 library.
Definition: hdf5_tree.hpp:86
K-point related variables and methods.
Definition: k_point.hpp:44
sddk::mdarray< double, 1 > fv_eigen_values_
First-variational eigen values.
Definition: k_point.hpp:75
std::unique_ptr< Matching_coefficients > alm_coeffs_col_
LAPW matching coefficients for the column G+k vectors.
Definition: k_point.hpp:125
auto const & atomic_wave_functions() const
Return the initial atomic orbitals used to compute the hubbard wave functions.
Definition: k_point.hpp:502
std::vector< lo_basis_descriptor > lo_basis_descriptors_row_
Basis descriptors distributed between rows of the 2D MPI grid.
Definition: k_point.hpp:138
std::vector< std::complex< double > > zil_
Imaginary unit to the power of l.
Definition: k_point.hpp:151
void generate_atomic_wave_functions(std::vector< int > atoms__, std::function< basis_functions_index const *(int)> indexb__, Radial_integrals_atomic_wf< false > const &ri__, wf::Wave_functions< T > &wf__)
Generate plane-wave coefficients of the atomic wave-functions.
Definition: k_point.cpp:678
std::unique_ptr< wf::Wave_functions< T > > atomic_wave_functions_S_
Pseudopotential atmoic wave-functions (not orthogonalized) with S-operator applied.
Definition: k_point.hpp:105
auto gkvec_sptr() const
Return shared pointer to gkvec object.
Definition: k_point.hpp:381
la::dmatrix< std::complex< T > > fv_eigen_vectors_
First-variational eigen vectors, distributed over 2D BLACS grid.
Definition: k_point.hpp:78
double band_occupancy(int j__, int ispn__) const
Get band occupancy.
Definition: k_point.hpp:434
std::vector< std::vector< int > > atom_lo_cols_
List of columns of the Hamiltonian and overlap matrix lo block (local index) for a given atom.
Definition: k_point.hpp:145
int num_atom_lo_cols(int ia) const
Return number of lo columns for a given atom.
Definition: k_point.hpp:620
int num_atom_lo_rows(int ia) const
Return number of lo rows for a given atom.
Definition: k_point.hpp:632
std::unique_ptr< wf::Wave_functions< T > > fv_eigen_vectors_slab_
First-variational eigen vectors, distributed in slabs.
Definition: k_point.hpp:81
std::unique_ptr< Beta_projectors< T > > beta_projectors_
Beta projectors for a local set of G+k vectors.
Definition: k_point.hpp:169
int num_lo_row() const
Local number of local orbitals for each MPI rank in the row of the 2D MPI grid.
Definition: k_point.hpp:547
void band_occupancy(int j__, int ispn__, double occ__)
Set band occupancy.
Definition: k_point.hpp:440
void generate_spinor_wave_functions()
Generate two-component spinor wave functions.
void update()
Update the reciprocal lattice vectors of the G+k array.
Definition: k_point.cpp:393
void generate_gkvec(double gk_cutoff__)
Find G+k vectors within the cutoff.
Definition: k_point.cpp:340
std::unique_ptr< Matching_coefficients > alm_coeffs_loc_
LAPW matching coefficients for the local set G+k vectors.
Definition: k_point.hpp:128
Simulation_context & ctx_
Simulation context.
Definition: k_point.hpp:47
std::unique_ptr< wf::Wave_functions< T > > hubbard_wave_functions_
Hubbard wave functions.
Definition: k_point.hpp:108
mpi::Communicator const & comm_col_
Communicator between(!!) columns.
Definition: k_point.hpp:183
sddk::mdarray< std::complex< T >, 2 > fd_eigen_vectors_
Full-diagonalization eigen vectors.
Definition: k_point.hpp:93
mpi::Communicator const & comm_
Communicator for parallelization inside k-point.
Definition: k_point.hpp:60
std::unique_ptr< wf::Wave_functions< T > > singular_components_
Lowest eigen-vectors of the LAPW overlap matrix with small aigen-values.
Definition: k_point.hpp:84
auto const & atomic_wave_functions_S() const
Definition: k_point.hpp:489
int rank_row_
Row rank of the processors of ScaLAPACK/ELPA diagonalization grid.
Definition: k_point.hpp:163
std::unique_ptr< Beta_projectors< T > > beta_projectors_col_
Beta projectors for column G+k vectors.
Definition: k_point.hpp:177
std::ostream & out(int level__) const
Return stdout stream for high verbosity output.
Definition: k_point.hpp:729
void get_fv_eigen_vectors(sddk::mdarray< std::complex< T >, 2 > &fv_evec__) const
Collect distributed first-variational vectors into a global array.
Definition: k_point.cpp:425
int lo_col(int ia, int i) const
Return local index (for the current MPI rank) of a column for a given atom and column index within an...
Definition: k_point.hpp:626
Unit_cell const & unit_cell_
Unit cell object.
Definition: k_point.hpp:50
std::unique_ptr< Matching_coefficients > alm_coeffs_row_
LAPW matching coefficients for the row G+k vectors.
Definition: k_point.hpp:121
auto & atomic_wave_functions()
Return the initial atomic orbitals used to compute the hubbard wave functions.
Definition: k_point.hpp:509
std::vector< lo_basis_descriptor > lo_basis_descriptors_col_
Basis descriptors distributed between columns of the 2D MPI grid.
Definition: k_point.hpp:142
double band_energy(int j__, int ispn__) const
Get band energy.
Definition: k_point.hpp:413
double weight() const
Return weight of k-point.
Definition: k_point.hpp:456
int gklo_basis_size_row() const
Local number of basis functions for each MPI rank in the row of the 2D MPI grid.
Definition: k_point.hpp:553
mpi::Communicator const & comm_row_
Communicator between(!!) rows.
Definition: k_point.hpp:180
void initialize()
Initialize the k-point related arrays and data.
Definition: k_point.cpp:33
std::array< la::dmatrix< std::complex< T > >, 2 > sv_eigen_vectors_
Second-variational eigen vectors.
Definition: k_point.hpp:90
int num_lo_col() const
Local number of local orbitals for each MPI rank in the column of the 2D MPI grid.
Definition: k_point.hpp:565
r3::vector< double > vk_
Fractional k-point coordinates.
Definition: k_point.hpp:53
int num_gkvec() const
Total number of G+k vectors within the cutoff distance.
Definition: k_point.hpp:387
int num_gkvec_row() const
Local number of G+k vectors for each MPI rank in the row of the 2D MPI grid.
Definition: k_point.hpp:541
void generate_gklo_basis()
Generate G+k and local orbital basis sets.
Definition: k_point.cpp:763
int num_gkvec_col() const
Local number of G+k vectors for each MPI rank in the column of the 2D MPI grid.
Definition: k_point.hpp:559
void generate_fv_states()
Generate first-variational states from eigen-vectors.
int num_gkvec_row_
Number of G+k vectors distributed along rows of MPI grid.
Definition: k_point.hpp:131
void get_sv_eigen_vectors(sddk::mdarray< std::complex< T >, 2 > &sv_evec__) const
Collect distributed second-variational vectors into a global array.
Definition: k_point.hpp:345
int num_ranks_col_
Number of processors along the columns of the diagonalization grid.
Definition: k_point.hpp:160
std::vector< std::vector< int > > atom_lo_rows_
list of rows of the Hamiltonian and overlap matrix lo block (local index) for a given atom
Definition: k_point.hpp:148
int gklo_basis_size() const
Basis size of LAPW+lo method.
Definition: k_point.hpp:535
int gklo_basis_size_col() const
Local number of basis functions for each MPI rank in the column of the 2D MPI grid.
Definition: k_point.hpp:571
std::unique_ptr< wf::Wave_functions< T > > fv_states_
First-variational states.
Definition: k_point.hpp:96
auto const & hubbard_wave_functions_S() const
Return the actual hubbard wave functions used in the calculations.
Definition: k_point.hpp:516
int num_occupied_bands(int ispn__=-1) const
Get the number of occupied bands for each spin channel.
Definition: k_point.hpp:399
std::shared_ptr< fft::Gvec > gkvec_
List of G-vectors with |G+k| < cutoff.
Definition: k_point.hpp:63
std::unique_ptr< Beta_projectors< T > > beta_projectors_row_
Beta projectors for row G+k vectors.
Definition: k_point.hpp:173
std::unique_ptr< wf::Wave_functions< T > > atomic_wave_functions_
Pseudopotential atmoic wave-functions (not orthogonalized).
Definition: k_point.hpp:102
std::unique_ptr< wf::Wave_functions< T > > spinor_wave_functions_
Two-component (spinor) wave functions describing the bands.
Definition: k_point.hpp:99
int num_gkvec_col_
Number of G+k vectors distributed along columns of MPI grid.
Definition: k_point.hpp:134
sddk::mdarray< double, 2 > band_energies_
Band energies.
Definition: k_point.hpp:117
std::unique_ptr< wf::Wave_functions< T > > hubbard_wave_functions_S_
Hubbard wave functions with S-operator applied.
Definition: k_point.hpp:111
sddk::mdarray< double, 2 > band_occupancies_
Band occupation numbers.
Definition: k_point.hpp:114
void save(std::string const &name__, int id__) const
Save data to HDF5 file.
Definition: k_point.cpp:539
int rank_col_
Column rank of the processors of ScaLAPACK/ELPA diagonalization grid.
Definition: k_point.hpp:157
int lo_row(int ia, int i) const
Return local index (for the current MPI rank) of a row for a given atom and row index within an atom.
Definition: k_point.hpp:638
K_point(Simulation_context &ctx__, std::shared_ptr< fft::Gvec > gkvec__, double weight__)
Constructor.
Definition: k_point.hpp:238
void band_energy(int j__, int ispn__, double e__)
Set band energy.
Definition: k_point.hpp:419
int num_gkvec_loc() const
Local number of G+k vectors in case of flat distribution.
Definition: k_point.hpp:393
K_point(Simulation_context &ctx__, r3::vector< double > vk__, double weight__)
Constructor.
Definition: k_point.hpp:219
int num_ranks_row_
Number of processors along the rows of the diagonalization grid.
Definition: k_point.hpp:166
std::vector< int > l_by_lm_
Mapping between lm and l.
Definition: k_point.hpp:154
int num_ranks() const
Number of MPI ranks for a given k-point.
Definition: k_point.hpp:609
std::shared_ptr< fft::Gvec_fft > gkvec_partition_
G-vector distribution for the FFT transformation.
Definition: k_point.hpp:70
double weight_
Weight of k-point.
Definition: k_point.hpp:56
Radial integrals of the atomic centered orbitals.
Simulation context is a set of parameters and objects describing a single simulation.
int num_spins() const
Number of spin components.
bool gamma_point(bool gamma_point__)
Set flag for Gamma-point calculation.
int num_fv_states(int num_fv_states__)
Set the number of first-variational states.
int num_spinors() const
Number of spinor wave-functions labeled by a sinlge band index.
int max_occupancy() const
Maximum band occupancy.
int num_bands(int num_bands__)
Set the number of bands.
int num_mag_dims() const
Number of dimensions in the magnetization vector.
double gk_cutoff() const
Cutoff for G+k vectors (in 1/[a.u.]).
double min_occupancy() const
Minimum occupancy to consider band to be occupied.
Representation of a unit cell.
Definition: unit_cell.hpp:43
int mt_lo_basis_size() const
Total number of local orbital basis functions over all atoms.
Definition: unit_cell.hpp:419
A helper class to establish various index mappings for the atomic basis functions.
Distributed matrix.
Definition: dmatrix.hpp:56
MPI communicator wrapper.
int size() const
Size of the communicator (number of ranks).
int rank() const
Rank of MPI process inside communicator.
void zero(memory_t mem__, size_t idx0__, size_t n__)
Zero n elements starting from idx0.
Definition: memory.hpp:1316
Wave-functions representation.
Contains helper functions for the interface with SpFFT library.
Contains definition and partial implementation of sirius::Matching_coefficients class.
void copy(T *target__, T const *source__, size_t n__)
Copy memory inside a device.
Definition: acc.hpp:320
Namespace of the SIRIUS library.
Definition: sirius.f90:5
Contains definition and implementation of sirius::radial_functions_index class.
Descriptor of the local-orbital part of the LAPW+lo basis.
Definition: typedefs.hpp:186
Contains declaration and implementation of Wave_functions class.