lmf,lmfa,lmchk
⚠️ TOML migration (2026-05) —
lmf,lmfa,lmchknow readctrlg.<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, 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 (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 / ...
[esm] boundary / origin / shiftmode / zb / potential / field (slabs only)
[gw] n1n2n3 / QpGcut_psi / HistBin_dw / iSigMode / niw / esmr / GaussSmear / ...
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)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
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 -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. | |
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 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 | [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 / 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) | [product_basis].nlx / .valence / .core (end of the file; a separate PB.<sname>.toml before 2026-09) |
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.
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)
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.