分子の入力#

Part III — ユーザーガイドへようこそ。Part I・II でインストールと理論を済ませました;ここからは、実際に使う のと同じく機能ごとに進めます。あらゆる計算は同じ場所から始まります:分子を記述すること。本章はその最初の 一歩 — 何を計算するのかを qc-rs にどう伝え、それが正しく理解されたかをどう確認するか — についてです。

理論:量子化学計算にとって分子を定めるものは何か#

Part IIBorn–Oppenheimer 近似に出会いました:核は電子より はるかに重いのでその場に固定し、核が作る場の中で電子問題を解く、というものです。この 1 つの考えが、計算の 入力に必要なものを正確に決めます。3 つ、それだけです:

  1. 核配置(構造) — どの原子がどこにあるか。核は固定なので、その位置 \(\{\mathbf R_A\}\) はあなたが与える固定 値です。これが電子の動く外部ポテンシャル \(v_{\text{ext}}(\mathbf r) = -\sum_A Z_A / |\mathbf r - \mathbf R_A|\) と、電子エネルギーに加わる定数の 核間反発 \(E_{\text{nuc}} = \sum_{A<B} Z_A Z_B / R_{AB}\) を決めます。

  2. 全電荷 — 電子が何個あるか。中性分子は \(N_e = \sum_A Z_A\) 個の電子を持ち、電荷 \(q\) はそれを取り除く (\(q>0\))または加えます(\(q<0\))。これが SCF の詰める数 \(N_e\) を決めます。

  3. スピン状態 — それらの電子スピンの並び方。多重度 \(2S+1\) で与えます。

それ以外 — 基底関数、手法、収束設定 — はすべて問題をどう解くかの選択です。構造・電荷・スピンは問題そのもの。 qc-rs ではこの 3 つを qc.chk.new(...) に渡し、中核概念チェックポイントを作ります。

定義 3 (スピン多重度)

全スピン量子数 \(S\) の状態について、多重度\(2S+1\)\(M_S\) 射影(\(-S, \dots, +S\))の数です。不対電子は それぞれスピン \(\tfrac12\) を与えるので、不対電子 \(n\) 個では \(S = n/2\)、多重度は \(n+1\):

不対電子 \(n\)

\(S\)

多重度 \(2S+1\)

名称

0

0

1

一重項(singlet)

1

½

2

二重項(doublet)

2

1

3

三重項(triplet)

これは Gaussian の慣習で、qc-rs の spin= が期待するものです — 閉殻一重項なら spin=1、ラジカルなら spin=2、三重項なら spin=3 を渡します。

使い方:atom= 文字列#

構造は atom= 引数で記述します — 1 行 1 原子の文字列で、各行は元素ラベルに続けて 3 つのデカルト座標:

Element   x   y   z

原子は改行またはセミコロン ; で区切ります。だから次の 2 つは同じ水分子です:

import qc

# セミコロン区切り(コンパクト、ワンライナー向き)
w1 = qc.chk.new(atom="O 0 0 0; H 0 0.757 0.587; H 0 -0.757 0.587", ao="sto-3g")

# 改行区切り(読みやすい、実際の分子向き)— 三重引用符文字列
w2 = qc.chk.new(atom="""
    O   0.000   0.000   0.117
    H   0.000   0.757  -0.469
    H   0.000  -0.757  -0.469
""", ao="sto-3g")

元素ラベルは、化学記号(H, C, Fe — 大文字小文字を区別しない)、原子番号6 は炭素)、または 同一種の原子を区別するラベル接尾辞つき記号(C1, C2, Fe3)が使えます。ラベルは、後で特定の 1 原子に 独自の基底関数を与えたいときに効きます — 基底関数と AO 表現 参照。

Tip

Python メモ:三重引用符文字列 """… """複数行文字列です。実際の構造を書く自然な方法 — 入力ファイルのように 1 行 1 原子で列を揃える — です。先頭/末尾の空行やインデントは問題ありません;qc-rs は無視します。

単位:オングストロームまたはボーア#

座標は既定でオングストロームunit="angstrom")です。原子単位で与えるなら unit="bohr" を設定します:

