Skip to content

Commit 48c7914

Browse files
Zikkyingcursoragent
andcommitted
Require DFT k-spacing and license-gated VASP image discovery.
Enforce KSPACING/kspacing validation, Bohrium-safe VASP run commands, and private list_images resolution before setting vasp_image_name. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent b639671 commit 48c7914

9 files changed

Lines changed: 756 additions & 35 deletions

File tree

apex/skills/apex-flow/SKILL.md

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ Options to offer via AskQuestion:
5959
- LAMMPS + MLIP (DeePMD / DPA / MACE / NEP): fast, GPU-friendly
6060
- LAMMPS + classical (EAM / MEAM / SNAP): fast, CPU
6161
- ABACUS (DFT)
62-
- VASP (DFT; license + image required)
62+
- VASP (DFT; license-gated — resolve image via Bohrium `list_images` keyword=`vasp` or a user-known authorized address; otherwise stop)
6363
**Step B — only if Step A is LAMMPS + DeePMD/DPA: use the model bundled with this skill.**
6464
- Copy `models/DPA-3.2-5M/DPA-3.2-5M-OMat24.pth` into the job directory.
6565
- This is the frozen, single-task `OMat24` branch of DPA-3.2-5M. It is
@@ -179,6 +179,57 @@ Options to offer via AskQuestion:
179179
If the library is missing/incomplete: **STOP**, tell the user the path is
180180
unusable, and ask for the correct POTCAR location. Never submit with an
181181
absolute host POTCAR path hoping the container can see it.
182+
13. **MUST set DFT k-spacing; never rely on a hand-written KPOINTS/KPT file.**
183+
APEX auto-generates the k-mesh from spacing; omitting it fails at make time.
184+
- **VASP**: `INCAR` (or `cal_setting`) **must** contain `KSPACING`. Prefer also
185+
setting `KGAMMA` (`True` = Gamma-centered, `False` = Monkhorst-Pack).
186+
Do not hand-author per-task `KPOINTS`; APEX writes it from POSCAR + spacing.
187+
- **ABACUS**: `INPUT` **must** contain `kspacing` (1/Bohr), **or** set
188+
`cal_setting.K_POINTS` like `[nx, ny, nz, 0, 0, 0]`. APEX writes `KPT`.
189+
- **Screening defaults** (APEX is screening-oriented, not publication-grade):
190+
VASP `KSPACING=0.1–0.2` Å⁻¹; ABACUS `kspacing=0.20` (relax) / `0.15` (phonon SCF).
191+
Smaller spacing → denser mesh and much higher cost (~8× from 0.20→0.10 on ABACUS).
192+
- Confirm the spacing with the user before submit when they care about accuracy.
193+
Details: `reference/calculators.md` → k-spacing sections.
194+
14. **STOP: Resolve VASP image via Bohrium `list_images` or a user-known authorized address — never invent a default.**
195+
VASP is commercial. There is **no** default `vasp_image_name`. Before any
196+
VASP `create` / submit, resolve an image by **exactly one** of these paths:
197+
1. **Private image discovery (preferred):** query the user's own private
198+
Bohrium Docker images filtered by keyword `vasp`:
199+
- If the MatMaster / Bohrium tool is available:
200+
`Bohrium(action="list_images", keyword="vasp")`
201+
(tool description: *list the user's own private Docker images
202+
(filtered by keyword)*).
203+
- Otherwise run the skill helper (same OpenAPI):
204+
```bash
205+
python <skill-root>/scripts/list_bohrium_images.py \
206+
--keyword vasp --require
207+
```
208+
Present matching image URL(s) to the user and get approval before use.
209+
2. **User-known authorized address:** the user explicitly provides a
210+
licensed/authorized VASP image path they are allowed to use.
211+
**If neither path yields an image → TERMINATE the VASP workflow.** Do not
212+
guess public tags (including `vasp:5.4.4-dflow`), do not submit, and tell
213+
the user that a private VASP image or an authorized image address is
214+
required. Only after a confirmed image exists, pass
215+
`--vasp-image <url>` to `generate_config.py create` (writes
216+
`vasp_image_name`).
217+
15. **MUST use a Bohrium-safe VASP `vasp_run_command` — never bare `vasp_std`.**
218+
After a licensed VASP image is resolved (Rule 14), `global.json` should use a
219+
command that sources Intel oneAPI, raises stack limit, and calls an absolute
220+
binary. Typical Bohrium layout:
221+
```text
222+
bash -c "source /opt/intel/oneapi/setvars.sh && ulimit -s unlimited && mpirun -n <N> /opt/vasp.5.4.4/bin/vasp_std"
223+
```
224+
Constraints:
225+
- Always `source /opt/intel/oneapi/setvars.sh` (Intel MPI / MKL env).
226+
- Always `ulimit -s unlimited` (avoids stack overflow on large cells).
227+
- Prefer absolute binary path (PATH `vasp_std` is unreliable); adjust path if
228+
the user-approved image differs.
229+
- Align `<N>` with `scass_type` CPU count (`c32_*``-n 32`, `c16_*``-n 16`).
230+
- Do **not** use bare `mpirun -n 16 vasp_std`.
231+
`generate_config.py` writes the run_command template for `--backend vasp`
232+
and sets `vasp_image_name` only from `--vasp-image`.
182233

