Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
966ef73
Create pyproject.toml
ZhouXY-PKU Apr 4, 2026
fe8f93f
Add ABACUS Wannier90 interface module
ZhouXY-PKU Apr 4, 2026
c02f916
Create runner.py
ZhouXY-PKU Apr 4, 2026
b43bd78
Create io_utils.py
ZhouXY-PKU Apr 4, 2026
cfc2e55
Add ABACUSWannier90 interface class
ZhouXY-PKU Apr 4, 2026
e80d40b
Create README.md
ZhouXY-PKU Apr 4, 2026
81a7b6e
Create example_basic.py
ZhouXY-PKU Apr 5, 2026
ef9c9ef
Create example_advanced.py
ZhouXY-PKU Apr 5, 2026
f6db979
Add README for ABACUS Wannier90 Interface
ZhouXY-PKU Apr 5, 2026
e5684db
Update example_basic.py
ZhouXY-PKU Apr 6, 2026
0e340b8
Revise example script documentation and parameters
ZhouXY-PKU Apr 6, 2026
2f5b08f
Create example_pw.py
ZhouXY-PKU Apr 6, 2026
261689d
Add example script for LCAO Gamma-only in ABACUS
ZhouXY-PKU Apr 6, 2026
79144d7
Merge branch 'develop' into ZhouXY-PKU-Wannier90
ZhouXY-PKU Apr 17, 2026
81a1955
Update io_utils.py
ZhouXY-PKU Apr 17, 2026
b529bbe
Update pyproject.toml
ZhouXY-PKU Apr 21, 2026
8693080
Update pyproject.toml
ZhouXY-PKU Apr 21, 2026
ddf25d4
Update example_advanced.py
ZhouXY-PKU Apr 21, 2026
24c2712
Update example_basic.py
ZhouXY-PKU Apr 21, 2026
7955048
Update example_pw.py
ZhouXY-PKU Apr 21, 2026
ad59f5e
Update and rename example_lcao_gamma.py to unsupported_lcao_gamma
ZhouXY-PKU Apr 21, 2026
165f11a
Update README.md
ZhouXY-PKU Apr 21, 2026
e528014
Update README.md
ZhouXY-PKU Apr 21, 2026
12679d9
Refactor comments and formatting in interface.py
ZhouXY-PKU Apr 21, 2026
e5cc9ce
Update io_utils.py
ZhouXY-PKU Apr 21, 2026
82bbb31
Update runner.py
ZhouXY-PKU Apr 21, 2026
0731077
Add files via upload
ZhouXY-PKU Apr 21, 2026
3d0c404
Delete interfaces/Wannier90_interface/examples/unsupported_lcao_gamma
ZhouXY-PKU Apr 21, 2026
3f1c387
Rename Bi.orb to Bi.orb
ZhouXY-PKU Apr 22, 2026
bcfffca
Rename Bi.upf to Bi.upf
ZhouXY-PKU Apr 22, 2026
ccad698
Add Se.orb example for Python interface
ZhouXY-PKU Apr 22, 2026
bc47e70
refactor: move dirs.
ZhouXY-PKU Apr 22, 2026
c23c9d0
refactor: move dirs.
ZhouXY-PKU Apr 23, 2026
03212d0
Modify path and add a CI/CD workflow.
ZhouXY-PKU Apr 24, 2026
c0e6acd
Update interface.yml
ZhouXY-PKU Apr 24, 2026
f973178
refactor: move files.
ZhouXY-PKU Apr 24, 2026
61eb1d8
Merge branch 'ZhouXY-PKU-Wannier90' of https://github.com/deepmodelin…
ZhouXY-PKU Apr 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
293 changes: 293 additions & 0 deletions .github/workflows/interface.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
name: interface

on:
workflow_dispatch:

jobs:
wannier-interface:
name: "wannier interface — ${{ matrix.name }}"
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- name: basic (LCAO)
script: example_basic.py
prefix: Bi2Se3_basic
basis: lcao
- name: pw (Plane Wave)
script: example_pw.py
prefix: Bi2Se3_pw
basis: pw
- name: advance (LCAO)
script: example_advance.py
prefix: Bi2Se3_advanced
basis: lcao

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"

