nDot.io physics
08-ilang-propagation / 08-tilt
08tiltverified

Determines whether a push on one cell orients rotation-symmetric exchange cells far away, how small deviations match the anchored oscillator field, and which sources have a long-range mutual cost.

Code of version 2

ed_push.py6 KB · raw
"""Check (item 1): exact diagonalization of exchange cells with a push.

C = J sum_<xy> S_x.S_y - h_p S^3_h  (J = 1, n = e_3), spin S = 1/2 and S = 1.
Clusters: rings of even size L (S=1/2: 8,12,16,20; S=1: 6,8,10,12) and the
16-object periodic cubic cluster Z^3 / Lambda, Lambda spanned by (2,2,0),(2,0,2),(0,2,2).
C commutes with M = sum_x S^3_x; the lowest eigenvector is searched in M = 0,1,2.
Output: output/ed_push.txt
"""
from pathlib import Path
from collections import deque
import itertools
import numpy as np
import scipy.sparse as sp
from scipy.sparse.linalg import eigsh

OUT = Path(__file__).parent / "output"
OUT.mkdir(exist_ok=True)
HPS = [0.01, 0.1, 0.3, 1.0, 3.0, 10.0]


def ring(L):
    links = [(i, (i + 1) % L) for i in range(L)]
    eps = np.array([(-1) ** i for i in range(L)])
    return links, eps


def cubic16():
    A = np.array([[2, 2, 0], [2, 0, 2], [0, 2, 2]]).T  # columns are the periods
    Ainv = np.linalg.inv(A)

    def same(u, v):
        c = Ainv @ (np.array(u) - np.array(v))
        return np.allclose(c, np.round(c))

    reps = []
    for p in itertools.product(range(4), repeat=3):
        if not any(same(p, q) for q in reps):
            reps.append(p)
    assert len(reps) == 16

    def idx(p):
        return [k for k, q in enumerate(reps) if same(p, q)][0]

    links = set()
    for k, p in enumerate(reps):
        nb = set()
        for d in np.eye(3, dtype=int):
            for s in (1, -1):
                j = idx(tuple(np.array(p) + s * d))
                nb.add(j)
                links.add(tuple(sorted((k, j))))
        assert len(nb) == 6
    links = sorted(links)
    assert len(links) == 48
    eps = np.array([(-1) ** (sum(p) % 2) for p in reps])
    for a, b in links:
        assert eps[a] != eps[b]
    return links, eps, reps


def distances(links, n, h=0):
    adj = [[] for _ in range(n)]
    for a, b in links:
        adj[a].append(b)
        adj[b].append(a)
    d = [-1] * n
    d[h] = 0
    q = deque([h])
    while q:
        u = q.popleft()
        for v in adj[u]:
            if d[v] < 0:
                d[v] = d[u] + 1
                q.append(v)
    return np.array(d)


def sector(n, S2, M2):
    """Basis states (digit arrays, digit = m + S) with 2*sum(m) = M2; S2 = 2S."""
    d = S2 + 1
    codes = np.arange(d ** n, dtype=np.int64)
    digits = np.zeros((codes.size, n), dtype=np.int8)
    c = codes.copy()
    for i in range(n):
        digits[:, i] = c % d
        c //= d
    tot = 2 * digits.sum(axis=1).astype(np.int64) - n * S2
    keep = tot == M2
    return codes[keep], digits[keep]


def build(n, S2, M2, links, J=1.0):
    S = S2 / 2.0
    d = S2 + 1
    codes, digits = sector(n, S2, M2)
    m = digits.astype(float) - S
    diag = np.zeros(codes.size)
    rows, cols, vals = [], [], []
    for a, b in links:
        diag += J * m[:, a] * m[:, b]
        for i, j in ((a, b), (b, a)):  # S^+_i S^-_j
            ok = (digits[:, i] < S2) & (digits[:, j] > 0)
            src = np.nonzero(ok)[0]
            new = codes[src] + d ** i - d ** j
            dst = np.searchsorted(codes, new)
            amp = 0.5 * J * np.sqrt(S * (S + 1) - m[src, i] * (m[src, i] + 1)) \
                * np.sqrt(S * (S + 1) - m[src, j] * (m[src, j] - 1))
            rows.append(dst); cols.append(src); vals.append(amp)
    off = sp.csr_matrix((np.concatenate(vals), (np.concatenate(rows), np.concatenate(cols))),
                        shape=(codes.size, codes.size))
    return off, diag, m


def lowest(H, k=1):
    if H.shape[0] <= 1500:
        w, v = np.linalg.eigh(H.toarray())
        return w[:k], v[:, :k]
    w, v = eigsh(H, k=k, which="SA", tol=1e-12)
    o = np.argsort(w)
    return w[o], v[:, o]


