Skip to content

Commit 7649894

Browse files
authored
Merge branch 'deepmodeling:develop' into develop
2 parents 42417ad + 71f3524 commit 7649894

1,716 files changed

Lines changed: 52806 additions & 48864 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitattributes

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.gitattributes export-ignore
2+
.gitignore export-ignore
3+
.gitmodules export-ignore
4+
.pre-commit-config.yaml export-ignore
5+
.github/ export-ignore

.github/workflows/ase_plugin_test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
uses: actions/checkout@v6
1616

1717
- name: Set up Miniconda
18-
uses: conda-incubator/setup-miniconda@v3
18+
uses: conda-incubator/setup-miniconda@v4
1919
with:
2020
miniconda-version: 'latest'
2121
activate-environment: abacuslite

.github/workflows/doxygen.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ jobs:
4848
uses: actions/configure-pages@v6
4949

5050
- name: Upload artifact
51-
uses: actions/upload-pages-artifact@v4
51+
uses: actions/upload-pages-artifact@v5
5252
with:
5353
path: './doxygen/html'
5454

.github/workflows/interface.yml

Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
name: interface
2+
3+
on:
4+
workflow_dispatch:
5+
6+
jobs:
7+
wannier-interface:
8+
name: "wannier interface — ${{ matrix.name }}"
9+
runs-on: ubuntu-latest
10+
strategy:
11+
fail-fast: false
12+
matrix:
13+
include:
14+
- name: basic (LCAO)
15+
script: example_basic.py
16+
prefix: Bi2Se3_basic
17+
basis: lcao
18+
- name: pw (Plane Wave)
19+
script: example_pw.py
20+
prefix: Bi2Se3_pw
21+
basis: pw
22+
- name: advance (LCAO)
23+
script: example_advance.py
24+
prefix: Bi2Se3_advanced
25+
basis: lcao
26+
27+
defaults:
28+
run:
29+
working-directory: interfaces/Wannier90_interface/examples_python
30+
31+
steps:
32+
- name: Checkout repository
33+
uses: actions/checkout@v6
34+
35+
- name: Set up Python 3.10
36+
uses: actions/setup-python@v6
37+
with:
38+
python-version: "3.10"
39+
40+
- name: Install abacusw90
41+
run: |
42+
python -m pip install --upgrade pip
43+
pip install -e ..
44+
45+
- name: Confirm no wannier90.x in environment
46+
run: |
47+
if command -v wannier90.x 2>/dev/null; then
48+
echo "::error::wannier90.x found — CI must test WITHOUT external binaries"
49+
exit 1
50+
fi
51+
echo "OK: no wannier90.x (dryrun mode)"
52+
53+
- name: Create mock data & patch script
54+
env:
55+
SCRIPT: ${{ matrix.script }}
56+
PREFIX: ${{ matrix.prefix }}
57+
run: |
58+
python3 << 'PYEOF'
59+
import os, re, textwrap
60+
61+
script = os.environ["SCRIPT"]
62+
prefix = os.environ["PREFIX"]
63+
64+
# ── 1. Patch the example script ────────────────────────
65+
with open(script) as f:
66+
src = f.read()
67+
68+
src = src.replace("DRY_RUN = False", "DRY_RUN = True")
69+
70+
src = re.sub(
71+
r"\s*job\.step0_run_scf\([^)]*\)",
72+
" # [CI:skip] step0_run_scf — no ABACUS in this environment",
73+
src,
74+
flags=re.DOTALL,
75+
)
76+
77+
src = src.replace(
78+
"job.step1_generate_wannier_win()",
79+
"# [CI:skip] step1_generate_wannier_win — no wannier90.x in this environment",
80+
)
81+
82+
with open(script, "w") as f:
83+
f.write(src)
84+
print(f"[patch] {script}")
85+
86+
# ── 2. Create work directories ─────────────────────────
87+
for d in [f"{prefix}/scf", f"{prefix}/wannier"]:
88+
os.makedirs(d, exist_ok=True)
89+
90+
# ── 3. Mock STRU (scf/ + wannier/) ────────────────────
91+
if basis == "pw":
92+
atom_species = (
93+
"ATOMIC_SPECIES\n"
94+
"Bi 208.980 Bi_pbe_fr.upf\n"
95+
"Se 78.960 Bi_pbe_fr.upf\n"
96+
"\n"
97+
)
98+
else:
99+
atom_species = (
100+
"ATOMIC_SPECIES\n"
101+
"Bi 208.980 Bi_pbe_fr.upf Bi_gga_10au_100Ry_2s2p2d.orb\n"
102+
"Se 78.960 Bi_pbe_fr.upf Se_gga_10au_100Ry_2s2p2d.orb\n"
103+
"\n"
104+
)
105+
106+
lattice_block = textwrap.dedent("""\
107+
LATTICE_CONSTANT
108+
1.0
109+
110+
LATTICE_VECTORS
111+
-2.069 -3.583614 0.0
112+
2.069 -3.583614 0.0
113+
0.000 2.389075 9.546667
114+
115+
ATOMIC_POSITIONS
116+
Direct
117+
118+
Bi
119+
0.399 0.399 0.697 1 1 1
120+
0.601 0.601 0.303 1 1 1
121+
122+
Se
123+
0.000 0.000 0.500 1 1 1
124+
0.206 0.206 0.118 1 1 1
125+
0.794 0.794 0.882 1 1 1
126+
""")
127+
128+
stru = atom_species + lattice_block
129+
for d in [f"{prefix}/scf", f"{prefix}/wannier"]:
130+
p = os.path.join(d, "STRU")
131+
with open(p, "w") as f:
132+
f.write(stru)
133+
print(f"[mock] {p}")
134+
135+
# ── 4. Mock wannier90.nnkp ────────────────────────────
136+
nbands = 20
137+
nk = 64 # 4 × 4 × 4
138+
nntot = 14
139+
140+
lines = [
141+
f" {nbands}", "! num_bands",
142+
f" {nk}", "! num_kpts",
143+
" 4 4 4", "! mp_grid",
144+
]
145+
for ix in range(4):
146+
for iy in range(4):
147+
for iz in range(4):
148+
lines.append(f" {ix/4:.15f} {iy/4:.15f} {iz/4:.15f}")
149+
150+
lines.append(f" {nntot}")
151+
lines.append("! nntot")
152+
for ik in range(nk):
153+
lines.append(f" {nntot}")
154+
for ib in range(nntot):
155+
lines.append(f" {(ik + ib) % nk + 1}")
156+
lines.append(f" {nntot}")
157+
for ib in range(nntot):
158+
lines.append(" 0 0 0")
159+
160+
lines += [
161+
f" {nbands}", "! num_exclude_bands",
162+
" 30", "! num_wann",
163+
" 6", "! num_proj",
164+
]
165+
for proj in ["Bi : pz","Bi : px","Bi : py",
166+
"Se : pz","Se : px","Se : py"]:
167+
lines.append(f" {proj}")
168+
169+
nnkp = os.path.join(prefix, "wannier", "wannier90.nnkp")
170+
with open(nnkp, "w") as f:
171+
f.write("\n".join(lines) + "\n")
172+
print(f"[mock] {nnkp} ({len(lines)} lines)")
173+
174+
# ── 5. Mock PP & ORB files ─────────────────────────────
175+
orb_dir = os.path.abspath("../../../tests/PP_ORB/")
176+
os.makedirs(orb_dir, exist_ok=True)
177+
for name in ["Bi_pbe_fr.upf", "Se_pbe_fr.upf", "Bi_gga_10au_100Ry_2s2p2d.orb", "Se_gga_10au_100Ry_2s2p2d.orb"]:
178+
p = os.path.join(orb_dir, name)
179+
with open(p, "w") as f:
180+
f.write("# mock for CI dryrun\n")
181+
print(f"[mock] {p}")
182+
183+
print("\n[done] all mocks ready")
184+
PYEOF
185+
186+
- name: Run ${{ matrix.script }} — dryrun
187+
run: python ${{ matrix.script }} 2>&1 | tee run.log
188+
189+
- name: Check dryrun completion banner
190+
run: |
191+
if grep -q "DRY RUN COMPLETE" run.log; then
192+
echo " [OK] dryrun banner found"
193+
else
194+
echo " [FAIL] 'DRY RUN COMPLETE' not found — script may have crashed"
195+
exit 1
196+
fi
197+
198+
- name: Validate generated files (${{ matrix.name }})
199+
run: |
200+
W="${{ matrix.prefix }}/wannier"
201+
ERR=0
202+
203+
check() {
204+
if [ -f "$1" ]; then
205+
echo " [OK] $1 ($(wc -c < "$1") bytes)"
206+
else
207+
echo " [FAIL] $1 (not found)"
208+
ERR=1
209+
fi
210+
}
211+
212+
echo "=========================================="
213+
echo " NSCF input files (from step2)"
214+
echo "=========================================="
215+
check "$W/INPUT"
216+
check "$W/KPT"
217+
check "$W/STRU"
218+
219+
if [ -f "$W/INPUT" ]; then
220+
echo ""
221+
echo "--- INPUT keyword checks ---"
222+
for key in "calculation" "towannier90" "nspin"; do
223+
if grep -qi "$key" "$W/INPUT"; then
224+
echo " [OK] INPUT contains '$key'"
225+
else
226+
echo " [FAIL] INPUT missing '$key'"
227+
ERR=1
228+
fi
229+
done
230+
if grep -qi "gamma_only" "$W/INPUT"; then
231+
echo " [FAIL] INPUT contains 'gamma_only' — forbidden!"
232+
ERR=1
233+
else
234+
echo " [OK] INPUT does NOT contain 'gamma_only'"
235+
fi
236+
fi
237+
238+
echo ""
239+
echo "--- Basis-specific checks (${{ matrix.basis }}) ---"
240+
if [ "${{ matrix.basis }}" = "pw" ]; then
241+
if grep -qi "orbital_file\|orbital_dir" "$W/INPUT"; then
242+
echo " [FAIL] PW INPUT contains orbital_file/orbital_dir"
243+
ERR=1
244+
else
245+
echo " [OK] PW INPUT does NOT contain orbital_file/orbital_dir"
246+
fi
247+
else
248+
if grep -qi "orbital_file\|orbital_dir" "$W/INPUT"; then
249+
echo " [OK] LCAO INPUT contains orbital_file/orbital_dir"
250+
else
251+
echo " [WARN] LCAO INPUT missing orbital references (may be in STRU)"
252+
fi
253+
fi
254+
255+
if [ -f "$W/KPT" ]; then
256+
echo ""
257+
klines=$(wc -l < "$W/KPT")
258+
if [ "$klines" -gt 5 ]; then
259+
echo " [OK] KPT has $klines lines (reasonable)"
260+
else
261+
echo " [FAIL] KPT too short ($klines lines)"
262+
ERR=1
263+
fi
264+
fi
265+
266+
echo ""
267+
if [ "$ERR" -ne 0 ]; then
268+
echo "=========================================="
269+
echo " VALIDATION FAILED"
270+
echo "=========================================="
271+
exit 1
272+
fi
273+
echo "=========================================="
274+
echo " ALL CHECKS PASSED (${{ matrix.name }})"
275+
echo "=========================================="
276+
277+
- name: Show full script output
278+
if: always()
279+
run: cat run.log
280+
281+
- name: Show generated INPUT
282+
if: always()
283+
run: |
284+
f="${{ matrix.prefix }}/wannier/INPUT"
285+
if [ -f "$f" ]; then echo "=== $f ==="; cat "$f"; else echo "$f not found"; fi
286+
287+
- name: Show generated KPT (first 20 lines)
288+
if: always()
289+
run: |
290+
f="${{ matrix.prefix }}/wannier/KPT"
291+
if [ -f "$f" ]; then echo "=== $f (first 20 lines) ==="; head -20 "$f"; else echo "$f not found"; fi
292+
293+
- name: List all generated files
294+
if: always()
295+
run: find ${{ matrix.prefix }} -type f | sort

0 commit comments

Comments
 (0)