Skip to content

Latest commit

 

History

8 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

qe-pseudos

Versioned PseudoDojo ONCV stringent pseudopotential bundle, packaged as a FROM scratch Docker image. Ships UPF families for PBE and PBEsol with a manifest.json for runtime resolution (Quantum ESPRESSO), and a flat PBE psp8 set (ABINIT). Full periodic-table coverage where upstream provides it. The image name predates the second consumer.

The image content is just /pseudo/{pbe,pbesol}/<element>.{upf,djrepo}, /pseudo/psp8/<element>.psp8 and /pseudo/manifest.json — no shell, no libc, nothing else. Intended for COPY --from consumption by downstream QE runners that need a pinned, integrity-verified, manifest-indexed pseudopotential set.

SCAN is not bundled — PseudoDojo NC SR 0.4 doesn't publish a SCAN family. Users who need SCAN must supply their own bundle.

Why an image, not a tarball

PseudoDojo distributes tarballs over HTTP. The advantages of repackaging as a Docker image are concrete:

  • Reproducibility — image tags are immutable; ghcr.io/material-codes/qe-pseudos:pseudodojo-v0.4 is byte-identical forever
  • Integrity — every UPF's MD5 is cross-checked against its djrepo's md5_upf field at build time, before publishing
  • Atomic consumptionCOPY --from=...:tag /pseudo /opt/pseudo pulls everything in one Docker layer with caching, no shell scripting or curl-and-verify dance
  • Manifest — a single manifest.json keyed by family + element gives runtime resolvers an O(1) lookup with cutoffs and z_valence already parsed and unit-converted (Ha → Ry)
  • Sanity guard — the build re-derives ecutwfc for known elements (Si, O) and refuses to publish if the values don't match expectations within a tolerance, catching upstream metadata regressions before they hit production

When to use this image