- name: Install abacusw90
run: |
python -m pip install --upgrade pip
pip install -e .

- name: Confirm no wannier90.x in environment
run: |
if command -v wannier90.x 2>/dev/null; then
echo "::error::wannier90.x found — CI must test WITHOUT external binaries"
exit 1
fi
echo "OK: no wannier90.x (dryrun mode)"

# ================================================================
# Shared mock + patch
# NOTE: env: MUST be a sibling of run: (same indent level).
# run: uses block scalar literal (|) so the heredoc inside
# is passed to bash with YAML indentation stripped.
# ================================================================
- name: Create mock data & patch script
env:
SCRIPT: ${{ matrix.script }}
PREFIX: ${{ matrix.prefix }}
run: |
python3 << 'PYEOF'
import os, re, textwrap

script = os.environ["SCRIPT"]
prefix = os.environ["PREFIX"]

# ── 1. Patch the example script ────────────────────────
with open(script) as f:
src = f.read()

src = src.replace("DRY_RUN = False", "DRY_RUN = True")

src = re.sub(
r"\s*job\.step0_run_scf\([^)]*\)",
" # [CI:skip] step0_run_scf — no ABACUS in this environment",
src,
flags=re.DOTALL,
)

src = src.replace(
"job.step1_generate_wannier_win()",
"# [CI:skip] step1_generate_wannier_win — no wannier90.x in this environment",
)

with open(script, "w") as f:
f.write(src)
print(f"[patch] {script}")

# ── 2. Create work directories ─────────────────────────
for d in [f"{prefix}/scf", f"{prefix}/wannier"]:
os.makedirs(d, exist_ok=True)

# ── 3. Mock STRU (scf/ + wannier/) ────────────────────
stru = textwrap.dedent("""\
ATOMIC_SPECIES
Bi 208.980 Bi.upf
Se 78.960 Se.upf

LATTICE_CONSTANT
1.0

LATTICE_VECTORS
-2.069 -3.583614 0.0
2.069 -3.583614 0.0
0.000 2.389075 9.546667

ATOMIC_POSITIONS
Direct

Bi
0.399 0.399 0.697 1 1 1
0.601 0.601 0.303 1 1 1

Se
0.000 0.000 0.500 1 1 1
0.206 0.206 0.118 1 1 1
0.794 0.794 0.882 1 1 1
""")
for d in [f"{prefix}/scf", f"{prefix}/wannier"]:
p = os.path.join(d, "STRU")
with open(p, "w") as f:
f.write(stru)
print(f"[mock] {p}")

# ── 4. Mock wannier90.nnkp ────────────────────────────
nbands = 20
nk = 64 # 4 × 4 × 4
nntot = 14

lines = [
f" {nbands}", "! num_bands",
f" {nk}", "! num_kpts",
" 4 4 4", "! mp_grid",
]
for ix in range(4):
for iy in range(4):
for iz in range(4):
lines.append(f" {ix/4:.15f} {iy/4:.15f} {iz/4:.15f}")

lines.append(f" {nntot}")
lines.append("! nntot")
for ik in range(nk):
lines.append(f" {nntot}")
for ib in range(nntot):
lines.append(f" {(ik + ib) % nk + 1}")
lines.append(f" {nntot}")
for ib in range(nntot):
lines.append(" 0 0 0")

lines += [
f" {nbands}", "! num_exclude_bands",
" 30", "! num_wann",
" 6", "! num_proj",
]
for proj in ["Bi : pz","Bi : px","Bi : py",
"Se : pz","Se : px","Se : py"]:
lines.append(f" {proj}")

nnkp = os.path.join(prefix, "wannier", "wannier90.nnkp")
with open(nnkp, "w") as f:
f.write("\n".join(lines) + "\n")
print(f"[mock] {nnkp} ({len(lines)} lines)")

