def verify_matrix_element(mat, dst, src, tag): src_prime = g.eval(mat * src) dst.checkerboard(src_prime.checkerboard()) X = g.inner_product(dst, src_prime) eps_ref = src.grid.precision.eps * 50.0 if mat.adj_mat is not None: X_from_adj = g.inner_product(src, g.adj(mat) * dst).conjugate() eps = abs(X - X_from_adj) / abs(X) g.message(f"Test adj({tag}): {eps}") assert eps < eps_ref if mat.inv_mat is not None: eps = (g.norm2(src - mat * g.inv(mat) * src) / g.norm2(src))**0.5 g.message(f"Test inv({tag}): {eps}") assert eps < eps_ref Y = g.inner_product(dst, g.inv(g.adj(mat)) * src) Y_from_adj = g.inner_product(src, g.inv(mat) * dst).conjugate() eps = abs(Y - Y_from_adj) / abs(Y) g.message(f"Test adj(inv({tag})): {eps}") assert eps < eps_ref return X
def verify_matrix_element(fermion, dst, src, tag): mat = get_matrix(fermion_dp, tag) src_prime = g.eval(mat * src) dst.checkerboard(src_prime.checkerboard()) X = g.inner_product(dst, src_prime) eps_ref = src.grid.precision.eps * finger_print_tolerance if mat.adj_mat is not None: X_from_adj = g.inner_product(src, g.adj(mat) * dst).conjugate() eps = abs(X - X_from_adj) / abs(X) g.message(f"Test adj({tag}): {eps}") assert eps < eps_ref if mat.inv_mat is not None: eps = (g.norm2(src - mat * g.inv(mat) * src) / g.norm2(src)) ** 0.5 g.message(f"Test inv({tag}): {eps}") assert eps < eps_ref Y = g.inner_product(dst, g.inv(g.adj(mat)) * src) Y_from_adj = g.inner_product(src, g.inv(mat) * dst).conjugate() eps = abs(Y - Y_from_adj) / abs(Y) g.message(f"Test adj(inv({tag})): {eps}") assert eps < eps_ref # do even/odd tests even_odd_operators = {"": ("Mooee", "Meooe")} if tag in even_odd_operators: g.message(f"Test eo versions of {tag}") grid_rb = fermion.F_grid_eo src_p = g.vspincolor(grid_rb) dst_p = g.vspincolor(grid_rb) tag_Mooee, tag_Meooe = even_odd_operators[tag] mat_Mooee = get_matrix(fermion, tag_Mooee) mat_Meooe = get_matrix(fermion, tag_Meooe) for parity in [g.even, g.odd]: g.pick_checkerboard(parity, src_p, src) g.pick_checkerboard(parity, dst_p, src) verify_matrix_element(fermion, dst_p, src_p, tag_Mooee) verify_projected_even_odd(mat, mat_Mooee, dst_p, src_p, src) g.pick_checkerboard(parity.inv(), dst_p, src) verify_matrix_element(fermion, dst_p, src_p, tag_Meooe) verify_projected_even_odd(mat, mat_Meooe, dst_p, src_p, src) # perform derivative tests projected_gradient_operators = {"": "M_projected_gradient"} if tag in projected_gradient_operators and isinstance( fermion, g.qcd.fermion.differentiable_fine_operator ): # Test projected gradient for src^dag M^dag M src g.message(f"Test projected_gradient of {tag} via src^dag M^dag M src") mat_pg = get_matrix(fermion, projected_gradient_operators[tag]) dst_pg = g(mat * src) class df(g.group.differentiable_functional): def __call__(self, Uprime): return g.norm2(get_matrix(fermion.updated(Uprime), tag) * src) def gradient(self, Uprime, dUprime): assert dUprime == Uprime return [ g.qcd.gauge.project.traceless_hermitian(g.eval(a + b)) for a, b in zip(mat_pg(dst_pg, src), mat_pg.adj()(src, dst_pg)) ] dfv = df() dfv.assert_gradient_error(rng, U, U, 1e-3, 1e-6) # Test projected gradient for src^dag G5 M src if isinstance(fermion, g.qcd.fermion.gauge_independent_g5_hermitian): g.message(f"Test projected_gradient of {tag} via src^dag G5 M src") class df(g.group.differentiable_functional): def __call__(self, Uprime): return g.inner_product( src, fermion.G5 * get_matrix(fermion.updated(Uprime), tag) * src ).real def gradient(self, Uprime, dUprime): assert dUprime == Uprime return g.qcd.gauge.project.traceless_hermitian( mat_pg(fermion.G5 * src, src) ) dfv = df() dfv.assert_gradient_error(rng, U, U, 1e-3, 1e-6) g.message(f"Test projected_gradient of {tag} via src^dag M^dag G5 src") class df(g.group.differentiable_functional): def __call__(self, Uprime): return g.inner_product( src, get_matrix(fermion.updated(Uprime), tag).adj() * fermion.G5 * src, ).real def gradient(self, Uprime, dUprime): assert dUprime == Uprime return g.qcd.gauge.project.traceless_hermitian( mat_pg.adj()(src, fermion.G5 * src) ) dfv = df() dfv.assert_gradient_error(rng, U, U, 1e-3, 1e-6) # perform even-odd derivative tests projected_gradient_operators = {"Meooe": "Meooe_projected_gradient"} if tag in projected_gradient_operators and isinstance( fermion, g.qcd.fermion.differentiable_fine_operator ): # Test projected gradient for src_p^dag M^dag M src_p g.message(f"Test projected_gradient of {tag} via src^dag M^dag M src") mat_pg = get_matrix(fermion, projected_gradient_operators[tag]) src_p = g.lattice(fermion.F_grid_eo, fermion.otype) for parity in [g.even, g.odd]: g.pick_checkerboard(parity, src_p, src) dst_p = g(mat * src_p) class df(g.group.differentiable_functional): def __call__(self, Uprime): return g.norm2(get_matrix(fermion.updated(Uprime), tag) * src_p) def gradient(self, Uprime, dUprime): assert dUprime == Uprime R = g.group.cartesian(Uprime) for r, x in zip( R + R, mat_pg(dst_p, src_p) + mat_pg.adj()(src_p, dst_p) ): g.set_checkerboard( r, g.qcd.gauge.project.traceless_hermitian(x) ) return R dfv = df() dfv.assert_gradient_error(rng, U, U, 1e-3, 1e-6) return X
xc = (2, 3, 1, 5) x = np.array(list(xc)) ref = np.exp(1j * np.dot(p, x)) * l_dp[xc] val = g.eval(exp_ixp * l_dp)[xc] eps = g.norm2(ref - val) g.message("Reference value test: ", eps) assert eps < 1e-25 # single/double eps = g.norm2(exp_ixp * l_sp - g.convert(exp_ixp * l_dp, g.single)) / g.norm2(l_sp) g.message("Momentum phase test single/double: ", eps) assert eps < 1e-10 eps = g.norm2(g.inv(exp_ixp) * exp_ixp * l_dp - l_dp) / g.norm2(l_dp) g.message("Momentum inverse test: ", eps) assert eps < 1e-20 eps = g.norm2(g.adj(exp_ixp) * exp_ixp * l_dp - l_dp) / g.norm2(l_dp) g.message("Momentum adj test: ", eps) assert eps < 1e-20 eps = g.norm2(g.adj(exp_ixp * exp_ixp) * exp_ixp * exp_ixp * l_dp - l_dp) / g.norm2(l_dp) g.message("Momentum adj test (2): ", eps) assert eps < 1e-20 ################################################################################ # Test FFT ################################################################################
def gradient(self, fields, dfields): return g( g.inv(self.fft) * (self.weight * len(dfields)) * self.fft * self.base.gradient(fields, dfields))