ViennaSHE 1.3.0
Free open-source semiconductor device simulator using spherical harmonics expansions techniques.
spherical_harmonics.cpp
Go to the documentation of this file.
1/* ============================================================================
2 Copyright (c) 2011-2022, Institute for Microelectronics,
3 Institute for Analysis and Scientific Computing,
4 TU Wien.
5
6 -----------------
7 ViennaSHE - The Vienna Spherical Harmonics Expansion Boltzmann Solver
8 -----------------
9
10 http://viennashe.sourceforge.net/
11
12 License: MIT (X11), see file LICENSE in the base directory
13=============================================================================== */
14
15#include <iostream>
16#include <cstdlib>
17#include <cmath>
18#include <vector>
19#include <sstream>
20
21#include "tests/src/common.hpp"
22
25
27
28#include <math.h>
29
30
36//up to which order assoc. Legendre functions should be checked:
37#define LEGENDRE_DEGREE 7
38
39//up to which order spherical harmonics should be checked (values of 5 and above may take very long...)
40#define SH_DEGREE 3
41
42//up to which order coupling matrices shall be computed (values of 5 and above may take very long...)
43#define COUPLING_DEGREE 3
44
45class AssocLegendreTester
46{
47 public:
48 AssocLegendreTester(long l, long m,
49 long lprime, long mprime) : A(l, m), B(lprime, mprime) {}
50
51 double operator()(double x) const
52 {
53 return A(x) * B(x);
54 }
55
56
57 private:
60};
61
62
63class SphericalHarmonicTester
64{
65 public:
66 SphericalHarmonicTester(int l, int m,
67 int lprime, int mprime) : A(l, m), B(lprime, mprime) {}
68
69 double operator()(double theta, double phi) const
70 {
71 return A(theta, phi) * B(theta, phi) * sin(theta);
72 }
73
74
75 private:
78};
79
80
81inline void fuzzy_check(double is, double should, std::string message)
82{
83 const double tol = 1e-7; //tolerance
84 if (!viennashe::testing::fuzzy_equal(is, should, tol)
85 && std::max(std::abs(is), std::abs(should)) > 1e-4)
86 {
87 std::cerr << "Failed at: " << message << std::endl;
88 exit(EXIT_FAILURE);
89 }
90 else
91 {
92 //std::cout << "Success!" << std::endl;
93 }
94}
95
96
97int main()
98{
99 const double pi = 3.1415926535897932384626433832795;
102
103 std::cout << "Test 1: Value of Y_00" << std::endl;
104 fuzzy_check(Y_00(0, 0), 1.0 / sqrt(4.0 * pi), "Value of Y_00" );
105
106 std::cout << "Test 2: Orthonormality of associated Legendre functions up to degree " << LEGENDRE_DEGREE << std::endl;
107 for (long l=0; l <= LEGENDRE_DEGREE; ++l)
108 {
109 for (long m=0; m<=l; ++m)
110 {
111 //checknig fixed second index only
112 for (long lprime=0; lprime <= LEGENDRE_DEGREE; ++lprime)
113 {
114 if (m > lprime)
115 continue;
116
117 std::stringstream ss;
118 ss << "Testing P(" << l << "," << m << ") "
119 << "with P(" << lprime << "," << m << ")" << std::endl;
120
121 double expected_result = 0.0;
122 if (l == lprime)
123 expected_result = 2.0 * viennashe::math::factorial(l+m)
124 / ( (2.0*l + 1.0) * viennashe::math::factorial(l-m) );
125
126 double is_result = viennashe::math::integrate(AssocLegendreTester(l, m, lprime, m),
127 -1.0, 1.0,
128 integration_rule);
129 fuzzy_check(is_result, expected_result, ss.str());
130 } //for lprime
131
132 } //for m
133 } // for l
134
135 std::cout << "Test 3: Orthonormality of Spherical Harmonics up to degree " << SH_DEGREE << std::endl;
136 for (int l=0; l <= SH_DEGREE; ++l)
137 {
138 for (int m=-l; m<=l; ++m)
139 {
140 for (int lprime=0; lprime <= SH_DEGREE; ++lprime)
141 {
142 for (int mprime=-lprime; mprime <= lprime; ++mprime)
143 {
144 std::stringstream ss;
145 ss << "Testing Y(" << l << "," << m << ") "
146 << "with Y(" << lprime << "," << mprime << ")" << std::endl;
147
148 double expected_result = 0.0;
149 if ( (l == lprime) && (m == mprime) )
150 expected_result = 1.0;
151
152 double is_result = viennashe::math::integrate2D(0.0, pi,
153 0.0, 2.0 * pi,
154 SphericalHarmonicTester(l, m, lprime, mprime),
155 integration_rule);
156 fuzzy_check(is_result, expected_result, ss.str());
157 } //for mprime
158 } //for lprime
159 } //for m
160 } // for l
161
162
163
164 std::cout << "Test 4: Coupling matrices up to degree " << COUPLING_DEGREE << " (this might take a while...)" << std::endl;
165 for (int l=0; l <= COUPLING_DEGREE; ++l)
166 {
167 for (int m=-l; m<=l; ++m)
168 {
169 for (int lprime=0; lprime <= COUPLING_DEGREE; ++lprime)
170 {
171 for (int mprime=-lprime; mprime <= lprime; ++mprime)
172 {
173 viennashe::she::vIntegrand_x integrand_a_x(l, m, lprime, mprime);
174 viennashe::she::vIntegrand_y integrand_a_y(l, m, lprime, mprime);
175 viennashe::she::vIntegrand_z integrand_a_z(l, m, lprime, mprime);
176
177 viennashe::she::GammaIntegrand_x integrand_b_x(l, m, lprime, mprime);
178 viennashe::she::GammaIntegrand_y integrand_b_y(l, m, lprime, mprime);
179 viennashe::she::GammaIntegrand_z integrand_b_z(l, m, lprime, mprime);
180
181 double result_a_x = viennashe::math::integrate2D(0.0, pi, 0.0, 2.0 * pi, integrand_a_x, integration_rule);
182 double result_a_y = viennashe::math::integrate2D(0.0, pi, 0.0, 2.0 * pi, integrand_a_y, integration_rule);
183 double result_a_z = viennashe::math::integrate2D(0.0, pi, 0.0, 2.0 * pi, integrand_a_z, integration_rule);
184
185 double result_b_x = viennashe::math::integrate2D(0.0, pi, 0.0, 2.0 * pi, integrand_b_x, integration_rule);
186 double result_b_y = viennashe::math::integrate2D(0.0, pi, 0.0, 2.0 * pi, integrand_b_y, integration_rule);
187 double result_b_z = viennashe::math::integrate2D(0.0, pi, 0.0, 2.0 * pi, integrand_b_z, integration_rule);
188
189 if (std::abs(l - lprime) > 1)
190 {
191 fuzzy_check(result_a_x, 0, "result_a_x");
192 fuzzy_check(result_a_y, 0, "result_a_y");
193 fuzzy_check(result_a_z, 0, "result_a_z");
194
195 fuzzy_check(result_b_x, 0, "result_b_x");
196 fuzzy_check(result_b_y, 0, "result_b_y");
197 fuzzy_check(result_b_z, 0, "result_b_z");
198 }
199
200 } //for mprime
201 } //for lprime
202 } //for m
203 } // for l
204
205
206 std::cout << "*******************************" << std::endl;
207 std::cout << "* Test finished successfully! *" << std::endl;
208 std::cout << "*******************************" << std::endl;
209
210} //main()
211
Associated Legendre polynomial.
Tag for an adaptive integration rule.
Definition: integrator.hpp:58
x-component of the Gamma coupling integral (cf. Dissertation Rupp)
y-component of the Gamma coupling integral (cf. Dissertation Rupp)
z-component of the Gamma coupling integral (cf. Dissertation Rupp)
x-component of the velocity coupling integral \int Y_{l,m} e_r Y_{l',m'} \d \Omega (cf....
y-component of the velocity coupling integral \int Y_{l,m} e_r Y_{l',m'} \d \Omega (cf....
z-component of the velocity coupling integral \int Y_{l,m} e_r Y_{l',m'} \d \Omega (cf....
Provides the SHE coupling matrices and computes higher-order coupling matrices if required....
Implementation of numerical integration routines.
double integrate2D(double a1, double b1, double a2, double b2, T const &func2integrate, IntRuleTag)
Convenience overload for two-dimensional integration.
Definition: integrator.hpp:357
double factorial(long n)
Compute the factorial.
double integrate(T const &f, double a, double b, IntMidPointRule)
Integration of a function using the mid point rule.
Definition: integrator.hpp:118
bool fuzzy_equal(double is, double should, double tol=1e-1)
Performs a fuzzy (up to a tolerance) equal. Returns true if is and should are equal within the tolera...
Definition: common.hpp:39
int main()
Definition: resistor1d-c.c:108
Implementation of spherical harmonics plus helper functions.
Contains common functions, functors and other classes often needed by the tests.