Changelog¶
All notable changes between releases of TransitionListener.
The format follows Keep a Changelog, and the project adheres to Semantic Versioning.
[Unreleased]¶
Added¶
Four verdicts the solver formed but never reported are now observables.
WARNING:accuracy_targets_missedand the threeDIAG:accuracy_*_uncertaintyvalues say whether the accepted percolation profile metacc_tperc,acc_tfinalandacc_rh. Those targets are advisory – the controller accepts either way – so this is the only record of whether they were honoured; a profile whoseRHmissed its 1% target was previously indistinguishable from one that met it, with a 90th-percentile spread of 27.6%. The warning false with finite uncertainties means the targets were met; true means they could not be certified, which covers a target genuinely missed as well as a profile accepted with no comparable second estimate to measure convergence against; false withnanmeans no verdict was formed at all, which is the fixed step size backend and the adaptive controller’s iteration-limit exit.WARNING:v_wall_no_solutionfires wherefind_vwreturns exactly 0, which is a verdict that no wall solution exists but which zeroes every kinetic energy fraction, soLISA_SNRcomes out exactly 0.0 and reads as a prediction of no signal; note thatv_wall == 1is the normal outcome on a supercooled line, so only the exact zero is a non-solution.WARNING:v_wall_branch_ambiguousfires where the wall-velocity residual changes sign more than once between adjacent samples of the search grid, i.e. where the branch was chosen rather than determined.A refusal to complete reports the percolation temperature it had already determined. All 14 such points on the 2HDM marginal line, the 29-point zoom at the no-percolation edge, reached
Pintbetween 0.3215 and 0.7640, abovef_perc = 0.28957, soTpercwas in hand when the point was refused.Four diagnostics of how a point was reached, rather than of what it is.
WARNING:action_rescue_attemptedsays that actions were recomputed with the path deformation tightened, by either the rate-jitter rescue or the fit rescue above;WARNING:action_rescue_failedsays that this did not settle the quantity that prompted it.DIAG:action_rescue_attemptscounts the actions recomputed andDIAG:runtime_sgives the wall clock of the point, which is what makes the cost of a rescue visible: a rescued 2HDM point took 1887 s against about 775 s without one. The rate-jitter rescue already recorded its outcome internally and nothing read it. These are written to1_All_params.txtunder their ownDiagnostics:heading, apart from the observables, so that two runs of one point still agree there byte for byte.Output column
Treh_DS_GeV: the reheating temperature of the transitioning sector, i.e. the fields of the potential and the coupled radiation bath.Model attribute
SM_bath("coupled"or"decoupled") that names the radiation bath holding the Standard Model. If it is not set, TL takes the bath whose tables aree_geffSM, and warns if both are. A model with Standard Model fields in its potential (e.g. the 2HDM) cannot decouple the Standard Model; TL raises an error when it is set up that way.constants.h_eff_today, today’s entropy degrees of freedom.Setting
entropy_definitionof the percolation solver,"dof_table"(default) or"eff_potential", with the run-time overridepercolation_entropy_definition. It selects the thermodynamics of the expansion history. Both describe the same plasma, the fields of the potential and the coupled radiation bath without the decoupled one, and differ in how they treat the fields."dof_table"counts them as free particles at their zero-temperature masses and adds the tabulated entropy degrees of freedom of the coupled bath."eff_potential"takes-dV/dTof the effective potential, which gives the fields their thermal masses and the Arnold-Espinosa daisy term; it carries the tabulated bath with its perturbative corrections too, since the field-independent part of the potential is built from the same tables, and what it lacks is those corrections for the fields of the potential themselves. Neither scheme contains the other: the counted one has the perturbative corrections everywhere and no thermal masses, the potential one has the thermal masses and the daisy term but free-particle counting for the fields. No published work decides between them, so the difference is a modelling uncertainty that can now be measured by running both.A flag for points where the entropy scheme matters.
entropy_definitionchooses between two approximations to one entropy density, and neither contains the other, so the choice is a modelling uncertainty of the expansion history rather than a numerical one. Every adaptive step size run insound_speedmode now evaluates the other scheme on the support that fixed the percolation temperature and reportsDIAG:entropy_scheme_cs2_spread, the median relative difference between the two schemes’3 c_s^2over that support, andDIAG:entropy_scheme_lna_gap, the difference of their logarithmic entropy ratios over three.WARNING:entropy_scheme_sensitiveis raised when the spread exceedspercolation_entropy_scheme_warn_threshold, 4% by default, and the comparison can be switched off withpercolation_entropy_scheme_diagnostic. The fixed step size solver does not readentropy_definitionand refuses anything but the default, so it has no second scheme to compare against: it writes the flag as false and both diagnostics asnan. It costs one further pass over the percolation support to build the other scheme’s history, which is three entropy evaluations per support point, at the temperature and at both endpoints of the derivative stencil, and no further bounce actions. Measured on the example point, the runtime was 121.3 s against 121.6 s without the comparison, andTpercandR_*are unchanged.The median spread is an estimate of how far the mean bubble separation of that point moves between the two schemes. Over 91 points of four scan lines, each run in both schemes so that the shift is known, the ratio of the estimate to the measured shift has median 1.06 and lies between 0.88 and 1.29 for eight points in ten, with 93% of points inside a factor of two; the bias is between 1.00 and 1.17 on every line separately.
The default threshold says “flag a point whose
R_*is uncertain at about the five per cent level from this choice”. It sits a little below five so that the scatter of the estimate does not hide such a point, and the precise value is not critical. On the calibration sample four per cent flags one of the ninety-one, whose separation moves by 3.7%; the largest measured shift in that sample is 3.8%, so the sample constrains the estimate rather than the threshold. A run that wants the weaker cases can lower it: at 3.5% the sample flags 6 points, every one of which moves by more than 2.9%, and none that moves by less than 2%.Two choices behind those numbers are worth recording. The statistic is the median over the support and not the largest value, because the shift integrates the difference over the whole history: the maximum overstates it by a factor 1.8 and a single support temperature that has lost a usable sound speed in one scheme drives it to 100% where the separation moves by a few per cent. And
DIAG:entropy_scheme_lna_gapis reported but is not the criterion: it is the linearised estimate of the same shift, and its ratio to the measured shift has median 0.08 on an abelian dark Higgs line, 1.0 on a conformal dark U(1) line and 5.2 on a 2HDM line, reaching 109% estimated against 3.8% measured at one 2HDM point. Read it as a diagnostic of the expansion history, not as a prediction for an observable.
Changed¶
The action-rate jitter gate no longer judges a rate that has died. It defines its band by probability,
0.01 <= P <= 0.9, but measures the smoothness of the rate, and under strong supercoolingPclimbs pastf_percwhilelog10(Gamma/H^4)falls through hundreds of decades. One quadratic inln Tcannot describe that: with the exemption disabled a perfectly smooth synthetic band is flagged with a 39.8-decade residual. All 22 rejections measured across the coarse, refined and marginal 2HDM lines sat 40.5 to 688.5 decades below the in-band rate peak, and 16 lay past percolation, where they cannot moveTperc,RHoralpha. Samples more than 30 decades below the peak are now excluded, with liveness taken from the cold-side running maximum so that a downward spike cannot exempt itself.percolation_maxitis raised from 10 to 20. Every point rejected for an unresolvedDelta Phad reached the support-update limit with 112 to 119 action evaluations unspent. This closes that class at about 2% more action solves. The setting is shared with the fixed-step backend, where each iteration recomputes the whole profile and non_action_maxbounds it, so a non-converging fixed-step run can spend up to twice the action solves and one that previously stopped at iteration 10 can return a differentTperc.The hybrid wall-velocity limit is found by searching its range.
Hydrodynamics.max_alreturned its search bound when the matching residual had not crossed zero by the top of the range, which is correct only while that residual is monotonic. Where it is not, the bound enteredalN > max_alas though it were a physical strength, the runaway branch was skipped, and a wall that should run away was computed as a hybrid:v_wallcame back 0.7475 and 0.9509 instead of 1 at two couplings, taking the LISA SNR at the first of them from 0.8076 to 11.269, a factor 14. The crossing is now sought across the range. This departs from the reference implementation ofarxiv:2303.10171, from which the routine is taken verbatim, rather than fixing a defect in TransitionListener. Where the residual is monotonic the answer is unchanged, and 125 of 127 couplings on the 2HDM line are bit-identical. Where it never goes negative there is no subsonic branch to bound at all: the old code then handedroot_scalara bracket with equal signs at both ends and raised a bareValueError: f(a) and f(b) must have different signs, which nothing upstream types, so the point was reported as error -1. Sweeping 15 x 15 x 11 triples withc_b^2andc_s^2in [0.05, 1/3] andpsi_Nin [0.9, 1.1], 895 of the 2475 have a finite non-negative residual at both ends of the old bracket, the condition that maderoot_scalarraise, 227 of them withpsi_Nbelow one; the count depends on thepsi_Nwindow, which is why it is quoted. The search bound is reported there instead, which leaves the subsonic-against-runaway verdict tofind_vw’s ownshooting(v_J) < 0test. A strength at which the residual cannot be evaluated leaves a hole in the grid, which the search skips; the run’s ownTimeoutis re-raised rather than absorbed into one, so a point whose deadline expires inside the search is reported as a timeout instead of sampling on past it. The sign changes behindWARNING:v_wall_branch_ambiguousare counted between adjacent samples only, so a hole cannot read as a crossing that the bracketed search itself would refuse. That count reaches nothing but the flag, and over 2475 triples swept withc_b^2,c_s^2in [0.05, 1/3] andpsi_Nin [0.9, 1.1], fifteen, fifteen and eleven values, the limit is bit-identical under either counting and the flag, raised on 105 of them, changes on none: the two differ only where a hole falls on a crossing, and no triple in that sweep leaves a hole on a grid that has one.The path-deformation basis grows when the force ratio plateaus above its target instead of stopping there, about 2.5x faster on the 2HDM edge line.
A retried action starts from the straight line between the minima, as every other temperature does. Seeding a retry from a neighbouring temperature’s converged path was measured to return a non-finite action on the 2HDM, so the retry would have voided the sample it was meant to rescue; the idea is not part of the solver. The rate-jitter retry still tightens the path deformation relative to what the run configured, as above.
A model’s declared path-deformation target now reaches the bounce solver.
generic_potential.__init__tightensfRatioConvfrom the 1d default of 2e-2 to 1e-2 for multi-field models, and guards that override with a sentinel so a value the model chose is respected. The sentinel was read aftersetConfigParameters(), so it already held the model’s own value, the equality test always passed, and the model’s choice was overwritten.models/TL_2HDM_BSMPT_highacc.pydeclaresfRatioConv = 5e-3and every run of it had been using 1e-2. The two settings are not equivalent: at the 2HDM edge line (lambda3 = 5.8164076664, T = 26.7116 GeV) they giveS_3/Tof 211.518 and 212.086, a difference of 0.247 orders of magnitude in the nucleation rate, so results from that model variant move. Models that make no choice of their own are unaffected and still get 1e-2.The rate-jitter rescue always has real margin over what the run configured, instead of only clamping to a fixed target a model may already declare. The clamp was
min(current, 5e-3)forfRatioConvandmin(current, 1.0)forconverge_0, which are exactly the valuesR2HDM_HighAcc_NAct100_Conv1_FRatio005declares: every deformation parameter of the “tight” set was then bit-identical to the run’s and the rescue recomputed the outlier action with the settings that produced it.fRatioConvis now divided by a further factor 5 after the historical cap of 5e-3, so there is always real margin and a run that already asks for something stricter still keeps it. Measured against the configured value, the tight target is 1e-3 for any run at or above 5e-3 – a factor 10 below the multi-field default of 1e-2 and a factor 20 below the 1d default of 2e-2 – and one fifth of the configured value below that.converge_0keeps the plainmin(current, 1.0)clamp, so the margin comes fromfRatioConvalone. HalvingfRatioConvfrom 1e-2 to 5e-3 took the action jitter from 0.78 to 0.28 rms inS_3/Ton the 2HDM edge line, and the cost is bounded because the rescue only recomputes the handful of outlier temperatures it targets.One entropy for the expansion history: the time-temperature relation took the scale factor from the counted degrees of freedom and the sound speed from the effective potential. These are the same relation, since
1/(3 c_s^2) = 1 + (1/3) d ln g_*s/d ln T: a constantg_*s,c_s^2 = 1/3anda ~ 1/Tare one assumption and not three. Both now come from the entropy selected byentropy_definition, and both are taken along the traced phase: the sound speed is the logarithmic derivative of that same entropy, so it carries thed2V/dXdT * dX/dTterm that a derivative at fixed field value drops. That term is exactly zero for a phase pinned at the origin and reaches 0.09% of3 c_s^2at a drift ofdX/dT = 0.5on the 2HDM, so it matters only where the symmetric phase moves with temperature.Tperc, the mean bubble separation and(beta/H)_S3all belong to one equation of state. How much the choice is worth is a question for the first two of those:(beta/H)_S3is the slope of the action, and at the default path deformation that slope is limited by the scatter ofS3/Trather than by the thermodynamics, on the 2HDM line in particular. The default,"dof_table", stays defined below about 2 MeV, where after neutrino decoupling no single pressure withdp/dT = sexists and the potential route has nothing to refer to. How far apart the two are is a property of the model. As a fixed-field probe of the symmetric-phase thermodynamics at the 2HDM point oftests/test_potential_broadcasting.py(lambda1 = 0.006, lambda2 = 0.25, lambda3 = 8.27, lambda4 = -2.55, lambda5 = 0.76, m12^2 = 14186.7 GeV^2, tan_beta = 17.7, v = 246.22 GeV), with the fields held at the origin: over T = 160 to 31.2 GeV, which is the range in which that phase is traced, the counted route gives3 c_s^2between 0.977 and 0.997 against 0.955 to 1.037 from the potential, whose sound speed follows the thermal masses of the modes that are becoming heavy, a separation of 5.5%. Continued to 20 GeV, below the traced range, the potential route falls to 0.765 and the separation reaches 24%, but that is extrapolation: the phase is traced only down to 31.11 GeV and this point does not percolate at all. The window is part of the statement.This moves existing results. The default sound speed previously came from the potential while the scale factor came from the counted degrees of freedom, so every adaptive run with the default
time_temperature_mode = "sound_speed"changes. On the released example point ofexamples/example_point.yaml(conformal dark U(1), g = 0.7, v = 0.1 GeV, y = 0.01) the shifts are small, because that model is close to conformal and the two entropies nearly agree:observable
before
after
change
Tperc_SM_GeV0.0022119
0.0022120
+0.005%
alpha387.10
387.04
-0.017%
RH0.070683
0.070726
+0.061%
betaH_RH62.640
62.601
-0.062%
betaH_S363.232
63.190
-0.066%
Models whose
g_*svaries strongly across the transition move much more. Over 95 points on four lines (a 2HDMlambda_3scan, an abelian dark Higgslambdascan, a conformal dark U(1)gscan and nine single benchmarks), the median shift against the previous mixed default is 0.09% inTpercand 2.4% inR_*on the 2HDM line, reaching 3.9%, while the abelian line moves by 0.14% inR_*.Tpercis barely affected throughout; what moves is the mean bubble separation and with it(beta/H)_RH. Anyone reproducing a published number should say which entropy definition produced it.Sound speed in the pseudo-trace: the pseudo-trace strengths now divide the pressure of both phases by the broken-phase sound speed, as in arXiv:2004.06995 eq. (2.13), arXiv:2010.09744 and arXiv:2206.01130 sec. 2. Each phase was divided by its own, which leaves whatever the two phases share, a radiation bath or the zero point of the potential, in the difference. Affected:
alphaandalpha_hydin both solvers,alpha_thetabarin the adaptive solver, andalpha_thetain the fixed step size one, where that column holds the pseudo-trace strength; in the adaptive solveralpha_thetais the bag-model strength and is unchanged, as arealpha_pandalpha_e.Tperc,Treh,beta/Hand the peak frequency are unchanged, the amplitude is not. The sound speed of the percolation integral’s time-temperature relation is a different quantity and is untouched.Redshift of the gravitational-wave spectrum:
Treh_SM_GeVis the temperature of the Standard Model bath at reheating: the reheated temperature if the Standard Model is coupled to the transitioning sector,Tpercif it is decoupled; before, it always held the reheating temperature of the transitioning sector.g_eff_tot_rehandh_eff_tot_rehsum the fields of the potential, the coupled bath and the decoupled bath, each at its own temperature after reheating and weighted by its temperature ratio to the Standard Model bath,(T_i/T_SM)^4and(T_i/T_SM)^3(arXiv:2109.06208, arXiv:2311.06346), with the radiation parts taken fromkin_coupled_*andkin_decoupled_*. Before, they were evaluated atTpercbut paired with the reheating temperature; with a coupled Standard Model they are now evaluated at the reheating temperature (arXiv:2502.19478). The energy and entropy of a decoupled dark sector are assumed to end up in the photon bath without entropy injection (D = 1). This changes spectra and signal-to-noise ratios also without a decoupled bath: by a fraction of a per cent where the degrees of freedom barely change betweenTpercandTreh, but by up to a factor 1.36 in peak frequency and 0.75 in amplitude on the strongly supercooled conformal dark U(1) line (y = 0.01,v = 0.14 GeV), whereTpercfalls to 40 keV andTrehis 10.6 MeV.g_eff_tot_rehandh_eff_tot_rehcount the Standard Model fields of the potential. The 2HDM models put W, Z, t, h and further Standard Model fields into the potential and flag themis_SM; these were masked out while the Standard Model tables left no room for them, so they were counted nowhere, andg_eff_tot_rehcame out near 69 instead of near 98. The 2HDM spectra move by about +6 % in peak frequency and -10 % in amplitude; models without Standard Model fields in the potential are unaffected.Today’s entropy degrees of freedom
h0passed to the spectrum were 3.91; they are now 3.9309 (arXiv:1803.01038), the valuegwfoptalready used as its default. All amplitudes rise by 0.7 %.
Fixed¶
The bounce profile is integrated, and judged to have arrived, on the scale of the bounce and not of the gap between the minima.
findProfileholds the profile integration to an absolute errorepsabs, and that wasphitoltimesdelta_phi, the distance between the two minima. The field range the integration covers is the bounce’s own excursion,|phi(0) - phi_metaMin|, which on a supercooled transition is a fewTwhile the minima stayvapart. On the classically conformal dark U(1) at g = 0.46, y = 0.01, v = 0.14 GeV – the configuration every number in this entry is measured at – the gap is 1000 internal units at every temperature while the excursion is 4.3 to 6.1 T, sophitol |delta_phi|is 1.6e-07 of the integrated feature at T_int = 0.1 and 2.4e-02 of it at 1e-6.epsabsis now computed inside the shooting loop from the current trial bounce.integrateProfilespendsepsabson two different jobs, and both were mis-scaled. Besides controlling the Runge-Kutta step it is the radius inabs(y - [phi_metaMin, 0]) < 3*epsabsinside which a trial profile counts as having reached the false vacuum, and that verdict ends the shooting loop. Tied to the gap, that radius was a fixed absolute distance while the bounce shrank with the temperature, so3 phitol |delta_phi| / excursiongrew to above one by T_int = 1e-7: an acceptance radius wider than the whole bounce. The first trial was then declared converged with the profile having barely moved.Changing one without the other does not work, and makes things worse at some temperature. Giving the bounce’s scale to the Runge-Kutta step alone, with the acceptance radius left on the gap, takes S3/T at T_int = 1e-6 from 96.45 to 91.10 – further from the converged 102.46, because a better-integrated profile still stops at the same too-wide radius – and still returns zero at 1e-7. Giving it to the acceptance radius alone returns 96.93 at 1e-6 and 636.3 at 1e-7. Only the two together give 103.20 and 102.93. Tied to the bounce,
3*epsabs/excursionis3*phitolat every temperature.One consequence is worth stating: that acceptance test now never fires. It asks for
3*phitolof the excursion inphiand indphi, which a shooting method that stops on its own bracket does not reach, so the loop ends on(xmax - xmin) < xtolat every temperature measured. Replacing the test withFalseleaves the conformal action identical to the last digit at T_int = 0.1, 1e-4, 1e-6 and 1e-7 and leaves the whole test suite unchanged. It was only ever reached because it was scaled to the gap, and when it was reached it was wrong.How far this reaches a transition that is not supercooled depends on how thick its wall is, and it is not nothing. On the g = 0.7, y = 0.24 configuration at T = 15 that
tests/test_1d_tunneling.pyuses, whereT/vis 0.015 and the wall is thick, the two rules differ by 3.1e-08 relative at the configuredphitol = 1e-10. On the 2HDM benchmark’s supercooled grids, 97 couplings of theedgeandrefinedlines atT/vof 0.082 to 0.182, they differ by more. Over the 72 pairs that complete on both arms the percolation temperature moves by a median of 0.0039 per cent, with a 90th percentile of 0.40 and a largest move of 34.5;(beta/H)_RHby a median of 0.17 per cent with a largest of 99.8;alphaby a median of 0.016 per cent with a largest of 462. The median is the no-op this change was expected to be and the tail is not, and the tail is at the cold end of the two grids that were measured,edgeandrefined, whereT_percfalls from 37.136 GeV to 20.0 GeV overlambda3of 0.0061 and the spectrum is a steep function of it. The benchmark’smarginalgrid and its twobroadgrids are not in this campaign.8 of the 97 points change verdict:
edge 5.7918389018, and onrefined5.8099242424, 5.812995338, 5.8157252007, 5.8167488993, 5.819478762, 5.8225498575 and 5.8314219116. Four are pointsmainresolves and this code does not, three the reverse, and the last fails on both with only the code changing from 10 to 8. Which arm is right at each one is not established here: seven of the eight sit at the cold end, where each arm’s own scatter against a local fit through its neighbours has a 90th percentile of 3 to 4 per cent inT_perc, against 0.003 per cent warm of 37.5 GeV, and the sign of that residual changes with the choice of fit at five of the six points where the test can be made.The largest move does not rest on the neighbours. At
refined lambda3 = 5.8184550635,mainreturnsT_perc = 41.012GeV and(beta/H)_RH = 2058.3against 26.845 GeV and 4.5467 here.mainplaced 53 of its 197 support points inside 41.00 to 41.10 GeV, a window ofdT/T = 2.16e-03, and across it its ownS3/Truns from 106.39 to 151.40; its recorded(beta/H)_S3of -67.4 allows 0.15 units over a window that narrow, and 45.0 units ise^45in the nucleation rate. This code has one support point there, atS3/T = 150.04. Any statement that quotes a singleedgeorrefinedpoint of this benchmark has to be re-read against this branch rather than againstmain.Measured against a bounce solved a second way – the false vacuum at the origin,
V(phi) - V(0)of the unsplined potential, a wall at 30 times the escape point, and the problem reflected so that the minima handed to the solver are the bounce’s own scale rather thanv, which is a construction that cannot carry this defect – S3/T at g = 0.46, y = 0.01 was low by 0.003, 0.021, 0.144, 0.794 and 5.865 per cent at T_int = 1e-2, 1e-3, 1e-4, 1e-5 and 1e-6. It is now +0.000, +0.000, +0.005, +0.063 and +0.722 per cent at the same five temperatures, and the collapse at 1e-7 is gone. At T_int = 1e-1 both rules sit 0.55 per cent above that reference, the same offset on each, which is the path spline against the unsplined potential and not these tolerances.What is left of the 0.722 per cent at T_int = 1e-6 is not
epsabs. With the loop no longer ending on3*epsabswhat stops it is the shooting bracket(xmax - xmin) < xtol, which is absolute inxwhilexitself is 4.3e-09 there, soxtol = 1e-10resolves the escape point to 2.3 per cent only. Judging that bracket relative to thexit contains, at the samextol, gives 102.465 against the reference’s 102.461: +0.004 per cent in place of +0.722, and the same verdict at every coupling of the ladder. That is a separate change and is not made here.This reduces the couplings at which the conformal dark U(1) percolates, from a lowest g = 0.42 to 0.44, and that is the correction rather than a regression: at the temperature those couplings percolate, internal 1.8e-6, the action was 7.45 per cent low at g = 0.44, S3/T 111.823 against the reflected reference’s 120.819, and 7.90 per cent low at g = 0.43, 119.415 against 129.656. Since
Gamma ~ exp(-S3/T)atS3/Tof 120 to 130, that understatement raised the nucleation rate by 8.1e+03 and 2.8e+04 respectively. This code reproduces that reference to 0.08 per cent at both couplings, 120.921 and 129.761.Tpercmoves by -5e-05 per cent at g = 0.62 and -47 per cent at g = 0.44, the coupling now at the boundary.It takes longer, because tighter tolerances mean smaller integration steps on the same solves. Measured on
examples/example_point.yaml, the conformal dark U(1) at g = 0.7, v_GeV = 0.1, y = 0.01: 143.04 s at d66a774 against 183.92 s here, 28.6 per cent, on one core of an idle machine for observables identical to five figures. That is the same point run twice and is the only runtime figure quoted here. A per-grid cost over the 2HDM benchmark is not quoted because it is not measurable: the two arms’ runtimes per coupling scatter by 21 to 38 per cent for reasons unrelated to this change, and over 592 pairs on four grids no grid total is distinguishable from zero.The extra time is inside the integration rather than around it: counted through
run_TL, this code makes 1036calcActioncalls against 1059 and 3117integrateProfilecalls against 3150. The subprocess timeout intests/test_release_smoke.pyis raised from 180 s to 600 s accordingly, with all six of that test’s reference bands unchanged.Not addressed: below about T_int = 1e-8 the action is wrong by orders of magnitude on both sides of this change. At g = 0.44 and T_int = 1e-8 both return S3/T = 5.6e+08 against 96.50 from the reflected reference above, and the solver has lost the bounce rather than mis-integrated it. The barrier there ends 1.36 T from the false vacuum, measured from V(phi) - V(0) alone with no solver and no tolerance in it, against 1.49 T at T_int = 1e-6 where the solve works. The profile the solver returns starts 1.4e+07 T out, against 4.3 T at 1e-6 and 4.8 T at 1e-7: it has gone four orders of magnitude past the whole barrier into the region where the potential falls away, and the action it reports belongs to that excursion and not to a bounce. Nothing below T_int ~ 1e-7 should be read as converged, and the percolation of a model whose transition completes that cold is not established here.
A timeout raised inside the initial-condition root find is no longer read as a wall too thin to integrate.
errors.Timeoutcomes from a POSIX alarm handler, so it lands wherever the run happens to be,scipy.optimize.brentqincluded, and it subclassesException. The handler around that root find inSingleFieldInstanton.initialConditionsturned it into aTunnelingError, whichpathDeformation._find_profileturns into anInfiniteActionErrorandbounceActionreports as no tunnelling: a timed-out point came back as a finished one with a verdict. It is re-raised, as it already was in the path extension and the spline fit.Two temperatures are compared relative to their own size, not to an absolute floor of one and not to the hottest point of the support. The adaptive percolation decides whether a proposed temperature is already present in the support, whether two samples are duplicates, and which support point an interval endpoint refers to. Every one of those comparisons used an absolute tolerance built either as
1e-6 * max(..., 1.0)or as1e-6 * max|support|. Temperatures are in the model’s internal units, where the stable minimum sits atv_stableand aconversionFactorconverts to GeV, so an internal temperature isv_stabletimesT/vand falls below one wherever the transition is supercooled by more than1/v_stable: 4e-3 for the 2HDM, 1e-3 for the models built oninternal_scale = 1000. Both tolerance forms then become a large fraction of the temperature they are applied to.The floor of one made the presence tolerance 1e-6 in absolute terms, larger than the temperature itself below internal 1e-6. The support maximum is worse, and worse on models that are not extreme: it only needs the support to span decades, which it does whenever the bank reaches up to the critical temperature while the transition happens far below it. The 2HDM reaches both regimes. On the 144-point support of the point at
lambda3 = 5.8197, which reached internal 2.4e-13 while its hot end stayed at 76.2 – the 2HDM’sconversionFactoris one, so those are GeV too – 32 points sat below internal one, the presence tolerance was 7.6e-5, and 26 of the 143 adjacent pairs of the support’s own points fell inside it: 22 of them more than a tenth apart, the median one 172 per cent apart, and the three coldest 110 per cent apart each. The rule that replaces it merges four of the same 143, all duplicates to nine digits. A 200-point log-spaced support from internal 1e-12 to 1e-1 has 125 of its 199 adjacent pairs inside the old tolerance and none inside the new one. Either way, every point the jump refinement proposed inside a rise ofP(T)counted as already present and was dropped, the controller found nothing to add with most of its budget unspent, and the acceptance gate then rejected the profile the controller had accepted.Each comparison is now
|a - b| <= relative * max(|a|, |b|), through one helper_temperatures_match, withrelative1e-6 for presence and 1e-10 for deduplication. The new tolerance is never larger than either of the old ones, so points can only be separated, never merged: the change can add support points and action evaluations, never remove them. It is bit-identical wherever every temperature involved is at least one, which is where the floor never acted; it is not identical on a support that spans decades, whatever its absolute scale, which is the case it exists for. The 2HDM points that percolate are on the safe side of the old boundary and do not move: on the support of the point atlambda3 = 5.8106060606, which spans internal 2.2 to 76.2, the old rule merges three adjacent pairs and the new rule merges the same three, and the campaign reproduces that point’s observables unchanged. It is the points that fail to percolate whose supports reach far below one, and there the two rules part: 25, 28 and 26 of their adjacent pairs merged under the old rule against 5, 5 and 4 under the new one. Across the four dark U(1) regression datasets of the validation scans, internalTpercruns from 0.21 to 162 against an internalTcritof 84 to 316, so the floor of one is nearly inert there – 22 of their 1080 points fall below internal one – while the old presence tolerance still reached 5e-5 to 1.5e-3 of the cold end; a refinement step coarser than that is unaffected, and the jump refinement’s steps are of order a per cent.Two further absolute floors are removed for the same reason, and both are latent rather than active: the dead band around the step-1 startup centre, which at an internal window of 1e-9 stops
_count_highand_count_lowfrom seeing points that are there and makes the fill loops spend action budget replacing them, and the window that collects cached actions, which at an internal window of 1e-9 reaches a tenth of the way below it and admits actions from outside it. Both are 1e-10 absolute, so they need an internal window below about 1e-8 to matter, which is colder than any model shipped here reaches; they are removed because the expression is the same one and the next supercooled point is where it would be found. The lookup that turns the endpoints of a probability jump back into support indices took the first match of an absolute tolerance scaled by the hottest support point; on the 144-point support above it resolved 28 of the 143 adjacent pairs to at least one wrong index, 26 of them tohigh_index >= low_index, which returned “not inert” – the verdict that vetoes the repair of the jump – without reading a rate. It now matches relative to each endpoint and takes the closest support point.A fixed-step scan is untouched by all of this.
percolation_algorithm_mode="fixed_step_size"selectstransitionObservables_fixedstep, which callscalcPercAndEvolvefrombubbledynamics_fixedstep, and that module contains none of the changed names: not_temperature_grid, not_finalize_percolation_state, not the presence rule, the window tolerances or the interval-endpoint lookup.Those last two do reach the other fixed-step solver.
bubbledynamics.calcPercAndEvolverunspercolation_fixedstepsizewhen it is handed a fixed-step configuration, and there_temperature_gridbuilds the support bank and_finalize_percolation_stateapplies the 1e-10 deduplication afterwards. That path is reached from the adaptive observables module, not from a fixed-step scan, and both functions can only keep temperatures the old rule merged, and only where a temperature below one in internal units is involved.A phase no longer leaves the range of its own traced minima between two traced temperatures.
PhaseInfointerpolated the trace withsplprep(..., s=0, k=3), an interpolating cubic. The tracer does not space its temperatures evenly – it clusters them where it steps small and leaves gaps where it steps large – and a cubic through spacing ratios of that size oscillates between the nodes. The minima are now interpolated withPchipInterpolator, which is shape preserving: between two traced temperatures each field component stays between the two values traced there. It still passes through every traced node, so this is not smoothing, and past the ends of the trace it still extrapolates rather than refusing: two places inbubbledynamicsread a raise fromvalAtas a phase that cannot be evaluated at that temperature, and clamp their stencils for that reason, so a refusal there would be taken for a missing phase.The bounce solver reads the phase through
valAt, so an overshoot is handed to it as a field value the tracer never found: the solver then tunnels from a displaced point rather than from the one the tracer established, a shorter path over a lower barrier, and returns too small an action over the temperatures either side of the excursion. With the shape-preserving interpolation there is no excursion: the largest field value between two traced temperatures is the largest of the two. A trace that exhibits the excursion is the fixture oftests/test_phase_interpolation_does_not_overshoot.py, where the two interpolations are compared on it directly. That trace comes from a development model outside this repository and is kept as recorded data, not as something reproducible from the models shipped here.A displaced action is what produces the steps the rate-jitter gate flags, so removing the overshoot removes one cause of them. The comment at the action discard added in the percolation work named this overshoot as the reason couplings reached it and said the fix belonged in the phase tracing; it is updated to say the fix has landed, and the discard is kept for any other model that trips the gate.
This changes results. Where the trace is evenly spaced the two interpolations agree closely; the difference grows where the tracer left a cluster next to a gap, which on a supercooled line is the stretch nearest the end of the transition. Per-model figures are not quoted here: the campaign behind them loaded its potential from a development checkout rather than from this repository, so its numbers describe a different model. A re-validation against the models shipped here is running, and measured figures will be added when it lands.
Both solvers are affected:
phases.pyhas no fixed-step twin, andtransitionObservables.pyandtransitionObservables_fixedstep.pyboth read this onePhaseInfo.PhaseInfo.tckis replaced byPhaseInfo.interpolator; it was read nowhere outsidephases.py, and of the 114valAtcall sites insrcexactly one passesderiv, which the new interpolator supports.valAtkeeps its signature and the shape it returns for a scalar, one- or two-dimensionalT; itsderivargument now accepts any order rather than at most three, returning zero above the third. A trace carrying a non-finite temperature or field value is refused when the phase is built, where the B-spline accepted it and returnednanat every temperature of the affected component; scanning turns that into an error for the point rather thannanobservables.The bubble nucleation rate no longer grows above the temperatures whose action was computed. The percolation result’s action spline returned the action of the hottest temperature that had one for everything above it. Holding the action constant while the temperature rises lets
S3/Tfall, and the rate goes asexp(-S3/T), so the rate grew towards high temperature where the barrier grows and it has to vanish. It is now infinite there, which is the limit and is what the estimator’s own spline inpercolation_adaptivestepsizealready returned, so the two agree. The upper limit of the mean-bubble-separation integral is likewise the hottest temperature whose action is known rather than the hottest in the support, since a temperature whose solve failed carries no integrand. Only the adaptive backend is affected: the fixed step size backend builds its action spline over the finite-action temperatures withfill_value = (-inf, +inf), so it already returned an infinite action above its data and its bubble-number integrand is identically zero there.The two only differ where an action solve fails at the hot end of the support, which was one coupling of the 333 resolved across the validation scans: the 2HDM benchmark at
lambda3 = 5.7727298627, where the solve failed at T = 57.18 GeV while the hottest computed action was at 49.28 GeV. The action was held at 7441.88,S3/Tfell from 151.0 to 130.2 over that stretch, a factorexp(20.8)in the rate, and the integrand of the bubble-number integral peaked at the hot end with 99% of its weight there instead of at the percolation temperature. The bubble number density came out 7340 times too large, which put the mean bubble separation 19 times too low atRH = 0.002352against 0.044533 and 0.046287 at the neighbouring couplings,betaH_RHat 1883 against 99.4 and 95.7, and the LISA signal-to-noise ratio at 7.8 against 23.9 and 26.5. With the fix that coupling givesRH = 0.045396andbetaH_RH = 97.53, between its neighbours at 99.42 and 95.65, and the LISA signal-to-noise ratio 25.18 between 23.92 and 26.49. Where no solve fails the two rules agree and nothing moves: over the four U(1) scans behind figures 4, 12 and 13, 1082 points in all,Tcrit,Tnuc,Tperc,Treh,alpha,betaH_S3,c_sandv_wallare bit-identical at every point and every error code is unchanged, whileRHandbetaH_RHmove at 51 of the 1080 points that resolve, by at most 4.7e-04.The bounce action no longer dies where the barrier is small compared with the path.
pathDeformationset several of its numerical scales to a fixed fraction of the distance between the two minima, while the barrier is a feature whose width is set by the temperature, so in a strongly supercooled model each scale eventually exceeded it. Reported from the four-dimensional daisy-resummed rate of the conformal U(1), where the action came back infinite below T_int = 0.146 at g = 0.54 with the solver calling the potential “stable, not metastable” although the barrier was there. On the conformal dark U(1) ladder ing(y = 0.01,v = 0.14 GeV), againstmainat b31e178, the lowest coupling that percolates moves from 0.54 to 0.42: twelve couplings gain a percolation, 0.53 from “incomplete” and 0.52 down to 0.42 from “no percolation”. Two more change one failure for another, g = 0.38 and 0.36 from “no percolation” to an unresolved jump in P(T), and g = 0.40 does not percolate on either side. Where the old code also resolved it the percolation temperature is unchanged, by 1.8e-06 to 2.4e-04 per cent over g = 0.54 to 0.62, the one exception being -0.074 per cent at g = 0.55. Against TL’s ownSingleFieldInstantonon the unsplined potential the action is now right to 1.3e-08 at T_int = 0.1 and 0.01, 4.2e-07 at 1e-3, 6.6e-08 at 1e-4, 2.6e-07 at 1e-5 and 5.9e-05 at 1e-6, where before it was infinite below T_int = 0.1. Those figures measure the path and the spline, not the whole solve: the reference carries the same shooting tolerances as the solver under test,tunneling_findProfile_paramsphitol = xtol = 1e-10, and those are themselves fractions of the distance between the minima. Against a bounce converged with tolerances relative to its own profile, the action is biased low and smoothly so below about T_int = 1e-2: at g = 0.46, 131.713 against 131.899 at T_int = 1e-4 and 96.76 against 102.854 at 1e-6. That fourth scale is not touched here, so the numbers above should be read as the accuracy of the path construction at a fixed shooting tolerance, and the action below T_int = 1e-2 is not yet converged.The path extension searches for the nearest minimum. It used
scipy.optimize.fminfromx0 = 0, whose initial simplex step is 2.5e-4 of the knot spacing whatever the problem looks like. On a two-knot path that spacing is the whole path, so the end extension settled a full knot out, at the mirror of the broken minimum, because the potential is even in the field: the path ran from 1000 to -1000, connected two minima degenerate at -2.0220e+08, and the solver reported no metastable end. A rise now has to clear the rounding of the potential, since near an end it can be flat to machine precision over decades of the distance, and an extension past the metastable end is refused if it would take the potential to or below the other end, which is what destroys the metastability the bounce needs. An end with no minimum within reach is left alone.The samples that build the potential spline are placed where the barrier is, but only where the uniform grid is blind to it: fewer than two of them inside the barrier and at least a thousand of them in total. Both bounds are measured. The overhang past each end shrinks with them, and is the larger effect of the two: the potential is -2.0e+08 at the broken minimum and -9.3e-17 at the symmetric one, and 0.2 of the path past the symmetric end it is -2.4e+06, so one cubic spline through all of it is bent, just inside that end, towards a value far above the barrier. A path whose barrier the uniform grid already carries keeps exactly the samples it had, which is what leaves the 2HDM unchanged, to 2.0e-06 at T = 85.3 and 8.7e-06 at T = 48.8.
The adaptive percolation controller no longer spends its budget below the transition, and no longer refuses to repair a jump it then rejects the profile for. Eight separate faults, all found by instrumenting a 40-point 2HDM “edge line” scan on which 31 of 40 points resolved.
A percolation sample whose
H * T * 3 c_s^2has underflowed to exactly zero is marked invalid. Every factor can be positive and finite while the product underflows, and-log(0)is+inf, which the floor clamp’snp.maximumremoves for-infbut not for+inf; it then reached the PCHIP interpolants as a bareValueError: 'y' must contain only finite valueswith no typed error and no diagnostic. The bag-limit branch of the same integral does not share the exposure: on the grid that makes one of 32 general-EOS denominators underflow, itslog(1/H)transport term is still finite at 667.7 and its source term never goes+inf, because-S/Tdominates._refine_step1_rate_peakdrops non-finite samples before building its interpolant. Its peak search isnp.nanargmax, so it is written for an array that may carry them; ten lines later it handed the same array toPchipInterpolator. Captured at lambda3 = 5.8191375291 with 1 NaN among 79 samples.The step-1 scout hands step 2 the temperatures whose action came back usable as free support, not every temperature it probed. The free bank is support that costs no new action budget, so a failed cold probe handed over there plants the active grid’s cold boundary on it: traced from
[2.2235, 62.279]to[3.8032e-06, 68.772]GeV against a transition at 20-40 GeV, after which the rate-step refinement filled the span in one step (29 to 75 points).A support point whose solve has already run no longer counts against the controller’s new-action budget when that solve returned non-finite. Its cost is sunk, and counting it as pending held the whole budget for the rest of the run.
The cold range expansion stops where the bounce stops existing. Below the transition the symmetric phase is no longer metastable and every action there is non-finite; those samples are dropped by the percolation integral and by the profile rebuild, yet each one costs a bounce solve. 38-57% of all support points in every one of five recorded runs were of that kind, in one contiguous run at the cold end.
A cached action is no longer promoted into the active grid where
S_3/Thas run past anything that can nucleate. The cold actions of a completed transition do not fail, they saturate: measured at lambda3 = 5.8123128723 the action settles near 4357 andS_3/Treaches 1.15e+09 at T = 3.8e-06 internal, so the point has a perfectly finite action and a rate of exactly zero. The test is confined to candidates colder than the grid already is, becauseS_3/Tis just as large on the hot shoulder: across the 31 recorded edge-line profiles the hottest retained support point sits between 478 and 509.The rate-step refinement no longer refines an interval whose colder end has collapsed more than 1000 decades below the profile’s own rate peak. That floor is sized for deciding where to place support, where being permissive costs only a few wasted evaluations; the rate-jitter gate judges smoothness instead and carries its own, much tighter floor of 30 decades, under Changed above. A fall out of the live region exceeds any
max_log10_rate_step, so the refinement walked lambda3 = 5.8205024605 down to T = 1.4e-5 GeV withlog10(Gamma/H^4) = -1.4e8, whereupon one quadratic inln Tfitted across seven decades of temperature reported a residual of 1.6e10 orders of magnitude and advised raising the bounce precision for a sample at fourteen microelectronvolts. The floor is relative to each profile’s own peak, never absolute: contributing samples reachlog10(Gamma/H^4) = -447in absolute terms, and a strongly supercooled model has its peak at very low temperature by construction.A
Delta Pjump that the acceptance test will reject is now repairable even past the rate peak, where the post-peak inert veto used to decline it unconditionally. The two rules contradicted each other: at lambda3 = 5.8177725978 the interval [28.745, 30.453] GeV lies below the rate peak at 41.05 GeV, so the controller drove maxDelta Pfrom 0.85 to 0.12, found nothing further it was permitted to do, and accepted the profile with 119 action evaluations unspent, whereupon the gate rejected it. “Post-peak” cannot excuse a coarseP(T)in any case, sinceR_His sensitive toP(T)aboveTpercand about 97% of that interval lies inside its integration range. Where a repair exists only by this exemption the anchor remesh is offered first and the repair stays as the fallback, because at lambda3 = 5.8136778037 the repair otherwise took the slot the remesh needed and the run ended one support update short atDelta P = 0.0578.
A rejected profile says which resource ran out. The unresolved-jump rejection asserted that the controller “already spent its remaining support budget on local jump refinement”, which is frequently untrue and sends the reader to the wrong place: at lambda3 = 5.8136778037 the point was rejected with 115 of its action evaluations still unspent, having instead reached the support-update limit (
maxit, then 10 and now 20). The message now reports whichever resource actually ran out, and says nothing about a cause when the caller does not supply the numbers. Reaching the support-update limit with a repair still waiting is reported as well, naming the repairs that were outstanding.The daisy term is evaluated without throwing away its significant digits, and the sound speed is taken from the thermal part of the potential. Both are numerics: the same expressions, evaluated so that they keep their accuracy. Three cancellations stood on top of one another.
The Arnold-Espinosa term is proportional to
(m_T^2)^{3/2} - (m_0^2)^{3/2}. Written that way it subtracts two nearly equal numbers wherever the thermal correction is small against the mass, which is the whole low-temperature regime: on the conformal dark U(1) ofexamples/example_point.yamlat an internal temperature of 0.02 the two cubes are about1e9while their difference is about0.3. It is now evaluated as(m_0^2)^{3/2} [(1 + u)^{3/2} - 1]withu = Pi/m_0^2, throughexpm1(1.5 log1p(u)). That rearrangement is kept in real arithmetic, because numpy’s complexlog1pandexpm1lose a relative8e-8atu = 1e-9against1e-16for the real ones, and the+0jthat exists only to admit tachyonic modes was being applied to every mode.The thermal correction itself was taken as the difference of the mass spectra at
Tand at zero, which keeps seven of sixteen digits at that temperature and underflows to exactly zero below an internal temperature of about1e-7, silently deleting the daisy term.generic_potential.debye_massSq(X, T)provides it directly. A model that writes its Debye masses in closed form overrides it, asmodels/TL_conformal_dark_u1.pydoes, and the base class measures it for every model that does not: where the thermal part isPi = c(X) T^2, which is what the Arnold-Espinosa Debye masses are, the coefficient is read off at the model’s own scale, where the subtraction still keeps its digits, and then used at any temperature.Nothing here assumes the quadratic law. It is verified, at a second temperature and at two field points, and the base class declines whenever the check fails. The check decides four of the eight models in
models/each way. It passes for the conformal dark U(1), both dark U(1) parameterisations and the template. It fails for the three 2HDM models and for the dark flip-flop, and for one reason in all four: their bosonic masses are eigenvalues of a mass matrix whose entries go asT^2, and the eigenvalues of such a matrix do not. Onmodels/TL_2HDM.pythe two longitudinal gauge modes move their apparent coefficient by 4.6% and 11% betweenTandT/2.models/TL_dark_flipflop.pyis the reason the check uses two field points rather than one: alongX0its second field vanishes, its matrix is diagonal and the law holds to7e-18, while at a point with both fields on it is off by5e-3, so a one-point check would have accepted it and handed the daisy term aPiwrong by half a per cent. For those four there is noPito hand over and the subtraction is the only route, so declining is the correct answer rather than a missing feature.The quadratic law is checked mode by mode, with a relative tolerance and a round-off-sized absolute floor for the modes whose coefficient is exactly zero. A single tolerance scaled to the largest coefficient only ever tests that one, and a mode whose coefficient is orders of magnitude smaller could be badly non-quadratic and still pass, after which a heavy mode can make that wrong contribution matter at low temperature. None of the eight models in
models/distinguishes the two rules, the worst per-mode deviation among those that pass being8e-15, so this guards a case none of them exhibits.The verdict is settled once per model and at field points the model itself fixes, not at whichever point arrives first:
Vtotis called with random field values while a model is being constructed, and a verdict read off those would differ between runs of the same input. Models whose coefficient is field independent, which is all four that pass, cache it and never measure again. Measured on the conformal dark U(1), the base class reproduces that model’s own closed form to1e-12, and on the others it agrees with the subtraction to1e-13wherever the subtraction still works.This changes the daisy term of
models/TL_dark_U1.py,models/TL_dark_U1_g_parameterization.pyandmodels/templatePotential.py, which now get an exact thermal part where they previously got the difference of two spectra. A scalarVtotcosts 9 to 13% more on those, and 1% or less on the models that decline, since the verdict is cached. Where a model declines, the thermal part is still taken as the difference of the two spectra, as before, and the rearrangement above still improves the accuracy of that difference once it is taken.On the conformal dark U(1) an exact
Pichanges the thermal part of the potential by1.7e-3of itself at a temperature of1e-7of the scale, and at1e-9the version without it has nothing left to compare. It changesVtotby nothing measurable at any of them, which is the point: the shift lives below the last digit of the vacuum energy, and that is why the sound speed is taken from the thermal part. Andmodels/TL_conformal_dark_u1.pyimplements it with the sameT^2coefficients its mass function already uses.And
Hydrodynamics.calc_csnow differentiatesgeneric_potential.V_thermal, the temperature-dependent part of the potential, rather than the whole of it. A model that rewrites the effective potential from scratch is told by this class to overrideVtotandV1T_from_X. Such a model must now overrideV_thermalas well, which is the temperature-dependent part on its own and is what the sound speed, the pseudo-trace strengths and the wall velocity are taken from; a reconstruction from the mass spectrum would not be that model’s own thermodynamics. It is a separate hook fromV1T_from_Xon purpose: the class documentation calls the latter the temperature-dependent part ofVtot, which would include the radiation bath, while its base implementation returns neither the bath nor the daisy term, and nothing in the signature says which an override means. Adding the bath to an override that has it double counts, and not adding it to one that does not drops it, so a model that has rewrittenVtotorV1T_from_Xwithout also overridingV_thermalis told so with anerrors.PotentialErrorrather than handed a guess. No model inmodels/overrides either, so none is affected. The two are the same analytically, since what does not depend on temperature drops out of both derivatives, and differ numerically: the whole potential subtracts the vacuum energy from itself, and under supercooling that vacuum energy is the larger by ten orders of magnitude or more.And the derivative step is sized for what is being differenced.
temperatureDerivativeStepsizes it from the magnitude of the whole potential, vacuum offset included, with a sixth-root balance derived for the five-point stencils ofdVdTandd2VdT2; below a temperature of1e-3of the scale it saturates its own3e-2ceiling.helper_functions.thermalDerivativeStepreplaces it for the thermal part. There the binding balance is the round-off of the second difference against the truncation of the first,4 eps |V_th| / dT^2 |d2V_th|againstdT^2 |d3V_th| / 6 |dV_th|; the fourth derivative that would set the second difference’s own truncation nearly vanishes wherever the daisy term dominates, because thereV_thgoes asT^3andn(n-1)(n-2)(n-3) = 0atn = 3. ForV_thproportional toT^nthat balance givesdT/T = (24 eps / n(n-1)^2(n-2))^{1/4}, in which the magnitude ofV_thcancels because round-off and truncation both scale with it. The step is therefore a pure number:(eps/3)^{1/4} = 9.3e-5for radiation,(2 eps)^{1/4} = 1.45e-4for a daisy-dominatedT^3, and the radiation value is used for both.Measured together, on the second temperature derivative of the daisy term, as the relative change when the derivative step is changed by a factor ten, released against fixed, on the traced broken phase of the conformal dark U(1) at
g = 0.7:T/vas released
fixed
1e-13.7e-61.1e-71e-27.7e-71.9e-91e-37.5e-76.6e-91e-55.6e-35.8e-91e-71.12.6e-91e-9the daisy term has underflowed to zero
1.5e-9And on the sound speed itself: at this step
c_sagrees to4e-8or better, on the traced broken phase, with the plateau measured overdT/Tfrom3e-5to1e-3, at every temperature from1e-1to1e-9of the scale and atg = 0.455,0.7and0.95. Round-off takes over belowdT/T ~ 1e-5and truncation above3e-3.bubbledynamics.calcSoundSpeedSq, which both percolation backends use for the sound speed that normalises the pseudo-trace strengths, differentiates the thermal part as well. Before, the adaptive backend took the whole potential at the step rule above and the fixed-step one took it at a hard-codeddT/T = 1e-3; the two now agree by construction. Where the released version returned nothing there,alpha_thetabar,alpha_hydandalpha_hyd_wallwere not-a-number and are now finite.In the fixed-step backend that same function also fills
soundSpSq, which entersfalseVacuumVolumeGrowthRateand so the percolation integral itself, so that backend’s percolation moves slightly. It is evaluated on the symmetric phase, where there is almost no vacuum offset to cancel and therefore almost nothing to fix: measured on the conformal dark U(1) over temperatures from1e-1to1e-7of the scale, the change is at most1.9e-6relative.On the example point of
examples/example_point.yamlthe effect of all of this is nothing visible: all 54 entries of the transition table and all 58 of the observability table are unchanged to the digits the output carries, and the only new columns are the four diagnostics below. The point is healthy, which is what that shows:DIAG:c_s_step_changeis4.9e-7against its0.05alarm andDIAG:daisy_over_radiationis0.32.The cancellation-free daisy evaluation costs time, because it decides per mode which form to use. A single scalar
Vtotgoes from 132 to 173 microseconds, 31% more, of which the analytic Debye masses are about a quarter; the two cases that actually occur, all modes small and none small, are each taken in one array operation rather than through the masked general path. End to end the cost is far smaller, because a scan is dominated by bounce solving rather than by potential evaluations: the example point goes from 121 to 124 seconds, under 3%, on two concurrent runs of the same node.The wall velocity takes its sound speed from the thermal part too.
Hydrodynamics.calcWallVelocityLTEis a fourth copy of the same quantity and is on the default path:GWConf.wall_velocityis"LTE", and in the observables stage_ensure_wall_velocityruns before_ensure_sound_speed, so it was evaluated first on every default run and the refusal above could not protect it. Its enthalpy-T dV/dTand its two sound speeds all came from the whole potential, with the same cancellation.Measured on the conformal dark U(1), 31 couplings from
g = 0.45to0.75and five temperatures from1e-1to1e-7of the scale: the broken-phase sound speed it used disagreed with the thermal part by more than one per cent at 42 of 135 points, and at two of them it was superluminal,c_s = 1.26atg = 0.650and1.11atg = 0.750, both at a temperature of1e-5of the scale. Those values went intoDTheta, which divides by the sound speed, and intofind_vw, which compares the wall velocity against it. There was no check that they were below one.generic_potential.V_thermaland its two derivatives now takeinclude_decoupled, because this caller followsGWConf.coupled_hydrodynamicsrather than always excluding the decoupled bath: an enthalpy taken on one plasma and combined with a pressure taken on another is not a thermodynamic identity. A sound speed of one or more is refused here on the same footing as incalc_cs. A phase with no plasma at all is a different statement and is still the runaway branch,v_wall = 1, as before.A second derivative that underflows against a first derivative that has not is a third case, and it is an infinite sound speed rather than either of those. It is refused in both places, whether the denominator reached zero exactly or is merely subnormal so that the quotient overflows. The comparison against one carries no finiteness test, so positive infinity reaches it, while
nanand negative infinity do not compare greater than or equal to one and still fall through to the frozen-phase branch. In the wall velocity the sign the underflowed denominator kept is what decides between the two, so where it is exactly zero the quotient is formed rather than assumed, and that check runs before the zero-denominator return that would otherwise give the runaway answer first; where it is subnormal the quotient overflows on its own and the guard on the computed sound speeds tests positivity alone, which lets positive infinity through to the refusal and keeps the other two out.A refusal raised by the wall velocity carries the same two diagnostics as one raised by the sound speed. That stage runs before the sound-speed stage in both backends, so without it a default run would get its only refusal with neither of them, and with the least to say of any refusal in this change.
The wall velocity itself barely moves, because the superluminal values were being handed to a
find_vwthat saturates: over the same 155 evaluations, 152 are bit-identical, the largest change is1.0e-6relative, and nothing is refused, since the superluminal values existed only in the route that no longer runs.A sound speed of one or more is refused rather than replaced.
c_ssets the speed at which the bubbles grow,max(v_wall, c_s), the efficiency factors and the spectrum, and for a runaway wall a superluminal value multiplies(beta/H)_RHbyc_swhile the spectrum divides byv_wall - c_s.errors.SuperluminalSoundSpeedErrornow names the value and the temperature, and suggestsGWconfig.sound_speed = "1/3"for a run that wants the radiation value. Nothing is substituted: which thermodynamics a model has is the user’s choice, and a number the model did not give would hide the fact that the potential, as evaluated, has no sound speed there. A phase that has simply frozen out, where the ratio is zero over zero or negative, is still reported as not-a-number as before. Both phases are refused: the symmetric-phase value is what the hydrodynamic matching across the wall is solved with.The refusal is not hypothetical. Over 366 evaluations spanning
g = 0.45to0.75and temperatures from1e-1to1e-9of the scale, the released version returns a number at 222 of them and three of those are at or above the speed of light:c_s = 1.4387atg = 0.455,1.4799atg = 0.470and1.0536atg = 0.710, all at a temperature of1e-5of the scale. With the numerics above it returns a number at all 366, none of them reaches one, and they lie between0.5677and0.7071. Each half of that comparison was computed by the version it describes, in its own source tree, through that version’s ownHydrodynamics.calc_cs. That scan is the conformal dark U(1) ofmodels/TL_conformal_dark_u1.pyatv = 0.1 GeVandy = 0.01, with the sound speed taken on the traced broken phase at fixed field value; percolation is not computed.The error carries the value, the temperature, the phase it came from, CLI error code 18, and the two diagnostics below, so the message says which of the two known mechanisms produced the value rather than only that it was refused. The remedy it recommends,
GWconfig.sound_speed = "1/3", is now accepted by both percolation backends; the fixed-step one read only a bare number and the adaptive one only the label, so the recommendation was rejected by one of the two. Both resolve the setting throughhydrodynamics.resolve_configured_sound_speed, which reads"1/3"as the massless value1/sqrt(3)and anything else asc_sitself, strictly between zero and one.On the shipped line scan of
examples/example_line.yaml, 30 couplings fromg = 0.5to1.0atv = 0.14 GeV, nothing changes status: the same two points fail with the same error code and the same 28 give a sound speed, none refused. Of the 79 shared columns 32 are bit-identical and the rest move by at most3.2e-4relative, inalphaandalpha_thetabar;c_sby2.4e-4,betaH_RHandR_*by2.0e-4, and the signal-to-noise ratios by about two parts in ten thousand. The shifts are largest at the most supercooled surviving point, where the daisy term is 30 times the radiation, and fall away as that ratio does. The solver is deterministic: two runs of the same code agree bit for bit on 82 of 83 files.Two diagnostics of whether the sound speed means anything.
WARNING:noisy_c_sandDIAG:c_s_step_changesay whether it survives a change of the derivative step, because a value can be round-off and still be a speed, so no test on the value itself can find it. The step is varied both ways, by a factor ten in each direction, and the larger of the two changes is reported: a coarser step adds truncation error and a finer one adds round-off, and only the second is the failure being looked for, so testing one side alone would miss a value that breaks down as the step shrinks. The diagnostic does not propagate the refusal above. Each step is evaluated on its own and a refused value is compared like any other, so the three cases come apart: refused at one step and not at another is noise, because the value stopped being a speed somewhere inside the step range and no single step shows that; refused everywhere but moving is noise too; and refused everywhere with the same value is not, because it is not a speed but it does not depend on the step, and the refusal already says what is wrong with it. Catching the refusal around the group rather than per step let one at the base step end the measurement before either varied step was taken, and a constant superluminal value was then reported as maximally step dependent.Measured through
Hydrodynamics.sound_speed_is_step_dependenton the traced broken phase, atg = 0.455,0.7and0.95and six temperatures each: with the step rule above the change in a healthy regime is1.4e-7to9.9e-7, a factor 50000 below the0.05alarm. With the step rule these derivatives used to inherit it runs from2.1e-4to2.5e-2, so at its worst a factor two below the alarm, close enough to raise it on a point with nothing wrong with it.WARNING:daisy_outside_validityandDIAG:daisy_over_radiationsay whether the daisy resummation is being used where it does not apply. They report only ondaisy = "ArnoldEspinosa"; with"Parwani"or"off"there is no such term in the potential, and both come back as a false flag beside anan.The second is a statement about the model rather than the arithmetic. The Arnold-Espinosa term resums the bosonic zero Matsubara mode, which is justified where that mode is infrared enhanced,
m << T. Wherem >> Ta mode should be Boltzmann suppressed, and the one-loop thermal integral is: it falls below what a double can represent. The daisy term does not, tending instead to-(T^3/8 pi) sum n_i c_i m_i, a power law with noexp(-m/T)in it. On the conformal dark U(1) it is 7% of the field-independent radiation at a temperature of1e-1of the scale, thirteen times it at1e-3and ten million times it at1e-9, while the lightest mode runs fromm/T = 1.3to1.3e8. Where it dominates the free energy goes asT^3instead ofT^4, so the entropy goes asT^2andc_s^2 = s/(T ds/dT)tends to1/2. No free gas at zero chemical potential does that: therec_s^2 = 1/3for massless species and masses only lower it. A sound speed above1/sqrt(3)in a cold, heavily supercooled phase is therefore the prescription and not the plasma, and the physically expected value there is the1/sqrt(3)of the radiation that is still relativistic. The flag is raised when the daisy term exceeds that radiation and the lightest mode hasm/T > 1. The lightest mode is taken over every boson that contributes to the daisy term, which is every one with degrees of freedom, a mass squared that is not negative, and a Debye mass. All three are needed. A massless mode with a Debye mass is the lightest there is and counts: excluding it left a symmetric phase, where every zero-temperature mass vanishes, with no modes at all, and the ratio was discarded along with them in exactly the case a symmetric-phase refusal would want it. On the conformal dark U(1) the symmetric phase now reports ratios of0.005to0.01where it reportednan. A mode with no Debye mass does not count, however many degrees of freedom it has, because it adds exactly nothing to the term being judged: the transverse gauge bosons are massless and thermally uncorrected in every model here, and counting them pinned the lightest mass at zero and left the flag unable to fire at all. Whether a mode has a Debye mass is asked at the model’s own scale, since it is a property of the mode and at the temperatures this diagnostic exists for the difference of the two spectra has underflowed.This is reported and not corrected. A resummation that is Boltzmann suppressed at low temperature would remove the artefact and is the subject of planned follow-up work; it is a change to the thermodynamics rather than a guard, and it belongs in a change of its own.
A timed-out point no longer comes back as a number:
g_eff_DSandh_eff_DScaughtBaseExceptionaround the phase evaluation and substituted theT = 0vev, which absorbed the run’s ownTimeoutand turned a timed-out point into a finite entropy. They are the innermost evaluations on the counted route, below the handlers in the percolation history, so the timeout is now re-raised in both copies of both functions, and the fallback for ordinary failures is unchanged. The same held one level up, wherepercolation_temperature_from_odeanswered every exception withNone: the adaptive refinement then kept the interpolated percolation temperature and finished a run that had timed out. Every consumer of the time-temperature factors now has a test that a timeout in the innermost entropy evaluation reaches the caller.An unstable action slope is now retried at a tighter path deformation.
calc_betaH_S3fits the slope ofS3/Tover the support samples nearest the percolation temperature and repeats the fit over a smaller subset; where the two disagree by more thanbetaH_S3_fit_rel_tolthe result was reported throughWARNING:betaH_S3_fit_unstableand otherwise left alone. At the default path deformation the actions themselves are the reason: on a 2HDM benchmarkS3/Tscatters by 0.5 about a straight line across the fitting window, against a physical variation of 0.2 over the same window, so the slope and even its sign are not determined. Tightening the deformation toconverge_0 = 1andfRatioConv = 5e-3, the two settings thetunneltightprecision mode and the rate-jitter rescue already use, leaves a scatter of 0.003 and a smooth, monotonicS3/T. Where the two fits disagree the slope is therefore fitted again on a stencil of its own, spaced as the sparse-support fallback spaces one and computed with the deformation tightened. The support samples themselves are not reused: they can sit as little as1e-6 Tapart, and over a baseline that short even an exact action leaves the slope undetermined, so recomputing them would cure noisy actions but not a stencil too short to differentiate over. On the benchmark above this turns-27.3into+66.5, against+67.0to+67.3from fitting resolved actions over the windows the solver allows. The original value is kept if the recomputation fails. The new settingbetaH_S3_fit_rescue, with the run-time overridepercolation_betaH_S3_fit_rescue, switches it off.Symmetric phase at extreme supercooling. Where only the thermal masses hold the symmetric minimum in place, as in a classically conformal model, the potential is flat near the origin to within the tracing tolerance:
fminreturns any starting point within about 20xepsof the origin unchanged, the step predictor evaluated off the minimum pushes the trace further out at each step, and the last node, at the lowest tracing temperature, is an extrapolation that is not a minimum. The spline through those nodes then puts the false vacuum at an arbitrary field value over the lowest decades in temperature, which is where a strongly supercooled transition percolates, and everything read off the false vacuum there inherits the error: the masses of the fields, the counted entropy of the transitioning sector (bubbledynamics.h_eff_DS), the scale factor of the percolation integral and the mean bubble separation. A phase that coincides with its image under a symmetry of the potential at every traced temperature, within the tracer’s own same-point tolerance, is now projected onto the fixed subspace of that symmetry (phases.symmetrizeInvariantPhases). Broken phases, phases that differ from their image anywhere, and field components even under the symmetry are untouched. On a drifted trace the counted entropy of the false vacuum falls from its 7.5 light modes to 2.1 between 30 and 0.3 keV, and the sound speed of the symmetric phase comes outc_s^2 = 0.324instead of1/3. How much that costs grows with the supercooling: in the conformal dark U(1) shipped here nothing that percolates moves by a tenth of a per cent, the largest change being 1.4e-5 at a percolation temperature of 2.7 MeV and 8e-4 at 40 keV. Where the origin is held more weakly, as in a classically conformal U(1) without fermions, the same drift moved the percolation temperature by about 4 % and the mean bubble separation by about 8 % at a percolation temperature of 2.8 keV.Mirror of a phase that is its own image.
generateMirrorPhasescompared each image it built only with the other images of the same phase, never with the phase it came from, so a phase lying on the fixed subspace of a symmetry received a second copy of itself. Withgen_mirror_phases = Truethat second copy carries the same highest temperature as the original and the tracer rejects the pair, which made the classically conformal dark U(1) unusable with that option. Each image is now compared with its source as well, and a phase whose images all coincide with it contributes none. That comparison runs over the whole trace rather than its two ends, since dropping an image removes a phase outright and a trace that meets its image at both ends may still leave it in between. Broken phases keep their mirrors as before.The transition links these images carry were rebuilt with them. They named the image of the linked phase with the index of the transformation rather than the index plus one, which is the suffix the image itself is given, so every such link pointed at a phase that was never created; the links across the upper boundary were built from the key of a lower one, and raised
UnboundLocalErrorfor a phase with an upper link and no lower one; and a link to a phase that turns out to be its own image now names that phase, by the key it has rather than a string of it, since the links are read withinagainst the key of a phase and a traced phase has an integer key. Which image of which phase is kept is now settled for every phase before any link is built, so that a link naming an image dropped as a copy of another names the one kept instead, and each link is set both ways round as it is for traced phases. Two images count as the same one where they stay together at every traced temperature rather than only at the two ends of the trace: images of one phase under different transformations can meet at the ends and part in between, and are then different phases. Whether a phase lies on the fixed subspace at all is asked at the tolerance the symmetric phases were put there with, rather than atdiftol: a broken phase can sit nearer to the subspace than two phases have to be to merge, and its image is then a phase of its own rather than a copy. Nothing of this is reachable with the defaultgen_mirror_phases = False.A broken phase with no thermal pressure: at percolation temperatures far below the mass scale, the thermal part of the potential underflows in the broken phase, so its enthalpy and its sound speed come back as zero or as not a number. Two places carried that forward. The wall velocity in local thermal equilibrium formed the sound speed as
(dV/dT)/(T d2V/dT2), i.e. zero over zero, and divided by it while building the transition strength; with the strength then not a number, the bounds it is compared against are passed, and the plasma was integrated from a non-finite initial state, raising an error from the integrator. The wall velocity now returns one as soon as either enthalpy or either second temperature derivative is unusable, since a broken phase without a plasma gives the wall nothing to push against, and again if either sound speed itself is unusable, which a subnormal first derivative against a large second one can cause while both ingredients still look healthy; the same check also guards the matching-condition solver when it is called directly. The pseudo-trace strengthsalpha_thetabarandalpha_hyddivided by the broken-phase sound speed and raised a division by zero; they are now not a number where no sound speed exists, with the reason reported in verbose mode. The two sound speeds are checked separately, because only the broken-phase one builds the pseudo-trace while the symmetric-phase one appears solely in the normalisation ofalpha_thetabar: a usable broken-phase value still gives the hydrodynamic strengths. The strengths that need no sound speed,alpha_p,alpha_theta,alpha_e,alpha_infandalpha_eq, are unaffected. The fixed step size solver has its own copy of that calculation, where the same division produced an infinity and then a not-a-number together with a floating-point warning rather than an error, and where the pseudo-trace strength is calledalpha_theta; it is guarded in the same way. That solver’s owncalcSoundSpeedSqalso divided byT d2V/dT2unprotected, so it raised or warned before any caller could check the result; it now returns the not-a-number, as the adaptive solver’s copy already did, and leaves the decision to its callers.Hydrodynamics.calc_cs, which fills the reported sound-speed columns on the defaultgwConf.sound_speed = "compute"path, took the square root of the same ratio without protection; it now returns not a number both where the ratio is zero over zero and where it is negative, so that an unphysical sound speed appears as such in the output instead of stopping the run. No result changes where the broken-phase plasma exists.Documentation of
logGamma: both copies, inbubbledynamicsand inbubbledynamics_fixedstep, said the function returns a base-ten logarithm. They return the natural one,4 ln T + (3/2) ln(S/2 pi T) - S/T, which is what every caller uses. Only the sentence was wrong; no behaviour changes.Double percolation integral on coarse support grids (
integral_method = "double_integral"):percIntegralapplied the trapezoidal rule in temperature directly to the support points of the adaptive solver, which leave gaps of up to several e-folds of temperature on the hot shoulder of the rate. Across such a gap the rule overestimates an exponentially falling source by aboutbeta du/2, and the bubbles nucleated there enter the integral with the cube of their radius. On grids the solver produced for strongly supercooled points, the integral at the percolation temperature came out 40 to 60 % high andTperc1 to 4 % high, which moved the mean bubble separation andbetaH_RHby up to 15 %. The integral is now evaluated on a sub-grid that resolves the source to a change of 0.1 in its logarithm, interpolatingS3/T,ln H,3 c_s^2andln abetween the support points with a cubic spline, and the radius is accumulated from neighbouring scale-factor ratios in linear time. Against the closed form for an exponential rate in de Sitter space and against quadrature for a Gaussian turnover, the double integral now agrees to 0.5 % on grids with a gap of 0.7 e-folds, where it was off by 60 to 380 %. The differential equation method was not affected. Two quantities are interpolated in linear space rather than logarithmically,S3/Tand3 c_s^2, and a cubic spline through them can leave the range of the two support values it sits between where a feature is unresolved, which for a positive quantity would mean crossing zero; both are now held between those two values, which on a resolved interval barely binds: the benchmarks above are unchanged to the digits quoted and the mean bubble separation of a conformal dark U(1) point moves by four parts in ten million. The cap on sub-steps per support interval bounds the memory one interval can ask for, and now warns, naming the resolution actually achieved, on the rare grid where it is what limits that resolution instead of the requested step. A constant3 c_s^2may again be passed as a single number rather than an array, which the sub-grid had started to require. Where a feature of the rate lives entirely between two support points, the answer is set by the spacing of those points and not by the sub-grid between them; tests pin that, so that the limitation is not mistaken for one of the quadrature.Degrees of freedom of the fields of the potential:
h_eff_DSandg_eff_DS, used for the temperature inside the bubbles, for the integration ofTrehand for the redshift, masked out every field flaggedis_SM, skipped the Goldstone modes and kept the ghosts of the gauge bosons. They now count every mode and subtract the ghosts, i.e. the Landau gauge counting thatradiationEnergyDensityhas always used. For the 2HDM models W, Z, t, b, tau, h and the Goldstone modes were counted nowhere, since the Standard Model tables were capped below them: 68 entropy degrees of freedom at 50 GeV instead of 93. Where the Goldstone modes are massless at the minimum, as inmodels/TL_dark_U1.py, the counting is unchanged to machine precision, since the Goldstone that was dropped and the ghost that was kept cancel; where they are not, as inmodels/TL_conformal_dark_u1.py, it changes, by -16 % atT = 0.1 v. The count is floored at zero: the ghosts are massless in the Landau gauge while the Goldstone modes they cancel are not, so once every mode of the potential is frozen out the difference would otherwise turn negative.reheating_geffnow also evaluates the fields of the potential with their zero-temperature masses, asradiationEnergyDensityandh_eff_DSdo, rather than with the Debye-corrected ones.Standard Model fields of the potential in the tabulated baths: the Standard Model tables were frozen above half the mass of the lightest massive
is_SMfield of the potential (set_sm_temperature_cap, 0.888 GeV for the 2HDM) to leave room for those fields. The cap also froze the photon, the gluons, the light fermions and the whole QCD crossover above that temperature, and it was module-wide state that the construction of one potential changed for all others. It is replaced by subtracting the Standard Model fields of the potential from the tables, at the masses they have in the zero-temperature vacuum, so that each field is counted exactly once: in the zero-temperature vacuum the total is the full Standard Model table plus the additional fields of the model.set_sm_temperature_capis removed. Together with the previous entry, this lowers the degrees of freedom after reheating of the 2HDM benchmark line by 2.9 % in energy and 1.8 % in entropy, movesTpercby 0.02 % andTrehby 0.04 %, andalpha, which is built from the sound speed, by 1.4 %; along the dark lines the percolation is unchanged and only the redshift moves, by -0.87 % (conformal) and +0.29 % (abelian dark Higgs) in the degrees of freedom after reheating.Transverse photon mass in
models/TL_2HDM.py: the transverse photon was given the Debye mass of the longitudinal photon instead of zero, since both eigenvalues were taken from the neutral gauge mass matrix including the Debye terms. The transverse modes receive no thermal mass at this order, and that eigenvalue vanishes identically without them. The wrong mass entered the thermal potential and, with two degrees of freedom, the daisy term, so it shifted the barrier of every 2HDM run,TL_2HDM_BSMPT.pyincluded. Along the benchmark lineTcritfalls by 0.26 %,Tpercby 0.35 %,Trehby 0.27 %,alpharises by 1.4 % (up to 7.5 %) and the peak amplitude by 3.7 %. The step inalphaandbeta/Hatlambda3 = 5.69, which the daisy term produced, is gone. One point of the 49-point line ends in error 10 where it had a result before, and does not come back with more support points; its neighbours are unaffected.Scale factor of the percolation integral:
a(T)was obtained by integratingd ln a / dT = -1 / (3 c_s^2 T)with the trapezoidal rule over the solver’s temperature grid, which spans the overlap of the two traced phases and can run over ten or more decades with few points. Each interval was weighted by the sound speed at its cold end, where the false vacuum is far below completion and its sound speed is meaningless, so single intervals contributed hundreds of e-folds: for the 2HDM benchmarka(T)jumped by 10^135 between neighbouring grid points and reached 10^217, and the percolation integral then failed with error 10. It now uses the integral form of the same relation, entropy conservationa^3 s = const, with the bag relationa ~ 1/Twhere the entropy of the traced phase is not usable, and it accepts sound speeds only inside(0, 1]. For a pure radiation bath, wherea ~ 1/Texactly, the old rule was wrong by a factor 680 at the cold end of a twelve-decade grid. Along the 2HDM benchmark line the change movesTperc,Trehandalphaby less than 0.01 %, and it gives back the one point that the transverse photon fix had cost, so the line has a result at all 49 of its points.Expansion history of the mean bubble separation: the bubble number density
n_Bwas integrated with the bag relation,a ~ 1/TanddT/dt = -H T, while the percolation integral that fixedTpercused the sound speed of the plasma and an entropy-conservinga(T), soR_*andTpercdescribed two different cosmologies.calcMeanBubbleSeparationalready accepted the history throughentropyIntandcoolingInt, but nothing passed it. Both now come fromexpansion_interpolants, built from the same routine the percolation integral uses, soTperc,R_*andbeta/Hbelong to one expansion history. WithC = 1/(3 c_s^2)atTperc, the old expression gave anR_* H_*too large byC^(1/3): for an exact exponential nucleation rate,beta/Hread offR_*keeps the same residual forC = 1, 1.08 and 1.2 once the history is shared, and drifts by -1.7 % and -5.1 % without it.Tperc,alpha,kappa_swand(beta/H)_S3are unchanged;R_* H_*,(beta/H)_RHand the spectrum are not. Along the abelian dark Higgs line (Cfrom 0.974 to 1.090)R_* H_*moves by a median -2.20 % (range -2.69 % to +0.83 %) and the peak amplitude by -4.34 % (-5.31 % to +1.64 %); along the supercooled conformal line by -0.15 % (-2.06 % to +0.83 %) and -0.31 %; along the 2HDM line by +0.28 % (-0.32 % to +1.01 %) and +0.57 %. At single points: -2.51 % inR_* H_*for the abelian dark Higgs atlambda = 0.03, -4.67 % for the conformal model atv = 20 GeV(C = 1.175) and +0.92 % for the 2HDM benchmark, whereC = 0.972is below one andR_*grows instead. Every point keeps its error code, and the fixed step size solver, which uses the bag relation throughout, is unchanged. The expansion history is carried asln s = -3 ln arather than assitself, and the ratio the separation needs is formed as a difference of logarithms:a^-3underflows to zero beyond about 236 e-folds, while the scale factor is allowed 700, and a ratio of two underflowed entropies comes back as one, an unexpanding universe. The integral over the separation also moved from a linear to a logarithmic temperature grid, which matters where the percolation support spans decades: at a support ratio of 1000 the linear grid was 1.6 % low at the same number of points, at a ratio of 100 it was 0.10 % low. Thebagmode keeps the linear grid and the bag relation throughout and is unchanged.Sound speed of the
(beta/H)_S3time-temperature factor: the factor3 c_s^2that convertsT d(S_3/T)/dTinto(beta/H)_S3was read from the sound speed of the gravitational wave settings,GWConf.sound_speed. WithGWConf.sound_speed = "1/3"that factor became exactly one, so(beta/H)_S3lost the correction while the percolation history kept the sound speed of the plasma. It now comes from the percolation history itself, through the same routine the percolation integral, the mean bubble separation and the false-vacuum criterion use. With the defaultGWConf.sound_speed = "compute"the two agree to 2e-14 and no result changes.Double integral and the time-temperature mode: with
percolation_integral_method = "double_integral",percIntegralignored the expansion history whateverpercolation_time_temperature_modewas set to, while(beta/H)_S3still carried its3 c_s^2factor.percIntegralnow implementsentropy_densityandcooling_factorand receives the same factors as the ODE; it reduces exactly to the previous expression in the bag limit, and agrees with the ODE to better than 1e-3 wherever the percolation integral is of order one. For the conformal model atg = 0.692,Tpercmoves by +0.46 %, +0.64 % and +1.41 % atv = 2, 6 and 20 GeV,R_* H_*by +5.7 %, +7.5 % and +15.6 %, and the peak amplitude by +11.6 %, +15.6 % and +33.7 %. The default method ("ode") is unaffected. One rule,percolation_uses_sound_speed, now decides for the percolation integral,R_*,(beta/H)_S3andpercolation_sound_speed_sqalike; the sound speed is used unless the mode is"bag", for both integral methods.Diagnostic plots:
plotDOFsdrew the fields of the potential against the whole Standard Model table, so its total double counted the Standard Model fields of the potential; both curves now use the counting of the solvers.plotPercolationunpacked nine return values fromcalcPercAndEvolve, which returns six, so it failed for every model; the three extra values were never used. It also failed when a transition has no nucleation temperature, where the upper end of the percolation profile now sets the plotting range.Decoupled radiation baths: runs with radiation in
kin_decoupled_*, the setting 2.0.0 prescribes for a sector decoupled from the Standard Model, ended with error code 8 or gave wrong results without an error. The percolation solvers mixed the decoupled bath into the reheating of the bubbles: the energy balance counted it in the released energy but not in the broken phase, the expansion rate evaluated it at the temperature inside the bubbles, and the entropy conservation between support points and the integration ofTrehadded the Standard Model entropy table whatever the baths were. Now only the transitioning sector is reheated; the decoupled bath keeps the temperature of the surrounding false vacuum and enters the expansion rate. This holds in the adaptive solver including its self-consistency check, in the fixed step size solver of the pipeline (bubbledynamics_fixedstep) and in the one reached throughbubbledynamics.calcPercAndEvolve(percolation_fixedstepsize). TheradiationEnergyDensityof the BSMPT 2HDM models now includes a decoupled bath like the base class. Percolation results without a decoupled bath are unchanged.In
h2Omega_0_sumthe break frequencies were redshifted withD^(-4/3)instead ofD^(-1/3); the amplitude keepsD^(-4/3). No effect for the defaultD = 1.Treh scatter (#6): since 2.1.0 the reheating temperature was read off the tabulated broken-phase temperature trajectory at
Tperc, which made it depend on where the adaptive support points happen to sit and produced point-to-point scatter along smooth parameter scans. The broken-phase temperature is now integrated down toTpercwith an error-controlled solver (integrate_broken_temperature), in both the adaptive and the fixed step size percolation solver; the true-vacuum fraction enters through its percolation integralI = -ln(1 - P), whose logarithm is smooth, instead of through a spline ofP. The tabulated trajectory and the instantaneous reheating solve remain as fallbacks. The read-off also carried a bias that shrinks only linearly with the support spacing, soTrehmoves down by a few hundredths to a few tenths of a per cent, depending on the model.Tperc in the adaptive step size solver is now taken from an event of the percolation-integral ODE rather than from root-finding on interpolated samples, so it no longer moves with the support points.
A degenerate step-3 profile, which reaches percolation without any evolved broken-phase temperature right after a support rebuild, is no longer accepted as self-consistent.
The conformal dark U(1) model splines the potential along the bounce path with 10000 instead of 1000 samples. With 1000 samples the bounce action was biased towards strong supercooling (for
y = 0.01,v = 0.14 GeV,g = 0.554:Tperc31 % too low,alpha4.3 times too high), scattered along smooth parameter lines, and some strongly supercooled points failed. The new setting agrees with the unsplined potential to within 0.2 % inTperc.
[2.1.0] - 2026-07-28¶
Bugfix release: reheating temperature (Treh) is now computed from the evolved true-vacuum energy density rather than assumed instantaneous.
Fixed¶
Treh (reheating temperature): previously solved for Treh by assuming instantaneous reheating via energy conservation at the single percolation temperature (
eBRO(Treh) = eSYM(Tperc)), discarding the gradual true-vacuum-energy-density evolution the percolation routine already tracks per step. This disagreed with the paper definition and overestimated Treh for deeply supercooled transitions (low Tperc). TheTBROintspline built from the evolved(TSYM, TBRO)trajectory is now restored onPercolationResultand evaluated atTperc, realigning the adaptive-step path withtransitionObservables_fixedstep.py. The directTb_criterionsolve remains as a fallback when the spline is unavailable, andTreh = Tpercas the final fallback.
Added¶
TL_2HDM_BSMPT.pyandTL_2HDM_BSMPT_highacc.pymodel files, needed to use thebp_lisa.yamlbenchmark point.
Changed¶
Installation check now shows a progress indicator while warming the numpy cache, so the install doesn’t appear to hang; installation instructions updated to match.
README and FAQ now reference CosmoTransitions and arXiv:2303.10171 for the LTE velocity approximation;
hydrodynamics.pyheader updated accordingly.Issue and feature request templates updated.
[2.0.1] - 2026-05-18¶
Compatibility and packaging fixes; no physics changes.
Fixed¶
numpy ≥ 2.0 compatibility:
np.product()(removed in numpy 2.0) replaced withnp.prod(). Percolation criterion functions inbubbledynamics.pyandbubbledynamics_fixedstep.pynow return Python scalars instead of shape-(1,)arrays, fixing aSystemErrorfromscipy.optimize.brentqon numpy 2.x.np.linalg.lstsqcalls updated from deprecatedrcond=-1torcond=None.Windows compatibility:
signal.SIGALRMandsignal.alarm()are POSIX-only and not available on Windows. All usages are now guarded byhasattrchecks, fixing anAttributeErroron import that caused the conda-forge Windows CI to fail.PTA diagnostics: when
ptarcade.signal_builderfails to import, the underlying error is now shown alongside the “PTA likelihood unavailable” warning.
Added¶
conda/meta.yamlrecipe for conda-forge submission.buildandtwineadded to the[dev]optional dependencies inpyproject.toml.GitHub Actions workflow (
.github/workflows/publish.yml) for automatic PyPI publishing on tagged releases via OIDC trusted publishing.
[2.0.0] - 2026-05-06¶
Major code release accompanied by the paper arXiv:2605.15259.
Added¶
Public packaged interface (
pip install -e .,tlconsole script, YAML-driven scans). v1 was a collection of top-level Python scripts (My_point.py,My_point_comparison.py,My_potential_plot_point.py,My_scan_LISA_low_res.py,scanner.py,tl_dark_photon_model.py) invoked individually; v2 ships a single CLI and a structuredtransitionlistenerpackage undersrc/.Self-consistent percolation solver. The new
adaptive_step_sizealgorithm iterates the Hubble rate and the false-vacuum fraction until convergence and is the default. Afixed_step_sizestatic-grid solver is kept as a benchmarking baseline; both run from the same model files via thepercolation_algorithm_modeYAML override (orPercolationConfdefault).ODE-based percolation integral (
percolation_integral_method = "ode", default) that uses the symmetric-phase sound speed and the integrated cosmological scale-factor ratio (percolation_time_temperature_mode = "sound_speed", default) so the evolvedP_t(T)already includes both effects without a separatePr_expchannel. The historical bag/c_s²=1/3form is still reachable viapercolation_time_temperature_mode = "bag".Full thermodynamic alpha catalogue:
alpha(the canonical column), now defined as the Giese:2020 / pseudo-trace-anomaly definition (alpha_thetabar).alpha_theta(bag-EOS) is still emitted as a separate output column so users can compare definitions on a per-point basis.alpha_p,alpha_e,alpha_hyd,alpha_inf,alpha_eq.
LTE bubble-wall velocity solver based on arXiv:2303.10171 (
Hydrodynamics.calcWallVelocityLTE), reading the hydrodynamic coupling option frompot.config.gwConf.coupled_hydrodynamics. Free-input numericwall_velocityvalues in(0, 1]are also accepted.LISA Cosmology Working Group spectrum recommendations (arXiv:2403.03723): bubble-collision + sound-wave + turbulence contributions with sound-wave-source lifetime.
precision_modebundles for tracing and tunnelling tolerances:default,robust,xtrace,tunneltight,benchmark.Output schema and observability:
Stable, fully columnar
output_table.csvwith documented columns (see paper App. A).Documented error codes in
transitionlistener/errors.py.SNR computation against LISA, BBO, DECIGO, ET, muAres, and the PTA datasets (NANOGrav, EPTA, IPTA).
PTA log-likelihood evaluation through
PTArcade.UltraNest integration for nested-sampling scans of large parameter spaces.
Multi-Higgs / multi-field potentials:
models/TL_2HDM.pyand high-accuracy variants,models/TL_dark_flipflop.py(two-singlet vev-flip-flop),models/TL_dark_U1.py,models/TL_dark_U1_g_parameterization.py,models/TL_conformal_dark_u1.py,models/templatePotential.pyas a starting point for new models.
Automatic SM and BSM degrees-of-freedom accounting at finite T, including a kinetic-equilibrium switch (
pot.config.gwConf.coupled_hydrodynamics) that controls whether the species coupled to the transitioning scalar and the rest of the heat bath are treated as a single hydrodynamic fluid.Self-consistent energy-density evaluation from the user-defined effective potential (replacing the older
ΔV/ bag approximation).Stable down to extreme supercooling:
α ~ 10^10benchmarks pass.Reproducibility infrastructure for the paper:
arxiv/figures/paper/configs/: every YAML scan that feeds a paper figure.arxiv/reproducibility/paper/manifest.yaml: figure → builder script → YAML inputs map.arxiv/reproducibility/paper/scripts/build_all.py: walks the manifest, optionally re-runs the underlying tl scans, and rebuilds the figures (--regenerate,--mode {adaptive_step_size, fixed_step_size},--only LABEL).
Sphinx documentation: https://tasillo.de/TransitionListener/.
tests/test_release_smoke.py: 1-2 minute end-to-end smoke that runstl -c examples/example_point.yamland assertsTperc,Treh,alpha,alpha_thetabar,RHin their expected physical bands.GitHub Actions CI that installs the package (with the dev extras for pytest) and runs the smoke test on every push to
main/release.CITATION.cffand an expandedpyproject.toml(project URLs, classifiers, dev extras).
Changed¶
derived["alpha"]now equals the Giese:2020 definition (alpha_thetabar) instead of the bag-EOS one. Old code that readalphawill continue to work but will pick up the new (more accurate) value; the old definition is still available asalpha_theta.The package layout moved from
TransitionListener/*.py(top of repo, with hand-written paths in user scripts) to a propersrc/transitionlistener/*.pyimport root with subpackages (interface/,counterterms/).transitionFinder.py(the v1 monolith) was split into:phases.py+transitions.py+transitionObservables.py+bubbledynamics.py+nucleation.py.The
xi/ temperature-ratio quantities (xi_nuc,Tnuc_DSvs.Tnuc_SM) are no longer first-class outputs (see Removed).
Removed¶
Computation of the temperature ratio between the transitioning sector and the external bath, and its propagation into the phase- transition observables. v1 carried
xi_nuc,Tnuc_DS,g_eff_DS,g_eff_SMseparately; v2 reports a single SM-temperature column (*_SM_GeV) and assumes thermal equilibrium between the two sectors during the transition (controlled bypot.config.gwConf.coupled_hydrodynamics). For models in which the two sectors decouple, set the flag toFalseand supply the decoupled-sectorgeffcallbacks on the model.Computation of the dilution factor
D. v1 shippedTransitionListener/dilution.py(a full Boltzmann solver inspired by arXiv:1811.03608 for non-thermal mediator decays). v2 leavesDas an open parameter on the GW spectrum (default1); users who need the dilution can compute it externally and pass it in.
[1.0.2] - 2023-12-06¶
Added a conda environment file.
Added¶
TL.yml, a conda environment file intended to provide a working v1 setup withscipy==1.10.1and the small Python dependencies needed by the original scripts.
Changed¶
My_scan_LISA_low_res.pywas wrapped in a standardif __name__ == "__main__":entry point so the example scan script behaves more cleanly when imported or launched from different environments.The README compatibility note was updated to document the
scipy-related failure mode in the CosmoTransitions backend more precisely and to point users to the new conda environment file.
[1.0.1] - 2023-10-12¶
Documentation-only maintenance update on the public v1 repository.
Changed¶
The README command examples were corrected to match the actual script names (
My_point.py,My_scan.py,My_comparison.py).A compatibility note was added documenting that the v1 code path can run into CosmoTransitions error-code-7 failures on then-current Python / NumPy / SciPy stacks, especially on Apple M2 systems, while the authors could still confirm a working environment with
python 3.9.16,scipy 1.10.1, andnumpy 1.24.3.
[1.0.0] - 2021-10-21¶
Initial public v1 release of TransitionListener on GitHub, corresponding to the original dark sector workflow used in arXiv:2109.06208.
Added¶
A script-driven analysis workflow built on top of CosmoTransitions for dark sector first-order phase transitions and their stochastic gravitational wave signals.
Single-point, grid-scan, comparison, and potential-cross-check entry points via
My_point.py,scanner.py,My_point_comparison.py,My_scan_LISA_low_res.py, andMy_potential_plot_point.py.Model support for a dark
U(1)extension throughtl_dark_photon_model.pyand the bundledTransitionListener/module directory.Computation of nucleation temperature, transition strength, inverse timescale, relativistic degrees of freedom, entropy-dilution effects, GW spectra, and detector signal-to-noise ratios in the original v1 framework.