Level III solvers
Four fermion actions are bound: Wilson clover (isotropic and anisotropic), twisted mass, Möbius domain wall, and the QOPQDP Wilson multigrid. The first three share a shape, which is worth stating once.
The common shape
A solver object is built from a gauge field and the action's parameters. It owns the imported gauge configuration, which is why it has a close method: the memory is not Lua's and is not freed by the collector at a time you choose.
local CL = qcd.Clover(U, kappa, c_sw, boundary)
local solve = CL:solver(eps, max_iter)
local eta, eps_got, iters, secs, flops = solve(psi)
CL:close()
The object's own methods apply the operator; solver, mxm_solver and mixed_solver each return a function, and it is that function which does the solving. The returned function is
solve(psi [, relaxed [, logging]])
psi is a lattice DiracFermion or a lattice DiracPropagator. With relaxed = true a solve that fails to converge returns anyway, having printed its status; without it a failure raises. With logging = true the library prints the residual as it goes.
For a DiracFermion the result is five values:
| Position | Meaning |
|---|
| 1 | the solution, a lattice DiracFermion | | 2 | the residual actually reached | | 3 | the number of iterations | | 4 | the seconds taken | | 5 | the floating-point operations performed |
For a DiracPropagator the result is three: the solution, a table of residuals indexed [color][spin], and a table of iteration counts in the same shape — the propagator is solved column by column.
A zero right-hand side is answered immediately, without calling the library.
Every solve prints a one-line summary from the master node, naming the solver, the status, the residual, the iteration count, the time and the rate.
Clover
qcd.Clover
qcd.Clover(U, kappa, c_sw, boundary) --> clover
U is a list of four lattice ColorMatrix fields over three colors, kappa and c_sw are numbers, and boundary is a list of four complex numbers — the phase picked up crossing each face, so antiperiodic time is {1, 1, 1, -1}.
The field strength is built from U by the constructor; there is no separate clover-term argument.
Clover is compiled for three colors and four dimensions only, and for Ns = 4; a lattice of another rank raises at construction.
qcd.AnisotropicClover
qcd.AnisotropicClover(U, {kappa = {...}, c_sw = {{...}, ...},
boundary = {...}}) --> clover
The same operator with a direction-dependent hopping parameter and clover coefficient. kappa and boundary are lists of four complex numbers; c_sw is a 4×4 table of complex numbers, one per plane. All three keys are required.
The result is a clover object with the same methods as qcd.Clover's.
clover:D
CL:D(psi) --> DiracFermion or DiracPropagator
Applies the Dirac operator.
clover:Dx
CL:Dx(psi) --> DiracFermion or DiracPropagator
Applies its Hermitian conjugate.
clover:DplusDx
CL:DplusDx(psi) --> DiracFermion or DiracPropagator
Applies D + D†.
clover:inv_clovterm
CL:inv_clovterm() --> DiracPropagator
The inverse of the clover term alone, as a lattice DiracPropagator.
clover:solver
CL:solver(eps, max_iter) --> function
A conjugate-gradient solver for D.
clover:mxm_solver
CL:mxm_solver(eps, max_iter) --> function
A solver for D†D rather than D.
clover:mixed_solver
CL:mixed_solver(inner_eps, inner_iter, eps, max_iter) --> function
A single-precision inner solve inside a double-precision outer iteration. Usually several times faster than solver for the same final residual.
clover:eig_deflator
CL:eig_deflator(vmax, nev, eps, umax) --> deflator
An EigCG deflator: it accumulates an eigenspace as solves go by and uses it to shorten later ones. vmax is the search-space size, nev the number of eigenvectors extracted per restart, eps the accuracy, umax the number of vectors kept. vmax must exceed 2*nev, and all three counts must be positive.
clover:eig_deflator_lanczos
CL:eig_deflator_lanczos(nev, ncv, max_iter, tol [, options])
--> deflator, nconv, niter
Computes the eigenspace up front with ARPACK's Lanczos/Arnoldi, then loads the converged vectors into a frozen EigCG deflator. The options are
| Key | Meaning |
|---|
cheb_accel = {n, a, b [, x0]} | Chebyshev acceleration of degree n on [a,b], optionally normalized at x0 | which | "SR", "LR", "SI", "LI", "SM" or "LM" — which end of the spectrum, smallest real part by default | eigcg = {vmax, nev, eps, umax} | leave the deflator able to continue with EigCG | arpack_logfile | a file for ARPACK's own trace | inplace | boolean; use the in-place Lanczos variant |
Only min(umax, nconv) vectors are kept. Present only in a build with ARPACK, which the reference build has.
clover:close
CL:close() --> nothing
Releases the imported gauge field and the library state. Using the object afterwards raises.
Deflators
A deflator is what eig_deflator and eig_deflator_lanczos return. It is not a solver: ask it for one.
deflator:mixed_solver
df:mixed_solver(inner_eps, inner_iter, eps, max_iter) --> function
A mixed-precision solver that uses the deflation space. This is the point of the whole object.
deflator:current_dim
df:current_dim() --> number
How many vectors the space currently holds.
deflator:eigenvalues
df:eigenvalues() --> vector.real
The Ritz values of the accumulated space, or nothing if it is empty.
deflator:start_load
df:start_load() --> number
Opens the space for explicit loading; returns the current dimension.
deflator:add_vector
df:add_vector(psi) --> number
Adds one lattice DiracFermion to the space; returns the new dimension. Only between start_load and stop_load.
deflator:stop_load
df:stop_load() --> number
Closes the loading phase; returns the dimension.
deflator:get_vector
df:get_vector(i) --> DiracFermion
Reads vector i back out.
deflator:stop
df:stop() --> nothing
Freezes the space: solves still use it, but stop adding to it.
deflator:resume
df:resume() --> nothing
Unfreezes it.
deflator:reset
df:reset() --> nothing
Empties the space.
deflator:close
df:close() --> nothing
Releases the space.
truncate, get_counter, put_counter, write_eigspace and read_eigspace appear in the Clover and MDWF deflator tables but are inside #if 0, so they are in no build. They are listed here only so that a reader who finds them in the sources knows why calling them raises.
Twisted mass
qcd.Twisted
qcd.Twisted(U, {mq = z, mu = z, boundary = {...}}) --> twisted
mq and mu are complex, boundary a list of four complex numbers. Like Clover, this is three colors and four dimensions.
The object has D, Dx, solver, mxm_solver, mixed_solver, eig_deflator, eig_deflator_lanczos and close, each exactly as Clover's. There is no DplusDx and no inv_clovterm.
twisted:set_param
TW:set_param{mq = z, mu = z} --> nothing
Changes the masses of an existing object without reimporting the gauge field. Useful for a sweep over mu on one configuration.
Up to and including 2026.10d, type() answered "userdata" for a twisted object rather than naming it, because the twisted types were missing from the table type consults. The same was true of scatters, gathers, latmats, contraction states and files.
Möbius domain wall
The MDWF binding works in five dimensions: a fermion is a Lua table of Ls lattice DiracFermions, indexed from 1, and that is what the operator and the solver take and return.
qcd.MDWF.Shamir
qcd.MDWF.Shamir(U, boundary, Ls, M5, mf, a5 [, options]) --> mdwf
qcd.MDWF.Borichi
qcd.MDWF.Borichi(U, boundary, Ls, M5, mf, a5 [, options]) --> mdwf
qcd.MDWF.Chiu
qcd.MDWF.Chiu(U, boundary, Ls, M5, mf, {a5...} [, options]) --> mdwf
a5 is a list of Ls numbers.
qcd.MDWF.Moebius
qcd.MDWF.Moebius(U, boundary, Ls, M5, mf, {b5...}, kappa [, options]) --> mdwf
b5 is a list of Ls numbers.
qcd.MDWF.generic
qcd.MDWF.generic(U, boundary, Ls, M5, mf, {b5...}, {c5...} [, options]) --> mdwf
The general Möbius kernel. b5 and c5 are lists of Ls entries, each a number or a complex; if any imaginary part is non-zero the complex form of the kernel is used.
In all five, U is a list of four three-color lattice ColorMatrix fields, boundary a list of four numbers or complexes, Ls the fifth dimension, M5 the domain-wall height (the library is given -M5) and mf the quark mass. The options, where accepted, are
| Key | Meaning |
|---|
parity | 0 or 1, the preconditioning parity | pctype | "eopc2" (default) or "eopc2p" |
mdwf:D
DW:D(psi5) --> table of Ls DiracFermions
mdwf:Dx
DW:Dx(psi5) --> table of Ls DiracFermions
mdwf:solver
DW:solver(eps, max_iter) --> function
mdwf:mixed_solver
DW:mixed_solver(inner_eps, inner_iter, eps, max_iter) --> function
mdwf:qlmdefl_mixed_solver
DW:qlmdefl_mixed_solver(latmat, evals,
inner_eps, inner_iter, eps, max_iter
[, {defl_log = 0}]) --> function
A mixed solver deflated by an eigenspace held in a qcd.latmat object rather than in a deflator. This is how a large eigenspace read from disk is used without copying it into the library's own storage. evals is a vector.real of the same length as the latmat's vector count, and the latmat's layout must match the operator — single precision, the operator's parity, an array of Ls DiracFermions over three colors — or the call raises saying which part disagrees.
mdwf:eig_deflator
DW:eig_deflator(vmax, nev, eps, umax) --> deflator
mdwf:eig_deflator_lanczos
DW:eig_deflator_lanczos(nev, ncv, max_iter, tol [, options])
--> deflator, nconv, niter
As Clover's, with the same options.
mdwf:debugmesilly
DW:debugmesilly(op_name, psi5) --> table of Ls DiracFermions
Applies one of the library's internal operators by name, for comparing against a reference implementation. Which names are accepted is the MDWF library's business, not qlua's: the string is passed straight to QOP_D3_MDWF_debugmesilly. A development hook, named accordingly.
mdwf:close
DW:close() --> nothing
The MDWF deflator has the Clover deflator's methods and two more:
mdwf.deflator:evecs_rawdump
df:evecs_rawdump(filename, n_evec [, {rank_stride = 1, verbose = 0}])
Writes n_evec vectors of the deflation space to disk in the library's raw layout: the vectors, the eigenvalues and a checksum, as separate files under filename.
mdwf.deflator:evecs_rawload
df:evecs_rawload(filename, n_evec [, {rank_stride = 1, verbose = 0}])
Reads n_evec vectors back.
Wilson multigrid
qcd.qop.WilsonMG
qcd.qop.WilsonMG(U, parameters) --> qop.WilsonMG
QOPQDP's adaptive multigrid for the Wilson and clover actions, for three colors and four dimensions. U is the list of four lattice ColorMatrix fields; parameters describes the action, the inverter and the multigrid hierarchy. The setup is built during the call, so the constructor is slow.
| Key | Meaning |
|---|
name | a label for the setup | verbose | QOP's verbosity | action | {kappa = …, c_sw = …, boundary = {…}} | residual | {rsqmin = …, relmin = …} | inverter | {max_iter = …, restart = …, max_restarts = …, evenodd = "evenodd"|"even"|"odd"} | global | {nlevels = …, verbose = …, nc = …, kappa = …, kappanv = …} | multigrid | a list, one table per level |
Each entry of multigrid is a table of named numbers passed through to QOP_3_wilsonMgSet for that level, plus lattice, a list of four numbers giving the blocked lattice at that level. qlib/mg_param.qlua in the shipped Lua library builds the whole structure from a shorter description, and is the practical way in.
| Method | Meaning |
|---|
mg:solve(rhs [, overrides]) | solves; returns the solution and a table of info and residual | mg:operator(psi) | applies the Wilson operator | mg:inverter() | the inverter settings, as a table | mg:info() | the last operation's flop count and seconds | mg:status() | info and residual from the last solve | mg:colors() | the number of colors | mg:close() | releases the setup |
solve's optional third argument is a table with the same residual and inverter keys as the constructor's, overriding them for that one solve.
|