183234

184235

@@ -306,13 +357,14 @@ Successfully validated workflow (ID: `cu-fcc-elastic-v3-joint-sdfml`):
306357
## Scripts
307358

308359

309-
| Script | Purpose |
310-
| ------------------------ | --------------------------------------------------------------------------------- |
311-
| `generate_config.py` | `create` a complete job or `refresh-global` credentials without changing param.json |
312-
| `validate_apex_combo.py` | List / check / recommend safe image × scass_type combos |
313-
| `fetch_models.py` | Optional: download the DPA-3.2-5M multi-head source `.pt` for freezing another head |
314-
| `parse_results.py` | Parse APEX output into summary |
315-
| `validate_inputs.py` | Validate configuration before submission |
360+
| Script | Purpose |
361+
| -------------------------- | --------------------------------------------------------------------------------- |
362+
| `generate_config.py` | `create` a complete job or `refresh-global` credentials without changing param.json |
363+
| `list_bohrium_images.py` | List private Bohrium images by keyword (MatMaster `list_images` equivalent) |
364+
| `validate_apex_combo.py` | List / check / recommend safe image × scass_type combos |
365+
| `fetch_models.py` | Optional: download the DPA-3.2-5M multi-head source `.pt` for freezing another head |
366+
| `parse_results.py` | Parse APEX output into summary |
367+
| `validate_inputs.py` | Validate configuration before submission |
316368

317369

318370

