• Class / Function / Type

      std::
    • Header file

      <>
    • Other / All

    最終更新日時(UTC):
    が更新

    履歴 編集

    function
    <cmath>

    std::sph_legendre

    namespace std {
      double
        sph_legendre(unsigned int l,
                     unsigned int m,
                     double theta);               // (1) C++17
      floating-point-type
        sph_legendre(unsigned int l,
                     unsigned int m,
                     floating-point-type theta);  // (1) C++23
    
      Promoted
        sph_legendre(unsigned int l,
                     unsigned int m,
                     Arithmetic theta);           // (2) C++17
    
      float
        sph_legendref(unsigned int l,
                      unsigned int m,
                      float theta);               // (3) C++17
    
      long double
        sph_legendrel(unsigned int l,
                      unsigned int m,
                      long double theta);         // (4) C++17
    }
    

    概要

    球面調和関数 (spherical harmonic function) の θ 成分を求める。

    戻り値

    引数 l, m, theta について Ylm(θ,0) (ただし 0ml) を返す。 Ylm(θ,ϕ) は球面調和関数 Ylm(θ,ϕ)=(1)m2l+14π(lm)!(l+m)!Plm(cosθ)exp(imϕ)for |m|l である。 Plm はルジャンドル陪関数 (assoc_legendre) である。

    備考

    球面調和関数

    球面調和関数として使う場合には ϕ 依存性は自分で与える必要がある。 また、この標準関数は m0 にしか対応していないので、m<0 の時の球面調和関数を計算したければ自分で Yl|m|(θ,0) の値を調節して使う必要がある。 ルジャンドル陪関数の性質 Plm(x)=(1)m[(lm)!/(l+m)!]Plm(x) より、一般の m の球面調和関数は Ylm(θ,ϕ)=(1)(m+|m|)/22l+14π(l|m|)!(l+|m|)!Pl|m|(cosθ)eimϕ={Ylm(θ,0)eimϕ,(0ml),(1)|m|Yl|m|(θ,0)eimϕ,(lm<0). で与えられる。

    #include <cmath>
    #include <complex>
    #include <numbers>
    
    // 球面調和関数の実装例
    std::complex<double> sph_harmonics(unsigned l, int m, double theta, double phi) {
      if (m >= 0)
        return std::sph_legendre(l, (unsigned) m, theta) * std::polar(1.0, m * phi);
      else
        return std::sph_legendre(l, (unsigned) -m, theta) * std::polar(1.0, m * (phi - std::numbers::pi));
    }
    

    また線形結合を取り直して実数にした、実数球面調和関数 Ylm(θ,ϕ) を計算することもできる。

    Ylm(θ,ϕ)={(1)mYl|m|(θ,ϕ)Yl|m|(θ,ϕ)2i=2(1)|m|Yl|m|(θ,0)sin(|m|ϕ),(lm<0),Yl0=Yl0(θ,0),(m=0),(1)mYl|m|(θ,ϕ)+Yl|m|(θ,ϕ)2=2(1)|m|Yl|m|(θ,0)cos(|m|ϕ),(0<ml).

    #include <cmath>
    #include <numbers>
    
    // 実数球面調和関数の実装例
    double real_sph_harmonics(unsigned l, int m, double theta, double phi) {
      if (m == 0)
        return std::sph_legendre(l, 0u, theta);
      else if (m > 0)
        return std::numbers::sqrt2 * std::sph_legendre(l, (unsigned) m, theta) * std::cos(m * (phi - std::numbers::pi));
      else
        return std::numbers::sqrt2 * std::sph_legendre(l, (unsigned) -m, theta) * std::sin(-m * (phi - std::numbers::pi));
    }
    

    #include <cmath>
    #include <complex>
    #include <numbers>
    #include <iostream>
    
    // 球面調和関数
    std::complex<double> sph_harmonics(unsigned l, int m, double theta, double phi) {
      if (m >= 0)
        return std::sph_legendre(l, (unsigned) m, theta) * std::polar(1.0, m * phi);
      else
        return std::sph_legendre(l, (unsigned) -m, theta) * std::polar(1.0, m * (phi - std::numbers::pi));
    }
    
    int main() {
      constexpr unsigned l = 1;
      constexpr unsigned m = 1;
      // Y_1^1(θ, φ) = - sqrt(3 / 8π) |sin θ| exp(iφ)
    
      std::cout << "#θ / π\tφ / π\tY_" << l << "^" << m << "(θ, φ)\n";
      for (double t : {0., 0.25, 0.5, 0.75, 1.}) {
        double theta = t * std::numbers::pi;
        for (double p : {0., 0.25, 0.5, 0.75, 1., 1.25, 1.5, 1.75, 2.}) {
          double phi = p * std::numbers::pi / 4;
          std::cout << t << "\t" << p << "\t" << sph_harmonics(l, m, theta, phi) << "\n";
          if (t == 0 || t == 1) break;
        }
      }
    }
    

    出力例

    #θ / π  φ / π   Y_1^1(θ, φ)
    0   0   (0,0)
    0.25    0   (-0.244301,-0)
    0.25    0.25    (-0.239607,-0.0476608)
    0.25    0.5 (-0.225705,-0.09349)
    0.25    0.75    (-0.203129,-0.135727)
    0.25    1   (-0.172747,-0.172747)
    0.25    1.25    (-0.135727,-0.203129)
    0.25    1.5 (-0.09349,-0.225705)
    0.25    1.75    (-0.0476608,-0.239607)
    0.25    2   (-1.49591e-17,-0.244301)
    0.5 0   (-0.345494,-0)
    0.5 0.25    (-0.338856,-0.0674026)
    0.5 0.5 (-0.319195,-0.132215)
    0.5 0.75    (-0.287268,-0.191946)
    0.5 1   (-0.244301,-0.244301)
    0.5 1.25    (-0.191946,-0.287268)
    0.5 1.5 (-0.132215,-0.319195)
    0.5 1.75    (-0.0674026,-0.338856)
    0.5 2   (-2.11554e-17,-0.345494)
    0.75    0   (-0.244301,-0)
    0.75    0.25    (-0.239607,-0.0476608)
    0.75    0.5 (-0.225705,-0.09349)
    0.75    0.75    (-0.203129,-0.135727)
    0.75    1   (-0.172747,-0.172747)
    0.75    1.25    (-0.135727,-0.203129)
    0.75    1.5 (-0.09349,-0.225705)
    0.75    1.75    (-0.0476608,-0.239607)
    0.75    2   (-1.49591e-17,-0.244301)
    1   0   (0,0)
    

    バージョン

    言語

    • C++17

    処理系

    備考

    GCC (libstdc++)

    GCC 7.1.0–8.0.0 では l < m の場合 (Ylm=0) std::domain_error を送出する。

    関連項目

    参照