Recent Changes
- Commit
Add Hodge–de Rham Laplacian to the compact lattice (#152) by Evan Berkowitz at 2026-06-25 21:16:45
Add laplacian(f) = (dδ + δd)f to supervillain/lattice/compact.py, mapping a p-form to a p-form of the same degree. On a flat periodic lattice d and δ are constant-coefficient combinations of commuting shift operators, so the Weitzenböck cross terms cancel and Δ acts diagonally on each component as the negative nearest-neighbor scalar Laplacian. The implementation evaluates that stencil directly (2D shifts, independent of p) rather than composing d and δ, and is tested against the explicit dδ + δd composition. Also export laplacian from supervillain.lattice, document it in form.rst, add an inline self-test block, and add pytest coverage: matches-dδ+δd, self-adjointness, the Weitzenböck identity ⟨Δf,f⟩ = ⟨df,df⟩+⟨δf,δf⟩, positivity, commutation with d and δ, component-diagonality, and the scalar-Laplacian reduction. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Generalize the lattice and forms from 2D to arbitrary dimension D (#151) by Evan Berkowitz at 2026-06-25 20:21:33
For various physics reasons we want to be able to simulate beyond D=2. But Lattice2D was built in to a lot of places in the code. # Physics Infrastructure: Lattice and Form We start by thinking about the interlaced data lattice structure on which differential forms can naturally be encoded. These are now available as a reference implementation. The issue is that this data layout is extremely inefficient---for any given form degree much of the data is just 0. We previously held out the prospect of using asymmetric lattices (with different extents in different directions). Here we concede that taking advantage of this is quite unlikely and we just settle on (hyper)cubic lattices. * The interlaced lattice layout was first hand-coded from Shi Chen's notes. That included d, δ, *, and wedge that the code almost matches exactly; there might be one or two signs different, but the test suite shows the signs match the identities that he listed. * Restructure lattice/ package: move Lattice2D, compact, interlaced into submodules. * supervillain.lattice now exports the new arbitrary-D Lattice object * Some generators need to sum nearest neighbors of boundaries or coboundaries; in 2D these sums were hard-coded; we introduce .face_sum and .coface_sum which is D-agnostic. * Lattices have arbitrary-D checkerboarding. * Lattices have .origin attribute to make it easy to avoid needing to get a D-dimensional coordinate repetitively. * Lattices have symmetrize, linearize, coordinatize, distance_squared (almost) matching the 2D lattice. The main difference is that 2D had the generic-irrep projection; in higher dimensions this could cause a proliferation of group theory infrastructure that we haven't really needed anyway---in practice we've always been interested in the totally-symmetric correlators. * Drop D=2-only properties (plaquettes, nt, nx, t, x, T, X) from Lattice and add them to Lattice2D; Lattice.to_h5/from_h5 overridden to write only D and N. Along the way we were careful to ensure that Lattice and Lattice2D agreed on d, δ, shifts, and so on. Once the D=2 functionality matched exactly we removed most of the Lattice2D infrastructure and made it inherit from Lattice, keeping a few D=2 specifics. * A new Form type is just a numpy array with a stored integer degree. This allows us to avoid having to manually track the degree as we pass data around (and work more easily in arbitrary-D where the same physical quantity might have different form degree---if it's on the dual lattice, for example, where it could have fixed co-degree). * Forms of degree p are indexed by [number of independent p-form directions, lattice size], much the same way that 1-forms were previously stored. But for uniformity 0- and top-forms even have a singleton direction. * The differential geometry operators d, δ, Hodge star, and wedge all operate on Forms without needing a separate degree argument, and just dispatches based on the Form's built-in degree. For example, plot_form(p, form, …) → plot_form(form, …): degree inferred from form.degree; form[0] extracted for p=0 scatter and p=2 imshow to respect (C,N,N) layout. The construction and matching accomplished by a set of tests and shims to/from 2D which were ultimately removed once the 2D-specialization was no longer needed. We also ran statistical tests where eg. the 2D Villain formulation was run with the new Lattice object and the Worldline formulation was run with the old Lattice2D object and they produced 4 or 5 digits of agreement on small lattices. Then we could be sure that the Villain side had been upgraded correctly and we then separately upgraded the Worldline formulation and checked again for statistical agreement. * Port generators and worm to compact Form/d. We started with D=2 guards to ensure we could migrate the lattice infrastructure separately from worrying about higher-D physics. It was in this step where we ran into the need for higher-dimensional checkerboarding, co/face sums, and so on. * Fix Winding_Winding.Villain to return (N,N) displacement array. Where we landed was to sum over all planes to remove the leading form index. You could in principle measure cross-correlators. Basically all two-point correlation functions might have previously carried form labels; in many cases we just average across the same-form elements. * Observables were updated to remove D=2 assumptions when possible; the notable un-updated examples are taxicab observables---but these should be more effectively measured inline with worms anyway. # Physics and Analysis Changes * Remove D=2-specific TWrapping and XWrapping aliases (not good in D≠2) but also add a WrappingSquared observable. * Replace HolonomyUpdate with CohomologyUpdate The old HolonomyUpdate naively generalized a 2D construction to D dimensions, proposing independent position-dependent h(x_perp) per direction, which made d(Δn) ≠ 0 and broke the dn ≡ 0 (mod W) constraint. CohomologyUpdate uses the correct construction: a single scalar h_μ added to n_μ on the slice x_μ = 0 (all perpendicular positions). Because h_μ is constant, d(Δn) = 0 exactly, so the constraint is preserved for any W while the winding number w_μ (the H^1(T^D, Z) class) changes by h_μ. * Generalize the worldline ClassicWorm from 2D to arbitrary D. The physical interpretation of the Villain worm for D ≠ 2 is less obvious and we haven't tried. The issue is that in D=2 you cross 1 link to move a vortex so that the worm lives on the plaquettes / sites of the dual lattice; in other D you need to do... something else. * Normalized correlator DerivedQuantities: Spin_Spin_Normalized and Vortex_Vortex_Normalized which are essentially no-ops except for inline worm measurements and update other DerivedQuantities to depend on this data rather than normalize in each further dq. * Non-scalar correlators are form-direction-averaged as mentioned above. * Some observables that require stencils have their stencils cached more aggressively. * Autocorrelation now does not raise when fluctuations are too low, but it does emit a logging warning. Fall back to τ = ⌈len/2⌉ when no observable fluctuates enough. This solves a long-annoying safety 'feature' that 'helped' us avoid bad analyses and could really interrupt short-run tests. # Software Improvements * Add Batch container and wire production stack; add compact validation. Introduce Batch for configuration/observable columns with HDF5 persistence, layout translation between production and compact Form conventions, and statistical comparison tooling so compact Villain MC can be checked against the existing Lattice2D path without breaking current scripts. * Harden Batch analysis boundaries for legacy HDF5 weight/index columns. * Use Batch.as_array at blocking, bootstrap, and plot_history boundaries so pre-Batch extendable.array columns still work after from_h5. * Batch does some basic typechecking to ensure that no data is lost---you can't write a float into an int-holding Batch, for example. # Documentation, Tests, and Examples * Minor docstring improvements for pre-existing infrastructure. * Fix RTD :source: linking for non-main branches to github source even on non-HEAD. ReadTheDocs sets READTHEDOCS_VERSION to the version slug (e.g. four-dimensional) during builds. The fix is to check that environment variable first. * Upgrade sphinx versions and handle some things that broke. - Replace \begin{align}...\end{align} with \begin{aligned}...\end{aligned} throughout all .. math:: blocks: Sphinx wraps any block containing \\ in \begin{split}...\end{split}, and MathJax rejects \begin{align} nested inside \begin{split} with "Erroneous nesting of equation structures". The \begin{aligned} environment is an inner environment safe to nest inside split. - Escape underscores as \_ inside \texttt{} and \text{} in all math contexts: MathJax 3 treats _ inside \texttt{} as a subscript marker / text-mode error, producing "'_' allowed only in math mode" for names like distance_squared, Vortex_Vortex, interval_phi, etc. - Add sphinx-math-dollar>=1.3 to pyproject.toml dependencies. - Use uv run --with sphinx-toolbox in Makefile to avoid toolbox dependency conflict with sphinx-tabs and sphinx-autodoc-typehints. - Add sphinx-git>=11.0.0 to pyproject.toml (was in conf.py but not installed). - Exclude .venv from Sphinx source scan (exclude_patterns). - Insert project root into sys.path in conf.py so autodoc can import supervillain. * Add [tool.pytest.ini_options] to pyproject.toml: pythonpath = ["."] so that `uv run pytest` from the project root finds supervillain without PYTHONPATH, and testpaths = ["test"] to set the default discovery path. * Add make livehtml target (sphinx-autobuild). * Document Batch, Form, the interlaced picture, and sign conventions. - Add Batch to the ensemble docs page alongside Configurations. - New Differential Forms page (form.rst): Form class, exterior calculus operators, and a sign-conventions section deriving every sign as the signature of the permutation sorting the component direction tuples. - Explain the interlaced (doubled-lattice) picture at the top of the Lattices page, illustrated by example/plot/lattice/layout.py. - Document the standalone interlaced module under Reference Implementations and give it a proper module docstring. * Document and test interlaced forms; split interlaced tests into own file. * We have added a large suite of tests. - Tests that check ensure the interlaced data format matches the original notes - Tests that check the dense data format can round-trip to and from the interlaced format. - Tests that check that [data format, lattice operations] = 0. - Tests that check d, δ, *, and wedge do not give 0 (which is otherwise a sneaky way to pass other tests). - Tests that 'direct' calculations of ΔS match the obvious subtraction of two evaluations of S. - Tests that check the Batch dtype handling. * Example scripts we first migrated to the new arbitrary-D Lattice object with D=2. Once the generators and observables were ready they got --D flags. * example/action-comparison.py: add a correlator figure; show both figures together and save to one PDF --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>Fix missing : syntax error (#149) by Evan Berkowitz at 2024-09-23 12:17:03
Version/1.0.0 (#148) by Evan Berkowitz at 2024-09-23 11:32:45
* Bump to version 1
documentation/publications (#147) by Evan Berkowitz at 2024-09-23 11:19:23
DOCS ADDITIONS ============== * Publications * Compact boson documentation * Update 3450 reference with publication details * Support * Sidebar links * ORCID IDs + handle trademark rights * Contributor + collaborator affiliations + contact * Zenodo badge * CITATION.cff DOCS FIXES ========== * Squash example/plot/{comparison,forms}.py warning The fix was simple: just separate the marker styling from coloring. The point is that in the p={1,2} we just want to draw background-color markers, not color them according to a cmap. * We no longer restraing W=1 in the Villain case. * Remove TODO about lattice irrep projection * Include supervillain logo on main docs page
Hotfix: dopey axis labeling (#146) by Evan Berkowitz at 2024-09-18 09:08:02
Documentation/lattice derivative pictures (#145) by Evan Berkowitz at 2024-09-18 08:56:32
LATTICE DOCUMENTATION ===================== * Examples visualizing Lattice2D.{d,delta} + explanation. * Example visualizing data layout + explanation.
Feature/production (#144) by Evan Berkowitz at 2024-09-13 09:10:33
* Legible str(Worm generators) * Log generator report during ensemble.generate * Derived registry This makes it easy to loop everything a Bootstrap object understands: the primary observables AND the derived quantities, by doing eg. ```python for o in (supervillain.observables | supervillain.derivedQuantities): ... ``` * cli.input_file type to parse modules * Use hammer in tests * Bootstrap.estimate only collapses the bootstrap axis Previously the estimate of any observable at all whatsoever would produce a single number, even a two-point correlator, which should have produced a whole volume's worth of numbers. * Feature/numba worm (#142) * numba-aware _Lattice2D stub * numba acceleration of worldline worm * old implementation moved to reference_implementations.worldline.ClassicWorm * Add numba to installation requirements.txt * Needs numba 0.60.0 to avoid [issue when passing np.rng objects](https://numba.discourse.group/t/numba-not-recognizing-numpy-random-generator-obj/1766/5) * Monitors Monitors are do-nothing generators which let you perform arbitrary actions during the generation loop. * Fix example/action-comparison.py cli defaults + types * Require recent pandas * Villain worm with numba acceleration * test_validity checks no constraint-violating cfgs are generated * Spun out production scripts into their own repo. See supervillain-generalized-bkt-transition commit c6ef22b9044f8af9a06dd2240584f6e0baa95698changes.rst contains recent git log (#141) by Evan Berkowitz at 2024-08-27 14:09:57
Also remove the untracked / uncommitted changes; that seems to appear on RtD even though the repo there should be clean. I assume it's because the compilation produces some h5 files, but why aren't they ignored?
Feature/infinite w (#140) by Evan Berkowitz at 2024-08-23 19:37:48
# W=∞ Documentation ------------- * What follows: (integer v)/W --> (real v)/2π Derive the substitution rule for the rest of this branch. * Comments explaining choices in Hammers. Code ---- * Critical scaling dimensions Δ_V and Δ_S for the W=∞ case * Worldline Action adaptations for W=∞ * Introduce _W to make the simple replacement W-->2π when v is real. * v is float when W=∞. * Most Worldline updates just need to use _W * The VortexUpdate is trickier with W=∞ The main thing is that it needs to draw from a real-valued distribution, not a discrete choice of integers. * Update all W dependent observables It's only 2! Almost all that are sensitive to W are through Links, which we update here. * Tweak validity for Villain configurations at W=∞ * Harmonize worm tallying This isn't a bugfix exactly, but it does affect the matching between self-dual W=∞ computations. The issue is essentially that by tallying at different times we slightly change the histograms of the inline observables. In particular, different choices slightly change the tally at 0 displacement, resulting in differing normalizations. This harmonizes those choices so that the self-dual correlator match as close as we care to measure. * Update Villain hammer to handle W=∞ specially * Adjustable Hammer The worm is pure python and the slowest generator included in the Hammers. Therefore we add an adjustable parameter to control how many worms are done per iteration. This essentially controls both the runtime and the number of inline observables. Examples -------- * example/no-vortices.py Produces results at W=∞. * Generators log at the DEBUG level, not INFO so that examples can log at the INFO level more helpfully. * Correctly parse W=∞ using supervillain.cli.W * Tweak default parameters for inline demo