Skip to content

Periodic ASEP: two hopping rates

The worked bias-scan tutorial separates relaxation and oscillation while keeping the total hopping rate fixed.

Status: precision-generic relaxation-gap library and bethe-asep-pbc frontend implemented. This extends TASEP to nonnegative right and left hopping rates, including the symmetric endpoint. It does not enumerate the full spectrum or implement open reservoirs.

Physical convention and API

Particles hop to an empty neighbouring site on a periodic ring at rates r and s. At least one rate must be positive; they need not sum to one. As in TASEP, dP/dt=M P, with columns of M summing to zero. Eigenvalues are inverse-time relaxation rates, not quantum energies. The stationary eigenvalue is zero.

#include <bethe/asep.hpp>
auto state = bethe::asep::relaxation_gap(32, 8, 1.0, 0.5);
if (state.converged && state.gap) {
  // Positive decay gap: *state.gap == -state.eigenvalue->real().
  // Nonnegative angular frequency: state.eigenvalue->imag().
}

The arithmetic is fp64, long-double, fp128 or explicit MPFR precision. Reflection and particle–hole symmetry reduce the calculation to \(n =\min (N,L -N)\) and \(x =\min (r,s)/\max (r,s)\). We select the conjugate eigenvalue with nonnegative imaginary part, without assigning it a physical momentum in the original sector. For empty/full sectors there is only a stationary state: stationary_only is successful, but both gap and eigenvalue are absent.

One-particle/one-hole results are analytic:

\[ \lambda=-2(r+s)\sin^2(\pi/L)+i\lvert r-s\rvert\sin(2\pi/L). \]

At r=s the gap is 4r sin²(pi/L) for every nontrivial filling, with zero frequency. These analytic cases require no iterative roots. At L=2 both directions reach the same neighbouring site and their rates add.

Command-line use

bethe-asep-pbc 32 --particles 8 --right-rate 1 --left-rate 0.5 --roots
bethe-asep-pbc 64 --particles 32 --left-rate 1 --precision long-double
bethe-asep-pbc 32 --particles 8 --left-rate 0.5 --roots --json rates.json \
  --csv-table relaxation=rates.csv --tsv-table roots=roots.tsv
bethe-asep-pbc --references

L and --particles are required. Rates default to right=1, left=0 (TASEP). The shared --precision choices are fp64, long-double and fp128 when enabled. With Uni20 MPFR scalars, bits-N and digits-N select explicit arbitrary precision using normal CPU/provider LU dispatch. The relaxation schema is shared with TASEP: has_mode, lambda_real, lambda_imag, gap, frequency, residual, iterations, seed_iterations, converged, status. Frequency is angular frequency, not cycles per time.

--roots adds index,v_real,v_imag, the scaled coordinates described below. Metadata records the wave root index and complex wave base needed to reconstruct z, the input rates, all numerical controls, continuation attempts, seed Newton updates, last reached rate ratio, provenance and CPU time. Analytic results have no root rows or wave-base metadata values. Failed iterative calculations have null root coordinates and null physical observables; they exit 2. Empty/full sectors succeed with has_mode=false and null observables.

--max-iterations limits each continuation corrector; --max-continuation-steps limits all attempts. --max-seed-iterations, --max-seed-newton-iterations, --seed-tolerance and --max-sites control the TASEP seed. --tolerance controls the ASEP rescaled residual. The two residual normalizations differ: at the exact TASEP endpoint the reported residual is the seed's logarithmic residual.

All shared output options, including streaming and no-retain exports, apply. Invalid inputs exit 1 before touching files, including existing --force targets. References appear only with --references.

Equations and continuation

With the larger rate factored out, the Bethe equations are

\[ \begin{aligned} z_i^L&=(-1)^{n-1}\prod_{j\ne i} \frac{xz_iz_j-(1+x)z_i+1}{xz_iz_j-(1+x)z_j+1},\\{} \frac{\lambda}{\max(r,s)}&=\sum_j\left(xz_j+\frac1{z_j}-1-x\right). \end{aligned} \]

These are the rate-rescaled equations (66) and (69) of Golinelli–Mallick (2006), using reflection to place the larger rate in the inverse-z term. The starting branch is the existing TASEP first-relaxation solution, not a new independent seed prescription. Adaptive continuation increases x from zero to the requested ratio. Each step solves the coupled logarithmic equations using an analytic Jacobian and the shared recoverable Newton solver.

Near symmetric hopping, n-1 roots approach one. Ordinary z coordinates lose the small bias and can give a converged-looking but inaccurate frequency. We instead store finite scaled coordinates v:

\[ \begin{aligned} \delta&=\frac{\max(r,s)-\min(r,s)}{\max(r,s)},\\{} z_j&=1+\delta v_j&&\text{(ordinary roots)},\\{} z_{\mathrm{wave}}&=z_0+\delta v_{\mathrm{wave}}&&\text{(one finite-wave root)},\\{} z_0&=e^{\pm2\pi i/L}. \end{aligned} \]

scaled_roots, wave_index, and wave_base=z0-1 expose this representation. The rescaled residual divides the logarithmic equations by delta and L; the first-harmonic driving phase is removed analytically. A shared stable complex \(\log (1+z)\) helper retains tiny increments. The eigenvalue is evaluated as an analytic finite-wave contribution plus small corrections, preserving frequencies even when the bias is only a few native epsilons. Root separation and the translation factor are checked before publishing an observable.

The first TASEP relaxation branch is followed continuously; this is not an exhaustive search proving that no other branch overtakes it at every size and rate. Small-ring full-spectrum comparisons independently check the branch selection. Numerical convergence is not an interval certification.

Budgets and failures