def run(name, n, S2, links, eps, out):
    dist = distances(links, n)
    far = np.nonzero(dist == dist.max())[0]
    out.append(f"\n## {name}: N={n}, S={S2}/2, links={len(links)}, far sites {list(far)} at distance {dist.max()}")
    secs = {}
    for M2 in (0, 2, 4):
        if M2 // 2 > n * S2 // 2:
            continue
        secs[M2] = build(n, S2, M2, links)
    # item 1(a): no push
    w0, _ = lowest(secs[0][0] + sp.diags(secs[0][1]), k=2)
    w1, _ = lowest(secs[2][0] + sp.diags(secs[2][1]), k=1)
    out.append(f"no push: E0(M=0)={w0[0]:.10f}, E1(M=0)={w0[1]:.10f}, E0(M=1)={w1[0]:.10f}"
               f"  -> unique singlet: {w0[0] < w0[1] - 1e-9 and w0[0] < w1[0] - 1e-9}")
    out.append("h_p/J   M_low   E_low            m(far)=eps*<S3_far>   m(h)")
    for hp in HPS:
        best = None
        for M2, (off, diag, m) in secs.items():
            H = off + sp.diags(diag - hp * m[:, 0])
            w, v = lowest(H, k=1)
            if best is None or w[0] < best[0] - 1e-12:
                best = (w[0], v[:, 0], m, M2)
        E, psi, m, M2 = best
        p = np.abs(psi) ** 2
        sz = p @ m
        mfar = np.mean(eps[far] * sz[far])
        out.append(f"{hp:6.2f}  {M2/2:5.1f}  {E:.10f}   {mfar: .6f}            {sz[0]: .6f}")


def main():
    out = ["# ED check, item 1: exchange cells, J=1, push -h_p S^3_h at h=0 (class +)"]
    for L in (8, 12, 16, 20):
        links, eps = ring(L)
        run(f"ring L={L}", L, 1, links, eps, out)
    links, eps, reps = cubic16()
    out.append("\n16-object cubic cluster sites (representatives mod Lambda): " + str(reps))
    out.append("links: each site x to x+e_i, i=1,2,3 (mod Lambda); 48 links, 6 distinct neighbours each")
    run("cubic cluster 16", 16, 1, links, eps, out)
    for L in (6, 8, 10, 12):
        links, eps = ring(L)
        run(f"ring L={L}", L, 2, links, eps, out)
    (OUT / "ed_push.txt").write_text("\n".join(out) + "\n")
    print("\n".join(out))


if __name__ == "__main__":
    main()
spinwave_mutual.py10 KB · raw
"""Check (item 3, leading order in 1/S): mutual cost of two held sources on the cubic torus.

Units J S = 1.  Quadratic form C_2 = 1/2 P^T T P + 1/2 Q^T V Q, T_k = z(1+gamma_k), V_k = z(1-gamma_k).
(1) Transverse direction sources (linear in Q): E_12 = -S eps1 eps2 g1 g2 G_a(x1,x2); the separation part is
    J E_r/(g1 g2) = -eps1 eps2 ghat(r), ghat = Lap^+ (single objects); -eps1 eps2 sum_{a,b} ghat(a-b) (two-object cells).
(2) Quadratic sources dH_i = 1/2 Q^T A_i Q + 1/2 P^T B_i P (along-n sources, bound held spin as a spin-length defect,
    changed link): E_12 = -2 int_0^inf dtau <dH_1(tau) dH_2(0)>_c, Wick with G_QQ, G_PP and G_QP = (i/2) F (tau > 0);
    far-from-push limit: the two zero modes (k = 0, k = Q) are left out.
Output: output/spinwave_mutual.txt
"""
from pathlib import Path
import numpy as np
from scipy.integrate import quad
from scipy.special import ive

OUT = Path(__file__).parent / "output"
OUT.mkdir(exist_ok=True)
Z = 6


def kgrid(L):
    k = 2 * np.pi * np.arange(L) / L
    c = np.cos(k)
    g = (c[:, None, None] + c[None, :, None] + c[None, None, :]) / 3.0
    return g


def ghat(L):
    k = 2 * np.pi * np.arange(L) / L
    lap = 2 * ((1 - np.cos(k))[:, None, None] + (1 - np.cos(k))[None, :, None] + (1 - np.cos(k))[None, None, :])
    inv = np.zeros_like(lap)
    inv[lap > 1e-12] = 1.0 / lap[lap > 1e-12]
    return np.real(np.fft.ifftn(inv))


def ghat_inf(x):
    """Infinite cubic lattice: (Lap^{-1})(x) = int_0^inf prod_i e^{-2t} I_{x_i}(2t) dt."""
    f = lambda t: np.prod([ive(abs(int(c)), 2 * t) for c in x])
    return quad(f, 0, np.inf, limit=400, epsabs=1e-13, epsrel=1e-11)[0]


def eps(x):
    return (-1) ** (int(sum(x)) % 2)


def check_58(L=6, eta=0.7):
    n = L ** 3
    co = np.array(np.unravel_index(np.arange(n), (L,) * 3)).T
    adj = np.zeros((n, n))
    for d in range(3):
        sh = co.copy(); sh[:, d] = (sh[:, d] + 1) % L
        j = np.ravel_multi_index(sh.T, (L,) * 3)
        adj[np.arange(n), j] += 1; adj[j, np.arange(n)] += 1
    V = Z * np.eye(n) - adj
    V[0, 0] += eta
    Ga = np.linalg.inv(V)
    g = ghat(L).ravel()
    dif = lambda a, b: np.ravel_multi_index(tuple((co[a] - co[b]) % L), (L,) * 3)
    err = 0.0
    for a, b in [(5, 17), (40, 101), (3, 3), (0, 77)]:
        f = 1 / eta + g[dif(a, b)] - g[dif(a, 0)] - g[dif(b, 0)] + g[0]
        err = max(err, abs(f - Ga[a, b]))
    return err


