SIRIUS 7.5.0
Electronic structure library and applications
gaunt.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 gaunt.hpp
21 *
22 * \brief Contains definition and implementation of sirius::Gaunt class.
23 */
24
25#ifndef __GAUNT_HPP__
26#define __GAUNT_HPP__
27
28#include "SDDK/memory.hpp"
29#include "core/typedefs.hpp"
30#include "core/sf/specfunc.hpp"
31
32namespace sirius {
33
34/// Used in the {lm1, lm2} : {lm3, coefficient} way of grouping non-zero Gaunt coefficients
35template <typename T>
37{
38 int lm3;
39 int l3;
40 T coef;
41};
42
43/// Used in the {lm1, lm2, coefficient} : {lm3} way of grouping non-zero Gaunt coefficients
44template <typename T>
46{
47 int lm1;
48 int lm2;
49 T coef;
50};
51
52/// Compact storage of non-zero Gaunt coefficients \f$ \langle \ell_1 m_1 | \ell_3 m_3 | \ell_2 m_2 \rangle \f$.
53/** Very important! The following notation is adopted and used everywhere: lm1 and lm2 represent 'bra' and 'ket'
54 * spherical harmonics of the Gaunt integral and lm3 represent the inner spherical harmonic.
55 */
56template <typename T>
58{
59 private:
60 /// lmax of <lm1|
61 int lmax1_;
62 /// lmmax of <lm1|
64
65 /// lmax of inner real or complex spherical harmonic
66 int lmax3_;
67 /// lmmax of inner real or complex spherical harmonic
69
70 /// lmax of |lm2>
71 int lmax2_;
72 /// lmmax of |lm2>
74
75 /// List of non-zero Gaunt coefficients for each lm3.
77
78 /// List of non-zero Gaunt coefficients for each combination of lm1, lm2.
80
81 public:
82 /// Class constructor.
83 Gaunt_coefficients(int lmax1__, int lmax3__, int lmax2__, std::function<T(int, int, int, int, int, int)> get__)
84 : lmax1_(lmax1__)
85 , lmax3_(lmax3__)
86 , lmax2_(lmax2__)
87 {
91
94
96 gaunt_L3<T> g3;
97
98 for (int l1 = 0, lm1 = 0; l1 <= lmax1_; l1++) {
99 for (int m1 = -l1; m1 <= l1; m1++, lm1++) {
100 for (int l2 = 0, lm2 = 0; l2 <= lmax2_; l2++) {
101 for (int m2 = -l2; m2 <= l2; m2++, lm2++) {
102 for (int l3 = 0, lm3 = 0; l3 <= lmax3_; l3++) {
103 for (int m3 = -l3; m3 <= l3; m3++, lm3++) {
104
105 T gc = get__(l1, l3, l2, m1, m3, m2);
106 if (std::abs(gc) > 1e-12) {
107 g12.lm1 = lm1;
108 g12.lm2 = lm2;
109 g12.coef = gc;
110 gaunt_packed_L1_L2_[lm3].push_back(g12);
111
112 g3.lm3 = lm3;
113 g3.l3 = l3;
114 g3.coef = gc;
115 gaunt_packed_L3_(lm1, lm2).push_back(g3);
116 }
117 }
118 }
119 }
120 }
121 }
122 }
123 }
124
125 /// Return number of non-zero Gaunt coefficients for a given lm3.
126 inline int num_gaunt(int lm3) const
127 {
128 assert(lm3 >= 0 && lm3 < lmmax3_);
129 return static_cast<int>(gaunt_packed_L1_L2_[lm3].size());
130 }
131
132 /// Return a structure containing {lm1, lm2, coef} for a given lm3 and index.
133 /** Example:
134 * \code{.cpp}
135 * for (int lm3 = 0; lm3 < lmmax3; lm3++)
136 * {
137 * for (int i = 0; i < gaunt_coefs.num_gaunt(lm3); i++) {
138 * int lm1 = gaunt_coefs.gaunt(lm3, i).lm1;
139 * int lm2 = gaunt_coefs.gaunt(lm3, i).lm2;
140 * double coef = gaunt_coefs.gaunt(lm3, i).coef;
141 *
142 * // do something with lm1,lm2,lm3 and coef
143 * }
144 * }
145 * \endcode
146 */
147 inline gaunt_L1_L2<T> const& gaunt(int lm3, int idx) const
148 {
149 assert(lm3 >= 0 && lm3 < lmmax3_);
150 assert(idx >= 0 && idx < (int)gaunt_packed_L1_L2_[lm3].size());
151 return gaunt_packed_L1_L2_[lm3][idx];
152 }
153
154 /// Return number of non-zero Gaunt coefficients for a combination of lm1 and lm2.
155 inline int num_gaunt(int lm1, int lm2) const
156 {
157 return static_cast<int>(gaunt_packed_L3_(lm1, lm2).size());
158 }
159
160 /// Return a structure containing {lm3, coef} for a given lm1, lm2 and index
161 inline gaunt_L3<T> const& gaunt(int lm1, int lm2, int idx) const
162 {
163 return gaunt_packed_L3_(lm1, lm2)[idx];
164 }
165
166 /// Return a sum over L3 (lm3) index of Gaunt coefficients and a complex vector.
167 /** The following operation is performed:
168 * \f[
169 * \sum_{\ell_3 m_3} \langle \ell_1 m_1 | \ell_3 m_3 | \ell_2 m_2 \rangle v_{\ell_3 m_3}
170 * \f]
171 * Result is assumed to be complex.
172 */
173 inline auto sum_L3_gaunt(int lm1, int lm2, std::complex<double> const* v) const
174 {
175 std::complex<double> zsum(0, 0);
176 for (int k = 0; k < (int)gaunt_packed_L3_(lm1, lm2).size(); k++) {
177 zsum += gaunt_packed_L3_(lm1, lm2)[k].coef * v[gaunt_packed_L3_(lm1, lm2)[k].lm3];
178 }
179 return zsum;
180 }
181
182 /// Return a sum over L3 (lm3) index of Gaunt coefficients and a real vector.
183 /** The following operation is performed:
184 * \f[
185 * \sum_{\ell_3 m_3} \langle \ell_1 m_1 | \ell_3 m_3 | \ell_2 m_2 \rangle v_{\ell_3 m_3}
186 * \f]
187 * Result is assumed to be of the same type as Gaunt coefficients.
188 */
189 inline T sum_L3_gaunt(int lm1, int lm2, double const* v) const
190 {
191 T sum = 0;
192 for (int k = 0; k < (int)gaunt_packed_L3_(lm1, lm2).size(); k++) {
193 sum += gaunt_packed_L3_(lm1, lm2)[k].coef * v[gaunt_packed_L3_(lm1, lm2)[k].lm3];
194 }
195 return sum;
196 }
197
198 /// Return vector of non-zero Gaunt coefficients for a given combination of lm1 and lm2
199 inline std::vector<gaunt_L3<T>> const& gaunt_vector(int lm1, int lm2) const
200 {
201 return gaunt_packed_L3_(lm1, lm2);
202 }
203
204 /// Return the full tensor of Gaunt coefficients <R_{L1}|R_{L3}|R_{L2}> with a (L3, L1, L2) order of indices.
205 inline auto get_full_set_L3() const
206 {
208 gc.zero();
209 for (int lm2 = 0; lm2 < lmmax2_; lm2++) {
210 for (int lm1 = 0; lm1 < lmmax1_; lm1++) {
211 for (int k = 0; k < (int)gaunt_packed_L3_(lm1, lm2).size(); k++) {
212 int lm3 = gaunt_packed_L3_(lm1, lm2)[k].lm3;
213 gc(lm3, lm1, lm2) = gaunt_packed_L3_(lm1, lm2)[k].coef;
214 }
215 }
216 }
217 return gc;
218 }
219};
220
221}; // namespace sirius
222
223#endif
Compact storage of non-zero Gaunt coefficients .
Definition: gaunt.hpp:58
int lmmax2_
lmmax of |lm2>
Definition: gaunt.hpp:73
auto get_full_set_L3() const
Return the full tensor of Gaunt coefficients <R_{L1}|R_{L3}|R_{L2}> with a (L3, L1,...
Definition: gaunt.hpp:205
sddk::mdarray< std::vector< gaunt_L3< T > >, 2 > gaunt_packed_L3_
List of non-zero Gaunt coefficients for each combination of lm1, lm2.
Definition: gaunt.hpp:79
auto sum_L3_gaunt(int lm1, int lm2, std::complex< double > const *v) const
Return a sum over L3 (lm3) index of Gaunt coefficients and a complex vector.
Definition: gaunt.hpp:173
int num_gaunt(int lm3) const
Return number of non-zero Gaunt coefficients for a given lm3.
Definition: gaunt.hpp:126
int lmax1_
lmax of <lm1|
Definition: gaunt.hpp:61
int lmax3_
lmax of inner real or complex spherical harmonic
Definition: gaunt.hpp:66
int lmmax1_
lmmax of <lm1|
Definition: gaunt.hpp:63
std::vector< gaunt_L3< T > > const & gaunt_vector(int lm1, int lm2) const
Return vector of non-zero Gaunt coefficients for a given combination of lm1 and lm2.
Definition: gaunt.hpp:199
gaunt_L3< T > const & gaunt(int lm1, int lm2, int idx) const
Return a structure containing {lm3, coef} for a given lm1, lm2 and index.
Definition: gaunt.hpp:161
int lmmax3_
lmmax of inner real or complex spherical harmonic
Definition: gaunt.hpp:68
int num_gaunt(int lm1, int lm2) const
Return number of non-zero Gaunt coefficients for a combination of lm1 and lm2.
Definition: gaunt.hpp:155
int lmax2_
lmax of |lm2>
Definition: gaunt.hpp:71
T sum_L3_gaunt(int lm1, int lm2, double const *v) const
Return a sum over L3 (lm3) index of Gaunt coefficients and a real vector.
Definition: gaunt.hpp:189
Gaunt_coefficients(int lmax1__, int lmax3__, int lmax2__, std::function< T(int, int, int, int, int, int)> get__)
Class constructor.
Definition: gaunt.hpp:83
gaunt_L1_L2< T > const & gaunt(int lm3, int idx) const
Return a structure containing {lm1, lm2, coef} for a given lm3 and index.
Definition: gaunt.hpp:147
sddk::mdarray< std::vector< gaunt_L1_L2< T > >, 1 > gaunt_packed_L1_L2_
List of non-zero Gaunt coefficients for each lm3.
Definition: gaunt.hpp:76
Multidimensional array with the column-major (Fortran) order.
Definition: memory.hpp:660
void zero(memory_t mem__, size_t idx0__, size_t n__)
Zero n elements starting from idx0.
Definition: memory.hpp:1316
Memory management functions and classes.
int lmmax(int lmax)
Maximum number of combinations for a given .
Definition: specfunc.hpp:44
Namespace of the SIRIUS library.
Definition: sirius.f90:5
Special functions.
Used in the {lm1, lm2, coefficient} : {lm3} way of grouping non-zero Gaunt coefficients.
Definition: gaunt.hpp:46
Used in the {lm1, lm2} : {lm3, coefficient} way of grouping non-zero Gaunt coefficients.
Definition: gaunt.hpp:37
Contains typedefs, enums and simple descriptors.