def __init__(self, op, bs): self.op = op self.op_blk = [] dt = -gpt.time() # thanks to double copy inside operator, U only temporary Ublk = [sap_blk(op.U_grid, bs, eo) for eo in range(2)] U = [gpt.mcolor(Ublk[0].grid) for _ in range(4)] for eo in range(2): Ucoor = Ublk[eo].coor(op.U_grid) for mu in range(4): U[mu][Ublk[eo].pos] = op.U[mu][Ucoor] Ublk[eo].set_BC_Ufld(U) self.op_blk.append(op.updated(U)) if self.op.F_grid.nd == len(bs) + 1: _bs = [self.op.F_grid.fdimensions[0]] + bs else: _bs = bs blk = [sap_blk(self.op.F_grid, _bs, eo) for eo in range(2)] self.pos = blk[0].pos self.pos.flags["WRITEABLE"] = False self.coor = [blk[eo].coor(op.F_grid) for eo in range(2)] for eo in range(2): self.coor[eo].flags["WRITEABLE"] = False dt += gpt.time() gpt.message(f"SAP Initialized in {dt:g} secs")
def mk_gpt_field(ctype, geo): if ctype == "ColorMatrix": return g.mcolor(mk_grid(geo)) elif ctype == "WilsonMatrix": return g.mspincolor(mk_grid(geo)) elif ctype == "WilsonVector": return g.vspincolor(mk_grid(geo)) else: raise Exception("make_gpt_field")
def gpt_from_qlat_gauge_field(gf): assert isinstance(gf, q.GaugeField) geo = gf.geo() ctype = "ColorMatrix" total_site = geo.total_site() multiplicity = 1 tag = "gpt_from_qlat" plan = get_qlat_gpt_copy_plan(ctype, total_site, multiplicity, tag) fs = [None] * 4 q.split_fields(fs, gf) assert len(fs) == 4 grid = mk_grid(geo) gpt_gf = [g.mcolor(grid) for i in range(4)] for i in range(4): plan(gpt_gf[i], fs[i].mview()) return gpt_gf
g.message("Expected correlator eps: ", eps) assert eps < 1e-5 # split grid solver check slv_split_eo1 = w.propagator( inv.preconditioned( pc.eo1_ne(), inv.split(cg, mpi_split=g.default.get_ivec("--mpi_split", None, 4)))) dst_split = g.mspincolor(grid) dst_split @= slv_split_eo1 * src eps2 = g.norm2(dst_split - dst_eo1) / g.norm2(dst_eo1) g.message(f"Split grid solver check {eps2}") assert eps2 < 1e-12 # gauge transformation check V = rng.element(g.mcolor(grid)) prop_on_transformed_U = w.updated(g.qcd.gauge.transformed(U, V)).propagator( inv.preconditioned(pc.eo2_ne(), cg)) prop_transformed = g.qcd.gauge.transformed(slv_eo2, V) src = rng.cnormal(g.vspincolor(grid)) dst1 = g(prop_on_transformed_U * src) dst2 = g(prop_transformed * src) eps2 = g.norm2(dst1 - dst2) / g.norm2(dst1) g.message(f"Gauge transformation check {eps2}") assert eps2 < 1e-12 # test twisted boundary momentum phase U_unit = g.qcd.gauge.unit(grid) theta = 0.91231 quark0 = g.qcd.fermion.mobius( U_unit,
# now project to algebra and make sure it is a linear combination of # the provided generators n0 = g.norm2(algebra) algebra2.otype.coordinates( algebra2, g.component.real(algebra.otype.coordinates(algebra))) algebra -= algebra2 eps = (g.norm2(algebra) / n0)**0.5 g.message(f"Test representation: {eps}") assert eps < eps_ref ################################################################################ # Test projection schemes on promoting SP to DP group membership ################################################################################ V0 = g.convert(rng.element(g.mcolor(grid_sp)), g.double) for method in ["defect_left", "defect_right"]: V = g.copy(V0) I = g.identity(V) I_s = g.identity(g.complex(grid_dp)) for i in range(3): eps_uni = (g.norm2(g.adj(V) * V - I) / g.norm2(I))**0.5 eps_det = (g.norm2(g.matrix.det(V) - I_s) / g.norm2(I_s))**0.5 g.message( f"Before {method} iteration {i}, unitarity defect: {eps_uni}, determinant defect: {eps_det}" ) g.project(V, method) assert eps_uni < 1e-14 and eps_det < 1e-14 ################################################################################ # Test SU(2) fundamental and conversion to adjoint
eps2 = g.norm2(vc2 - vc3) / g.norm2(vc2) assert eps2 < 1e-10 # test transpose and adjoint of mcomplex mc_adj = g.eval(g.adj(mc)) mc_transpose = g.eval(g.transpose(mc)) mc_array = mc[0, 0, 0, 0].array mc_adj_array = mc_adj[0, 0, 0, 0].array mc_transpose_array = mc_transpose[0, 0, 0, 0].array assert np.linalg.norm(mc_adj_array - mc_array.transpose().conjugate()) < 1e-13 assert np.linalg.norm(mc_transpose_array - mc_array.transpose()) < 1e-13 assert g.norm2(g.adj(mc[0, 0, 0, 0]) - mc_adj[0, 0, 0, 0]) < 1e-25 assert g.norm2(g.transpose(mc[0, 0, 0, 0]) - mc_transpose[0, 0, 0, 0]) < 1e-25 # assign entire lattice cm = g.mcolor(grid) cv = g.vcolor(grid) cv[:] = 0 cm[:] = 0 # assign position and tensor index cv[0, 0, 0, 0, 0] = 1 cv[0, 0, 0, 0, 1] = 2 # read out entire tensor at position assert g.norm2(cv[0, 0, 0, 0] - g.vcolor([1, 2, 0])) < 1e-13 # set three internal indices to a vector cm[0, 0, 0, 0, [[0, 1], [2, 2], [0, 0]]] = g.vcolor([7, 6, 5]) assert g.norm2(cm[0, 0, 0, 0] - g.mcolor([[5, 7, 0], [0, 0, 0], [0, 0, 6]])) < 1e-13
def project_to_suN_step(dest, unprojected): t_total = -gpt.time() t_product, t_separate, t_merge, t_su2extract, t_su2fill, t_calcnorm, t_applynorm = [ 0.0 for _ in range(7) ] vol = dest.grid.fsites n_colors = dest.otype.Nc tmp = gpt.mcolor(dest.grid) zero = gpt.complex(dest.grid) zero[:] = 0.0 one = gpt.complex(dest.grid) one[:] = 1.0 square = gpt.component.pow(2) norm = gpt.complex(dest.grid) for su2_index in range(n_colors * (n_colors - 1) // 2): index, i1, i2 = 0, None, None for ii in range(1, n_colors): for jj in range(n_colors - ii): if index == su2_index and i1 is None: i1 = jj i2 = ii + jj index += 1 t_product -= gpt.time() tmp @= dest * unprojected t_product += gpt.time() t_separate -= gpt.time() tmp_sep = gpt.separate_color(tmp) t_separate += gpt.time() t_su2extract -= gpt.time() su2_components = extract_su2_components(tmp_sep, [i1, i2]) t_su2extract += gpt.time() t_calcnorm -= gpt.time() norm @= gpt.component.inv( gpt.component.sqrt( gpt.eval(su2_components[0] * su2_components[0] + su2_components[1] * su2_components[1] + su2_components[2] * su2_components[2] + su2_components[3] * su2_components[3]))) t_calcnorm += gpt.time() t_applynorm -= gpt.time() su2_components[0] @= su2_components[0] * norm su2_components[1] @= -su2_components[1] * norm su2_components[2] @= -su2_components[2] * norm su2_components[3] @= -su2_components[3] * norm t_applynorm += gpt.time() t_su2fill -= gpt.time() fill_su2_components_into_suN(tmp_sep, su2_components, [i1, i2], cache=[zero, one]) t_su2fill += gpt.time() t_merge -= gpt.time() gpt.merge_color(tmp, tmp_sep) t_merge += gpt.time() t_product -= gpt.time() dest @= tmp * dest t_product += gpt.time() t_total += gpt.time() if gpt.default.is_verbose("project_to_suN_step"): t_profiled = t_product + t_separate + t_merge + t_su2extract + t_su2fill + t_calcnorm + t_applynorm t_unprofiled = t_total - t_profiled gpt.message("project_to_suN_step: total", t_total, "s") gpt.message("project_to_suN_step: t_product", t_product, "s", round(100 * t_product / t_total, 1), "%") gpt.message("project_to_suN_step: t_separate", t_separate, "s", round(100 * t_separate / t_total, 1), "%") gpt.message("project_to_suN_step: t_merge", t_merge, "s", round(100 * t_merge / t_total, 1), "%") gpt.message("project_to_suN_step: t_su2extract", t_su2extract, "s", round(100 * t_su2extract / t_total, 1), "%") gpt.message("project_to_suN_step: t_su2fill", t_su2fill, "s", round(100 * t_su2fill / t_total, 1), "%") gpt.message("project_to_suN_step: t_calcnorm", t_calcnorm, "s", round(100 * t_calcnorm / t_total, 1), "%") gpt.message("project_to_suN_step: t_applynorm", t_applynorm, "s", round(100 * t_applynorm / t_total, 1), "%") gpt.message("project_to_suN_step: unprofiled", t_unprofiled, "s", round(100 * t_unprofiled / t_total, 1), "%")
#!/usr/bin/env python3 # # Authors: Christoph Lehner 2020 # import gpt as g import numpy as np # load configuration rng = g.random("test") L = [8, 8, 8, 16] grid = g.grid(L, g.double) U = g.qcd.gauge.random(grid, rng) U_unit = g.qcd.gauge.unit(grid) V = rng.lie(g.mcolor(grid)) # Test covariance of gauss smearing operator smear = g.create.smear.gauss(U, sigma=0.5, steps=3, dimensions=[0, 1, 2]) U_transformed = g.qcd.gauge.transformed(U, V) smear_transformed = g.create.smear.gauss(U_transformed, sigma=0.5, steps=3, dimensions=[0, 1, 2]) src = g.mspincolor(grid) rng.cnormal(src) dst1 = g(V * smear * src) dst2 = g(smear_transformed * V * src) eps2 = g.norm2(dst1 - dst2) / g.norm2(dst1) g.message(f"Covariance test: {eps2}") assert eps2 < 1e-29
#!/usr/bin/env python3 # # Authors: Christoph Lehner 2020 # import gpt as g import numpy as np grid_dp = g.grid([8, 4, 4, 4], g.double) grid_sp = g.grid([8, 4, 4, 4], g.single) for grid, eps in [(grid_dp, 1e-14), (grid_sp, 1e-6)]: rng = g.random("test") m = g.mcolor(grid) # first test matrix operators rng.lie(m) m2 = g.matrix.exp(g.matrix.log(m)) eps2 = g.norm2(m - m2) / g.norm2(m) g.message(eps2) assert eps2 < eps**2.0 # then test component operators c = g.component def inv(x): return x**-1.0 def pow3p45(x): return x**3.45 for op in [
"--------------------------------------------------------------------------------" ) g.message(" Summary of solver tests") g.message( "--------------------------------------------------------------------------------" ) g.message("%-38s %-25s %-25s" % ("Solver name", "Solve time / s", "Difference with CG result")) for t in timings: g.message("%-38s %-25s %-25s" % (t, timings[t], resid[t])) #### # Minimal Residual Extrapolation (Chronological Inverter) #### g.message("Minimal Residual Extrapolation") U_eps = [[g(u * rng.element(g.mcolor(U[0].grid), scale=1e-3)) for u in U] for i in range(3)] w_eps = [w.updated(u) for u in U_eps] inv_cg = inv.cg({"eps": 1e-8, "maxiter": 500}) solution_space = [] inv_chron = inv.solution_history( solution_space, inv.sequence(inv.subspace_minimal_residual(solution_space), inv_pc(eo2, inv_cg)), 2, ) history = [] for we in w_eps:
def quark_contract_xx(mspincolor1, mspincolor2, components): """ This routine is written for Nc = 3 y^{k2, k1} = \\sum_{i1, i2, j1, j2} \\epsilon^{i1, j1, k1} \\epsilon^{i2, j2, k2} xc1^{i1, i2} xc2^{j1, j2} Permutations: +(0, 1, 2), +(1, 2, 0), +(2, 0, 1), -(1, 0, 2), -(0, 2, 1), -(2, 1, 0) i.e. - y^{0, 0} = \\epsilon^{i1, j1, 0} \\epsilon^{i2, j2, 0} xc1^{i1, i2} xc2^{j1, j2} Permutations: +(1, 2, 0), -(2, 1, 0); +(1, 2, 0), -(2, 1, 0) - y^{0, 1} = \\epsilon^{i1, j1, 1} \\epsilon^{i2, j2, 0} xc1^{i1, i2} xc2^{j1, j2} Permutations: +(2, 0, 1), -(0, 2, 1); +(1, 2, 0), -(2, 1, 0) - y^{0, 2} = \\epsilon^{i1, j1, 2} \\epsilon^{i2, j2, 0} xc1^{i1, i2} xc2^{j1, j2} Permutations: +(0, 1, 2), -(1, 0, 2) +(1, 2, 0), -(2, 1, 0) - y^{1, 0} = \\epsilon^{i1, j1, 0} \\epsilon^{i2, j2, 1} xc1^{i1, i2} xc2^{j1, j2} Permutations: +(1, 2, 0), -(2, 1, 0) +(2, 0, 1), -(0, 2, 1) - y^{1, 1} = \\epsilon^{i1, j1, 1} \\epsilon^{i2, j2, 1} xc1^{i1, i2} xc2^{j1, j2} Permutations: +(2, 0, 1), -(0, 2, 1) +(2, 0, 1), -(0, 2, 1) - y^{1, 2} = \\epsilon^{i1, j1, 2} \\epsilon^{i2, j2, 1} xc1^{i1, i2} xc2^{j1, j2} Permutations: +(0, 1, 2), -(1, 0, 2) +(2, 0, 1), -(0, 2, 1) - y^{2, 0} = \\epsilon^{i1, j1, 0} \\epsilon^{i2, j2, 2} xc1^{i1, i2} xc2^{j1, j2} Permutations: +(1, 2, 0), -(2, 1, 0) +(0, 1, 2), -(1, 0, 2) - y^{2, 1} = \\epsilon^{i1, j1, 1} \\epsilon^{i2, j2, 2} xc1^{i1, i2} xc2^{j1, j2} Permutations: +(2, 0, 1), -(0, 2, 1) +(0, 1, 2), -(1, 0, 2) - y^{2, 2} = \\epsilon^{i1, j1, 2} \\epsilon^{i2, j2, 2} xc1^{i1, i2} xc2^{j1, j2} Permutations: +(0, 1, 2), -(1, 0, 2) +(0, 1, 2), -(1, 0, 2) """ t_separatespin, t_separatecolor, t_create, t_bilinear, t_merge = 0.0, 0.0, 0.0, 0.0, 0.0 t_start = gpt.time() comps1, comps2 = dict(), dict() for mspincolor, comps in [[mspincolor1, comps1], [mspincolor2, comps2]]: if isinstance(mspincolor, gpt.lattice): t_separatespin -= gpt.time() spin_separated = gpt.separate_spin(mspincolor) t_separatespin += gpt.time() for spinkey in spin_separated: t_separatecolor -= gpt.time() comps[spinkey] = gpt.separate_color(spin_separated[spinkey]) t_separatecolor += gpt.time() elif isinstance(mspincolor, dict): for spinkey in mspincolor: n_keys = len(mspincolor[spinkey]) n_colors = np.sqrt(n_keys) assert n_colors == int(n_colors) assert (int(n_colors) - 1, int(n_colors) - 1) in mspincolor[spinkey] comps[spinkey] = mspincolor[spinkey] grid = comps1[0, 0][0, 0].grid t_create -= gpt.time() dst = gpt.mspincolor(grid) spinsep_dst = {(ii // 4, ii % 4): gpt.mcolor(grid) for ii in range(16)} bilinear_result = [gpt.complex(grid) for _ in range(9)] t_create += gpt.time() leftbase = np.array( [[4, 5, 7, 8], [7, 8, 1, 2], [1, 2, 4, 5], [5, 3, 8, 6], [8, 6, 2, 0], [2, 0, 5, 3], [3, 4, 6, 7], [6, 7, 0, 1], [0, 1, 3, 4]], dtype=np.int32) rightbase = np.array( [[8, 7, 5, 4], [2, 1, 8, 7], [5, 4, 2, 1], [6, 8, 3, 5], [0, 2, 6, 8], [3, 5, 0, 2], [7, 6, 4, 3], [1, 0, 7, 6], [4, 3, 1, 0]], dtype=np.int32) for spin_key in components.keys(): lefts, rights = [], [] bilin_coeffs, bilin_leftbasis, bilin_rightbasis = [], [], [] for nn, comps in enumerate(components[spin_key]): c0_0, c0_1, c1_0, c1_1 = comps for ii in range(9): lefts.append(comps1[c0_0, c0_1][ii // 3, ii % 3]) rights.append(comps2[c1_0, c1_1][ii // 3, ii % 3]) bilin_coeffs = np.append(bilin_coeffs, [1.0, -1.0, -1.0, +1.0]) bilin_leftbasis.append(leftbase + nn * 9) bilin_rightbasis.append(rightbase + nn * 9) bilin_coeffs = np.array([bilin_coeffs for _ in range(9)], dtype=np.int32) bilin_leftbasis = np.concatenate(bilin_leftbasis, axis=1) bilin_rightbasis = np.concatenate(bilin_rightbasis, axis=1) t_bilinear -= gpt.time() gpt.bilinear_combination(bilinear_result, lefts, rights, bilin_coeffs, bilin_leftbasis, bilin_rightbasis) t_bilinear += gpt.time() cmat_dict = dict() for ii in range(9): cmat_dict[ii // 3, ii % 3] = bilinear_result[ii] t_merge -= gpt.time() gpt.merge_color(spinsep_dst[spin_key], cmat_dict) t_merge += gpt.time() t_merge -= gpt.time() gpt.merge_spin(dst, spinsep_dst) t_merge += gpt.time() t_total = gpt.time() - t_start t_profiled = t_separatespin + t_separatecolor + t_create + t_bilinear + t_merge if gpt.default.is_verbose("quark_contract_xx"): gpt.message("quark_contract_xx: total", t_total, "s") gpt.message("quark_contract_xx: t_separatespin", t_separatespin, "s", round(100 * t_separatespin / t_total, 1), "%") gpt.message("quark_contract_xx: t_separatecolor", t_separatecolor, "s", round(100 * t_separatecolor / t_total, 1), "%") gpt.message("quark_contract_xx: t_create", t_create, "s", round(100 * t_create / t_total, 1), "%") gpt.message("quark_contract_xx: t_bilinear", t_bilinear, "s", round(100 * t_bilinear / t_total, 1), "%") gpt.message("quark_contract_xx: t_merge", t_merge, "s", round(100 * t_merge / t_total, 1), "%") gpt.message("quark_contract_xx: unprofiled", t_total - t_profiled, "s", round(100 * (t_total - t_profiled) / t_total, 1), "%") return dst
assert eps2 < 1e-10 # test transpose and adjoint of mcomplex mc_adj = g.eval(g.adj(mc)) mc_transpose = g.eval(g.transpose(mc)) mc_array = mc[0, 0, 0, 0].array mc_adj_array = mc_adj[0, 0, 0, 0].array mc_transpose_array = mc_transpose[0, 0, 0, 0].array assert np.linalg.norm(mc_adj_array - mc_array.transpose().conjugate()) < 1e-13 assert np.linalg.norm(mc_transpose_array - mc_array.transpose()) < 1e-13 assert g.norm2(g.adj(mc[0, 0, 0, 0]) - mc_adj[0, 0, 0, 0]) < 1e-25 assert g.norm2(g.transpose(mc[0, 0, 0, 0]) - mc_transpose[0, 0, 0, 0]) < 1e-25 # assign entire lattice cm = g.mcolor(grid) cv = g.vcolor(grid) cv[:] = 0 cm[:] = 0 # assign position and tensor index cv[0, 0, 0, 0, 0] = 1 cv[0, 0, 0, 0, 1] = 2 # read out entire tensor at position assert g.norm2(cv[0, 0, 0, 0] - g.vcolor([1, 2, 0])) < 1e-13 # set three internal indices to a vector cm[0, 0, 0, 0, [[0, 1], [2, 2], [0, 0]]] = g.vcolor([7, 6, 5]) assert g.norm2(cm[0, 0, 0, 0] - g.mcolor([[5, 7, 0], [0, 0, 0], [0, 0, 6]])) < 1e-13
if p_mpi_split is None: g.message("Need to provide mpi_split") sys.exit(1) # create rng if needed rng = None if p_rng_seed is None else g.random(p_rng_seed) # load source U = g.load(p_source) # split in time Nt = U[0].grid.gdimensions[3] g.message(f"Separate {Nt} time slices") Usep = [g.separate(u, 3) for u in U[0:3]] Vt = [g.mcolor(Usep[0][0].grid) for t in range(Nt)] cache = {} split_grid = Usep[0][0].grid.split(p_mpi_split, Usep[0][0].grid.fdimensions) g.message("Split grid") Usep_split = [g.split(Usep[mu], split_grid, cache) for mu in range(3)] Vt_split = g.split(Vt, split_grid, cache) # optimizer opt = g.algorithms.optimize cg = opt.non_linear_cg( maxiter=p_maxiter_cg, eps=p_eps, step=p_step, line_search=opt.line_search_quadratic, beta=opt.polak_ribiere,
val = g.eval(exp_ixp_rel * l_dp)[xc] eps = g.norm2(ref - val) g.message("Reference value test (arbitrary momentum with origin): ", eps) assert eps < 1e-25 ################################################################################ # Test slice sums ################################################################################ for lattice_object in [ g.complex(grid_dp), g.vcomplex(grid_dp, 10), g.vspin(grid_dp), g.vcolor(grid_dp), g.vspincolor(grid_dp), g.mspin(grid_dp), g.mcolor(grid_dp), g.mspincolor(grid_dp), ]: g.message(f"Testing slice with random {lattice_object.describe()}") obj_list = [g.copy(lattice_object) for _ in range(3)] rng.cnormal(obj_list) for dimension in range(4): tmp = g.slice(obj_list, dimension) full_sliced = np.array([[g.util.tensor_to_value(v) for v in obj] for obj in tmp]) for n, obj in enumerate(obj_list): tmp = g.slice(obj, dimension) sliced = np.array([g.util.tensor_to_value(v) for v in tmp]) assert np.allclose(full_sliced[n], sliced, atol=0.0, rtol=1e-13)