cms.integration.integ_imt のソースコード

import numpy as np
from math import exp, sqrt, pi
# 既存の自作モジュール(パスが通っていることを前提としています)
from integ_gauss_legendre import integ_GL

"""
  井本・森口・高澤 (I.M.T.) 公式を用いた数値積分モジュール。

  概要:
    井本・森口・高澤 (I.M.T.) 公式を実装し、指定された関数を数値積分します。

  詳細説明:
    I.M.T.変換は、積分区間の端点で特異性を持つ関数を、変換によって滑らかな関数にすることで、
    高精度な数値積分を可能にする手法です。
    このモジュールでは、特に`sqrt(1 - x^2)`のような区間端点で微分不可能となる関数に対して、
    ガウス・ルジャンドル積分と組み合わせて使用します。
    モジュールの主要な機能は`main`関数にまとめられており、
    `nblock`の数を変えながら積分の精度を確認することができます。

  関連リンク:
    :doc:`integ_imt_usage`
"""

# define function to be integrated
[ドキュメント] def func(x): """ 被積分関数 sqrt(1 - x^2) を定義します。 概要: 与えられた`x`に対して`sqrt(1 - x*x)`を計算します。 詳細説明: この関数は、積分される対象の具体的な式を表現します。 円の方程式の一部であり、`x`が`[-1, 1]`の範囲で実数を返します。 :param x: float 積分変数の値。 :returns: float `sqrt(1 - x*x)` の計算結果。 """ return sqrt(1.0 - x*x)
# I.M.T. weight constants Q_VAL = 0.00702985840661 # int(exp(-1/t - 1/(1-t)) by Gauss-Legendre method
[ドキュメント] def IMTfunc(x): """ I.M.T.変換における重み関数を生成します。 概要: I.M.T.変換で使用される`exp(-1/x - 1/(1-x)) / Q_VAL`の重み関数を計算します。 詳細説明: この関数は、I.M.T.変換の核となる部分であり、特異点近傍での関数の振る舞いを調整し、 積分区間全体で関数を滑らかにする役割を果たします。 `Q_VAL`は重み関数の正規化定数で、この関数の`[0, 1]`区間での積分値が1になるように調整します。 :param x: float 変換された積分変数の値 (通常は `[0, 1]` の範囲)。 :returns: float I.M.T.重み関数の値。 """ return exp(-1.0 / x - 1.0 / (1.0 - x)) / Q_VAL
#=================== # parameters (Default values) #=================== # Gauss-Legendre integration parameters to convert x to u n_gl_order_def = 5 ngl_def = 10 # Integration parameters xmin_def, xmax_def = -1.0, 1.0 nblock_max_def = 10
[ドキュメント] def main(): """ I.M.T.公式を用いて`sqrt(1 - x^2)`の数値積分を実行し、結果を表示します。 概要: `nblock`の数を変化させながら、I.M.T.公式による数値積分を実行し、 解析解との誤差を比較して表示します。 詳細説明: この関数は、以下のステップで数値積分を行います。 1. パラメータをデフォルト値で初期化します。 2. 解析解と被積分関数`func(x)`の特定点での値を表示します。 3. `nblock`を2から`nblock_max_def`まで増加させながら以下の処理を繰り返します。 a. 積分区間`[0, 1]`を`nblock`個の小区間に分割します。 b. 各小区間において、I.M.T.変換`phi(ui)`によって元の積分変数を求めます。 この`phi(ui)`の計算には、`integ_GL`(ガウス・ルジャンドル積分)を用いて`IMTfunc`を積分します。 c. 変換された積分変数`xi`を用いて`func(xi)`を評価し、`IMTfunc`の重みを乗じて積算します。 d. 最後にスケーリングを行い、数値積分結果`S`と解析解`Fx`との誤差を表示します。 :returns: None """ # パラメータのローカル変数化 n_gl_order = n_gl_order_def ngl = ngl_def xmin, xmax = xmin_def, xmax_def nblock_max = nblock_max_def print("Numerical integration using by IMT formula") fx = func(xmin) # Analytical integration of sqrt(1-x^2) from -1 to 1 is pi/2 Fx = pi / 2.0 print("") print("Analytical values:") print(" f({})={}".format(xmin, fx)) print(" integ(f)[{}, {}]={}".format(xmin, xmax, Fx)) print("") print("nBlock\tS\tError") for nblock in range(2, nblock_max + 1): h = (1.0 - 0.0) / nblock S = 0.0 for i in range(1, nblock): # ui is in the converted range [0, 1] ui = i * h # x' = phi(ui) is in [0,1] phiui = 0.0 for j in range(ngl): hgl = (ui - 0.0) / ngl x0_gl = 0.0 + j * hgl x1_gl = x0_gl + hgl # Gauss-Legendre積分を用いて座標変換を行う phiui += integ_GL(n_gl_order, IMTfunc, x0_gl, x1_gl) # obtain the original x from x' = phi(ui) xi = xmin + (xmax - xmin) * phiui yi = func(xi) phi1 = exp(-1.0 / ui - 1.0 / (1.0 - ui)) / Q_VAL S += yi * phi1 # Final scaling S *= (xmax - xmin) / nblock print("{}\t{}\t{}".format(nblock, S, S - Fx))
if __name__ == "__main__": main()