# これらは*同じ* H2 分子(結合長 ≈ 0.741 Å ≈ 1.400 bohr)
h2_ang  = qc.chk.new(atom="H 0 0 0; H 0 0 0.741", ao="sto-3g", unit="angstrom")
h2_bohr = qc.chk.new(atom="H 0 0 0; H 0 0 1.400", ao="sto-3g", unit="bohr")

内部では qc-rs は座標を常にボーア(原子単位)で保持し、入力時に唯一の定数 \(\text{1 Å} = 1/0.52917721092 \approx 1.8897\) bohr で変換します。だから下の coordinates() アクセサは、あなたが どの単位で打っても常にボーアで返します。

重要

既定はオングストローム — ボーアと思い込まない PDB ファイル・論文・多くの GUI からコピーした構造はオングストロームなので、既定でたいてい正解です。しかし 原子単位の座標を貼って unit="bohr" を忘れると、すべての結合が約 1.9 倍長くなり、計算は無意味になります(または 収束しません)。迷ったら coordinates() で確認してください。

電荷とスピン#

charge=spin= は既定で中性一重項charge=0, spin=1)です。イオンや開殻種では変更します。例えば中性の ヒドロキシルラジカル OH は電子 9 個 — 奇数なので一重項にはなれず、二重項(spin=2)です:

oh = qc.chk.new(atom="O 0 0 0; H 0 0 0.97", ao="sto-3g", unit="angstrom",
                charge=0, spin=2)          # 中性の二重項ラジカル
print(oh.nelectron(), oh.spin)             # 9 2

例 1 (電荷とスピンの選び方)

  • H₂O — 中性、全電子対 → charge=0, spin=1

  • 水酸化物イオン OH⁻ — 電子 1 個追加 → charge=-1, spin=1(10 電子、閉殻)。

  • メチルラジカル CH₃ — 中性で不対電子 1 個 → charge=0, spin=2

  • 二酸素 O₂ — 基底状態は三重項(不対電子 2 個)→ charge=0, spin=3

手早い確認:電子数と多重度のパリティ(偶奇)は整合していなければなりません。偶数の電子数は二重項になれず、奇数は 一重項になれません。矛盾すれば run() がその状態を拒否します。

qc-rs が解釈した内容を確認する#

重い計算を走らせる前に、チェックポイントが何を理解したかを見てください。単位ミス・電子数の誤り・打ち間違いを 即座に捕まえられます。関連アクセサ(プロパティのものとメソッドのものがある — () に注意):

w = qc.chk.new(atom="O 0 0 0; H 0 0.757 0.587; H 0 -0.757 0.587", ao="sto-3g", unit="angstrom")

w.natom               # 3          — (実 + ゴースト)原子数
w.symbols             # ['O','H','H']
w.charge, w.spin      # (0, 1)
w.nelectron()         # 10         — SCF が詰める電子数
w.coordinates()       # (3, 3) 配列、常にボーア
w.nuclear_energy()    # 9.188258   — E_nuc(hartree)、電子エネルギーに加わる定数

これが分子指定の全体で、そのまま返ってきます。nelectron()nuclear_energy() がおかしければ、入力を 直してください — 下流のすべての数値がこれに依存します。

特殊原子#

通常の原子に加え、atom= 文法は 3 種の特殊原子をサポートします。日常作業では不要ですが、いくつかの重要な手法に 不可欠です。

ゴースト原子(Element-Bq)— カウンターポイズ / BSSE 用#

ゴースト原子Element-Bq(例 O-Bq, H-Bq)と書き、その元素の基底関数だけを持ち、核も電子も持たない 点です — 核電荷 0、電子 0、核間反発 0。目的は基底関数重ね合わせ誤差(BSSE)カウンターポイズ補正です: 2 分子が近づくと、各々が相手の基底関数を借りてエネルギーが不自然に下がります。この人工効果を測るには、片方の 単量体を相手の基底をゴーストとして置いて再計算します:

# 単量体を「二量体の完全な基底」で計算:相手の原子をゴーストにする
mono = qc.chk.new(atom="O 0 0 0; H 0 0 1.8; H-Bq 0 0 3.5", ao="sto-3g", unit="bohr")
print(mono.natom, mono.nelectron())     # 3 9   — ゴーストは原子として数えるが、電子は加えない

