lmf,lmfa,lmchk
⚠️ TOML migration (2026-05) —
lmf,lmfa,lmchknow readctrlg.<sname>.toml+PB.<sname>.tomlonly. Thectrl.<sname>examples below are legacy syntax kept as developer reference; convert withLegacy2toml.py <sname>before invoking these binaries. See TOML migration for the full guide and migrated Samples/.
We need an input file ctrlg.<sname>.toml (legacy: ctrl.<sname>).<sname> is the positional argument passed to the binary (e.g. lmf si reads ctrlg.si.toml); the rest of this page uses <sname> as a placeholder for whatever material extension the user chose at Legacy2toml.py / ctrlgenToml.py time.
lmfa: spherical atom calculations
Example:`
lmfa siIt finishes instantaneously.
lmfa si |grep confshows electronic configurations. It gives electron densities of spherical atoms contained in the primitive cell specified by . With the superposition of the densities From which, we construct initial electronic density for lmf. In addition,lmfa generates
lmchk: Check crystal symmetry.
lmchk gives useful information of space group symmetry recognized by lmf. In addition, it determines MT radius.The space-group operations are explained at SYMGRP.
MT radius determined by lmchk
The ideal choice of sphere radii best approximates a potential that is spherical within the MT spheres and flat outside. Program lmchk has implemented one algorithm that makes a reasonable initial choice for MT radii. The algorithm works by computing the (electrostatic) potential obtained from overlapping free-atom densities along all connecting vectors between a given site and its relatively near neighbors. The MT radius is taken as the first potential maximum along any ray. This choice is a pretty reasonable estimate for the potential being approximately spherical inside. Also, note that for a completely symmetric bond, the potential maximum will fall exactly midway between the bond, so for that case the two sphere radii will exactly touch and have equal potentials. To tell lmchk to find these radii, invoke lmchk as lmchk --getwsr. This is performed automatically in ctrlgenToml.py (and the legacy ctrlgenM1.py).
In addition,
ctrlgenToml.pyenforces a limit on the maximum radius for alkali atoms, to avoid the linear-dependency problem between APWs and MTOs.When we treat molecules (especially dimers), we have to use very small size of MT radius. T.Kotani checked PMT works well even for such systems. However, we need examination a little more.
lmf: Solve one-body problem.
This is for band calculation in LDA/GGA and LDA+U. In addition, we can add the potential term for QSGW via sigm.<sname>.
Example:
mpirun -np 4 lmf si [options] > llmfThis is a case with ctrlg.si.toml.
options
- quit option at some point.
--quit=band,--quit=ldau... We need to do 'grep cmdopt SRC//.f90|grep quit' to know details. --tdostotal dos calculation. But we usually use `job_tdos'--ctrlg:<dotted.path>=<value>: Runtime override of a key inctrlg.<sname>.toml. The path uses dotted TOML syntax (e.g.--ctrlg:bz.nkabc=[8,8,8],--ctrlg:ham.scaledsigma=0.8,--ctrlg:ham.phispinsym=true,--ctrlg:verbose=50,--ctrlg:spec.1.r=2.5for the 1st[[spec]]). Substituted into the in-memory TOML before parsing; the file on disk is untouched. Each applied override is logged on rank 0. Older syntaxes (-vfoo=val,-v[<path>]=val,--[<path>]=val,--toml.<path>=val,--pr=N,--time=N,M,--phispinsym) abort with a one-line migration hint.
We have some kinds of options for electron density plot, boltztrap and so on. (not yet described).
Input files
(<sname> is the positional argument of lmf, e.g. si for lmf si reading ctrlg.si.toml.)
syml.<sname>symmetry line for band plot (usuallyjob_bandcalls lmf internally)sigm.<sname>a part of QSGW calculationatmpnu.{1,2,3}.<sname>generated bylmfa(when[ham] readp = true)
Output files
rst.<sname>restart file, containing density and related information. Together withctrlg.<sname>.toml,atmpnu*,sigm*, andrst*we can resume anlmfcalculation. (dmat*is used for LDA+U.)save.<sname>Minimal iteration history forlmf/lmfa/lmchk, with total energies for eachlmfSCF step.__mix.<sname>mixing file for electron density. When you stop iteration at the middle, you may need to delete this. mixm retains prior iterations of sets of input and output moments. Used by the Anderson or Broyden mixing scheme to accelerate convergence towards self-consistency. Usually you should delete these when starting a new calculation (such as changing the lattice constant) so it doesn't get used in subsequent runs.
** Main Source** : SRC/main/lmf.f90
ctrlg.<sname>.toml — current input format (2026-05+)
lmf, lmfa, lmchk read TOML only since 2026-05. The single file ctrlg.<sname>.toml carries everything that used to live in ctrl.<sname> plus the GW driver and product-basis sections that used to live in GWinput. Per-atom product-basis tables (sname-free) sit in a sibling PB.<sname>.toml. Run Legacy2toml.py <sname> inside any old working directory to generate both files.
PB.<sname>.tomlis for the GW path (consumed byhbasfp0/hvccfp0/ etc. when generating the mixed product basis). It is auto-emitted byctrlgenToml.py(orLegacy2toml.py) and does not normally need hand editing — when you tune a calculation, edits go intoctrlg.<sname>.toml.
File structure (sections)
# Top-level scalars
symgrp = "find" # space-group spec: 'find' = auto-detect
verbose = 35 # console verbosity
time = [0, 0] # CPU timing log: [depth, on-the-fly]
[struc] alat / plat (nspec / nbas auto-derived from arrays)
[[site]] atom / pos / xpos / af / relax (one table per atom)
[[spec]] atom / z / r / rsmh / eh / lmx / ... (one table per species)
[bz] nkabc / metal / tetra / npts / ...
[iter] nit / mix / b / conv / convc / umix / tolu
[ham] nspin / rel / so / phispinsym / xcfun / gmax / pwmode / pwemax / oveps / ...
[gw] n1n2n3 / QpGcut_psi / HistBin_dw / iSigMode / niw / esmr / GaussSmear / ...
[product_basis] pb_tolerance / pb_lcutmx
[blocks] QPNT, QforEPS, Worb (multi-line strings, GW-side blocks)Worked example: bcc-Cu (FCC, 1 atom, non-magnetic)
The full ctrlg.cu.toml from Samples/EPS/EPS_Cu/ is shown below. Inline # comments document each key's role; copy-paste the file as a starting point for FCC monatomic metals and adjust [spec], [bz], [ham] to your case.
# Top-level scalars
symgrp = "find" # 'find' = auto-detect space group from lattice + species
verbose = 35 # 31 default, 35 verbose, 41+ debug
time = [0, 0] # CPU timing log: [depth, on-the-fly]
[struc]
alat = 6.798 # lattice constant (a.u.)
plat = [[0.0, 0.5, 0.5], # primitive vectors in units of alat
[0.5, 0.0, 0.5],
[0.5, 0.5, 0.0]]
[[site]]
atom = "Cu"
pos = [0.0, 0.0, 0.0]
[[spec]]
atom = "Cu"
z = 29
r = 2.33 # MT radius (a.u.)
rsmh = [1.17, 1.17, 1.17, 1.17] # smoothing radii per l
eh = [-1.0, -1.0, -1.0, -1.0] # tail energies
rsmh2 = [1.17, 1.17, 1.17] # second basis group
eh2 = [-2.0, -2.0, -2.0]
lmx = 3 # basis l-cutoff
lmxa = 4 # augmentation l-cutoff
nmcore = 1 # 1: spin-averaged core; 0: spin-polarized core
kmxa = 5 # radial expansion order at tail sites
[bz]
nkabc = [12, 12, 12] # k-mesh divisions; 1 entry => isotropic
metal = 3 # 0 insulator, 3 tetra+broadening (safe metal)
savdos = true # write dos.tot.* file
npts = 2001
dosmax = 1.5
[iter]
nit = 30 # max self-consistency iterations
mix = "A2" # B3 = Broyden hist=3 (default); A2 = Anderson hist=2
conv = 1e-05 # max dE between iterations (Ry)
convc = 1e-05 # max d(rho_out - rho_in) (Ry)
b = 0.2 # mixing ratio
[ham]
nspin = 1 # 1 nonmag, 2 spin-polarized (then spec.mmom seeds)
rel = true
so = 0 # 0 none, 1 L.S, 2 Lz.Sz
gmax = 12.0 # real-space mesh G-cutoff (Ry); alt: ftmesh
frzwf = false
xcfun = 1 # 1=VWN, 2=Barth-Hedin, 103=PBE-GGA
forces = 0
scaledsigma = 1.0 # QSGW mixing: 1.0 full, 0.8 = QSGW80
oveps = 0.0
pwmode = 1 # 0=MTO 1=PMT 2=APW 11=PMT(|q+G|, default) 12=LAPW
pwemax = 3.0 # APW cutoff (Ry)
# === GW driver (used by lmf --jobgw=N and gwsc) ===
[gw]
n1n2n3 = [10, 10, 10] # GW BZ mesh (typically smaller than [bz].nkabc)
QpGcut_psi = 3.0 # |q+G| cutoff for eigenfunctions
QpGcut_cou = 2.0 # |q+G| cutoff for Coulomb / W
unit_2pioa = false # false: a.u.; true: 2*pi/alat
HistBin_dw = 1e-05 # bin width on real-axis at omega=0
HistBin_ratio = 1.03
iSigMode = 3 # self-energy mode (3 = standard QSGW)
niw = 10 # # of imag-axis frequencies
delta = -1e-06
deltaw = 0.02
esmr = 0.003 # hsfp0 smearing
GaussSmear = true
[product_basis]
pb_tolerance = [0.001] # drop near-linear-dep products (default 1e-3)
pb_lcutmx = [4] # max l-cutoff per atom
# Per-atom product-basis tables (nlx / valence / core) live in PB.<sname>.toml.
# === GW additional blocks (legacy GWinput tags become multi-line strings) ===
[blocks]
QforEPS = """
0 0 0.00050
0 0 0.00100
0 0 0.00200
"""
Worb = """
! 1 Cu 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
"""That's the entire input. [blocks] carries the legacy <...>...</...> GWinput tag content as multi-line TOML strings; the body is parsed opaquely (per-block) by the GW driver.
Per-physics deltas (from the Cu starting point)
- Spin-polarized metal (Fe, Ni, FeCo): set
[ham].nspin = 2and addmmom = [0, 0, 2.5](or per-l guess) to each[[spec]]. - SOC (
HAM_SO): set[ham].so = 1(full L·S) or2(Lz·Sz only), with[ham].nspin = 2. SeeSamples/MLOsamples/FeSoc/. - Insulator / semiconductor (Si, GaAs):
[bz].metal = 0and[bz].tetra = true; smaller[bz].nkabc;[ham].pwemax~3 is enough. - LDA+U: add
idu = [0, 0, 2, 2],uh = [0, 0, 0.1, 0.632],jh = [0, 0, 0, 0.055]to[[spec]].dmatu.<sname>is read separately if present. - Atomic-position relaxation:
[dyn].mode = 4(CG) or6(Broyden), set[[site]].relax = [1, 1, 1]per atom. - GW BZ mesh: keep
[gw].n1n2n3≤[bz].nkabc(often 1/2 or 2/3 of it) —n1n2n3dominates GW wall-time.
Run-time -v overrides
The legacy -v<NAME>=<VAL> (where <NAME> was a %const symbol baked into ctrl.<sname>) is replaced by bracketed dotted-path syntax processed in-memory by m_toml_override.f90:
# OLD (legacy ctrl + %const)
lmf si -vnk=8 -vmetal=3 -vnspin=2 -vso=0
# NEW (ctrlg.toml + path syntax)
lmf si --ctrlg:bz.nkabc=[8,8,8] --ctrlg:bz.metal=3 --ctrlg:ham.nspin=2 --ctrlg:ham.so=0The bracketed key is the dotted TOML path ([section.key] or [section.subkey]); the right-hand side parses as TOML ([8,8,8] for an integer vector, 1 for an int, 1.0 for a float, "r4z r3d r2x" for a string). No on-disk rewrite of the .toml file takes place.
Legacy ctrl.<sname> ↔ TOML path map
Most legacy Category_Token keys map 1:1 onto [section.key] after lower-casing. A few are renamed or restructured:
legacy Category_Token | TOML location | note |
|---|---|---|
STRUC_ALAT / STRUC_PLAT | [struc].alat / .plat | |
SITE_ATOM=, POS=, XPOS= | [[site]] atom = ...; pos = [...] (or xpos) | one [[site]] table per atom |
SPEC_ATOM=, Z=, R=, RSMH=, EH=, ... | [[spec]] atom = ...; z = ...; r = ...; rsmh = [...] | one [[spec]] table per species; R/W= and R/A= kept as "r/a" quoted-key |
BZ_NKABC / BZ_METAL / BZ_TETRA | [bz].nkabc / .metal / .tetra | |
HAM_NSPIN / HAM_SO / HAM_XCFUN / HAM_GMAX / HAM_PWMODE / HAM_PWEMAX | [ham].nspin etc. | |
HAM_FORCES / HAM_OVEPS / HAM_FRZWF / HAM_REL | [ham].forces etc. | |
HAM_ScaledSigma | [ham].scaledsigma | lowercase |
HAM_READP / HAM_PNUFIX / HAM_V0FIX | [ham].readp etc. | |
ITER_NIT / ITER_MIX / ITER_CONV / ITER_CONVC / ITER_UMIX / ITER_TOLU | [iter].nit / .mix / ... | |
SYMGRP / SYMGRPAF | top-level symgrp = "..." (and symgrp_af) | not nested in a section |
EWALD_TOL | [ewald].tol | rarely touched |
DYN_MODE / DYN_NIT / DYN_HESS / ... | [dyn].mode etc. | |
IO_VERBOS / IO_TIM | top-level verbose / time | promoted out of [io] (section dropped) |
<Worb>...</Worb> block | [blocks].Worb = """ ... """ | multi-line string |
<QforEPS>...</QforEPS> block | [blocks].QforEPS = """ ... """ | |
n1n2n3 (GWinput) | [gw].n1n2n3 = [k1,k2,k3] | int vector |
HistBin_dw / HistBin_ratio / niw / delta / esmr / GaussSmear (GWinput) | [gw].HistBin_dw etc. | unchanged names, lowercased |
product-basis cut-offs (tolerance, lcutmx from <PRODUCT_BASIS>) | [product_basis].pb_tolerance / .pb_lcutmx | |
product-basis per-atom tables (nlx, valence, core) | PB.<sname>.toml (separate file) | per-sname |
The full schema lives in SRC/exec/ctrl_schema.py (the conversion source of truth). Annotations / inline comments are applied by SRC/exec/toml_comments.py.
LDA+U (TOML)
LDA+U is selected per species by writing the idu, uh, jh vectors into each [[spec]] table. Indices [s, p, d, f]:
[[spec]]
atom = "Er"
z = 68
r = 3.00
# ... rsmh, eh, ... ...
idu = [0, 0, 2, 2] # 0 = none, 1 = AMF, 2 = FLL. +10 disables when sigm.* exists
uh = [0.0, 0.0, 0.10, 0.632] # Hubbard U (Ry)
jh = [0.0, 0.0, 0.00, 0.055] # exchange J (Ry)Mode codes (idu[l]):
0— no U on this l-channel1— AMF (Around-Mean-Field), Petukhov, PRB 67, 153106 (2003)2— FLL (Fully Localized Limit), Liechtenstein, PRB 52, R5467 (1995)12/21/ ... — same code +10 means "skip LDA+U whensigm.<sname>exists" (so a QSGW run withsigmfalls back to plain QSGW).
dmatu.<sname> (density matrix) is read & written automatically — it is the LDA+U analogue of rst.<sname>. A first-shot LDA run without U populates it. You can override the initial occupation by hand-writing occnum.<sname> (one line of 2l+1 numbers per spin) — see the legacy LDA+U notes for the ErAs example and the spin-configuration hazard.
Mixing of the dmat happens independently of the charge with linear mixing:
[iter]
umix = 0.2 # dmat mixing beta (0..1)
tolu = 0.0 # rms tol where dmat mixing stops (0 = always mix)Check the dmat once with lmf <sname> --quit=dmat — it stops after the initial setup and prints the matrix without writing any restart files.
Core hole (TOML)
Partial core-hole occupancy implements Slater transition-state ideas (useful for XAS / unbinding 4f). Set per species:
[[spec]]
atom = "Nd"
z = 60
r = 3.00
p = [0.0, 0.0, 0.0, 5.2] # treat 4f as core, 5f as valence
c_hole = "4f" # core channel to perturb
c_hq = [-11.0] # excess electron charge in that channel
# c_hq = [-7.0, 7.0] # optional 2nd entry = spin momentCharge bookkeeping:
Q(spin1) = full_core_count + c_hq[1]/2 + c_hq[2]/2
Q(spin2) = full_core_count + c_hq[1]/2 - c_hq[2]/2Negative c_hq[1] removes electrons (a hole); the optional c_hq[2] polarises the core (used e.g. for the Gd 4f trick — c_hq = [-7, 7] freezes 7-up / 0-down in the 4f core while 5f remains valence).
Confirm neutrality with lmfa <sname> | grep -i 'add core hole'. See the legacy core-hole walkthrough for the full Gd / Nd / CrN case study.
Local orbitals (TOML)
The local-orbital channel pz is the analog of the continuously-variable principal quantum number p. Both are per-species, per-l vectors in [[spec]]:
[[spec]]
atom = "Ga"
# p[0..3] = s,p,d,f valence principal quantum numbers (continuous);
# fractional part 0.5 = mid-band, ->0 = bottom, ->1 = top.
p = [0.0, 0.0, 4.0, 0.0] # 4d "valence-like"
# pz[0..3] = semicore (lower n) or high-lying (higher n) local-orbital prinq;
# fractional part ~0.9 = semicore, ~0.3 = high-lying.
pz = [0.0, 0.0, 3.9, 0.0] # 3d treated as semicore local orbital
# add 10 to pz[l] to attach a smooth-Hankel tail (extended local orbital).Notes:
- Integer part of
pz↔pcontrols the principal quantum number used for the radial function (semicore →int(pz) = int(p) − 1, high-lying →int(pz) = int(p) + 1). - Fractional part:
0.9for semicore,0.3for high-lying is the common choice; smaller fractional ⇒ lower linearization energy. pz[l] + 10(i.e. writepz = [0, 0, 13.9, 0]) attaches a smooth-Hankel tail (extended local orbital). Use this when the deep state spills into the interstitial.- Verify the configuration with
lmfa <sname> | grep -i conf— the line shows which states are treated as core / valence / lo.
Common pitfalls:
- Conventional (non-extended) local orbitals on semicore states rely on the valence envelope for representation outside the MT sphere — keep at least one
rsmhfor that l small (~1) withehrather negative (~-1). - Extended-lo matching can fail ("
mtchre: failed to match phi'/phi") when the fractional part ofpzis too close to 1.0 — reduce it (e.g.0.98 → 0.85). - The
pwith the higher principal quantum number is automatically frozen — only the deepest state is allowed to float (controlled byidmod).
See the legacy local-orbital notes for the historical sm-Hankel mtchre discussion.
SYMGRP / symgrp — space-group specification
In TOML the space-group spec is the top-level symgrp string:
symgrp = "find" # auto-detect from lattice + species (default)
symgrp_af = "R4z*I" # extra generator for AF symmetry (optional)symgrp either takes the literal string "find" (auto-detect) or a space-separated list of generators. The generators are the same as the legacy SYMGRP token:
R<n>X,R<n>Y,R<n>Z,R<n>D—n-fold rotation around X, Y, Z, (1,1,1).M<axis>— mirror.I— inversion.<axis> = X | Y | Z | D | (nx,ny,nz)— pick a Cartesian axis or an explicit direction.- Products with
*, e.g.I*R4X. - Translations:
r6z:(0,0,0.4778973)(Cartesian) orr6z::(0,0,1/3)(fractional, multiples ofplat).
Example (cubic):
symgrp = "R4X MX R3D" # 4-fold around X, mirror in X, 3-fold around (1,1,1) ⇒ 48 symopsMix-and-find:
symgrp = "R4X find" # force 4-fold around X then let lmf find the restDisable symmetry entirely:
symgrp = "e"lmchk prints the recognised symops at the top of its console output — use it to verify the symmetry was parsed as intended. The inversion is implicit in the DFT path when the potential is local; pay attention to the inversion-related notes in the console banner.
Q: Should the Harris-Foulkes and Hohenberg-Kohn Sham functionals agree at self-consistency?
(due to Mark van Schilfgaarde) A: Yes. If they do not, either you have not reached self-consistency, or a tolerance is set too loosely in the evaluation of the matrix elements. A likely culprit is that the mesh of points for the interstitial integrals is not fine enough. Here is part of an output where mesh of 14x14x14 divisions were used for the interstitial density.
GVLIST: gmax = 4.702 a.u. created 973 vectors of 2744 (35%)
mesh has 14 x 14 x 14 divisions; length 0.588, 0.588, 0.668
SGVSYM: 170 symmetry stars found for 973 reciprocal lattice vectors
...
sugcut: make orbital-dependent reciprocal vector cutoffs for tol= 1.00E-05
spec l rsm eh gmax last term cutoff
Te 0* 1.30 -0.10 5.220 9.30E-05 973*
Te 1* 1.30 -0.10 5.597 4.36E-04 973*
Te 2 1.30 -0.10 5.976 2.04E-03 973*
Te 0* 1.40 -1.00 4.847 2.11E-05 973*
Te 1 1.40 -1.00 5.182 9.90E-05 973*
E 0* 1.50 -0.30 4.524 1.06E-05 847
E 1 1.50 -0.30 4.823 2.01E-05 973*The table reflects how well each of the basis orbitals is converged in a PW expansion, which is used to make matrix elements of the interstitial potential. Only the E s orbital is converged below the specified tolerance (10-5 ). Convergence in the Te d orbital is particularly poor; however, the Te d is only minimally part of the bonding, and its poor convergence doesn't affect the energy much. In this case (3 Te atoms), the HF and HK total energies differ by ~10-4 Ry. Below is a table showing the convergence in HF energy as a function of the number of divisions, and also the difference between HK and HF energies.
n ehf ehf-ehk
14 -14561.140624 0.000089
15 -14561.133966 0.000017
16 -14561.132309 0.000005
20 -14561.131170 0.000000Legacy reference
The bulk of historical Category_Token reference, old physics-notes (APW test, sm-Hankel mtchre discussion, old SPEC notes, old tetrahedron memo) has been moved to a dedicated page:
That page is the canonical place to look up the meaning of a legacy key, then translate to TOML via the Legacy ↔ TOML map above.