SIRIUS 7.5.0
Electronic structure library and applications
step_function.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2023 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 step_function.hpp
21 *
22 * \brief Generate unit step function for LAPW method.
23 */
24
25#ifndef __STEP_FUNCTION_HPP__
26#define __STEP_FUNCTION_HPP__
27
29
30namespace sirius {
31
32/// Utility function to generate LAPW unit step function.
33inline double
34unit_step_function_form_factors(double R__, double g__)
35{
36 if (g__ < 1e-12) {
37 return std::pow(R__, 3) / 3.0;
38 } else {
39 return (std::sin(g__ * R__) - g__ * R__ * std::cos(g__ * R__)) / std::pow(g__, 3);
40 }
41}
42
43/// Representation of the unit step function.
45 /// Step function on the real-space grid.
47 /// Plane wave expansion coefficients of the step function (global array).
49};
50
51/// Unit step function is defined to be 1 in the interstitial and 0 inside muffin-tins.
52/** Unit step function is constructed from it's plane-wave expansion coefficients which are computed
53 * analytically:
54 * \f[
55 * \Theta({\bf r}) = \sum_{\bf G} \Theta({\bf G}) e^{i{\bf Gr}},
56 * \f]
57 * where
58 * \f[
59 * \Theta({\bf G}) = \frac{1}{\Omega} \int \Theta({\bf r}) e^{-i{\bf Gr}} d{\bf r} =
60 * \frac{1}{\Omega} \int_{\Omega} e^{-i{\bf Gr}} d{\bf r} - \frac{1}{\Omega} \int_{MT} e^{-i{\bf Gr}}
61 * d{\bf r} = \delta_{\bf G, 0} - \sum_{\alpha} \frac{1}{\Omega} \int_{MT_{\alpha}} e^{-i{\bf Gr}}
62 * d{\bf r}
63 * \f]
64 * Integralof a plane-wave over the muffin-tin volume is taken using the spherical expansion of the
65 * plane-wave around central point \f$ \tau_{\alpha} \f$:
66 * \f[ \int_{MT_{\alpha}} e^{-i{\bf Gr}} d{\bf r} = e^{-i{\bf G\tau_{\alpha}}}
67 * \int_{MT_{\alpha}} 4\pi \sum_{\ell m} (-i)^{\ell} j_{\ell}(Gr) Y_{\ell m}(\hat {\bf G}) Y_{\ell m}^{*}(\hat
68 * {\bf r}) r^2 \sin \theta dr d\phi d\theta
69 * \f]
70 * In the above integral only \f$ \ell=m=0 \f$ term survives. So we have:
71 * \f[
72 * \int_{MT_{\alpha}} e^{-i{\bf Gr}} d{\bf r} = 4\pi e^{-i{\bf G\tau_{\alpha}}} \Theta(\alpha, G)
73 * \f]
74 * where
75 * \f[
76 * \Theta(\alpha, G) = \int_{0}^{R_{\alpha}} \frac{\sin(Gr)}{Gr} r^2 dr =
77 * \left\{ \begin{array}{ll} \displaystyle R_{\alpha}^3 / 3 & G=0 \\
78 * \Big( \sin(GR_{\alpha}) - GR_{\alpha}\cos(GR_{\alpha}) \Big) / G^3 & G \ne 0 \end{array} \right.
79 * \f]
80 * are the so-called step function form factors. With this we have a final expression for the plane-wave
81 * coefficients of the unit step function:
82 * \f[ \Theta({\bf G}) = \delta_{\bf G, 0} - \sum_{\alpha}
83 * \frac{4\pi}{\Omega} e^{-i{\bf G\tau_{\alpha}}} \Theta(\alpha, G)
84 * \f]
85 */
86inline auto
87init_step_function(Unit_cell const& uc__, fft::Gvec const& gv__, fft::Gvec_fft const& gvec_fft__,
88 sddk::mdarray<std::complex<double>, 2> const& phase_factors_t__,
89 fft::spfft_transform_type<double> spfft__)
90{
91 auto v = make_periodic_function<index_domain_t::global>(uc__, gv__, phase_factors_t__,
92 [&](int iat, double g) {
93 auto R = uc__.atom_type(iat).mt_radius();
95 });
96
97 step_function_t theta;
98 theta.rg = sddk::mdarray<double, 1>(spfft__.local_slice_size());
99 theta.pw = sddk::mdarray<std::complex<double>, 1>(gv__.num_gvec());
100
101 try {
102 for (int ig = 0; ig < gv__.num_gvec(); ig++) {
103 theta.pw[ig] = -v[ig];
104 }
105 theta.pw[0] += 1.0;
106
107 std::vector<std::complex<double>> ftmp(gvec_fft__.count());
108 gvec_fft__.scatter_pw_global(&theta.pw[0], &ftmp[0]);
109 spfft__.backward(reinterpret_cast<double const*>(ftmp.data()), SPFFT_PU_HOST);
110 double* theta_ptr = spfft__.local_slice_size() == 0 ? nullptr : &theta.rg[0];
111 fft::spfft_output(spfft__, theta_ptr);
112 } catch (...) {
113 std::stringstream s;
114 s << "Error creating step function" << std::endl
115 << " local_slice_size() = " << spfft__.local_slice_size() << std::endl
116 << " gvec_fft__.count() = " << gvec_fft__.count();
117 RTE_THROW(s);
118 }
119
120 double vit{0};
121 for (int i = 0; i < spfft__.local_slice_size(); i++) {
122 vit += theta.rg[i];
123 }
124 vit *= (uc__.omega() / fft::spfft_grid_size(spfft__));
125 mpi::Communicator(spfft__.communicator()).allreduce(&vit, 1);
126
127 if (std::abs(vit - uc__.volume_it()) > 1e-10) {
128 std::stringstream s;
129 s << "step function gives a wrong volume for IT region" << std::endl
130 << " difference with exact value : " << std::abs(vit - uc__.volume_it());
131 if (gv__.comm().rank() == 0) {
132 RTE_WARNING(s);
133 }
134 }
135
136 return theta;
137}
138
139}
140
141#endif
142
Representation of a unit cell.
Definition: unit_cell.hpp:43
double omega() const
Unit cell volume.
Definition: unit_cell.hpp:275
Atom_type & atom_type(int id__)
Return atom type instance by id.
Definition: unit_cell.hpp:288
Stores information about G-vector partitioning between MPI ranks for the FFT transformation.
Definition: gvec.hpp:772
int count(int rank__) const
Local number of G-vectors in the FFT distribution for a given rank.
Definition: gvec.hpp:823
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
MPI communicator wrapper.
void allreduce(T *buffer__, int count__) const
Perform the in-place (the output buffer is used as the input buffer) all-to-all reduction.
int rank() const
Rank of MPI process inside communicator.
Generate plane-wave coefficients of the periodic function from the form-factors.
void spfft_output(spfft_transform_type< T > &spfft__, T *data__)
Output CPU data from the CPU buffer of SpFFT.
Definition: fft.hpp:173
size_t spfft_grid_size(T const &spfft__)
Total size of the SpFFT transformation grid.
Definition: fft.hpp:221
Namespace of the SIRIUS library.
Definition: sirius.f90:5
auto init_step_function(Unit_cell const &uc__, fft::Gvec const &gv__, fft::Gvec_fft const &gvec_fft__, sddk::mdarray< std::complex< double >, 2 > const &phase_factors_t__, fft::spfft_transform_type< double > spfft__)
Unit step function is defined to be 1 in the interstitial and 0 inside muffin-tins.
double unit_step_function_form_factors(double R__, double g__)
Utility function to generate LAPW unit step function.
Representation of the unit step function.
sddk::mdarray< std::complex< double >, 1 > pw
Plane wave expansion coefficients of the step function (global array).
sddk::mdarray< double, 1 > rg
Step function on the real-space grid.