stastical_physics.plotW のソースコード

"""
配置の数 W(ni) の分布と熱力学的極限への収束を可視化するスクリプト。

概要:
    総要素数 $N$ のうち、特定の状態に属する要素数が $ni$ である場合の組み合わせ(配置の数) $W(ni)$ を計算し、
    システムサイズ $N$ による分布の変化をプロットします。

詳細説明:
    - 配置の数 $W = {}_N C_{ni}$ を計算します。
    - 大きな $N$ を扱うため、スターリングの近似 $\ln N! \approx N \ln N - N$ を用いて計算を行います。
    - 各 $N$ において最大値($ni = N/2$)で正規化し、相対的な確率分布として表示します。
    - $N$ が増大するにつれて、$ni/N = 0.5$ 付近の分布がいかに鋭くなるか(相対的な揺らぎの減少)を確認できます。
    - これは、多粒子系においてマクロな物理量が一点に定まる「熱力学的極限」を数学的に示唆します。

理論式:
    $$\ln W(ni) \approx N \ln N - ni \ln ni - (N-ni) \ln (N-ni)$$

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

import matplotlib.pyplot as plt
import numpy as np
from numpy import log, exp, sqrt

[ドキュメント] def calculate_normalized_W(N, ni_array): """ 総要素数 N における特定の状態の要素数 ni に対する組み合わせの数 W を計算します。 最大値で正規化した値を返します。 :param N: float: 総要素数。 :param ni_array: np.ndarray: 評価する要素数 ni の配列。 :returns: list: 正規化された配置の数 W/Wmax。 """ # スターリングの近似を用いた ln(W_max) の計算 (ni = N/2 のとき) lnW_max = N * log(N) - 2.0 * (N / 2.0) * log(N / 2.0) W_list = [] for ni in ni_array: # ln(ni!) の項 ni_term = ni * log(ni) if ni > 0 else 0 # ln((N-ni)!) の項 Nni_term = (N - ni) * log(N - ni) if (N - ni) > 0 else 0 # Wmaxで規格化した ln(W/Wmax) lnW_rel = N * log(N) - ni_term - Nni_term - lnW_max W_list.append(exp(lnW_rel)) return W_list
[ドキュメント] def main(): """ 異なる N に対して W(ni) を計算し、グラフを生成・保存します。 """ # Nの値のリスト (5から始まり、倍々で増やす) N_values = [5.0 * 2**i for i in range(0, 32, 4)] fig, ax = plt.subplots(figsize=(10, 7)) for N in N_values: # 分布の中心付近を重点的に計算するための範囲設定 N_avg = N * 0.5 Nrange = 6.0 * sqrt(N) # 数値的に安定した範囲で ni を生成 ni_min = max([1.0, N_avg - Nrange]) ni_max = N_avg + Nrange log_ni = np.linspace(log(ni_min), log(ni_max), 500) ni_array = exp(log_ni) # 配置の数の計算 W_vals = calculate_normalized_W(N, ni_array) x_vals = ni_array / N ax.plot(x_vals, W_vals, label=f'N = {N:.1e}', linewidth=1.5) # グラフの装飾 ax.set_title('Normalized Number of Configurations ($W/W_{max}$)', fontsize=16) ax.set_xlabel('$n_i / N$ (Occupancy Ratio)', fontsize=14) ax.set_ylabel('$W(n_i) / W_{max}$', fontsize=14) # 物理的に意味のある範囲(0.5付近の収束を見るため) ax.set_xlim([0.1, 1.0]) ax.set_xscale('log') ax.legend(title='System Size N', fontsize=10) ax.grid(True, which='both', linestyle='--', alpha=0.5) plt.tight_layout() # 画像の保存 save_path = 'plotW.png' plt.savefig(save_path, dpi=300) print(f"Graph saved as {save_path}") plt.show(block=False) input("Press ENTER to terminate>>")
if __name__ == "__main__": main()