Esempio n. 1
0
    def __call__(self, link, staple, mask):
        verbose = g.default.is_verbose(
            "metropolis"
        )  # need verbosity categories [ performance, progress ]
        project_method = self.params["project_method"]
        step_size = self.params["step_size"]

        number_accept = 0
        possible_accept = 0

        t = g.timer("metropolis")

        t("action")
        action = g.component.real(g.eval(-g.trace(link * g.adj(staple)) *
                                         mask))

        t("lattice")
        V = g.lattice(link)
        V_eye = g.identity(link)

        t("random")
        self.rng.element(V, scale=step_size, normal=True)

        t("update")
        V = g.where(mask, V, V_eye)

        link_prime = g.eval(V * link)
        action_prime = g.component.real(
            g.eval(-g.trace(link_prime * g.adj(staple)) * mask))

        dp = g.component.exp(g.eval(action - action_prime))

        rn = g.lattice(dp)

        t("random")
        self.rng.uniform_real(rn)

        t("random")
        accept = dp > rn
        accept *= mask

        number_accept += g.norm2(accept)
        possible_accept += g.norm2(mask)

        link @= g.where(accept, link_prime, link)

        t()

        g.project(link, project_method)

        # g.message(t)
        if verbose:
            g.message(
                f"Metropolis acceptance rate: {number_accept / possible_accept}"
            )
