ViennaSHE 1.3.0
Free open-source semiconductor device simulator using spherical harmonics expansions techniques.
spherical_harmonics.hpp
Go to the documentation of this file.
1#ifndef VIENNASHE_MATH_SPHERICAL_HARMONICS_HPP
2#define VIENNASHE_MATH_SPHERICAL_HARMONICS_HPP
3
4/* ============================================================================
5 Copyright (c) 2011-2022, Institute for Microelectronics,
6 Institute for Analysis and Scientific Computing,
7 TU Wien.
8
9 -----------------
10 ViennaSHE - The Vienna Spherical Harmonics Expansion Boltzmann Solver
11 -----------------
12
13 http://viennashe.sourceforge.net/
14
15 License: MIT (X11), see file LICENSE in the base directory
16=============================================================================== */
17
18
19// std
20#include <math.h>
21
22// viennashe
23#include "viennashe/forwards.h"
24
25#include "viennashe/log/log.hpp"
27
28
35namespace viennashe
36{
37 namespace math
38 {
39
40
42 inline double factorial(long n)
43 {
44 double result = 1;
45 for (long i=n; i>1; --i)
46 result *= i;
47
48 return result;
49 }
50
52 inline double doublefactorial(long n)
53 {
54 double result = 1;
55 double loopindex = n;
56
57 while (loopindex > 1)
58 {
59 result *= loopindex;
60 loopindex -= 2;
61 }
62
63 return result;
64 }
65
68 {
69 public:
70 AssocLegendre(long n, long m) : n_(n), m_(m) {}
71
72 double operator()(double x) const //evaluation is carried out via a recursion formula
73 {
74 log::info<log_AssocLegendre>() << "AssocLegendre() with n=" << n_ << ", m=" << m_ << std::endl;
75
76 if (n_ == m_)
77 return doublefactorial(2*n_ - 1) * pow(sqrt(1.0 - x*x), n_) * ( (n_ % 2 == 0) ? 1.0 : -1.0);
78 else if (m_ == (n_ - 1))
79 return x * (2.0 * n_ - 1.0) * AssocLegendre(m_, m_)(x);
80 else if (n_ < m_)
81 {
82 log::error() << "Error in AssocLegendre: n<m" << std::endl;
83 return 0.0;
84 }
85 else
86 return ( (2.0 * n_ - 1.0) * x * AssocLegendre(n_ - 1, m_)(x)
87 - (n_ + m_ - 1.0) * AssocLegendre(n_ - 2, m_)(x) ) / (n_ - m_);
88 }
89
90 private:
91 long n_;
92 long m_;
93 };
94
95
96
99 {
100 public:
101 SphericalHarmonic(int n, int m) : n_(n), m_(m)
102 {
103 const double pi = 3.1415926535897932384626433832795;
104 normalisation = sqrt( (2.0*n_ + 1.0) * factorial(n_ - abs(m_)) / (2.0 * pi * factorial(n_ + abs(m_))));
105 }
106
107 double operator()(double theta, double phi) const
108 {
109 if (m_ > 0)
110 return normalisation * AssocLegendre(n_, m_)(cos(theta)) * cos(m_ * phi);
111 else if (m_ == 0)
112 return normalisation * AssocLegendre(n_, 0)(cos(theta)) / sqrt(2.0);
113 else
114 return normalisation * AssocLegendre(n_, -m_)(cos(theta)) * sin(m_ * phi);
115 }
116
117 private:
118 double normalisation;
119 int n_;
120 int m_;
121 };
122
125 {
126 public:
127 SphericalHarmonic_dTheta(int n, int m) : n_(n), m_(m), Y_n_m(n, m), Y_n_1_m(n-1, m) {}
128
129 double operator()(double theta, double phi) const
130 {
131 if (n_ == 0)
132 return 0.0;
133
134 if (abs(m_) < n_)
135 {
136 //double sum1 = n_ * cos(theta) * SphericalHarmonic(n_, m_)(theta, phi) ;
137 //double sum2 = sqrt( (n_*n_ - m_*m_) * (2.0*n_ + 1.0) / (2.0*n_ - 1.0) ) * SphericalHarmonic(n_ - 1, m_)(theta, phi);
138 double sum1 = n_ * cos(theta) * Y_n_m(theta, phi);
139 double sum2 = sqrt( (n_*n_ - m_*m_) * (2.0*n_ + 1.0) / (2.0*n_ - 1.0) ) * Y_n_1_m(theta, phi);
140
141 //log::debug<log_AssocLegendre>() << sum1 << ", " << sum2 << std::endl;
142 return ( sum1 - sum2 ) / sin(theta);
143 }
144 else //n == abs(m)
145 return n_ * cos(theta) * SphericalHarmonic(n_, m_)(theta, phi) / sin(theta);
146 }
147
148 private:
149 int n_;
150 int m_;
151 SphericalHarmonic Y_n_m; //Y_{n,m}
152 SphericalHarmonic Y_n_1_m; //Y_{n-1,m}
153 };
154
157 {
158 public:
159 SphericalHarmonic_dTheta_2(int n, int m) : n_(n), m_(m) {}
160
161 double operator()(double theta, double phi) const
162 {
163 if (n_ == 0)
164 return 0.0;
165
166 const double pi = 3.1415926535897932384626433832795;
167 double normalisation = sqrt( (2.0*n_ + 1.0) * factorial(n_ - abs(m_)) / (2.0 * pi * factorial(n_ + abs(m_))));
168
169 double dP_dtheta = n_ * cos(theta) * AssocLegendre(n_, abs(m_))(cos(theta)) ;
170 if (abs(m_) < n_)
171 dP_dtheta -= (n_ + abs(m_)) * AssocLegendre(n_-1, abs(m_))(cos(theta));
172 dP_dtheta /= sin(theta);
173
174 if (m_ > 0)
175 return normalisation * dP_dtheta * cos(m_ * phi);
176 else if (m_ == 0)
177 return normalisation * dP_dtheta / sqrt(2.0);
178 else
179 return normalisation * dP_dtheta * sin(m_ * phi);
180 }
181
182 private:
183 int n_;
184 int m_;
185 };
186
189 {
190 public:
191 SphericalHarmonic_dPhi(int n, int m) : n_(n), m_(m) {}
192
193 double operator()(double theta, double phi) const
194 {
195 if (m_ == 0)
196 return 0.0;
197
198 return m_ * SphericalHarmonic(n_, -1 * m_)(theta, phi);
199 }
200
201
202 private:
203 int n_;
204 int m_;
205 };
206
207
208
209 //Iteration over spherical harmonics indices:
210
211
214 {
215 public:
217 : L_(Lmax),
218 l_( (it_type == ODD_HARMONICS_ITERATION_ID) ? 1 : 0),
219 m_( (it_type == ODD_HARMONICS_ITERATION_ID) ? -1 : 0),
220 iter_type_(it_type) {}
221
223 {
224 if (m_ < l_)
225 ++m_;
226 else
227 {
228 switch (iter_type_)
229 {
231 l_ += 1;
232 break;
235 l_ += 2;
236 break;
237 }
238 m_ = -1 * l_;
239 }
240 }
241 long valid() { return l_ <= L_; }
242 long operator*() const { return l_*l_ + m_ + l_; }
243
244 long index1() const { return l_; }
245 long index2() const { return m_; }
246
247 private:
248 long L_;
249 long l_;
250 long m_;
251 harmonics_iteration_type iter_type_;
252 };
253
254
255 } //namespace math
256} //namespace viennashe
257#endif
Associated Legendre polynomial.
Derivative of a spherical harmonic with respect to phi.
double operator()(double theta, double phi) const
Derivative of a spherical harmonic with respect to theta, alternative evaluation of theta-derivative.
double operator()(double theta, double phi) const
Derivative of a spherical harmonic with respect to theta.
double operator()(double theta, double phi) const
double operator()(double theta, double phi) const
Iteration over all spherical harmonics indices up to order L, with increasing indices l and m.
spherical_harmonics_iterator(long Lmax, harmonics_iteration_type it_type)
Contains forward declarations and definition of small classes that must be defined at an early stage.
A logging facility providing fine-grained control over logging in ViennaSHE.
logger< true > error()
Used to log errors. The logging level is logERROR.
Definition: log.hpp:301
harmonics_iteration_type
An enumeration of spherical harmonics types (all, even, odd) ViennaSHE supports.
Definition: forwards.h:159
@ ALL_HARMONICS_ITERATION_ID
Definition: forwards.h:160
@ EVEN_HARMONICS_ITERATION_ID
Definition: forwards.h:161
@ ODD_HARMONICS_ITERATION_ID
Definition: forwards.h:162
double factorial(long n)
Compute the factorial.
double doublefactorial(long n)
Compute the double factorial, i.e. n(n-2)(n-4)...
The main ViennaSHE namespace. All functionality resides inside this namespace.
Definition: accessors.hpp:40
Defines the log keys used within the viennashe::math namespace.