SIRIUS 7.5.0
Electronic structure library and applications
local_operator.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 local_operator.hpp
21 *
22 * \brief Declaration of sirius::Local_operator class.
23 */
24
25#ifndef __LOCAL_OPERATOR_HPP__
26#define __LOCAL_OPERATOR_HPP__
27
28#include "SDDK/memory.hpp"
29#include "core/typedefs.hpp"
30#include "core/fft/fft.hpp"
31#include "core/rte/rte.hpp"
32
33/* forward declarations */
34namespace sirius {
35class Potential;
36class Simulation_context;
37template <typename T>
38class Smooth_periodic_function;
39namespace wf {
40template <typename T>
41class Wave_functions;
42class band_range;
43class spin_range;
44}
45namespace fft {
46class Gvec_fft;
47}
48}
49namespace spfft {
50class Transform;
51}
52
53#ifdef SIRIUS_GPU
54extern "C" {
55
56void
57add_to_hphi_pw_gpu_float(int num_gvec__, int add_ekin__, void const* pw_ekin__, void const* phi__,
58 void const* vphi__, void* hphi__);
59
60void
61add_to_hphi_pw_gpu_double(int num_gvec__, int add_ekin__, void const* pw_ekin__, void const* phi__,
62 void const* vphi__, void* hphi__);
63
64void
65add_to_hphi_lapw_gpu_float(int num_gvec__, void const* p__, void const* gkvec_cart__, void* hphi__);
66
67void
68add_to_hphi_lapw_gpu_double(int num_gvec__, void const* p__, void const* gkvec_cart__, void* hphi__);
69
70void
71grad_phi_lapw_gpu_float(int num_gvec__, void const* p__, void const* gkvec_cart__, void* hphi__);
72
73void
74grad_phi_lapw_gpu_double(int num_gvec__, void const* p__, void const* gkvec_cart__, void* hphi__);
75
76void
77mul_by_veff_real_real_gpu_float(int nr__, void const* in__, void const* veff__, void* out__);
78
79void
80mul_by_veff_real_real_gpu_double(int nr__, void const* in__, void const* veff__, void* out__);
81
82void
83mul_by_veff_complex_real_gpu_float(int nr__, void const* in__, void const* veff__, void* out__);
84
85void
86mul_by_veff_complex_real_gpu_double(int nr__, void const* in__, void const* veff__, void* out__);
87
88void
89mul_by_veff_complex_complex_gpu_float(int nr__, void const* in__, float pref__,
90 void const* vx__, void const* vy__, void* out__);
91
92void
93mul_by_veff_complex_complex_gpu_double(int nr__, void const* in__, double pref__,
94 void const* vx__, void const* vy__, void* out__);
95
96} // extern C
97#endif
98
99template <typename T>
100inline void
101mul_by_veff_real_real_gpu(int nr__, T const* in__, T const* veff__, T* out__)
102{
103#ifdef SIRIUS_GPU
104 if (std::is_same<T, float>::value) {
105 mul_by_veff_real_real_gpu_float(nr__, in__, veff__, out__);
106 }
107 if (std::is_same<T, double>::value) {
108 mul_by_veff_real_real_gpu_double(nr__, in__, veff__, out__);
109 }
110#else
111 RTE_THROW("not compiled with GPU support");
112#endif
113}
114
115template <typename T>
116inline void
117mul_by_veff_complex_real_gpu(int nr__, std::complex<T> const* in__, T const* veff__, std::complex<T>* out__)
118{
119#ifdef SIRIUS_GPU
120 if (std::is_same<T, float>::value) {
121 mul_by_veff_complex_real_gpu_float(nr__, in__, veff__, out__);
122 }
123 if (std::is_same<T, double>::value) {
124 mul_by_veff_complex_real_gpu_double(nr__, in__, veff__, out__);
125 }
126#else
127 RTE_THROW("not compiled with GPU support");
128#endif
129}
130
131template <typename T>
132inline void
133mul_by_veff_complex_complex_gpu(int nr__, std::complex<T> const* in__, T pref__, T const* vx__, T const* vy__,
134 std::complex<T>* out__)
135{
136#ifdef SIRIUS_GPU
137 if (std::is_same<T, float>::value) {
138 mul_by_veff_complex_complex_gpu_float(nr__, in__, pref__, vx__, vy__, out__);
139 }
140 if (std::is_same<T, double>::value) {
141 mul_by_veff_complex_complex_gpu_double(nr__, in__, pref__, vx__, vy__, out__);
142 }
143#else
144 RTE_THROW("not compiled with GPU support");
145#endif
146}
147
148template <typename T>
149inline void
150add_to_hphi_pw_gpu(int num_gvec__, int add_ekin__, T const* pw_ekin__, std::complex<T> const* phi__,
151 std::complex<T> const* vphi__, std::complex<T>* hphi__)
152{
153#ifdef SIRIUS_GPU
154 if (std::is_same<T, float>::value) {
155 add_to_hphi_pw_gpu_float(num_gvec__, add_ekin__, pw_ekin__, phi__, vphi__, hphi__);
156 }
157 if (std::is_same<T, double>::value) {
158 add_to_hphi_pw_gpu_double(num_gvec__, add_ekin__, pw_ekin__, phi__, vphi__, hphi__);
159 }
160#else
161 RTE_THROW("not compiled with GPU support");
162#endif
163}
164
165template <typename T>
166inline void
167add_to_hphi_lapw_gpu(int num_gvec__, std::complex<T> const* p__, T const* gkvec_cart__, std::complex<T>* hphi__)
168{
169#ifdef SIRIUS_GPU
170 if (std::is_same<T, float>::value) {
171 add_to_hphi_lapw_gpu_float(num_gvec__, p__, gkvec_cart__, hphi__);
172 }
173 if (std::is_same<T, double>::value) {
174 add_to_hphi_lapw_gpu_double(num_gvec__, p__, gkvec_cart__, hphi__);
175 }
176#else
177 RTE_THROW("not compiled with GPU support");
178#endif
179}
180
181template <typename T>
182inline void
183grad_phi_lapw_gpu(int num_gvec__, std::complex<T> const* p__, T const* gkvec_cart__, std::complex<T>* hphi__)
184{
185#ifdef SIRIUS_GPU
186 if (std::is_same<T, float>::value) {
187 grad_phi_lapw_gpu_float(num_gvec__, p__, gkvec_cart__, hphi__);
188 }
189 if (std::is_same<T, double>::value) {
190 grad_phi_lapw_gpu_double(num_gvec__, p__, gkvec_cart__, hphi__);
191 }
192#else
193 RTE_THROW("not compiled with GPU support");
194#endif
195}
196
197namespace sirius {
198
199/// Representation of the local operator.
200/** The following functionality is implementated:
201 * - application of the local part of Hamiltonian (kinetic + potential) to the wave-functions in the PP-PW case
202 * - application of the interstitial part of H and O in the case of FP-LAPW
203 * - application of the interstitial part of effective magnetic field to the first-variational functios
204 * - remapping of potential and unit-step functions from fine to coarse mesh of G-vectors
205 */
206template <typename T>
208{
209 private:
210 /// Common parameters.
212
213 /// Coarse-grid FFT driver for this operator.
214 fft::spfft_transform_type<T>& fft_coarse_;
215
216 /// Distribution of the G-vectors for the FFT transformation.
217 std::shared_ptr<fft::Gvec_fft> gvec_coarse_p_;
218
219 /// Kinetic energy of G+k plane-waves.
221
222 sddk::mdarray<T, 2> gkvec_cart_;
223
224 // Names for indices.
226 {
227 static const int v0 = 0;
228 static const int v1 = 1;
229 static const int vx = 2;
230 static const int vy = 3;
231 static const int theta = 4;
232 static const int rm_inv = 5;
233 };
234
235 /// Effective potential components and unit step function on a coarse FFT grid.
236 /** The following elements are stored in the array:
237 - V(r) + B_z(r) (in PP-PW case) or V(r) (in FP-LAPW case)
238 - V(r) - B_z(r) (in PP-PW case) or B_z(r) (in FP-LAPW case)
239 - B_x(r)
240 - B_y(r)
241 - Theta(r) (in FP-LAPW case)
242 - inverse of 1 + relative mass (needed for ZORA LAPW)
243 */
244 std::array<std::unique_ptr<Smooth_periodic_function<T>>, 6> veff_vec_;
245
246 /// Temporary array to store [V*phi](G)
248
249 /// Temporary array to store psi_{up}(r).
250 /** The size of the array is equal to the size of FFT buffer. */
252
253 /// V(G=0) matrix elements.
254 T v0_[2];
255
256 public:
257 /// Constructor.
258 /** Prepares k-point independent part of the local potential. If potential is provided, it is mapped to the
259 * coarse FFT grid, otherwise the constant potential is assumed for the debug and benchmarking purposes.
260 * In the case of GPU-enabled FFT driver all effective fields on the coarse grid are copied to the device
261 * and remain there until the local operator is destroyed.
262
263 * \param [in] ctx Simulation context.
264 * \param [in] fft_coarse Explicit FFT driver for the coarse mesh.
265 * \param [in] gvec_coarse_p FFT-friendly G-vector distribution for the coarse mesh.
266 * \param [in] potential Effective potential and magnetic fields \f$ V_{eff}({\bf r}) \f$ and
267 * \f$ {\bf B}_{eff}({\bf r}) \f$ on the fine FFT grid.
268 */
269 Local_operator(Simulation_context const& ctx__, fft::spfft_transform_type<T>& fft_coarse__,
270 std::shared_ptr<fft::Gvec_fft> gvec_coarse_fft__, Potential* potential__ = nullptr);
271
272 /// Prepare the k-point dependent arrays.
273 /** \param [in] gkvec_p FFT-friendly G+k vector partitioning. */
274 void prepare_k(fft::Gvec_fft const& gkvec_p__);
275
276 /// Apply local part of Hamiltonian to pseudopotential wave-functions.
277 /** \param [in] spfftk SpFFT transform object for G+k vectors.
278 * \param [in] gkvec_p FFT-friendly G+k vector partitioning.
279 * \param [in] spins Range of wave-function spins to which Hloc is applied.
280 * \param [in] phi Input wave-functions.
281 * \param [out] hphi Local hamiltonian applied to wave-function.
282 * \param [in] idx0 Starting index of wave-functions.
283 * \param [in] n Number of wave-functions to which H is applied.
284 *
285 * Spin range can take the following values:
286 * - [0, 0]: apply H_{uu} to the up- component of wave-functions
287 * - [1, 1]: apply H_{dd} to the dn- component of wave-functions
288 * - [0, 1]: apply full Hamiltonian to the spinor wave-functions
289 *
290 * Local Hamiltonian includes kinetic term and local part of potential.
291 */
292 void apply_h(fft::spfft_transform_type<T>& spfftk__, std::shared_ptr<fft::Gvec_fft> gkvec_fft__,
293 wf::spin_range spins__, wf::Wave_functions<T> const& phi__, wf::Wave_functions<T>& hphi__,
294 wf::band_range br__);
295
296 /// Apply local part of LAPW Hamiltonian and overlap operators.
297 /** \param [in] spfftk SpFFT transform object for G+k vectors.
298 * \param [in] gkvec_p FFT-friendly G+k vector partitioning.
299 * \param [in] N Starting index of wave-functions.
300 * \param [in] n Number of wave-functions to which H and O are applied.
301 * \param [in] phi Input wave-functions [always on CPU].
302 * \param [out] hphi LAPW Hamiltonian applied to wave-function [CPU || GPU].
303 * \param [out] ophi LAPW overlap matrix applied to wave-function [CPU || GPU].
304 *
305 * Only plane-wave part of output wave-functions is changed.
306 */
307 void apply_fplapw(fft::spfft_transform_type<T>& spfftik__, std::shared_ptr<fft::Gvec_fft> gkvec_fft__,
310
311 /// Apply magnetic field to the full-potential wave-functions.
312 /** In case of collinear magnetism only Bz is applied to <tt>phi</tt> and stored in the first component of
313 * <tt>bphi</tt>. In case of non-collinear magnetims Bx-iBy is also applied and stored in the third
314 * component of <tt>bphi</tt>. The second component of <tt>bphi</tt> is used to store -Bz|phi>.
315 *
316 * \param [in] spfftk SpFFT transform object for G+k vectors.
317 * \param [in] phi Input wave-functions.
318 * \param [out] bphi Output vector of magentic field components, applied to the wave-functions.
319 * \param [in] br Range of bands to which B is applied.
320 */
321 //void apply_b(spfft_transform_type<T>& spfftk__, wf::Wave_functions<T> const& phi__,
322 // std::vector<wf::Wave_functions<T>>& bphi__, wf::band_range br__);
323
324 inline T v0(int ispn__) const
325 {
326 return v0_[ispn__];
327 }
328};
329
330} // namespace sirius
331
332#endif // __LOCAL_OPERATOR_H__
Representation of the local operator.
sddk::mdarray< T, 1 > pw_ekin_
Kinetic energy of G+k plane-waves.
void prepare_k(fft::Gvec_fft const &gkvec_p__)
Prepare the k-point dependent arrays.
void apply_h(fft::spfft_transform_type< T > &spfftk__, std::shared_ptr< fft::Gvec_fft > gkvec_fft__, wf::spin_range spins__, wf::Wave_functions< T > const &phi__, wf::Wave_functions< T > &hphi__, wf::band_range br__)
Apply local part of Hamiltonian to pseudopotential wave-functions.
Simulation_context const & ctx_
Common parameters.
sddk::mdarray< std::complex< T >, 1 > vphi_
Temporary array to store [V*phi](G)
fft::spfft_transform_type< T > & fft_coarse_
Coarse-grid FFT driver for this operator.
T v0_[2]
V(G=0) matrix elements.
std::array< std::unique_ptr< Smooth_periodic_function< T > >, 6 > veff_vec_
Effective potential components and unit step function on a coarse FFT grid.
sddk::mdarray< std::complex< T >, 1 > buf_rg_
Temporary array to store psi_{up}(r).
Local_operator(Simulation_context const &ctx__, fft::spfft_transform_type< T > &fft_coarse__, std::shared_ptr< fft::Gvec_fft > gvec_coarse_fft__, Potential *potential__=nullptr)
Constructor.
T v0(int ispn__) const
Apply magnetic field to the full-potential wave-functions.
void apply_fplapw(fft::spfft_transform_type< T > &spfftik__, std::shared_ptr< fft::Gvec_fft > gkvec_fft__, wf::band_range b__, wf::Wave_functions< T > &phi__, wf::Wave_functions< T > *hphi__, wf::Wave_functions< T > *ophi__, wf::Wave_functions< T > *bzphi__, wf::Wave_functions< T > *bxyphi__)
Apply local part of LAPW Hamiltonian and overlap operators.
std::shared_ptr< fft::Gvec_fft > gvec_coarse_p_
Distribution of the G-vectors for the FFT transformation.
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.
Stores information about G-vector partitioning between MPI ranks for the FFT transformation.
Definition: gvec.hpp:772
Wave-functions representation.
Describe a range of bands.
Describe a range of spins.
Contains helper functions for the interface with SpFFT library.
void add_to_hphi_pw_gpu_float(int num_gvec__, int add_ekin__, float const *pw_ekin__, gpu_complex_type< float > const *phi__, gpu_complex_type< float > const *vphi__, gpu_complex_type< float > *hphi__)
Update the hphi wave functions.
Memory management functions and classes.
Namespace of the SIRIUS library.
Definition: sirius.f90:5
Eror and warning handling during run-time execution.
Contains typedefs, enums and simple descriptors.