Options<Real> supplies tolerance (128 native epsilons), max_iterations (100 Newton updates per continuation attempt), max_continuation_steps (256 attempts, including rejected ones), and the existing tasep::Options as seed_options (including its default 256-site work budget). Increasing the size budget does not guarantee convergence.

iterations counts accepted Newton updates across all attempted stages; seed_iterations and seed_newton_iterations report the separate seed work. reached_ratio and residual_norm describe the last successfully reached stage, not a claim of convergence at the requested rates when continuation fails. Failure statuses include seed_limit, iteration_limit, continuation_limit, stalled, and precision_limit. Failed solves never publish a gap or eigenvalue; retained coordinates are diagnostic only. Invalid parameters and exceeded size budgets throw. Overflowing physical rates are also rejected rather than reported as a successful infinite gap.

Reusing a seed across rate queries

For many rate pairs at fixed size and filling, prepare the unit-rate TASEP state once:

#include <bethe/asep.hpp>
bethe::asep::PreparedGap<double> const prepared(32, 8);
auto a = prepared.at_rates(1.0, 0.3);
auto b = prepared.at_rates(1.0, 0.9);

The object owns its options and seed. Concurrent const queries borrow that immutable seed and allocate independent continuation roots, Newton matrices and diagnostics. Each query starts from the same TASEP state; a difficult rate pair cannot change another query's starting point or budget. Existing relaxation_gap calls retain their behavior, including avoiding seed work for analytic sectors and equal rates. Prefer that direct function for a single request or an entirely analytic curve.

seed_state() exposes a const view of the preparation result. A failed seed remains a numerical result, propagated to nonanalytic queries; an analytic endpoint can still succeed. Invalid preparation controls throw. Returned seed_iterations and seed_newton_iterations describe the shared seed's construction, so summing those fields over a curve would overcount preparation work. Query continuation counters retain their original meaning.

The Async example submits preparation and its consumer before either is ready. The existing reader-dependent grid retains the background through completion, limits active/uncollected results and collects rows in rate order. It waits on operation results; there is no global scheduler drain. From a build directory configured with -DBETHE_BUILD_EXAMPLES=ON:

cmake --build . --target bethe-async-asep-example -j2
OPENBLAS_NUM_THREADS=1 OMP_NUM_THREADS=1 \
  ./examples/bethe-async-asep-example prepared 32 8 129 8 fp64

Arguments are seed mode (prepared or independent), sites, particles, points, threads and precision. Zero threads selects direct serial execution; positive counts use Async, capped by the point count and admission window 32. The right rate is one and left rates cover [0,0.9] inclusively; a one-point request uses 0.5. Numerical controls remain the model defaults. The example retains complete states for printing after completion, so its output storage grows with the requested point count. Its timing includes preparation, scheduler and collection but excludes printing. The existing single-request frontend and physical state family are unchanged.

See measurements and limits. The example accepts native binary64, long double and configured binary128. The library also supports explicit MPFR requests through complex arithmetic, seed selection, Newton controls, continuation and all failure results; the example's precision selector remains native-only.

Validation and next step

ASEP and TASEP share an independent test-only configuration-space Markov matrix builder. Every nontrivial filling at L=2 through 9 is compared against its full spectrum at six hopping ratios, including both endpoints. A separate 90-digit ten-configuration reference checks native precision at L=5, N=2, r=1, s=1/2. All enabled precisions check original multiplicative equations, analytic Jacobian, rate scaling, reflection/particle–hole symmetry, selected rings through 32 sites, failure budgets, and a bias only eight working-precision epsilons from symmetry. Dense diagonalization is never a production fallback.

Prepared and direct queries compare every state field, including complex roots, wave representation, residuals and work counters, across both rate directions, particle-hole sectors, analytic endpoints and failure budgets. Two Async grids share one preparation after submission-local handles disappear, under deferred and one/four-worker scheduling. They retain complete numerical seed failures and preserve the independently successful analytic endpoint.

Frontend regressions additionally cover native rate parsing, rate/reflection symmetry, analytic and TASEP endpoints, all exposed iteration budgets, tiny bias, overflow, shared help/reference policy, JSON/CSV/TSV exports, streaming/no-retain output and invalid-input file protection. bethe-tasep-pbc remains right-only; its options have not silently changed.

Further work includes other relaxation branches and open-reservoir boundaries; neither is included in this leading periodic mode calculation.

Explicit precision

bethe-asep-pbc 32 --particles 8 --left-rate 0.5 --precision bits-160 --roots

With Uni20 MPFR/MPC enabled, bits-N and digits-N reach the TASEP seed, continuation, cancellation-safe complex logarithms, real-block Newton solve, scaled roots and diagnostics. Normal Uni20 CPU/provider dispatch supplies LU. The scalar library requires matching finite precision for both rates and the continuation/seed controls; it does not change ambient MPFR precision.

using R = uni20::mpreal;
auto p = uni20::Precision::bits(160);
bethe::asep::Options<R> options(p);
bethe::asep::PreparedGap<R> prepared(32, 8, options);
auto state = prepared.at_rates(R(1, p), R(1, p) / 2);

Prepared queries reuse one immutable unit-rate TASEP seed. Each query owns its continuation scratch, so rate grids at different precisions can compose through Async without synchronizing precision defaults. Observe the final grid result; its completion includes every admitted query. The single-request CLI stays serial, and each continuation remains sequential.

Independent ten-state Markov-matrix references test accuracy growth through 256 bits. Tests also retain the tiny-bias drift as the symmetric point is approached, compare real-block Jacobians, and check mixed-precision shared-seed Async results field by field against direct solves, including failed seeds with successful analytic endpoint queries. More arithmetic bits do not remove the existing continuation/seed/Newton work limits or establish completeness beyond the selected relaxation branch.