SIRIUS 7.5.0
Electronic structure library and applications
hamiltonian.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2018 Anton Kozhevnikov, Mathieu Taillefumier, 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 hamiltonian.hpp
21 *
22 * \brief Contains declaration and definition of sirius::Hamiltonian class.
23 */
24
25#ifndef __HAMILTONIAN_HPP__
26#define __HAMILTONIAN_HPP__
27
28#include <memory>
29#include <complex>
30#include "SDDK/memory.hpp"
32#include "core/typedefs.hpp"
33#include "core/fft/fft.hpp"
34#include "core/la/dmatrix.hpp"
35#include "local_operator.hpp"
37
38namespace sirius {
39/* forward declaration */
40class Atom;
41class Simulation_context;
42class Potential;
43class Unit_cell;
44template <typename T>
45class Local_operator;
46template <typename T>
47class D_operator;
48template <typename T>
49class Q_operator;
50template <typename T>
51class U_operator;
52template <typename T>
53class K_point;
54template <typename T>
55class Gaunt_coefficients;
56
57/// Representation of Kohn-Sham Hamiltonian.
58/** In general, Hamiltonian consists of kinetic term, local part of potential and non-local
59 part of potential:
60 \f[
61 H = -\frac{1}{2} \nabla^2 + V_{loc}({\bf r}) + \sum_{\alpha} \sum_{\xi \xi'} |\beta_{\xi}^{\alpha} \rangle
62 D_{\xi \xi'}^{\alpha} \langle \beta_{\xi'}^{\alpha}|
63 \f]
64*/
65
66/* forward declaration */
67template <typename T>
68class Hamiltonian_k;
69
70/// Represent the k-point independent part of Hamiltonian.
71/** \tparam T Precision of the wave-functions (float or double).
72 */
73template <typename T> // type is real type precision
75{
76 private:
77 /// Simulation context.
79
80 /// Alias for the potential.
82
83 /// Alias for unit cell.
85
86 /// Local part of the Hamiltonian operator.
87 std::unique_ptr<Local_operator<T>> local_op_;
88
89 /// D operator (non-local part of Hamiltonian).
90 std::unique_ptr<D_operator<T>> d_op_;
91
92 /// Q operator (non-local part of S-operator).
93 std::unique_ptr<Q_operator<T>> q_op_;
94
95 std::vector<sddk::mdarray<std::complex<T>, 2>> hmt_;
96
97 /* copy constructor is forbidden */
98 Hamiltonian0(Hamiltonian0<T> const& src) = delete;
99 /* copy assignment operator is forbidden */
100 Hamiltonian0<T>& operator=(Hamiltonian0<T> const& src) = delete;
101
102 public:
103 /// Constructor.
104 Hamiltonian0(Potential& potential__, bool precompute_lapw__);
105
107
108 /// Default move constructor.
110
111 /// Return a Hamiltonian for the given k-point.
113
114 Simulation_context& ctx() const
115 {
116 return ctx_;
117 }
118
119 Potential& potential() const
120 {
121 return *potential_;
122 }
123
124 Local_operator<T>& local_op() const
125 {
126 return *local_op_;
127 }
128
129 inline Q_operator<T>& Q() const
130 {
131 return *q_op_;
132 }
133
134 inline D_operator<T>& D() const
135 {
136 return *d_op_;
137 }
138
139 auto const& hmt(int ia__) const
140 {
141 return hmt_[ia__];
142 }
143
144 /// Apply the muffin-tin part of the Hamiltonian to the apw basis functions of an atom.
145 /** The following matrix is computed:
146 * \f[
147 * b_{L_2 \nu_2}^{\alpha}({\bf G'}) = \sum_{L_1 \nu_1} \sum_{L_3}
148 * a_{L_1\nu_1}^{\alpha}({\bf G'})
149 * \langle u_{\ell_1\nu_1}^{\alpha} | h_{L3}^{\alpha} | u_{\ell_2\nu_2}^{\alpha}
150 * \rangle \langle Y_{L_1} | R_{L_3} | Y_{L_2} \rangle
151 * \f]
152 */
153 template <spin_block_t sblock>
154 void apply_hmt_to_apw(Atom const& atom__, int ngv__, sddk::mdarray<std::complex<T>, 2>& alm__,
155 sddk::mdarray<std::complex<T>, 2>& halm__) const;
156
157 /// Add correction to LAPW overlap arising in the infinite-order relativistic approximation (IORA).
158 void add_o1mt_to_apw(Atom const& atom__, int num_gkvec__,
159 sddk::mdarray<std::complex<T>, 2>& alm__) const; // TODO: documentation
160
161 /// Apply muffin-tin part of magnetic filed to the wave-functions.
162 void apply_bmt(wf::Wave_functions<T>& psi__, std::vector<wf::Wave_functions<T>>& bpsi__) const;
163
164 /// Apply SO correction to the first-variational LAPW wave-functions.
165 /** Raising and lowering operators:
166 * \f[
167 * L_{\pm} Y_{\ell m}= (L_x \pm i L_y) Y_{\ell m} = \sqrt{\ell(\ell+1) - m(m \pm 1)} Y_{\ell m \pm 1}
168 * \f]
169 */
170 void apply_so_correction(wf::Wave_functions<T>& psi__, std::vector<wf::Wave_functions<T>>& hpsi__) const;
171};
172
173template <typename T>
175{
176 private:
177 /// K-point independent part of Hamiltonian.
179 K_point<T>& kp_;
180 /// Hubbard correction.
181 /** In general case it is a k-dependent matrix */
182 std::shared_ptr<U_operator<T>> u_op_;
183
184 /// Copy constructor is forbidden.
185 Hamiltonian_k(Hamiltonian_k<T> const& src__) = delete;
186
187 /// Assignment operator is forbidden.
189
190 public:
191 Hamiltonian_k(Hamiltonian0<T> const& H0__, K_point<T>& kp__);
192
194
196
197 Hamiltonian0<T> const& H0() const
198 {
199 return H0_;
200 }
201
202 template <typename F, int what>
203 std::pair<sddk::mdarray<T, 2>, sddk::mdarray<T, 2>> get_h_o_diag_pw() const;
204
205 template <int what>
206 std::pair<sddk::mdarray<T, 2>, sddk::mdarray<T, 2>> get_h_o_diag_lapw() const;
207
208 auto U() const -> U_operator<T> const&
209 {
210 return *u_op_;
211 }
212
213 /// Apply first-variational LAPW Hamiltonian and overlap matrices.
214 /** Check the documentation of Hamiltonain::set_fv_h_o() for the expressions of Hamiltonian and overlap
215 * matrices and \ref basis for the definition of the LAPW+lo basis.
216 *
217 * For the set of wave-functions expanded in LAPW+lo basis (k-point index is dropped for simplicity)
218 * \f[
219 * \psi_{i} = \sum_{\mu} \phi_{\mu} C_{\mu i}
220 * \f]
221 * where \f$ \mu = \{ {\bf G}, j \} \f$ is a combined index of LAPW and local orbitals we want to contrusct
222 * a subspace Hamiltonian and overlap matrices:
223 * \f[
224 * H_{i' i} = \langle \psi_{i'} | \hat H | \psi_i \rangle =
225 * \sum_{\mu' \mu} C_{\mu' i'}^{*} \langle \phi_{\mu'} | \hat H | \phi_{\mu} \rangle C_{\mu i} =
226 * \sum_{\mu'} C_{\mu' i'}^{*} h_{\mu' i}(\psi)
227 * \f]
228 * \f[
229 * O_{i' i} = \langle \psi_{i'} | \psi_i \rangle =
230 * \sum_{\mu' \mu} C_{\mu' i'}^{*} \langle \phi_{\mu'} | \phi_{\mu} \rangle C_{\mu i} =
231 * \sum_{\mu'} C_{\mu' i'}^{*} o_{\mu' i}(\psi)
232 * \f]
233 * where
234 * \f[
235 * h_{\mu' i}(\psi) = \sum_{\mu} \langle \phi_{\mu'} | \hat H | \phi_{\mu} \rangle C_{\mu i}
236 * \f]
237 * and
238 * \f[
239 * o_{\mu' i}(\psi) = \sum_{\mu} \langle \phi_{\mu'} | \phi_{\mu} \rangle C_{\mu i}
240 * \f]
241 * For the APW block of \f$ h_{\mu' i}(\psi) \f$ and \f$ o_{\mu' i}(\psi) \f$ we have:
242 * \f[
243 * h_{{\bf G'} i}(\psi) = \sum_{{\bf G}} \langle \phi_{\bf G'} | \hat H | \phi_{\bf G} \rangle C_{{\bf G} i} +
244 * \sum_{j} \langle \phi_{\bf G'} | \hat H | \phi_{j} \rangle C_{j i}
245 * \f]
246 * \f[
247 * o_{{\bf G'} i}(\psi) = \sum_{{\bf G}} \langle \phi_{\bf G'} | \phi_{\bf G} \rangle C_{{\bf G} i} +
248 * \sum_{j} \langle \phi_{\bf G'} | \phi_{j} \rangle C_{j i}
249 * \f]
250 * and for the lo block:
251 * \f[
252 * h_{j' i}(\psi) = \sum_{{\bf G}} \langle \phi_{j'} | \hat H | \phi_{\bf G} \rangle C_{{\bf G} i} +
253 * \sum_{j} \langle \phi_{j'} | \hat H | \phi_{j} \rangle C_{j i}
254 * \f]
255 * \f[
256 * o_{j' i}(\psi) = \sum_{{\bf G}} \langle \phi_{j'} | \phi_{\bf G} \rangle C_{{\bf G} i} +
257 * \sum_{j} \langle \phi_{j'} | \phi_{j} \rangle C_{j i}
258 * \f]
259 *
260 * APW-APW contribution, muffin-tin part:
261 * \f[
262 * h_{{\bf G'} i}(\psi) = \sum_{{\bf G}} \langle \phi_{\bf G'} | \hat H | \phi_{\bf G} \rangle C_{{\bf G} i} =
263 * \sum_{{\bf G}} \sum_{\alpha} \sum_{\xi'} a_{\xi'}^{\alpha *}({\bf G'}) b_{\xi'}^{\alpha}({\bf G})
264 * C_{{\bf G} i}
265 * \f]
266 * \f[
267 * o_{{\bf G'} i}(\psi) = \sum_{{\bf G}} \langle \phi_{\bf G'} | \phi_{\bf G} \rangle C_{{\bf G} i} =
268 * \sum_{{\bf G}} \sum_{\alpha} \sum_{\xi'} a_{\xi'}^{\alpha *}({\bf G'}) a_{\xi'}^{\alpha}({\bf G})
269 * C_{{\bf G} i}
270 * \f]
271 * APW-APW contribution, interstitial effective potential part:
272 * \f[
273 * h_{{\bf G'} i}(\psi) = \int \Theta({\bf r}) e^{-i{\bf G'}{\bf r}} V({\bf r}) \psi_{i}({\bf r}) d{\bf r}
274 * \f]
275 * This is done by transforming \f$ \psi_i({\bf G}) \f$ to the real space, multiplying by effectvive potential
276 * and step function and transforming the result back to the \f$ {\bf G} \f$ domain.
277 *
278 * APW-APW contribution, interstitial kinetic energy part:
279 * \f[
280 * h_{{\bf G'} i}(\psi) = \int \Theta({\bf r}) e^{-i{\bf G'}{\bf r}} \Big( -\frac{1}{2} \nabla \Big)
281 * \Big( \nabla \psi_{i}({\bf r}) \Big) d{\bf r}
282 * \f]
283 * and the gradient of the wave-function is computed with FFT as:
284 * \f[
285 * \Big( \nabla \psi_{i}({\bf r}) \Big) = \sum_{\bf G} i{\bf G}e^{i{\bf G}{\bf r}}\psi_i({\bf G})
286 * \f]
287 *
288 * APW-APW contribution, interstitial overlap:
289 * \f[
290 * o_{{\bf G'} i}(\psi) = \int \Theta({\bf r}) e^{-i{\bf G'}{\bf r}} \psi_{i}({\bf r}) d{\bf r}
291 * \f]
292 *
293 * APW-lo contribution:
294 * \f[
295 * h_{{\bf G'} i}(\psi) = \sum_{j} \langle \phi_{\bf G'} | \hat H | \phi_{j} \rangle C_{j i} =
296 * \sum_{j} C_{j i} \sum_{L'\nu'} a_{L'\nu'}^{\alpha_j *}({\bf G'})
297 * \langle u_{\ell' \nu'}^{\alpha_j}Y_{\ell' m'}|\hat h^{\alpha_j} | \phi_{\ell_j}^{\zeta_j \alpha_j}
298 * Y_{\ell_j m_j} \rangle =
299 * \sum_{j} C_{j i} \sum_{\xi'} a_{\xi'}^{\alpha_j *}({\bf G'}) h_{\xi' \xi_j}^{\alpha_j}
300 * \f]
301 * \f[
302 * o_{{\bf G'} i}(\psi) = \sum_{j} \langle \phi_{\bf G'} | \phi_{j} \rangle C_{j i} =
303 * \sum_{j} C_{j i} \sum_{L'\nu'} a_{L'\nu'}^{\alpha_j *}({\bf G'})
304 * \langle u_{\ell' \nu'}^{\alpha_j}Y_{\ell' m'}| \phi_{\ell_j}^{\zeta_j \alpha_j} Y_{\ell_j m_j} \rangle
305 * =
306 * \sum_{j} C_{j i} \sum_{\nu'} a_{\ell_j m_j \nu'}^{\alpha_j *}({\bf G'}) o_{\nu' \zeta_j \ell_j}^{\alpha_j}
307 * \f]
308 * lo-APW contribution:
309 * \f[
310 * h_{j' i}(\psi) = \sum_{\bf G} \langle \phi_{j'} | \hat H | \phi_{\bf G} \rangle C_{{\bf G} i} =
311 * \sum_{\bf G} C_{{\bf G} i} \sum_{L\nu} \langle \phi_{\ell_{j'}}^{\zeta_{j'} \alpha_{j'}} Y_{\ell_{j'}
312 * m_{j'}}
313 * |\hat h^{\alpha_{j'}} | u_{\ell \nu}^{\alpha_{j'}}Y_{\ell m} \rangle a_{L\nu}^{\alpha_{j'}}({\bf G}) =
314 * \sum_{\bf G} C_{{\bf G} i} \sum_{\xi} h_{\xi_{j'} \xi}^{\alpha_{j'}} a_{\xi}^{\alpha_{j'}}({\bf G})
315 * \f]
316 * \f[
317 * o_{j' i}(\psi) = \sum_{\bf G} \langle \phi_{j'} | \phi_{\bf G} \rangle C_{{\bf G} i} =
318 * \sum_{\bf G} C_{{\bf G} i} \sum_{L\nu} \langle \phi_{\ell_{j'}}^{\zeta_{j'} \alpha_{j'}} Y_{\ell_{j'}
319 * m_{j'}}
320 * | u_{\ell \nu}^{\alpha_{j'}}Y_{\ell m} \rangle a_{L\nu}^{\alpha_{j'}}({\bf G}) =
321 * \sum_{\bf G} C_{{\bf G} i} \sum_{\nu} o_{\zeta_{j'} \nu \ell_{j'}}^{\alpha_{j'}} a_{\ell_{j'} m_{j'}
322 * \nu}^{\alpha_{j'}}({\bf G})
323 * \f]
324 * lo-lo contribution:
325 * \f[
326 * h_{j' i}(\psi) = \sum_{j} \langle \phi_{j'} | \hat H | \phi_{j} \rangle C_{j i} = \sum_{j} C_{j i}
327 * h_{\xi_{j'} \xi_j}^{\alpha_j}
328 * \delta_{\alpha_j \alpha_{j'}}
329 * \f]
330 * \f[
331 * o_{j' i}(\psi) = \sum_{j} \langle \phi_{j'} | \phi_{j} \rangle C_{j i} = \sum_{j} C_{j i}
332 * o_{\zeta_{j'} \zeta_{j} \ell_j}^{\alpha_j}
333 * \delta_{\alpha_j \alpha_{j'}} \delta_{\ell_j \ell_{j'}} \delta_{m_j m_{j'}}
334 * \f]
335 *
336 * \param [in] apw_only True if only APW-APW block of H and O are applied.
337 * \param [in] phi_is_lo True if input wave-functions are pure local orbitals.
338 * \param [in] b Range of bands.
339 * \param [in] phi Input wave-functions.
340 * \param [out] hphi Result of Hamiltonian, applied to wave-functions.
341 * \param [out] ophi Result of overlap operator, applied to wave-functions.
342 */
343 void apply_fv_h_o(bool apw_only__, bool phi_is_lo__, wf::band_range b__, wf::Wave_functions<T>& phi__,
344 wf::Wave_functions<T>* hphi__, wf::Wave_functions<T>* ophi__) const;
345
346 /// Setup the Hamiltonian and overlap matrices in APW+lo basis
347 /** The Hamiltonian matrix has the following expression:
348 * \f[
349 * H_{\mu' \mu}=\langle \varphi_{\mu' } | \hat H | \varphi_{\mu } \rangle =
350 * \left( \begin{array}{cc}
351 * H_{\bf G'G} & H_{{\bf G'}j} \\
352 * H_{j'{\bf G}} & H_{j'j}
353 * \end{array} \right)
354 * \f]
355 * APW-APW block:
356 * \f{eqnarray*}{
357 * H_{{\bf G'} {\bf G}}^{\bf k} &=& \sum_{\alpha} \sum_{L'\nu', L\nu} a_{L'\nu'}^{\alpha *}({\bf G'+k})
358 * \langle u_{\ell' \nu'}^{\alpha}Y_{\ell' m'}|\hat h^{\alpha} | u_{\ell \nu}^{\alpha}Y_{\ell m} \rangle
359 * a_{L\nu}^{\alpha}({\bf G+k}) + \frac{1}{2}{\bf G'} {\bf G} \cdot \Theta({\bf G - G'}) + \tilde V_{eff}({\bf
360 * G - G'}) \\
361 * &=& \sum_{\alpha} \sum_{\xi' } a_{\xi'}^{\alpha *}({\bf G'+k})
362 * b_{\xi'}^{\alpha}({\bf G+k}) + \frac{1}{2}{\bf G'} {\bf G} \cdot \Theta({\bf G - G'}) + \tilde
363 * V_{eff}({\bf G - G'})
364 * \f}
365 * APW-lo block:
366 * \f[
367 * H_{{\bf G'} j}^{\bf k} = \sum_{L'\nu'} a_{L'\nu'}^{\alpha_j *}({\bf G'+k})
368 * \langle u_{\ell' \nu'}^{\alpha_j}Y_{\ell' m'}|\hat h^{\alpha_j} | \phi_{\ell_j}^{\zeta_j \alpha_j}
369 * Y_{\ell_j m_j} \rangle
370 * \f]
371 * lo-APW block:
372 * \f[
373 * H_{j' {\bf G}}^{\bf k} = \sum_{L\nu} \langle \phi_{\ell_{j'}}^{\zeta_{j'} \alpha_{j'}} Y_{\ell_{j'} m_{j'}}
374 * |\hat h^{\alpha_{j'}} | u_{\ell \nu}^{\alpha_{j'}}Y_{\ell m} \rangle a_{L\nu}^{\alpha_{j'}}({\bf G+k})
375 * \f]
376 * lo-lo block:
377 * \f[
378 * H_{j' j}^{\bf k} = \langle \phi_{\ell_{j'}}^{\zeta_{j'} \alpha_{j'}} Y_{\ell_{j'} m_{j'}}
379 * |\hat h^{\alpha_{j}} | \phi_{\ell_j}^{\zeta_j \alpha_j} Y_{\ell_j m_j} \rangle \delta_{\alpha_j
380 * \alpha_{j'}}
381 * \f]
382 *
383 * The overlap matrix has the following expression:
384 * \f[
385 * O_{\mu' \mu} = \langle \varphi_{\mu'} | \varphi_{\mu} \rangle
386 * \f]
387 * APW-APW block:
388 * \f[
389 * O_{{\bf G'} {\bf G}}^{\bf k} = \sum_{\alpha} \sum_{L\nu} a_{L\nu}^{\alpha *}({\bf G'+k})
390 * a_{L\nu}^{\alpha}({\bf G+k}) + \Theta({\bf G-G'})
391 * \f]
392 *
393 * APW-lo block:
394 * \f[
395 * O_{{\bf G'} j}^{\bf k} = \sum_{\nu'} a_{\ell_j m_j \nu'}^{\alpha_j *}({\bf G'+k})
396 * \langle u_{\ell_j \nu'}^{\alpha_j} | \phi_{\ell_j}^{\zeta_j \alpha_j} \rangle
397 * \f]
398 *
399 * lo-APW block:
400 * \f[
401 * O_{j' {\bf G}}^{\bf k} =
402 * \sum_{\nu'} \langle \phi_{\ell_{j'}}^{\zeta_{j'} \alpha_{j'}} | u_{\ell_{j'} \nu'}^{\alpha_{j'}} \rangle
403 * a_{\ell_{j'} m_{j'} \nu'}^{\alpha_{j'}}({\bf G+k})
404 * \f]
405 *
406 * lo-lo block:
407 * \f[
408 * O_{j' j}^{\bf k} = \langle \phi_{\ell_{j'}}^{\zeta_{j'} \alpha_{j'}} |
409 * \phi_{\ell_{j}}^{\zeta_{j} \alpha_{j}} \rangle \delta_{\alpha_{j'} \alpha_j}
410 * \delta_{\ell_{j'} \ell_j} \delta_{m_{j'} m_j}
411 * \f]
412 */
413 void set_fv_h_o(la::dmatrix<std::complex<T>>& h__, la::dmatrix<std::complex<T>>& o__) const;
414
415 /// Add interstitial contribution to apw-apw block of Hamiltonian and overlap.
416 void set_fv_h_o_it(la::dmatrix<std::complex<T>>& h__, la::dmatrix<std::complex<T>>& o__) const;
417
418 /// Setup lo-lo block of Hamiltonian and overlap matrices.
419 void set_fv_h_o_lo_lo(la::dmatrix<std::complex<T>>& h__, la::dmatrix<std::complex<T>>& o__) const;
420
421 /// Setup apw-lo and lo-apw blocks of LAPW Hamiltonian and overlap matrices.
422 void set_fv_h_o_apw_lo(Atom const& atom, int ia, sddk::mdarray<std::complex<T>, 2>& alm_row,
423 sddk::mdarray<std::complex<T>, 2>& alm_col, sddk::mdarray<std::complex<T>, 2>& h,
424 sddk::mdarray<std::complex<T>, 2>& o) const;
425
426 /// Apply pseudopotential H and S operators to the wavefunctions.
427 /** \tparam F Type of the subspace matrix.
428 * \param [in] spins Range of spins.
429 * \param [in] br Range of bands.
430 * \param [in] phi Input wave-functions [storage: CPU && GPU].
431 * \param [out] hphi Result of Hamiltonian, applied to wave-functions [storage: CPU || GPU].
432 * \param [out] sphi Result of S-operator, applied to wave-functions [storage: CPU || GPU].
433 *
434 * In non-collinear case (spins in [0,1]) the Hamiltonian and S operator are applied to both components of spinor
435 * wave-functions. Otherwise they are applied to a single component.
436 */
437 template <typename F>
438 std::enable_if_t<std::is_same<T, real_type<F>>::value, void>
440 wf::Wave_functions<T>* hphi__, wf::Wave_functions<T>* sphi__) const
441 {
442 PROFILE("sirius::Hamiltonian_k::apply_h_s");
443
444 auto pcs = env::print_checksum();
445
446 if (hphi__ != nullptr) {
447 /* apply local part of Hamiltonian */
448 H0().local_op().apply_h(reinterpret_cast<fft::spfft_transform_type<T>&>(kp_.spfft_transform()),
449 kp_.gkvec_fft_sptr(), spins__, phi__, *hphi__, br__);
450 }
451
452 auto mem = H0().ctx().processing_unit_memory_t();
453
454 if (pcs) {
455 auto cs = phi__.checksum(mem, br__);
456 print_checksum("phi", cs, RTE_OUT(H0().ctx().out()));
457 if (hphi__) {
458 auto cs = hphi__->checksum(mem, br__);
459 print_checksum("hloc_phi", cs, RTE_OUT(H0().ctx().out()));
460 }
461 }
462
463 /* set initial sphi */
464 if (sphi__ != nullptr) {
465 for (auto s = spins__.begin(); s!= spins__.end(); s++) {
466 auto sp = phi__.actual_spin_index(s);
467 wf::copy(mem, phi__, sp, br__, *sphi__, sp, br__);
468 }
469 }
470
471 /* return if there are no beta-projectors */
472 if (H0().ctx().unit_cell().max_mt_basis_size()) {
473 auto bp_generator = kp_.beta_projectors().make_generator();
474 auto beta_coeffs = bp_generator.prepare();
475 apply_non_local_D_Q<T, F>(mem, spins__, br__, bp_generator, beta_coeffs, phi__, &H0().D(), hphi__, &H0().Q(), sphi__);
476 }
477
478 /* apply the hubbard potential if relevant */
479 if (H0().ctx().hubbard_correction() && !H0().ctx().gamma_point() && hphi__) {
480 /* apply the hubbard potential */
481 apply_U_operator(H0().ctx(), spins__, br__, kp_.hubbard_wave_functions_S(), phi__, this->U(), *hphi__);
482 }
483
484 if (pcs) {
485 if (hphi__) {
486 auto cs = hphi__->checksum(mem, br__);
487 print_checksum("hphi", cs, RTE_OUT(H0().ctx().out()));
488 }
489 if (sphi__) {
490 auto cs = sphi__->checksum(mem, br__);
491 print_checksum("hsphi", cs, RTE_OUT(H0().ctx().out()));
492 }
493 }
494 }
495
496 template <typename F>
497 std::enable_if_t<!std::is_same<T, real_type<F>>::value, void>
499 wf::Wave_functions<T>* hphi__, wf::Wave_functions<T>* sphi__) const
500 {
501 RTE_THROW("implementat this");
502 }
503
504 /// apply S operator
505 /** \tparam F Type of the subspace matrix.
506 * \param [in] spins Range of spins.
507 * \param [in] br Range of bands.
508 * \param [in] phi Input wave-functions [storage: CPU && GPU].
509 * \param [out] sphi Result of S-operator, applied to wave-functions [storage: CPU || GPU].
510 *
511 * In non-collinear case (spins in [0,1]) the S operator is applied to both components of spinor
512 * wave-functions. Otherwise they are applied to a single component.
513 */
514 template <typename F>
515 std::enable_if_t<std::is_same<T, real_type<F>>::value, void>
517 auto mem = H0().ctx().processing_unit_memory_t();
518 auto bp_gen = kp_.beta_projectors().make_generator();
519 auto bp_coeffs = bp_gen.prepare();
520 apply_S_operator<T, F>(mem, spin__, br__,
521 bp_gen, bp_coeffs, phi__, &H0().Q(), sphi__);
522 }
523
524 /// Apply magnetic field to first-variational LAPW wave-functions.
525 void apply_b(wf::Wave_functions<T>& psi__, std::vector<wf::Wave_functions<T>>& bpsi__) const;
526};
527
528template <typename T>
529Hamiltonian_k<T>
531{
532 return Hamiltonian_k<T>(*this, kp__);
533}
534
535}
536
537#endif
Represent the k-point independent part of Hamiltonian.
Definition: hamiltonian.hpp:75
Unit_cell & unit_cell_
Alias for unit cell.
Definition: hamiltonian.hpp:84
Hamiltonian_k< T > operator()(K_point< T > &kp__) const
Return a Hamiltonian for the given k-point.
std::unique_ptr< Q_operator< T > > q_op_
Q operator (non-local part of S-operator).
Definition: hamiltonian.hpp:93
void apply_hmt_to_apw(Atom const &atom__, int ngv__, sddk::mdarray< std::complex< T >, 2 > &alm__, sddk::mdarray< std::complex< T >, 2 > &halm__) const
Apply the muffin-tin part of the Hamiltonian to the apw basis functions of an atom.
void apply_so_correction(wf::Wave_functions< T > &psi__, std::vector< wf::Wave_functions< T > > &hpsi__) const
Apply SO correction to the first-variational LAPW wave-functions.
std::unique_ptr< D_operator< T > > d_op_
D operator (non-local part of Hamiltonian).
Definition: hamiltonian.hpp:90
Potential * potential_
Alias for the potential.
Definition: hamiltonian.hpp:81
Hamiltonian0(Hamiltonian0< T > &&src)=default
Default move constructor.
void add_o1mt_to_apw(Atom const &atom__, int num_gkvec__, sddk::mdarray< std::complex< T >, 2 > &alm__) const
Add correction to LAPW overlap arising in the infinite-order relativistic approximation (IORA).
Simulation_context & ctx_
Simulation context.
Definition: hamiltonian.hpp:78
void apply_bmt(wf::Wave_functions< T > &psi__, std::vector< wf::Wave_functions< T > > &bpsi__) const
Apply muffin-tin part of magnetic filed to the wave-functions.
std::unique_ptr< Local_operator< T > > local_op_
Local part of the Hamiltonian operator.
Definition: hamiltonian.hpp:87
Representation of Kohn-Sham Hamiltonian.
Hamiltonian_k< T > & operator=(Hamiltonian_k< T > const &src__)=delete
Assignment operator is forbidden.
std::enable_if_t< std::is_same< T, real_type< F > >::value, void > apply_h_s(wf::spin_range spins__, wf::band_range br__, wf::Wave_functions< T > const &phi__, wf::Wave_functions< T > *hphi__, wf::Wave_functions< T > *sphi__) const
Apply pseudopotential H and S operators to the wavefunctions.
void set_fv_h_o_lo_lo(la::dmatrix< std::complex< T > > &h__, la::dmatrix< std::complex< T > > &o__) const
Setup lo-lo block of Hamiltonian and overlap matrices.
void apply_b(wf::Wave_functions< T > &psi__, std::vector< wf::Wave_functions< T > > &bpsi__) const
Apply magnetic field to first-variational LAPW wave-functions.
void set_fv_h_o(la::dmatrix< std::complex< T > > &h__, la::dmatrix< std::complex< T > > &o__) const
Setup the Hamiltonian and overlap matrices in APW+lo basis.
void set_fv_h_o_it(la::dmatrix< std::complex< T > > &h__, la::dmatrix< std::complex< T > > &o__) const
Add interstitial contribution to apw-apw block of Hamiltonian and overlap.
void apply_fv_h_o(bool apw_only__, bool phi_is_lo__, wf::band_range b__, wf::Wave_functions< T > &phi__, wf::Wave_functions< T > *hphi__, wf::Wave_functions< T > *ophi__) const
Apply first-variational LAPW Hamiltonian and overlap matrices.
std::shared_ptr< U_operator< T > > u_op_
Hubbard correction.
void set_fv_h_o_apw_lo(Atom const &atom, int ia, sddk::mdarray< std::complex< T >, 2 > &alm_row, sddk::mdarray< std::complex< T >, 2 > &alm_col, sddk::mdarray< std::complex< T >, 2 > &h, sddk::mdarray< std::complex< T >, 2 > &o) const
Setup apw-lo and lo-apw blocks of LAPW Hamiltonian and overlap matrices.
Hamiltonian0< T > const & H0_
K-point independent part of Hamiltonian.
Hamiltonian_k(Hamiltonian_k< T > const &src__)=delete
Copy constructor is forbidden.
std::enable_if_t< std::is_same< T, real_type< F > >::value, void > apply_s(wf::spin_range spin__, wf::band_range br__, wf::Wave_functions< T > const &phi__, wf::Wave_functions< T > &sphi__) const
apply S operator
K-point related variables and methods.
Definition: k_point.hpp:44
auto const & hubbard_wave_functions_S() const
Return the actual hubbard wave functions used in the calculations.
Definition: k_point.hpp:516
Generate effective potential from charge density and magnetization.
Definition: potential.hpp:46
Simulation context is a set of parameters and objects describing a single simulation.
Representation of a unit cell.
Definition: unit_cell.hpp:43
auto actual_spin_index(spin_index s__) const
Return the actual spin index of the wave-functions.
Wave-functions representation.
Describe a range of bands.
Describe a range of spins.
Contains definition and implementation of distributed matrix class.
Contains helper functions for the interface with SpFFT library.
Declaration of sirius::Local_operator class.
Memory management functions and classes.
void copy(sddk::memory_t mem__, Wave_functions< T > const &in__, wf::spin_index s_in__, wf::band_range br_in__, Wave_functions< F > &out__, wf::spin_index s_out__, wf::band_range br_out__)
Copy wave-functions.
Namespace of the SIRIUS library.
Definition: sirius.f90:5
void apply_U_operator(Simulation_context &ctx__, wf::spin_range spins__, wf::band_range br__, wf::Wave_functions< T > const &hub_wf__, wf::Wave_functions< T > const &phi__, U_operator< T > const &um__, wf::Wave_functions< T > &hphi__)
Contains declaration of sirius::Non_local_operator class.
Contains typedefs, enums and simple descriptors.
Contains declaration and implementation of Wave_functions class.