# 外部エンジン連携と経路緩和

IRC、履歴保存・再開、モデル常駐・キュー、内部座標拘束・スキャン、自動ノード追加、診断、熱化学、構造比較の操作と計算上の条件は[反応経路・計算管理・解析](../RESEARCH.md)にまとめています。

Molecule Studioの「外部エンジン / 経路緩和」から、このPCで動く **tblite / g-xTB / UMA** を利用できます。ユーザーが起動した `bridge.py` が計算を仲介します。GitHub Pagesに計算サーバーや座標をアップロードする必要はありません。

## UMA（fairchem-core）の導入と設定

この接続は**非周期分子のomolタスク**を対象にします。材料・表面用のomat/oc20等へ自動的に切り替えることはありません。エネルギー・力の評価、MIN、一括MIN、AFIR-MIN、CI-NEB、Sella TS、ASE振動解析を同じUMAポテンシャルで実行します。原子固定はMIN/AFIR-MINで使用できます。入力上限は500原子・100構造・Z=83、多重度1〜100です。これは入力範囲であり、その全範囲でのモデル精度を保証するものではありません。

1. [facebook/UMA](https://huggingface.co/facebook/UMA)で利用条件を確認し、モデルへのアクセス承認を取得します。
2. Linux / WSL2のPython 3.12専用環境で、次を実行します（Windowsネイティブでの動作確認は未実施）。

```bash
python3.12 -m venv .venv-uma
source .venv-uma/bin/activate
python -m pip install --upgrade pip
python -m pip install "fairchem-core>=2.23,<3" "psutil>=5.9,<8" huggingface_hub
hf auth login
python bridge.py --engine uma --uma-model uma-s-1p2p1 --uma-device cpu --uma-precision float64 --allow-origin https://h-nabata.github.io
```

3. 起動時のURLとbridgeのTokenをページへ入力し「接続を確認」を押します。モデル・omol・デバイス・精度の表示を確認し、電荷と多重度を指定して計算します。**Hugging Faceのトークンは端末の認証専用**です。ページの接続Token欄へ貼り付けないでください。

| 起動引数 | 設定 |
|---|---|
| `--uma-model` | `uma-s-1p2p1`（既定）、`uma-s-1p2`、`uma-s-1p1`、`uma-m-1p1` |
| `--uma-device` | `cpu`（既定）/ `cuda:0` / `cuda:1` 等（`cuda` は `cuda:0`）。画面からも選択できます。CUDAは対応GPU・ドライバー・PyTorchが必要。使用不可なら起動時にエラーとし、CPUへ黙って切り替えません。 |
| `--uma-precision` | `float64`（既定）/ `float32`。TS・微小変位の振動解析ではfloat64を推奨。float32はメモリ・計算時間を抑える選択肢。 |
| `--threads` | CPUスレッド数（既定1）。PyTorchにも設定します。 |
| `--job-timeout` | モデル読み込みを含む1ジョブの上限秒数。既定1800。初回取得が長い場合は例：`--job-timeout 7200`。 |

UMAには`--method`（GFN法）や`--binary`（g-xTB実行ファイル）を指定できません。SCF反復・電子温度・暗黙溶媒の設定も流用しません。`--evaluation-timeout`はg-xTB専用で、UMAはジョブ全体の時間上限と中止処理を使います。Sellaは必要な場合に同じ環境へ `python -m pip install "sella>=2.6,<3"` で追加します。

計算実行時にモデルを読み込みます。「接続を確認」の成功はモデル取得・推論の成功を意味しません。UMA／AnySolvは同じモデル・デバイス・精度のジョブ間で常駐し、一括MINでも再利用します。分子の元素、電荷、多重度、溶媒、ASEの状態はジョブごとに更新します。モデル条件が変わった場合、中止・失敗時、サービス終了時にはプロセスを終了します。「計算履歴 / キュー」の解放ボタン、または `--no-resident-models` でもメモリを解放できます。通常 `~/.cache/fairchem` に重みのキャッシュが残り、認証情報はHugging Faceのローカル設定に保存されます。計算座標や結果はHugging Faceへ送信しません。各評価の一時ファイルはジョブ終了時に削除し、計算履歴は後述の保存先へ残します。

`FAIRChemCalculator(predictor, task_name="omol")`を使用し、`atoms.info['charge']`へ全電荷、`atoms.info['spin']`へ**2S+1の多重度**を渡します。g-xTBの`--uhf`の値（2S）とは異なります。ASEの出力は既にeV・eV/ÅなのでHartree/Bohr変換を行いません。conservative UMAモデルのみを選択肢とし、`InferenceSettings(tf32=False, compile=False, merge_mole=False, execution_mode='general', base_precision_dtype=...)`を明示します。ジョブ種別によって精度を自動変更せず、MINからCI-NEB・TS・振動解析まで同じ設定を使用します。

結果JSONにはモデル名・task・device・精度・推論設定・fairchem-core/PyTorchの版を記録します。UMAは学習済みポテンシャルの予測で、DFTのSCFを実行するわけではありません。モデルやタスクが異なるエネルギー、tblite/g-xTBの絶対エネルギーとは直接比較しないでください。未知の構造や反応に対する精度・TSの妥当性は別途検証が必要です。

接続エラー時は利用承認、同じ環境での`hf auth login`、PyTorchの導入、モデルキャッシュを確認してください。上流のHTTP例外に含まれる認証情報やURLはページへ返しません。メモリ不足は中止として扱い、構造が得られていれば既存の途中結果保存を使います。

実装参照：[公式導入手順](https://facebookresearch.github.io/fairchem/install/)、[omolの電荷・多重度](https://facebookresearch.github.io/fairchem/quickstart/)、[推論設定・精度](https://facebookresearch.github.io/fairchem/ase-calculator/)、[モデル一覧](https://huggingface.co/facebook/UMA)。配布版fairchem-core 2.23.0のAPIを確認しました。検証範囲は[AFIR-VALIDATION.md](../AFIR-VALIDATION.md)を参照してください。

## AnySolvの溶媒補正をUMAに追加する

UMA用環境へ `python -m pip install "anysolv[ase,hub]==0.1.0"` で追加し、保存したbridge.pyで起動します。

```bash
python bridge.py --engine uma --uma-device cuda:0 --anysolv --anysolv-device cuda:1 --allow-origin https://h-nabata.github.io
```

2枚のGPUがある場合の例です。CPUを使う場合は両方のデバイス指定を `cpu` にします。接続後、「AnySolvで溶媒補正する」をオンにし、溶媒・モデル・各モデルの実行デバイスを選びます。補正は既定オフ。設定はMIN、一括MIN、AFIR、CI-NEB、TS、振動解析で共通です。AFIR欄にも選択中の溶媒を表示します。

- **Compact**（`model_compact`）：軽量モデル。パッケージ同梱で、最初の選択です。
- **MoE**（`model_moe`）：大規模モデル。配布元 [antonknee/anysolv](https://huggingface.co/antonknee/anysolv) の利用条件を確認し、必要な承認を取得してください。bridgeは承認操作や暗黙のモデル変更を行いません。

```bash
hf auth login
hf download antonknee/anysolv model_moe.pt --local-dir ./anysolv-weights
python bridge.py --engine uma --uma-device cuda:0 --anysolv --anysolv-model model_moe --anysolv-checkpoint /absolute/path/to/anysolv-weights/model_moe.pt --anysolv-device cuda:1 --allow-origin https://h-nabata.github.io
```

`--anysolv-checkpoint` は指定モデルのローカル絶対パスです。ブラウザから任意のファイルパスは受け付けません。導入済みのモデルだけが選択肢に出ます。溶媒はインストール済みAnySolvの公式溶媒表から選択し、入力ミスを気相として扱いません。対応する溶媒すべてが同等の学習・検証範囲という意味ではありません。

UMAはジョブプロセス、AnySolvは独立した常駐子プロセスで読み込みます。各プロセスでPyTorchの読み込み前に `CUDA_VISIBLE_DEVICES` を設定し、内部では1枚のGPUとして使います。画面の `cuda:N` はbridge起動時に見えているGPUの番号です。起動環境ですでにマスクしている場合は、その番号・UUID対応を維持します。同じGPUも選べますが2モデル分のVRAMが必要です。AnySolvの評価を先に送信し、その間にUMAを評価します。CPU配列に戻したエネルギーと力を加算するので、GPUをまたぐ自動微分は不要です。

物理ポテンシャルは `Ephysical = EUMA + ΔEsolv`、力は `Fphysical = FUMA + ΔFsolv`（`F = −∇E`）。座標・原子順・総電荷・スピン多重度を両モデルで共有します。AFIRはこの物理ポテンシャルに人工項を別途加えます。AnySolv補正だけをNEBの力から省くことはありません。ASEの拘束は加算後の力へ適用されます。

両モデルの精度は `--uma-precision`（既定float64）で統一。AnySolvはreference `default`（general、TF32・compile・MoE merge無効）を使い、TSや有限差分解析でも同じ設定を維持します。これはSMD由来の学習された溶媒補正であり、温度・エントロピー・標準状態補正をすべて含む反応自由エネルギーではありません。溶媒やモデルを変えたエネルギーは区別して扱ってください。

JSONの `energies` は溶媒補正込みです。`energyComponents.uma` と `energyComponents.solvation` に同じフレームの内訳を保存し、MIN/TS履歴にも付けます。結果表のエネルギーにカーソルを置くと内訳を確認できます。`provenance` は溶媒・モデル・選択GPU・精度・AnySolv版・モデルSHA256を含みます。認証情報・モデルのパスは結果へ出しません。補正モデルの失敗時は停止し、完成済みの評価だけを途中結果として残します。中止・タイムアウト時は両モデルのプロセスを終了します。AnySolvの重みはパッケージ内または指定したダウンロード先に残り、各ジョブの中間データは一時フォルダーとともに削除します。

参照：[AnySolv公式コード・導入例](https://github.com/Ant-on-knee/anysolv)、[エネルギー・力API](https://github.com/Ant-on-knee/anysolv/blob/main/predict.py)。実GPU2枚での検証範囲は [AFIR-VALIDATION.md](../AFIR-VALIDATION.md) に記載します。

## 1. tblite / g-xTBの導入

Python 3.10以上を使用します。[bridge.py](./bridge.py) を保存してください。以下の手順はbridge.pyだけをダウンロードした場合にも使えます。[requirements.txt](./requirements.txt) は基本パッケージ（numpy・ase・psutil）の一覧で、tbliteは含みません。

### 計算エンジンを選ぶ

使いたい計算エンジンを選んで導入します。UMAは後述の専用環境を使用してください。

| 起動時の指定 | 計算手法 | 必要なもの | このアプリで扱える系 |
|---|---|---|---|
| `--engine tblite` | GFN2-xTB（既定）、GFN1-xTB、IPEA1-xTB | tbliteのPython API（condaでは`tblite-python`） | 非周期系・固定セルの周期系 |
| `--engine gxtb --binary …` | g-xTB | 公式のg-xTB対応xtb実行ファイルと付属ライブラリ | 非周期系 |
| `--engine uma` | 学習済みUMA / omol | fairchem-core、PyTorch、利用承認済みUMAモデル | 非周期分子 |

**通常配布版tblite 0.7.0はg-xTBに対応していません（2026年10月15日確認）。** [tbliteの組み込み手法](https://tblite.readthedocs.io/en/latest/spec/methods.html)は上表の3種類です。[公式g-xTB](https://github.com/grimme-lab/g-xtb)は改変版tbliteを内部で使用していますが、通常配布版tbliteのPython APIとは異なります。g-xTBが目的なら、下の「g-xTBの実行ファイルを使う」へ進んでください。

### Windowsでtbliteを使う（推奨：Miniforge）

1. [Miniforge公式配布ページ](https://conda-forge.org/download/)からWindows x86_64版をインストールします。
2. スタートメニューの「Miniforge Prompt」を開き、専用環境を作ります。既存のPythonや仮想環境を削除する必要はありません。

```bat
conda create -n molecule-studio -c conda-forge --override-channels python=3.12 numpy ase psutil "tblite-python>=0.4,<1"
conda activate molecule-studio
python -c "import numpy, ase, psutil; from tblite.interface import Calculator; print('OK')"
```

3. `OK`が表示されたら、bridge.pyの保存先へ移動して起動します。次のパスは実際の保存先に置き換えてください。

```bat
cd /d "C:\Users\ユーザー名\Downloads"
python bridge.py --engine tblite --allow-origin https://h-nabata.github.io
```

次回以降もMiniforge Promptで `conda activate molecule-studio` を実行し、保存先へ移動してから起動します。conda-forgeでのPython APIのパッケージ名は **`tblite-python`** です。`tblite`だけの導入ではPython APIを導入したことにはなりません。[tblite公式Pythonチュートリアル](https://tblite.readthedocs.io/en/latest/tutorial/python/singlepoint.html)もこのパッケージを使用しています。

#### pipで「Unknown compiler(s)」が出た場合

Windows用の対応wheelが見つからないと、pipは `tblite-….tar.gz` を取得してソースからビルドします。`Unknown compiler(s): … ifort … ifx … gfortran …` は、そのビルドに必要なFortranコンパイラが見つからないというエラーです。Visual StudioのC/C++コンパイラだけでは足りません。利用者のコマンド入力の誤りではなく、以前の案内がWindowsでのバイナリ配布条件を説明していませんでした。

通常の導入ではコンパイラを追加する必要はありません。上記のMiniforge環境を新しく作ってください。`pip install tblite`を繰り返したり、`--only-binary`を外してソースビルドを始めたりする必要はありません。自前ビルドを行う場合は[公式のビルド要件](https://tblite.readthedocs.io/en/latest/installation.html)を確認してください。

### WSL / Linux / macOSでtbliteを使う

```sh
python3 -m venv .venv
source .venv/bin/activate
python -m pip install "numpy>=1.24,<3" "ase>=3.23,<4" "psutil>=5.9,<8"
python -m pip install --only-binary=:all: 'tblite>=0.4,<1'
python -c "import numpy, ase, psutil; from tblite.interface import Calculator; print('OK')"
python bridge.py --engine tblite --allow-origin https://h-nabata.github.io
```

`--only-binary=:all:` は対応wheelがない場合にソースビルドへ進むことを防ぎます。「No matching distribution found」なら、そのOS・CPU・Pythonに対応するwheelを取得できていません。その場合はMiniforgeを導入して、Windowsの例と同じ `conda create` と `conda activate` を使えます（フォルダー移動には通常の `cd` を使用）。Windows＋WSLで既存の計算エンジンを利用する場合は、サービスもそのWSL内で起動します。

### g-xTBの実行ファイルを使う

このアダプタは、[公式g-xTBリポジトリ](https://github.com/grimme-lab/g-xtb) が配布する **`xtb --gxtb --grad` 対応版**を対象にしています。旧版の独立した `gxtb` 実行ファイルとはコマンド形式が異なります。実行ファイルと付属ライブラリはユーザーがローカルに導入します。g-xTB使用時はtbliteのPythonパッケージは不要です。

[公式のbinariesフォルダー](https://github.com/grimme-lab/g-xtb/tree/main/binaries)からOSに対応する配布物を取得し、展開してください。通常版のxtbではなく、g-xTB対応版を指定します。

#### Windows（コマンドプロンプト）

Python 3.10以上を用意し、bridge.pyの保存先で専用環境を作ります。以下の2種類のパスを実際の保存先に置き換えてください。付属DLLも配布時の配置を保ち、xtb.exeがあるbinフォルダーをPATHへ追加します。

```bat
cd /d "C:\Users\ユーザー名\Downloads"
python -m venv .venv-gxtb
.venv-gxtb\Scripts\python.exe -m pip install "numpy>=1.24,<3" "ase>=3.23,<4" "psutil>=5.9,<8"
set "PATH=C:\path\to\g-xtb\bin;%PATH%"
"C:\path\to\g-xtb\bin\xtb.exe" --help
.venv-gxtb\Scripts\python.exe bridge.py --engine gxtb --binary "C:\path\to\g-xtb\bin\xtb.exe" --allow-origin https://h-nabata.github.io
```

`--help`で起動でき、`--gxtb`と`--grad`が使える版であることを確認します。`set`は現在のコマンドプロンプトだけに適用されます。次回も保存先へ移動し、PATHを設定してから最後の起動コマンドを実行してください。仮想環境の作成とpipによる導入は初回だけです。

#### WSL / Linux / macOS

```sh
python3 -m venv .venv-gxtb
source .venv-gxtb/bin/activate
python -m pip install "numpy>=1.24,<3" "ase>=3.23,<4" "psutil>=5.9,<8"
/absolute/path/to/xtb --help
python bridge.py --engine gxtb --binary /absolute/path/to/xtb --allow-origin https://h-nabata.github.io
```

`/absolute/path/to/xtb`は対応実行ファイルの絶対パスに置き換えます。macOSでは付属ライブラリも配置し、公式READMEの案内に従ってください。WSLではLinux用バイナリとWSL内のPythonを使います。

既にtblite用のPython環境を作った場合は、その環境を再利用し、g-xTB対応実行ファイルを指定して起動することもできます。g-xTB使用時はtbliteのPythonパッケージを呼び出しません。空白のあるパスは引用符で囲みます。サービスは引数配列と `shell=False` で実行し、ブラウザからコマンド・任意の引数・ファイルパスは受け取りません。

### 起動後の接続（両エンジン共通）

起動するとURLと、起動のたびに変わる `Token` が表示されます。アプリの接続先URLと接続トークン欄へ入力し、「接続を確認」を押してください。ブラウザからローカルネットワークへの接続許可が求められた場合は許可します。接続トークンはブラウザの永続ストレージ・プロジェクト・結果JSONに保存しません。

端末はアプリの利用中開いたままにします。エンジンを切り替える場合はCtrl+Cでサービスを停止し、もう一方の `--engine` で起動して、新しく表示されたTokenで接続し直してください。

### 公開サイトから接続できない場合

ブラウザ・組織のポリシーによってHTTPSサイトからlocalhostへの接続が制限される場合があります。ブラウザ全体のセキュリティ設定を無効化する必要はありません。リポジトリを手元に取得して、アプリも同じローカルサービスから配信できます。

```bash
python bridge.py --engine tblite --site-dir /path/to/h-nabata.github.io/molecule-visualizer
```

`http://127.0.0.1:8766/` を開き、端末に表示されたTokenで接続します。この場合、公開サイト用の `--allow-origin` は不要です。`--site-dir` には必ずアプリのフォルダーを指定してください。

## 2. 操作

1. 構造を読み込み、座標欄の未適用編集を適用します。経路の場合は「反応経路の初期構造」から3〜20構造を生成するか、複数構造XYZ/SDFなどを読み込みます。
2. 「外部エンジン / 経路緩和」で接続し、**系全体の電荷とスピン多重度**を確認します。多重度は `2S+1`、エンジンへ渡す不対電子数は多重度−1です。g-xTBの閉殻一重項では `--uhf` を付けません。
3. 操作、収束閾値、最大ステップ数などを設定して計算します。経路の元素・原子数・File-order・セルは全フレームで同じである必要があります。
4. エネルギー図、数値表、収束状態を確認して「結果を構造へ適用」を押します。適用前の描画構造は変わりません。計算開始後に構造・編集欄が変更された場合は上書きを拒否します。適用は1回のUndoで戻せます。
5. 「エネルギー・力・履歴をJSON保存」で入力条件、座標、各原子の力、全エネルギー、ステップ履歴を保存できます。適用した構造列は既存の全フレームXYZ/SDF/プロジェクト保存も利用できます。

一度に実行するジョブは1つ、最大500原子・100構造です（bridge.py 1.4.0）。電荷・スピンの偶奇、非有限座標、周期最小像で0.1 Å未満の重なりを検査します。電子計算のSCF失敗はエラーとして停止し、未検証の構造を自動適用しません。最大ステップ到達は「未収束」と表示します。

bridge.py 1.1.2以降では、外部エンジンの最大ステップ数を1〜10,000で指定できます（ブラウザの既定値はCI-NEBが100、通常最適化・TSが150）。1.1.1以前の上限は1,000です。AFIRの既定値・上限は10,000です。旧サービスの場合はファイルを差し替えて再起動し、新しいTokenで再接続してください。

収束しきい値と最大変位の上下ボタンは0.01刻み、ばね定数は0.1刻みです。0.00001などの細かな値は直接入力できます。計算に使える下限は収束しきい値0.00001、最大変位・ばね定数0.001で、0は拒否します。

「計算を中止」でネイティブ計算も停止します。接続を失ったりブラウザを閉じたりした場合、計算はローカル側で継続することがあります。端末の **Ctrl+C** でサービスと計算を停止できます。既定のジョブ上限は30分、g-xTBの1評価上限は120秒、計算スレッド数は1です。必要ならサービス起動時に `--job-timeout 3600 --evaluation-timeout 300 --threads 4` などを指定します。終了した計算は次の計算で置き換わるため、必要な結果は保存してください。

## 3. 緩和方式

座標単位はÅ、エネルギーはeV、力はeV/Åです。tbliteとg-xTBの原子単位を変換し、`F = −∇E` とします。質量重み付けなしの、**全原子をまとめた3N次元Cartesian空間**で接線を定義します。個々の原子で独立に射影する方式ではありません。

局所単位接線を `τᵢ` とすると、物理的な力の直交成分は次の通りです。

```text
F⊥ᵢ = Fᵢ − (Fᵢ · τᵢ) τᵢ
```

| 操作 | 内部構造への力 | 端点 |
|---|---|---|
| 評価 | 移動なし。物理的な力・エネルギーを取得 | 移動なし |
| 単一構造の最適化 | 全物理力 | 現在の1構造のみ |
| 直交方向のみ緩和 | `F⊥`。接線方向のばね・再配置なし | 固定 |
| CI-NEB（既定の経路モード） | 通常像はNEB。CI像は `F − 2(F·τ)τ`、ばねなし | 固定 |
| LUP系（CI-String） | 通常像は `F⊥`、CI像は `F − 2(F·τ)τ`。全像ばねなし、弧長再分布あり | 固定 |

AFIRの抽出列の取り込み、3構造以上の経路を開いた際の初期選択ではCI-NEBを選択します。通常NEB単独の選択肢はありません。CI-NEBではCI開始ステップ（初期値5）までは通常NEBで経路を緩和し、指定ステップ以降に最高エネルギーの内部ノード1つをCI像にします。CI開始ステップは最大ステップ数より小さく設定してください。通常NEBのAPIは旧版との互換性とCI開始前の計算のため保持しています。

LUP系（CI-String）は接線垂直緩和に弧長再分布と遅延CIを加えた独立実装です。GRRMのLUPと同一ではなく、GRRMによる端点・各極大点の独立最適化を行うものでもありません。ばね定数は使用しません。FIRE／投影L-BFGS、自動ノード追加、経路分割、結果のTS最適化・保存に対応します。使い方・既定値は[計算・解析の案内](../RESEARCH.md#lup系ci-string)、数式と失敗時の扱いは[数値仕様](../AFIR.md#lup系ci-stringの数値仕様)を参照してください。

操作メニューの「単一構造の最適化（AFIR法を含む）」では、「通常の単一構造最適化（人工力なし）」または「AFIR法の設定を開く」を選べます。AFIRを選ぶと専用パネルへ移り、原子団ペア・人工力・探索条件を確認して「AFIR探索を開始」で実行します。通常の最適化に登録済みの人工力が自動で加わることはありません。

接線には隣接構造のエネルギー差を重みにしたimproved tangentを使用します。エネルギーが同じ場合は幾何学的な接線にフォールバックします。CIは指定ステップ以降の最高エネルギーの内部構造1つです。**CI像は意図的に接線方向へ登るので、「直交方向のみ」ではありません。** 最高点の候補が変わると積分器の速度をリセットします。

NEB・直交緩和と既定の単一構造最適化の座標更新は変位上限付きFIRE方式です。直交モードでは力の射影に加え、蓄積した速度と実際の更新量を毎ステップの接線へ再射影します。変位上限は各構造の全3N成分に共通の係数で適用します。原子ごとに異なる係数で切り詰めると直交性が壊れるため、その方式は使いません。報告される接線方向最大更新は `max |ΔRᵢ·τᵢ|` です。

「接線方向に動かない」は**各ステップの局所接線に対して**成立します。経路の曲率・接線自体は緩和で変化するため、最初の経路上の弧長や端点間の直線への射影位置を厳密に固定する制約ではありません。直交力が収束しても、接線方向の物理力が残ることがあります。構造が不適切に全方向へ最小化されることは防ぎますが、得られた経路・最高点が真の最小エネルギー経路・一次鞍点であることまでは保証しません。端点の事前最適化、適切な原子対応、必要な遷移状態・振動解析は別途行ってください。

ブラウザ内の**初期経路の衝突緩和**も変更しました。距離補間の人工的な目的関数の勾配、弱い平滑化項、初期の対称性を崩す摂動を、幾何学的な局所接線に直交する方向へ射影します。端点を固定し、隣接構造を同じ反復時点で評価します。こちらは電子エネルギーを計算せず、NEBのばねやCI像も使用しません。

## 4. 周期系・対応範囲

- **tblite:** 固定格子と周期方向をそのまま渡します。格子・座標をBohrへ変換します。GFN2-xTB（既定）、GFN1-xTB、IPEA1-xTBは `--method` で選択できます。元素は最大Rn（Z=86）、実際のパラメータ対応はエンジンが判定します。
- **g-xTB:** このアダプタは非周期系専用です。周期セルが有効な入力は拒否します。元素の上限はLr（Z=103）。`xtb --gxtb --grad` のTurbomole形式gradientからエネルギー・勾配を読み、元素順序と返された座標も照合します。
- 周期経路は**連続した、折り返していないCartesian座標**で入力します。緩和中に原子ごとの最小像へ経路を再写像しません。境界をまたぐ短い初期経路は、初期構造生成の「周期系で終点の最小像を使う」で作れます。この初期生成では終点が周期等価な座標になりますが、外部緩和へ渡した後は両端点を一切動かしません。
- 可変セルNEB、原子位置の固定、溶媒、外場、電荷・スピン状態をまたぐ経路、複数電子状態の追跡には対応していません。現在のUIでは系全体の電荷・多重度を全構造に共通して指定します。POSCARのselective dynamicsは外部緩和の拘束条件には使用しません。
- CIFの部分占有は計算前に確定した構造へ整理します。SMILES/MOLの結合次数は電子計算へ強制せず、元素・座標・総電荷・多重度を渡します。同位体は通常のBorn–Oppenheimerエネルギーに影響しません。振動解析はASEの標準原子質量を使います。現在の画面ではMOLの同位体指定・XYZの個別質量を持つ構造の振動解析を拒否します。

## 5. 接続の境界

サービスは **127.0.0.1のみ**に待ち受けます。毎回のランダムBearerトークン、Hostヘッダーの限定、許可Originとの完全一致、JSON POST、入力サイズ・数値・ジョブ数の制限を併用します。CORSだけを認証として使用しません。`--allow-origin` は信頼するサイトだけに指定してください。

サービスの接続権限は、その許可したサイトのJavaScriptを信頼することを意味します。トークンの漏洩や許可サイトの侵害まで防ぐサンドボックスではありません。管理者権限で起動する必要はありません。計算の各評価は一時フォルダーで実行し、中止・失敗・完了後に削除します。任意のシェルコマンドやユーザーのファイルを読み書きするAPIは提供しません。

## 6. 検証と参考仕様

```bash
python -m unittest discover -s molecule-visualizer/tests -p 'test_*.py' -v
node --test molecule-visualizer/tests/*.test.cjs
```

テストはリポジトリのルートで実行します。解析的二重井戸ポテンシャルでの収束、実際の変位の直交性、端点固定、ASEのimproved-tangent NEB/CI力との一致、tblite実計算の有限差分勾配・単一最適化・固定セル経路、HTTP認証・Origin・Host検証、ネイティブ子プロセスの中止を検査します。`GXTB_TEST_BINARY=/absolute/path/to/xtb` を環境変数に設定するとg-xTBの実エネルギー・勾配の有限差分検証も実行します。

g-xTBは公式配布 `xtb-6.7.1-gxtb-140526-linux-x86_64` で検証しています。別バージョンやOSでは導入後に単一構造の評価から確認してください。

- [tblite Python API](https://tblite.readthedocs.io/en/latest/api/python.html)
- [g-xTB公式の実行方法](https://github.com/grimme-lab/g-xtb)
- [xtbのTurbomole gradient出力](https://github.com/grimme-lab/xtb/blob/main/src/io/writer/turbomole.f90)
- Henkelman & Jónsson, *Improved tangent estimate in the nudged elastic band method*, J. Chem. Phys. 113, 9978 (2000), [DOI](https://doi.org/10.1063/1.1323224)
- Henkelman, Uberuaga & Jónsson, *A climbing image nudged elastic band method*, J. Chem. Phys. 113, 9901 (2000), [DOI](https://doi.org/10.1063/1.1329672)

## 7. 複数フラグメントAFIR（1.2.0）

AFIRを利用する場合は、このフォルダーの`bridge.py`を最新版の1.4.0へ更新して再起動します。最大ステップ数の既定値・上限は10,000です。1.1.0のAFIR上限は500ステップで、1.1.1以降は10,000です。追加のPython依存関係はありません。NEBと同じ接続画面を使います。[AFIR操作説明](../AFIR.md)を参照してください。

AFIRは非周期分子専用です。人工項を加えたエネルギーのFIRE最適化を実行し、物理エネルギーと人工項、原子ID付きの評価済みフレームを区別して返します。中止時は受領済みの途中フレームを保持し、子プロセスの終了後に停止を報告します。計算履歴は既定でディスクへ保存し、結果JSONもブラウザから保存できます。

Windowsでの実g-xTB試験と、残る未検証範囲は[追加検証記録](../AFIR-VALIDATION.md)に記載しています。NEBの従来の検証記録とは区別します。

## 8. ライブ表示と結果の対話的な確認（1.2.0）

最新版のbridge.pyをダウンロードして再起動・再接続すると、「計算中のエネルギー・構造を表示」を利用できます。既定ではオンで、AFIRと外部エンジンそれぞれのオン／オフをブラウザに保存します。追加の依存パッケージはありません。

AFIRは探索ステップごとの物理エネルギーと人工項を加えたエネルギーを表示します。NEB・CI-NEB・直交緩和は、最後に全構造の評価がそろった経路のエネルギープロファイルを更新します。ライブ中の構造表示は経路の中央の構造です。単一構造の評価は1点、通常の最適化は計算中に最新の1点を表示します。bridge.py 1.3.0では通常の最適化も終了後に全ステップの構造・エネルギーを表示します。

外部エンジンのライブ表示を開始すると設定ウィンドウを閉じ、構造エリアとグラフを表示します。「計算設定・結果」でウィンドウへ戻り、「計算を中止」で停止できます。通常の結果も「エネルギープロファイルと構造を見る」から点・スライダーを選択してプレビューできます。入力の置き換えは「結果を構造へ適用」で行います。

APIでは /api/info の livePreview: 1 が対応を示します。GET /api/jobs/{id}?preview=1&after={取得済み件数} で任意の進捗表示を取得します。AFIRは1応答最大1,000件のエネルギー差分と最新1構造だけを返します。経路はジョブ入力の livePreview: true を指定した場合に最新の完全な経路を保持します。通常のGETは途中座標を返しません。Host・Origin・Bearer Tokenの検証は従来どおり必要です。分子データを外部サーバーへ送信しません。

## 9. 通常の最適化履歴とXYZ保存（1.3.0）

`bridge.py`を1.3.0へ差し替えて再起動・再接続すると、通常の最適化でも初期構造と全更新後の評価済み座標を保持します。ライブ表示はオフのままで利用できます。追加のエネルギー評価は行いません。`/api/info`の`optimizationTrajectory: 1`が対応を示し、結果の`trajectory.images`と`trajectory.energies`に同じステップの座標・エネルギーを格納します。従来の`images`と`energies`は最終構造1件のままで、「結果を構造へ適用」も従来どおり最終構造を反映します。

中止・失敗時に受領済みの評価済みチェックポイントがある場合は、途中履歴を返します。未評価の座標を補完せず、途中結果は未収束と表示します。通常の進捗応答には履歴を載せず、計算の終了・中止・失敗後にまとめて返します。履歴は最大10,001構造のため、原子数・ステップ数に応じてメモリと最終応答の容量が増えます。

AFIR・通常の最適化・経路計算の結果から「構造列を保存・抽出」を開き、全構造または指定ノード数を1ファイルに保存できます。保存形式は複数フレームXYZとGRRM LUP infile（`# NODE`・`--`で区切る座標列）、抽出方法は番号の等分と累積RMS変位の等分に対応します。NODE形式の保存名は`<名前>_infile.log`です。「全構造を表示」「抽出した構造列を表示」で全文を表示し、ダウンロードせずCtrl+A・Ctrl+Cでコピーできます。NEB・CI-NEBでは終了時の反応経路上のノードを出力します。式・端点・重複・周期系の扱いは[AFIR操作説明の構造列保存](../AFIR.md#構造列の保存とノード抽出)を参照してください。旧bridgeの通常最適化は最終構造だけを保存でき、全履歴が必要な場合は更新後に再計算します。infile出力の追加に伴うbridgeの更新は不要です。


## 10. SellaによるTS最適化・ASE振動解析（1.4.0）

最新版の`bridge.py`に差し替え、起動に使用する**同じPython環境**へSellaを追加します。例えば既存のg-xTB用仮想環境なら、以下のようにそのPythonを明示します。

```bat
.venv-gxtb\Scripts\python.exe -m pip install --only-binary=:all: "sella>=2.6,<3"
```

有効化済みのconda/venvなら`python -m pip install --only-binary=:all: "sella>=2.6,<3"`で構いません。Python 3.12・Sella 2.6で検証しています。対応wheelが見つからない場合はPython 3.12の環境を使用してください。Sella 2.6自体は共通wheelを配布しています。依存する[JAXの公式導入案内](https://docs.jax.dev/en/latest/installation.html#cpu)ではWindows x86_64のCPU用wheelはexperimentalとされ、Visual Studio再頒布可能パッケージが必要になる場合があります。Windowsで導入できない場合は、WSL内でSella・計算エンジン・bridgeをそろえて実行してください。基本requirementsにはSellaを含めていないため、これまでのAFIR/NEBを使うだけなら追加不要です。振動解析だけなら既存のASEを使い、Sellaは不要です。bridgeを再起動して再接続すると、接続状態にSellaのバージョンが表示されます。

1. 描画エリア付近の「現在の構造をTS最適化」を押します。NEB結果からは、表の任意のノードの「TS入力」を押すと、緩和済み経路を描画へ反映し、そのノードを選択した状態でTSの条件が開きます。別の候補はFRAMESで選び直せます。
2. TS手法はSella PRFO（既定）またはRFO。一次鞍点（`order=1`）、Cartesian座標（`internal=False`）を使います。`初期信頼半径`はSellaの`delta0`であり、計算中に調整されるため固定の最大変位ではありません。通常の極小化にはFIRE、ASE L-BFGS、ASE BFGSを選べます。L-BFGSをTS探索として実行することはできません。
3. 電荷・多重度・収束閾値・最大ステップ数を確認して実行します。エネルギーと勾配は接続中のtbliteまたはg-xTBの物理ポテンシャルです。AFIR人工項やNEBばねは加えません。Sellaは非周期分子用です。
4. 「最適化後に振動解析」をオンにした場合のみ、得られた最終構造で解析します。既定は**オフ**。最大ステップで未収束でも実行します。「現在の構造の振動解析」なら座標を最適化せずに解析できます。
5. 「振動数表とモードを表示」で、全3Nモードの振動数（cm⁻¹）と量子エネルギーhν（meV）を表示します。虚振動は`i`を付けて赤字で表示します。表の行をクリックまたはEnter/Spaceで選ぶと、原子の変位矢印が描画されます。必要ならモードをアニメーションできます。表示振幅は最大原子変位（Å）として規格化し、動画の速さは全モード共通です。実時間の振動・虚振動の時間発展ではありません。
6. 「＋/−方向へ変位して入力に適用」で、解析した構造を選択モードに沿って微小変位させられます。変位はUndoできます。モードの符号は任意です。別の構造に編集した後の適用は拒否します。変位後「現在の構造をTS最適化」で再探索できます。これは収束の保証ではありません。

振動解析はASE `Vibrations`の中心差分（2点±δ、または4点±δ・±2δ）。ブラウザの既定δ=0.001 Å。N原子で平衡構造1回と6N/12N回の力評価を行います。最大200原子、ASE標準原子質量、固定セルなしの非周期分子を対象にします。tbliteはTS/振動解析時の`accuracy`を0.01に設定します。g-xTBはローカル実行ファイルのSCF設定を使用します。

モード表には並進・回転を射影除去しない全3Nモードを残し、指定閾値（既定20 cm⁻¹）より大きい虚振動の本数を別記します。熱化学量の計算では別途、質量重み付きHessianから剛体運動を射影除去します。低振動数が不安定な場合は構造の収束、差分幅、2/4点法、電子計算の収束を確認してください。**力の収束、虚振動1本、IRCによる接続確認は別の条件**です。

振動解析中は進捗を表示し、中止できます。差分計算が失敗・中止されても、すでに評価済みの構造結果は保存・適用可能です。未完了の振動数・モードは表示しません。差分キャッシュはジョブ専用の一時フォルダー内にだけ作り、正常終了・中止・失敗時に削除します。モード表のCSVと計算結果JSONを明示的に保存できます。JSONには全モード・条件・Sella/ASEのバージョンを含め、接続トークンは含めません。

- [Sella公式](https://github.com/zadorlab/sella)
- [ASE Vibrations](https://docs.ase-lib.org/ase/vibrations/modes.html)
- [ASE最適化手法](https://docs.ase-lib.org/ase/optimize.html)

## 11. NEB経路へのノード追加（1.4.0）

実行中は「NEBを一時停止してノード追加」を押します。ライブ表示のオン/オフにかかわらず、**全ノードのエネルギーと力が評価済みの最後の経路**を保持します。計算が最初の全ノード評価を終える前に停止した場合は、途中結果はありません。完了後の結果なら「結果の経路にノードを追加」、すでに描画へ反映した経路なら「経路のノードを補間・追加」を使います。

始点・終点の構造番号（画面上の1始まり）と、各隣接ペアに挿入するノード数を指定します。その区間だけをCartesian座標で線形補間し、すべての既存ノード・端点・原子IDを保持します。新しいノードは左側の原子IDを引き継ぎます。自動的な原子対応付け、再整列、周期折り返し、エネルギーの補間はしません。0.1 Å未満の原子衝突は拒否します。複数のTS候補の周辺に、区間を分けて追加できます。合計100ノードまでです。

「補間してNEB再開の設定へ」で新しい経路を適用し、NEB/CI-NEBの条件を開きます。実行を押すまでは計算しません。再開は新しいジョブで、全ノードのエネルギーを再評価し、速度・FIRE履歴・CI開始ステップをリセットします。旧ジョブの内部状態を引き継ぐ厳密なリスタートではありません。CI-NEBの登坂像は従来どおり最高点1つであり、ノードを増やしても複数CIへは変わりません。複数の極大候補は個別のSella TS探索へ渡してください。
