diff --git a/docs/superpowers/plans/2026-08-15-lattice-catalog.md b/docs/superpowers/plans/2026-08-15-lattice-catalog.md new file mode 100644 index 0000000..2187288 --- /dev/null +++ b/docs/superpowers/plans/2026-08-15-lattice-catalog.md @@ -0,0 +1,1107 @@ +# 格子カタログ(新フォーマット対応一式)実装計画 + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 現行 StdFace の全格子・全相互作用を新三層仕様(geometry/system/model + 拡張方言)の YAML カタログ + 日本語マニュアル + 意味検査リンタとして `lattice_catalog/` に作成する。 + +**Architecture:** Task 0 で規約・schema・リンタ・manifest を先に確定し、Task 1 (chain) で雛形を固めてから残り格子へ展開。YAML は 31 件((8格子 + ladder W=2/W=3)×3模型 + wannier90 Hubbard 例)。全ファイルがリンタ + manifest 検算 + ソース突合で検証される。 + +**Tech Stack:** YAML(手書き)、Markdown、Python 3(tools/ の開発時スクリプトのみ。PyYAML 使用可、リポジトリ依存には追加しない)。 + +**Spec:** `docs/superpowers/specs/2026-08-15-lattice-catalog-design.md`(Codex Round 1 反映版) + +## Global Constraints + +- 成果物はすべて `lattice_catalog/` 配下。リポジトリの既存コードは一切変更しない。 +- マニュアル・YAML コメントは日本語。 +- 各 YAML の先頭に `catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: <格子名>, model: }` を置く(lattice/model は C10 の manifest 照合元)。 +- ボンド type 名は StdFace キーワード名そのまま。プライムを含む名前(`J0'` 等)は YAML では必ず引用符付き。 +- **R の定義**: `R = cell(to) − cell(from)`。実変位 δ = (frac_to − frac_from) + R·A。 +- **向き = ソース順保持**: bonds は参照実装の向きのまま書く(`_BONDS` の `site_i → site_j`、Kondo は `general_j(..., 遍歴, 局在)` の引数順)。正準形への並べ替えは**しない**。各ボンドは一度だけ書き、リンタが反転同値 `(i,j,R)≡(j,i,−R)` の重複を検出する。反転時の係数変換(hopping: 複素共役、交換テンソル: 転置)は消費側規範として CONVENTIONS に記載。 +- **value 意味論**: `H = Σ value·operator` の物理ハミルトニアン係数(solver 出力の係数規約とは別物 — スペック §4.3 の検証連鎖)。**符号は必ずデータに持たせる**: param 参照の一般形は `{param: <名>, scale: <実数, 省略時1.0>, default: <最終値, 省略時0>}`。**param 指定時は scale × param、未指定時は default をそのまま(スケール適用なしの最終値)**。符号表(スペック §4.3): t 族 scale −1、mu/h/Gamma/Gamma_y coeff −1、U/V/D/J 族/Kondo J は +。 +- J 族は 9 成分 tensor_terms 正準形。**パラメータ解決順**(`input_params.py::_resolve_spin_matrix` と同一): 成分局所 > 成分大域 > スカラー局所(対角) > スカラー大域(対角) > 0。競合規則(スカラー同士・スカラーvs行列・行列vs行列)とプライム系(大域 fallback なし)の解決表を CONVENTIONS に規範として記載。 +- twist は度単位、境界 n 回横断で `exp(i·n·π·θ/180)`。`{twist: {param: phase0}}` 等で参照。 +- 出典記録は「ファイル名 + 関数名 + 参照コミットハッシュ」(行番号は補助)。 +- 各タスクの完了条件に `python3 lattice_catalog/tools/lint_catalog.py` の成功を含む。 +- コミットは Task ごと。コミットメッセージは中立的な表現(内部ツール名を出さない)。 +- 参照実装: `python/stdface/lattice/.py` の `_BONDS` テーブル。形式は + `(dW, dL, site_i, site_j, nn_level, J系, t系, V系)`(3D は `(dW, dL, dH, site_i, site_j, J系, t系, V系)`)。 + `dW, dL(, dH)` → R、`site_i/site_j` → from/to ラベル、J系/t系/V系の変数名 → type 名。 +- onsite 項の模型別適用範囲(`python/stdface/core/model_plugin.py` で確認済みの規範): + - Spin: 磁場(−h Sz, −Gamma Sx, −Gamma_y Sy)+ D(Szz) + - Hubbard: mu(−mu N)+ U(NupNdn)+ 磁場(電子スピンに −h/−Gamma/−Gamma_y) + - Kondo: Hubbard 一式を `_c` に + **磁場 3 成分を `_s` にも**(両側適用)+ J 結合。D は非 Spin 模型では不使用。 + +--- + +### Task 0: 規約・schema・リンタ・manifest・キーワード目録 + +**Files:** +- Create: `lattice_catalog/CONVENTIONS.md` +- Create: `lattice_catalog/manifest.yaml`(空の骨格 + 形式定義コメント) +- Create: `lattice_catalog/tools/lint_catalog.py` +- Create: `lattice_catalog/tools/keyword_inventory.py` +- Create: `lattice_catalog/tools/test_tools.py`(リンタ・目録の自動テスト) + +**Interfaces:** +- Consumes: スペック §4(規約)、`python/stdface/core/keyword_parser.py` の + `_COMMON_KEYWORDS`、`python/stdface/solvers/*/_plugin.py` のキーワードテーブル +- Produces: 全後続タスクが従う規約と検査基盤。 + `lint_catalog.py` は引数なしで `lattice_catalog/` 全体を検査し、 + 違反があれば非零終了。`keyword_inventory.py` は全キーワードの + JSON 目録を stdout に出力。 + +- [ ] **Step 1: CONVENTIONS.md を書く** + +スペック §4.1–4.5 の規約を規範文書として転記・整理する。章立て: + +```markdown +# lattice_catalog 記述規約 (stdface-catalog/0.1) + +1. 位置づけと dialect 宣言 + - 各 YAML 先頭: catalog: {schema: stdface-catalog/0.1, + dialect: experimental, lattice: <格子名>, model: <模型名>} + (lattice/model は manifest 照合 (C10) の照合元) + - draft 仕様準拠部分と拡張方言(§7)の区別 +2. ファイル構成(自己完結: catalog / geometry / system / model) +3. geometry 規約(サイト順序 = sites 配列順 = 仕様のサイト番号) +4. system 規約(size 代表値、twist: 度単位、exp(i·n·π·θ/180)、{param: phaseN}) +5. bonds 規約 + - R = cell(to) − cell(from)、δ = (frac_to − frac_from) + R·A + - type 名 = StdFace キーワード名(プライムは引用符付き) + - 向き = ソース順保持(_BONDS の site_i→site_j、Kondo は遍歴→局在)。 + 正準化しない。一意性は反転同値 (i,j,R)≡(j,i,−R) で判定 + - 反転時の係数変換(消費側規範): hopping 複素共役、交換テンソル転置 +6. couplings / onsite 規約 + - value 意味論: H = Σ value·operator(物理ハミルトニアン係数)。 + solver 出力係数規約(HPhi trans.def の H=−Σt 暗黙符号)との違いと + 検証連鎖(パラメータ→builder→trans/intr→solver規約→物理符号) + - 符号表(スペック §4.3 の表を転記): t 族 scale −1、mu/磁場 coeff −1、 + U/V/D/J/Kondo J は +。符号は必ずデータ(scale/coeff)に置く + - param 参照の一般形 {param, scale(省略時1), default(省略時0)}。 + param 指定時は scale × param、未指定時は default をそのまま使用 + (スケール適用なしの最終値)。型制約(2S: 正整数 等) + - J 族 9 成分 tensor_terms 正準形(成分キーワード名一覧、 + ops 対 ↔ 接尾辞対応表 [Sx,Sy]↔xy 等) + - パラメータ解決順序(実装準拠): 成分局所 > 成分大域 > + スカラー局所(対角) > スカラー大域(対角) > 0。 + 競合規則(スカラー同士/スカラーvs行列/行列vs行列)と + プライム系(大域 fallback なし)の prefix 別解決表 + - 演算子意味論と端点順序: hop(符号なし)、density-density、 + s_i . S_j(第1端点=遍歴)、onsite 語彙(N, Nup, Ndn, NupNdn, + Sx, Sy, Sz, Szz) + - 演算子と site_dof の型整合表(hop/density-density: fermion–fermion、 + s_i . S_j: fermion–spin この順、J テンソル: spin–spin) + - 模型別 onsite 適用範囲(Global Constraints の表と同内容) + - Kondo 2 ラベル(_c/_s、同一分率座標、物理的には 1 サイト 2 自由度) +7. 拡張方言一覧(fermion site_dof、演算子語彙、{param,scale,default}参照、 + catalog ヘッダ、4フェルミオン一般項の素描(将来課題)) +8. 検算・出典記録の書式(manifest 参照、関数名+コミットハッシュ) +``` + +- [ ] **Step 2: manifest.yaml の形式を定義し骨格を書く** + +```yaml +# lattice_catalog 検算台帳 +# 各エントリはリンタが YAML 本体と突合する期待値(全キー必須)。 +# coordination: サイトラベル × ボンド type ごとの配位数 +# (min_size_for_check のトーラス上で計数展開により実測比較。 +# 全ボンド type を列挙する — 省略不可) +# min_size_for_check: 異なる R が同一サイト対に折り畳まれない最小サイズ +# (各方向 L > 2 * max|R成分| を満たす奇数を記載) +files: {} +# 記入例(Task 1 で実エントリを追加): +# chain/chain_spin.yaml: +# lattice: chain +# model: spin +# dimension: 1 +# n_sites_uc: 1 +# bonds_per_uc: {J0: 1, "J0'": 1, "J0''": 1} +# coordination: +# A: {J0: 2, "J0'": 2, "J0''": 2} +# min_size_for_check: [7] +# source: {file: python/stdface/lattice/chain_lattice.py, func: chain, commit: } +``` + +- [ ] **Step 3: lint_catalog.py を書く** + +チェック項目(スペック §6.1 と同一。各 ID は診断メッセージの接頭辞): + +| ID | 検査内容 | +|----|----------| +| C1 | `catalog.schema == "stdface-catalog/0.1"` **かつ** `catalog.dialect == "experimental"` **かつ** `catalog.lattice`/`catalog.model` が存在 | +| C2 | schema 検査: 文書が dict、geometry/system/model の必須キーと型、サイトラベル重複なし、dimension は正整数、R/size 要素は整数、site_dof が存在 | +| C3 | R の長さ = dimension = size の長さ | +| C4 | bonds の from/to、**onsite のサイトラベル**が定義済み。`geometry.sites` のラベル集合 = `site_dof` のキー集合 | +| C5 | bonds の type ↔ couplings キー整合(未定義参照・未使用定義) | +| C6 | 反転同値での重複検出。同値キーは **type を含む** `(type,i,j,R) ≡ (type,j,i,−R)`(同一幾何ボンド上の t/V 共存は正当)。向きの並べ替え検査はしない — ソース順保持のため | +| C7 | `{param: ...}` 参照名が目録に存在。`scale` は実数、`default` は数値 | +| C8 | J 型 coupling(tensor_terms が Sx/Sy/Sz の 2 サイト積のもの)は**総項数がちょうど 9**、ops 対の**重複はエラー**、ops 対と param 接尾辞が対応(`[Sx,Sy]↔…xy` 等) | +| C9 | 演算子と site_dof の型整合: hop/density-density は fermion–fermion、`s_i . S_j` は fermion–spin(この順)、J テンソルは spin–spin。tensor_terms の ops 長 = ボンド 2 / onsite 1 | +| C10 | manifest 全キー(lattice/model/dimension/n_sites_uc/bonds_per_uc/coordination/min_size_for_check/source)の存在と、n_sites_uc・dimension・bonds_per_uc の一致 | +| C11 | **計数展開**: min_size_for_check のトーラス上に bonds を展開し、ラベル×type の配位数を実測して manifest の coordination と比較 | + +実装要件: +- 不正 YAML・キー欠落でも例外で落とさず、ファイル単位の診断として報告 + (try/except で C2 診断に変換)。 +- 引数のパスは `Path.resolve()` してから ROOT 相対に変換(ROOT 外は + エラー報告)。引数なしで `lattice_catalog/**/*.yaml` 全件 + (manifest.yaml 除外)。違反があれば exit 1、末尾に + `{N} files, {M} errors` を出力。 +- 目録は `keyword_inventory.py` をサブプロセス実行して取得。 + +中核アルゴリズム(この通り実装): + +```python +def reversal_dup(bonds): + """C6: 反転同値 (type,i,j,R)~(type,j,i,-R) での重複検出。 + キーに type を含める — 同一幾何ボンド上の t/V 共存は正当。""" + seen, errs = set(), [] + for b in bonds: + k = (b["type"], b["from"], b["to"], tuple(b["R"])) + rk = (b["type"], b["to"], b["from"], tuple(-x for x in b["R"])) + if k in seen or rk in seen: + errs.append(f"C6: (逆向き)重複ボンド {b}") + seen.add(k) + return errs + +_J_COMPONENTS = { # C8: ops 対 ↔ param 接尾辞 + ("Sx", "Sx"): "x", ("Sy", "Sy"): "y", ("Sz", "Sz"): "z", + ("Sx", "Sy"): "xy", ("Sx", "Sz"): "xz", ("Sy", "Sx"): "yx", + ("Sy", "Sz"): "yz", ("Sz", "Sx"): "zx", ("Sz", "Sy"): "zy", +} + +def check_j_coupling(type_name, tensor_terms): + """C8: 総項数 9・重複なし・ops↔接尾辞対応。 + 重複 ops 対は交換係数の二重加算になるため明示的にエラー。""" + errs, seen = [], set() + if len(tensor_terms) != 9: + errs.append(f"C8: {type_name}: 項数 {len(tensor_terms)} != 9") + for i, tt in enumerate(tensor_terms): + pair = tuple(tt.get("ops", [])) + suffix = _J_COMPONENTS.get(pair) + if suffix is None: + errs.append(f"C8: {type_name}[{i}]: 不正な ops 対 {pair}") + continue + if pair in seen: + errs.append(f"C8: {type_name}[{i}]: ops 対 {pair} の重複") + seen.add(pair) + coeff = tt.get("coeff") + expected = f"{type_name}{suffix}" + got = coeff.get("param") if isinstance(coeff, dict) else None + if got != expected: + errs.append(f"C8: {type_name}[{i}]: param {got} != {expected}") + return errs + +def expand_and_count(dim, labels, bonds, size): + """C11: min_size トーラス上でボンドを展開し、 + ラベル×type の配位数(そのラベルのサイト 1 個に接続する本数)を返す。 + from/to 双方の接続を数える。R=0 の同一ラベル自己ボンドは現行 + StdFace に存在しない前提とし、検出したら C2 エラーにする(呼び出し + 側で事前検査)。""" + import itertools + ncells = 1 + for s in size: + ncells *= s + touch = {lb: {} for lb in labels} # label -> type -> 接続本数合計 + for _cell in itertools.product(*[range(s) for s in size]): + for b in bonds: + t = b["type"] + touch[b["from"]][t] = touch[b["from"]].get(t, 0) + 1 + touch[b["to"]][t] = touch[b["to"]].get(t, 0) + 1 + # ラベルごとのサイト数 = ncells なので配位数 = 合計 / ncells + return {lb: {t: n // ncells for t, n in d.items()} for lb, d in touch.items()} +``` + +(注: 実装時は C8/C9 の診断に coupling 名と項番号を含め、キー欠落は +例外でなく該当チェックの診断として報告する。) + +- [ ] **Step 4: keyword_inventory.py を書く** + +```python +#!/usr/bin/env python3 +"""StdFace パーサーレジストリ全体からキーワード目録(JSON)を生成する。 + +母集合: core の _COMMON_KEYWORDS + ソルバーレジストリ経由で列挙した +全プラグインのキーワードテーブル(クラスのハードコード禁止)+ +格子名/模型名の alias(lattice/model registry から)。 +出力(canonical 単位に集約、安定ソート): +[{"keyword_canonical": "J0x", "keyword_lower": "j0x", + "sources": ["common"], "kind": "keyword"}, + {"keyword_canonical": "chain", "sources": ["lattice_registry"], + "kind": "lattice_alias", "canonical_target": "chain"}, ...] +""" +from __future__ import annotations +import json, sys +from collections import defaultdict +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "python")) + +from stdface.core.keyword_parser import _COMMON_KEYWORDS # noqa: E402 +# ソルバーは plugin レジストリ経由で列挙する。実装時に +# stdface.plugin のレジストリ API(登録済みプラグイン一覧)を確認し、 +# 各プラグインのキーワードテーブル属性を取得する。 +# 格子 alias は stdface.lattice のレジストリ(LatticePlugin.aliases)から。 + +_CANON_EXCEPTIONS = {"2s": "2S", "2sz": "2Sz", "gamma": "Gamma", + "gamma_y": "Gamma_y", "u": "U", "v": "V", "d": "D", + "k": "K", "l": "L", "w": "W", "h": "h", "mu": "mu"} + +def canon(kw: str) -> str: + if kw in _CANON_EXCEPTIONS: + return _CANON_EXCEPTIONS[kw] + if kw and kw[0] in "jv" and len(kw) > 1: # J/V 族は先頭大文字 + return kw[0].upper() + kw[1:] + return kw + +def main() -> None: + agg: dict[tuple, set] = defaultdict(set) # (canonical, kind) -> sources + for kw in _COMMON_KEYWORDS: + agg[(canon(kw), "keyword")].add("common") + # ソルバーレジストリの全プラグイン: agg[(canon(kw), "keyword")].add(name) + # 格子レジストリ: agg[(alias, "lattice_alias")].add("lattice_registry") + # 模型名: agg[(name, "model_alias")].add("model_registry") + # (実装時にレジストリ API に合わせて記入。既存コードは変更しない) + entries = [{"keyword_canonical": c, "kind": k, "sources": sorted(s)} + for (c, k), s in sorted(agg.items())] + json.dump(entries, sys.stdout, ensure_ascii=False, indent=1) + +if __name__ == "__main__": + main() +``` + +- [ ] **Step 5: test_tools.py を書く** + +tools の自動テスト(pytest 不要、`python3 test_tools.py` で完結する +assert ベースでよい)。最低限: +- inventory: `2S` がソルバー表から取れる / prime 付き J 成分 + (`J0'x` 等)が canonical に含まれる / 出力が安定ソート・重複なし / + ソルバーレジストリの件数 ≧ 4(将来プラグイン追加の検知) +- リンタ C1–C11: 各チェックの正例・負例(インライン YAML 文字列で + 最小ケースを構成 — 壊れた schema、逆向き重複(同 type)と + t/V 共存の正当性、9 成分の欠落・重複・10 項、型不整合 fermion–spin、 + manifest 不一致、計数展開の配位数不一致) +- param 参照の意味論: param 指定時 = scale × param、未指定時 = + default(スケール適用なし)の条件分岐を C7 検査・テストで固定 +- 不正 YAML(パース不能・null 文書)で例外にならず診断が出ること + +Run: `python3 lattice_catalog/tools/test_tools.py` +Expected: `all tools tests passed` + +- [ ] **Step 6: 動作確認** + +Run: `python3 lattice_catalog/tools/keyword_inventory.py | python3 -c "import json,sys; d=json.load(sys.stdin); print(len(d), 'entries'); assert any(e['keyword_canonical']=='2S' for e in d)"` +Expected: 件数表示、assert 成功 + +Run: `python3 lattice_catalog/tools/lint_catalog.py` +Expected: `0 files, 0 errors`(カタログ YAML なしの状態で正常終了) + +- [ ] **Step 7: Commit** + +```bash +git add lattice_catalog/CONVENTIONS.md lattice_catalog/manifest.yaml lattice_catalog/tools/ +git commit -m "Add lattice catalog conventions, manifest format, and semantic linter" +``` + +--- + +### Task 1: chain(3模型)— 雛形の確定 + +**Files:** +- Create: `lattice_catalog/chain/chain_spin.yaml` +- Create: `lattice_catalog/chain/chain_hubbard.yaml` +- Create: `lattice_catalog/chain/chain_kondo.yaml` +- Modify: `lattice_catalog/manifest.yaml`(chain 3 エントリ追加) + +**Interfaces:** +- Consumes: Task 0 の CONVENTIONS.md・リンタ。 + `python/stdface/lattice/chain_lattice.py::chain`(幾何と `_BONDS`) +- Produces: 後続格子タスクが踏襲する 3 模型分の完全な雛形 + +chain の抽出済み事実: +- 1 サイト/単位胞、tau=(0,0,0)。論理 1 次元(内部は W=1 の 2D。 + `phase0` 入力は内部で `phase[1]` に転写される — manual 3 章に記載) +- ボンド: `J0/t0/V0` = R=[1]、`J0'/t0'/V0'` = R=[2]、`J0''/t0''/V0''` = R=[3] +- 別名: `J→J0, J'→J0', J''→J0'', t→t0, ..., V''→V0''` + +- [ ] **Step 1: chain_spin.yaml を書く** + +```yaml +# StdFace chain / Spin 模型 +# stan.in 対応例: model="Spin" / lattice="chain" / L=16 / J=1.0 (J は J0 の別名) +# 検算は manifest.yaml の chain/chain_spin.yaml エントリを参照。 +# 出典: python/stdface/lattice/chain_lattice.py::chain (_BONDS), commit + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: chain, model: spin} + +geometry: + dimension: 1 + lattice_vectors: + a1: [1.0] # StdFace: a (既定 1.0) + sites: + - {label: A, frac: [0.0]} + +system: + finite: true + size: [16] # StdFace: L (代表値) + boundary: + - {twist: {param: phase0}} # 度単位。phase0=0 で periodic と等価 + +model: + site_dof: + A: {spin: {param: 2S, scale: 0.5, default: 0.5}} # S = 0.5 × 2S。既定 S=1/2 + + bonds: + # 参照実装 (_BONDS) のソース順を保持 + - {from: A, to: A, R: [1], type: J0} # 最近接 (別名 J) + - {from: A, to: A, R: [2], type: "J0'"} # 次近接 (別名 J') + - {from: A, to: A, R: [3], type: "J0''"} # 三次近接 (別名 J'') + + couplings: + # J 族は 9 成分正準形。パラメータ解決: 成分 > スカラー対角 > 大域別名 > 0 + J0: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J0x}} + - {ops: [Sy, Sy], coeff: {param: J0y}} + - {ops: [Sz, Sz], coeff: {param: J0z}} + - {ops: [Sx, Sy], coeff: {param: J0xy}} + - {ops: [Sx, Sz], coeff: {param: J0xz}} + - {ops: [Sy, Sx], coeff: {param: J0yx}} + - {ops: [Sy, Sz], coeff: {param: J0yz}} + - {ops: [Sz, Sx], coeff: {param: J0zx}} + - {ops: [Sz, Sy], coeff: {param: J0zy}} + "J0'": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J0'x"}} + - {ops: [Sy, Sy], coeff: {param: "J0'y"}} + - {ops: [Sz, Sz], coeff: {param: "J0'z"}} + - {ops: [Sx, Sy], coeff: {param: "J0'xy"}} + - {ops: [Sx, Sz], coeff: {param: "J0'xz"}} + - {ops: [Sy, Sx], coeff: {param: "J0'yx"}} + - {ops: [Sy, Sz], coeff: {param: "J0'yz"}} + - {ops: [Sz, Sx], coeff: {param: "J0'zx"}} + - {ops: [Sz, Sy], coeff: {param: "J0'zy"}} + "J0''": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J0''x"}} + - {ops: [Sy, Sy], coeff: {param: "J0''y"}} + - {ops: [Sz, Sz], coeff: {param: "J0''z"}} + - {ops: [Sx, Sy], coeff: {param: "J0''xy"}} + - {ops: [Sx, Sz], coeff: {param: "J0''xz"}} + - {ops: [Sy, Sx], coeff: {param: "J0''yx"}} + - {ops: [Sy, Sz], coeff: {param: "J0''yz"}} + - {ops: [Sz, Sx], coeff: {param: "J0''zx"}} + - {ops: [Sz, Sy], coeff: {param: "J0''zy"}} + + onsite: + A: + field_z: # -h Sz + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: # -Gamma Sx + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: # -Gamma_y Sy + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + aniso_z: # D (Sz)^2 + operator: {tensor_terms: [{ops: [Szz], coeff: 1.0}]} + value: {param: D} +``` + +- [ ] **Step 2: chain_hubbard.yaml を書く** + +```yaml +# StdFace chain / Hubbard 模型 +# stan.in 対応例: model="Hubbard" / lattice="chain" / L=16 / t=1.0 / U=4.0 +# 検算は manifest.yaml を参照。符号は scale/coeff がデータとして持つ (CONVENTIONS 6章) +# 出典: python/stdface/lattice/chain_lattice.py::chain (_BONDS), commit + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: chain, model: hubbard} + +geometry: + dimension: 1 + lattice_vectors: + a1: [1.0] # StdFace: a + sites: + - {label: A, frac: [0.0]} + +system: + finite: true + size: [16] # StdFace: L + boundary: + - {twist: {param: phase0}} # 度単位 + +model: + site_dof: + A: {fermion: {orbitals: 1}} # 拡張方言 (CONVENTIONS 7章) + + bonds: + - {from: A, to: A, R: [1], type: t0} # 別名 t + - {from: A, to: A, R: [2], type: "t0'"} # 別名 t' + - {from: A, to: A, R: [3], type: "t0''"} # 別名 t'' + - {from: A, to: A, R: [1], type: V0} # 別名 V + - {from: A, to: A, R: [2], type: "V0'"} # 別名 V' + - {from: A, to: A, R: [3], type: "V0''"} # 別名 V'' + + couplings: + # H への寄与 = value × operator (物理係数)。-t は scale で表す。 + t0: {operator: "hop", value: {param: t0, scale: -1.0}} # -t Σσ(c†c+h.c.) + "t0'": {operator: "hop", value: {param: "t0'", scale: -1.0}} + "t0''": {operator: "hop", value: {param: "t0''", scale: -1.0}} + V0: {operator: "density-density", value: {param: V0}} # +V n_i n_j + "V0'": {operator: "density-density", value: {param: "V0'"}} + "V0''": {operator: "density-density", value: {param: "V0''"}} + + onsite: + A: + hubbard_u: # +U n↑n↓ + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: # -mu N + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: # -h Sz (電子スピン) + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} +``` + +- [ ] **Step 3: chain_kondo.yaml を書く** + +```yaml +# StdFace chain / Kondo 格子模型 +# stan.in 対応例: model="Kondo" / lattice="chain" / L=16 / t=1.0 / J=1.0 +# 磁場 (h/Gamma/Gamma_y) は遍歴電子と局在スピンの両方に適用される +# (python/stdface/core/model_plugin.py::KondoModel)。 +# 現行実装のサイト倍加 (前半=局在 S2, 後半=遍歴) との対応は manual 4章。 +# 出典: python/stdface/lattice/chain_lattice.py::chain (_BONDS), commit + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: chain, model: kondo} + +geometry: + dimension: 1 + lattice_vectors: + a1: [1.0] # StdFace: a + sites: + - {label: A_c, frac: [0.0]} # 遍歴電子 (1物理サイト上の自由度その1) + - {label: A_s, frac: [0.0]} # 局在スピン (同・その2) + +system: + finite: true + size: [16] # StdFace: L + boundary: + - {twist: {param: phase0}} # 度単位 + +model: + site_dof: + A_c: {fermion: {orbitals: 1}} + A_s: {spin: {param: 2S, scale: 0.5, default: 0.5}} + + bonds: + # Kondo 結合はソース順 = general_j(..., 遍歴, 局在) の引数順。 + # 遍歴 A_c が第 1 端点 (s_i . S_j の役割と一致) + - {from: A_c, to: A_s, R: [0], type: J} # Kondo 結合 (セル内) + - {from: A_c, to: A_c, R: [1], type: t0} + - {from: A_c, to: A_c, R: [2], type: "t0'"} + - {from: A_c, to: A_c, R: [3], type: "t0''"} + - {from: A_c, to: A_c, R: [1], type: V0} + - {from: A_c, to: A_c, R: [2], type: "V0'"} + - {from: A_c, to: A_c, R: [3], type: "V0''"} + + couplings: + t0: {operator: "hop", value: {param: t0, scale: -1.0}} + "t0'": {operator: "hop", value: {param: "t0'", scale: -1.0}} + "t0''": {operator: "hop", value: {param: "t0''", scale: -1.0}} + V0: {operator: "density-density", value: {param: V0}} + "V0'": {operator: "density-density", value: {param: "V0'"}} + "V0''": {operator: "density-density", value: {param: "V0''"}} + J: {operator: "s_i . S_j", value: {param: J}} # +J s·S (第1端点=遍歴) + + onsite: + A_c: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + A_s: + field_z: # 局在側にも同じ 3 成分 + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} +``` + +注意: chain_kondo の J は等方スカラーのみ(Kondo の `input_spin` は +スカラー入力)だが、成分キーワード(`Jx` 等)が共通テーブルに存在する +ため `{param: J}` のスカラー参照とし、その旨コメントする。 + +- [ ] **Step 4: manifest.yaml に chain 3 エントリを追加** + +commit ハッシュは `git rev-parse HEAD` の値を使用。coordination は +ラベル×type で**全ボンド type を列挙**(省略不可): + +```yaml +files: + chain/chain_spin.yaml: + lattice: chain + model: spin + dimension: 1 + n_sites_uc: 1 + bonds_per_uc: {J0: 1, "J0'": 1, "J0''": 1} + coordination: + A: {J0: 2, "J0'": 2, "J0''": 2} + min_size_for_check: [7] + source: {file: python/stdface/lattice/chain_lattice.py, func: chain, commit: } + chain/chain_hubbard.yaml: + lattice: chain + model: hubbard + dimension: 1 + n_sites_uc: 1 + bonds_per_uc: {t0: 1, "t0'": 1, "t0''": 1, V0: 1, "V0'": 1, "V0''": 1} + coordination: + A: {t0: 2, "t0'": 2, "t0''": 2, V0: 2, "V0'": 2, "V0''": 2} + min_size_for_check: [7] + source: {file: python/stdface/lattice/chain_lattice.py, func: chain, commit: } + chain/chain_kondo.yaml: + lattice: chain + model: kondo + dimension: 1 + n_sites_uc: 2 + bonds_per_uc: {J: 1, t0: 1, "t0'": 1, "t0''": 1, V0: 1, "V0'": 1, "V0''": 1} + coordination: + A_c: {J: 1, t0: 2, "t0'": 2, "t0''": 2, V0: 2, "V0'": 2, "V0''": 2} + A_s: {J: 1} + min_size_for_check: [7] + source: {file: python/stdface/lattice/chain_lattice.py, func: chain, commit: } +``` + +- [ ] **Step 5: リンタ実行** + +Run: `python3 lattice_catalog/tools/lint_catalog.py` +Expected: `3 files, 0 errors` で exit 0 + +- [ ] **Step 6: ソース突合** + +`chain_lattice.py::chain` の `_BONDS` 3 行と YAML bonds を突合 +((0,1,...)→R=[1] 等)。onsite は `model_plugin.py` の +SpinModel/HubbardModel/KondoModel と突合(特に Kondo 両側磁場)。 +不一致があれば YAML を修正して Step 5 からやり直す。 + +- [ ] **Step 7: Commit** + +```bash +git add lattice_catalog/chain/ lattice_catalog/manifest.yaml +git commit -m "Add chain lattice catalog definitions (spin/Hubbard/Kondo)" +``` + +--- + +### Task 2: square(3模型) + +**Files:** +- Create: `lattice_catalog/square/square_{spin,hubbard,kondo}.yaml` +- Modify: `lattice_catalog/manifest.yaml` + +**Interfaces:** +- Consumes: Task 0 規約、Task 1 の chain 雛形(全面踏襲) +- Produces: なし(独立成果物) + +- [ ] **Step 1: `python/stdface/lattice/square_lattice.py` から抽出** + +確定する項目: `NsiteUC`/`tau`/`direct` 既定(幾何)、`_BONDS` 全行 +(R とサイト対と type 名)、模型別 `not_used_*`(YAML に含めない項)。 +J0/J1 の方向割当(W方向/L方向)はソースコメントと +`input_spin_nn` の名前引数で確認。 + +- [ ] **Step 2: 3 つの YAML を書く**(chain 雛形と同一構造) + +相違点: `dimension: 2`、`lattice_vectors` 2 本(ソース既定値)、 +`system.size: [4, 4] # StdFace: W, L`、 +`boundary: [{twist: {param: phase0}}, {twist: {param: phase1}}]`、 +bonds/couplings は抽出結果を全数記載(J 族は 9 成分正準形)。 +Kondo は A_c/A_s の 2 ラベル、磁場両側適用。 + +- [ ] **Step 3: manifest エントリ追加**(3 件。coordination はラベル×type +で全 type 列挙: 最近接は J0+J1 各 2、対角 `J'` 系 4。 +min_size_for_check は各方向 L > 2·max|R成分| の奇数) + +- [ ] **Step 4: リンタ実行** + +Run: `python3 lattice_catalog/tools/lint_catalog.py` +Expected: `6 files, 0 errors` + +- [ ] **Step 5: ソース突合**(`_BONDS` 全行、onsite) + +- [ ] **Step 6: Commit** + +```bash +git add lattice_catalog/square/ lattice_catalog/manifest.yaml +git commit -m "Add square lattice catalog definitions (spin/Hubbard/Kondo)" +``` + +--- + +### Task 3: triangular(3模型) + +**Files:** +- Create: `lattice_catalog/triangular/triangular_{spin,hubbard,kondo}.yaml` +- Modify: `lattice_catalog/manifest.yaml` + +**Interfaces:** Task 2 と同じ(Consumes: Task 0/1) + +- [ ] **Step 1: `python/stdface/lattice/triangular_lattice.py` から抽出** +(Task 2 Step 1 と同じ項目。格子ベクトル既定 a1=(1,0), a2=(1/2,√3/2) を +ソースで確認。t/J/V は 0,1,2 系 + p/pp) + +- [ ] **Step 2: 3 つの YAML を書く**(検算: 最近接配位数 6 = J0/J1/J2 各 2) + +- [ ] **Step 3: manifest エントリ追加** + +- [ ] **Step 4: リンタ実行** — Expected: `9 files, 0 errors` + +- [ ] **Step 5: ソース突合** + +- [ ] **Step 6: Commit** + +```bash +git add lattice_catalog/triangular/ lattice_catalog/manifest.yaml +git commit -m "Add triangular lattice catalog definitions (spin/Hubbard/Kondo)" +``` + +--- + +### Task 4: honeycomb(3模型) + +**Files:** +- Create: `lattice_catalog/honeycomb/honeycomb_{spin,hubbard,kondo}.yaml` +- Modify: `lattice_catalog/manifest.yaml` + +**Interfaces:** Task 2 と同じ + +- [ ] **Step 1: `python/stdface/lattice/honeycomb_lattice.py` から抽出** +(2 サイト A/B。J0/J1/J2 = 3 方向ボンド(Kitaev 慣例)の対応をコメントに +明記。Kondo は A_c/A_s/B_c/B_s の 4 ラベル) + +- [ ] **Step 2: 3 つの YAML を書く**(検算: 最近接配位数 3) + +- [ ] **Step 3: manifest エントリ追加** + +- [ ] **Step 4: リンタ実行** — Expected: `12 files, 0 errors` + +- [ ] **Step 5: ソース突合** + +- [ ] **Step 6: Commit** + +```bash +git add lattice_catalog/honeycomb/ lattice_catalog/manifest.yaml +git commit -m "Add honeycomb lattice catalog definitions (spin/Hubbard/Kondo)" +``` + +--- + +### Task 5: kagome(3模型) + +**Files:** +- Create: `lattice_catalog/kagome/kagome_{spin,hubbard,kondo}.yaml` +- Modify: `lattice_catalog/manifest.yaml` + +**Interfaces:** Task 2 と同じ + +- [ ] **Step 1: `python/stdface/lattice/kagome.py` から抽出** +(確認済み: 3 サイト、tau=(0,0),(1/2,0),(0,1/2)。`_BONDS` は +`kagome.py::kagome`。p 系まで、pp なし。検算: 最近接配位数 4。 +Kondo は 6 ラベル) + +- [ ] **Step 2: 3 つの YAML を書く** + +- [ ] **Step 3: manifest エントリ追加** + +- [ ] **Step 4: リンタ実行** — Expected: `15 files, 0 errors` + +- [ ] **Step 5: ソース突合** + +- [ ] **Step 6: Commit** + +```bash +git add lattice_catalog/kagome/ lattice_catalog/manifest.yaml +git commit -m "Add kagome lattice catalog definitions (spin/Hubbard/Kondo)" +``` + +--- + +### Task 6: ladder(W=2 / W=3 × 3模型 = 6件) + +**Files:** +- Create: `lattice_catalog/ladder/ladder_w2_{spin,hubbard,kondo}.yaml` +- Create: `lattice_catalog/ladder/ladder_w3_{spin,hubbard,kondo}.yaml` +- Modify: `lattice_catalog/manifest.yaml` + +**Interfaces:** Task 2 と同じ + +- [ ] **Step 1: `python/stdface/lattice/ladder.py` から抽出** + +`_BONDS` は W に依存して動的構築(`ladder.py::ladder`)。ループを読み、 +脚内(J1, J1')・ラング(J0)・斜め(J2, J2')の割当を W の関数として +文書化した上で、W=2 と W=3 の具体的ボンド集合を書き下す。 +単位胞 = 1 ラング(W サイト、ラベル A0..A{W-1})、`size: [16] # StdFace: L` +の論理 1 次元表現。rung 方向は open(セル内結合のみ)である根拠を +ソースで確認して記載。 + +- [ ] **Step 2: 6 つの YAML を書く** + +W 一般化規則(ラベルとボンドの生成則)を各ファイル冒頭コメントに記載。 +検算(W=2): 脚方向配位数 2、ラング 1。 + +- [ ] **Step 3: manifest エントリ追加**(6 件) + +- [ ] **Step 4: リンタ実行** — Expected: `21 files, 0 errors` + +- [ ] **Step 5: ソース突合**(W=2/W=3 それぞれループを手で展開して照合) + +- [ ] **Step 6: Commit** + +```bash +git add lattice_catalog/ladder/ lattice_catalog/manifest.yaml +git commit -m "Add ladder (W=2, W=3) lattice catalog definitions" +``` + +--- + +### Task 7: orthorhombic(3模型) + +**Files:** +- Create: `lattice_catalog/orthorhombic/orthorhombic_{spin,hubbard,kondo}.yaml` +- Modify: `lattice_catalog/manifest.yaml` + +**Interfaces:** +- Consumes: Task 0/1 +- Produces: 3D 格子の雛形(Task 8, 9 が参照) + +- [ ] **Step 1: `python/stdface/lattice/orthorhombic.py` から抽出** +(3D: `dimension: 3`、`size: [4,4,4] # W, L, Height`、boundary 3 方向 +`{twist: {param: phase0/1/2}}`。`_BONDS` は `(dW,dL,dH,...)` 形式。 +J0/J1/J2 = 3 軸 nn、pp の割当をソースで確認。検算: 最近接配位数 6) + +- [ ] **Step 2: 3 つの YAML を書く** + +- [ ] **Step 3: manifest エントリ追加** + +- [ ] **Step 4: リンタ実行** — Expected: `24 files, 0 errors` + +- [ ] **Step 5: ソース突合** + +- [ ] **Step 6: Commit** + +```bash +git add lattice_catalog/orthorhombic/ lattice_catalog/manifest.yaml +git commit -m "Add orthorhombic lattice catalog definitions (spin/Hubbard/Kondo)" +``` + +--- + +### Task 8: fc_ortho(3模型) + +**Files:** +- Create: `lattice_catalog/fc_ortho/fc_ortho_{spin,hubbard,kondo}.yaml` +- Modify: `lattice_catalog/manifest.yaml` + +**Interfaces:** Consumes: Task 0/1/7(3D 雛形) + +- [ ] **Step 1: `python/stdface/lattice/fc_ortho.py` から抽出** +(面心系の格子ベクトル既定を確認。J0/J1/J2 の方向割当と p/pp の範囲) + +- [ ] **Step 2: 3 つの YAML を書く** + +- [ ] **Step 3: manifest エントリ追加** + +- [ ] **Step 4: リンタ実行** — Expected: `27 files, 0 errors` + +- [ ] **Step 5: ソース突合** + +- [ ] **Step 6: Commit** + +```bash +git add lattice_catalog/fc_ortho/ lattice_catalog/manifest.yaml +git commit -m "Add face-centered orthorhombic lattice catalog definitions" +``` + +--- + +### Task 9: pyrochlore(3模型) + +**Files:** +- Create: `lattice_catalog/pyrochlore/pyrochlore_{spin,hubbard,kondo}.yaml` +- Modify: `lattice_catalog/manifest.yaml` + +**Interfaces:** Consumes: Task 0/1/7 + +- [ ] **Step 1: `python/stdface/lattice/pyrochlore.py` から抽出** +(4 副格子、FCC 格子ベクトル既定。四面体内(R=0)と四面体間の区別を +コメントに明記。検算: 最近接配位数 6) + +- [ ] **Step 2: 3 つの YAML を書く** + +**Kondo の特記事項(必須)**: 現行実装(C/Python 共通、 +`src/Pyrochlore.c` の GeneralJ 呼び出しおよび +`python/stdface/lattice/pyrochlore.py::_local`)は Kondo 結合を +**副格子 3 の遍歴サイトと全副格子(0–3)の局在スピン**の間に生成する。 +カタログはこの現行動作を忠実に再現する: + +```yaml + bonds: + # Kondo 結合: 現行実装は A3_c (副格子3の遍歴サイト) と全局在スピンを + # 結合する (他格子の副格子ごと対応と異なる。上流実装のバグの可能性 + # あり — manual 7章参照。上流修正時はカタログの versioning が必要)。 + # ソース順保持: general_j(..., isite+3, jsite+uc_i) の引数順で + # 遍歴 A3_c が常に第 1 端点 (s_i . S_j の役割と一致) + - {from: A3_c, to: A0_s, R: [0, 0, 0], type: J} + - {from: A3_c, to: A1_s, R: [0, 0, 0], type: J} + - {from: A3_c, to: A2_s, R: [0, 0, 0], type: J} + - {from: A3_c, to: A3_s, R: [0, 0, 0], type: J} +``` + +- [ ] **Step 3: manifest エントリ追加** + +- [ ] **Step 4: リンタ実行** — Expected: `30 files, 0 errors` + +- [ ] **Step 5: ソース突合**(Kondo 結合 4 本の対応を C/Python 両方で確認) + +- [ ] **Step 6: Commit** + +```bash +git add lattice_catalog/pyrochlore/ lattice_catalog/manifest.yaml +git commit -m "Add pyrochlore lattice catalog definitions (spin/Hubbard/Kondo)" +``` + +--- + +### Task 10: wannier90 Hubbard 小例 + +**Files:** +- Create: `lattice_catalog/wannier90/example_hubbard.yaml` +- Modify: `lattice_catalog/manifest.yaml` + +**Interfaces:** +- Consumes: Task 0 規約。`python/stdface/lattice/wannier90.py` + (変換アルゴリズム)、`test/wannier90_data/` または `samples/`(入力データ) +- Produces: manual 5 章(Task 12)が参照する具体例 + +- [ ] **Step 1: 変換アルゴリズムを精読して変換規則を確定** + +`wannier90.py` から以下を確定(manual 5 章の下書きを兼ねる): +- H_mn(R) → hop の符号規約(現行実装の符号反転の有無と位置) +- R=0 & m=n の対角要素 → onsite 一体項としての分離 +- Hermite 対 `(m,n,R)/(n,m,−R)` の正準対選択(現行実装がどちらを + 採用しているか)と縮退重みの扱い +- cutoff(`cutoff_t/u/j`, `cutoff_*R`, `cutoff_length_*`)の適用順 +- `lambda_U/lambda_J/alpha/doublecounting` の作用点 + +- [ ] **Step 2: 入力データを選ぶ** + +`test/wannier90_data/` と `samples/` から軌道数最小の Hubbard 用 +データセットを選ぶ。**H(_hr.dat)と U(_ur.dat)チャネルのみ使用**。 +J チャネル(_jr.dat: Hund・exchange・pair-hopping)は 4 フェルミオン項の +データモデルが未定義のため対象外(manual 5.5 章で規則を散文記述、 +7 章に制限として明記)。 + +- [ ] **Step 3: example_hubbard.yaml を書く** + +- `geometry`: _geom の格子ベクトルと Wannier 中心 → sites(W1, W2, …) +- `bonds` + `couplings`: 選んだ cutoff の**範囲内全要素**を Step 1 の + 規則で変換(上位 N 件抽出ではない)。正準対のみ列挙し、 + 排除した Hermite 対の扱いをコメントで明記。R=0 対角は onsite へ。 +- 値は実数値を直接記載(外部データ由来。param 参照不可の旨コメント)。 + H チャネルの符号反転など Step 1 で確定した規則の適用は + ファイル冒頭コメントに規則名で明記する。 +- 各要素に元ファイルの行番号をコメントで記録。 + +- [ ] **Step 4: manifest エントリ追加 + リンタ実行** + +Run: `python3 lattice_catalog/tools/lint_catalog.py` +Expected: `31 files, 0 errors` +(リンタの C8 は数値直書きを許すこと — Task 0 の実装で +`{param: ...}` 形式のみ検査対象とし、数値はスキップされる) + +- [ ] **Step 5: 検算** — 記載全要素を元データと突合、変換規則(符号・ +正準対・onsite 分離)の適用を 2 要素以上で手計算検証しコメントに残す + +- [ ] **Step 6: Commit** + +```bash +git add lattice_catalog/wannier90/ lattice_catalog/manifest.yaml +git commit -m "Add wannier90 Hubbard mapping example for the lattice catalog" +``` + +--- + +### Task 11: manual.md 前半(1–2章: 概要・キーワード対応表) + +**Files:** +- Create: `lattice_catalog/manual.md`(1–2 章) + +**Interfaces:** +- Consumes: `tools/keyword_inventory.py` の出力、CONVENTIONS.md +- Produces: manual.md の章立て(Task 12, 13 が追記) + +- [ ] **Step 1: 1 章(概要と読み方)を書く** + +内容: 三層仕様の要約、本カタログの位置づけ(experimental dialect、 +「実行検証済みではなくソース突合+リンタ検査」)、ファイル構成一覧、 +CONVENTIONS.md の規約の詳説、`{param: ...}` とパラメータ解決規則の読み方。 + +- [ ] **Step 2: 2 章(キーワード対応表)を書く** + +Run: `python3 lattice_catalog/tools/keyword_inventory.py > /tmp/inv.json` +の出力を母集合とし、**全エントリ**を分類した表を作る: + +| StdFace キーワード | 出典テーブル | 新フォーマットでの対応 | 備考 | + +分類: (a) geometry(`a`, `wx…`, `wlength…`)、(b) system(`W/L/Height`, +`phase0-2`, `box`→supercell(S) 写像)、(c) bonds+couplings(t/J/V 族全 +変種、J 成分 9 種×全 prefix)、(d) onsite(`U`,`mu`,`D`,`h`,`Gamma`, +`Gamma_y`)、(e) site_dof(`2S`)、(f) wannier90(`cutoff_*`,`lambda*`, +`alpha`,`doublecounting` → 5 章参照)、(g) 対象外(`model`,`lattice`, +`outputmode`,`ncond/nelec`,`2Sz`,`K` ほかソルバー固有の計算条件 — +理由を各行に明記) + +- [ ] **Step 3: 網羅性チェック** + +表の行数と inventory のエントリ数を照合(スクリプト出力件数と一致、 +欠落ゼロ)。カタログ YAML 中の全 `{param: ...}` が表の (a)–(f) の +いずれかに載っていることをリンタ C8 で再確認。 + +- [ ] **Step 4: Commit** + +```bash +git add lattice_catalog/manual.md +git commit -m "Add lattice catalog manual: overview and keyword correspondence table" +``` + +--- + +### Task 12: manual.md 中盤(3–5章: 格子・模型・wannier90) + +**Files:** +- Modify: `lattice_catalog/manual.md`(3–5 章を追記) + +**Interfaces:** +- Consumes: Task 1–10 の全 YAML・manifest・各タスクの突合記録 +- Produces: なし + +- [ ] **Step 1: 3 章(格子ごとの解説)を書く** + +9 格子それぞれ 1 節: 幾何(格子ベクトル・副格子表)、ボンド定義表 +(type / from–to / R / 意味)、検算(manifest 値の根拠)、出典 +(ファイル+関数+コミット)。chain の内部 2D 表現(phase0→phase[1])、 +ladder の W 一般化規則もここに記載。 + +- [ ] **Step 2: 4 章(模型ごとの演算子対応)を書く** + +- **符号表と検証連鎖**(スペック §4.3 の表): StdFace パラメータ → + builder(`interaction_builder.py`)→ trans/intr 係数 → solver 規約 + (HPhi trans.def の H=−Σt 暗黙符号)→ 物理符号、の導出を明記。 +- Spin: 9 成分正準形とパラメータ解決規則(成分キーワード 9 種の表、 + 解決順序: 成分局所 > 成分大域 > スカラー局所 > スカラー大域 > 0)、 + 等方入力・異方入力・同時指定エラーの 3 例。 +- Hubbard: hop / density-density / onsite の定義(数式)、scale による + 符号表現、複素 t と反転同値(共役)。 +- Kondo: 2 ラベル表現と端点順序(遍歴第 1)、磁場両側適用、 + サイト倍加(前半=局在)との対応、GC 変種(粒子数条件は solver 層)。 + +- [ ] **Step 3: 5 章(wannier90 変換仕様)を書く** + +Task 10 Step 1 で確定した規則を模型別に文書化: +- Hubbard: H/U チャネルの変換(符号反転、onsite 分離、Hermite 正準対、 + 縮退重み、cutoff、λ/α、doublecounting) +- Spin: 超交換 `2|t_mn|^2(1/U_m+1/U_n)` 生成の現行アルゴリズムと、 + 直接写像との差異 +- **5.5 J チャネル**: Hund・exchange・pair-hopping の変換規則を散文で + 記述し、YAML 例が対象外である理由(4 フェルミオン項スキーマ未定義)と + 一般項スキーマの素描(6 章の拡張提案 6 項)を示す +- example_hubbard.yaml の読み解き + +- [ ] **Step 4: Commit** + +```bash +git add lattice_catalog/manual.md +git commit -m "Add lattice catalog manual: per-lattice, per-model, and wannier90 chapters" +``` + +--- + +### Task 13: manual.md 後半(6–7章)+ README + 最終検証 + +**Files:** +- Modify: `lattice_catalog/manual.md`(6–7 章を追記) +- Create: `lattice_catalog/README.md` + +**Interfaces:** +- Consumes: 全タスクの成果物 +- Produces: 完成した一式 + +- [ ] **Step 1: 6 章(仕様拡張提案)を書く** + +スペック §4.6 の 6 項目(fermion site_dof、1 サイト演算子語彙、 +名前付き 2 体演算子と端点順序の意味論、`{param, scale, default}` 参照の +許容箇所、catalog ヘッダ、4 フェルミオン一般項の素描)を、 +それぞれ tensor_terms への展開形・型・意味論つきで draft への +追記提案として記述。 + +- [ ] **Step 2: 7 章(既知の制限・未対応事項)を書く** + +- oracle 比較(数値同値性)未実施 — 展開エンジン実装時の課題 +- ladder は W=2/3 の例のみ(一般 W は生成規則の文書) +- wannier90 は Hubbard の H/U チャネル例のみ。J チャネル + (4 フェルミオン項)は散文記述のみ、Spin/Kondo も仕様記述のみ +- pyrochlore Kondo の `isite+3` 挙動(上流バグ疑い、現行動作を記載。 + 上流修正時はカタログの versioning が必要) +- box 行列は写像説明のみで YAML 例なし +- 機械的識別子(prime を含む type 名)の分離は仕様確定時の課題 +- 多体項(3 体以上)は現行 StdFace に存在しないため対象外 +- YAML・manifest・manual の三重記載はリンタと inventory の機械照合で + 緩和しているが、ソース変更時は三箇所の同期更新が必要 + +- [ ] **Step 3: README.md を書く** + +一式の目的(1 段落)、ディレクトリ構成、リンタの使い方、manual.md への +案内、参照仕様(格子定義仕様 draft 2026/07/27)への言及。 + +- [ ] **Step 4: 最終検証** + +Run: `python3 lattice_catalog/tools/lint_catalog.py` +Expected: `31 files, 0 errors` + +Run: `python3 lattice_catalog/tools/keyword_inventory.py | python3 -c "import json,sys; print(len(json.load(sys.stdin)),'keywords')"` +の件数と manual 2 章の表の行数が一致することを確認。 + +- [ ] **Step 5: Commit** + +```bash +git add lattice_catalog/ +git commit -m "Complete lattice catalog manual and README" +``` diff --git a/docs/superpowers/specs/2026-08-15-lattice-catalog-design.md b/docs/superpowers/specs/2026-08-15-lattice-catalog-design.md new file mode 100644 index 0000000..d4b4018 --- /dev/null +++ b/docs/superpowers/specs/2026-08-15-lattice-catalog-design.md @@ -0,0 +1,264 @@ +# StdFace 格子カタログ(新フォーマット対応一式)設計書 + +- 日付: 2026-08-15(Codex デザインレビュー Round 1・Round 2 反映済み) +- ブランチ: `lattice-catalog` +- 参照仕様: 「格子定義仕様 (draft)」2026/07/27 + (PASUMS 共有ドライブ `19. StdFace/1. 打ち合わせ/20260727/stdface_lattice_spec.pdf`) + +## 1. 目的 + +現行 StdFace が定義する全格子・全相互作用タイプを、新しい三層格子定義仕様 +(geometry / system / model)へ網羅的に対応させ、 + +1. 格子×模型ごとの新フォーマット YAML 定義ファイル(静的カタログ) +2. 対応関係を説明する日本語マニュアル +3. カタログの構造的正しさを機械検査する意味検査リンタ + manifest + +の一式を作成する。変換ツール(stan.in → YAML)と展開エンジンはスコープ外。 + +### 位置づけ + +- YAML は draft 仕様に**拡張方言**(experimental extensions、§4.6)を加えた + 形式。各ファイル先頭で + `catalog: {schema: stdface-catalog/0.1, dialect: experimental}` を宣言。 +- 主張する検証水準: (a) 現行実装ソースとの突合、(b) リンタによる構造・ + 整合検査(計数展開による配位数実測を含む)、(c) manifest 検算。 + 数値同値性(oracle 比較)は主張しない。 + +## 2. スコープ + +### 対象 + +- **格子 9 種**: chain, ladder(W=2 / W=3 の 2 例), square, triangular, + honeycomb, kagome, orthorhombic, fc_ortho, pyrochlore +- **wannier90**: 模型別変換仕様の章 + **H(hopping)・U(Coulomb)チャネル + のみの Hubbard 小規模例** 1 件(J チャネルは §5.5 参照) +- **模型 3 種**: Spin / Hubbard / Kondo(GC 変種は粒子数条件のみ → + solver 層の扱いとしてマニュアルに明記) +- **相互作用の語彙**(現行実装から抽出・検証済み): + - ホッピング t 族(複素)、`U`、`mu`、V 族、J 族(3×3 テンソル、成分 + キーワード `{x,y,z,xy,xz,yx,yz,zx,zy}`、`x`=xx 対角) + - `D`、`h, Gamma, Gamma_y`、`phase0–2`(度)、`box` +- **YAML 件数**: (8 格子 + ladder×2) × 3 模型 = 30 件 + wannier90 1 件 = 31 件 + +### 対象外 + +- 展開エンジン、stan.in 変換ツール、数値 oracle 比較 +- wannier90 J チャネル(Hund・exchange・pair-hopping)の YAML 例 + (4 フェルミオン項のデータモデルが未定義のため。§5.5 で規則を散文 + 記述し、一般項スキーマの素描を将来課題として示す) +- 計算条件系キーワード → 対応表で「対象外」と分類 +- draft 本体の改訂(拡張は提案として記載) + +## 3. 成果物の構成 + +``` +lattice_catalog/ + README.md / manual.md / CONVENTIONS.md + manifest.yaml # 機械可読の検算台帳 + tools/ + lint_catalog.py # 意味検査リンタ(計数展開器を含む) + keyword_inventory.py # キーワード目録生成(レジストリ走査) + test_tools.py # tools の自動テスト(開発時専用) + chain/ ladder/ square/ triangular/ honeycomb/ kagome/ + orthorhombic/ fc_ortho/ pyrochlore/ + wannier90/example_hubbard.yaml +``` + +## 4. 対応規約 + +### 4.1 geometry / system + +- 幾何は現行実装から抽出。サイト順序は `geometry.sites` の**配列順** = + 仕様 §4.2 の「サイト番号」。 +- `W, L, Height` → `system.size`。`phase0–2` → `{twist: {param: phaseN}}` + (**度単位**、境界 n 回横断で `exp(i·n·π·θ/180)`)。 +- chain は論理 1 次元(内部 W=1 2D 表現、`phase0`→`phase[1]` 転写は + manual 3 章)。 +- `box` → `supercell(S)` 写像(`A_super = S·A` 行ベクトル規約、 + det(S)≠0、`W/L/Height` との排他)はマニュアル説明のみ。 + +### 4.2 ボンド(model.bonds)— ソース順保持 + +- **R の定義**: `R = cell(to) − cell(from)`。δ = (frac_to − frac_from) + R·A。 +- **向き**: **参照実装のソース順をそのまま保持する** + (`_BONDS` テーブルの `site_i → site_j`、Kondo 結合は + `general_j(..., isite, jsite)` の引数順 = 遍歴が第 1)。 + 正準形への並べ替えは**行わない**(並べ替えは複素 hopping の共役・ + 交換テンソルの転置を要求し、単一の couplings キーでは表現できない + ため。Round 2 指摘)。 +- **一意性**: 各ボンドは一度だけ書く。リンタが**反転同値** + `(i,j,R) ≡ (j,i,−R)` での重複を検出する(反転時の係数変換 + — hopping: 複素共役、交換テンソル: 転置 — は消費側の規範として + CONVENTIONS に記載)。 +- type 名 = StdFace キーワード名(プライムは引用符付き)。 + 機械的識別子の分離は将来課題(manual 7 章)。 +- 出典: ファイル + 関数名 + 参照コミットハッシュ(行番号は補助)。 + +### 4.3 係数の意味論と符号(規範) + +- **value 意味論**: `H = Σ_bonds value·(operator) + Σ_onsite value·(operator)` + の**物理ハミルトニアン係数**。solver 出力ファイル(HPhi trans.def 等)の + 係数規約(H_trans = −Σ t c†c の暗黙符号)とは**別物**であることを + manual に明記し、以下の**検証連鎖**で突合する: + `StdFace パラメータ → builder 呼び出し(interaction_builder.py) + → trans/intr 係数 → solver 規約 → 物理符号`。 +- **符号表**(検証済み。manual 4 章に導出つきで記載): + + | StdFace | 物理ハミルトニアン寄与 | YAML 表現 | + |---|---|---| + | t 族 | −t Σσ (c†c + h.c.) | `value: {param: t0, scale: -1.0}` | + | mu | −mu N | onsite `coeff: -1.0`(ops [N]) | + | U | +U n↑n↓ | `coeff: +1.0` | + | V 族 | +V n_i n_j | `scale: +1.0`(省略可) | + | J 族 | +Σ_ab J_ab S^a S^b | tensor_terms(§4.4) | + | h/Gamma/Gamma_y | −h Sz −Γ Sx −Γy Sy | `coeff: -1.0` | + | D | +D (Sz)² | `coeff: +1.0` | + | Kondo J | +J s·S | `scale: +1.0` | + +- **符号は必ずデータ(scale / coeff)に持たせ、コメントに置かない。** +- **param 参照の一般形**(拡張方言): + `{param: <名>, scale: <実数, 省略時 1.0>, default: <最終値, 省略時 0>}` + → **param 指定時**: 値 = scale × param。 + **param 未指定時**: 値 = default(**スケールは適用しない最終値**)。 + 例: `{param: 2S, scale: 0.5, default: 0.5}` → 2S=1 指定で S=0.5、 + 未指定でも S=0.5。この条件分岐は C7 検査とツールテストに明記する。 +- wannier90 の符号規則は実装検証の結果、物理ホッピング係数 = **+H_mn** + (wannier90 経路の `−Cphase` 負号と solver 規約の負号が相殺。 + Task 10 で `trans.def` 実出力により確認)。固定格子の t 族 + (scale −1)との違いとして manual 5 章に明記。 + +### 4.4 J テンソルとパラメータ解決(規範) + +- J 族は 9 成分 tensor_terms 正準形(`coeff: {param: J0xy}` 等)。 +- **解決順序**(`input_params.py::_resolve_spin_matrix` と同一): + 1. 局所成分(`J0xy` 等) + 2. **大域成分**(`Jxy` 等) + 3. 局所スカラー `J0`(対角のみ) + 4. 大域スカラー `J`(対角のみ) + 5. 0 +- **競合規則**(`input_spin_nn` と同一): スカラー同士(J vs J0)、 + スカラー vs 行列(全 4 組合せ)、行列 vs 行列(J0 成分と J 成分の + 同時指定)はエラー。プライム系(`input_spin`)は大域 fallback なし + (`J0'` スカラー vs `J0'` 成分のみ)。prefix ごとの解決表・競合表を + CONVENTIONS に規範として列挙する。 +- 解決の実行者は**カタログ消費側**(resolver)。カタログは規範表を + 提供する(入力契約)。出力契約は「ボンドごとの解決済み数値係数」。 + +### 4.5 模型ごとの演算子 + +- 演算子語彙: `hop` = Σσ (c†_iσ c_jσ + h.c.)(符号なし)、 + `density-density` = n_i n_j、`s_i . S_j`(**第 1 端点 = 遍歴**。 + 端点順序に意味があり、ソース順保持(§4.2)により保証)、 + onsite: `N, Nup, Ndn, NupNdn, Sx, Sy, Sz, Szz`。 +- 演算子と site_dof の型整合(リンタ検査): `hop`/`density-density` は + fermion–fermion、`s_i . S_j` は fermion–spin(この順)、J テンソルは + spin–spin、onsite スピン演算子は spin または fermion(電子スピン)。 +- **Spin**: J 族 §4.4、D、磁場(符号表)。 +- **Hubbard**: t/U/mu/V + 磁場(電子スピン)。 +- **Kondo**: `_c`(fermion)+ `_s`(spin、同一分率座標、 + 1 物理サイト 2 自由度)。Hubbard 一式は `_c`、磁場は**両側**、 + J は `_c → _s`(遍歴第 1)。 + - **pyrochlore の例外**: 現行実装(C/Python 共通)は J を + 「副格子 3 の遍歴サイト ↔ 全副格子の局在スピン」に生成 + (`src/Pyrochlore.c` GeneralJ / `pyrochlore.py::_local`)。 + カタログは現行動作を忠実に再現し(from は遍歴 `A3_c`)、 + 上流バグの可能性と、上流修正時のカタログ versioning が必要に + なる旨を注記する。 +- **2S**: `spin: {param: 2S, scale: 0.5, default: 0.5}` + (spin 値 = S = 0.5 × 2S。param 未指定時 S=0.5。型: 2S は正整数)。 + +### 4.6 仕様への拡張提案(マニュアル 6 章) + +1. `site_dof` フェルミオン `{fermion: {orbitals: n}}` +2. 1 サイト演算子語彙(N 系・S 系・Szz)と展開形 +3. 名前付き 2 体演算子(`hop`, `density-density`, `s_i . S_j`)と + 端点順序の意味論 +4. param 参照 `{param, scale, default}`(value / coeff / spin / twist) +5. `catalog:` ヘッダ(schema/dialect) +6. (素描のみ)4 フェルミオン一般項: 順序付き生成消滅演算子列と + site/orbital 束縛を持つ項表現。named operator はその省略記法。 + wannier90 J チャネルの記述に将来必要(今回は対象外)。 + +## 5. マニュアル構成(manual.md) + +1. 概要と読み方(位置づけ、CONVENTIONS 詳説、param 参照と解決規則) +2. キーワード対応表(母集合 = レジストリ走査による機械的 inventory。 + canonical キーワード単位に集約し出典を配列で保持。格子名・模型名の + alias は registry から別表で生成) +3. 格子ごとの解説(幾何、ボンド表、manifest 検算の根拠、出典) +4. 模型ごとの解説(**符号表と検証連鎖の導出**、解決規則、Kondo 対応、 + GC 変種) +5. wannier90 変換仕様(模型別): + - Hubbard: H_mn(R) の符号規則(反転なし、物理係数 = +H_mn)、R=0 対角の onsite 分離、Hermite + 正準対と縮退重み、cutoff、λ/α、doublecounting + - Spin: 超交換 `2|t|²(1/U_m+1/U_n)` 生成 + - **5.5 J チャネル**: Hund・exchange・pair-hopping の変換規則を散文で + 記述し、YAML 例は対象外である理由(4 フェルミオン項スキーマ未定義) + と §4.6-6 の素描を示す +6. 仕様拡張提案(§4.6) +7. 既知の制限(oracle 比較なし、ladder W=2/3 のみ、wannier90 J チャネル + 例なし、pyrochlore Kondo 現行動作固定と versioning、機械的識別子) + +## 6. 検証方法 + +### 6.1 リンタ(`tools/lint_catalog.py`) + +構造検査(C1–C9)+ manifest 突合(C10)+ **計数展開**(C11): + +- C1 catalog ヘッダ(schema **と dialect** の値、および `lattice`/`model` + メタデータ — C10 の照合元。例: + `catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: chain, model: spin}`) +- C2 schema 検査(null 文書、必須キー、型、サイトラベル重複、 + dimension/R/size の整数・次元整合) +- C3 R 次元 = dimension = size 次元 +- C4 ラベル整合(bonds の from/to、**onsite のラベル**、 + geometry.sites と site_dof の集合一致) +- C5 type ↔ couplings 整合(未定義参照・未使用定義) +- C6 反転同値での重複検出。同値キーは **type を含む** + `(type, i, j, R) ≡ (type, j, i, −R)`(同一幾何ボンド上の t/V 共存は正当) +- C7 param 参照の目録整合(scale/default の型検査を含む) +- C8 J coupling の 9 成分完全性と **ops 対 ↔ param 接尾辞の対応** + (`[Sx,Sy] ↔ …xy` 等)。**総項数 = 9 かつ ops 対の重複はエラー** + (重複項は交換係数の二重加算になるため) +- C9 演算子と site_dof の型整合(§4.5 の表)、tensor_terms の ops 長 +- C10 manifest 全項目突合(lattice/model/dimension/n_sites_uc/ + bonds_per_uc/source の存在) +- C11 **計数展開**: min_size トーラス上に bonds を展開し、 + サイトラベル×type ごとの配位数を実測して manifest の + `coordination: {label: {type: count}}` と比較(ladder W=3 の + 非一様配位、Kondo 重複座標もラベル単位で扱える) +- 実装要件: 不正 YAML でも例外で落ちずファイル単位で診断、 + 相対パス入力の解決、`test_tools.py` に C1–C11 の正例・負例テスト + +### 6.2 その他 + +- ソース突合(`_BONDS`・`model_plugin.py`・`input_params.py`) +- `keyword_inventory.py` はソルバー**レジストリ経由**で列挙 + (クラスのハードコード禁止)、canonical 集約、格子/模型 alias 出力 +- 数値 oracle 比較は対象外(§2) + +## 7. 進め方 + +Task 0(規約・schema・リンタ・manifest・目録 + tools 自動テスト)→ +Task 1 chain 雛形 → 各格子 → wannier90 → manual。コミットは Task 単位。 + +## 8. 決定事項の記録 + +初回(ユーザー承認済み): 静的カタログ+マニュアル / 全 3 模型 / +wannier90 例あり / `lattice_catalog/` / 日本語 / 自己完結型 / +type 名 = StdFace 名 / Kondo 2 ラベル + +Round 1 対応(ユーザー判断): リンタ+manifest / pyrochlore 現行動作忠実 / +wannier90 模型別仕様+Hubbard 例 / ladder W=2・W=3 + +Round 2 対応(設計判断、検証に基づく): +- 係数 = 物理ハミルトニアン規約と確定(Codex の符号指摘は HPhi の + H_trans = −Σt 規約の見落としで、物理符号としては −t/−mu/−h が正。 + ただし意味論が未規範だった点は正当 → 符号をデータに持たせ scale を導入) +- ボンドはソース順保持(正準化強制を撤回) +- 解決順序を実装通り(成分局所 > 成分大域 > スカラー局所 > スカラー大域)に修正 +- 2S は scale 付き param 参照 +- wannier90 例は H+U チャネルのみ(J チャネルはデータモデル未定義のため + 散文記述+将来スキーマ素描) +- manifest coordination をラベル×type に、リンタに計数展開(C11)を追加 diff --git a/lattice_catalog/CONVENTIONS.md b/lattice_catalog/CONVENTIONS.md new file mode 100644 index 0000000..09de2cc --- /dev/null +++ b/lattice_catalog/CONVENTIONS.md @@ -0,0 +1,364 @@ +# lattice_catalog Authoring Conventions (stdface-catalog/0.1) + +This document defines the normative conventions that the YAML catalogs under `lattice_catalog/` must follow. +The reference specification is "Lattice Definition Specification (draft)", 2026/07/27 (hereafter the "draft spec"). +Where this document and the draft spec conflict, the draft spec takes precedence for the parts it covers, +and this document is normative for matters the draft does not address (experimental extensions). +For the design rationale, see §4/§6 of `docs/superpowers/specs/2026-08-15-lattice-catalog-design.md`. + +--- + +## 1. Positioning and the dialect declaration + +Every YAML file must begin with the following header. + +```yaml +catalog: + schema: stdface-catalog/0.1 + dialect: experimental + lattice: # e.g. chain, square, kagome, ... + model: # e.g. spin, hubbard, kondo +``` + +- `schema` is the version identifier for this convention document. Fixed value `stdface-catalog/0.1`. +- `dialect` is a fixed value, `experimental`, indicating an extension dialect relative to the draft spec + (see §7). +- `lattice` / `model` are the source used for the manifest cross-check (linter check C10). + They must match the `lattice` / `model` of the corresponding entry in + `lattice_catalog/manifest.yaml`. +- The parts that conform to the draft spec (the geometry / system / model three-layer structure itself) + and the extension dialect items enumerated in §7 of this document (fermion site_dof, the operator + vocabulary, `{param, scale, default}` references, the `catalog:` header, etc.) + are treated as distinct. For matters the draft does not specify, the conventions in this document + are the sole normative reference. + +## 2. File structure + +Every YAML file is self-contained and has the following four elements as top-level keys. + +```yaml +catalog: { ... } # §1 +geometry: { ... } # §3 +system: { ... } # §4 +model: { ... } # §5, §6 +``` + +References to other files (via `include` etc.) are not used. 1 file = 1 lattice × 1 model. + +## 3. geometry conventions + +- `geometry.sites` is an array, and **the array order matches the "site number" of draft spec + §4.2**. That is, `sites[0]` corresponds to site 0 in the spec, `sites[1]` to site 1, and this + correspondence is maintained mechanically. +- Site labels (`sites[*].label`) use the conventional names from the spec document or the source + implementation (`A`, `B`, `A3`, etc.) and must not be duplicated within a file (C2). +- `geometry` holds the unit cell's lattice vectors `geometry.lattice_vectors` + (a dictionary of named vectors `a1`, `a2`, `a3`, ... for as many dimensions as there are; + the matrix `A` in §5 is these stacked as row vectors), and each site's + fractional coordinates `frac`. + +## 4. system conventions + +- Repeat counts such as `W, L, Height` are mapped to `system.size` (an integer array). + `system.size` only indicates a representative value for stan.in and is independent of the + linter's check size (the manifest's `min_size_for_check`). `min_size_for_check` + is a check size derived independently from the maximum `|R|` component of each bond, + and for each direction it is the smallest odd number exceeding `2 * max|R|`. +- `phase0`-`phase2` are mapped to `system.boundary` (an array whose elements are each + `{twist: {param: phaseN}}`), and the phase factor for a path crossing the boundary + n times is interpreted by the consumer as `exp(i · n · π · θ / 180)` + (**in degrees**). `{param: phaseN}` itself is expressed in the general form of §6.3. +- The chain lattice is logically one-dimensional, but the current implementation internally + uses a two-dimensional representation with `W=1`. The transcription from `phase0` to the + internal `phase[1]` is an implementation detail, explained in manual chapter 3 (it does not + affect the YAML's semantics). +- `box` (the supercell transformation matrix) corresponds to `system.supercell` (row-vector + convention `A_super = S · A`, `det(S) ≠ 0`). `supercell` and `W/L/Height` + (= `size`) are used exclusively of each other. The details of this correspondence are + documented only in the manual; this catalog's YAML uses the `size` representation as the base. + +## 5. bonds conventions + +- **Definition of the cell difference R**: `R = cell(to) − cell(from)` (an integer vector, + whose dimension matches `dimension`). +- **Definition of the displacement δ**: `δ = (frac_to − frac_from) + R · A` + (`A` is the matrix formed by stacking the row vectors `a1`, `a2`, ... of + `geometry.lattice_vectors`). +- **type names**: Use StdFace's keyword names as-is + (`J0`, `J0'`, `t0`, etc.). Names containing a prime are written in YAML with + quotes (`"J0'"`). Splitting primes into a mechanical identifier is a future task + (manual chapter 7). +- **Direction (source-order preservation)**: The `from` → `to` direction of a bond + preserves the source order of the reference implementation as-is. + - Ordinary bonds: the `site_i → site_j` order in the `_BONDS` table. + - Kondo coupling: the argument order of `general_j(..., isite, jsite)` + (**the itinerant site is the first argument**). + Reordering into a canonical form is not performed. Reordering would require the complex + conjugate of complex hopping and the transpose of the exchange tensor, which cannot be + expressed with a single `couplings` key + (design §4.2, Round 2 decision). +- **Uniqueness check**: Each bond is described exactly once. The linter detects duplicates + under **reversal equivalence** `(type, i, j, R) ≡ (type, j, i, −R)` (C6). + It is valid for different `type`s (e.g. `t0` and `V0`) to coexist on the same + geometric bond; this is distinguished by including `type` in the equivalence + key. +- **Coefficient transformation under reversal (normative for the consumer)**: When reading + `(i,j,R)` as `(j,i,−R)`, + - hopping (complex number): take the complex conjugate (`t_ij = conj(t_ji)`). + - exchange tensor (J family, 3×3): take the transpose (`J_ij = J_ji^T`). + Since the catalog itself is described uniquely in source order, this transformation is a + norm needed only when the **consumer of the catalog** (the resolver/expansion engine) + performs a reversal reinterpretation; catalog authors only need to write things in source + order. + +## 6. couplings / onsite conventions + +### 6.1 value semantics + +`model.couplings[].value` (for scalar/vector-family couplings: `hop` / +`density-density` / `s_i . S_j`) and +`model.onsite[][].value` are + +``` +H = Σ_bonds value · operator + Σ_onsite value · operator +``` + +that is, they are the **coefficient of the physical Hamiltonian**. Note that this is +**distinct** from the coefficient convention of HPhi's solver output files such as +`trans.def` (where the sign is implicitly reversed, as in +`H_trans = −Σ t c†c`). The correspondence between the two is cross-checked +via the following verification chain (documented with derivations in manual chapter 4): + +``` +StdFace parameters → builder call (interaction_builder.py) +→ trans/intr coefficients → solver output convention → sign of the physical Hamiltonian +``` + +**J-family / onsite exception**: The J-family exchange interaction +(`model.couplings[].operator.tensor_terms`) has no shared `value`; +each component term individually carries `coeff: {param: ...}` (§6.4). Each onsite +term (`model.onsite[][]`) likewise takes the form +`operator: {tensor_terms: [{ops: [...], coeff: }]}`, but here +`tensor_terms` is a single-element array whose `coeff` is a **literal number** +representing sign only (`+1.0` / `-1.0`, etc.). The actual external parameter +reference is carried by that same term's `value` (`{param, scale, default}`, §6.3). + +**Values sourced from external data (wannier90 example)**: For concrete numeric values +read from external data such as `_ur.dat` (e.g. measured values of `H_mn(R)`), it is +acceptable to write a numeric literal directly in `value` (the general form +`{param, scale, default}` is not required). Since C7 scans only dict-typed `value`s +that carry a `param` key via `_find_param_refs`, a non-dict `value` (a numeric +literal) is outside the scope of that check +(see `lattice_catalog/wannier90/example_hubbard.yaml`). + +### 6.2 Sign table (normative) + +| StdFace | Contribution to physical Hamiltonian | YAML representation | +|---|---|---| +| t family (hopping) | −t Σ_σ (c†c + h.c.) | `couplings[t0]: {operator: hop, value: {param: t0, scale: -1.0}}` | +| mu (chemical potential) | −mu N | onsite `operator.tensor_terms: [{ops: [N], coeff: -1.0}]`, `value: {param: mu}` | +| U (onsite Coulomb) | +U n↑n↓ | onsite `operator.tensor_terms: [{ops: [NupNdn], coeff: 1.0}]`, `value: {param: U}` | +| V family (intersite Coulomb) | +V n_i n_j | `couplings[V0]: {operator: density-density, value: {param: V0}}` (scale may be omitted, default +1.0) | +| J family (exchange interaction) | +Σ_ab J_ab S^a S^b | `couplings[J0]: {operator: {tensor_terms: [...]}}` (§6.4) | +| h / Gamma / Gamma_y (magnetic field) | −h Sz − Γ Sx − Γy Sy | onsite `operator.tensor_terms: [{ops: [Sz/Sx/Sy], coeff: -1.0}]`, `value: {param: h/Gamma/Gamma_y}` | +| D (single-ion anisotropy) | +D (Sz)² | onsite `operator.tensor_terms: [{ops: [Szz], coeff: 1.0}]`, `value: {param: D}` | +| Kondo J (s·S coupling) | +J s·S | `couplings[J]: {operator: "s_i . S_j", value: {param: J}}` (+1.0 if scale is omitted) | + +**The sign must always be carried in the data (`scale` / `coeff`), never written as a +comment.** This is a required convention to guarantee verifiability (mechanical cross-checking +by the linter and downstream processing). + +### 6.3 General form of param references + +`{param, scale, default}` is an extension dialect (§7) with the following general form. + +```yaml +value: {param: , scale: , default: } +``` + +- **If param is specified (by the consumer's input)**: value = `scale × param`. +- **If param is not specified**: value = `default` (**treated as the final value, with + scale not applied**). + +That is, `scale` is "a multiplier that applies only when param is given," and +`default` is "the final value when param is absent," not the product with `scale`. +This branching is itself normative and is fixed by the C7 check and the tool tests +(`test_tools.py`). + +Example: `{param: 2S, scale: 0.5, default: 0.5}` +- If `2S=1` is given → S = 0.5 × 1 = 0.5. +- If `2S` is not given → S = 0.5 (`default` is taken as-is, + `scale` is not applied). + +Type constraints: `scale` is a real number, `default` is a number (integer or real, either +is acceptable). Type constraints for individual parameters follow the semantics of each +keyword (e.g. `2S` is a positive integer). + +The wannier90 hop channel follows a different rule from the above: `wannier90.py:: +_apply_hopping_terms` passes the nonlocal term as `hopping(StdI, -Cphase*tUJ[0][it], +jsite, isite, dR)` (the builder call itself carries a sign flip), and this +cancels with the solver-side sign flip of trans.def (§6.1), with the result that +**the physical hopping coefficient is `+H_mn(R)` itself (no sign flip)** +(the flip `H_mn → −H_mn` does not occur). The verified derivation is documented +separately in Section 5.2 of the manual (this is outside the scope of this catalog's +`{param, scale, default}` general form). + +### 6.4 Canonical form of the J-family 9-component tensor_terms + +The J-family exchange interaction is expressed as the 9 components of +`model.couplings[].operator.tensor_terms` (it is not reduced to a single parameter +such as an isotropic `J0` -- all 9 terms are always written out in full). Each term +consists of a product of two spin operators `ops: [S?, S?]` and its +coefficient `coeff: {param: }`. + +Correspondence table between ops pairs and param suffixes: + +| ops pair | suffix | example (prefix=J0) | +|---|---|---| +| `[Sx, Sx]` | `x` | `J0x` | +| `[Sy, Sy]` | `y` | `J0y` | +| `[Sz, Sz]` | `z` | `J0z` | +| `[Sx, Sy]` | `xy` | `J0xy` | +| `[Sx, Sz]` | `xz` | `J0xz` | +| `[Sy, Sx]` | `yx` | `J0yx` | +| `[Sy, Sz]` | `yz` | `J0yz` | +| `[Sz, Sx]` | `zx` | `J0zx` | +| `[Sz, Sy]` | `zy` | `J0zy` | + +Note that for the diagonal components (`x`, `y`, `z`), both ends of `ops` are the same +operator, while for off-diagonal components (`xy`, etc.), they are an ordered product of +different operators (`xy` and `yx` are independent parameters). + +### 6.5 Parameter resolution order (implementation-conformant) + +The value of each component is resolved with the same priority order as +`input_params.py::_resolve_spin_matrix` (the catalog provides this resolution rule as a +norm; the actual resolution is performed by the **catalog consumer** (the resolver). The +catalog's output contract is "resolved numeric coefficients per bond"): + +1. Component-local (e.g. `J0xy`) +2. Component-global (e.g. `Jxy`) +3. Scalar-local, diagonal only (e.g. `J0`, applies only to the `x=y=z` components) +4. Scalar-global, diagonal only (e.g. `J`, applies only to the `x=y=z` components) +5. 0 (default) + +**Conflict rules** (identical to `input_spin_nn`. All of the following combinations are +detected as errors): + +- Scalar vs. scalar: `J` (global scalar) and `J0` (local scalar) specified at the same time. +- Scalar vs. matrix (all 4 combinations): `J` vs. `J` (matrix), + `J` vs. `J0` (matrix), `J0` (scalar) vs. `J` (matrix), + `J0` (scalar) vs. `J0` (matrix). +- Matrix vs. matrix: components of `J0` and components of `J` specified at the same time. + +**Exception for the primed series** (identical to `input_spin`): primed series such as +`J0'`, `J0''`, `J1'`, etc. have **no global fallback**. That is, only the conflict +between the scalar version `J0'` and the component version `J0'xy` is checked for +`J0'xy`, and the corresponding global variable (`J'`, etc.) never appears in the +fallback chain. + +Resolution table by prefix (summary): + +| prefix series | local component | local scalar | global component fallback | global scalar fallback | +|---|---|---|---|---| +| `J0`, `J1`, `J2` (nearest-neighbor series) | yes | yes | `J` components | `J` (scalar) | +| `J0'`, `J0''`, `J1'`, ... (primed series) | yes | yes | none | none | +| `J` (the global itself) | -- | -- | -- | -- | + +### 6.6 Operator semantics and endpoint order + +- `hop` = Σ_σ (c†_iσ c_jσ + h.c.) (unsigned. The sign is carried in + `value`'s `scale`/`coeff` -- §6.2). +- `density-density` = n_i n_j. +- `s_i . S_j` (Kondo coupling): **the first endpoint (i) is the itinerant electron spin, + the second endpoint (j) is the localized spin**. Endpoint order is meaningful, and the + order is guaranteed by the source-order-preservation convention of §5. +- onsite operator vocabulary: `N`, `Nup`, `Ndn`, `NupNdn`, `Sx`, `Sy`, `Sz`, `Szz`. + These appear as elements of + `model.onsite[][].operator.tensor_terms[0].ops` (a single operator; + see the exception in §6.1). + +Type-compatibility table between operators and `site_dof` (checked by linter C9): + +| operator | required site_dof types (endpoint order) | +|---|---| +| `hop` (couplings, `operator` string) | fermion - fermion | +| `density-density` (couplings, `operator` string) | fermion - fermion | +| `s_i . S_j` (couplings, `operator` string) | fermion - spin (in this order, the first endpoint is fermion) | +| J tensor (couplings, `operator.tensor_terms`, ops are `S?`) | spin - spin | +| onsite spin operators (`Sx`/`Sy`/`Sz`/`Szz`) | spin, or fermion (as the electron spin) | +| onsite `N`/`Nup`/`Ndn`/`NupNdn` | fermion | + +Applicable onsite scope by model (same content as the Global Constraints table): + +| model | terms that may appear onsite | +|---|---| +| Spin | magnetic field (`h`, `Gamma`, `Gamma_y`), single-ion anisotropy `D` | +| Hubbard | `mu` (chemical potential), `U`, magnetic field (`h`/`Gamma`/`Gamma_y` for the electron spin) | +| Kondo | the `_c` label carries the full Hubbard set (`mu`, `U`, magnetic field), the `_s` label carries the magnetic field, and both labels carry the magnetic field (§6.7) | + +### 6.7 Kondo's two-label convention + +The Kondo model represents 1 physical site as **two geometry labels** +(`_c` = the fermion degree of freedom of the itinerant electron, `_s` = the spin +degree of freedom of the localized spin). Both labels share **the same fractional +coordinate**, but physically represent 2 degrees of freedom on 1 site. + +- The full Hubbard set (`t`, `U`, `mu`) applies only to the `_c` label. +- The magnetic field (`h`, `Gamma`, `Gamma_y`) applies to **both** the `_c` and `_s` + labels (per the sign table in §6.2). +- Kondo `J` (`s_i . S_j`) is in the order `_c → _s` (the itinerant one is the first + endpoint, §6.6). +- **Pyrochlore exception**: the current implementation (common to C/Python) generates J + in an asymmetric form, "the itinerant site of sublattice 3 ↔ the localized spins of + all sublattices" (`GeneralJ` in `src/Pyrochlore.c` / + `python/stdface/lattice/pyrochlore.py::_local`). This catalog faithfully reproduces the + behavior of the current implementation as-is (`from` is fixed to the itinerant site + `A3_c`). This may be a bug in the upstream implementation, but since this catalog's + verification level is "cross-checking against the current implementation's source," + the upstream behavior takes precedence. A note will be added to the manual that if the + upstream is fixed in the future, the catalog will need versioning (a schema version + bump). + +## 7. List of extension dialects (experimental extensions) + +Under `dialect: experimental`, this catalog uses the following extensions that the draft +spec does not explicitly define. These are also documented as a proposal to the draft in +manual chapter 6. + +1. **fermion site_dof**: expresses a fermionic degree of freedom in the form + `{fermion: {orbitals: n}}` (distinguished from a spin degree of freedom; see the + type-compatibility table in §6.6). +2. **Single-site operator vocabulary**: `N`, `Nup`, `Ndn`, `NupNdn`, `Sx`, `Sy`, `Sz`, + `Szz` and their expanded forms (§6.6). +3. **Named two-body operators**: `hop`, `density-density`, `s_i . S_j`, together with the + convention that endpoint order is meaningful (§6.6). +4. **param references** `{param, scale, default}` (§6.3). The same general form is used + for all of `value` / `coeff` / `spin` (`2S`) / `twist` (`phaseN`). +5. **The `catalog:` header** (`schema` / `dialect` / `lattice` / `model`, §1). +6. **(sketch only -- future task) general 4-fermion terms**: a term representation with an + ordered sequence of creation/annihilation operators and site/orbital bindings. Named + operators (`hop`, etc.) would then be positioned as an abbreviated notation for this. + This will be needed in the future for describing the J channel of wannier90 (Hund, + exchange, pair-hopping), but is out of scope for this catalog + (design §2 out of scope, manual Section 5.5). + +## 8. Format for recording consistency checks and provenance + +- The consistency-check values for each YAML entry (`n_sites_uc`, `bonds_per_uc`, + `coordination`, `min_size_for_check`, etc.) are recorded in + `lattice_catalog/manifest.yaml`, and the linter (C10, C11) cross-checks them + automatically. +- Provenance is recorded as a set of "file path + function name + referenced commit hash" + (a line number may additionally be noted as supplementary information, but the commit + hash is the unique reference point). + +```yaml +source: + file: python/stdface/lattice/chain_lattice.py + func: chain + commit: +``` + +- For the manifest-side format definition and the list of keys, see the comment at the top + of `manifest.yaml`. diff --git a/lattice_catalog/README.md b/lattice_catalog/README.md new file mode 100644 index 0000000..237387d --- /dev/null +++ b/lattice_catalog/README.md @@ -0,0 +1,132 @@ +# StdFace Lattice Catalog + +`lattice_catalog/` is a set of YAML files that transcribe every combination of the lattices +(chain, ladder, square, triangular, honeycomb, kagome, orthorhombic, fc_ortho, +pyrochlore) and models (Spin, Hubbard, Kondo) that StdFace supports out of the box, +plus one example of a wannier90 conversion, into the geometry / system / model +three-layer structure defined by the reference specification "Lattice Definition +Specification (draft)", 2026/07/27 (hereafter the "draft spec"). Each YAML is a +**source-cross-checked transcription**, read and copied directly from StdFace's +C/Python implementation (the `_BONDS` table, the operator-generation logic, the +parameter-resolution rules), and it passes the linter checks in `tools/ +lint_catalog.py` (schema, bond-duplicate detection, param-reference consistency, +operator/type consistency, and cross-checking against `manifest.yaml`). +Matters the draft spec leaves unspecified (fermion site_dof, the single-site +operator vocabulary, `{param, scale, default}` references, the `catalog:` header, +etc.) are filled in with an experimental extension dialect explicitly marked as +`dialect: experimental`. Note, however, that what this catalog guarantees is +"static agreement with the reference implementation's source"; it does not go so +far as to verify runtime equivalence (an oracle comparison) -- that is, whether +actually running the generated Hamiltonian numerically produces results matching +StdFace's output (see `manual.md` Section 1.1 / chapter 7 for details). + +## Directory layout + +``` +lattice_catalog/ + README.md # this file + CONVENTIONS.md # authoring conventions (normative document) + manual.md # guide (how to read it, examples, full keyword mapping table) + manifest.yaml # consistency-check ledger (bonds_per_uc/coordination, etc., machine-readable) + tools/ + lint_catalog.py # semantic-check linter (C1-C12) + keyword_inventory.py # generates an inventory of all StdFace keywords + test_tools.py # automated tests for the tools themselves (development use only) + chain/ chain_{spin,hubbard,kondo}.yaml + ladder/ ladder_w2_{spin,hubbard,kondo}.yaml, ladder_w3_{spin,hubbard,kondo}.yaml + square/ square_{spin,hubbard,kondo}.yaml + triangular/ triangular_{spin,hubbard,kondo}.yaml + honeycomb/ honeycomb_{spin,hubbard,kondo}.yaml + kagome/ kagome_{spin,hubbard,kondo}.yaml + orthorhombic/ orthorhombic_{spin,hubbard,kondo}.yaml + fc_ortho/ fc_ortho_{spin,hubbard,kondo}.yaml + pyrochlore/ pyrochlore_{spin,hubbard,kondo}.yaml + wannier90/ example_hubbard.yaml +``` + +With 9 lattices × 3 models, that is 30 files, plus 1 wannier90 Hubbard example +file, for a total of **31 files** that are checked by `lint_catalog.py` +(`manifest.yaml` is a data file and is not counted among the checked files). + +## Using the linter + +Development-time dependency: this linter requires PyYAML (`pyyaml`) (a development-only +tool, not included in the runtime dependencies of `python/pyproject.toml`. +If it is not installed, the linter exits with a clear message prompting +`pip install pyyaml`). + +Run it from the repository root: + +```bash +python3 lattice_catalog/tools/lint_catalog.py +``` + +For all 31 files, it performs schema checks (including deep type checks of +geometry/sites/bonds/site_dof), label consistency, duplicate detection under bond +reversal equivalence, param-reference consistency, J-tensor component +completeness, operator/site_dof type consistency, the sign convention +(`CONVENTIONS.md` §6.2), and cross-checking against `manifest.yaml` (a "counting +expansion" check that actually expands the bonds onto a torus of the specified +size and compares the measured `bonds_per_uc`/`coordination` against the +expected values, plus a strictness check of `min_size_for_check` itself). If +there are no errors, it prints + +``` +31 files, 0 errors +``` + +For details on the individual checks (C1-C12), see `CONVENTIONS.md` and +`manual.md` Section 1.1. + +`tools/` also contains `keyword_inventory.py`, which scans and lists the +keywords of every StdFace solver (HPhi/HWAVE/UHF/mVMC), and `test_tools.py` +(development use only, a self-contained test runner that does not use pytest), +which checks the behavior of the linter and inventory tools themselves. + +## Guide to manual.md + +How to read this catalog, examples, and the full mapping table against every +keyword are collected in `manual.md`. Its structure is as follows: + +1. **Overview and how to read it** -- a summary of the three-layer specification, + the positioning of `dialect: experimental`, this catalog's verification level + (source cross-checking, the linter, and manifest consistency checks -- not a + numeric oracle comparison), the directory layout, and supplementary + explanation of the main conventions in CONVENTIONS.md. +2. **Keyword mapping table** -- a table that assigns **every one** of the + StdFace keywords reported by `keyword_inventory.py` (351 items: 313 + keywords + 26 lattice_alias + 12 model_alias) to one of 7 categories: + geometry / system / bonds+couplings / onsite / site_dof / wannier90 / out of + scope. +3. **Per-lattice notes** -- for each of the 9 lattices, its geometry, bond + definition table, manifest consistency-check basis, and provenance. +4. **Per-model operator mapping** -- the derivation of the sign table (the + verification chain), Spin's J-tensor resolution rules, Hubbard/Kondo's + operators and signs, and the GC variants. +5. **wannier90 conversion specification** -- the conversion rules from + RESPACK/Wannier90 output (the sign, cutoff, and Hermitian canonical-pair + selection for the H/U channels, automatic generation of Spin's + superexchange, and a prose description of the J channel). +6. **Specification extension proposals** -- an organization, as a proposed + addendum to the draft spec, of the 6 extensions introduced by + `dialect: experimental` (fermion site_dof, the single-site operator + vocabulary, named two-body operators, `{param, scale, default}` + references, the `catalog:` header, and the sketch of general 4-fermion + terms). +7. **Known limitations and unhandled items** -- the oracle comparison not yet + performed, the W=2/3 limitation of ladder, the scope of wannier90 support, + known inconsistencies in the upstream implementation, and so on. + +The normative document (which takes precedence in case of conflict with this +one) is `CONVENTIONS.md`; `manual.md` is positioned as its explanation, examples, +and index. + +## Reference specification + +The geometry / system / model three-layer structure of this catalog conforms to +the reference specification "Lattice Definition Specification (draft)", +2026/07/27 (the basis for the design decisions organized in +`docs/superpowers/specs/2026-08-15-lattice-catalog-design.md`). Matters the +draft does not explicitly specify are documented and adopted as an +"experimental extension dialect" in this README, `CONVENTIONS.md` §7, and +`manual.md` chapter 6. diff --git a/lattice_catalog/chain/chain_hubbard.yaml b/lattice_catalog/chain/chain_hubbard.yaml new file mode 100644 index 0000000..39141d3 --- /dev/null +++ b/lattice_catalog/chain/chain_hubbard.yaml @@ -0,0 +1,58 @@ +# StdFace chain / Hubbard model +# Corresponding stan.in input: model="Hubbard" / lattice="chain" / L=16 / t=1.0 / U=4.0 +# See manifest.yaml for the consistency check. Signs are carried as data in scale/coeff (CONVENTIONS §6) +# Source: python/stdface/lattice/chain_lattice.py::chain (_BONDS), commit b96aef2107f1ab200565efd496606a01184e3f46 + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: chain, model: hubbard} + +geometry: + dimension: 1 + lattice_vectors: + a1: [1.0] # StdFace: a + sites: + - {label: A, frac: [0.0]} + +system: + finite: true + size: [16] # StdFace: L + boundary: + - {twist: {param: phase0}} # in degrees + +model: + site_dof: + A: {fermion: {orbitals: 1}} # extended dialect (CONVENTIONS §7) + + bonds: + - {from: A, to: A, R: [1], type: t0} # alias t + - {from: A, to: A, R: [2], type: "t0'"} # alias t' + - {from: A, to: A, R: [3], type: "t0''"} # alias t'' + - {from: A, to: A, R: [1], type: V0} # alias V + - {from: A, to: A, R: [2], type: "V0'"} # alias V' + - {from: A, to: A, R: [3], type: "V0''"} # alias V'' + + couplings: + # Contribution to H = value × operator (physical coefficient). -t is expressed via scale. + t0: {operator: "hop", value: {param: t0, scale: -1.0}} # -t Σσ(c†c+h.c.) + "t0'": {operator: "hop", value: {param: "t0'", scale: -1.0}} + "t0''": {operator: "hop", value: {param: "t0''", scale: -1.0}} + V0: {operator: "density-density", value: {param: V0}} # +V n_i n_j + "V0'": {operator: "density-density", value: {param: "V0'"}} + "V0''": {operator: "density-density", value: {param: "V0''"}} + + onsite: + A: + hubbard_u: # +U n↑n↓ + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: # -mu N + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: # -h Sz (electron spin) + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} diff --git a/lattice_catalog/chain/chain_kondo.yaml b/lattice_catalog/chain/chain_kondo.yaml new file mode 100644 index 0000000..aab5df3 --- /dev/null +++ b/lattice_catalog/chain/chain_kondo.yaml @@ -0,0 +1,75 @@ +# StdFace chain / Kondo lattice model +# Corresponding stan.in input: model="Kondo" / lattice="chain" / L=16 / t=1.0 / J=1.0 +# The field (h/Gamma/Gamma_y) is applied to both the itinerant electrons and the localized spins +# (python/stdface/core/model_plugin.py::KondoModel). +# The correspondence with the current implementation's site doubling (first half = localized S2, second half = itinerant) is described in manual Section 4. +# Source: python/stdface/lattice/chain_lattice.py::chain (_BONDS), commit b96aef2107f1ab200565efd496606a01184e3f46 + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: chain, model: kondo} + +geometry: + dimension: 1 + lattice_vectors: + a1: [1.0] # StdFace: a + sites: + - {label: A_c, frac: [0.0]} # itinerant electron (degree of freedom 1 on 1 physical site) + - {label: A_s, frac: [0.0]} # localized spin (degree of freedom 2, same site) + +system: + finite: true + size: [16] # StdFace: L + boundary: + - {twist: {param: phase0}} # in degrees + +model: + site_dof: + A_c: {fermion: {orbitals: 1}} + A_s: {spin: {param: 2S, scale: 0.5, default: 0.5}} + + bonds: + # Kondo coupling follows the source order = argument order of general_j(..., itinerant, localized). + # Itinerant A_c is the 1st endpoint (matching the role of s_i . S_j) + - {from: A_c, to: A_s, R: [0], type: J} # Kondo coupling (intra-cell) + - {from: A_c, to: A_c, R: [1], type: t0} + - {from: A_c, to: A_c, R: [2], type: "t0'"} + - {from: A_c, to: A_c, R: [3], type: "t0''"} + - {from: A_c, to: A_c, R: [1], type: V0} + - {from: A_c, to: A_c, R: [2], type: "V0'"} + - {from: A_c, to: A_c, R: [3], type: "V0''"} + + couplings: + t0: {operator: "hop", value: {param: t0, scale: -1.0}} + "t0'": {operator: "hop", value: {param: "t0'", scale: -1.0}} + "t0''": {operator: "hop", value: {param: "t0''", scale: -1.0}} + V0: {operator: "density-density", value: {param: V0}} + "V0'": {operator: "density-density", value: {param: "V0'"}} + "V0''": {operator: "density-density", value: {param: "V0''"}} + J: {operator: "s_i . S_j", value: {param: J}} # +J s·S (1st endpoint = itinerant) + + onsite: + A_c: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + A_s: + field_z: # same 3 components apply to the localized side + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} diff --git a/lattice_catalog/chain/chain_spin.yaml b/lattice_catalog/chain/chain_spin.yaml new file mode 100644 index 0000000..5f29505 --- /dev/null +++ b/lattice_catalog/chain/chain_spin.yaml @@ -0,0 +1,83 @@ +# StdFace chain / Spin model +# Corresponding stan.in input: model="Spin" / lattice="chain" / L=16 / J=1.0 (J is an alias of J0) +# See the chain/chain_spin.yaml entry of manifest.yaml for the consistency check. +# Source: python/stdface/lattice/chain_lattice.py::chain (_BONDS), commit b96aef2107f1ab200565efd496606a01184e3f46 + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: chain, model: spin} + +geometry: + dimension: 1 + lattice_vectors: + a1: [1.0] # StdFace: a (default 1.0) + sites: + - {label: A, frac: [0.0]} + +system: + finite: true + size: [16] # StdFace: L (representative value) + boundary: + - {twist: {param: phase0}} # in degrees. phase0=0 is equivalent to periodic + +model: + site_dof: + A: {spin: {param: 2S, scale: 0.5, default: 0.5}} # S = 0.5 × 2S. Default S=1/2 + + bonds: + # Preserves the source order of the reference implementation (_BONDS) + - {from: A, to: A, R: [1], type: J0} # nearest neighbor (alias J) + - {from: A, to: A, R: [2], type: "J0'"} # next-nearest neighbor (alias J') + - {from: A, to: A, R: [3], type: "J0''"} # third-nearest neighbor (alias J'') + + couplings: + # J family is in canonical 9-component form. Parameter resolution: component > scalar diagonal > global alias > 0 + J0: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J0x}} + - {ops: [Sy, Sy], coeff: {param: J0y}} + - {ops: [Sz, Sz], coeff: {param: J0z}} + - {ops: [Sx, Sy], coeff: {param: J0xy}} + - {ops: [Sx, Sz], coeff: {param: J0xz}} + - {ops: [Sy, Sx], coeff: {param: J0yx}} + - {ops: [Sy, Sz], coeff: {param: J0yz}} + - {ops: [Sz, Sx], coeff: {param: J0zx}} + - {ops: [Sz, Sy], coeff: {param: J0zy}} + "J0'": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J0'x"}} + - {ops: [Sy, Sy], coeff: {param: "J0'y"}} + - {ops: [Sz, Sz], coeff: {param: "J0'z"}} + - {ops: [Sx, Sy], coeff: {param: "J0'xy"}} + - {ops: [Sx, Sz], coeff: {param: "J0'xz"}} + - {ops: [Sy, Sx], coeff: {param: "J0'yx"}} + - {ops: [Sy, Sz], coeff: {param: "J0'yz"}} + - {ops: [Sz, Sx], coeff: {param: "J0'zx"}} + - {ops: [Sz, Sy], coeff: {param: "J0'zy"}} + "J0''": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J0''x"}} + - {ops: [Sy, Sy], coeff: {param: "J0''y"}} + - {ops: [Sz, Sz], coeff: {param: "J0''z"}} + - {ops: [Sx, Sy], coeff: {param: "J0''xy"}} + - {ops: [Sx, Sz], coeff: {param: "J0''xz"}} + - {ops: [Sy, Sx], coeff: {param: "J0''yx"}} + - {ops: [Sy, Sz], coeff: {param: "J0''yz"}} + - {ops: [Sz, Sx], coeff: {param: "J0''zx"}} + - {ops: [Sz, Sy], coeff: {param: "J0''zy"}} + + onsite: + A: + field_z: # -h Sz + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: # -Gamma Sx + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: # -Gamma_y Sy + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + aniso_z: # D (Sz)^2 + operator: {tensor_terms: [{ops: [Szz], coeff: 1.0}]} + value: {param: D} diff --git a/lattice_catalog/examples_experimental/README.md b/lattice_catalog/examples_experimental/README.md new file mode 100644 index 0000000..e3ed750 --- /dev/null +++ b/lattice_catalog/examples_experimental/README.md @@ -0,0 +1,34 @@ +# examples_experimental — hands-on trial samples + +Unlike the main catalog (31 files), the YAML in this directory are +**experimental samples meant to demonstrate the limits of the new format's +(catalog dialect's) expressive power**. The design friction points observed +while writing lattices/models that don't exist in the catalog are +summarized in +[`../feedback_draft_spec.md`](../feedback_draft_spec.md). + +## Important: relationship to the linter + +Some of these files **intentionally fail to pass the linter** (that failure +is itself an observation). For this reason, this directory is excluded from +the linter's default scan +(`_DISCOVERY_EXCLUDED_DIRS` in `tools/lint_catalog.py`). +To reproduce the individual diagnostics, pass an explicit path: + +```bash +python3 lattice_catalog/tools/lint_catalog.py \ + lattice_catalog/examples_experimental/kagome_dm_spin.yaml +``` + +## File list and key observations + +| File | Subject | Key observation | +|---|---|---| +| `ssh_dimer_chain_spin.yaml` | Alternating-bond (dimerized) chain | Geometry is straightforward. Free-form parameter names (e.g. `J_intra`) are rejected by C7 — the closedness of the parameter vocabulary | +| `shastry_sutherland_spin.yaml` | Shastry-Sutherland (draft §7.3) | The bond structure can be written almost isomorphically to the draft. The draft's own isotropic operator `"S_i . S_j"` has no place in the dialect's vocabulary and is rejected by C9 | +| `kagome_dm_spin.yaml` | Kagome with DM interaction | DM can be expressed via antisymmetric tensor components. However, sharing a parameter across components (`Dz` with opposite sign in 2 components) is rejected by C8/C12. Confirms that the source-order-preservation convention is essential for preserving the DM sign | +| `two_orbital_hubbard_chain.yaml` | Two-orbital Hubbard chain | The orbital = separate-label scheme reaches as far as U'/t_ab, but Hund coupling and pair hopping (4-fermion terms) cannot be written with the current vocabulary | +| `square_cylinder_spin.yaml` | Cylindrical boundary (for DMRG) | `boundary: [periodic, open]` is straightforward to write. However, since the C11 consistency check assumes a torus, an open boundary cannot be verified | + +Details of the observations for each sample are recorded in that file's +leading comment. diff --git a/lattice_catalog/examples_experimental/kagome_dm_spin.yaml b/lattice_catalog/examples_experimental/kagome_dm_spin.yaml new file mode 100644 index 0000000..218bdf2 --- /dev/null +++ b/lattice_catalog/examples_experimental/kagome_dm_spin.yaml @@ -0,0 +1,90 @@ +# Experimental sample 3: kagome with DM interaction (nearest-neighbor D-vector z component) +# Purpose: check whether antisymmetric exchange (DM) can be expressed in the +# 9-component tensor form +# +# Result (observation): +# (1) the DM z component D_z (S_i x S_j)_z = D_z (Sx_i Sy_j - Sy_i Sx_j) can +# be written naturally in tensor form as the antisymmetric components +# Jxy = +D_z, Jyx = -D_z. OK +# (2) however, in kagome physics it is standard for the DM sign to flip +# between the up-triangle and the down-triangle. The up-triangle +# (= intra-cell bond, R=0) and the down-triangle (= inter-cell bond) +# can be distinguished by "row", but if the coupling type is the same +# (e.g. J1), the same tensor is applied to both, so the sign flip +# cannot be expressed. +# -> expressing it requires splitting type into J1_up / J1_dn, which +# breaks the correspondence with StdFace parameter names (a +# premise of the catalog dialect). +# (3) furthermore, since the DM sign is determined by the bond's +# "orientation", under the source-order-preservation convention each +# bond row's orientation directly fixes the sign. If the draft spec's +# "orientation canonicalization" were applied, the DM sign information +# would be destroyed — this confirms that switching the catalog +# dialect to source-order preservation was also the right call for +# handling DM. +# +# Below is an example that attaches D_z only to the up-triangle (the +# down-triangle's sign flip is abandoned since it would require splitting +# type): + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: kagome_dm, model: spin} + +geometry: + dimension: 2 + lattice_vectors: + a1: [1.0, 0.0] + a2: [0.5, 0.8660254037844386] + sites: + - {label: A, frac: [0.0, 0.0]} + - {label: B, frac: [0.5, 0.0]} + - {label: C, frac: [0.0, 0.5]} + +system: + finite: true + size: [4, 4] + boundary: + - {twist: {param: phase0}} + - {twist: {param: phase1}} + +model: + site_dof: + A: {spin: {param: 2S, scale: 0.5, default: 0.5}} + B: {spin: {param: 2S, scale: 0.5, default: 0.5}} + C: {spin: {param: 2S, scale: 0.5, default: 0.5}} + + bonds: + # up-triangle (intra-cell, with DM) — type split off as up-triangle-only + - {from: A, to: B, R: [0, 0], type: J_up} + - {from: B, to: C, R: [0, 0], type: J_up} + - {from: C, to: A, R: [0, 0], type: J_up} + # down-triangle (inter-cell) — the DM sign needs to flip, which can't be + # written under the same type, so it gets a separate type + - {from: B, to: A, R: [1, 0], type: J_dn} + - {from: C, to: B, R: [1, -1], type: J_dn} + - {from: A, to: C, R: [0, -1], type: J_dn} + + couplings: + J_up: # isotropic J + DM z component (+D_z): Jxy = +Dz, Jyx = -Dz + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J_upx}} + - {ops: [Sy, Sy], coeff: {param: J_upy}} + - {ops: [Sz, Sz], coeff: {param: J_upz}} + - {ops: [Sx, Sy], coeff: {param: Dz, scale: 1.0}} + - {ops: [Sy, Sx], coeff: {param: Dz, scale: -1.0}} + - {ops: [Sx, Sz], coeff: {param: J_upxz}} + - {ops: [Sy, Sz], coeff: {param: J_upyz}} + - {ops: [Sz, Sx], coeff: {param: J_upzx}} + - {ops: [Sz, Sy], coeff: {param: J_upzy}} + J_dn: # sign-flipped DM version: Jxy = -Dz, Jyx = +Dz + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J_dnx}} + - {ops: [Sy, Sy], coeff: {param: J_dny}} + - {ops: [Sz, Sz], coeff: {param: J_dnz}} + - {ops: [Sx, Sy], coeff: {param: Dz, scale: -1.0}} + - {ops: [Sy, Sx], coeff: {param: Dz, scale: 1.0}} + - {ops: [Sx, Sz], coeff: {param: J_dnxz}} + - {ops: [Sy, Sz], coeff: {param: J_dnyz}} + - {ops: [Sz, Sx], coeff: {param: J_dnzx}} + - {ops: [Sz, Sy], coeff: {param: J_dnzy}} diff --git a/lattice_catalog/examples_experimental/shastry_sutherland_spin.yaml b/lattice_catalog/examples_experimental/shastry_sutherland_spin.yaml new file mode 100644 index 0000000..1452e11 --- /dev/null +++ b/lattice_catalog/examples_experimental/shastry_sutherland_spin.yaml @@ -0,0 +1,51 @@ +# Experimental sample 2: Shastry-Sutherland lattice (writing the draft +# spec's §7.3 flagship example in the catalog dialect) +# Purpose: check whether the draft spec's example can be written as-is in +# the catalog dialect +# +# Friction points (under observation): +# (1) the draft writes the isotropic operator as operator: "S_i . S_j" +# (a string), but the catalog dialect's operator vocabulary has no +# capitalized "S_i . S_j" (spin-spin) entry (s_i . S_j is +# fermion-spin only). Here we use the draft's notation as-is and +# observe the linter's behavior. +# (2) J1/J2 are names that exist in the StdFace inventory, but their +# meaning in StdFace (a direction class) conflicts with their meaning +# in this file (nn/dimer). + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: shastry_sutherland, model: spin} + +geometry: + dimension: 2 + lattice_vectors: + a1: [1.0, 1.0] + a2: [1.0, -1.0] + sites: + - {label: A, frac: [0.0, 0.0]} + - {label: B, frac: [0.5, 0.5]} + +system: + finite: true + size: [4, 4] + boundary: + - periodic + - periodic + +model: + site_dof: + A: {spin: {param: 2S, scale: 0.5, default: 0.5}} + B: {spin: {param: 2S, scale: 0.5, default: 0.5}} + + bonds: + # nearest neighbor (square-lattice horizontal/vertical J1, A-B) + - {from: A, to: B, R: [0, 0], type: J1} + - {from: A, to: B, R: [-1, -1], type: J1} + - {from: A, to: B, R: [0, -1], type: J1} + - {from: A, to: B, R: [-1, 0], type: J1} + # next-nearest neighbor (diagonal dimer J2, alternating placement) + - {from: A, to: A, R: [1, 0], type: J2} # diagonal along (1,1) + - {from: B, to: B, R: [0, 1], type: J2} # diagonal along -(1,1) + + couplings: + J1: {operator: "S_i . S_j", value: {param: J1}} + J2: {operator: "S_i . S_j", value: {param: J2}} diff --git a/lattice_catalog/examples_experimental/square_cylinder_spin.yaml b/lattice_catalog/examples_experimental/square_cylinder_spin.yaml new file mode 100644 index 0000000..2e7abad --- /dev/null +++ b/lattice_catalog/examples_experimental/square_cylinder_spin.yaml @@ -0,0 +1,66 @@ +# Experimental sample 5: cylindrical geometry of a square lattice (for DMRG: periodic along W, open along L) +# Purpose: hands-on trial of direction-dependent boundary conditions (the +# cylindrical case in draft spec §3.1) +# +# Observation: +# (1) direction-dependent boundary specification is straightforward to +# write. OK +# (2) however, the catalog's consistency-check mechanism (C11 counting +# expansion) assumes a torus. When there is an open direction, the +# edge sites have a different coordination number and so do not match +# the manifest's (uniform-value) coordination. +# -> checking an open boundary requires distinguishing "bulk +# coordination number" from "edge deficit", which the current +# manifest schema cannot express (verification only works for the +# periodic example). + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: square_cylinder, model: spin} + +geometry: + dimension: 2 + lattice_vectors: + a1: [1.0, 0.0] + a2: [0.0, 1.0] + sites: + - {label: A, frac: [0.0, 0.0]} + +system: + finite: true + size: [4, 16] # W (circumference) x L (axis) + boundary: + - periodic # W: circumferential direction + - open # L: axial direction (DMRG) + +model: + site_dof: + A: {spin: {param: 2S, scale: 0.5, default: 0.5}} + + bonds: + - {from: A, to: A, R: [1, 0], type: J0} + - {from: A, to: A, R: [0, 1], type: J1} + + couplings: + J0: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J0x}} + - {ops: [Sy, Sy], coeff: {param: J0y}} + - {ops: [Sz, Sz], coeff: {param: J0z}} + - {ops: [Sx, Sy], coeff: {param: J0xy}} + - {ops: [Sx, Sz], coeff: {param: J0xz}} + - {ops: [Sy, Sx], coeff: {param: J0yx}} + - {ops: [Sy, Sz], coeff: {param: J0yz}} + - {ops: [Sz, Sx], coeff: {param: J0zx}} + - {ops: [Sz, Sy], coeff: {param: J0zy}} + J1: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J1x}} + - {ops: [Sy, Sy], coeff: {param: J1y}} + - {ops: [Sz, Sz], coeff: {param: J1z}} + - {ops: [Sx, Sy], coeff: {param: J1xy}} + - {ops: [Sx, Sz], coeff: {param: J1xz}} + - {ops: [Sy, Sx], coeff: {param: J1yx}} + - {ops: [Sy, Sz], coeff: {param: J1yz}} + - {ops: [Sz, Sx], coeff: {param: J1zx}} + - {ops: [Sz, Sy], coeff: {param: J1zy}} diff --git a/lattice_catalog/examples_experimental/ssh_dimer_chain_spin.yaml b/lattice_catalog/examples_experimental/ssh_dimer_chain_spin.yaml new file mode 100644 index 0000000..f1da6c1 --- /dev/null +++ b/lattice_catalog/examples_experimental/ssh_dimer_chain_spin.yaml @@ -0,0 +1,72 @@ +# Experimental sample 1: alternating-bond (dimerized) chain (spin-Peierls / dimerization) +# Purpose: hands-on trial of coefficient modulation (spec §5.2 "cell +# enlargement + non-uniform coefficient assignment") +# The unit cell is enlarged to 2 sites, with separate parameters assigned to +# the intra-cell bond (strong) and the inter-cell bond (weak). +# +# Friction point: parameter names. Physically these are J_intra / J_inter, +# but the catalog dialect's C7 requires that {param: ...} exist in the +# StdFace keyword inventory, so the only options are to borrow an existing +# name whose meaning doesn't fit (J0 / J1) or to accept a C7 violation. +# Here we deliberately use J_intra / J_inter to observe C7's behavior. + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: dimer_chain, model: spin} + +geometry: + dimension: 1 + lattice_vectors: + a1: [2.0] # unit cell enlarged to 2 sites + sites: + - {label: A, frac: [0.0]} + - {label: B, frac: [0.5]} + +system: + finite: true + size: [8] + boundary: + - {twist: {param: phase0}} + +model: + site_dof: + A: {spin: {param: 2S, scale: 0.5, default: 0.5}} + B: {spin: {param: 2S, scale: 0.5, default: 0.5}} + + bonds: + - {from: A, to: B, R: [0], type: J_intra} # strong bond (intra-cell) + - {from: B, to: A, R: [1], type: J_inter} # weak bond (inter-cell) + + couplings: + J_intra: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J_intrax}} + - {ops: [Sy, Sy], coeff: {param: J_intray}} + - {ops: [Sz, Sz], coeff: {param: J_intraz}} + - {ops: [Sx, Sy], coeff: {param: J_intraxy}} + - {ops: [Sx, Sz], coeff: {param: J_intraxz}} + - {ops: [Sy, Sx], coeff: {param: J_intrayx}} + - {ops: [Sy, Sz], coeff: {param: J_intrayz}} + - {ops: [Sz, Sx], coeff: {param: J_intrazx}} + - {ops: [Sz, Sy], coeff: {param: J_intrazy}} + J_inter: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J_interx}} + - {ops: [Sy, Sy], coeff: {param: J_intery}} + - {ops: [Sz, Sz], coeff: {param: J_interz}} + - {ops: [Sx, Sy], coeff: {param: J_interxy}} + - {ops: [Sx, Sz], coeff: {param: J_interxz}} + - {ops: [Sy, Sx], coeff: {param: J_interyx}} + - {ops: [Sy, Sz], coeff: {param: J_interyz}} + - {ops: [Sz, Sx], coeff: {param: J_interzx}} + - {ops: [Sz, Sy], coeff: {param: J_interzy}} + + onsite: + A: + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + B: + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} diff --git a/lattice_catalog/examples_experimental/two_orbital_hubbard_chain.yaml b/lattice_catalog/examples_experimental/two_orbital_hubbard_chain.yaml new file mode 100644 index 0000000..4683ede --- /dev/null +++ b/lattice_catalog/examples_experimental/two_orbital_hubbard_chain.yaml @@ -0,0 +1,73 @@ +# Experimental sample 4: two-orbital Hubbard chain (demonstrating what cannot be written) +# Purpose: check the expressive range of multi-orbital models +# +# Conclusion: cannot be written in the current dialect. +# (1) site_dof can "declare" {fermion: {orbitals: 2}}, but the operator +# side has no way to refer to an orbital: +# - "hop" is orbital-undecomposed (Sum_sigma c^dagger_sigma c_sigma) — +# orbital a->b hopping t_ab cannot be written +# - the onsite vocabulary (N, NupNdn, etc.) also has no orbital index +# - intra-orbital U / inter-orbital U' / Hund J_H / pair hopping are +# 4-fermion terms, and the general-term schema (a sketch exists in +# manual §6.6) is not yet defined +# (2) as a workaround, "orbital = separate label" (the scheme used by the +# wannier90 example, placing W1/W2 at the same frac) can write the +# two-body density-density term (U') but not Hund/pair hopping. Also, +# since NupNdn can only be written within a single label, intra-orbital +# U can be written, but spin-selective inter-orbital terms cannot. +# +# Below, we write as much as can be expressed under the "orbital = separate +# label" scheme, and mark unwritable terms with comments: + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: two_orbital_chain, model: hubbard} + +geometry: + dimension: 1 + lattice_vectors: + a1: [1.0] + sites: + - {label: W1, frac: [0.0]} # orbital 1 (same atom) + - {label: W2, frac: [0.0]} # orbital 2 (same atom) + +system: + finite: true + size: [8] + boundary: + - periodic + +model: + site_dof: + W1: {fermion: {orbitals: 1}} + W2: {fermion: {orbitals: 1}} + + bonds: + - {from: W1, to: W1, R: [1], type: t11} # intra-orbital hopping + - {from: W2, to: W2, R: [1], type: t22} + - {from: W1, to: W2, R: [1], type: t12} # inter-orbital hopping + - {from: W1, to: W2, R: [0], type: Uprime} # inter-orbital Coulomb U' (same atom, R=0) + + couplings: + t11: {operator: "hop", value: {param: t, scale: -1.0}} + t22: {operator: "hop", value: {param: t, scale: -1.0}} + t12: {operator: "hop", value: {param: "t'", scale: -1.0}} + Uprime: {operator: "density-density", value: {param: "V"}} + + onsite: + W1: + hubbard_u: # intra-orbital U + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + W2: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + + # --- terms below cannot be written in the current dialect --- + # Hund coupling: -J_H Sum s_{W1} . s_{W2} <- no itinerant-itinerant spin-product + # operator in the vocabulary + # (s_i . S_j is fermion-spin only) + # pair hopping: J_H (c^dagger_{W1,up} c^dagger_{W1,dn} c_{W2,dn} c_{W2,up} + h.c.) + # <- 4-fermion general-term schema not + # yet defined + # spin-selective terms: spin-dependent inter-orbital hopping, etc. + # <- ops has no spin index diff --git a/lattice_catalog/fc_ortho/fc_ortho_hubbard.yaml b/lattice_catalog/fc_ortho/fc_ortho_hubbard.yaml new file mode 100644 index 0000000..f298a63 --- /dev/null +++ b/lattice_catalog/fc_ortho/fc_ortho_hubbard.yaml @@ -0,0 +1,85 @@ +# StdFace face-centered orthorhombic (fc_ortho) / Hubbard model +# Corresponding stan.in input: model="Hubbard" / lattice="fcorthorhombic" / W=4 / L=4 / Height=4 / t0=1.0 / U=4.0 +# See manifest.yaml for the consistency check. Signs are carried as data in scale/coeff (CONVENTIONS §6) +# Source: python/stdface/lattice/fc_ortho.py::fc_ortho (_BONDS), commit 8e3601167d1254807f58ce365107333f1d505fa0 + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: fc_ortho, model: hubbard} + +geometry: + dimension: 3 + lattice_vectors: + a1: [0.0, 0.5, 0.5] # StdFace: Wx, Wy, Wz (default: 0, Llength/2, Hlength/2) + a2: [0.5, 0.0, 0.5] # StdFace: Lx, Ly, Lz (default: Wlength/2, 0, Hlength/2) + a3: [0.5, 0.5, 0.0] # StdFace: Hx, Hy, Hz (default: Wlength/2, Llength/2, 0) + sites: + - {label: A, frac: [0.0, 0.0, 0.0]} + +system: + finite: true + size: [4, 4, 4] # StdFace: W, L, Height + boundary: + - {twist: {param: phase0}} # in degrees + - {twist: {param: phase1}} + - {twist: {param: phase2}} + +model: + site_dof: + A: {fermion: {orbitals: 1}} # extended dialect (CONVENTIONS §7) + + bonds: + # Preserves the source order of the reference implementation (_BONDS). R = [dW, dL, dH] + # nearest neighbor (nn, coordination number 12. Each of the W/L/H series has 2 equivalent directions, coordination number 4 per series) + - {from: A, to: A, R: [1, 0, 0], type: t0} # along W + - {from: A, to: A, R: [0, 1, -1], type: t0} # along W (equiv) + - {from: A, to: A, R: [0, 1, 0], type: t1} # along L + - {from: A, to: A, R: [-1, 0, 1], type: t1} # along L (equiv) + - {from: A, to: A, R: [0, 0, 1], type: t2} # along H + - {from: A, to: A, R: [1, -1, 0], type: t2} # along H (equiv) + # second-nearest neighbor (coordination number 6. Only 1 direction per series, coordination number 2) + - {from: A, to: A, R: [-1, 1, 1], type: "t0'"} # -W+L+H + - {from: A, to: A, R: [1, -1, 1], type: "t1'"} # -L+H+W + - {from: A, to: A, R: [1, 1, -1], type: "t2'"} # -H+W+L + # nearest neighbor (nn, coordination number 12. Each of the W/L/H series has 2 equivalent directions, coordination number 4 per series) + - {from: A, to: A, R: [1, 0, 0], type: V0} # along W + - {from: A, to: A, R: [0, 1, -1], type: V0} # along W (equiv) + - {from: A, to: A, R: [0, 1, 0], type: V1} # along L + - {from: A, to: A, R: [-1, 0, 1], type: V1} # along L (equiv) + - {from: A, to: A, R: [0, 0, 1], type: V2} # along H + - {from: A, to: A, R: [1, -1, 0], type: V2} # along H (equiv) + # second-nearest neighbor (coordination number 6. Only 1 direction per series, coordination number 2) + - {from: A, to: A, R: [-1, 1, 1], type: "V0'"} # -W+L+H + - {from: A, to: A, R: [1, -1, 1], type: "V1'"} # -L+H+W + - {from: A, to: A, R: [1, 1, -1], type: "V2'"} # -H+W+L + + couplings: + # Contribution to H = value × operator (physical coefficient). -t is expressed via scale. + t0: {operator: "hop", value: {param: t0, scale: -1.0}} # -t Σσ(c†c+h.c.) + t1: {operator: "hop", value: {param: t1, scale: -1.0}} + t2: {operator: "hop", value: {param: t2, scale: -1.0}} + "t0'": {operator: "hop", value: {param: "t0'", scale: -1.0}} + "t1'": {operator: "hop", value: {param: "t1'", scale: -1.0}} + "t2'": {operator: "hop", value: {param: "t2'", scale: -1.0}} + V0: {operator: "density-density", value: {param: V0}} # +V n_i n_j + V1: {operator: "density-density", value: {param: V1}} + V2: {operator: "density-density", value: {param: V2}} + "V0'": {operator: "density-density", value: {param: "V0'"}} + "V1'": {operator: "density-density", value: {param: "V1'"}} + "V2'": {operator: "density-density", value: {param: "V2'"}} + + onsite: + A: + hubbard_u: # +U n↑n↓ + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: # -mu N + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: # -h Sz (electron spin) + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} diff --git a/lattice_catalog/fc_ortho/fc_ortho_kondo.yaml b/lattice_catalog/fc_ortho/fc_ortho_kondo.yaml new file mode 100644 index 0000000..071c0a2 --- /dev/null +++ b/lattice_catalog/fc_ortho/fc_ortho_kondo.yaml @@ -0,0 +1,102 @@ +# StdFace face-centered orthorhombic (fc_ortho) / Kondo lattice model +# Corresponding stan.in input: model="Kondo" / lattice="fcorthorhombic" / W=4 / L=4 / Height=4 / t0=1.0 / J=1.0 +# The field (h/Gamma/Gamma_y) is applied to both the itinerant electrons and the localized spins +# (python/stdface/core/model_plugin.py::KondoModel). +# The correspondence with the current implementation's site doubling (first half = localized S2, second half = itinerant) is described in manual Section 4. +# Source: python/stdface/lattice/fc_ortho.py::fc_ortho (_BONDS), commit 8e3601167d1254807f58ce365107333f1d505fa0 + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: fc_ortho, model: kondo} + +geometry: + dimension: 3 + lattice_vectors: + a1: [0.0, 0.5, 0.5] # StdFace: Wx, Wy, Wz (default: 0, Llength/2, Hlength/2) + a2: [0.5, 0.0, 0.5] # StdFace: Lx, Ly, Lz (default: Wlength/2, 0, Hlength/2) + a3: [0.5, 0.5, 0.0] # StdFace: Hx, Hy, Hz (default: Wlength/2, Llength/2, 0) + sites: + - {label: A_c, frac: [0.0, 0.0, 0.0]} # itinerant electron (degree of freedom 1 on 1 physical site) + - {label: A_s, frac: [0.0, 0.0, 0.0]} # localized spin (degree of freedom 2, same site) + +system: + finite: true + size: [4, 4, 4] # StdFace: W, L, Height + boundary: + - {twist: {param: phase0}} # in degrees + - {twist: {param: phase1}} + - {twist: {param: phase2}} + +model: + site_dof: + A_c: {fermion: {orbitals: 1}} + A_s: {spin: {param: 2S, scale: 0.5, default: 0.5}} + + bonds: + # Kondo coupling follows the source order = argument order of general_j(..., itinerant, localized). + # Itinerant A_c is the 1st endpoint (matching the role of s_i . S_j) + - {from: A_c, to: A_s, R: [0, 0, 0], type: J} # Kondo coupling (intra-cell) + # Preserves the source order of the reference implementation (_BONDS). R = [dW, dL, dH] + # nearest neighbor (nn, coordination number 12. Each of the W/L/H series has 2 equivalent directions, coordination number 4 per series) + - {from: A_c, to: A_c, R: [1, 0, 0], type: t0} # along W + - {from: A_c, to: A_c, R: [0, 1, -1], type: t0} # along W (equiv) + - {from: A_c, to: A_c, R: [0, 1, 0], type: t1} # along L + - {from: A_c, to: A_c, R: [-1, 0, 1], type: t1} # along L (equiv) + - {from: A_c, to: A_c, R: [0, 0, 1], type: t2} # along H + - {from: A_c, to: A_c, R: [1, -1, 0], type: t2} # along H (equiv) + # second-nearest neighbor (coordination number 6. Only 1 direction per series, coordination number 2) + - {from: A_c, to: A_c, R: [-1, 1, 1], type: "t0'"} # -W+L+H + - {from: A_c, to: A_c, R: [1, -1, 1], type: "t1'"} # -L+H+W + - {from: A_c, to: A_c, R: [1, 1, -1], type: "t2'"} # -H+W+L + # nearest neighbor (nn, coordination number 12. Each of the W/L/H series has 2 equivalent directions, coordination number 4 per series) + - {from: A_c, to: A_c, R: [1, 0, 0], type: V0} # along W + - {from: A_c, to: A_c, R: [0, 1, -1], type: V0} # along W (equiv) + - {from: A_c, to: A_c, R: [0, 1, 0], type: V1} # along L + - {from: A_c, to: A_c, R: [-1, 0, 1], type: V1} # along L (equiv) + - {from: A_c, to: A_c, R: [0, 0, 1], type: V2} # along H + - {from: A_c, to: A_c, R: [1, -1, 0], type: V2} # along H (equiv) + # second-nearest neighbor (coordination number 6. Only 1 direction per series, coordination number 2) + - {from: A_c, to: A_c, R: [-1, 1, 1], type: "V0'"} # -W+L+H + - {from: A_c, to: A_c, R: [1, -1, 1], type: "V1'"} # -L+H+W + - {from: A_c, to: A_c, R: [1, 1, -1], type: "V2'"} # -H+W+L + + couplings: + t0: {operator: "hop", value: {param: t0, scale: -1.0}} + t1: {operator: "hop", value: {param: t1, scale: -1.0}} + t2: {operator: "hop", value: {param: t2, scale: -1.0}} + "t0'": {operator: "hop", value: {param: "t0'", scale: -1.0}} + "t1'": {operator: "hop", value: {param: "t1'", scale: -1.0}} + "t2'": {operator: "hop", value: {param: "t2'", scale: -1.0}} + V0: {operator: "density-density", value: {param: V0}} + V1: {operator: "density-density", value: {param: V1}} + V2: {operator: "density-density", value: {param: V2}} + "V0'": {operator: "density-density", value: {param: "V0'"}} + "V1'": {operator: "density-density", value: {param: "V1'"}} + "V2'": {operator: "density-density", value: {param: "V2'"}} + J: {operator: "s_i . S_j", value: {param: J}} # +J s·S (1st endpoint = itinerant) + + onsite: + A_c: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + A_s: + field_z: # same 3 components apply to the localized side + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} diff --git a/lattice_catalog/fc_ortho/fc_ortho_spin.yaml b/lattice_catalog/fc_ortho/fc_ortho_spin.yaml new file mode 100644 index 0000000..d8bdb0d --- /dev/null +++ b/lattice_catalog/fc_ortho/fc_ortho_spin.yaml @@ -0,0 +1,131 @@ +# StdFace face-centered orthorhombic (fc_ortho) / Spin model +# Corresponding stan.in input: model="Spin" / lattice="fcorthorhombic" / W=4 / L=4 / Height=4 / J0=1.0 +# See the fc_ortho/fc_ortho_spin.yaml entry of manifest.yaml for the consistency check. +# Source: python/stdface/lattice/fc_ortho.py::fc_ortho (_BONDS), commit 8e3601167d1254807f58ce365107333f1d505fa0 + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: fc_ortho, model: spin} + +geometry: + dimension: 3 + lattice_vectors: + a1: [0.0, 0.5, 0.5] # StdFace: Wx, Wy, Wz (default: 0, Llength/2, Hlength/2) + a2: [0.5, 0.0, 0.5] # StdFace: Lx, Ly, Lz (default: Wlength/2, 0, Hlength/2) + a3: [0.5, 0.5, 0.0] # StdFace: Hx, Hy, Hz (default: Wlength/2, Llength/2, 0) + sites: + - {label: A, frac: [0.0, 0.0, 0.0]} + +system: + finite: true + size: [4, 4, 4] # StdFace: W, L, Height + boundary: + - {twist: {param: phase0}} # in degrees + - {twist: {param: phase1}} + - {twist: {param: phase2}} + +model: + site_dof: + A: {spin: {param: 2S, scale: 0.5, default: 0.5}} # S = 0.5 × 2S. Default S=1/2 + + bonds: + # Preserves the source order of the reference implementation (_BONDS). R = [dW, dL, dH] + # nearest neighbor (nn, coordination number 12. Each of the W/L/H series has 2 equivalent directions, coordination number 4 per series) + - {from: A, to: A, R: [1, 0, 0], type: J0} # along W + - {from: A, to: A, R: [0, 1, -1], type: J0} # along W (equiv) + - {from: A, to: A, R: [0, 1, 0], type: J1} # along L + - {from: A, to: A, R: [-1, 0, 1], type: J1} # along L (equiv) + - {from: A, to: A, R: [0, 0, 1], type: J2} # along H + - {from: A, to: A, R: [1, -1, 0], type: J2} # along H (equiv) + # second-nearest neighbor (coordination number 6. Only 1 direction per series, coordination number 2) + - {from: A, to: A, R: [-1, 1, 1], type: "J0'"} # -W+L+H + - {from: A, to: A, R: [1, -1, 1], type: "J1'"} # -L+H+W + - {from: A, to: A, R: [1, 1, -1], type: "J2'"} # -H+W+L + + couplings: + # J family is in canonical 9-component form. Parameter resolution: component > scalar diagonal > global alias > 0 + J0: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J0x}} + - {ops: [Sy, Sy], coeff: {param: J0y}} + - {ops: [Sz, Sz], coeff: {param: J0z}} + - {ops: [Sx, Sy], coeff: {param: J0xy}} + - {ops: [Sx, Sz], coeff: {param: J0xz}} + - {ops: [Sy, Sx], coeff: {param: J0yx}} + - {ops: [Sy, Sz], coeff: {param: J0yz}} + - {ops: [Sz, Sx], coeff: {param: J0zx}} + - {ops: [Sz, Sy], coeff: {param: J0zy}} + J1: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J1x}} + - {ops: [Sy, Sy], coeff: {param: J1y}} + - {ops: [Sz, Sz], coeff: {param: J1z}} + - {ops: [Sx, Sy], coeff: {param: J1xy}} + - {ops: [Sx, Sz], coeff: {param: J1xz}} + - {ops: [Sy, Sx], coeff: {param: J1yx}} + - {ops: [Sy, Sz], coeff: {param: J1yz}} + - {ops: [Sz, Sx], coeff: {param: J1zx}} + - {ops: [Sz, Sy], coeff: {param: J1zy}} + J2: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J2x}} + - {ops: [Sy, Sy], coeff: {param: J2y}} + - {ops: [Sz, Sz], coeff: {param: J2z}} + - {ops: [Sx, Sy], coeff: {param: J2xy}} + - {ops: [Sx, Sz], coeff: {param: J2xz}} + - {ops: [Sy, Sx], coeff: {param: J2yx}} + - {ops: [Sy, Sz], coeff: {param: J2yz}} + - {ops: [Sz, Sx], coeff: {param: J2zx}} + - {ops: [Sz, Sy], coeff: {param: J2zy}} + "J0'": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J0'x"}} + - {ops: [Sy, Sy], coeff: {param: "J0'y"}} + - {ops: [Sz, Sz], coeff: {param: "J0'z"}} + - {ops: [Sx, Sy], coeff: {param: "J0'xy"}} + - {ops: [Sx, Sz], coeff: {param: "J0'xz"}} + - {ops: [Sy, Sx], coeff: {param: "J0'yx"}} + - {ops: [Sy, Sz], coeff: {param: "J0'yz"}} + - {ops: [Sz, Sx], coeff: {param: "J0'zx"}} + - {ops: [Sz, Sy], coeff: {param: "J0'zy"}} + "J1'": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J1'x"}} + - {ops: [Sy, Sy], coeff: {param: "J1'y"}} + - {ops: [Sz, Sz], coeff: {param: "J1'z"}} + - {ops: [Sx, Sy], coeff: {param: "J1'xy"}} + - {ops: [Sx, Sz], coeff: {param: "J1'xz"}} + - {ops: [Sy, Sx], coeff: {param: "J1'yx"}} + - {ops: [Sy, Sz], coeff: {param: "J1'yz"}} + - {ops: [Sz, Sx], coeff: {param: "J1'zx"}} + - {ops: [Sz, Sy], coeff: {param: "J1'zy"}} + "J2'": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J2'x"}} + - {ops: [Sy, Sy], coeff: {param: "J2'y"}} + - {ops: [Sz, Sz], coeff: {param: "J2'z"}} + - {ops: [Sx, Sy], coeff: {param: "J2'xy"}} + - {ops: [Sx, Sz], coeff: {param: "J2'xz"}} + - {ops: [Sy, Sx], coeff: {param: "J2'yx"}} + - {ops: [Sy, Sz], coeff: {param: "J2'yz"}} + - {ops: [Sz, Sx], coeff: {param: "J2'zx"}} + - {ops: [Sz, Sy], coeff: {param: "J2'zy"}} + + onsite: + A: + field_z: # -h Sz + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: # -Gamma Sx + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: # -Gamma_y Sy + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + aniso_z: # D (Sz)^2 + operator: {tensor_terms: [{ops: [Szz], coeff: 1.0}]} + value: {param: D} diff --git a/lattice_catalog/feedback_draft_spec.md b/lattice_catalog/feedback_draft_spec.md new file mode 100644 index 0000000..05a7b47 --- /dev/null +++ b/lattice_catalog/feedback_draft_spec.md @@ -0,0 +1,157 @@ +# Feedback on the Lattice Definition Specification (draft 2026/07/27) — from cataloging and hands-on trials + +- Date: 2026-08-15 +- Basis: (1) cataloging every StdFace lattice and interaction (the 31 YAML + files in this directory, cross-checked against source and lint-verified), + (2) hands-on trials of 5 lattices/models outside the catalog + (see [`examples_experimental/`](examples_experimental/)) +- Purpose: proposals for the next revision of the draft specification "Lattice + Definition Specification (draft)" (2026/07/27). Each item is given a + priority (High/Medium/Low) and cites the sample it is based on. + +## 0. Overall assessment + +**The bond description via (from, to, R, type) and the three-layer +separation (geometry / system / model) hold up strongly in practice** — across +all 9 StdFace lattices x 3 models, plus Shastry-Sutherland, the alternating-bond +(dimerized) chain, breathing-type lattices, DM interactions, and cylindrical +boundaries, there was not a single case where the geometry/connectivity +description hit a wall. The improvement proposals concentrate mainly in two +areas: **(A) a parameter-declaration mechanism** and **(B) the operator +vocabulary**. + +## 1. Proposals for the draft specification (in priority order) + +### 1.1 [High] Introduce an in-file `parameters:` declaration block + +- **Problem**: the draft writes coefficients as numeric literals (§7.3). The + catalog dialect introduced `{param: }` references, but bound the set + of referenceable names to the StdFace keyword inventory. As a result, a + model with parameters that don't exist in StdFace (e.g. the alternating-bond + chain's `J_intra`/`J_inter`, or DM's `Dz`) can only be written by "bending + the meaning of an existing name and borrowing it." + (Evidence: `ssh_dimer_chain_spin.yaml`, `kagome_dm_spin.yaml` — wiped out by + C7) +- **Proposal**: introduce a declaration block at the top of the file. + + ```yaml + parameters: + J_intra: {default: 1.0, type: real} + J_inter: {default: 0.5, type: real} + Dz: {default: 0.1, type: real} + ``` + + The couplings side would reference it as `{param: J_intra}`. The validator + would only need to check "is the referenced name declared?" — and for a + StdFace-compatible catalog, the declaration block could be auto-generated + from the inventory (retaining backward compatibility with the current + catalog). + +### 1.2 [High] Give the isotropic spin operator a place in the vocabulary (consistency with the draft itself) + +- **Problem**: draft §4.3/§7.3 uses `operator: "S_i . S_j"`, but the catalog + dialect canonicalized only the 9-component tensor_terms expansion, to + support anisotropy. As a result, **the draft's own flagship example + (Shastry-Sutherland) does not pass the catalog dialect's validator**. + (Evidence: `shastry_sutherland_spin.yaml` — C9: unknown operator) +- **Proposal**: make `"S_i . S_j"` (isotropic spin-spin) an official + vocabulary entry, and specify a mechanical expansion rule into + tensor_terms (the same coefficient on the 3 diagonal components) in the + spec. Isotropic as shorthand, anisotropic as tensor_terms — defining these + roles at the spec level lets both coexist. At the same time, we recommend + also adding `"s_i . s_j"` (fermion-fermion spin product), needed for + multi-orbital Hund coupling, to the vocabulary (see 1.4). + +### 1.3 [High] Bond-orientation convention: prefer source-order (definition-order) preservation over canonicalization + +- **Problem**: draft §4.2 proposes an "orientation-canonicalization + convention (e.g. lexicographic order)", but for DM interactions the bond's + orientation *is* the sign of the coefficient itself (J_xy = +D_z, + J_yx = -D_z requires a transpose under bond reversal). In a design where a + single coupling definition is shared by multiple bonds, rewriting the + orientation via canonicalization **becomes inexpressible the moment bonds + that need reversal and bonds that don't are mixed together**. +- **Proposal**: adopt into the spec: "each bond is kept in its defined + orientation and written exactly once. Uniqueness is checked via reversal + equivalence (type, i, j, R) = (type, j, i, -R). The coefficient + transformation under reversal (complex conjugate for hopping, transpose + for the exchange tensor) is the consumer's responsibility." (We have + confirmed the catalog can describe DM interactions without breakdown under + this scheme — `kagome_dm_spin.yaml`) + +### 1.4 [High] Multi-orbital support: orbital-indexed operators, or a general 4-fermion term + +- **Problem**: `site_dof` can declare an orbital count, but there is no way + for the operator side to refer to an orbital. Orbital-resolved hopping + t_ab, Hund coupling, and pair hopping cannot be written. Even the + "orbital = separate label" workaround only reaches inter-orbital + density-density (U'). + (Evidence: `two_orbital_hubbard_chain.yaml`) +- **Proposal**: either of the following (can be combined). + 1. Specify a **general 4-fermion term** — an ordered sequence of + creation/annihilation operators with site/orbital/spin bindings (a + sketch already exists in this catalog's manual §6.6). + 2. As a near-term, practical scope: allow orbital indices on named + operators (e.g. `hop[a,b]`, `density-density[a,b]`, `s_i . s_j`). + The same mechanism is also needed to describe wannier90's J channels + (Hund, exchange, pair-hopping; manual §5.5), so this is high priority. + +### 1.5 [Medium] Allow `{param, scale}` in tensor_terms' coeff + +- **Problem**: for antisymmetric exchange (DM), two components share the + same parameter with opposite sign (`Jxy = +Dz`, `Jyx = -Dz`). Forcing an + independent parameter name per component invites users to break the + convention by "entering the same value in two places." +- **Proposal**: allow the `{param: Dz, scale: -1.0}` form in coeff. + (The catalog dialect's C8/C12 enforce StdFace-compatible 9-component + naming; this would be demoted to "an additional StdFace-catalog-only + convention," not a general rule.) + +### 1.6 [Medium] Make onsite (one-body terms) optional + +- **Problem**: requiring an empty `onsite:` even for models with no onsite + term is descriptive noise. (Evidence: `shastry_sutherland_spin.yaml` and + others — C2) +- **Proposal**: make `onsite` optional, and define "omitted" as "no + one-body term." + +### 1.7 [Medium] Consistency-check semantics for open-boundary systems + +- **Problem**: direction-dependent boundary conditions (e.g. cylindrical) + are straightforward to write, but the coordination-number consistency + check (this catalog's counting-expansion check) assumes a torus, and + cannot express or verify the coordination deficit at edge sites along an + open direction. (Evidence: `square_cylinder_spin.yaml`) +- **Proposal**: define a verification spec with expected values held on two + layers — "bulk coordination number + edge deficit count" (this could also + double as an acceptance test for the expansion engine). + +### 1.8 [Low] Clarify that aperiodic modulation is out of scope + +- Aperiodic modulation — a single impurity, or a coupling that differs only + at the edge — is, in principle, out of scope for the three-layer design + (unit cell + translation); a supercell approximation is the only recourse. + This is a reasonable trade-off, but stating "out of scope" explicitly in + the spec would help manage users' expectations. + +## 2. Catalog-side tooling improvements (a TODO for this repository; no spec revision needed) + +| Item | Description | Status | +|---|---|---| +| standalone mode | add `--standalone` to the linter (skip C10/C11's manifest cross-check, allow paths outside `lattice_catalog/`) so it can be used for syntax/consistency checks on user-authored lattices | not started (proposed) | +| onsite optional | once 1.6 is adopted into the draft, update C2 to match | pending spec | +| parameters declaration | once 1.1 is adopted, change C7 to a "declared-reference" check, and for StdFace-compatible catalogs keep the inventory cross-check as an additional check | pending spec | + +## 3. Summary (one page for the next meeting) + +- **Strengths (no change needed)**: the (from,to,R,type) bond description, + the three-layer separation, direction-dependent boundaries. No breakdown + in geometry description across all StdFace models plus the 5 non-trivial + lattice trials. +- **To decide now (High)**: the parameter-declaration block / giving the + isotropic operator a vocabulary entry / switching the orientation + convention to source-order preservation / a path for multi-orbital + (4-fermion terms). +- **Good to settle (Medium)**: coeff's {param, scale} / making onsite + optional / the consistency-check format for open boundaries. +- **To document explicitly (Low)**: aperiodic modulation is out of scope. diff --git a/lattice_catalog/honeycomb/honeycomb_hubbard.yaml b/lattice_catalog/honeycomb/honeycomb_hubbard.yaml new file mode 100644 index 0000000..a0e6fff --- /dev/null +++ b/lattice_catalog/honeycomb/honeycomb_hubbard.yaml @@ -0,0 +1,120 @@ +# StdFace honeycomb / Hubbard model +# Corresponding stan.in input: model="Hubbard" / lattice="honeycomb" / W=4 / L=4 / t=1.0 / U=4.0 +# 2-site basis A/B (NsiteUC=2). t0/t1/t2 correspond respectively to the 3 nearest-neighbor bond +# directions (Kitaev x/y/z convention): t0=intra-cell bond (z equivalent), t1=W direction (x equivalent), t2=L direction (y equivalent). +# Consistency check: the nearest-neighbor coordination number is 3 for each site (t0+t1+t2, 1 bond each). +# See manifest.yaml for the consistency check. Signs are carried as data in scale/coeff (CONVENTIONS §6) +# Source: python/stdface/lattice/honeycomb_lattice.py::honeycomb (_BONDS), commit e42ef547c5fb073d78200752c5c5ff01375d4619 + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: honeycomb, model: hubbard} + +geometry: + dimension: 2 + lattice_vectors: + a1: [1.0, 0.0] # StdFace: Wx, Wy + a2: [0.5, 0.8660254037844386] # StdFace: Lx, Ly + sites: + - {label: A, frac: [0.0, 0.0]} # tau[0] + - {label: B, frac: [0.3333333333333333, 0.3333333333333333]} # tau[1] = (1/3, 1/3) + +system: + finite: true + size: [3, 3] # StdFace: W, L + boundary: + - {twist: {param: phase0}} # in degrees + - {twist: {param: phase1}} + +model: + site_dof: + A: {fermion: {orbitals: 1}} # extended dialect (CONVENTIONS §7) + B: {fermion: {orbitals: 1}} + + bonds: + # Preserves the source order of the reference implementation (_BONDS). site 0=A, 1=B. + # The t block (hop) is enumerated in _BONDS row order, followed by the V block + # (density-density) in the same row order (same presentation convention as chain/square/triangular). + # --- nearest neighbor (nn=1): Kitaev x/y/z convention, t1=x, t2=y, t0=z --- + - {from: A, to: B, R: [0, 0], type: t0} # intra-cell bond (Kitaev z equivalent) + - {from: B, to: A, R: [1, 0], type: t1} # W direction (Kitaev x equivalent) + - {from: B, to: A, R: [0, 1], type: t2} # L direction (Kitaev y equivalent) + # --- second-nearest neighbor (nn=2) --- + - {from: A, to: A, R: [1, 0], type: "t2'"} # W direction, 0->0 + - {from: B, to: B, R: [1, 0], type: "t2'"} # W direction, 1->1 + - {from: A, to: A, R: [0, 1], type: "t1'"} # L direction, 0->0 + - {from: B, to: B, R: [0, 1], type: "t1'"} # L direction, 1->1 + - {from: A, to: A, R: [1, -1], type: "t0'"} # W-L direction, 0->0 + - {from: B, to: B, R: [1, -1], type: "t0'"} # W-L direction, 1->1 + # --- third-nearest neighbor (nn=3) --- + - {from: A, to: B, R: [1, -1], type: "t1''"} # W-L direction + - {from: A, to: B, R: [-1, -1], type: "t0''"} # -W-L direction + - {from: A, to: B, R: [-1, 1], type: "t2''"} # -W+L direction + # --- nearest neighbor (V) --- + - {from: A, to: B, R: [0, 0], type: V0} + - {from: B, to: A, R: [1, 0], type: V1} + - {from: B, to: A, R: [0, 1], type: V2} + # --- second-nearest neighbor (V) --- + - {from: A, to: A, R: [1, 0], type: "V2'"} + - {from: B, to: B, R: [1, 0], type: "V2'"} + - {from: A, to: A, R: [0, 1], type: "V1'"} + - {from: B, to: B, R: [0, 1], type: "V1'"} + - {from: A, to: A, R: [1, -1], type: "V0'"} + - {from: B, to: B, R: [1, -1], type: "V0'"} + # --- third-nearest neighbor (V) --- + - {from: A, to: B, R: [1, -1], type: "V1''"} + - {from: A, to: B, R: [-1, -1], type: "V0''"} + - {from: A, to: B, R: [-1, 1], type: "V2''"} + + couplings: + # Contribution to H = value × operator (physical coefficient). -t is expressed via scale. + t0: {operator: "hop", value: {param: t0, scale: -1.0}} # -t Σσ(c†c+h.c.) + t1: {operator: "hop", value: {param: t1, scale: -1.0}} + t2: {operator: "hop", value: {param: t2, scale: -1.0}} + "t2'": {operator: "hop", value: {param: "t2'", scale: -1.0}} + "t1'": {operator: "hop", value: {param: "t1'", scale: -1.0}} + "t0'": {operator: "hop", value: {param: "t0'", scale: -1.0}} + "t1''": {operator: "hop", value: {param: "t1''", scale: -1.0}} + "t0''": {operator: "hop", value: {param: "t0''", scale: -1.0}} + "t2''": {operator: "hop", value: {param: "t2''", scale: -1.0}} + V0: {operator: "density-density", value: {param: V0}} # +V n_i n_j + V1: {operator: "density-density", value: {param: V1}} + V2: {operator: "density-density", value: {param: V2}} + "V2'": {operator: "density-density", value: {param: "V2'"}} + "V1'": {operator: "density-density", value: {param: "V1'"}} + "V0'": {operator: "density-density", value: {param: "V0'"}} + "V1''": {operator: "density-density", value: {param: "V1''"}} + "V0''": {operator: "density-density", value: {param: "V0''"}} + "V2''": {operator: "density-density", value: {param: "V2''"}} + + onsite: + A: + hubbard_u: # +U n↑n↓ + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: # -mu N + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: # -h Sz (electron spin) + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + B: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} diff --git a/lattice_catalog/honeycomb/honeycomb_kondo.yaml b/lattice_catalog/honeycomb/honeycomb_kondo.yaml new file mode 100644 index 0000000..132ceea --- /dev/null +++ b/lattice_catalog/honeycomb/honeycomb_kondo.yaml @@ -0,0 +1,149 @@ +# StdFace honeycomb / Kondo lattice model +# Corresponding stan.in input: model="Kondo" / lattice="honeycomb" / W=4 / L=4 / t=1.0 / J=1.0 +# The 2 physical sites A/B are each decomposed into 2 labels, _c (itinerant electron) / _s +# (localized spin) (CONVENTIONS §6.7). The Kondo J bond is 1 per physical site, with the +# itinerant side as the 1st endpoint (A_c->A_s, B_c->B_s) — this directly reflects the order +# in which the reference implementation doubles each site within the unit cell. +# The field (h/Gamma/Gamma_y) is applied to both the itinerant electrons and the localized spins +# (python/stdface/core/model_plugin.py::KondoModel). +# The correspondence with the current implementation's site doubling (first half = localized S2, second half = itinerant) is described in manual Section 4. +# Source: python/stdface/lattice/honeycomb_lattice.py::honeycomb (_BONDS), commit e42ef547c5fb073d78200752c5c5ff01375d4619 + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: honeycomb, model: kondo} + +geometry: + dimension: 2 + lattice_vectors: + a1: [1.0, 0.0] # StdFace: Wx, Wy + a2: [0.5, 0.8660254037844386] # StdFace: Lx, Ly + sites: + - {label: A_c, frac: [0.0, 0.0]} # itinerant electron (physical site A, tau[0]) + - {label: A_s, frac: [0.0, 0.0]} # localized spin (same as above) + - {label: B_c, frac: [0.3333333333333333, 0.3333333333333333]} # itinerant electron (physical site B, tau[1]) + - {label: B_s, frac: [0.3333333333333333, 0.3333333333333333]} # localized spin (same as above) + +system: + finite: true + size: [3, 3] # StdFace: W, L + boundary: + - {twist: {param: phase0}} # in degrees + - {twist: {param: phase1}} + +model: + site_dof: + A_c: {fermion: {orbitals: 1}} + A_s: {spin: {param: 2S, scale: 0.5, default: 0.5}} + B_c: {fermion: {orbitals: 1}} + B_s: {spin: {param: 2S, scale: 0.5, default: 0.5}} + + bonds: + # Kondo coupling follows the source order = argument order of general_j(..., itinerant, localized). + # Itinerant A_c/B_c is the 1st endpoint (matching the role of s_i . S_j). Preserves the + # reference implementation's traversal order, which doubles the unit cell in physical-site order (A then B). + - {from: A_c, to: A_s, R: [0, 0], type: J} # Kondo coupling (physical site A, intra-cell) + - {from: B_c, to: B_s, R: [0, 0], type: J} # Kondo coupling (physical site B, intra-cell) + # --- nearest neighbor (nn=1): Kitaev x/y/z convention, t1=x, t2=y, t0=z --- + - {from: A_c, to: B_c, R: [0, 0], type: t0} # intra-cell bond (Kitaev z equivalent) + - {from: B_c, to: A_c, R: [1, 0], type: t1} # W direction (Kitaev x equivalent) + - {from: B_c, to: A_c, R: [0, 1], type: t2} # L direction (Kitaev y equivalent) + # --- second-nearest neighbor (nn=2) --- + - {from: A_c, to: A_c, R: [1, 0], type: "t2'"} + - {from: B_c, to: B_c, R: [1, 0], type: "t2'"} + - {from: A_c, to: A_c, R: [0, 1], type: "t1'"} + - {from: B_c, to: B_c, R: [0, 1], type: "t1'"} + - {from: A_c, to: A_c, R: [1, -1], type: "t0'"} + - {from: B_c, to: B_c, R: [1, -1], type: "t0'"} + # --- third-nearest neighbor (nn=3) --- + - {from: A_c, to: B_c, R: [1, -1], type: "t1''"} + - {from: A_c, to: B_c, R: [-1, -1], type: "t0''"} + - {from: A_c, to: B_c, R: [-1, 1], type: "t2''"} + # --- nearest neighbor (V) --- + - {from: A_c, to: B_c, R: [0, 0], type: V0} + - {from: B_c, to: A_c, R: [1, 0], type: V1} + - {from: B_c, to: A_c, R: [0, 1], type: V2} + # --- second-nearest neighbor (V) --- + - {from: A_c, to: A_c, R: [1, 0], type: "V2'"} + - {from: B_c, to: B_c, R: [1, 0], type: "V2'"} + - {from: A_c, to: A_c, R: [0, 1], type: "V1'"} + - {from: B_c, to: B_c, R: [0, 1], type: "V1'"} + - {from: A_c, to: A_c, R: [1, -1], type: "V0'"} + - {from: B_c, to: B_c, R: [1, -1], type: "V0'"} + # --- third-nearest neighbor (V) --- + - {from: A_c, to: B_c, R: [1, -1], type: "V1''"} + - {from: A_c, to: B_c, R: [-1, -1], type: "V0''"} + - {from: A_c, to: B_c, R: [-1, 1], type: "V2''"} + + couplings: + t0: {operator: "hop", value: {param: t0, scale: -1.0}} + t1: {operator: "hop", value: {param: t1, scale: -1.0}} + t2: {operator: "hop", value: {param: t2, scale: -1.0}} + "t2'": {operator: "hop", value: {param: "t2'", scale: -1.0}} + "t1'": {operator: "hop", value: {param: "t1'", scale: -1.0}} + "t0'": {operator: "hop", value: {param: "t0'", scale: -1.0}} + "t1''": {operator: "hop", value: {param: "t1''", scale: -1.0}} + "t0''": {operator: "hop", value: {param: "t0''", scale: -1.0}} + "t2''": {operator: "hop", value: {param: "t2''", scale: -1.0}} + V0: {operator: "density-density", value: {param: V0}} + V1: {operator: "density-density", value: {param: V1}} + V2: {operator: "density-density", value: {param: V2}} + "V2'": {operator: "density-density", value: {param: "V2'"}} + "V1'": {operator: "density-density", value: {param: "V1'"}} + "V0'": {operator: "density-density", value: {param: "V0'"}} + "V1''": {operator: "density-density", value: {param: "V1''"}} + "V0''": {operator: "density-density", value: {param: "V0''"}} + "V2''": {operator: "density-density", value: {param: "V2''"}} + J: {operator: "s_i . S_j", value: {param: J}} # +J s·S (1st endpoint = itinerant) + + onsite: + A_c: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + A_s: + field_z: # same 3 components apply to the localized side + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + B_c: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + B_s: + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} diff --git a/lattice_catalog/honeycomb/honeycomb_spin.yaml b/lattice_catalog/honeycomb/honeycomb_spin.yaml new file mode 100644 index 0000000..4633f81 --- /dev/null +++ b/lattice_catalog/honeycomb/honeycomb_spin.yaml @@ -0,0 +1,187 @@ +# StdFace honeycomb / Spin model +# Corresponding stan.in input: model="Spin" / lattice="honeycomb" / W=4 / L=4 / J=1.0 (J is an alias of J0/J1/J2) +# 2-site basis A/B (NsiteUC=2). J0/J1/J2 correspond respectively to the 3 nearest-neighbor bond +# directions (Kitaev x/y/z convention): J0=intra-cell bond (Kitaev z equivalent), J1=W direction (x equivalent), +# J2=L direction (y equivalent). Consistency check: the nearest-neighbor coordination number is 3 for each site (J0+J1+J2, 1 bond each). +# See the honeycomb/honeycomb_spin.yaml entry of manifest.yaml for the consistency check. +# Source: python/stdface/lattice/honeycomb_lattice.py::honeycomb (_BONDS), commit e42ef547c5fb073d78200752c5c5ff01375d4619 + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: honeycomb, model: spin} + +geometry: + dimension: 2 + lattice_vectors: + a1: [1.0, 0.0] # StdFace: Wx, Wy (default a, 0) + a2: [0.5, 0.8660254037844386] # StdFace: Lx, Ly (default a/2, a*sqrt(3)/2) + sites: + - {label: A, frac: [0.0, 0.0]} # tau[0] + - {label: B, frac: [0.3333333333333333, 0.3333333333333333]} # tau[1] = (1/3, 1/3) + +system: + finite: true + size: [3, 3] # StdFace: W, L + boundary: + - {twist: {param: phase0}} # in degrees. phase0=0 is equivalent to periodic + - {twist: {param: phase1}} + +model: + site_dof: + A: {spin: {param: 2S, scale: 0.5, default: 0.5}} # S = 0.5 × 2S. Default S=1/2 + B: {spin: {param: 2S, scale: 0.5, default: 0.5}} + + bonds: + # Preserves the source order of the reference implementation (_BONDS). site 0=A, 1=B. + # --- nearest neighbor (nn=1): Kitaev x/y/z convention, J1=x, J2=y, J0=z --- + - {from: A, to: B, R: [0, 0], type: J0} # intra-cell bond (Kitaev z equivalent) + - {from: B, to: A, R: [1, 0], type: J1} # W direction (Kitaev x equivalent) + - {from: B, to: A, R: [0, 1], type: J2} # L direction (Kitaev y equivalent) + # --- second-nearest neighbor (nn=2) --- + - {from: A, to: A, R: [1, 0], type: "J2'"} # W direction, 0->0 + - {from: B, to: B, R: [1, 0], type: "J2'"} # W direction, 1->1 + - {from: A, to: A, R: [0, 1], type: "J1'"} # L direction, 0->0 + - {from: B, to: B, R: [0, 1], type: "J1'"} # L direction, 1->1 + - {from: A, to: A, R: [1, -1], type: "J0'"} # W-L direction, 0->0 + - {from: B, to: B, R: [1, -1], type: "J0'"} # W-L direction, 1->1 + # --- third-nearest neighbor (nn=3) --- + - {from: A, to: B, R: [1, -1], type: "J1''"} # W-L direction + - {from: A, to: B, R: [-1, -1], type: "J0''"} # -W-L direction + - {from: A, to: B, R: [-1, 1], type: "J2''"} # -W+L direction + + couplings: + # J family is in canonical 9-component form. Parameter resolution: component > scalar diagonal > global alias > 0 + J0: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J0x}} + - {ops: [Sy, Sy], coeff: {param: J0y}} + - {ops: [Sz, Sz], coeff: {param: J0z}} + - {ops: [Sx, Sy], coeff: {param: J0xy}} + - {ops: [Sx, Sz], coeff: {param: J0xz}} + - {ops: [Sy, Sx], coeff: {param: J0yx}} + - {ops: [Sy, Sz], coeff: {param: J0yz}} + - {ops: [Sz, Sx], coeff: {param: J0zx}} + - {ops: [Sz, Sy], coeff: {param: J0zy}} + J1: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J1x}} + - {ops: [Sy, Sy], coeff: {param: J1y}} + - {ops: [Sz, Sz], coeff: {param: J1z}} + - {ops: [Sx, Sy], coeff: {param: J1xy}} + - {ops: [Sx, Sz], coeff: {param: J1xz}} + - {ops: [Sy, Sx], coeff: {param: J1yx}} + - {ops: [Sy, Sz], coeff: {param: J1yz}} + - {ops: [Sz, Sx], coeff: {param: J1zx}} + - {ops: [Sz, Sy], coeff: {param: J1zy}} + J2: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J2x}} + - {ops: [Sy, Sy], coeff: {param: J2y}} + - {ops: [Sz, Sz], coeff: {param: J2z}} + - {ops: [Sx, Sy], coeff: {param: J2xy}} + - {ops: [Sx, Sz], coeff: {param: J2xz}} + - {ops: [Sy, Sx], coeff: {param: J2yx}} + - {ops: [Sy, Sz], coeff: {param: J2yz}} + - {ops: [Sz, Sx], coeff: {param: J2zx}} + - {ops: [Sz, Sy], coeff: {param: J2zy}} + "J2'": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J2'x"}} + - {ops: [Sy, Sy], coeff: {param: "J2'y"}} + - {ops: [Sz, Sz], coeff: {param: "J2'z"}} + - {ops: [Sx, Sy], coeff: {param: "J2'xy"}} + - {ops: [Sx, Sz], coeff: {param: "J2'xz"}} + - {ops: [Sy, Sx], coeff: {param: "J2'yx"}} + - {ops: [Sy, Sz], coeff: {param: "J2'yz"}} + - {ops: [Sz, Sx], coeff: {param: "J2'zx"}} + - {ops: [Sz, Sy], coeff: {param: "J2'zy"}} + "J1'": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J1'x"}} + - {ops: [Sy, Sy], coeff: {param: "J1'y"}} + - {ops: [Sz, Sz], coeff: {param: "J1'z"}} + - {ops: [Sx, Sy], coeff: {param: "J1'xy"}} + - {ops: [Sx, Sz], coeff: {param: "J1'xz"}} + - {ops: [Sy, Sx], coeff: {param: "J1'yx"}} + - {ops: [Sy, Sz], coeff: {param: "J1'yz"}} + - {ops: [Sz, Sx], coeff: {param: "J1'zx"}} + - {ops: [Sz, Sy], coeff: {param: "J1'zy"}} + "J0'": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J0'x"}} + - {ops: [Sy, Sy], coeff: {param: "J0'y"}} + - {ops: [Sz, Sz], coeff: {param: "J0'z"}} + - {ops: [Sx, Sy], coeff: {param: "J0'xy"}} + - {ops: [Sx, Sz], coeff: {param: "J0'xz"}} + - {ops: [Sy, Sx], coeff: {param: "J0'yx"}} + - {ops: [Sy, Sz], coeff: {param: "J0'yz"}} + - {ops: [Sz, Sx], coeff: {param: "J0'zx"}} + - {ops: [Sz, Sy], coeff: {param: "J0'zy"}} + "J1''": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J1''x"}} + - {ops: [Sy, Sy], coeff: {param: "J1''y"}} + - {ops: [Sz, Sz], coeff: {param: "J1''z"}} + - {ops: [Sx, Sy], coeff: {param: "J1''xy"}} + - {ops: [Sx, Sz], coeff: {param: "J1''xz"}} + - {ops: [Sy, Sx], coeff: {param: "J1''yx"}} + - {ops: [Sy, Sz], coeff: {param: "J1''yz"}} + - {ops: [Sz, Sx], coeff: {param: "J1''zx"}} + - {ops: [Sz, Sy], coeff: {param: "J1''zy"}} + "J0''": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J0''x"}} + - {ops: [Sy, Sy], coeff: {param: "J0''y"}} + - {ops: [Sz, Sz], coeff: {param: "J0''z"}} + - {ops: [Sx, Sy], coeff: {param: "J0''xy"}} + - {ops: [Sx, Sz], coeff: {param: "J0''xz"}} + - {ops: [Sy, Sx], coeff: {param: "J0''yx"}} + - {ops: [Sy, Sz], coeff: {param: "J0''yz"}} + - {ops: [Sz, Sx], coeff: {param: "J0''zx"}} + - {ops: [Sz, Sy], coeff: {param: "J0''zy"}} + "J2''": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J2''x"}} + - {ops: [Sy, Sy], coeff: {param: "J2''y"}} + - {ops: [Sz, Sz], coeff: {param: "J2''z"}} + - {ops: [Sx, Sy], coeff: {param: "J2''xy"}} + - {ops: [Sx, Sz], coeff: {param: "J2''xz"}} + - {ops: [Sy, Sx], coeff: {param: "J2''yx"}} + - {ops: [Sy, Sz], coeff: {param: "J2''yz"}} + - {ops: [Sz, Sx], coeff: {param: "J2''zx"}} + - {ops: [Sz, Sy], coeff: {param: "J2''zy"}} + + onsite: + A: + field_z: # -h Sz + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: # -Gamma Sx + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: # -Gamma_y Sy + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + aniso_z: # D (Sz)^2 + operator: {tensor_terms: [{ops: [Szz], coeff: 1.0}]} + value: {param: D} + B: + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + aniso_z: + operator: {tensor_terms: [{ops: [Szz], coeff: 1.0}]} + value: {param: D} diff --git a/lattice_catalog/kagome/kagome_hubbard.yaml b/lattice_catalog/kagome/kagome_hubbard.yaml new file mode 100644 index 0000000..855eda8 --- /dev/null +++ b/lattice_catalog/kagome/kagome_hubbard.yaml @@ -0,0 +1,133 @@ +# StdFace kagome / Hubbard model +# Corresponding stan.in input: model="Hubbard" / lattice="kagome" / W=4 / L=4 / t=1.0 / U=4.0 +# 3-site basis A/B/C (NsiteUC=3, tau=(0,0),(1/2,0),(0,1/2)). +# t0/t1/t2 correspond respectively to the 3 types of intra/inter-cell nearest-neighbor bonds: +# t0=B-C direction, t1=A-C direction, t2=A-B direction. The primed series (t0'/t1'/t2') are +# second-nearest-neighbor bonds. A third-nearest-neighbor (pp) series does not exist in the source. +# Consistency check: the nearest-neighbor coordination number is 4 for each site (a feature of the +# kagome lattice: each site connects to only 2 of the 3 nearest-neighbor bond types, each with coordination number 2). +# See manifest.yaml for the consistency check. Signs are carried as data in scale/coeff (CONVENTIONS §6) +# Source: python/stdface/lattice/kagome.py::kagome (_BONDS, L164-179), commit 20b2c3cda3a489b5dcd4c9180a19ca23e9280c73 + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: kagome, model: hubbard} + +geometry: + dimension: 2 + lattice_vectors: + a1: [1.0, 0.0] # StdFace: Wx, Wy + a2: [0.5, 0.8660254037844386] # StdFace: Lx, Ly + sites: + - {label: A, frac: [0.0, 0.0]} # tau[0] + - {label: B, frac: [0.5, 0.0]} # tau[1] = (1/2, 0) + - {label: C, frac: [0.0, 0.5]} # tau[2] = (0, 1/2) + +system: + finite: true + size: [3, 3] # StdFace: W, L + boundary: + - {twist: {param: phase0}} # in degrees + - {twist: {param: phase1}} + +model: + site_dof: + A: {fermion: {orbitals: 1}} # extended dialect (CONVENTIONS §7) + B: {fermion: {orbitals: 1}} + C: {fermion: {orbitals: 1}} + + bonds: + # Preserves the source order of the reference implementation (_BONDS). site 0=A, 1=B, 2=C. + # The t block (hop) is enumerated in _BONDS row order, followed by the V block + # (density-density) in the same row order (same presentation convention as chain/square/triangular/honeycomb). + # --- nearest neighbor (nn=1) --- + - {from: A, to: B, R: [0, 0], type: t2} # intra 0->1 + - {from: A, to: C, R: [0, 0], type: t1} # intra 0->2 + - {from: B, to: C, R: [0, 0], type: t0} # intra 1->2 + - {from: B, to: A, R: [1, 0], type: t2} # along W + - {from: C, to: A, R: [0, 1], type: t1} # along L + - {from: B, to: C, R: [1, -1], type: t0} # along W-L + # --- second-nearest neighbor (nn=2) --- + - {from: C, to: A, R: [1, 0], type: "t1'"} # along W, 2->0 + - {from: B, to: C, R: [1, 0], type: "t0'"} # along W, 1->2 + - {from: B, to: A, R: [0, 1], type: "t2'"} # along L, 1->0 + - {from: C, to: B, R: [0, 1], type: "t0'"} # along L, 2->1 + - {from: A, to: C, R: [1, -1], type: "t1'"} # along W-L, 0->2 + - {from: A, to: B, R: [-1, 1], type: "t2'"} # along L-W, 0->1 + # --- nearest neighbor (V) --- + - {from: A, to: B, R: [0, 0], type: V2} + - {from: A, to: C, R: [0, 0], type: V1} + - {from: B, to: C, R: [0, 0], type: V0} + - {from: B, to: A, R: [1, 0], type: V2} + - {from: C, to: A, R: [0, 1], type: V1} + - {from: B, to: C, R: [1, -1], type: V0} + # --- second-nearest neighbor (V) --- + - {from: C, to: A, R: [1, 0], type: "V1'"} + - {from: B, to: C, R: [1, 0], type: "V0'"} + - {from: B, to: A, R: [0, 1], type: "V2'"} + - {from: C, to: B, R: [0, 1], type: "V0'"} + - {from: A, to: C, R: [1, -1], type: "V1'"} + - {from: A, to: B, R: [-1, 1], type: "V2'"} + + couplings: + # Contribution to H = value × operator (physical coefficient). -t is expressed via scale. + t0: {operator: "hop", value: {param: t0, scale: -1.0}} # -t Σσ(c†c+h.c.) + t1: {operator: "hop", value: {param: t1, scale: -1.0}} + t2: {operator: "hop", value: {param: t2, scale: -1.0}} + "t0'": {operator: "hop", value: {param: "t0'", scale: -1.0}} + "t1'": {operator: "hop", value: {param: "t1'", scale: -1.0}} + "t2'": {operator: "hop", value: {param: "t2'", scale: -1.0}} + V0: {operator: "density-density", value: {param: V0}} # +V n_i n_j + V1: {operator: "density-density", value: {param: V1}} + V2: {operator: "density-density", value: {param: V2}} + "V0'": {operator: "density-density", value: {param: "V0'"}} + "V1'": {operator: "density-density", value: {param: "V1'"}} + "V2'": {operator: "density-density", value: {param: "V2'"}} + + onsite: + A: + hubbard_u: # +U n↑n↓ + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: # -mu N + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: # -h Sz (electron spin) + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + B: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + C: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} diff --git a/lattice_catalog/kagome/kagome_kondo.yaml b/lattice_catalog/kagome/kagome_kondo.yaml new file mode 100644 index 0000000..a935a12 --- /dev/null +++ b/lattice_catalog/kagome/kagome_kondo.yaml @@ -0,0 +1,175 @@ +# StdFace kagome / Kondo lattice model +# Corresponding stan.in input: model="Kondo" / lattice="kagome" / W=4 / L=4 / t=1.0 / J=1.0 +# The 3 physical sites A/B/C are each decomposed into 2 labels, _c (itinerant electron) / _s +# (localized spin) (CONVENTIONS §6.7). The Kondo J bond is 1 per physical site, with the +# itinerant side as the 1st endpoint (A_c->A_s, B_c->B_s, C_c->C_s) — this directly reflects the +# order in which the reference implementation doubles each site within the unit cell (physical-site order A,B,C). +# The field (h/Gamma/Gamma_y) is applied to both the itinerant electrons and the localized spins +# (python/stdface/core/model_plugin.py::KondoModel). +# t0/t1/t2 correspond respectively to the 3 types of intra/inter-cell nearest-neighbor bonds: +# t0=B-C direction, t1=A-C direction, t2=A-B direction. The primed series (t0'/t1'/t2') are +# second-nearest-neighbor bonds. A third-nearest-neighbor (pp) series does not exist in the source. +# The correspondence with the current implementation's site doubling (first half = localized S2, second half = itinerant) is described in manual Section 4. +# Source: python/stdface/lattice/kagome.py::kagome (_BONDS, L164-179), commit 20b2c3cda3a489b5dcd4c9180a19ca23e9280c73 + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: kagome, model: kondo} + +geometry: + dimension: 2 + lattice_vectors: + a1: [1.0, 0.0] # StdFace: Wx, Wy + a2: [0.5, 0.8660254037844386] # StdFace: Lx, Ly + sites: + - {label: A_c, frac: [0.0, 0.0]} # itinerant electron (physical site A, tau[0]) + - {label: A_s, frac: [0.0, 0.0]} # localized spin (same as above) + - {label: B_c, frac: [0.5, 0.0]} # itinerant electron (physical site B, tau[1]) + - {label: B_s, frac: [0.5, 0.0]} # localized spin (same as above) + - {label: C_c, frac: [0.0, 0.5]} # itinerant electron (physical site C, tau[2]) + - {label: C_s, frac: [0.0, 0.5]} # localized spin (same as above) + +system: + finite: true + size: [3, 3] # StdFace: W, L + boundary: + - {twist: {param: phase0}} # in degrees + - {twist: {param: phase1}} + +model: + site_dof: + A_c: {fermion: {orbitals: 1}} + A_s: {spin: {param: 2S, scale: 0.5, default: 0.5}} + B_c: {fermion: {orbitals: 1}} + B_s: {spin: {param: 2S, scale: 0.5, default: 0.5}} + C_c: {fermion: {orbitals: 1}} + C_s: {spin: {param: 2S, scale: 0.5, default: 0.5}} + + bonds: + # Kondo coupling follows the source order = argument order of general_j(..., itinerant, localized). + # Itinerant A_c/B_c/C_c is the 1st endpoint (matching the role of s_i . S_j). Preserves the + # reference implementation's traversal order, which doubles the unit cell in physical-site order (A then B then C). + - {from: A_c, to: A_s, R: [0, 0], type: J} # Kondo coupling (physical site A, intra-cell) + - {from: B_c, to: B_s, R: [0, 0], type: J} # Kondo coupling (physical site B, intra-cell) + - {from: C_c, to: C_s, R: [0, 0], type: J} # Kondo coupling (physical site C, intra-cell) + # --- nearest neighbor (nn=1) --- + - {from: A_c, to: B_c, R: [0, 0], type: t2} # intra 0->1 + - {from: A_c, to: C_c, R: [0, 0], type: t1} # intra 0->2 + - {from: B_c, to: C_c, R: [0, 0], type: t0} # intra 1->2 + - {from: B_c, to: A_c, R: [1, 0], type: t2} # along W + - {from: C_c, to: A_c, R: [0, 1], type: t1} # along L + - {from: B_c, to: C_c, R: [1, -1], type: t0} # along W-L + # --- second-nearest neighbor (nn=2) --- + - {from: C_c, to: A_c, R: [1, 0], type: "t1'"} # along W, 2->0 + - {from: B_c, to: C_c, R: [1, 0], type: "t0'"} # along W, 1->2 + - {from: B_c, to: A_c, R: [0, 1], type: "t2'"} # along L, 1->0 + - {from: C_c, to: B_c, R: [0, 1], type: "t0'"} # along L, 2->1 + - {from: A_c, to: C_c, R: [1, -1], type: "t1'"} # along W-L, 0->2 + - {from: A_c, to: B_c, R: [-1, 1], type: "t2'"} # along L-W, 0->1 + # --- nearest neighbor (V) --- + - {from: A_c, to: B_c, R: [0, 0], type: V2} + - {from: A_c, to: C_c, R: [0, 0], type: V1} + - {from: B_c, to: C_c, R: [0, 0], type: V0} + - {from: B_c, to: A_c, R: [1, 0], type: V2} + - {from: C_c, to: A_c, R: [0, 1], type: V1} + - {from: B_c, to: C_c, R: [1, -1], type: V0} + # --- second-nearest neighbor (V) --- + - {from: C_c, to: A_c, R: [1, 0], type: "V1'"} + - {from: B_c, to: C_c, R: [1, 0], type: "V0'"} + - {from: B_c, to: A_c, R: [0, 1], type: "V2'"} + - {from: C_c, to: B_c, R: [0, 1], type: "V0'"} + - {from: A_c, to: C_c, R: [1, -1], type: "V1'"} + - {from: A_c, to: B_c, R: [-1, 1], type: "V2'"} + + couplings: + t0: {operator: "hop", value: {param: t0, scale: -1.0}} + t1: {operator: "hop", value: {param: t1, scale: -1.0}} + t2: {operator: "hop", value: {param: t2, scale: -1.0}} + "t0'": {operator: "hop", value: {param: "t0'", scale: -1.0}} + "t1'": {operator: "hop", value: {param: "t1'", scale: -1.0}} + "t2'": {operator: "hop", value: {param: "t2'", scale: -1.0}} + V0: {operator: "density-density", value: {param: V0}} + V1: {operator: "density-density", value: {param: V1}} + V2: {operator: "density-density", value: {param: V2}} + "V0'": {operator: "density-density", value: {param: "V0'"}} + "V1'": {operator: "density-density", value: {param: "V1'"}} + "V2'": {operator: "density-density", value: {param: "V2'"}} + J: {operator: "s_i . S_j", value: {param: J}} # +J s·S (1st endpoint = itinerant) + + onsite: + A_c: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + A_s: + field_z: # same 3 components apply to the localized side + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + B_c: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + B_s: + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + C_c: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + C_s: + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} diff --git a/lattice_catalog/kagome/kagome_spin.yaml b/lattice_catalog/kagome/kagome_spin.yaml new file mode 100644 index 0000000..6372eb4 --- /dev/null +++ b/lattice_catalog/kagome/kagome_spin.yaml @@ -0,0 +1,168 @@ +# StdFace kagome / Spin model +# Corresponding stan.in input: model="Spin" / lattice="kagome" / W=4 / L=4 / J=1.0 (J is an alias of J0/J1/J2) +# 3-site basis A/B/C (NsiteUC=3, tau=(0,0),(1/2,0),(0,1/2)). +# J0/J1/J2 correspond respectively to the 3 types of intra/inter-cell nearest-neighbor bonds: +# J0=B-C direction, J1=A-C direction, J2=A-B direction. The primed series (J0'/J1'/J2') are +# second-nearest-neighbor bonds. A third-nearest-neighbor (pp) series does not exist in the source. +# Consistency check: the nearest-neighbor coordination number is 4 for each site (a feature of the +# kagome lattice: each site connects to only 2 of the 3 nearest-neighbor bond types, each with coordination number 2). +# See the kagome/kagome_spin.yaml entry of manifest.yaml for the consistency check. +# Source: python/stdface/lattice/kagome.py::kagome (_BONDS, L164-179), commit 20b2c3cda3a489b5dcd4c9180a19ca23e9280c73 + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: kagome, model: spin} + +geometry: + dimension: 2 + lattice_vectors: + a1: [1.0, 0.0] # StdFace: Wx, Wy (default a, 0) + a2: [0.5, 0.8660254037844386] # StdFace: Lx, Ly (default a/2, a*sqrt(3)/2) + sites: + - {label: A, frac: [0.0, 0.0]} # tau[0] + - {label: B, frac: [0.5, 0.0]} # tau[1] = (1/2, 0) + - {label: C, frac: [0.0, 0.5]} # tau[2] = (0, 1/2) + +system: + finite: true + size: [3, 3] # StdFace: W, L + boundary: + - {twist: {param: phase0}} # in degrees. phase0=0 is equivalent to periodic + - {twist: {param: phase1}} + +model: + site_dof: + A: {spin: {param: 2S, scale: 0.5, default: 0.5}} # S = 0.5 × 2S. Default S=1/2 + B: {spin: {param: 2S, scale: 0.5, default: 0.5}} + C: {spin: {param: 2S, scale: 0.5, default: 0.5}} + + bonds: + # Preserves the source order of the reference implementation (_BONDS). site 0=A, 1=B, 2=C. + # --- nearest neighbor (nn=1) --- + - {from: A, to: B, R: [0, 0], type: J2} # intra 0->1 + - {from: A, to: C, R: [0, 0], type: J1} # intra 0->2 + - {from: B, to: C, R: [0, 0], type: J0} # intra 1->2 + - {from: B, to: A, R: [1, 0], type: J2} # along W + - {from: C, to: A, R: [0, 1], type: J1} # along L + - {from: B, to: C, R: [1, -1], type: J0} # along W-L + # --- second-nearest neighbor (nn=2) --- + - {from: C, to: A, R: [1, 0], type: "J1'"} # along W, 2->0 + - {from: B, to: C, R: [1, 0], type: "J0'"} # along W, 1->2 + - {from: B, to: A, R: [0, 1], type: "J2'"} # along L, 1->0 + - {from: C, to: B, R: [0, 1], type: "J0'"} # along L, 2->1 + - {from: A, to: C, R: [1, -1], type: "J1'"} # along W-L, 0->2 + - {from: A, to: B, R: [-1, 1], type: "J2'"} # along L-W, 0->1 + + couplings: + # J family is in canonical 9-component form. Parameter resolution: component > scalar diagonal > global alias > 0 + J0: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J0x}} + - {ops: [Sy, Sy], coeff: {param: J0y}} + - {ops: [Sz, Sz], coeff: {param: J0z}} + - {ops: [Sx, Sy], coeff: {param: J0xy}} + - {ops: [Sx, Sz], coeff: {param: J0xz}} + - {ops: [Sy, Sx], coeff: {param: J0yx}} + - {ops: [Sy, Sz], coeff: {param: J0yz}} + - {ops: [Sz, Sx], coeff: {param: J0zx}} + - {ops: [Sz, Sy], coeff: {param: J0zy}} + J1: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J1x}} + - {ops: [Sy, Sy], coeff: {param: J1y}} + - {ops: [Sz, Sz], coeff: {param: J1z}} + - {ops: [Sx, Sy], coeff: {param: J1xy}} + - {ops: [Sx, Sz], coeff: {param: J1xz}} + - {ops: [Sy, Sx], coeff: {param: J1yx}} + - {ops: [Sy, Sz], coeff: {param: J1yz}} + - {ops: [Sz, Sx], coeff: {param: J1zx}} + - {ops: [Sz, Sy], coeff: {param: J1zy}} + J2: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J2x}} + - {ops: [Sy, Sy], coeff: {param: J2y}} + - {ops: [Sz, Sz], coeff: {param: J2z}} + - {ops: [Sx, Sy], coeff: {param: J2xy}} + - {ops: [Sx, Sz], coeff: {param: J2xz}} + - {ops: [Sy, Sx], coeff: {param: J2yx}} + - {ops: [Sy, Sz], coeff: {param: J2yz}} + - {ops: [Sz, Sx], coeff: {param: J2zx}} + - {ops: [Sz, Sy], coeff: {param: J2zy}} + "J0'": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J0'x"}} + - {ops: [Sy, Sy], coeff: {param: "J0'y"}} + - {ops: [Sz, Sz], coeff: {param: "J0'z"}} + - {ops: [Sx, Sy], coeff: {param: "J0'xy"}} + - {ops: [Sx, Sz], coeff: {param: "J0'xz"}} + - {ops: [Sy, Sx], coeff: {param: "J0'yx"}} + - {ops: [Sy, Sz], coeff: {param: "J0'yz"}} + - {ops: [Sz, Sx], coeff: {param: "J0'zx"}} + - {ops: [Sz, Sy], coeff: {param: "J0'zy"}} + "J1'": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J1'x"}} + - {ops: [Sy, Sy], coeff: {param: "J1'y"}} + - {ops: [Sz, Sz], coeff: {param: "J1'z"}} + - {ops: [Sx, Sy], coeff: {param: "J1'xy"}} + - {ops: [Sx, Sz], coeff: {param: "J1'xz"}} + - {ops: [Sy, Sx], coeff: {param: "J1'yx"}} + - {ops: [Sy, Sz], coeff: {param: "J1'yz"}} + - {ops: [Sz, Sx], coeff: {param: "J1'zx"}} + - {ops: [Sz, Sy], coeff: {param: "J1'zy"}} + "J2'": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J2'x"}} + - {ops: [Sy, Sy], coeff: {param: "J2'y"}} + - {ops: [Sz, Sz], coeff: {param: "J2'z"}} + - {ops: [Sx, Sy], coeff: {param: "J2'xy"}} + - {ops: [Sx, Sz], coeff: {param: "J2'xz"}} + - {ops: [Sy, Sx], coeff: {param: "J2'yx"}} + - {ops: [Sy, Sz], coeff: {param: "J2'yz"}} + - {ops: [Sz, Sx], coeff: {param: "J2'zx"}} + - {ops: [Sz, Sy], coeff: {param: "J2'zy"}} + + onsite: + A: + field_z: # -h Sz + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: # -Gamma Sx + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: # -Gamma_y Sy + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + aniso_z: # D (Sz)^2 + operator: {tensor_terms: [{ops: [Szz], coeff: 1.0}]} + value: {param: D} + B: + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + aniso_z: + operator: {tensor_terms: [{ops: [Szz], coeff: 1.0}]} + value: {param: D} + C: + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + aniso_z: + operator: {tensor_terms: [{ops: [Szz], coeff: 1.0}]} + value: {param: D} diff --git a/lattice_catalog/ladder/ladder_w2_hubbard.yaml b/lattice_catalog/ladder/ladder_w2_hubbard.yaml new file mode 100644 index 0000000..1b14770 --- /dev/null +++ b/lattice_catalog/ladder/ladder_w2_hubbard.yaml @@ -0,0 +1,112 @@ +# StdFace ladder (W=2) / Hubbard model +# Corresponding stan.in input: model="Hubbard" / lattice="ladder" / W=2 / L=16 / t0=1.0 (rung) / t1=1.0 (leg) / U=4.0 +# +# Unit cell = 1 rung (W sites; W=2 -> labels A0, A1 = leg 0, leg 1). +# ladder.py sets NsiteUC=W and then fixes StdI.W to 1 (ladder.py:80-81). +# Grounds for the rung (former W) direction being open: (1) the dW component of _BONDS is always 0, +# (2) rung/diagonal bonds are only generated under the condition `if uc_i < NsiteUC - 1:` +# (ladder.py:184), so no bond is generated that "closes" from the last leg back to the first leg. +# Hence this catalog is represented as logically one-dimensional (periodic boundary only along L). +# phase0 is transcribed into the internal phase[1] (ladder.py:75-78). This is the same style of +# internal transcription as chain (CONVENTIONS.md §4). +# Signs are carried as data in scale/coeff (CONVENTIONS §6). +# +# W generalization rule (manually unrolling the dynamic loop of ladder.py:176-188; read J -> t/V): +# for uc_i in range(W): +# leg: A{uc_i}-A{uc_i} R=[1] t1/V1, R=[2] t1'/V1' +# if uc_i < W-1: +# rung (intra-cell): A{uc_i}-A{uc_i+1} R=[0] t0/V0 +# diag (L+1): A{uc_i}-A{uc_i+1} R=[1] t2/V2 +# diag (L-1): A{uc_i}-A{uc_i+1} R=[-1] t2'/V2' +# The t bonds and V bonds originate from the same physical bond (the same tuple of _BONDS), +# so following the same presentation convention as chain/square, the t block is listed +# first, followed by the V block (the physical ordering within each block preserves the uc_i loop order). +# Consistency check (W=2): coordination number 2 along the leg direction (t1), coordination number 1 for the rung (t0) (both legs are edges). +# See the ladder/ladder_w2_hubbard.yaml entry of manifest.yaml for the consistency check. +# Source: python/stdface/lattice/ladder.py::ladder (_BONDS, L176-188), commit e733ff893a52b81addd27ef7e347f77273c0d129 + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: ladder, model: hubbard} + +geometry: + dimension: 1 + lattice_vectors: + a1: [1.0] # StdFace: Llength (default a=1.0). No lattice_vector for the rung direction since it is non-periodic + sites: + - {label: A0, frac: [0.0]} # leg 0 (edge) + - {label: A1, frac: [0.0]} # leg 1 (edge) + +system: + finite: true + size: [16] # StdFace: L + boundary: + - {twist: {param: phase0}} # in degrees. Transcribed to internal phase[1] (phase[0] is always 0) + +model: + site_dof: + A0: {fermion: {orbitals: 1}} # extended dialect (CONVENTIONS §7) + A1: {fermion: {orbitals: 1}} + + bonds: + # --- t block (uc_i loop order, leg 0 -> leg 1) --- + - {from: A0, to: A0, R: [1], type: t1} + - {from: A0, to: A0, R: [2], type: "t1'"} + - {from: A0, to: A1, R: [0], type: t0} + - {from: A0, to: A1, R: [1], type: t2} + - {from: A0, to: A1, R: [-1], type: "t2'"} + - {from: A1, to: A1, R: [1], type: t1} + - {from: A1, to: A1, R: [2], type: "t1'"} + # --- V block (same physical bonds, same order) --- + - {from: A0, to: A0, R: [1], type: V1} + - {from: A0, to: A0, R: [2], type: "V1'"} + - {from: A0, to: A1, R: [0], type: V0} + - {from: A0, to: A1, R: [1], type: V2} + - {from: A0, to: A1, R: [-1], type: "V2'"} + - {from: A1, to: A1, R: [1], type: V1} + - {from: A1, to: A1, R: [2], type: "V1'"} + + couplings: + # Contribution to H = value × operator (physical coefficient). -t is expressed via scale. + t0: {operator: "hop", value: {param: t0, scale: -1.0}} # -t Σσ(c†c+h.c.) + t1: {operator: "hop", value: {param: t1, scale: -1.0}} + "t1'": {operator: "hop", value: {param: "t1'", scale: -1.0}} + t2: {operator: "hop", value: {param: t2, scale: -1.0}} + "t2'": {operator: "hop", value: {param: "t2'", scale: -1.0}} + V0: {operator: "density-density", value: {param: V0}} # +V n_i n_j + V1: {operator: "density-density", value: {param: V1}} + "V1'": {operator: "density-density", value: {param: "V1'"}} + V2: {operator: "density-density", value: {param: V2}} + "V2'": {operator: "density-density", value: {param: "V2'"}} + + onsite: + A0: + hubbard_u: # +U n↑n↓ + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: # -mu N + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: # -h Sz (electron spin) + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + A1: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} diff --git a/lattice_catalog/ladder/ladder_w2_kondo.yaml b/lattice_catalog/ladder/ladder_w2_kondo.yaml new file mode 100644 index 0000000..523f6a2 --- /dev/null +++ b/lattice_catalog/ladder/ladder_w2_kondo.yaml @@ -0,0 +1,145 @@ +# StdFace ladder (W=2) / Kondo lattice model +# Corresponding stan.in input: model="Kondo" / lattice="ladder" / W=2 / L=16 / t0=1.0 / t1=1.0 / J=1.0 +# The field (h/Gamma/Gamma_y) is applied to both the itinerant electrons and the localized spins +# (python/stdface/core/model_plugin.py::KondoModel). +# The correspondence with the current implementation's site doubling (first half = localized S2, second half = itinerant) is described in manual Section 4. +# The Kondo J coupling is 1 bond per leg, A{i}_c -> A{i}_s (itinerant is the 1st endpoint). +# +# Unit cell = 1 rung (W sites; W=2 -> leg 0, leg 1). Each leg is doubled by Kondo into +# 2 labels: _c (itinerant electron) / _s (localized spin). +# ladder.py sets NsiteUC=W and then fixes StdI.W to 1 (ladder.py:80-81). +# Grounds for the rung (former W) direction being open: (1) the dW component of _BONDS is always 0, +# (2) rung/diagonal bonds are only generated under the condition `if uc_i < NsiteUC - 1:` +# (ladder.py:184), so no bond is generated that "closes" from the last leg back to the first leg. +# Hence this catalog is represented as logically one-dimensional (periodic boundary only along L). +# phase0 is transcribed into the internal phase[1] (ladder.py:75-78). Same style as chain +# (CONVENTIONS.md §4). +# +# W generalization rule (t/V are the manually-unrolled dynamic loop of ladder.py:176-188, read J -> t/V. +# The Kondo J is generated per leg uc_i as 1 bond A{uc_i}_c-A{uc_i}_s R=[0], in leg order +# — following expand_bonds_2d's intra-cell loop order: the local terms (including Kondo J) are +# added first for all legs, and only afterward are the t/V bonds of _BONDS added): +# for uc_i in range(W): J: A{uc_i}_c-A{uc_i}_s R=[0] <- local-term loop (first) +# for uc_i in range(W): <- _BONDS loop (after) +# leg: A{uc_i}_c-A{uc_i}_c R=[1] t1/V1, R=[2] t1'/V1' +# if uc_i < W-1: +# rung (intra-cell): A{uc_i}_c-A{uc_i+1}_c R=[0] t0/V0 +# diag (L+1): A{uc_i}_c-A{uc_i+1}_c R=[1] t2/V2 +# diag (L-1): A{uc_i}_c-A{uc_i+1}_c R=[-1] t2'/V2' +# Consistency check (W=2): coordination number 2 along the leg direction (t1), coordination number 1 for the rung (t0) (both legs are edges), +# Kondo J coordination number is 1 for each site. +# See the ladder/ladder_w2_kondo.yaml entry of manifest.yaml for the consistency check. +# Source: python/stdface/lattice/ladder.py::ladder (_BONDS, L176-188), commit e733ff893a52b81addd27ef7e347f77273c0d129 + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: ladder, model: kondo} + +geometry: + dimension: 1 + lattice_vectors: + a1: [1.0] # StdFace: Llength (default a=1.0). No lattice_vector for the rung direction since it is non-periodic + sites: + - {label: A0_c, frac: [0.0]} # leg 0, itinerant electron + - {label: A0_s, frac: [0.0]} # leg 0, localized spin + - {label: A1_c, frac: [0.0]} # leg 1, itinerant electron + - {label: A1_s, frac: [0.0]} # leg 1, localized spin + +system: + finite: true + size: [16] # StdFace: L + boundary: + - {twist: {param: phase0}} # in degrees. Transcribed to internal phase[1] (phase[0] is always 0) + +model: + site_dof: + A0_c: {fermion: {orbitals: 1}} + A0_s: {spin: {param: 2S, scale: 0.5, default: 0.5}} + A1_c: {fermion: {orbitals: 1}} + A1_s: {spin: {param: 2S, scale: 0.5, default: 0.5}} + + bonds: + # Kondo coupling (leg order, itinerant is the 1st endpoint) + - {from: A0_c, to: A0_s, R: [0], type: J} + - {from: A1_c, to: A1_s, R: [0], type: J} + # --- t block (_c to _c, uc_i loop order, leg 0 -> leg 1) --- + - {from: A0_c, to: A0_c, R: [1], type: t1} + - {from: A0_c, to: A0_c, R: [2], type: "t1'"} + - {from: A0_c, to: A1_c, R: [0], type: t0} + - {from: A0_c, to: A1_c, R: [1], type: t2} + - {from: A0_c, to: A1_c, R: [-1], type: "t2'"} + - {from: A1_c, to: A1_c, R: [1], type: t1} + - {from: A1_c, to: A1_c, R: [2], type: "t1'"} + # --- V block (same physical bonds, same order) --- + - {from: A0_c, to: A0_c, R: [1], type: V1} + - {from: A0_c, to: A0_c, R: [2], type: "V1'"} + - {from: A0_c, to: A1_c, R: [0], type: V0} + - {from: A0_c, to: A1_c, R: [1], type: V2} + - {from: A0_c, to: A1_c, R: [-1], type: "V2'"} + - {from: A1_c, to: A1_c, R: [1], type: V1} + - {from: A1_c, to: A1_c, R: [2], type: "V1'"} + + couplings: + t0: {operator: "hop", value: {param: t0, scale: -1.0}} + t1: {operator: "hop", value: {param: t1, scale: -1.0}} + "t1'": {operator: "hop", value: {param: "t1'", scale: -1.0}} + t2: {operator: "hop", value: {param: t2, scale: -1.0}} + "t2'": {operator: "hop", value: {param: "t2'", scale: -1.0}} + V0: {operator: "density-density", value: {param: V0}} + V1: {operator: "density-density", value: {param: V1}} + "V1'": {operator: "density-density", value: {param: "V1'"}} + V2: {operator: "density-density", value: {param: V2}} + "V2'": {operator: "density-density", value: {param: "V2'"}} + J: {operator: "s_i . S_j", value: {param: J}} # +J s·S (1st endpoint = itinerant) + + onsite: + A0_c: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + A0_s: + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + A1_c: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + A1_s: + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} diff --git a/lattice_catalog/ladder/ladder_w2_spin.yaml b/lattice_catalog/ladder/ladder_w2_spin.yaml new file mode 100644 index 0000000..135d87d --- /dev/null +++ b/lattice_catalog/ladder/ladder_w2_spin.yaml @@ -0,0 +1,148 @@ +# StdFace ladder (W=2) / Spin model +# Corresponding stan.in input: model="Spin" / lattice="ladder" / W=2 / L=16 / J0=1.0 (rung) / J1=1.0 (leg) +# +# Unit cell = 1 rung (W sites; W=2 -> labels A0, A1 = leg 0, leg 1). +# ladder.py sets NsiteUC=W and then fixes StdI.W to 1 (ladder.py:80-81). +# Grounds for the rung (former W) direction being open: (1) the dW component of _BONDS is always 0 +# (a cell-direction offset that crosses legs is never generated), (2) rung/diagonal +# bonds are only generated under the condition `if uc_i < NsiteUC - 1:` (ladder.py:184), +# so no bond is generated that "closes" from the last leg (uc_i=W-1) back to the first leg (uc_i=0). +# Hence this catalog is represented as logically one-dimensional (periodic boundary only along L). +# phase0 is transcribed into the internal phase[1] (ladder.py:75-78: `StdI.phase[1] = StdI.phase[0]; StdI.phase[0] = 0.0`). +# This is the same style of internal transcription as chain (CONVENTIONS.md §4), and it carries the boundary phase along L. +# +# W generalization rule (manually unrolling the dynamic loop of ladder.py:176-188): +# for uc_i in range(W): +# leg (within the same leg): A{uc_i}-A{uc_i} R=[1] J1, R=[2] J1' +# if uc_i < W-1: +# rung (intra-cell): A{uc_i}-A{uc_i+1} R=[0] J0 +# diag (L+1): A{uc_i}-A{uc_i+1} R=[1] J2 +# diag (L-1): A{uc_i}-A{uc_i+1} R=[-1] J2' +# An edge leg (uc_i=0 or W-1) has rung/diag on only one side. For W=2 both legs are +# edge legs, so the coordination number is symmetric (for W=3, only the middle leg A1 has rung/diag on both sides). +# Consistency check (W=2): coordination number 2 along the leg direction (J1), coordination number 1 for the rung (J0) (both legs are edges). +# See the ladder/ladder_w2_spin.yaml entry of manifest.yaml for the consistency check. +# Source: python/stdface/lattice/ladder.py::ladder (_BONDS, L176-188), commit e733ff893a52b81addd27ef7e347f77273c0d129 + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: ladder, model: spin} + +geometry: + dimension: 1 + lattice_vectors: + a1: [1.0] # StdFace: Llength (default a=1.0). No lattice_vector for the rung direction since it is non-periodic + sites: + - {label: A0, frac: [0.0]} # leg 0 (edge) + - {label: A1, frac: [0.0]} # leg 1 (edge) + +system: + finite: true + size: [16] # StdFace: L + boundary: + - {twist: {param: phase0}} # in degrees. Transcribed to internal phase[1] (phase[0] is always 0) + +model: + site_dof: + A0: {spin: {param: 2S, scale: 0.5, default: 0.5}} # S = 0.5 × 2S. Default S=1/2 + A1: {spin: {param: 2S, scale: 0.5, default: 0.5}} + + bonds: + # Preserves the source order of the reference implementation (_BONDS): uc_i=0 block -> uc_i=1 block + - {from: A0, to: A0, R: [1], type: J1} # leg nearest neighbor (uc_i=0) + - {from: A0, to: A0, R: [2], type: "J1'"} # leg next-nearest neighbor (uc_i=0) + - {from: A0, to: A1, R: [0], type: J0} # rung, intra-cell (uc_i=0 < W-1) + - {from: A0, to: A1, R: [1], type: J2} # diag L+1 (uc_i=0 < W-1) + - {from: A0, to: A1, R: [-1], type: "J2'"} # diag L-1 (uc_i=0 < W-1) + - {from: A1, to: A1, R: [1], type: J1} # leg nearest neighbor (uc_i=1) + - {from: A1, to: A1, R: [2], type: "J1'"} # leg next-nearest neighbor (uc_i=1) + # uc_i=1 = W-1, so rung/diag is cut off (edge leg) + + couplings: + # J family is in canonical 9-component form. Parameter resolution: component > scalar diagonal > global alias > 0 + J0: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J0x}} + - {ops: [Sy, Sy], coeff: {param: J0y}} + - {ops: [Sz, Sz], coeff: {param: J0z}} + - {ops: [Sx, Sy], coeff: {param: J0xy}} + - {ops: [Sx, Sz], coeff: {param: J0xz}} + - {ops: [Sy, Sx], coeff: {param: J0yx}} + - {ops: [Sy, Sz], coeff: {param: J0yz}} + - {ops: [Sz, Sx], coeff: {param: J0zx}} + - {ops: [Sz, Sy], coeff: {param: J0zy}} + J1: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J1x}} + - {ops: [Sy, Sy], coeff: {param: J1y}} + - {ops: [Sz, Sz], coeff: {param: J1z}} + - {ops: [Sx, Sy], coeff: {param: J1xy}} + - {ops: [Sx, Sz], coeff: {param: J1xz}} + - {ops: [Sy, Sx], coeff: {param: J1yx}} + - {ops: [Sy, Sz], coeff: {param: J1yz}} + - {ops: [Sz, Sx], coeff: {param: J1zx}} + - {ops: [Sz, Sy], coeff: {param: J1zy}} + "J1'": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J1'x"}} + - {ops: [Sy, Sy], coeff: {param: "J1'y"}} + - {ops: [Sz, Sz], coeff: {param: "J1'z"}} + - {ops: [Sx, Sy], coeff: {param: "J1'xy"}} + - {ops: [Sx, Sz], coeff: {param: "J1'xz"}} + - {ops: [Sy, Sx], coeff: {param: "J1'yx"}} + - {ops: [Sy, Sz], coeff: {param: "J1'yz"}} + - {ops: [Sz, Sx], coeff: {param: "J1'zx"}} + - {ops: [Sz, Sy], coeff: {param: "J1'zy"}} + J2: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J2x}} + - {ops: [Sy, Sy], coeff: {param: J2y}} + - {ops: [Sz, Sz], coeff: {param: J2z}} + - {ops: [Sx, Sy], coeff: {param: J2xy}} + - {ops: [Sx, Sz], coeff: {param: J2xz}} + - {ops: [Sy, Sx], coeff: {param: J2yx}} + - {ops: [Sy, Sz], coeff: {param: J2yz}} + - {ops: [Sz, Sx], coeff: {param: J2zx}} + - {ops: [Sz, Sy], coeff: {param: J2zy}} + "J2'": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J2'x"}} + - {ops: [Sy, Sy], coeff: {param: "J2'y"}} + - {ops: [Sz, Sz], coeff: {param: "J2'z"}} + - {ops: [Sx, Sy], coeff: {param: "J2'xy"}} + - {ops: [Sx, Sz], coeff: {param: "J2'xz"}} + - {ops: [Sy, Sx], coeff: {param: "J2'yx"}} + - {ops: [Sy, Sz], coeff: {param: "J2'yz"}} + - {ops: [Sz, Sx], coeff: {param: "J2'zx"}} + - {ops: [Sz, Sy], coeff: {param: "J2'zy"}} + + onsite: + A0: + field_z: # -h Sz + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: # -Gamma Sx + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: # -Gamma_y Sy + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + aniso_z: # D (Sz)^2 + operator: {tensor_terms: [{ops: [Szz], coeff: 1.0}]} + value: {param: D} + A1: + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + aniso_z: + operator: {tensor_terms: [{ops: [Szz], coeff: 1.0}]} + value: {param: D} diff --git a/lattice_catalog/ladder/ladder_w3_hubbard.yaml b/lattice_catalog/ladder/ladder_w3_hubbard.yaml new file mode 100644 index 0000000..631590b --- /dev/null +++ b/lattice_catalog/ladder/ladder_w3_hubbard.yaml @@ -0,0 +1,140 @@ +# StdFace ladder (W=3) / Hubbard model +# Corresponding stan.in input: model="Hubbard" / lattice="ladder" / W=3 / L=16 / t0=1.0 (rung) / t1=1.0 (leg) / U=4.0 +# +# Unit cell = 1 rung (W sites; W=3 -> labels A0, A1, A2 = leg 0, 1, 2). +# ladder.py sets NsiteUC=W and then fixes StdI.W to 1 (ladder.py:80-81). +# Grounds for the rung (former W) direction being open: (1) the dW component of _BONDS is always 0, +# (2) rung/diagonal bonds are only generated under the condition `if uc_i < NsiteUC - 1:` +# (ladder.py:184), so no bond is generated that "closes" from the last leg (uc_i=W-1=2) back to +# the first leg. Hence this catalog is logically one-dimensional (periodic boundary only along L). +# phase0 is transcribed into the internal phase[1] (ladder.py:75-78). Same style as chain +# (CONVENTIONS.md §4). Signs are carried as data in scale/coeff (same §6). +# +# W generalization rule (manually unrolling the dynamic loop of ladder.py:176-188; read J -> t/V): +# for uc_i in range(W): +# leg: A{uc_i}-A{uc_i} R=[1] t1/V1, R=[2] t1'/V1' +# if uc_i < W-1: +# rung (intra-cell): A{uc_i}-A{uc_i+1} R=[0] t0/V0 +# diag (L+1): A{uc_i}-A{uc_i+1} R=[1] t2/V2 +# diag (L-1): A{uc_i}-A{uc_i+1} R=[-1] t2'/V2' +# t/V originate from the same physical bond tuple, so following the same presentation +# convention as chain/square, the t block is listed first, followed by the V block +# (within each block the uc_i=0->1->2 order is preserved). +# Consistency check (middle leg A1 vs. edge legs A0/A2): for W=3, only the middle leg A1 has +# rung/diag (t0, t2, t2', V0, V2, V2') on both sides, so its coordination number is twice +# that of the edge legs (2 bonds vs. 1). Along the leg direction (t1, t1') all legs have coordination number 2. +# See the ladder/ladder_w3_hubbard.yaml entry of manifest.yaml for the consistency check. +# Source: python/stdface/lattice/ladder.py::ladder (_BONDS, L176-188), commit e733ff893a52b81addd27ef7e347f77273c0d129 + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: ladder, model: hubbard} + +geometry: + dimension: 1 + lattice_vectors: + a1: [1.0] # StdFace: Llength (default a=1.0). No lattice_vector for the rung direction since it is non-periodic + sites: + - {label: A0, frac: [0.0]} # leg 0 (edge) + - {label: A1, frac: [0.0]} # leg 1 (middle) + - {label: A2, frac: [0.0]} # leg 2 (edge) + +system: + finite: true + size: [16] # StdFace: L + boundary: + - {twist: {param: phase0}} # in degrees. Transcribed to internal phase[1] (phase[0] is always 0) + +model: + site_dof: + A0: {fermion: {orbitals: 1}} # extended dialect (CONVENTIONS §7) + A1: {fermion: {orbitals: 1}} + A2: {fermion: {orbitals: 1}} + + bonds: + # --- t block (uc_i=0 -> 1 -> 2 order) --- + - {from: A0, to: A0, R: [1], type: t1} + - {from: A0, to: A0, R: [2], type: "t1'"} + - {from: A0, to: A1, R: [0], type: t0} + - {from: A0, to: A1, R: [1], type: t2} + - {from: A0, to: A1, R: [-1], type: "t2'"} + - {from: A1, to: A1, R: [1], type: t1} + - {from: A1, to: A1, R: [2], type: "t1'"} + - {from: A1, to: A2, R: [0], type: t0} + - {from: A1, to: A2, R: [1], type: t2} + - {from: A1, to: A2, R: [-1], type: "t2'"} + - {from: A2, to: A2, R: [1], type: t1} + - {from: A2, to: A2, R: [2], type: "t1'"} + # --- V block (same physical bonds, same order) --- + - {from: A0, to: A0, R: [1], type: V1} + - {from: A0, to: A0, R: [2], type: "V1'"} + - {from: A0, to: A1, R: [0], type: V0} + - {from: A0, to: A1, R: [1], type: V2} + - {from: A0, to: A1, R: [-1], type: "V2'"} + - {from: A1, to: A1, R: [1], type: V1} + - {from: A1, to: A1, R: [2], type: "V1'"} + - {from: A1, to: A2, R: [0], type: V0} + - {from: A1, to: A2, R: [1], type: V2} + - {from: A1, to: A2, R: [-1], type: "V2'"} + - {from: A2, to: A2, R: [1], type: V1} + - {from: A2, to: A2, R: [2], type: "V1'"} + + couplings: + t0: {operator: "hop", value: {param: t0, scale: -1.0}} # -t Σσ(c†c+h.c.) + t1: {operator: "hop", value: {param: t1, scale: -1.0}} + "t1'": {operator: "hop", value: {param: "t1'", scale: -1.0}} + t2: {operator: "hop", value: {param: t2, scale: -1.0}} + "t2'": {operator: "hop", value: {param: "t2'", scale: -1.0}} + V0: {operator: "density-density", value: {param: V0}} # +V n_i n_j + V1: {operator: "density-density", value: {param: V1}} + "V1'": {operator: "density-density", value: {param: "V1'"}} + V2: {operator: "density-density", value: {param: V2}} + "V2'": {operator: "density-density", value: {param: "V2'"}} + + onsite: + A0: + hubbard_u: # +U n↑n↓ + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: # -mu N + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: # -h Sz (electron spin) + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + A1: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + A2: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} diff --git a/lattice_catalog/ladder/ladder_w3_kondo.yaml b/lattice_catalog/ladder/ladder_w3_kondo.yaml new file mode 100644 index 0000000..e1d6df3 --- /dev/null +++ b/lattice_catalog/ladder/ladder_w3_kondo.yaml @@ -0,0 +1,188 @@ +# StdFace ladder (W=3) / Kondo lattice model +# Corresponding stan.in input: model="Kondo" / lattice="ladder" / W=3 / L=16 / t0=1.0 / t1=1.0 / J=1.0 +# The field (h/Gamma/Gamma_y) is applied to both the itinerant electrons and the localized spins +# (python/stdface/core/model_plugin.py::KondoModel). +# The correspondence with the current implementation's site doubling (first half = localized S2, second half = itinerant) is described in manual Section 4. +# The Kondo J coupling is 1 bond per leg, A{i}_c -> A{i}_s (itinerant is the 1st endpoint). +# +# Unit cell = 1 rung (W sites; W=3 -> leg 0, 1, 2). Each leg is doubled by Kondo into +# 2 labels: _c (itinerant electron) / _s (localized spin). +# ladder.py sets NsiteUC=W and then fixes StdI.W to 1 (ladder.py:80-81). +# Grounds for the rung (former W) direction being open: (1) the dW component of _BONDS is always 0, +# (2) rung/diagonal bonds are only generated under the condition `if uc_i < NsiteUC - 1:` +# (ladder.py:184), so no bond is generated that "closes" from the last leg (uc_i=W-1=2) back to +# the first leg. Hence this catalog is logically one-dimensional (periodic boundary only along L). +# phase0 is transcribed into the internal phase[1] (ladder.py:75-78). Same style as chain +# (CONVENTIONS.md §4). +# +# W generalization rule (t/V are the manually-unrolled dynamic loop of ladder.py:176-188, read J -> t/V. +# The Kondo J is generated per leg uc_i as 1 bond A{uc_i}_c-A{uc_i}_s R=[0], in leg order +# — following expand_bonds_2d's intra-cell loop order: the local terms (including Kondo J) are +# added first for all legs, and only afterward are the t/V bonds of _BONDS added): +# for uc_i in range(W): J: A{uc_i}_c-A{uc_i}_s R=[0] <- local-term loop (first) +# for uc_i in range(W): <- _BONDS loop (after) +# leg: A{uc_i}_c-A{uc_i}_c R=[1] t1/V1, R=[2] t1'/V1' +# if uc_i < W-1: +# rung (intra-cell): A{uc_i}_c-A{uc_i+1}_c R=[0] t0/V0 +# diag (L+1): A{uc_i}_c-A{uc_i+1}_c R=[1] t2/V2 +# diag (L-1): A{uc_i}_c-A{uc_i+1}_c R=[-1] t2'/V2' +# Consistency check (middle leg A1_c vs. edge legs A0_c/A2_c): for W=3, only the middle leg has +# rung/diag (t0, t2, t2', V0, V2, V2') on both sides, so its coordination number is twice +# that of the edge legs (2 bonds vs. 1). Along the leg direction (t1, t1') all legs have coordination number 2. +# The Kondo J coordination number is 1 for each site (both _c and _s), regardless of leg position. +# See the ladder/ladder_w3_kondo.yaml entry of manifest.yaml for the consistency check. +# Source: python/stdface/lattice/ladder.py::ladder (_BONDS, L176-188), commit e733ff893a52b81addd27ef7e347f77273c0d129 + +catalog: {schema: stdface-catalog/0.1, dialect: experimental, lattice: ladder, model: kondo} + +geometry: + dimension: 1 + lattice_vectors: + a1: [1.0] # StdFace: Llength (default a=1.0). No lattice_vector for the rung direction since it is non-periodic + sites: + - {label: A0_c, frac: [0.0]} # leg 0 (edge), itinerant electron + - {label: A0_s, frac: [0.0]} # leg 0 (edge), localized spin + - {label: A1_c, frac: [0.0]} # leg 1 (middle), itinerant electron + - {label: A1_s, frac: [0.0]} # leg 1 (middle), localized spin + - {label: A2_c, frac: [0.0]} # leg 2 (edge), itinerant electron + - {label: A2_s, frac: [0.0]} # leg 2 (edge), localized spin + +system: + finite: true + size: [16] # StdFace: L + boundary: + - {twist: {param: phase0}} # in degrees. Transcribed to internal phase[1] (phase[0] is always 0) + +model: + site_dof: + A0_c: {fermion: {orbitals: 1}} + A0_s: {spin: {param: 2S, scale: 0.5, default: 0.5}} + A1_c: {fermion: {orbitals: 1}} + A1_s: {spin: {param: 2S, scale: 0.5, default: 0.5}} + A2_c: {fermion: {orbitals: 1}} + A2_s: {spin: {param: 2S, scale: 0.5, default: 0.5}} + + bonds: + # Kondo coupling (leg order, itinerant is the 1st endpoint) + - {from: A0_c, to: A0_s, R: [0], type: J} + - {from: A1_c, to: A1_s, R: [0], type: J} + - {from: A2_c, to: A2_s, R: [0], type: J} + # --- t block (_c to _c, uc_i=0 -> 1 -> 2 order) --- + - {from: A0_c, to: A0_c, R: [1], type: t1} + - {from: A0_c, to: A0_c, R: [2], type: "t1'"} + - {from: A0_c, to: A1_c, R: [0], type: t0} + - {from: A0_c, to: A1_c, R: [1], type: t2} + - {from: A0_c, to: A1_c, R: [-1], type: "t2'"} + - {from: A1_c, to: A1_c, R: [1], type: t1} + - {from: A1_c, to: A1_c, R: [2], type: "t1'"} + - {from: A1_c, to: A2_c, R: [0], type: t0} + - {from: A1_c, to: A2_c, R: [1], type: t2} + - {from: A1_c, to: A2_c, R: [-1], type: "t2'"} + - {from: A2_c, to: A2_c, R: [1], type: t1} + - {from: A2_c, to: A2_c, R: [2], type: "t1'"} + # --- V block (same physical bonds, same order) --- + - {from: A0_c, to: A0_c, R: [1], type: V1} + - {from: A0_c, to: A0_c, R: [2], type: "V1'"} + - {from: A0_c, to: A1_c, R: [0], type: V0} + - {from: A0_c, to: A1_c, R: [1], type: V2} + - {from: A0_c, to: A1_c, R: [-1], type: "V2'"} + - {from: A1_c, to: A1_c, R: [1], type: V1} + - {from: A1_c, to: A1_c, R: [2], type: "V1'"} + - {from: A1_c, to: A2_c, R: [0], type: V0} + - {from: A1_c, to: A2_c, R: [1], type: V2} + - {from: A1_c, to: A2_c, R: [-1], type: "V2'"} + - {from: A2_c, to: A2_c, R: [1], type: V1} + - {from: A2_c, to: A2_c, R: [2], type: "V1'"} + + couplings: + t0: {operator: "hop", value: {param: t0, scale: -1.0}} + t1: {operator: "hop", value: {param: t1, scale: -1.0}} + "t1'": {operator: "hop", value: {param: "t1'", scale: -1.0}} + t2: {operator: "hop", value: {param: t2, scale: -1.0}} + "t2'": {operator: "hop", value: {param: "t2'", scale: -1.0}} + V0: {operator: "density-density", value: {param: V0}} + V1: {operator: "density-density", value: {param: V1}} + "V1'": {operator: "density-density", value: {param: "V1'"}} + V2: {operator: "density-density", value: {param: V2}} + "V2'": {operator: "density-density", value: {param: "V2'"}} + J: {operator: "s_i . S_j", value: {param: J}} # +J s·S (1st endpoint = itinerant) + + onsite: + A0_c: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + A0_s: + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + A1_c: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + A1_s: + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + A2_c: + hubbard_u: + operator: {tensor_terms: [{ops: [NupNdn], coeff: 1.0}]} + value: {param: U} + chemical_potential: + operator: {tensor_terms: [{ops: [N], coeff: -1.0}]} + value: {param: mu} + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + A2_s: + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} diff --git a/lattice_catalog/ladder/ladder_w3_spin.yaml b/lattice_catalog/ladder/ladder_w3_spin.yaml new file mode 100644 index 0000000..1b5a652 --- /dev/null +++ b/lattice_catalog/ladder/ladder_w3_spin.yaml @@ -0,0 +1,171 @@ +# StdFace ladder (W=3) / Spin model +# Corresponding stan.in input: model="Spin" / lattice="ladder" / W=3 / L=16 / J0=1.0 (rung) / J1=1.0 (leg) +# +# Unit cell = 1 rung (W sites; W=3 -> labels A0, A1, A2 = leg 0, 1, 2). +# ladder.py sets NsiteUC=W and then fixes StdI.W to 1 (ladder.py:80-81). +# Grounds for the rung (former W) direction being open: (1) the dW component of _BONDS is always 0 +# (a cell-direction offset that crosses legs is never generated), (2) rung/diagonal +# bonds are only generated under the condition `if uc_i < NsiteUC - 1:` (ladder.py:184), +# so no bond is generated that "closes" from the last leg (uc_i=W-1=2) back to the first leg (uc_i=0). +# Hence this catalog is represented as logically one-dimensional (periodic boundary only along L). +# phase0 is transcribed into the internal phase[1] (ladder.py:75-78). Same style as chain +# (CONVENTIONS.md §4). +# +# W generalization rule (manually unrolling the dynamic loop of ladder.py:176-188): +# for uc_i in range(W): +# leg (within the same leg): A{uc_i}-A{uc_i} R=[1] J1, R=[2] J1' +# if uc_i < W-1: +# rung (intra-cell): A{uc_i}-A{uc_i+1} R=[0] J0 +# diag (diagonal, L+1): A{uc_i}-A{uc_i+1} R=[1] J2 +# diag (diagonal, L-1): A{uc_i}-A{uc_i+1} R=[-1] J2' +# W=3: unrolling uc_i=0,1,2, only uc_i=1 (the middle leg, A1) has rung/diag on both +# sides (the uc_i=0 side and the uc_i=1 uc_i=1 -> uc_i=2 + - {from: A0, to: A0, R: [1], type: J1} # leg nearest neighbor (uc_i=0) + - {from: A0, to: A0, R: [2], type: "J1'"} # leg next-nearest neighbor (uc_i=0) + - {from: A0, to: A1, R: [0], type: J0} # rung, intra-cell (uc_i=0 < W-1) + - {from: A0, to: A1, R: [1], type: J2} # diag L+1 (uc_i=0 < W-1) + - {from: A0, to: A1, R: [-1], type: "J2'"} # diag L-1 (uc_i=0 < W-1) + - {from: A1, to: A1, R: [1], type: J1} # leg nearest neighbor (uc_i=1) + - {from: A1, to: A1, R: [2], type: "J1'"} # leg next-nearest neighbor (uc_i=1) + - {from: A1, to: A2, R: [0], type: J0} # rung, intra-cell (uc_i=1 < W-1) + - {from: A1, to: A2, R: [1], type: J2} # diag L+1 (uc_i=1 < W-1) + - {from: A1, to: A2, R: [-1], type: "J2'"} # diag L-1 (uc_i=1 < W-1) + - {from: A2, to: A2, R: [1], type: J1} # leg nearest neighbor (uc_i=2) + - {from: A2, to: A2, R: [2], type: "J1'"} # leg next-nearest neighbor (uc_i=2) + # uc_i=2 = W-1, so rung/diag is cut off (edge leg) + + couplings: + # J family is in canonical 9-component form. Parameter resolution: component > scalar diagonal > global alias > 0 + J0: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J0x}} + - {ops: [Sy, Sy], coeff: {param: J0y}} + - {ops: [Sz, Sz], coeff: {param: J0z}} + - {ops: [Sx, Sy], coeff: {param: J0xy}} + - {ops: [Sx, Sz], coeff: {param: J0xz}} + - {ops: [Sy, Sx], coeff: {param: J0yx}} + - {ops: [Sy, Sz], coeff: {param: J0yz}} + - {ops: [Sz, Sx], coeff: {param: J0zx}} + - {ops: [Sz, Sy], coeff: {param: J0zy}} + J1: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J1x}} + - {ops: [Sy, Sy], coeff: {param: J1y}} + - {ops: [Sz, Sz], coeff: {param: J1z}} + - {ops: [Sx, Sy], coeff: {param: J1xy}} + - {ops: [Sx, Sz], coeff: {param: J1xz}} + - {ops: [Sy, Sx], coeff: {param: J1yx}} + - {ops: [Sy, Sz], coeff: {param: J1yz}} + - {ops: [Sz, Sx], coeff: {param: J1zx}} + - {ops: [Sz, Sy], coeff: {param: J1zy}} + "J1'": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J1'x"}} + - {ops: [Sy, Sy], coeff: {param: "J1'y"}} + - {ops: [Sz, Sz], coeff: {param: "J1'z"}} + - {ops: [Sx, Sy], coeff: {param: "J1'xy"}} + - {ops: [Sx, Sz], coeff: {param: "J1'xz"}} + - {ops: [Sy, Sx], coeff: {param: "J1'yx"}} + - {ops: [Sy, Sz], coeff: {param: "J1'yz"}} + - {ops: [Sz, Sx], coeff: {param: "J1'zx"}} + - {ops: [Sz, Sy], coeff: {param: "J1'zy"}} + J2: + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: J2x}} + - {ops: [Sy, Sy], coeff: {param: J2y}} + - {ops: [Sz, Sz], coeff: {param: J2z}} + - {ops: [Sx, Sy], coeff: {param: J2xy}} + - {ops: [Sx, Sz], coeff: {param: J2xz}} + - {ops: [Sy, Sx], coeff: {param: J2yx}} + - {ops: [Sy, Sz], coeff: {param: J2yz}} + - {ops: [Sz, Sx], coeff: {param: J2zx}} + - {ops: [Sz, Sy], coeff: {param: J2zy}} + "J2'": + operator: + tensor_terms: + - {ops: [Sx, Sx], coeff: {param: "J2'x"}} + - {ops: [Sy, Sy], coeff: {param: "J2'y"}} + - {ops: [Sz, Sz], coeff: {param: "J2'z"}} + - {ops: [Sx, Sy], coeff: {param: "J2'xy"}} + - {ops: [Sx, Sz], coeff: {param: "J2'xz"}} + - {ops: [Sy, Sx], coeff: {param: "J2'yx"}} + - {ops: [Sy, Sz], coeff: {param: "J2'yz"}} + - {ops: [Sz, Sx], coeff: {param: "J2'zx"}} + - {ops: [Sz, Sy], coeff: {param: "J2'zy"}} + + onsite: + A0: + field_z: # -h Sz + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: # -Gamma Sx + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: # -Gamma_y Sy + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + aniso_z: # D (Sz)^2 + operator: {tensor_terms: [{ops: [Szz], coeff: 1.0}]} + value: {param: D} + A1: + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + aniso_z: + operator: {tensor_terms: [{ops: [Szz], coeff: 1.0}]} + value: {param: D} + A2: + field_z: + operator: {tensor_terms: [{ops: [Sz], coeff: -1.0}]} + value: {param: h} + field_x: + operator: {tensor_terms: [{ops: [Sx], coeff: -1.0}]} + value: {param: Gamma} + field_y: + operator: {tensor_terms: [{ops: [Sy], coeff: -1.0}]} + value: {param: Gamma_y} + aniso_z: + operator: {tensor_terms: [{ops: [Szz], coeff: 1.0}]} + value: {param: D} diff --git a/lattice_catalog/manifest.yaml b/lattice_catalog/manifest.yaml new file mode 100644 index 0000000..2746c9c --- /dev/null +++ b/lattice_catalog/manifest.yaml @@ -0,0 +1,465 @@ +# lattice_catalog consistency-check ledger +# +# Each entry holds the expected values that the linter (tools/lint_catalog.py) +# cross-checks against the YAML body. All keys are mandatory (a missing key is a C10 error). +# +# files: +# : # e.g. chain/chain_spin.yaml +# lattice: +# model: +# dimension: +# n_sites_uc: +# bonds_per_uc: {: , ...} +# # List every bond type (omission is not allowed). +# coordination: +# # Coordination number per site label × bond type. +# # Measured by counting expansion on the min_size_for_check torus +# # and compared against the value here (expand_and_count in tools/lint_catalog.py). +#