Skip to content

TOML migration (2026-05) โ€‹

๐Ÿค– Auto-edited by Claude (Opus 4.7) โ€” verify before relying on details. This page and the TOML-migration banners across ecaljdoc were drafted in a single Claude Code session (commit 86e7646 on main). The shape is right (file roles, conversion command, sample dirs, gotchas all reflect the actual ecalj state at master 7ee2d7c13 / c4bf09418 plus the nvfortran cherry-pick f693848ce), but specific commit hashes, line counts, and English wording may need a human pass. Flag anything that reads off and either fix it directly or open an issue.

As of May 2026, the Fortran binaries (lmf, lmfa, lmchk, gwsc, hsfp0, eps_lmfh, epsPP_lmfh, epsPP0, mlo, ...) read structured TOML only. Legacy ctrl.<sname> and GWinput text files are no longer parsed by Fortran โ€” they are kept around as developer references but must be converted before any binary is invoked.

The two TOML files โ€‹

filerolescope
ctrlG.<sname>.tomlmerged ctrl + GW driver sections + product-basis cut-offssname-specific
PB.tomlper-atom product-basis tables (nlx, valence, core)sname-free, shared per spec

PB.toml is for the GW path only โ€” normally no hand editing. It feeds the mixed-product-basis generator (hbasfp0 / hvccfp0 etc.) used by gwsc, the eps tools and mlo's W-side. It is auto-emitted by ctrlgenToml.py (or Legacy2toml.py); leave it as generated. All hand edits live in ctrlG.<sname>.toml.

If you have a pure DFT / no-GW workflow (just lmf / lmfa / band plots) and don't want the GW sections at all, pass --skipgw to ctrlgenToml.py โ€” that skips the lmfa โ†’ lmf --jobgw=0 โ†’ gwinit sub-step, omits [gw] / [product_basis] / [blocks] from the output, and does not write PB.toml.

Adding GW sections later (preserving your hand-edits): use ctrlgenToml.py <ext> --addgw. This appends [gw] / [product_basis] / [blocks] and writes PB.toml without regenerating the ctrl-side keys โ€” your edits to [bz], [ham], [[spec]] etc. are preserved as is. It refuses to run if [gw] is already present (to avoid silent duplication). Do not plain re-run ctrlgenToml.py <ext> for this purpose: the default flow overwrites the whole ctrlG.<ext>.toml from ctrls.<ext> (the previous file is moved to ctrlG.<ext>.toml.bakup, one-generation backup only).

<sname> is the user-defined material extension (e.g. si, cu, gaas, fe, ...). One working directory normally has exactly one ctrlG.<sname>.toml; lmf auto-detects it without a positional argument when run inside the directory.

Migration of an existing legacy directory โ€‹

bash
# inside an old directory containing ctrl.<sname> [+ GWinput]
Legacy2toml.py <sname>
# produces ctrlG.<sname>.toml + PB.toml
# resume normal workflow (lmf, gwsc, eps_lmfh, ...) unchanged

Legacy2toml.py lives at ecalj/SRC/exec/Legacy2toml.py (installed in ~/bin/ along with the binaries by InstallAll.py). It is idempotent and prints [INFO] / [WARN] / [ERROR] diagnostics for any command-line -v overrides that would not survive the conversion.

Run-time -v overrides โ€‹

%const constants embedded in the legacy ctrl.<sname> are baked into ctrlG.<sname>.toml at conversion time. Run-time overrides have moved from -v<NAME>=<VAL> to bracketed TOML-path syntax processed in-memory by m_toml_override.f90 (no on-disk rewrite):

bash
# OLD (still works only for legacy ctrl, not for ctrlG.toml)
lmf si -vnk=8 -vmetal=3

# NEW
lmf si -v[bz.nkabc]=[8,8,8] -v[bz.metal]=3

The bracketed key is the dotted TOML path ([section.key]); the value parses as TOML too ([8,8,8] for an integer vector).

โš ๏ธ CAUTION โ€” the meaning of -v changed. Originally, -v<NAME>=<VAL> overrode a %const NAME=... symbol defined inside the legacy ctrl.<sname> (the value then propagated wherever {NAME} was referenced). Under TOML, -v no longer looks up a user-defined %const โ€” it points directly at a TOML path (-v[section.key]=val). The two syntaxes look similar but mean different things:

  • -vnk=8 (legacy) โ€” set the %const nk=... token, which the ctrl body then expanded as {nk} into wherever nk was used. Symbol resolution depended on what %consts the ctrl actually declared.
  • -v[bz.nkabc]=[8,8,8] (TOML) โ€” directly set the value at TOML path [bz].nkabc in ctrlG.<sname>.toml for this run, in memory. No %const indirection; no on-disk rewrite. The path must match a real key in the schema.

Practical consequences:

  • Habits like -vmetal=3 silently do nothing under TOML mode (the symbol metal is not a TOML path). Use -v[bz.metal]=3 instead.
  • -vnspin=2 -vso=0 likewise has no effect; use -v[ham.nspin]=2 -v[ham.so]=0.
  • Legacy2toml.py prints [INFO] / [WARN] / [ERROR] diagnostics for any %const overrides it encounters during conversion to help spot silent breakages.

Migrated samples (use these as templates) โ€‹

The following directories under ecalj/Samples/ are fully TOML-migrated and pass testecalj:

dirrole
Samples/MLOsamples/MuffinTin Localized Orbitals (Wannier replacement). 17 samples โ€” see MLOsamples/README.md
Samples/TestInstall/install validation suite. 23 samples driven by testecalj --all
Samples/EPS/dielectric function ฮต(q,ฯ‰) โ€” EPS_Cu, EPS_GaAs, EPS_Ag (epsPP0)
Samples/PROCAR/fat-band weight โ€” MgO_PROCAR, Ni2MnGa_L21_PROCAR

The catch-all index for the sample tree is Samples/README.md.

Legacy (awaiting migration) โ€‹

Everything else lives under Samples/Legacy/ and still uses ctrl.<sname> + GWinput. To run any of those, first Legacy2toml.py <sname> inside a working copy of the directory, then proceed as usual. The Legacy/ subgroups include Magnon/, AFsymmetry/ (with test.py) plus 24 example/educational directories.

Result summaries (worked-out reference values) โ€‹

Auto-job runner (ecalj_auto) โ€‹

For batch QSGW / GW jobs across many materials, see ecalj_auto/README.md and ecalj_auto/README_slot_scheduler.md. The auto/ driver consumes ctrlG.<sname>.toml directly (no legacy fallback) and dispatches to jobtemplate.{kugui,ohtaka,ucgw,...} for SLURM/PBS clusters.

Common gotchas โ€‹

  • -v form mismatch โ€” lmf will silently ignore -vnspin=2 -vso=0 under TOML mode; use -v[ham.nspin]=2 -v[ham.so]=0.
  • Stale Worb blocks โ€” gwinput2toml.py (the GWinput leg of Legacy2toml.py) used to last-write-wins on duplicate <Worb> blocks; now keeps the first.
  • mlo_emax = 0 literal โ€” TOML reader now honours an explicit 0; the historical "0 means default" sentinel was retired.
  • gfortran 13.3 / 14.2 codegen โ€” a documented codegen bug was worked around in m_HamPMT.f90 (one-line bait aaa = trim(aaa) // ' '); see commits 35ee9f225 and f693848ce on master.

For nvfortran 26.1 specifically: findloc runtime crashes on logical arrays were fixed by adding use m_nvfortran, only: findloc to the seven affected source files (commit f693848ce).