Skip to content

Commit 5800b64

Browse files
committed
cmath (std::sph_legendre): 球面調和関数と使い方について記述
1 parent 304f099 commit 5800b64

File tree

1 file changed

+67
-4
lines changed

1 file changed

+67
-4
lines changed

reference/cmath/sph_legendre.md

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ namespace std {
4747
4848
4949
## 戻り値
50-
引数 `l`, `m`, `theta` について $Y_l^m(\theta, 0)$ を返す。
50+
引数 `l`, `m`, `theta` について $Y_l^m(\theta, 0)$ (ただし $0 \le m \le l$) を返す。
5151
$Y_l^m(\theta, \phi)$ は球面調和関数
5252
$$
5353
Y_l^m(\theta, \phi) = (-1)^m \sqrt{\frac{2l + 1}{4\pi} \frac{(l - m)!}{(l + m)!}} P_l^m(\cos \theta) \exp(i m \phi)
@@ -56,11 +56,71 @@ $$
5656
である。
5757
$P_l^m$ はルジャンドル陪関数 ([`assoc_legendre`](assoc_legendre.md)) である。
5858
59-
6059
## 備考
6160
- `l >= 128` の場合、この関数の呼び出しの効果は実装定義である
6261
- (1) : C++23では、拡張浮動小数点数型を含む浮動小数点数型へのオーバーロードとして定義された
6362
63+
### 球面調和関数
64+
球面調和関数として使う場合には $\phi$ 依存性は自分で与える必要がある。
65+
また、この標準関数は $m\ge0$ にしか対応していないので、$m < 0$ の時の球面調和関数を計算したければ自分で $Y_l^{|m|}(\theta,0)$ の値を調節して使う必要がある。
66+
ルジャンドル陪関数の性質 $P_l^{-m}(x) = (-1)^m [(l - m)!/(l + m)!] P_l^m(x)$ より、一般の $m$ の球面調和関数は
67+
$$
68+
\begin{align*}
69+
Y_l^m(\theta, \phi)
70+
&= (-1)^{(m+|m|)/2} \sqrt{\frac{2l + 1}{4\pi} \frac{(l - |m|)!}{(l + |m|)!}} P_l^{|m|}(\cos \theta) e^{i m \phi} \\
71+
&= \begin{cases}
72+
Y_l^{m}(\theta, 0) e^{im\phi}, & (0 \le m \le l), \\
73+
(-1)^{|m|} Y_l^{|m|}(\theta, 0) e^{im\phi}, & (-l \le m < 0).
74+
\end{cases}
75+
\end{align*}
76+
$$
77+
で与えられる。
78+
79+
```cpp
80+
#include <cmath>
81+
#include <complex>
82+
#include <numbers>
83+
84+
// 球面調和関数の実装例
85+
std::complex<double> sph_harmonics(unsigned l, int m, double theta, double phi) {
86+
if (m >= 0)
87+
return std::sph_legendre(l, (unsigned) m, theta) * std::polar(1.0, m * phi);
88+
else
89+
return std::sph_legendre(l, (unsigned) -m, theta) * std::polar(1.0, m * (phi - std::numbers::pi));
90+
}
91+
```
92+
* std::sph_legendre[color ff0000]
93+
* std::polar[link /reference/complex/complex/polar.md]
94+
* std::numbers::pi[link /reference/numbers/pi.md]
95+
96+
また線形結合を取り直して実数にした、実数球面調和関数 $Y_{lm}(\theta,\phi)$ を計算することもできる。
97+
98+
$$
99+
Y_{lm}(\theta,\phi)
100+
= \begin{cases}
101+
\frac{(-1)^m Y_l^{|m|}(\theta,\phi) - Y_l^{-|m|}(\theta,\phi)}{\sqrt{2} i} = \sqrt{2} (-1)^{|m|} Y_l^{|m|}(\theta, 0) \sin(|m|\phi), & (-l \le m < 0), \\
102+
Y_l^0 = Y_l^0(\theta, 0), & (m = 0), \\
103+
\frac{(-1)^m Y_l^{|m|}(\theta,\phi) + Y_l^{-|m|}(\theta,\phi)}{\sqrt{2}} = \sqrt{2} (-1)^{|m|} Y_l^{|m|}(\theta, 0) \cos(|m|\phi), & (0 < m \le l).
104+
\end{cases}
105+
$$
106+
107+
```cpp
108+
#include <cmath>
109+
#include <numbers>
110+
111+
// 実数球面調和関数の実装例
112+
double real_sph_harmonics(unsigned l, int m, double theta, double phi) {
113+
if (m == 0)
114+
return std::sph_legendre(l, 0u, theta);
115+
else if (m > 0)
116+
return std::numbers::sqrt2 * std::sph_legendre(l, (unsigned) m, theta) * std::cos(m * (phi - std::numbers::pi));
117+
else
118+
return std::numbers::sqrt2 * std::sph_legendre(l, (unsigned) -m, theta) * std::sin(-m * (phi - std::numbers::pi));
119+
}
120+
```
121+
* std::sph_legendre[color ff0000]
122+
* std::numbers::pi[link /reference/numbers/pi.md]
123+
* std::numbers::sqrt2[link /reference/numbers/sqrt2.md]
64124
65125
## 例
66126
```cpp example
@@ -71,8 +131,11 @@ $P_l^m$ はルジャンドル陪関数 ([`assoc_legendre`](assoc_legendre.md))
71131
constexpr double pi = 3.141592653589793;
72132
73133
// 球面調和関数
74-
std::complex<double> sph_harmonics(unsigned l, unsigned m, double theta, double phi) {
75-
return std::sph_legendre(l, m, theta) * std::polar(1.0, m * phi);
134+
std::complex<double> sph_harmonics(unsigned l, int m, double theta, double phi) {
135+
if (m >= 0)
136+
return std::sph_legendre(l, (unsigned) m, theta) * std::polar(1.0, m * phi);
137+
else
138+
return std::sph_legendre(l, (unsigned) -m, theta) * std::polar(1.0, m * (phi - std::numbers::pi));
76139
}
77140
78141
int main() {

0 commit comments

Comments
 (0)