apex/skills/apex-flow/data/default_templates.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
},
1919
"vasp": {
2020
"image": null,
21-
"machine": null,
22-
"run_command": "mpirun -n 16 vasp_std",
23-
"note": "User must provide image. VASP is commercial software."
21+
"machine": "c32_m128_cpu",
22+
"run_command": "bash -c \"source /opt/intel/oneapi/setvars.sh && ulimit -s unlimited && mpirun -n 32 /opt/vasp.5.4.4/bin/vasp_std\"",
23+
"note": "Commercial software. Resolve image via Bohrium list_images(keyword=vasp) or a user-known authorized address; if neither exists, stop. Never invent a default image. Never use bare mpirun ... vasp_std."
2424
}
2525
},
2626
"properties": {

apex/skills/apex-flow/reference/calculators.md

Lines changed: 73 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -370,10 +370,24 @@ kspacing 0.15
370370
| `smearing_method` | **mp** | gauss | Smearing type |
371371
| `force_thr_ev` | 0.03 | 0.02 | Force convergence (eV/Å) |
372372
| `stress_thr` | 1.0 | 0.5 | Stress convergence (GPa) |
373-
| `kspacing` | 0.20 | 0.20 | K-point spacing (1/Bohr) |
373+
| `kspacing` | **0.20 (required)** | **0.20 (required)** | K-point spacing (1/Bohr); APEX writes `KPT` from it |
374374
| `scf_nmax` | **200** | 100 | Max SCF iterations |
375375
| `relax_nmax` | **100** | 50 | Max relaxation steps |
376376

377+
### ABACUS k-spacing constraints (REQUIRED)
378+
379+
APEX does **not** accept a hand-written `KPT` as the primary control. At make time it requires either:
380+
1. `kspacing` in `INPUT` (float, unit **1/Bohr**), or
381+
2. `cal_setting.K_POINTS` as a 6-int list, e.g. `[6, 6, 6, 0, 0, 0]`.
382+
383+
Missing both → `RuntimeError: K point information is not defined`.
384+
385+
| Use case | Recommended `kspacing` | Notes |
386+
|----------|------------------------|-------|
387+
| Relaxation / screening | **0.20** | Default in skill templates |
388+
| Phonon / force SCF | **0.15** | Slightly denser |
389+
| Higher accuracy (user request) | 0.10 | ~8× cost vs 0.20 |
390+
377391
> **kspacing 对比**: 0.20 → ~6×6×6 k-mesh (216 pts), 0.10 → ~12×12×12 (1728 pts). 计算量差 **8 倍**
378392
379393
### ABACUS global.json Settings (Bohrium/dflow)
@@ -445,9 +459,25 @@ When `interaction.type` is `abacus` or `vasp`, the skill auto-applies smaller su
445459

446460
| File | Description | User Responsibility |
447461
|------|-------------|-------------------|
448-
| INCAR | VASP input parameters | Provided or generated |
462+
| INCAR | VASP input parameters | Provided or generated; **must include `KSPACING`** |
449463
| POTCAR | Pseudopotentials | **User must provide** (license-restricted) |
450-
| KPOINTS | K-mesh | Auto-generated by APEX or provided |
464+
| KPOINTS | K-mesh | **Auto-generated by APEX** from `KSPACING` (+ `KGAMMA`); do not hand-author |
465+
466+
### VASP k-spacing constraints (REQUIRED)
467+
468+
APEX **requires** `KSPACING` in `INCAR` (or `cal_setting.kspacing`). At make time it:
469+
1. Reads `KSPACING` / `KGAMMA` from INCAR
470+
2. Builds a Monkhorst/Gamma mesh from the POSCAR reciprocal lattice
471+
3. Writes per-task `KPOINTS`
472+
473+
Missing `KSPACING``RuntimeError: KSPACING must be given in INCAR`.
474+
475+
| Tag | Required? | Default / recommendation | Notes |
476+
|-----|-----------|--------------------------|-------|
477+
| `KSPACING` | **Yes** | `0.1``0.2` (Å⁻¹) for screening | Smaller → denser mesh, higher cost |
478+
| `KGAMMA` | Strongly recommended | `True` (Gamma) or `False` (MP) | Controls mesh centering |
479+
480+
Do **not** ship a static `KPOINTS` file expecting APEX to use it as the primary control — spacing drives generation. For `elastic`, APEX regenerates one shared `KPOINTS` from the undeformed cell and symlinks it into every deformation task.
451481

452482
### INCAR Example (Relaxation)
453483

@@ -463,26 +493,54 @@ ISIF = 3
463493
ISMEAR = 1
464494
SIGMA = 0.1
465495
LREAL = Auto
496+
KSPACING = 0.15
497+
KGAMMA = True
466498
```
467499

468-
### VASP global.json Settings
500+
### VASP global.json Settings (Bohrium / dflow)
501+
502+
> ⚠️ **Never** use bare `mpirun -n 16 vasp_std`. The Bohrium VASP image needs Intel oneAPI env + absolute binary path.
469503
470504
```json
471505
{
472-
"machine": {
473-
"batch_type": "Shell",
474-
"context_type": "LazyLocalContext",
475-
"local_root": "."
476-
},
477-
"resources": {
478-
"number_node": 1,
479-
"cpu_per_node": 16,
480-
"group_size": 1
481-
},
482-
"run_command": "mpirun -n 16 vasp_std"
506+
"dflow_host": "https://workflows.deepmodeling.com",
507+
"k8s_api_server": "https://workflows.deepmodeling.com",
508+
"batch_type": "Bohrium",
509+
"context_type": "Bohrium",
510+
"vasp_image_name": "<USER-PROVIDED licensed VASP image — never invent a default>",
511+
"vasp_run_command": "bash -c \"source /opt/intel/oneapi/setvars.sh && ulimit -s unlimited && mpirun -n 32 /opt/vasp.5.4.4/bin/vasp_std\"",
512+
"scass_type": "c32_m128_cpu",
513+
"group_size": 1,
514+
"pool_size": 1
483515
}
484516
```
485517

518+
> ⚠️ **Do not auto-fill `vasp_image_name`.** VASP is commercial. Resolve the image
519+
> first via Bohrium private-image listing or a user-known authorized address:
520+
>
521+
> ```text
522+
> # Preferred when MatMaster Bohrium tool is available:
523+
> Bohrium(action="list_images", keyword="vasp")
524+
>
525+
> # Skill helper (same OpenAPI /openapi/v2/image/private):
526+
> python scripts/list_bohrium_images.py --keyword vasp --require
527+
> ```
528+
>
529+
> Then pass the approved URL to `generate_config.py create --vasp-image <url>`.
530+
> If `list_images` returns nothing **and** the user does not know an authorized
531+
> image address → **terminate** the VASP workflow (do not invent a public tag).
532+
533+
`vasp_run_command` constraints (typical Bohrium VASP layout; adjust binary path if the user image differs):
534+
535+
| Piece | Why |
536+
|-------|-----|
537+
| `source /opt/intel/oneapi/setvars.sh` | Loads Intel MPI / MKL |
538+
| `ulimit -s unlimited` | Avoids stack overflow on large cells |
539+
| Absolute `vasp_std` path | PATH `vasp_std` is unreliable |
540+
| `mpirun -n <N>` | `<N>` must match `scass_type` CPUs (`c32_*`→32, `c16_*`→16) |
541+
542+
Local/debug Shell jobs may use a simpler command only when the host already has VASP + MPI on PATH; for Bohrium use the template above. `generate_config.py` emits the run_command template for `--backend vasp` but leaves `vasp_image_name` unset.
543+
486544
### VASP POTCAR Handling
487545
488546
APEX concatenates files at:

apex/skills/apex-flow/reference/examples.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,9 +321,10 @@ apex rss rss.json
321321

322322
**Scenario**: Phonon band structure for Si using VASP.
323323

324-
> ⚠️ Requires user to provide VASP image. Stage POTCARs into the job root
324+
> ⚠️ Confirm VASP license/image with the user. Stage POTCARs into the job root
325325
> (`POTCAR_Si` + `"potcar_prefix": "."`); do not leave absolute host paths
326-
> like `/share/PAW_PBE`.
326+
> like `/share/PAW_PBE`. INCAR **must** include `KSPACING`. Use the Bohrium
327+
> `vasp_run_command` template (never bare `mpirun ... vasp_std`).
327328
328329
### param.json
329330
```json
@@ -363,6 +364,25 @@ NSW = 0
363364
ISMEAR = 0
364365
SIGMA = 0.05
365366
LREAL = .FALSE.
367+
KSPACING = 0.15
368+
KGAMMA = True
369+
```
370+
371+
### Resolve VASP image first
372+
```bash
373+
# MatMaster: Bohrium(action="list_images", keyword="vasp")
374+
python <skill-root>/scripts/list_bohrium_images.py --keyword vasp --require
375+
# If empty and user has no authorized address → stop.
376+
# Else create with --vasp-image <approved-url>
377+
```
378+
379+
### global.json (VASP keys)
380+
```json
381+
{
382+
"vasp_image_name": "<from list_images or user-known authorized address>",
383+
"vasp_run_command": "bash -c \"source /opt/intel/oneapi/setvars.sh && ulimit -s unlimited && mpirun -n 32 /opt/vasp.5.4.4/bin/vasp_std\"",
384+
"scass_type": "c32_m128_cpu"
385+
}
366386
```
367387

368388
---

apex/skills/apex-flow/reference/submission.md

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ dflow validates workflow names against RFC 1123 subdomain regex. Names like `"Cu
120120
| **Outer job (submission client)** | `registry.dp.tech/dptech/dp/native/prod-397637/apex-flow:1.3.0.post` | Lightweight; just runs `apex submit` |
121121
| **LAMMPS calculator** | `registry.dp.tech/dptech/dp/native/prod-397637/deepmd-kit-phonolammps:3.1.3` | Default; includes phonoLAMMPS |
122122
| **ABACUS calculator** | (same APEX image has ABACUS) | Or user-specified |
123-
| **VASP calculator** | User must provide | Commercial; confirm with user |
123+
| **VASP calculator** | User must provide after confirming license | Commercial; **never invent a default image** |
124124

125125
> ⚠️ **Do NOT combine `deepmd-kit:3.1.1` with any NVIDIA T4 machine**. It also has a known segfault bug when handling triclinic cells (non-orthogonal boxes), including on CPU. Use `3.1.3` or later.
126126
@@ -131,7 +131,36 @@ dflow validates workflow names against RFC 1123 subdomain regex. Names like `"Cu
131131
| LAMMPS (DeePMD/MACE/NEP) | `c8_m31_1 * NVIDIA T4` | GPU beneficial |
132132
| LAMMPS (EAM/MEAM/SNAP) | `c16_m32_cpu` | CPU sufficient |
133133
| ABACUS | `c16_m32_cpu` | CPU |
134-
| VASP | User specifies | User's license |
134+
| VASP | `c32_m128_cpu` (default) | Align `mpirun -n <N>` with CPU count |
135+
136+
### VASP image resolution + `vasp_run_command` (license-gated)
137+
138+
**Image resolution (mandatory before VASP submit):**
139+
140+
1. Query the user's **private** Bohrium images with keyword `vasp`:
141+
- MatMaster tool: `Bohrium(action="list_images", keyword="vasp")`
142+
(*list the user's own private Docker images (filtered by keyword)*)
143+
- Or skill helper: `python scripts/list_bohrium_images.py --keyword vasp --require`
144+
2. Else use a **user-known authorized** VASP image address.
145+
3. If neither exists → **stop**. Do not invent `vasp:5.4.4-dflow` or any default.
146+
4. Pass the approved image as `--vasp-image` to `generate_config.py create`.
147+
148+
**Run command:** do **not** use bare `mpirun -n 16 vasp_std`. Typical
149+
Bohrium-safe command (adjust binary path to the user-approved image):
150+
151+
```text
152+
bash -c "source /opt/intel/oneapi/setvars.sh && ulimit -s unlimited && mpirun -n 32 /opt/vasp.5.4.4/bin/vasp_std"
153+
```
154+
155+
Must include: Intel `setvars.sh`, `ulimit -s unlimited`, absolute `vasp_std`,
156+
and `-n` matching `scass_type`. See `reference/calculators.md` and Critical
157+
Rules in `SKILL.md`.
158+
159+
### DFT k-spacing (REQUIRED)
160+
161+
- VASP: `INCAR` must set `KSPACING` (APEX auto-writes `KPOINTS`).
162+
- ABACUS: `INPUT` must set `kspacing`, or `cal_setting.K_POINTS`.
163+
- `validate_inputs.py` rejects missing spacing / bare VASP run commands.
135164

136165
> **IMPORTANT**: Use the minimal `c1_m2_cpu` machine for the outer Bohrium job since it only submits to dflow and waits. The heavy compute is in the inner containers specified by `scass_type` in `global.json`.
137166

0 commit comments

Comments
 (0)