lmf,lmfa,lmchk
⚠️
lmf,lmfa,lmchkreadctrlg.<sname>.tomlonly. A directory with the legacyctrl.<sname>is converted withLegacy2toml.py <sname>before invoking these binaries (the legacy syntax is described in Legacyctrl.<sname>reference). See TOML migration for the full guide and 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.
In addition,
ctrlgenToml.pyenforces upper limits of the radius (a.u.): H 1.4, Li and Be 2.7, Na and Mg 2.4, K and Ca 2.6, Rb and Cs 2.4, Sr and Ba 2.8, others 3.0 (r_upper_limit; H, Rb and Cs from 2026-10-07, before H had none and Rb, Cs 2.8). A large sphere around an atom whose valence states are spread out (alkali s, H 1s) gains nothing: those states are carried by the envelope functions outside. It can instead make ghost levels, because the part of the envelope functions that augmentation throws away inside the sphere is left undetermined (Rb2Sc2O4 with Rb 2.8 a.u. had them in LDA). Atoms with a bound d (Sr 4d, Ba 5d) keep a larger sphere: the d must sit inside it. The example and the scan: mtradius.md.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=show,--quit=ham,--quit=mkpot,--quit=dmat,--quit=band(see Command-line options). --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.__mixm.<sname>mixing file for electron density. It retains prior iterations of sets of input and output densities. Used by the Anderson or Broyden mixing scheme to accelerate convergence towards self-consistency.lmfdiscards the file of a previous run at start (the option--keepmixmkeeps it), so that it is not used in a new calculation (such as changing the lattice constant).
** 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, including the per-atom product-basis tables that close the file. Run Legacy2toml.py <sname> inside any old working directory to generate it.
The
[product_basis]tablesnlx/valence/coreare for the GW path (consumed byhbasfp0/hvccfp0/ etc. when generating the mixed product basis). They are written bygwinit(throughctrlgenToml.pyorLegacy2toml.py) and do not normally need hand editing; the cut-offspb_tolerance/pb_lcutmxabove them are what you tune. (Before 2026-09 the tables were a separatePB.<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 (no nbas / nspec: the counts are those of the tables below)
[[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 / ...
[esm] boundary / origin / shiftmode / zb / potential / field (slabs only)
[gw] n1n2n3 / QpGcut_psi / HistBin_dw / iSigMode / niw / t_sigmaw / t_tetrakbt / ...
QforEPS / QforGW (multi-line q lists)
[mlo] mlo_method / mlo_delta / mlo_w / mlo_nkabc (required for job_mlo) / mlo_lm (formerly Worb)
[blocks] QPNT, QforEPSL, hrotr (raw multi-line blocks with no better home)
[product_basis] pb_tolerance / pb_lcutmx + nlx / valence / core (always the last section)Do not write
nbas/nspec(2026-09-28). The numbers of sites and species are the numbers of[[site]]/[[spec]]tables, andlmfstops if[struc]carriesnbasornspec. A count written beside the tables used to win over them, so sites added to the tables were silently left out. To leave a site out, comment out its whole[[site]]block. For an older file,ctrlg_update.py ctrlg.<sname>.tomlremoves the two lines; ifnbaswas smaller than the tables (the old way to use only the first sites), it comments out the[[site]]blocks beyond it, so the calculation stays the same.
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
deltaw = 0.02
t_sigmaw = 262 # (K) Fermi-Dirac width of the Sigma levels
t_tetrakbt = 0 # (K) required. 0: no smearing of chi0; T > 0: finite-T tetrahedron; -T: Gaussian on Im chi0
QforEPS = """ # q points for eps (a.u. if QforEPSau = true)
0 0 0.00050
0 0 0.00100
0 0 0.00200
"""
QforGW = """ # q points for the one-shot GW driver (gw_lmfh)
0.0 0.0 0.0
0.1 0.0 0.0
"""
# === MLO (muffin-tin based localized orbitals; see manual/mlo) ===
[mlo]
mlo_method = 4 # theta = sigma((eps - ecut_j)/mlo_w), ecut_j = max(CBM + mlo_delta, eps^MTO_j)
mlo_delta = 2.0 # (eV) how far above the band edge the model must be accurate
mlo_w = 2.0 # (eV) width of the fall-off; the knob if the residual is too large
mlo_lm = """ # which lm channels of which atom make the model (1=s, 2-4=p, 5-9=d, 10-16=f)
1 Cu 5 6 7 8 9
"""
[product_basis]
pb_tolerance = [0.001] # drop near-linear-dep products (default 1e-3)
pb_lcutmx = [4] # max l-cutoff per atom
# ----------------------------------------------------------------
# nlx [iatom, l, nnvv, nnc] ... (per-atom tables written by gwinit; see manual/gwsc)
nlx = [
[1, 0, 2, 3],
[1, 1, 2, 2],
[1, 2, 2, 0],
[1, 3, 2, 0],
[1, 4, 2, 0],
]
# ----------------------------------------------------------------
valence = [
[1, 0, 1, 1, 1], # 4s_phi
[1, 0, 2, 0, 0], # 4s_phidot
# ...
]
# ----------------------------------------------------------------
core = [
[1, 0, 1, 0, 0, 0, 0], # 1S
# ...
](QforEPS / QforGW, the q-point lists, sit at the end of [gw] as multi-line strings; the example above shows them.) That's the entire input.
Layout convention of the generated files (ctrlgenToml.py, gwinit, Legacy2toml.py and the formatter pylib/toml_tidy.py all produce it): a blank line separates only the big headings — the # === X === comment runs and single [section] headers — while everything inside a section (one [[site]] or [[spec]] table from the next, a multi-line block from its neighbours, the three product-basis tables) is divided by a # ---- rule instead. The example above is abridged; real files carry the # === headers and rules. A [blocks] section only appears for the few legacy <...> tags that have no better home (QPNT, QforEPSL, hrotr), kept as multi-line strings and parsed opaquely by the GW driver; when present it sits between [mlo] and [product_basis], which always closes the file (toml_tidy.py enforces the order [gw] [mlo] [blocks] [product_basis]).
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]]. Start from a clean directory:lmfkeeps its mixing history in__mixm.<sname>, and a history left by a run that ended non-magnetic drags the new run onto the non-magnetic solution at the first Broyden step (Fe: 2.13 → 0.02 μB). Since 2026-09-18lmfdeletes__mixm.<sname>at start (the hidden--keepmixmkeeps it), so only the densityrst.<sname>carries over; if you changenspinon top of an existingrst, deleterst.<sname>first. The defaultmix = "B3",b = 0.2is fine. - 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 --ctrlg: overrides
A key of ctrlg.<sname>.toml is overridden for one run by --ctrlg:<dotted.path>=<value>, processed in-memory by m_toml_override.f90. The legacy -v<NAME>=<VAL> (where <NAME> was a %const symbol baked into ctrl.<sname>) makes the programs stop with a message:
# OLD (legacy ctrl + %const; the programs stop)
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 path is the dotted TOML path (section.key; spec.1.r for a key of the first [[spec]] table; a top-level key such as verbose has no section); the right-hand side parses as TOML ([8,8,8] for an integer vector, 1 for an int, 1.0 for a float, true / false for a logical, "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].readp / .pnufix | HAM_V0FIX is the command-line option --v0fix |
esm_input.dat (separate positional file) | [esm] section | retired 2026-09-16; not read — ctrlg_absorb.py <sname> converts it, see ESM |
ITER_NIT / ITER_MIX / ITER_CONV / ITER_CONVC / ITER_UMIX / ITER_TOLU | [iter].nit / .mix / ... | |
SYMGRP / SYMGRPAF | top-level symgrp = "..." (and symgrpaf) | 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 | [mlo].mlo_lm = """ ... """ | multi-line string |
<QforEPS>...</QforEPS> block | [gw].QforEPS = """ ... """ (likewise QforGW) | |
n1n2n3 (GWinput) | [gw].n1n2n3 = [k1,k2,k3] | int vector |
HistBin_dw / HistBin_ratio / niw (GWinput) | [gw].HistBin_dw etc. | unchanged names (upper and lower case as in GWinput) |
esmr, SmearX0 / GaussianFilterX0, GaussSmear, delta, dw, omg_c, WgtQ0P (GWinput) | [gw].t_sigmaw and [gw].t_tetrakbt (K; t_tetrakbt is required) | the old keys and what happens to them: gwinput Table 1 (表 1), kBT §2.5 Table 2 (表 2) |
product-basis cut-offs (tolerance, lcutmx from <PRODUCT_BASIS>) | [product_basis].pb_tolerance / .pb_lcutmx | |
product-basis per-atom tables (nlx, valence, core) | [product_basis].nlx / .valence / .core (end of the file; a separate PB.<sname>.toml before 2026-09) |
The full schema lives in SRC/exec/pylib/ctrl_schema.py (the conversion source of truth). Annotations / inline comments are applied by SRC/exec/pylib/toml_comments.py.
ESM (Effective Screening Medium)
A slab with a vacuum layer is not a periodic crystal, but a plane-wave / smooth-density code solves Poisson's equation as if it were. ESM (Otani & Sugino, PRB 73, 115407 (2006); implemented here by M. Obata, Kanazawa Univ.) replaces the periodic Green function of the electrostatics with one that carries the boundary condition you actually want — vacuum, or a metal electrode — on each side of the slab. ESM combined with QSGW is used in PRB 101, 205120 (2020).
Turn it on for every slab with a vacuum layer. Without it the G=0 component of the Coulomb potential is fixed by the periodic convention instead of by the vacuum level, and the whole eigenvalue spectrum shifts. The shift is not small: on the Samples/MLOsamples/FeMgO slab (30.5 a.u. of vacuum) it is 4.4 eV, while the total energy, Vesav and the magnetic moment all agree to 8–13 digits, so nothing looks wrong until you compare Fermi energies. Two directories that differ only in whether ESM was on will produce band plots on different energy zeros.
The [esm] section
[esm]
boundary = "vac/slab/vac" # vacuum(-z)/slab/vacuum(+z)
origin = -8.63717 # (a.u.) z-translation of the density
shiftmode = 0 # 0: origin is absolute, 1: in units of the cell length
zb = [23.907104, -23.907104] # (a.u.) boundaries z1esm, z2esm
potential = [0.0, 0.0] # (Ry) on the +z / -z sides
field = [0.0, 0.0] # (Ry/a.u.) on the +z / -z sidesNo [esm] section at all means ESM is off. That is the right thing for a bulk crystal and the wrong thing for a slab, so lmf prints a warning when c is more than 3× the longer of a, b and no [esm] is present.
ctrlgenToml.py writes a commented-out [esm] template (with the # === ESM heading and one line per key) into every new file, right after [ham]; for a slab, uncomment it and set the numbers with care. A bulk crystal leaves it commented — no [esm] section means ESM off.
| key | meaning | legacy esm_input.dat |
|---|---|---|
boundary | which boundary condition on each side (table below) | line 1, jesm |
origin | z-translation applied to the density before solving. The code uses -origin internally, so this is the same number as line 2 of the old file | line 2, tresm |
shiftmode | 0: origin is in a.u.; 1: in units of the cell length | line 2, jtresm |
zb | the two boundary planes z1esm, z2esm in a.u. Omit to get ±alat·plat[2][2]/2 | line 3 |
potential | fixed potential on the +z / -z side (Ry). Used by metal/... and the :v-e / :e-v forms | line 4 |
field | fixed electric field on the +z / -z side (Ry/a.u.). Used by the :field form | line 5 |
boundary values
| value | system | jesm |
|---|---|---|
"off" (or the section absent) | ESM disabled — plain periodic | 0 |
"vac/slab/vac" | vacuum on both sides | 1 |
"metal/slab/metal" | metal electrode on both sides | 2 |
"vac/slab/metal" | vacuum on −z, metal on +z | 3 |
"metal/slab/vac" | metal on −z, vacuum on +z | 4 |
"vac/slab/vac:field" | vacuum both sides, field imposed | 5 |
"metal/slab/metal:v-e" | potential on −z, field on +z | 6 |
"metal/slab/metal:e-v" | field on −z, potential on +z | 7 |
"periodic:esm" | same result as off, computed through the ESM path | 10 |
A bare integer is also accepted, so mechanically converted files keep working; the strings are preferred because 1 and 3 are not distinguishable by eye.
To apply an electric field to a slab, use "vac/slab/vac:field" with field = [E, -E], or hold the two electrodes at fixed potentials with "metal/slab/metal" and potential = [V1, V2].
Migration from esm_input.dat
Before 2026-09-16, ESM was configured by a separate positional file esm_input.dat — six lines of bare numbers with no keys. It had two problems: you could not tell what the numbers meant without reading esmsmves.f90, and a missing file disabled ESM silently (lmf printed one line and carried on). Copying a sample directory without that one file therefore changed the physics without any error.
The Fortran reads ctrlg.<sname>.toml and nothing else (since 2026-09-17; for one day in between lmf converted the file itself). A leftover esm_input.dat makes lmf / lmfa / lmchk abort with a message naming the converter — abort rather than ignore, so a slab never runs without ESM by accident:
ctrlg_absorb.py <sname> # esm_input.dat -> [esm] in ctrlg.<sname>.toml
# (and PB.<sname>.toml -> [product_basis], if present)| situation | what ctrlg_absorb.py does |
|---|---|
ctrlg.<sname>.toml already has [esm] | the TOML wins. esm_input.dat is moved to esm_input.dat.bk, whose header records that its settings were not used |
no [esm] in the TOML | the file is converted, the [esm] block is inserted (with comments, before the GW sections), and the original is moved to esm_input.dat.bk with a header saying where it went |
Legacy2toml.py performs the same conversion when it migrates a legacy directory.
Worked example — Fe/MgO slab
Samples/MLOsamples/FeMgO (c/a = 8.50, 30.5 a.u. of vacuum, 7 empty spheres filling it):
[esm]
boundary = "vac/slab/vac"
origin = -8.63717
shiftmode = 0
zb = [23.907104, -23.907104] # alat*plat[2][2]/2 = 23.903861; set by hand here
potential = [0.0, 0.0]
field = [0.0, 0.0]With and without this section, on the same rst.<sname>:
| E_F (Ry) | Vesav (eV) | val*vef (Ry) | |
|---|---|---|---|
[esm] present | −0.38286150 | −2.12295183 | −257.64 |
[esm] absent | −0.05833040 | −2.12295183 | −253.66 |
Vesav agrees to 8 digits, so the density and the electrostatics are the same — only the zero of energy moves, by 0.3245 Ry = 4.4155 eV. Check llmf_ef (or any lmf log) for which one you got:
effective screening medium method jesm= 1 <- ESM on
system : vaccum(-z)/slab/vaccum(+z)
esmsmves: ESM is off (no [esm] section in ctrlg.<sname>.toml) <- ESM offWhere it is implemented
SRC/subroutines/esmsmves.f90 (the solver; called from smves) and SRC/subroutines/m_lmfinit.f90::readesm (reads [esm], runs the migration).
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)
symgrpaf = "find" # AF symmetry (optional): spglib finds it from the af labels; generators only for the old searchsymgrp 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 symopsGenerators with find (an old form, still accepted): spglib finds the whole group, and the generators must be operations of it (lmf stops otherwise); they do not change the group.
symgrp = "R4Z*I MX*I R3D find" # zinc blende: the same 24 operations as symgrp = "find"Disable 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.
Symmetry from spglib: symmetry.<sname>.json (2026-10)
With symgrp = "find" (the default), lmf, lmchk and the MLO programs find the space group with spglib, which is built into ecalj (SRC/external/spglib, version 2.6.0; no Python needed). The operations , in the fractional coordinates of plat ( integer), are written to symmetry.<sname>.json in the working directory together with the space-group number and symbol and the structure they belong to. The next run reads this file; when the structure differs (alat, plat, species, af labels or positions, also through --ctrlg: overrides), the operations are found again and the file is rewritten. The console tells which: mksym: N operations, read from ... or found by spglib, <symbol> (<number>), written to ....
- Pure translations of a supercell (a cell larger than the primitive one, e.g. the 8-atom cubic cell of Si) are operations too: 192 for Si8. Total energies, MLO bands and QSGW quasiparticle energies agree with those of the primitive operations.
- AF: with
af = ±kon the sites of the AF pairs, the magnetic symmetry of spglib gives the operations; those with time reversal exchange up and down.symgrpaf = "find"switches the AF mode on with these operations (2026-10-02). Generators insymgrpaf(the old form, e.g."i:( 1 1 1 )"for NiO) are accepted and must be among these AF operations. Usepwmode = 11with it. symgrpwith generators (to lower the symmetry on purpose, e.g."r4z"for an orbital-ordered 4f state) uses the generators: the group they generate, as before, and writes no file. With such asymgrp,symgrpafneeds generators (not"find").- The old search of ecalj (the operations of the lattice and those leaving the crystal invariant,
ECALJ_SYMFIND=ecalj) was removed on 2026-10-02; spglib is the only finder. The input forms above are all still accepted. symfind.py <sname>(Python spglib) makes the same file outside lmf.
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.