def pert(kind, x, e=None):
    """Return (A, B) as lists of (site, site, value); per unit strength (see header of output)."""
    x = tuple(x)
    if kind == "along":
        A = [(x, x, -eps(x))]
        return A, A
    if kind == "along_cell":
        x2 = (x[0], x[1] + 1, x[2])
        A = [(x, x, -eps(x)), (x2, x2, -eps(x))]
        return A, A
    if kind == "defect":
        nb = []
        for d in range(3):
            for s in (1, -1):
                y = list(x); y[d] += s; nb.append(tuple(y))
        A = [(x, x, -Z)] + [(x, y, 0.5) for y in nb] + [(y, x, 0.5) for y in nb]
        B = [(x, x, -Z)] + [(x, y, -0.5) for y in nb] + [(y, x, -0.5) for y in nb]
        return A, B
    if kind == "link":
        y = tuple(np.array(x) - np.array(e))
        A = [(x, x, 1), (y, y, 1), (x, y, -1), (y, x, -1)]
        B = [(x, x, 1), (y, y, 1), (x, y, 1), (y, x, 1)]
        return A, B
    raise ValueError(kind)


def contraction(M1, M2, L):
    w, i1, i2 = [], [], []
    for a, b, u in M1:
        for c, d, v in M2:
            w.append(u * v)
            i1.append(np.ravel_multi_index(tuple(np.mod(np.array(a) - np.array(c), L)), (L,) * 3))
            i2.append(np.ravel_multi_index(tuple(np.mod(np.array(b) - np.array(d), L)), (L,) * 3))
    return np.array(w), np.array(i1), np.array(i2)


def mutual_quadratic(L, configs, nodes=400):
    g = kgrid(L)
    om = Z * np.sqrt(np.clip(1 - g ** 2, 0, None))
    mask = om > 1e-9
    Tk = np.where(mask, Z * (1 + g), 0.0)
    Vk = np.where(mask, Z * (1 - g), 0.0)
    omm = np.where(mask, om, 1.0)
    pre = []
    for (A1, B1), (A2, B2) in configs:
        pre.append((contraction(A1, A2, L), contraction(B1, B2, L),
                    contraction(A1, B2, L), contraction(B1, A2, L)))
    s, ws = np.polynomial.legendre.leggauss(nodes)
    lo, hi = np.log(1e-7), np.log(200.0)
    sv = 0.5 * (hi - lo) * s + 0.5 * (hi + lo)
    wv = 0.5 * (hi - lo) * ws
    acc = np.zeros(len(configs))
    for sj, wj in zip(sv, wv):
        tau = np.exp(sj)
        ex = np.where(mask, np.exp(-omm * tau), 0.0)
        GQ = np.real(np.fft.ifftn(Tk / (2 * omm) * ex)).ravel()
        GP = np.real(np.fft.ifftn(Vk / (2 * omm) * ex)).ravel()
        F = np.real(np.fft.ifftn(ex)).ravel()
        for n, (qq, pp, qp, pq) in enumerate(pre):
            val = 0.5 * np.sum(qq[0] * GQ[qq[1]] * GQ[qq[2]]) + 0.5 * np.sum(pp[0] * GP[pp[1]] * GP[pp[2]]) \
                - 0.125 * (np.sum(qp[0] * F[qp[1]] * F[qp[2]]) + np.sum(pq[0] * F[pq[1]] * F[pq[2]]))
            acc[n] += wj * tau * val
    return -2 * acc


def cont_link(e1, e2, e12):
    """Continuum: J E/(delta1 delta2 S) * r^7 for two changed links (unit vectors e1, e2), r along axis 1."""
    def C(t):
        X = np.array([t, 1.0, 0, 0]); rho = np.linalg.norm(X); n = X / rho
        I = np.eye(4) - 4 * np.outer(n, n)
        E1 = np.r_[0, e1]; E2 = np.r_[0, e2]; t0 = np.r_[1.0, 0, 0, 0]
        M1 = np.outer(E1, E1) - (2 / Z) * np.outer(t0, t0)
        M2 = np.outer(E2, E2) - (2 / Z) * np.outer(t0, t0)
        cross = I[0, 0] * (E1 @ I @ E2) - (I @ E1)[0] * (I @ E2)[0]
        return (4 * np.trace(M1 @ I @ M2 @ I) - (16 / Z) * e12 * cross) / rho ** 8
    val = quad(C, -np.inf, np.inf, epsabs=1e-13, epsrel=1e-12)[0]
    return -np.sqrt(2 * Z) / (16 * np.pi ** 4) * val