# ── 5. Mock PP & ORB files ─────────────────────────────
orb_dir = "tests/PP_ORB/for_interface/Wannier90_interface"
os.makedirs(orb_dir, exist_ok=True)
for name in ["Bi.upf", "Se.upf", "Bi.orb", "Se.orb"]:
p = os.path.join(orb_dir, name)
with open(p, "w") as f:
f.write("# mock for CI dryrun\n")
print(f"[mock] {p}")

print("\n[done] all mocks ready")
PYEOF

# ================================================================
# Run
# ================================================================
- name: Run ${{ matrix.script }} — dryrun
run: python ${{ matrix.script }} 2>&1 | tee run.log

# ================================================================
# Validate
# ================================================================
- name: Check dryrun completion banner
run: |
if grep -q "DRY RUN COMPLETE" run.log; then
echo " [OK] dryrun banner found"
else
echo " [FAIL] 'DRY RUN COMPLETE' not found — script may have crashed"
exit 1
fi

- name: Validate generated files (${{ matrix.name }})
run: |
W="${{ matrix.prefix }}/wannier"
ERR=0

check() {
if [ -f "$1" ]; then
echo " [OK] $1 ($(wc -c < "$1") bytes)"
else
echo " [FAIL] $1 (not found)"
ERR=1
fi
}

echo "=========================================="
echo " NSCF input files (from step2)"
echo "=========================================="
check "$W/INPUT"
check "$W/KPT"
check "$W/STRU"

if [ -f "$W/INPUT" ]; then
echo ""
echo "--- INPUT keyword checks ---"
for key in "calculation" "towannier90" "nspin"; do
if grep -qi "$key" "$W/INPUT"; then
echo " [OK] INPUT contains '$key'"
else
echo " [FAIL] INPUT missing '$key'"
ERR=1
fi
done
if grep -qi "gamma_only" "$W/INPUT"; then
echo " [FAIL] INPUT contains 'gamma_only' — forbidden!"
ERR=1
else
echo " [OK] INPUT does NOT contain 'gamma_only'"
fi
fi

echo ""
echo "--- Basis-specific checks (${{ matrix.basis }}) ---"
if [ "${{ matrix.basis }}" = "pw" ]; then
if grep -qi "orbital_file\|orbital_dir" "$W/INPUT"; then
echo " [FAIL] PW INPUT contains orbital_file/orbital_dir"
ERR=1
else
echo " [OK] PW INPUT does NOT contain orbital_file/orbital_dir"
fi
else
if grep -qi "orbital_file\|orbital_dir" "$W/INPUT"; then
echo " [OK] LCAO INPUT contains orbital_file/orbital_dir"
else
echo " [WARN] LCAO INPUT missing orbital references (may be in STRU)"
fi
fi

if [ -f "$W/KPT" ]; then
echo ""
klines=$(wc -l < "$W/KPT")
if [ "$klines" -gt 5 ]; then
echo " [OK] KPT has $klines lines (reasonable)"
else
echo " [FAIL] KPT too short ($klines lines)"
ERR=1
fi
fi

echo ""
if [ "$ERR" -ne 0 ]; then
echo "=========================================="
echo " VALIDATION FAILED"
echo "=========================================="
exit 1
fi
echo "=========================================="
echo " ALL CHECKS PASSED (${{ matrix.name }})"
echo "=========================================="

# ================================================================
# Debug (always runs, even on failure)
# ================================================================
- name: Show full script output
if: always()
run: cat run.log

- name: Show generated INPUT
if: always()
run: |
f="${{ matrix.prefix }}/wannier/INPUT"
if [ -f "$f" ]; then echo "=== $f ==="; cat "$f"; else echo "$f not found"; fi

- name: Show generated KPT (first 20 lines)
if: always()
run: |
f="${{ matrix.prefix }}/wannier/KPT"
if [ -f "$f" ]; then echo "=== $f (first 20 lines) ==="; head -20 "$f"; else echo "$f not found"; fi

- name: List all generated files
if: always()
run: find ${{ matrix.prefix }} -type f | sort
Loading
Loading