Good fits:

  • Workflow runners that resolve <family> + <element> requests at job submission time (e.g. material/core's qerunner)
  • CI fixtures that need a known-good pseudo set without downloading from pseudo-dojo.org on every run
  • Reproducibility artifacts for published QE calculations using PseudoDojo defaults

Not a fit:

  • PAW-only workflows — these are norm-conserving (NC) only
  • GBRV / SSSP / PSlibrary users — bundle a different image for those
  • ABINIT users — ABINIT consumes .psp8 / .psml formats, not the .upf shipped here. Use the PSP8 bundles from PseudoDojo directly for ABINIT
  • Workflows needing SCAN — supply your own SCAN bundle

What's inside

/pseudo/
├─ manifest.json              ← family + element index
├─ pbe/
│   ├─ <Element>.upf          ← e.g. Si.upf, O.upf
│   └─ <Element>.djrepo       ← per-element PseudoDojo metadata (cutoffs, hints, MD5)
├─ pbesol/
│   ├─ <Element>.upf
│   └─ <Element>.djrepo
├─ psp8/
│   └─ <Element>.psp8         ← flat PBE stringent set for ABINIT, 72 elements
└─ psp8.djson                 ← the upstream table the psp8 set was selected by

The psp8 set is not indexed by manifest.json: its consumer resolves a pseudopotential by stat-ing <dir>/<Element>.psp8 and reads its cutoffs from the job, so an index would be a second source of truth nobody queries. The selection table is kept beside it for provenance — it names, per element, which upstream variant was chosen and its md5.

Element coverage matches upstream PseudoDojo NC SR v0.4 stringent — most of the periodic table; check manifest.json after pulling for the exact list.

Manifest schema

{
  "schema_version": 1,
  "families": {
    "pseudodojo_pbe":    { "functional": "PBE",    "subdir": "pbe",    "dual": 4 },
    "pseudodojo_pbesol": { "functional": "PBEsol", "subdir": "pbesol", "dual": 4 }
  },
  "elements": {
    "pseudodojo_pbe": {
      "Si": { "file": "Si.upf", "ecutwfc_ry": 36, "ecutrho_ry": 144, "z_valence": 4 },
      "O":  { "file": "O.upf",  "ecutwfc_ry": 92, "ecutrho_ry": 368, "z_valence": 6 },
      // ... one entry per element
    },
    "pseudodojo_pbesol": { /* ... */ }
  }
}

Field semantics:

  • schema_version — currently 1. Bumped if the manifest shape changes incompatibly.
  • families.<family>.functional — XC functional this family targets (PBE, PBEsol).
  • families.<family>.subdir — directory under /pseudo containing the UPF files.
  • families.<family>.dualecutrho / ecutwfc ratio. NC pseudos use dual=4.
  • elements.<family>.<element>.file — UPF filename relative to the family subdir.
  • elements.<family>.<element>.ecutwfc_ry — recommended ecutwfc in Rydberg, derived from PseudoDojo's hints.normal.ecut (the recommended production hint level), converted Ha → Ry.
  • elements.<family>.<element>.ecutrho_ryecutwfc * dual.
  • elements.<family>.<element>.z_valence — number of valence electrons, parsed from the UPF PP_HEADER.

If you change the schema here, downstream consumers (e.g. cmd/qerunner/pseudo.go in material/core) need updating to match.

Pull

docker pull ghcr.io/material-codes/qe-pseudos:pseudodojo-v0.4
Tag pattern Meaning
pseudodojo-v<N.M> (e.g. pseudodojo-v0.4) Pinned to a PseudoDojo release. Immutable.
latest Tracks the most recent release tag. Moves over time.

For reproducibility, always pin a specific version in production references.

Use as a layer

FROM ghcr.io/material-codes/qe-base:7.4.1

# Stage the bundle into /opt/pseudo. The manifest is at /opt/pseudo/manifest.json.
COPY --from=ghcr.io/material-codes/qe-pseudos:pseudodojo-v0.4-r2 /pseudo /opt/pseudo

# An ABINIT runner wants only the flat psp8 half:
# COPY --from=ghcr.io/material-codes/qe-pseudos:pseudodojo-v0.4-r2 /pseudo/psp8 /opt/pseudodojo

The runner can then read /opt/pseudo/manifest.json at startup, build a family → element → ElementDef map, and resolve incoming jobs by looking up (requested_family, requested_element) directly.

A typical resolution flow on the consumer side:

  1. Read manifest.json once at startup.
  2. For each incoming job, look up the requested family. Reject if absent.
  3. For each species in the calculation, look up the element under that family. Reject if absent (per fail-fast policy).
  4. Use the manifest's ecutwfc_ry and ecutrho_ry as defaults; allow user override but warn if it sits below the recommended max across species.
  5. Resolve file to the absolute path /opt/pseudo/<subdir>/<file> for the QE input deck.

Build locally

docker build $(grep -E '^[A-Z0-9_]+=' pseudo-bundles.env | sed 's/^/--build-arg /') \
  -t qe-pseudos:pseudodojo-v0.4-r2 .

The character class must include 0-9: every SHA-256 variable and the whole PD_PSP8_* group carry digits, and a [A-Z_] pattern drops them without a word.

The build is fast (~3 minutes): a Go test+build of the manifest builder (~30s), a pull of the digest-pinned prior image for the UPF/djrepo trees (~20s), a single manifest pass that re-verifies every element's UPF md5 against its djrepo (~5s), and the psp8 stage's per-element fetch from GitHub with md5 verification (~1 min).

If an md5 doesn't match, the build fails at the manifest pass rather than shipping a bundle nobody checked.

Where the UPF half comes from

Not from the website, currently. The UPF and djrepo trees are inherited from the previously published image (pseudodojo-v0.4, pinned by digest), because pseudo-dojo.org goes unreachable for days at a time and has already failed a downstream runner release that way — and unlike the psp8 set, there is no content-addressed upstream to switch to: abinit/pseudo_dojo publishes psp8 and djrepo, not UPF. Inheritance keeps the release path independent of that host.

The pins in pseudo-bundles.env stay as the provenance record of which tarballs those bytes came from, and the curl-and-verify stage lives in this file's git history — restore it when the site is back, or when the bundle actually bumps (a bump has to download from the website anyway; see below). Integrity does not rest on the inheritance: the manifest pass re-verifies each element's UPF against the md5 in its djrepo.

Bumping the bundle

PseudoDojo updates approximately yearly. A bump replaces inherited bytes with downloaded ones, so it needs the curl-and-verify fetch stage back from git history first.

  1. Visit pseudo-dojo.org; for each functional, download:
    • The new _upf.tgz bundle (NC SR ONCVPSP v0.4 stringent, UPF format)
    • The matching _djrepo.tgz (same accuracy/version, djrepo format)
  2. Run sha256sum <each-downloaded-file> to get the new checksums.
  3. Update pseudo-bundles.env — replace each URL, SHA-256, and exact filename. The variable layout is 12 vars total: 2 bundles × 3 fields × 2 functionals. Pass them back as build-args in .github/workflows/build.yml, which today ships only the PD_PSP8_* group.
  4. Cut a new tag, e.g. pseudodojo-v0.5. The GHA workflow publishes both the version-pinned image and latest. ~3 minutes.

The psp8 set bumps separately and does not come from the website. Point PD_PSP8_COMMIT at a newer commit of abinit/pseudo_dojo and update PD_PSP8_COUNT if the stringent table gained or lost elements — the build fails on a count mismatch rather than shipping a shorter periodic table quietly. No checksum list to maintain: the table carries an md5 per element and the build verifies every file against it.

Why the repository and not the tarball: the two carry identical bytes (checked md5-for-md5 against the set running in production), but pseudo-dojo.org has gone unreachable for days at a time and, in August 2026, failed a downstream runner release along with its retry. A commit pin is content-addressed and does not depend on any host staying up.

The trigger is tags: ['pseudodojo-*']. Unrelated tags would not fire the workflow.

Versioning policy

Image tags mirror the PseudoDojo upstream version verbatim (e.g. PseudoDojo NC SR v0.4 → image tag pseudodojo-v0.4). A packaging change that adds no upstream version — a new format bundled from the same release, say — appends a bundle revision instead: pseudodojo-v0.4-r2. Consumers stamp this tag into their job records, so the suffix is what tells a reader that two differing tags may still hold identical physics. The pseudodojo- prefix disambiguates from any future bundle types (e.g. a separate gbrv-* or sssp-* set in this same image namespace, if added).

Licensing

The Dockerfile, manifest builder, and CI in this repo are MIT-licensed (see LICENSE).

The published image contains PseudoDojo pseudopotential files (.upf and .djrepo), which are distributed by upstream under the Creative Commons Attribution 4.0 International License (CC-BY 4.0). The MIT license covers only the repo's tooling — not the bundled pseudopotential data.

When using the image in published work, please cite the PseudoDojo project per their citation guidance — typically the van Setten et al. 2018 paper.

About

Versioned PseudoDojo ONCV pseudopotential bundle for Quantum ESPRESSO (PBE/PBEsol, stringent) — packaged as a Docker image with a manifest.json for runtime resolution.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages