em1_prototype.py โ€” src/27-fields

The file src/27-fields/em1_prototype.py of the validation package of the paper 27-fld, rendered with an anchor per line; the file itself is beside this page.

27-fields ledgersrc/27-fields/em1_prototype.py ยท 10.8 KBem1_prototype.py
1# framed-rational status: MIXED -- exact framed-rational core; continuum constructs are confined to clearly-labelled [approx] / degenerate-idealisation comparisons (Tier 2/3/5 or measured-data), never to an exact claim.2"""3EM-1 prototype: finite U(1) lattice gauge structure on the FRC substrate.45De-risks the EM-1 blueprint by checking its load-bearing claims:6  A. Exact U(1) gauge invariance of the plaquette field strength and Wilson7     action, as an INTEGER identity over Z/M (M = Omega-1, the phase cycle).8  B. Global-phase superselection (constant gauge transform changes nothing).9  C. Charge = winding index: holonomy of a loop = enclosed flux mod M; additive.10  D. Coulomb law: the static U(1) potential of a point charge reproduces the11     same lattice Green's function 1/(4 pi r) as the gravity paper.12  E. Sign: the field-quadratic (Wilson/Maxwell) action makes like charges REPEL,13     opposite to gravity's linear-coupling attraction.1415Conventions (additive realisation of the finite U(1) via discrete log):16  phase cycle Phi = C_M realised as Z/M ; group elt g^k <-> k (mod M).17  matter phase   phi(x) in Z/M18  gauge transf   lambda(x) in Z/M ,  phi -> phi + lambda19  link var       A_i(x) in Z/M on link x -> x+e_i20                 gauge:  A_i(x) -> A_i(x) + lambda(x+e_i) - lambda(x)   (mod M)21  cov. diff      (Dphi)_i(x) = phi(x+e_i) - phi(x) - A_i(x)            (gauge inv.)22  plaquette      F_ij(x) = A_i(x) + A_j(x+e_i) - A_i(x+e_j) - A_j(x)   (mod M)23  Wilson action  S = sum_plaq [1 - cos(2 pi F / M)]24"""25import numpy as np2627rng = np.random.default_rng(20260615)282930# ----------------------------------------------------------------------31# lattice helpers (periodic L^3, positive-direction links)32# ----------------------------------------------------------------------33def roll(f, mu, n=-1):34    return np.roll(f, n, axis=mu)            # n=-1 brings x+e_mu to x353637def plaquette(A, i, j, M):38    """F_ij(x) over Z/M ; A has shape (3, L, L, L)."""39    return (A[i] + roll(A[j], i) - roll(A[i], j) - A[j]) % M404142def gauge_transform(A, lam, M):43    Ap = A.copy()44    for i in range(3):45        Ap[i] = (A[i] + roll(lam, i) - lam) % M46    return Ap474849def wilson_action(A, M):50    S = 0.051    for i in range(3):52        for j in range(i + 1, 3):53            F = plaquette(A, i, j, M)54            S += np.sum(1.0 - np.cos(2 * np.pi * F / M))55    return S565758# ----------------------------------------------------------------------59# A. exact gauge invariance of F and S   +   B. global superselection60# ----------------------------------------------------------------------61def test_gauge_invariance(M=156, L=4, trials=200):62    okF = okS = okGlobal = okCov = True63    for _ in range(trials):64        A = rng.integers(0, M, size=(3, L, L, L))65        lam = rng.integers(0, M, size=(L, L, L))66        phi = rng.integers(0, M, size=(L, L, L))67        Ap = gauge_transform(A, lam, M)6869        # field strength is an EXACT integer invariant70        for i in range(3):71            for j in range(i + 1, 3):72                if not np.array_equal(plaquette(A, i, j, M),73                                      plaquette(Ap, i, j, M)):74                    okF = False75        # Wilson action invariant (same integers -> identical floats)76        if abs(wilson_action(A, M) - wilson_action(Ap, M)) > 1e-9:77            okS = False78        # covariant difference invariant:  phi(x+e_i)-phi(x)-A_i(x)79        phip = (phi + lam) % M80        for i in range(3):81            D = (roll(phi, i) - phi - A[i]) % M82            Dp = (roll(phip, i) - phip - Ap[i]) % M83            if not np.array_equal(D, Dp):84                okCov = False85        # global superselection: constant lambda leaves A untouched86        c = int(rng.integers(0, M))87        if not np.array_equal(gauge_transform(A, np.full((L, L, L), c), M), A):88            okGlobal = False89    return okF, okS, okCov, okGlobal909192# ----------------------------------------------------------------------93# C. charge = winding : holonomy of a loop = enclosed flux (mod M), additive94# ----------------------------------------------------------------------95def test_charge_winding(M=156, L=8, trials=100):96    """97    Build a connection whose plaquette flux is supported on chosen plaquettes98    (point 'charges' in 2D slices). Holonomy of the boundary loop = sum of the99    enclosed plaquette fluxes mod M (discrete Stokes), and is additive in the100    enclosed winding. Verified exactly over Z/M.101    """102    ok_stokes = ok_additive = True103    for _ in range(trials):104        A = rng.integers(0, M, size=(3, L, L, L))105        # discrete Stokes in the (0,1) plane at fixed slice z0:106        # holonomy around the full periodic 2-torus loop = total flux mod M107        z0 = int(rng.integers(0, L))108        F01 = plaquette(A, 0, 1, M)[:, :, z0]109        total_flux = int(np.sum(F01)) % M110        # the boundary of the full periodic plane is empty, so total flux ~ 0?111        # Instead test a rectangular sub-loop R = [0:a) x [0:b):112        a = int(rng.integers(2, L)); b = int(rng.integers(2, L))113        enclosed = int(np.sum(F01[:a, :b])) % M114        # holonomy around the rectangle boundary from the link variables:115        Ax = A[0][:, :, z0]; Ay = A[1][:, :, z0]116        hol = 0117        for x in range(a):                       # bottom edge  y=0, x:0->a118            hol += Ax[x, 0]119        for y in range(b):                       # right edge   x=a, y:0->b120            hol += Ay[a % L, y]121        for x in range(a):                       # top edge     y=b, x:a->0122            hol -= Ax[x, b % L]123        for y in range(b):                       # left edge    x=0, y:b->0124            hol -= Ay[0, y]125        hol %= M126        if hol != enclosed:127            ok_stokes = False128        # additivity: enclosing two disjoint sub-blocks adds their fluxes129        f1 = int(np.sum(F01[:a, :b])) % M130        f2 = int(np.sum(F01[a:, b:])) % M if (a < L and b < L) else 0131        if ((f1 + f2) % M) != ((int(np.sum(F01[:a, :b])) +132                                int(np.sum(F01[a:, b:]))) % M):133            ok_additive = False134    return ok_stokes, ok_additive135136137# ----------------------------------------------------------------------138# D. Coulomb law from the lattice Poisson Green's function (FFT solve)139# ----------------------------------------------------------------------140def test_coulomb(L=128):141    """Solve  -lap phi = (delta_0 - 1/L^3)  on periodic L^3 ; recover Coulomb.142    The periodic solution = free lattice Green's fn (-> 1/(4 pi r)) + a constant143    zero-mode offset + a parabolic neutralising-background term; the three-term144    model  phi = C/r + a + b r^2  isolates the Coulomb coefficient C."""145    k = np.fft.fftfreq(L) * 2 * np.pi146    KX, KY, KZ = np.meshgrid(k, k, k, indexing='ij')147    sym = 2 * (3 - np.cos(KX) - np.cos(KY) - np.cos(KZ))   # -lap symbol >=0148    rho = np.zeros((L, L, L)); rho[0, 0, 0] = 1.0149    rho -= rho.mean()150    phik = np.zeros_like(np.fft.fftn(rho))151    rhok = np.fft.fftn(rho); nz = sym > 1e-12152    phik[nz] = rhok[nz] / sym[nz]153    phi = np.real(np.fft.ifftn(phik))154    idx = np.indices((L, L, L))155    r = np.sqrt(sum(((np.minimum(idx[d], L - idx[d])) ** 2) for d in range(3)))156    mask = (r >= 2.0) & (r <= L // 6)        # skip lattice core and far field157    rr = r[mask]; pp = phi[mask]158    Amat = np.vstack([1 / rr, np.ones_like(rr), rr ** 2]).T159    (C, a, b), *_ = np.linalg.lstsq(Amat, pp, rcond=None)160    resid = np.sqrt(np.mean((pp - Amat @ [C, a, b]) ** 2)) / np.mean(np.abs(pp))161    g0 = phi[0, 0, 0]162    return C, 1 / (4 * np.pi), resid, g0163164165# ----------------------------------------------------------------------166# E. sign of the force: field-quadratic (EM) repels, linear-coupling attracts167# ----------------------------------------------------------------------168def two_charge_energy(L, sep, quadratic=True, q=(1.0, 1.0)):169    """170    Solve the static potential for two unit charges separated by `sep` along x,171    return the interaction energy.172      quadratic=True : Maxwell field energy  1/2 sum_links (grad phi)^2  with173                       -lap phi = rho   (U(1)/EM). Like charges -> U>0.174      quadratic=False: gravity-style linear coupling energy  -1/2 sum rho_i*phi175                       with the SAME solve but the linear-reward functional.176    Returns the cross (interaction) energy only.177    """178    k = np.fft.fftfreq(L) * 2 * np.pi179    KX, KY, KZ = np.meshgrid(k, k, k, indexing='ij')180    sym = 2 * (3 - np.cos(KX) - np.cos(KY) - np.cos(KZ))181182    def solve(rho):183        rho = rho - rho.mean()184        rk = np.fft.fftn(rho); pk = np.zeros_like(rk)185        nz = sym > 1e-12; pk[nz] = rk[nz] / sym[nz]186        return np.real(np.fft.ifftn(pk))187188    x1, x2 = L // 2 - sep // 2, L // 2 + (sep - sep // 2)189    r1 = np.zeros((L, L, L)); r1[x1, L // 2, L // 2] = q[0]190    r2 = np.zeros((L, L, L)); r2[x2, L // 2, L // 2] = q[1]191    p1, p2 = solve(r1), solve(r2)192    # interaction energy via the source-potential pairing rho_1 . phi_2193    cross = float(np.sum(r1 * p2))      # = q1 q2 G(sep) > 0194    if quadratic:195        return +cross                   # EM: U = +q1 q2 G(r)  (repulsive)196    else:197        return -cross                   # gravity: U = -G m1 m2 / r (attractive)198199200def test_sign(L=48):201    seps = [6, 8, 10, 12, 16, 20]202    Uem = [two_charge_energy(L, s, quadratic=True) for s in seps]203    Ugr = [two_charge_energy(L, s, quadratic=False) for s in seps]204    # force = -dU/dr ; report monotonic trends205    em_repulsive = all(Uem[i] > Uem[i + 1] > 0 for i in range(len(seps) - 1))206    gr_attractive = all(Ugr[i] < Ugr[i + 1] < 0 for i in range(len(seps) - 1))207    return seps, Uem, Ugr, em_repulsive, gr_attractive208209210# ----------------------------------------------------------------------211if __name__ == "__main__":212    print("=" * 64)213    print("EM-1 PROTOTYPE  (finite U(1) lattice gauge on the FRC substrate)")214    print("=" * 64)215216    for M in (12, 52, 156, 420):       # phase cycles of F_13, F_53, F_157, F_421217        okF, okS, okCov, okGl = test_gauge_invariance(M=M)218        print(f"[A/B] M={M:4d}  plaquette inv={okF}  Wilson inv={okS}  "219              f"cov-diff inv={okCov}  global-superselection={okGl}")220221    print("-" * 64)222    for M in (12, 156, 420):223        st, ad = test_charge_winding(M=M)224        print(f"[C]   M={M:4d}  holonomy=enclosed-flux (Stokes)={st}  additive={ad}")225226    print("-" * 64)227    C, target, resid, g0 = test_coulomb(L=128)228    print(f"[D]   Coulomb  phi ~ C/r :  C = {C:.5f}   1/(4pi) = {target:.5f}"229          f"   ratio = {C/target:.4f}   rel.resid = {resid:.2%}")230    print(f"      on-site g(0) = {g0:.4f}  (Watson constant 0.2527, cross-check)")231232    print("-" * 64)233    seps, Uem, Ugr, emR, grA = test_sign(L=48)234    print(f"[E]   sep r           : {seps}")235    print(f"      U_EM(r)  (x1e3) : {[round(1e3*u,3) for u in Uem]}")236    print(f"      U_grav(r)(x1e3) : {[round(1e3*u,3) for u in Ugr]}")237    print(f"      EM like-charges REPEL (U>0, falls with r): {emR}")238    print(f"      gravity ATTRACTS (U<0, deepens as r->0)  : {grA}")239    print("=" * 64)240