Esempio n. 2
0
    def __call__(self, link, staple, mask):
        verbose = g.default.is_verbose(
            "su2_heat_bath"
        )  # need verbosity categories [ performance, progress ]
        project_method = self.params["project_method"]

        # params
        niter = self.params["niter"]

        # temporaries
        grid = link.grid
        u2 = g.lattice(grid, g.ot_matrix_su_n_fundamental_group(2))
        u2_eye = g.identity(u2)
        one = g.identity(g.complex(grid))
        zero = g.complex(grid)
        zero[:] = 0
        eps = g.complex(grid)
        eps[:] = grid.precision.eps * 10.0
        xr = [g.complex(grid) for i in range(4)]
        a = [g.complex(grid) for i in range(4)]
        two_pi = g.complex(grid)
        two_pi[:] = 2.0 * np.pi
        accepted = g.complex(grid)
        d = g.complex(grid)
        V_eye = g.identity(link)

        # pauli
        pauli1, pauli2, pauli3 = tuple([g.lattice(u2) for i in range(3)])
        ident = g.identity(u2)
        pauli1[:] = 1j * np.array([[0, 1], [1, 0]], dtype=grid.precision.complex_dtype)
        pauli2[:] = 1j * np.array([[0, 1j], [-1j, 0]], dtype=grid.precision.complex_dtype)
        pauli3[:] = 1j * np.array([[1, 0], [0, -1]], dtype=grid.precision.complex_dtype)

        # counter
        num_sites = round(g.norm2(g.where(mask, one, zero)))

        # shortcuts
        inv = g.component.pow(-1.0)

        # go through subgroups
        for subgroup in link.otype.su2_subgroups():

            V = g.eval(link * g.adj(staple))

            # extract u2 subgroup following Kennedy/Pendleton
            link.otype.block_extract(u2, V, subgroup)
            u2 @= u2 - g.adj(u2) + g.identity(u2) * g.trace(g.adj(u2))
            udet = g.matrix.det(u2)
            adet = g.component.abs(udet)
            nzmask = adet > eps
            u2 @= g.where(nzmask, u2, u2_eye)
            udet = g.where(nzmask, udet, one)
            xi = g.eval(0.5 * g.component.sqrt(udet))
            u2 @= 0.5 * u2 * inv(xi)

            # make sure that su2 subgroup projection worked
            assert g.group.defect(u2) < u2.grid.precision.eps * 10.0

            xi @= 2.0 * xi
            alpha = g.component.real(xi)

            # main loop
            it = 0
            num_accepted = 0
            accepted[:] = 0
            d[:] = 0
            while (num_accepted < num_sites) and (it < niter):
                self.rng.uniform_real(xr, min=0.0, max=1.0)

                xr[1] @= -g.component.log(xr[1]) * inv(alpha)
                xr[2] @= -g.component.log(xr[2]) * inv(alpha)
                xr[3] @= g.component.cos(g.eval(xr[3] * two_pi))
                xr[3] @= xr[3] * xr[3]

                xrsq = g.eval(xr[2] + xr[1] * xr[3])

                d = g.where(accepted, d, xrsq)

                thresh = g.eval(one - d * 0.5)
                xrsq @= xr[0] * xr[0]

                newly_accepted = g.where(xrsq < thresh, one, zero)
                accepted = g.where(mask, g.where(newly_accepted, newly_accepted, accepted), zero)

                num_accepted = round(g.norm2(g.where(accepted, one, zero)))

                it += 1

            if verbose:
                g.message(f"SU(2)-heatbath update needed {it} / {niter} iterations")

            # update link
            a[0] @= g.where(mask, one - d, zero)

            a123mag = g.component.sqrt(g.component.abs(one - a[0] * a[0]))

            phi, cos_theta = g.complex(grid), g.complex(grid)
            self.rng.uniform_real([phi, cos_theta])
            phi @= phi * two_pi
            cos_theta @= (cos_theta * 2.0) - one
            sin_theta = g.component.sqrt(g.component.abs(one - cos_theta * cos_theta))

            a[1] @= a123mag * sin_theta * g.component.cos(phi)
            a[2] @= a123mag * sin_theta * g.component.sin(phi)
            a[3] @= a123mag * cos_theta

            ua = g.eval(a[0] * ident + a[1] * pauli1 + a[2] * pauli2 + a[3] * pauli3)

            b = g.where(mask, g.adj(u2) * ua, ident)
            link.otype.block_insert(V, b, subgroup)

            link @= g.where(accepted, V * link, link)

            # check
            check = g.where(accepted, ua * g.adj(ua) - ident, 0.0 * ident)
            delta = (g.norm2(check) / g.norm2(ident)) ** 0.5
            assert delta < grid.precision.eps * 10.0

            check = g.where(accepted, b * g.adj(b) - ident, 0.0 * ident)
            delta = (g.norm2(check) / g.norm2(ident)) ** 0.5
            assert delta < grid.precision.eps * 10.0

            check = g.where(accepted, V * g.adj(V) - V_eye, 0.0 * V_eye)
            delta = (g.norm2(check) / g.norm2(V_eye)) ** 0.5
            assert delta < grid.precision.eps * 10.0

        # project
        g.project(link, project_method)
Esempio n. 3
0
 def gmin(x, y):
     return g.where(x < y, x, y)
Esempio n. 4
0
 def gmax(x, y):
     return g.where(x > y, x, y)
