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:

PositionMeaning
1the solution, a lattice DiracFermion
2the residual actually reached
3the number of iterations
4the seconds taken
5the 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

KeyMeaning
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_logfilea file for ARPACK's own trace
inplaceboolean; 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

KeyMeaning
parity0 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.

KeyMeaning
namea label for the setup
verboseQOP'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 = …}
multigrida 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.

MethodMeaning
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.