qlat.qcd — Gauge Fields, Gauge Transformations, and DWF QED Solvers¶
Source: qlat/qlat/qcd.pyx
Note: Update this document when updating the source file.
Outline¶
Overview¶
qcd provides the core gauge-field infrastructure for lattice QCD
simulations in qlat. It defines two primary classes:
GaugeField— AFieldColorMatrixwith multiplicity 4 (one SU(3) matrix per lattice direction) representing the gauge link variables U(x,mu). Supports NERSC-format I/O, plaquette and link-trace observables, Wilson lines, and boundary condition manipulation.GaugeTransform— AFieldColorMatrixwith multiplicity 1 representing a gauge transformation matrix V(x). Supports application to gauge fields, propagators, and fermion fields via the*operator, as well as CPS-format I/O.
The module also provides standalone functions for computing plaquette fields, Wilson lines/loops, and domain-wall fermion (DWF) QED inversions that are used in lattice QED calculations (e.g., for the muon g-2 HLbL contribution).
import qlat as q
q.begin_with_mpi([[1, 1, 1, 1]])
total_site = q.Coordinate([4, 4, 4, 8])
geo = q.Geometry(total_site)
gf = q.qcd.GaugeField(geo)
rng = q.RngState("test")
gf.set_rand(rng)
print(f"plaquette = {gf.plaq():.10f}")
print(f"link_trace = {gf.link_trace():.10f}")
q.end_with_mpi()
GaugeField Class¶
GaugeField inherits from FieldColorMatrix with fixed multiplicity 4.
Each site stores 4 color matrices — one for each lattice direction mu=0,1,2,3.
Constructor¶
GaugeField(geo: Geometry = None, multiplicity: int = 4)¶
Create a gauge field. The multiplicity argument must be 4 (or 0 for an
uninitialized field).
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
|
|
Lattice geometry; |
|
|
|
Must be 4 |
I/O¶
save(path: str)¶
Save the gauge field to disk in the standard NERSC format.
load(path: str) -> int¶
Load the gauge field from a NERSC-format file. Returns 0 on success.
Random Generation¶
set_rand(rng: RngState, sigma: float = 0.5, n_step: int = 1)¶
Fill the field with random SU(3) matrices generated via Gaussian
smearing around the identity. Parameters sigma and n_step control the
smearing width and number of smearing steps.
Unitarization¶
unitarize()¶
Project each link matrix to SU(3) in place.
Observables¶
plaq() -> float¶
Return the average plaquette of the gauge field.
link_trace() -> float¶
Return the average link trace of the gauge field.
show_info()¶
Display the plaquette and link trace to the log.
Boundary Conditions¶
twist_boundary_at_boundary(lmom: float = -0.5, mu: int = 3)¶
Apply a twist boundary condition in direction mu by modifying the gauge
field in place. The parameter lmom controls the boundary phase (default
-0.5 corresponds to periodic boundary conditions).
GaugeTransform Class¶
GaugeTransform inherits from FieldColorMatrix with fixed multiplicity 1.
Each site stores one SU(3) matrix V(x) representing a gauge transformation.
Constructor¶
GaugeTransform(geo: Geometry = None, multiplicity: int = 1)¶
Create a gauge transformation field. The multiplicity argument must be 1
(or 0 for an uninitialized field).
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
|
|
Lattice geometry |
|
|
|
Must be 1 |
I/O¶
save(path: str)¶
Save as RealD precision using the generic field format (save_double).
load(path: str) -> int¶
Load as RealD precision using the generic field format (load_double).
save_cps(path: str)¶
Save in the CPS format.
load_cps(path: str) -> int¶
Load from the CPS format.
Random Generation and Unitarization¶
set_rand(rng: RngState, sigma: float = 0.5, n_step: int = 1)¶
Fill with random SU(3) matrices via Gaussian smearing.
unitarize()¶
Project each matrix to SU(3) in place.
Gauge Transformation Multiplication¶
__mul__(other) -> GaugeTransform | GaugeField | Prop | SelProp | PselProp | FermionField4d | list¶
Apply the gauge transformation to another object. The result type depends on the operand:
Operand type |
Result type |
Operation |
|---|---|---|
|
|
Compose transformations: V * V’ |
|
|
Transform gauge links: V * U |
|
|
Transform full propagator |
|
|
Transform selected-point propagator |
|
|
Transform point-selected propagator |
|
|
Transform fermion field |
|
|
Element-wise transformation |
Inverse¶
inv() -> GaugeTransform¶
Return the inverse transformation V^dagger.
Gauge Field Functions¶
Plaquette and Link Trace¶
gf_avg_plaq(gf: GaugeField) -> float¶
Return the average plaquette.
gf_avg_spatial_plaq(gf: GaugeField) -> float¶
Return the average spatial plaquette (mu,nu with mu,nu in {0,1,2}).
gf_avg_link_trace(gf: GaugeField) -> float¶
Return the average link trace (trace of U divided by Nc).
gf_show_info(gf: GaugeField)¶
Display the plaquette and link trace to the log.
gf_plaq_field(gf: GaugeField) -> FieldRealD¶
Return a FieldRealD with multiplicity 1 containing the plaquette value
at each site.
set_tr_less_anti_herm_matrix(fc: FieldColorMatrix)¶
Make each matrix in the field traceless anti-Hermitian in place.
Wilson Lines¶
gf_wilson_line_no_comm(wlf, m, gf_ext, path, path_n=None)¶
Compute a Wilson line along path and store the result in multiplicity m
of wlf. The gauge field gf_ext must already include halo expansion.
Parameter |
Type |
Description |
|---|---|---|
|
|
Output field (modified in multiplicity |
|
|
Multiplicity index to write |
|
|
Expanded gauge field |
|
|
Sequence of directions; negative values mean reversed links |
|
|
Optional repetition counts per step |
Path encoding: mu for forward link, -mu-1 for backward link.
For example, [0, 0, 3, -1, -1] means mu, mu, nu, -mu, -mu.
gf_wilson_lines_no_comm(gf_ext, path_list) -> FieldColorMatrix¶
Compute multiple Wilson lines. Each entry in path_list can be a plain
path list or a (path, path_n) tuple.
Parameter |
Type |
Description |
|---|---|---|
|
|
Expanded gauge field |
|
|
List of path specifications |
Returns a FieldColorMatrix with multiplicity len(path_list).
Wilson Loop¶
gf_avg_wilson_loop_normalized_tr(gf: GaugeField, l: int, t: int) -> float¶
Return the average Wilson loop trace (normalized by Nc=3) for an l x t rectangular loop.
Parameter |
Type |
Description |
|---|---|---|
|
|
Gauge field |
|
|
Spatial extent of the loop |
|
|
Temporal extent of the loop |
Random Color Matrix Field¶
set_g_rand_color_matrix_field(fc: FieldColorMatrix, rng: RngState, sigma: float, n_steps: int = 1)¶
Fill fc with random SU(3) matrices generated via Gaussian smearing
around the identity.
Boundary and Reduction¶
gf_twist_boundary_at_boundary(gf: GaugeField, lmom: float = -0.5, mu: int = 3)¶
Apply a twist boundary condition in direction mu by modifying gf in place.
mk_left_expanded_field(gf) -> FieldColorMatrix¶
Return a left-expanded copy of the gauge field (expansion of 1 in each
direction on the left side). Equivalent to set_left_expanded_gauge_field
in the C++ library.
gf_reduce_half(gf: GaugeField) -> GaugeField¶
Return a new gauge field with half the lattice size in all directions.
Does not modify the input. Can be combined with shifts, e.g.,
gf_reduce_half(gf.shift()).
DWF QED Inverters¶
These functions solve domain-wall fermion (DWF) linear systems with
QED corrections. They require an expanded gauge field gf1 (obtained via
q.mk_left_expanded_field(gf)).
The optional t_wick_phase_factor_arr parameter provides per-timeslice
Wick rotation phase factors for QED photon propagators.
invert_dwf_qed¶
invert_dwf_qed(f_in4d, gf1, mass, m5, ls, *, t_wick_phase_factor_arr=None,
is_dagger=False, stop_rsd=1e-8, max_num_iter=50000) -> FieldComplexD
Solve M * out = in (or M^dag * out = in if is_dagger=True) where M
is the DWF operator with QED corrections. The input f_in4d is a 4-D
fermion field and the output is also 4-D (properly projected from the 5-D
solution).
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
|
— |
4-D source field |
|
|
— |
Left-expanded gauge field |
|
|
— |
Quark mass |
|
|
— |
Domain-wall height |
|
|
— |
Fifth-dimension extent |
|
array or |
|
Per-timeslice Wick phase factors |
|
|
|
Use M^dag if True |
|
|
|
Stopping residual |
|
|
|
Maximum CG iterations |
cg_with_m_dwf_qed¶
cg_with_m_dwf_qed(f_in5d, gf1, mass, m5, ls, *, t_wick_phase_factor_arr=None,
is_dagger=False, stop_rsd=1e-8, max_num_iter=50000) -> FieldComplexD
Solve M^dag M * out = in (or M M^dag * out = in if is_dagger=True).
Input and output are 5-D fermion fields.
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
|
— |
5-D source field |
|
|
— |
Left-expanded gauge field |
|
|
— |
Quark mass |
|
|
— |
Domain-wall height |
|
|
— |
Fifth-dimension extent |
|
array or |
|
Per-timeslice Wick phase factors |
|
|
|
Use M M^dag if True |
|
|
|
Stopping residual |
|
|
|
Maximum CG iterations |
multiply_m_dwf_qed¶
multiply_m_dwf_qed(f_in5d, gf1, mass, m5, ls, *, t_wick_phase_factor_arr=None,
is_dagger=False) -> FieldComplexD
Apply the DWF operator with QED corrections: compute out = M * in (or
out = M^dag * in if is_dagger=True). Input and output are 5-D fields.
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
|
— |
5-D input field |
|
|
— |
Left-expanded gauge field |
|
|
— |
Quark mass |
|
|
— |
Domain-wall height |
|
|
— |
Fifth-dimension extent |
|
array or |
|
Per-timeslice Wick phase factors |
|
|
|
Apply M^dag if True |
Examples¶
Basic Gauge Field Operations¶
import qlat as q
size_node_list = [
[1, 1, 1, 1],
[1, 1, 1, 2],
[1, 1, 1, 4],
]
q.begin_with_mpi(size_node_list)
total_site = q.Coordinate([4, 4, 4, 8])
geo = q.Geometry(total_site)
gf = q.qcd.GaugeField(geo)
rng = q.RngState("test-seed")
gf.set_rand(rng, sigma=0.5, n_step=3)
gf.unitarize()
print(f"plaq = {gf.plaq():.10f}")
print(f"link_tr = {gf.link_trace():.10f}")
gf.show_info()
q.end_with_mpi()
Save and Load Gauge Field (NERSC Format)¶
import qlat as q
size_node_list = [[1, 1, 1, 1]]
q.begin_with_mpi(size_node_list)
total_site = q.Coordinate([4, 4, 4, 8])
geo = q.Geometry(total_site)
gf = q.qcd.GaugeField(geo)
rng = q.RngState("save-load-test")
gf.set_rand(rng)
gf.save("gauge_field.nersc")
gf2 = q.qcd.GaugeField()
gf2.load("gauge_field.nersc")
assert abs(gf.plaq() - gf2.plaq()) < 1e-12
q.end_with_mpi()
Gauge Transformation¶
import qlat as q
size_node_list = [[1, 1, 1, 1]]
q.begin_with_mpi(size_node_list)
total_site = q.Coordinate([4, 4, 4, 8])
geo = q.Geometry(total_site)
gf = q.qcd.GaugeField(geo)
rng = q.RngState("gt-test")
gf.set_rand(rng, sigma=0.3, n_step=3)
gf.unitarize()
plaq_before = gf.plaq()
gt = q.qcd.GaugeTransform(geo)
gt.set_rand(rng, sigma=0.1, n_step=1)
gt.unitarize()
gf_transformed = gt * gf
print(f"plaq before transform = {plaq_before:.10f}")
print(f"plaq after transform = {gf_transformed.plaq():.10f}")
gt_inv = gt.inv()
gf_roundtrip = gt_inv * gf_transformed
print(f"plaq after inverse = {gf_roundtrip.plaq():.10f}")
q.end_with_mpi()
Wilson Lines¶
import qlat as q
size_node_list = [[1, 1, 1, 1]]
q.begin_with_mpi(size_node_list)
total_site = q.Coordinate([4, 4, 4, 8])
geo = q.Geometry(total_site)
gf = q.qcd.GaugeField(geo)
rng = q.RngState("wilson-line")
gf.set_rand(rng, sigma=0.3, n_step=3)
gf.unitarize()
gf_ext = q.mk_left_expanded_field(gf)
mu, nu = 0, 1
path_list = [
[mu, mu, nu, -mu - 1, -mu - 1],
([mu, nu, -mu - 1], [2, 1, 2]),
]
wlf = q.qcd.gf_wilson_lines_no_comm(gf_ext, path_list)
print(f"Wilson line field multiplicity = {wlf.multiplicity}")
q.end_with_mpi()
DWF QED Inversion¶
import qlat as q
size_node_list = [[1, 1, 1, 1]]
q.begin_with_mpi(size_node_list)
total_site = q.Coordinate([4, 4, 4, 8])
geo = q.Geometry(total_site)
# QED gauge field: must be FieldComplexD (not GaugeField)
gf_qed = q.FieldComplexD(geo, 4)
gf_qed.set_unit()
gf1 = q.mk_left_expanded_field(gf_qed)
mass = 0.01
m5 = 1.8
ls = 12
# 4d source field: multiplicity 4 (spin components)
f_in = q.FieldComplexD(geo, 4)
f_in.set_rand(q.RngState("source"))
f_out = q.qcd.invert_dwf_qed(f_in, gf1, mass, m5, ls, stop_rsd=1e-8)
print(f"DWF QED inversion completed")
q.end_with_mpi()