def main():
    out = ["# Mutual cost of two held sources, leading order in 1/S, cubic torus (units as stated per block)"]
    out.append(f"\n(5.8) with kappa_h = J S, kappa_a = h_p against direct inverse (L=6): max error {check_58():.2e}")
    out.append("\n## (1) Transverse sources: separation part J E_r/(g1 g2 (m1perp.m2perp))")
    out.append("single objects: -eps1 eps2 ghat(r); cells (x, x+e2), + on the first object: -eps1 eps2 sum ghat")
    out.append(f"ghat_inf(0) = {ghat_inf((0, 0, 0)):.7f} (gamma_3 = 0.2527310)")
    out.append("r   eps1eps2   single: J E_r/(g1g2)  4 pi r ghat_inf(r)   cells: J E_r/(g1g2)  pi r sum ghat_inf"
               "   torus check: ghat_L(r)-ghat_L(8) for L=16, 32, 64 vs ghat_inf(r)-ghat_inf(8)")
    gl = {L: ghat(L) for L in (16, 32, 64)}
    g8 = ghat_inf((8, 0, 0))
    for r in range(2, 9):
        e12 = (-1) ** r
        gs = ghat_inf((r, 0, 0))
        gc = 2 * gs + ghat_inf((r, 1, 0)) + ghat_inf((r, -1, 0))
        tor = "  ".join(f"{gl[L][r, 0, 0] - gl[L][8, 0, 0]:.6f}" for L in (16, 32, 64))
        out.append(f"{r:2d}   {e12:+d}        {-e12 * gs: .6f}            {4 * np.pi * r * gs:.4f}"
                   f"             {-e12 * gc: .6f}         {np.pi * r * gc:.4f}            {tor}   {gs - g8:.6f}")
    kap = np.sqrt(2 * Z) / (32 * np.pi ** 3)
    lam = Z ** 1.5 / (16 * np.sqrt(2) * np.pi ** 3)
    cA = {1: cont_link([1, 0, 0], [1, 0, 0], 1), -1: cont_link([1, 0, 0], [1, 0, 0], -1)}
    cB = {1: cont_link([0, 1, 0], [0, 1, 0], 1), -1: cont_link([0, 1, 0], [0, 1, 0], -1)}
    pre = np.sqrt(3) / (8 * np.pi ** 3)
    out.append("\n## Continuum coefficients")
    out.append(f"along n, single:  J S E/(g1 g2) = -eps1 eps2 kappa_par / r^3, kappa_par = sqrt(2z)/(32 pi^3) = {kap:.7f}")
    out.append(f"held spin (defect), r >> l_b: S E/(J sig1 sig2) = +eps1 eps2 lambda / r^5, lambda = {lam:.7f}")
    out.append(f"changed links, J E/(d1 d2 S) * r^7: parallel to r: eps=+1 {cA[1]:.7f} (formula {-pre * (43/6 + 2.5):.7f}),"
               f" eps=-1 {cA[-1]:.7f} (formula {-pre * (43/6 - 2.5):.7f})")
    out.append(f"                                     perpendicular: eps=+1 {cB[1]:.7f} (formula {-pre * (4/3 - 5/12):.7f}),"
               f" eps=-1 {cB[-1]:.7f} (formula {-pre * (4/3 + 5/12):.7f})")
    out.append("\n## (2) Quadratic sources, lattice (zero modes left out); ratio = lattice / continuum")
    out.append("columns: r, eps1eps2, along single [J S E/(g1g2), ratio], along cell [.., ratio vs 4x], "
               "defect [S E/(J s1 s2), ratio], link par [J E/(d1d2S), ratio], link perp [.., ratio]")
    rs = list(range(2, 13))
    ratios = {}
    for L in (32, 64, 128):
        configs = []
        for r in rs:
            x2 = (r, 0, 0)
            configs += [(pert("along", (0, 0, 0)), pert("along", x2)),
                        (pert("along_cell", (0, 0, 0)), pert("along_cell", x2)),
                        (pert("defect", (0, 0, 0)), pert("defect", x2)),
                        (pert("link", (0, 0, 0), (1, 0, 0)), pert("link", x2, (1, 0, 0))),
                        (pert("link", (0, 0, 0), (0, 1, 0)), pert("link", x2, (0, 1, 0)))]
        res = mutual_quadratic(L, configs, nodes=300).reshape(len(rs), 5)
        out.append(f"L = {L}")
        ratios[L] = np.zeros_like(res)
        for i, r in enumerate(rs):
            e = (-1) ** r
            p = [-e * kap / r ** 3, -4 * e * kap / r ** 3, e * lam / r ** 5, cA[e] / r ** 7, cB[e] / r ** 7]
            ratios[L][i] = res[i] / np.array(p)
            row = "  ".join(f"{res[i, j]: .3e} {res[i, j] / p[j]:6.3f}" for j in range(5))
            out.append(f"{r:2d} {e:+d}  {row}")
    out.append("ratio extrapolated to L -> infinity: Aitken from L = 32, 64, 128 (geometric finite-size error);"
               " the L = 128 value where the change from 64 to 128 is below 1e-3 or not geometric")
    for i, r in enumerate(rs):
        x1, x2, x3 = ratios[32][i], ratios[64][i], ratios[128][i]
        d1, d2 = x2 - x1, x3 - x2
        geo = (np.abs(d2) > 1e-3) & (d1 * d2 > 0) & (np.abs(d2) < np.abs(d1))
        ex = np.where(geo, x3 + d2 / np.where(geo, d1 / np.where(geo, d2, 1.0) - 1, 1.0), x3)
        out.append(f"{r:2d}  " + "  ".join(f"{v:6.3f}" for v in ex))
    (OUT / "spinwave_mutual.txt").write_text("\n".join(out) + "\n")
    print("\n".join(out))


if __name__ == "__main__":
    main()
spinwave_tilt.py3 KB · raw
"""Check (item 1(b), leading order in 1/S): first correction to m(x) far from the push.

Quadratic form (units J S = 1): C_2 = 1/2 P^T T P + 1/2 Q^T V Q with
V = Lap + eta P_h, T = E V E = Lap^+ + eta P_h, eta = h_p/(J S), E = diag(eps).
Ground-state covariances: <QQ^T> = 1/2 T^(1/2) (T^(1/2) V T^(1/2))^(-1/2) T^(1/2), same for P with T<->V.
First correction: m(x) = eps_h (S - dS(x)), dS(x) = (<Q_x^2> + <P_x^2> - 1)/2.
Output: output/spinwave_tilt.txt
"""
from pathlib import Path
import numpy as np

OUT = Path(__file__).parent / "output"
OUT.mkdir(exist_ok=True)


def lattice(L, D):
    n = L ** D
    coords = np.array(np.unravel_index(np.arange(n), (L,) * D)).T
    adj = np.zeros((n, n))
    for d in range(D):
        sh = coords.copy()
        sh[:, d] = (sh[:, d] + 1) % L
        j = np.ravel_multi_index(sh.T, (L,) * D)
        adj[np.arange(n), j] += 1
        adj[j, np.arange(n)] += 1
    eps = (-1.0) ** coords.sum(axis=1)
    return coords, adj, eps