Esempio n. 5
0
    def __call__(self, link, staple, mask):
        """
        Generate new U(1) links with P(U) = e^{ Re Staple U }
        using the heatbath algorithm of Hattori-Nakajima (hep-lat/9210016),
        which draws a random variable x in (-pi, -pi) from P(x) ~ exp(a cos(x)).
        """
        verbose = g.default.is_verbose(
            "u1_heat_bath"
        )  # need verbosity categories [ performance, progress ]
        assert type(link) == g.lattice and type(staple) == g.lattice

        # component-wise functions needed below
        exp = g.component.exp
        log = g.component.log
        sqrt = g.component.sqrt
        cos = g.component.cos
        tan = g.component.tan
        atan = g.component.atan
        cosh = g.component.cosh
        tanh = g.component.tanh
        atanh = g.component.atanh
        inv = g.component.inv

        # functions needed in Hattori-Nakajima method
        def gmax(x, y):
            return g.where(x > y, x, y)

        def gmin(x, y):
            return g.where(x < y, x, y)

        def h(x):
            return g.eval(
                2.0 * inv(alpha) *
                atanh(g.eval(beta_s * tan(g.eval((2.0 * x - one) * tmp)))))

        def gg(x):
            return exp(g.eval(-a * G(h(x))))

        def G(x):
            return g.eval(one - cos(x) - a_inv * log(
                g.eval(one + (cosh(g.eval(alpha * x)) - one) *
                       inv(g.eval(one + beta)))))

        # temporaries
        a = g.component.abs(staple)  # absolute value of staple
        a_inv = g.eval(inv(a))  # needed several times
        grid = a.grid
        one = g.identity(g.complex(grid))
        zero = g.identity(g.complex(grid))
        zero[:] = 0
        Unew = g.complex(grid)  # proposal for new links
        accepted = g.complex(grid)  # mask for accepted links
        num_sites = round(g.norm2(g.where(mask, one, zero)))
        x1 = g.complex(grid)
        x2 = g.complex(grid)
        nohit = 0  # to compute acceptance ratio

        # parameters of Hattori-Nakajima method
        eps = 0.001
        astar = 0.798953686083986
        amax = gmax(zero, g.eval(a - astar * one))
        delta = g.eval(0.35 * amax + 1.03 * sqrt(amax))
        alpha = gmin(sqrt(g.eval(a * (2.0 - eps))),
                     gmax(sqrt(g.eval(eps * a)), delta))
        beta = g.eval((gmax(
            g.eval(alpha * alpha * a_inv),
            g.eval((cosh(g.eval(np.pi * alpha)) - one) *
                   inv(g.eval(exp(g.eval(2.0 * a)) - one))),
        ) - one))
        beta_s = sqrt(g.eval((one + beta) * inv(g.eval(one - beta))))
        tmp = atan(g.eval(inv(beta_s) * tanh(g.eval(0.5 * np.pi * alpha))))

        # main loop (large optimization potential but not time-critical anyway)
        num_accepted = 0
        accepted[:] = 0
        Unew[:] = 0
        # worst-case acceptance ratio of Hattori-Nakajima is 0.88
        while num_accepted < num_sites:
            self.rng.uniform_real(x1, min=0.0, max=1.0)
            self.rng.uniform_real(x2, min=0.0, max=1.0)
            Unew = g.where(accepted, Unew, exp(g.eval(1j * h(x1))))
            newly_accepted = g.where(x2 < gg(x1), one, zero)
            accepted = g.where(
                mask, g.where(newly_accepted, newly_accepted, accepted), zero)
            num_accepted = round(g.norm2(g.where(accepted, one, zero)))
            nohit += num_sites - num_accepted

        if verbose:
            g.message(
                f"Acceptance ratio for U(1) heatbath update = {num_sites/(num_sites+nohit)}"
            )

        # Unew was drawn with phase angle centered about zero
        # -> need to shift this by phase angle of staple
        # (we update every link, thus accepted = mask)
        link @= g.where(accepted, Unew * staple * a_inv, link)
Esempio n. 6
0
File: core.py Progetto: waterret/gpt
        g.message(f"Test bilinear combination of vector {j}: {eps2}")
        assert eps2 < 1e-13


################################################################################
# Test where
################################################################################
grid = grid_dp
sel = g.complex(grid)
rng.uniform_int(sel, min=0, max=1)

yes = g.vcomplex(grid, 8)
no = g.vcomplex(grid, 8)
rng.cnormal([yes, no])

w = g.where(sel, yes, no)

eps = np.linalg.norm(w[:] - np.where(sel[:] != 0.0, yes[:], no[:])) / np.linalg.norm(
    w[:]
)
g.message(
    f"Test gpt.where <> numpy.where with a selection of {g.norm2(sel)} points: {eps}"
)
assert eps == 0.0


################################################################################
# Test comparators
################################################################################
a = g.complex(grid)
b = g.complex(grid)