ゴーストは natom数えられますが(AO 関数を持つため)、nelectron()nuclear_energy() には何も 寄与しません。ゴーストの基底はまずラベルで、次に基底元素で引かれるので、H-Bq は自動的に H の基底を継承します (詳細は 基底関数と AO 表現)。

ダミー原子(X, Xx)— 幾何学的参照点#

ダミー原子X, Xx、またはラベル付き X1, X-ref)は純粋な幾何マーカーです:核電荷なし、電子なし、 基底関数もなし。物理的なものを何も加えずに参照できる座標(例:対称軸や測定点の定義)です:

d = qc.chk.new(atom="C 0 0 0; H 0 0 1.089; X 0 0 5.0", ao="sto-3g", unit="angstrom")
print(d.natom, d.nelectron())     # 2 7   — ダミーは数えられず、何も加えない

ゴーストと違い、ダミーは natom数えられません;dummy_atoms() に格納されます。

並進ベクトル(TV)— 周期系#

TV で始まる行は、周期系の格子並進ベクトルを与えます(ポリマーは 1 本、シートは 2 本、結晶は 3 本)。 translation_vectors() に格納され、ダミー同様、原子として数えられません:

poly = qc.chk.new(atom="""
    C  -0.574 -0.143  0.376
    C   0.579  0.022 -0.301
    TV  4.848  0.171  0.511
""", ao="sto-3g", unit="angstrom")

発展:原子ごとの核パラメータ#

原子ラベルの後の括弧内に核パラメータを付けられます — 最もよく使うのは同位体Iso=)とフラグメント 番号Fragment=、カウンターポイズ計算で原子をグループ化するのに使う)です:

# ¹³C 同位体置換体、原子を 2 フラグメントにタグ付け
m = qc.chk.new(atom="C(Iso=13,Fragment=1) 0 0 0; H(Fragment=1) 0 0 1.089",
               ao="sto-3g", unit="angstrom")

全体(Iso, Spin, ZNuc, ZEff, QMom, NMagM, RadNuclear, Fragment, …)、MM 力場フィールド、 オプティマイザのフリーズコードは、リファレンス章 分子指定 に記載しています。 これらメタデータの多くは解析・保存されますが、まだハミルトニアンやオプティマイザには影響しません — どのフィールド が現在有効かはリファレンスに注記があります。

注釈

受け付けられないもの qc-rs は分子構造を上記文法の文字列として受け取ります。(他のパッケージが受け付けるような)Python の タプルのリストは、有効な atom= の値ではありません — 文字列形式を使ってください。また名前による自動 構造取得はありません:座標は常に自分で与えます(または後で .opt() で最適化します)。

総合例:作って、確認して、SCF へ渡す#

まとめて — 水を記述し、確認し、計算の準備を整えます:

import qc

water = qc.chk.new(
    atom="""
        O   0.000000   0.000000   0.117300
        H   0.000000   0.757200  -0.469200
        H   0.000000  -0.757200  -0.469200
    """,
    ao="cc-pvdz",
    unit="angstrom",
    charge=0,
    spin=1,
)

# --- 何か作業する前の健全性チェック ---
print("atoms     :", water.natom, water.symbols)   # 3 ['O', 'H', 'H']
print("electrons :", water.nelectron())            # 10
print("E_nuc     :", round(water.nuclear_energy(), 6))

# 計算の準備完了 — チェックポイントがこれを以降の全ステップへ運ぶ
water = water.scf(ref="r").run()
print("E(RHF)    :", round(water.scf.energy, 6))   # -76.026772

これで分子は完全に指定され、チェックポイントがそれを後続の各ステップ — 基底関数(次章)、SCF、物性、勾配 — へ 運びます。ここで入力を正しく確認しておけば、下流のすべてが盤石の上に立ちます。

練習 1

次の各化学種について qc.chk.new(...) の呼び出しを書き、nelectron()spin を確認しなさい:

  1. アンモニウムカチオン NH₄⁺(中性 NH₄ なら電子 11 個)。

  2. 基底状態の酸素分子 O₂(結合長 1.208 Å)、正しいスピンを含めて

  3. ヘリウム二量体の基底で計算したヘリウム原子(2 つ目の He は 3 Å 離れたゴースト)。

分子が定義できたら、次の選択はその軌道をどう展開するか — 基底関数です。それが 次章 です。