def sqrtm_sym(A, power):
    w, U = np.linalg.eigh(A)
    return (U * w ** power) @ U.T


def dS_push(L, D, eta):
    coords, adj, eps = lattice(L, D)
    z = 2 * D
    n = L ** D
    V = z * np.eye(n) - adj
    V[0, 0] += eta
    T = (eps[:, None] * V) * eps[None, :]
    Vh = sqrtm_sym(V, 0.5)
    Th = (eps[:, None] * Vh) * eps[None, :]
    covQ = 0.5 * Th @ sqrtm_sym(Th @ V @ Th, -0.5) @ Th
    covP = 0.5 * Vh @ sqrtm_sym(Vh @ T @ Vh, -0.5) @ Vh
    far = np.ravel_multi_index(tuple(np.full(D, L // 2)), (L,) * D)
    dS = 0.5 * (np.diag(covQ) + np.diag(covP) - 1)
    return dS[far], dS[0], np.max(np.abs(np.diag(covQ) - np.diag(covP)))


def dS3_bulk(L):
    k = 2 * np.pi * (np.arange(L) + 0.5) / L
    c = np.cos(k)
    tot = 0.0
    for c1 in c:
        g = (c1 + c[:, None] + c[None, :]) / 3.0
        tot += np.sum(1.0 / np.sqrt(1.0 - g ** 2))
    W = tot / L ** 3
    return 0.5 * (W - 1.0)


def main():
    out = ["# Leading order in 1/S: first correction dS, m = eps_h (S - dS) + O(1/S)"]
    out.append("\n## Cubic torus, L -> infinity, no push (midpoint sums): dS_3 = (W - 1)/2")
    vals = {}
    for L in (64, 128, 256):
        vals[L] = dS3_bulk(L)
        out.append(f"L={L:4d}: dS_3 = {vals[L]:.6f}")
    rich = (4 * vals[256] - vals[128]) / 3
    out.append(f"Richardson (error ~ L^-2): dS_3 = {rich:.5f}")
    out.append("\n## Cubic torus with push (exact Gaussian), far site (L/2,L/2,L/2)")
    out.append("L    eta=h_p/(JS)   dS(far)    dS(h)     zero-mode estimate sqrt(2z/(N eta))/2   max|<Q^2>-<P^2>|")
    for L in (8, 12, 16):
        for eta in (0.1, 1.0, 10.0):
            f, h, sym = dS_push(L, 3, eta)
            est = 0.5 * np.sqrt(12.0 / (L ** 3 * eta))
            out.append(f"{L:3d}  {eta:6.2f}        {f:.5f}   {h:.5f}   {est:.5f}                                {sym:.1e}")
    out.append("\n## Ring with push (exact Gaussian), eta = 1, far site L/2")
    out.append("L      dS(L/2)    dS(L/2) - (1/pi) ln(L/2)")
    ring = []
    for L in (64, 128, 256, 512, 1024):
        f, h, _ = dS_push(L, 1, 1.0)
        ring.append((L, f))
        out.append(f"{L:5d}  {f:.5f}    {f - np.log(L / 2) / np.pi:.5f}")
    sl = np.polyfit(np.log([r[0] for r in ring[-3:]]), [r[1] for r in ring[-3:]], 1)[0]
    out.append(f"slope d dS / d ln L (last three sizes) = {sl:.5f};  1/pi = {1 / np.pi:.5f} (Dirichlet image at the push)")
    (OUT / "spinwave_tilt.txt").write_text("\n".join(out) + "\n")
    print("\n".join(out))


if __name__ == "__main__":
    main()
output/ed_push.txt6 KB · raw
# ED check, item 1: exchange cells, J=1, push -h_p S^3_h at h=0 (class +)

## ring L=8: N=8, S=1/2, links=8, far sites [np.int64(4)] at distance 4
no push: E0(M=0)=-3.6510934089, E1(M=0)=-3.1284190638, E0(M=1)=-3.1284190638  -> unique singlet: True
h_p/J   M_low   E_low            m(far)=eps*<S3_far>   m(h)
  0.01    0.0  -3.6511215930    0.002915             0.005637
  0.10    0.0  -3.6539014094    0.028913             0.055951
  0.30    0.0  -3.6756584654    0.081547             0.158772
  1.00    0.0  -3.8706747638    0.178327             0.361393
  3.00    0.0  -4.7406497893    0.217820             0.469512
 10.00    0.0  -8.1656749710    0.223623             0.496231

## ring L=12: N=12, S=1/2, links=12, far sites [np.int64(6)] at distance 6
no push: E0(M=0)=-5.3873909174, E1(M=0)=-5.0315434037, E0(M=1)=-5.0315434037  -> unique singlet: True
h_p/J   M_low   E_low            m(far)=eps*<S3_far>   m(h)
  0.01    0.0  -5.3874232606    0.003078             0.006468
  0.10    0.0  -5.3906079037    0.030399             0.063994
  0.30    0.0  -5.4152047132    0.083233             0.177593
  1.00    0.0  -5.6229268437    0.162829             0.374293
  3.00    0.0  -6.5029771989    0.187370             0.471246
 10.00    0.0  -9.9314563940    0.190367             0.496371

## ring L=16: N=16, S=1/2, links=16, far sites [np.int64(8)] at distance 8
no push: E0(M=0)=-7.1422963606, E1(M=0)=-6.8721066784, E0(M=1)=-6.8721066784  -> unique singlet: True
h_p/J   M_low   E_low            m(far)=eps*<S3_far>   m(h)
  0.01    0.0  -7.1423316575    0.003176             0.007059
  0.10    0.0  -7.1458016524    0.031226             0.069621
  0.30    0.0  -7.1722882312    0.083171             0.189514
  1.00    0.0  -7.3866985161    0.150071             0.379989
  3.00    0.0  -8.2707749474    0.167171             0.471891
 10.00    0.0  -11.7005556368    0.169000             0.496425

## ring L=20: N=20, S=1/2, links=20, far sites [np.int64(10)] at distance 10
no push: E0(M=0)=-8.9043865299, E1(M=0)=-8.6864409862, E0(M=1)=-8.6864409862  -> unique singlet: True
h_p/J   M_low   E_low            m(far)=eps*<S3_far>   m(h)
  0.01    0.0  -8.9044241355    0.003245             0.007520
  0.10    0.0  -8.9081154951    0.031764             0.073953
  0.30    0.0  -8.9359905145    0.082444             0.197877
  1.00    0.0  -9.1544799698    0.139769             0.383032
  3.00    0.0  -10.0405891867    0.152531             0.472206
 10.00    0.0  -13.4710121778    0.153753             0.496452

16-object cubic cluster sites (representatives mod Lambda): [(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 1, 0), (0, 1, 1), (0, 1, 2), (0, 1, 3), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 0, 3), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 1, 3)]
links: each site x to x+e_i, i=1,2,3 (mod Lambda); 48 links, 6 distinct neighbours each

## cubic cluster 16: N=16, S=1/2, links=48, far sites [np.int64(13), np.int64(15)] at distance 3
no push: E0(M=0)=-15.5783288133, E1(M=0)=-14.7965997285, E0(M=1)=-14.7965997285  -> unique singlet: True
h_p/J   M_low   E_low            m(far)=eps*<S3_far>   m(h)
  0.01    0.0  -15.5783455887    0.002435             0.003355
  0.10    0.0  -15.5800039442    0.024280             0.033454
  0.30    0.0  -15.5932340835    0.071115             0.098118
  1.00    0.0  -15.7272156212    0.192088             0.268207
  3.00    0.0  -16.4641224768    0.294607             0.424892
 10.00    0.0  -19.7476521880    0.330312             0.487059

## ring L=6: N=6, S=2/2, links=6, far sites [np.int64(3)] at distance 3
no push: E0(M=0)=-8.6174231818, E1(M=0)=-7.8967958192, E0(M=1)=-7.8967958192  -> unique singlet: True
h_p/J   M_low   E_low            m(far)=eps*<S3_far>   m(h)
  0.01    0.0  -8.6174901294    0.010352             0.013389
  0.10    0.0  -8.6240752905    0.102132             0.132193
  0.30    0.0  -8.6745349327    0.278218             0.362050
  1.00    0.0  -9.0869706859    0.546592             0.732523
  3.00    0.0  -10.7994879963    0.660086             0.919464
 10.00    0.0  -17.5670872881    0.694926             0.986112

## ring L=8: N=8, S=2/2, links=8, far sites [np.int64(4)] at distance 4
no push: E0(M=0)=-11.3369560779, E1(M=0)=-10.7434008235, E0(M=1)=-10.7434008235  -> unique singlet: True
h_p/J   M_low   E_low            m(far)=eps*<S3_far>   m(h)
  0.01    0.0  -11.3370291952    0.010221             0.014622
  0.10    0.0  -11.3442097178    0.100476             0.143920
  0.30    0.0  -11.3985873076    0.267565             0.386678
  1.00    0.0  -11.8253272598    0.494463             0.745935
  3.00    0.0  -13.5497976377    0.582260             0.922190
 10.00    0.0  -20.3241940732    0.609254             0.986461

## ring L=10: N=10, S=2/2, links=10, far sites [np.int64(5)] at distance 5
no push: E0(M=0)=-14.0941299549, E1(M=0)=-13.5693220045, E0(M=1)=-13.5693220045  -> unique singlet: True
h_p/J   M_low   E_low            m(far)=eps*<S3_far>   m(h)
  0.01    0.0  -14.0942062020    0.009913             0.015248
  0.10    0.0  -14.1016869890    0.097223             0.149801
  0.30    0.0  -14.1579598525    0.255412             0.398181
  1.00    0.0  -14.5907289613    0.456752             0.751132
  3.00    0.0  -16.3197109015    0.529673             0.923214
 10.00    0.0  -23.0967344366    0.550821             0.986603

## ring L=12: N=12, S=2/2, links=12, far sites [np.int64(6)] at distance 6
no push: E0(M=0)=-16.8695561395, E1(M=0)=-16.3853596696, E0(M=1)=-16.3853596696  -> unique singlet: True
h_p/J   M_low   E_low            m(far)=eps*<S3_far>   m(h)
  0.01    0.0  -16.8696337457    0.009055             0.015520
  0.10    0.0  -16.8772443685    0.088705             0.152333
  0.30    0.0  -16.9343124777    0.231425             0.402886
  1.00    0.0  -17.3693927041    0.407686             0.753039
  3.00    0.0  -19.1000782201    0.470341             0.923626
 10.00    0.0  -25.8782395163    0.488416             0.986670
output/spinwave_mutual.txt6 KB · raw
# Mutual cost of two held sources, leading order in 1/S, cubic torus (units as stated per block)

(5.8) with kappa_h = J S, kappa_a = h_p against direct inverse (L=6): max error 4.88e-14

## (1) Transverse sources: separation part J E_r/(g1 g2 (m1perp.m2perp))
single objects: -eps1 eps2 ghat(r); cells (x, x+e2), + on the first object: -eps1 eps2 sum ghat
ghat_inf(0) = 0.2527310 (gamma_3 = 0.2527310)
r   eps1eps2   single: J E_r/(g1g2)  4 pi r ghat_inf(r)   cells: J E_r/(g1g2)  pi r sum ghat_inf   torus check: ghat_L(r)-ghat_L(8) for L=16, 32, 64 vs ghat_inf(r)-ghat_inf(8)
 2   +1        -0.042889            1.0779             -0.157642         0.9905            0.029359  0.032566  0.032862   0.032901
 3   -1         0.027545            1.0384              0.106137         1.0003            0.014233  0.017247  0.017521   0.017557
 4   +1        -0.020289            1.0198             -0.079621         1.0005            0.007303  0.010028  0.010269   0.010301
 5   -1         0.016101            1.0117              0.063679         1.0003            0.003573  0.005889  0.006087   0.006113
 6   +1        -0.013365            1.0077             -0.053058         1.0001            0.001456  0.003213  0.003358   0.003377
 7   -1         0.011430            1.0055              0.045475         1.0001            0.000347  0.001353  0.001432   0.001442
 8   +1        -0.009988            1.0041             -0.039790         1.0000            0.000000  0.000000  0.000000   0.000000

## Continuum coefficients
along n, single:  J S E/(g1 g2) = -eps1 eps2 kappa_par / r^3, kappa_par = sqrt(2z)/(32 pi^3) = 0.0034913
held spin (defect), r >> l_b: S E/(J sig1 sig2) = +eps1 eps2 lambda / r^5, lambda = 0.0209480
changed links, J E/(d1 d2 S) * r^7: parallel to r: eps=+1 -0.0674991 (formula -0.0674991), eps=-1 -0.0325858 (formula -0.0325858)
                                     perpendicular: eps=+1 -0.0064008 (formula -0.0064008), eps=-1 -0.0122197 (formula -0.0122197)

## (2) Quadratic sources, lattice (zero modes left out); ratio = lattice / continuum
columns: r, eps1eps2, along single [J S E/(g1g2), ratio], along cell [.., ratio vs 4x], defect [S E/(J s1 s2), ratio], link par [J E/(d1d2S), ratio], link perp [.., ratio]
L = 32
 2 +1  -4.624e-04  1.060  -1.491e-03  0.854   5.671e-04  0.866  -1.274e-03  2.417  -1.174e-04  2.347
 3 -1   1.198e-04  0.927   4.142e-04  0.801  -1.211e-04  1.405  -2.430e-05  1.631  -1.119e-05  2.002
 4 +1  -3.922e-05  0.719  -1.480e-04  0.678   1.949e-05  0.952  -6.880e-06  1.670  -6.874e-07  1.759
 5 -1   1.640e-05  0.587   6.200e-05  0.555  -6.361e-06  0.949  -5.446e-07  1.306  -2.119e-07  1.355
 6 +1  -7.170e-06  0.444  -2.790e-05  0.432   2.055e-06  0.763  -3.006e-07  1.247  -2.761e-08  1.207
 7 -1   3.351e-06  0.329   1.293e-05  0.318  -8.651e-07  0.694  -4.524e-08  1.143  -1.714e-08  1.155
 8 +1  -1.510e-06  0.221  -5.918e-06  0.217   3.521e-07  0.551  -3.768e-08  1.171  -3.017e-09  0.988
 9 -1   6.659e-07  0.139   2.578e-06  0.135  -1.646e-07  0.464  -7.892e-09  1.158  -2.875e-09  1.125
10 +1  -2.585e-07  0.074  -1.014e-06  0.073   7.468e-08  0.356  -8.418e-09  1.247  -5.211e-10  0.814
11 -1   8.809e-08  0.034   3.369e-07  0.032  -3.849e-08  0.296  -2.283e-09  1.366  -7.612e-10  1.214
12 +1  -2.467e-08  0.012  -9.778e-08  0.012   2.099e-08  0.249  -2.906e-09  1.543  -1.184e-10  0.663
L = 64
 2 +1  -4.970e-04  1.139  -1.616e-03  0.926   5.756e-04  0.879  -1.274e-03  2.416  -1.174e-04  2.348
 3 -1   1.393e-04  1.077   4.876e-04  0.943  -1.251e-04  1.451  -2.430e-05  1.631  -1.119e-05  2.002
 4 +1  -5.146e-05  0.943  -1.957e-04  0.897   2.119e-05  1.036  -6.868e-06  1.667  -6.922e-07  1.772
 5 -1   2.483e-05  0.889   9.493e-05  0.850  -7.344e-06  1.096  -5.434e-07  1.303  -2.117e-07  1.353
 6 +1  -1.312e-05  0.812  -5.144e-05  0.796   2.620e-06  0.972  -2.969e-07  1.231  -2.873e-08  1.256
 7 -1   7.695e-06  0.756   3.007e-05  0.738  -1.231e-06  0.987  -4.446e-08  1.124  -1.699e-08  1.145
 8 +1  -4.679e-06  0.686  -1.850e-05  0.678   5.840e-07  0.914  -3.586e-08  1.114  -3.397e-09  1.113
 9 -1   2.998e-06  0.626   1.181e-05  0.616  -3.205e-07  0.904  -7.274e-09  1.068  -2.759e-09  1.080
10 +1  -1.950e-06  0.559  -7.737e-06  0.554   1.761e-07  0.841  -7.248e-09  1.074  -6.713e-10  1.049
11 -1   1.306e-06  0.498   5.163e-06  0.492  -1.058e-07  0.814  -1.750e-09  1.047  -6.603e-10  1.053
12 +1  -8.771e-07  0.434  -3.487e-06  0.431   6.334e-08  0.752  -1.997e-09  1.060  -1.788e-10  1.001
L = 128
 2 +1  -5.071e-04  1.162  -1.653e-03  0.947   5.768e-04  0.881  -1.274e-03  2.416  -1.174e-04  2.348
 3 -1   1.453e-04  1.124   5.105e-04  0.987  -1.256e-04  1.457  -2.430e-05  1.631  -1.119e-05  2.002
 4 +1  -5.554e-05  1.018  -2.116e-04  0.970   2.146e-05  1.049  -6.867e-06  1.667  -6.925e-07  1.773
 5 -1   2.784e-05  0.997   1.068e-04  0.956  -7.510e-06  1.120  -5.434e-07  1.303  -2.117e-07  1.353
 6 +1  -1.545e-05  0.956  -6.063e-05  0.938   2.724e-06  1.011  -2.967e-07  1.230  -2.881e-08  1.260
 7 -1   9.546e-06  0.938   3.740e-05  0.919  -1.304e-06  1.046  -4.445e-08  1.123  -1.699e-08  1.145
 8 +1  -6.180e-06  0.906  -2.447e-05  0.897   6.354e-07  0.994  -3.578e-08  1.112  -3.429e-09  1.123
 9 -1   4.239e-06  0.885   1.674e-05  0.874  -3.590e-07  1.012  -7.265e-09  1.066  -2.757e-09  1.079
10 +1  -2.985e-06  0.855  -1.186e-05  0.849   2.049e-07  0.978  -7.205e-09  1.067  -6.865e-10  1.072
11 -1   2.178e-06  0.830   8.638e-06  0.823  -1.282e-07  0.986  -1.743e-09  1.042  -6.589e-10  1.051
12 +1  -1.616e-06  0.800  -6.433e-06  0.796   8.072e-08  0.959  -1.970e-09  1.046  -1.869e-10  1.046
ratio extrapolated to L -> infinity: Aitken from L = 32, 64, 128 (geometric finite-size error); the L = 128 value where the change from 64 to 128 is below 1e-3 or not geometric
 2   1.172   0.956   0.881   2.416   2.348
 3   1.144   1.007   1.459   1.631   2.002
 4   1.055   1.007   1.051   1.667   1.773
 5   1.057   1.016   1.125   1.303   1.353
 6   1.047   1.029   1.020   1.230   1.260
 7   1.073   1.053   1.060   1.123   1.145
 8   1.104   1.095   1.017   1.112   1.124
 9   1.180   1.170   1.047   1.066   1.079
10   1.322   1.318   1.032   1.067   1.075
11   1.672   1.675   1.071   1.042   1.051
12   3.173   3.225   1.103   1.046   1.053
output/spinwave_tilt.txt2 KB · raw
# Leading order in 1/S: first correction dS, m = eps_h (S - dS) + O(1/S)

## Cubic torus, L -> infinity, no push (midpoint sums): dS_3 = (W - 1)/2
L=  64: dS_3 = 0.078304
L= 128: dS_3 = 0.078344
L= 256: dS_3 = 0.078354
Richardson (error ~ L^-2): dS_3 = 0.07836

## Cubic torus with push (exact Gaussian), far site (L/2,L/2,L/2)
L    eta=h_p/(JS)   dS(far)    dS(h)     zero-mode estimate sqrt(2z/(N eta))/2   max|<Q^2>-<P^2>|
  8    0.10        0.31135   0.29896   0.24206                                0.0e+00
  8    1.00        0.15197   0.11065   0.07655                                0.0e+00
  8   10.00        0.11169   0.01999   0.02421                                0.0e+00
 12    0.10        0.20637   0.19853   0.13176                                0.0e+00
 12    1.00        0.11960   0.08897   0.04167                                0.0e+00
 12   10.00        0.09770   0.01863   0.01318                                0.0e+00
 16    0.10        0.16197   0.15613   0.08558                                0.0e+00
 16    1.00        0.10561   0.07974   0.02706                                0.0e+00
 16   10.00        0.09139   0.01805   0.00856                                0.0e+00

## Ring with push (exact Gaussian), eta = 1, far site L/2
L      dS(L/2)    dS(L/2) - (1/pi) ln(L/2)
   64  1.10378    0.00061
  128  1.31488    -0.00893
  256  1.53065    -0.01380
  512  1.74882    -0.01626
 1024  1.96822    -0.01750
slope d dS / d ln L (last three sizes) = 0.31564;  1/pi = 0.31831 (Dirichlet image at the push)
Analyse with ChatGPTnDot Physics Research plugin
ChatGPT plugin

Analyse this research in ChatGPT

The free plugin nDot Physics Research gives ChatGPT read-only access to everything published here.

  1. Open ChatGPT and select the plugin in the message box.
  2. Write your question after it:nDot Physics Research Explain what 08-ilang-propagation/08-tilt establishes and what it builds on.
  3. Name the subproject when you cite an equation number, e.g. (17.7) of 03-ilang-space.
Open in ChatGPT

Interested in this research?

Join the readers' list and get an e-mail when a new stage or a correction is published. No password, and you can unsubscribe at any time.