TransitionListener 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. transitionlistener/__init__.py +21 -0
  2. transitionlistener/bubbledynamics.py +2250 -0
  3. transitionlistener/bubbledynamics_fixedstep.py +2929 -0
  4. transitionlistener/check_installation.py +309 -0
  5. transitionlistener/ckm.py +91 -0
  6. transitionlistener/colors.py +288 -0
  7. transitionlistener/config.py +185 -0
  8. transitionlistener/constants.py +64 -0
  9. transitionlistener/counterterms/__init__.py +230 -0
  10. transitionlistener/counterterms/cw.py +298 -0
  11. transitionlistener/counterterms/tensors.py +343 -0
  12. transitionlistener/counterterms/twohdm.py +520 -0
  13. transitionlistener/counterterms/twohdm_solver.py +374 -0
  14. transitionlistener/errors.py +315 -0
  15. transitionlistener/examples/bp_et.yaml +64 -0
  16. transitionlistener/examples/bp_lisa.yaml +70 -0
  17. transitionlistener/examples/bp_muares.yaml +69 -0
  18. transitionlistener/examples/bp_pta.yaml +64 -0
  19. transitionlistener/examples/example_dark_photon.yaml +73 -0
  20. transitionlistener/examples/example_grid.yaml +55 -0
  21. transitionlistener/examples/example_line.yaml +51 -0
  22. transitionlistener/examples/example_point.yaml +73 -0
  23. transitionlistener/examples/example_random_conformal.yaml +42 -0
  24. transitionlistener/examples/example_ultranest.yaml +39 -0
  25. transitionlistener/finiteT.py +468 -0
  26. transitionlistener/generic_potential.py +1521 -0
  27. transitionlistener/gridplots.py +592 -0
  28. transitionlistener/gwfopt.py +604 -0
  29. transitionlistener/helper_functions.py +843 -0
  30. transitionlistener/hydrodynamics.py +647 -0
  31. transitionlistener/interface/__init__.py +95 -0
  32. transitionlistener/interface/check.py +51 -0
  33. transitionlistener/interface/cli.py +211 -0
  34. transitionlistener/interface/config_loader.py +264 -0
  35. transitionlistener/interface/logging_utils.py +30 -0
  36. transitionlistener/interface/output_schema.py +296 -0
  37. transitionlistener/interface/pipeline.py +300 -0
  38. transitionlistener/interface/samplers.py +565 -0
  39. transitionlistener/interface/scans.py +468 -0
  40. transitionlistener/interface/single_point.py +581 -0
  41. transitionlistener/interface/state.py +61 -0
  42. transitionlistener/lineplots.py +597 -0
  43. transitionlistener/logo/TL-logo_large.png +0 -0
  44. transitionlistener/logo/TL-logo_small.png +0 -0
  45. transitionlistener/models/TL_2HDM.py +512 -0
  46. transitionlistener/models/TL_conformal_dark_u1.py +202 -0
  47. transitionlistener/models/TL_dark_U1.py +198 -0
  48. transitionlistener/models/TL_dark_U1_g_parameterization.py +198 -0
  49. transitionlistener/models/TL_dark_flipflop.py +274 -0
  50. transitionlistener/models/templatePotential.py +260 -0
  51. transitionlistener/nucleation.py +412 -0
  52. transitionlistener/observability.py +790 -0
  53. transitionlistener/particles.py +436 -0
  54. transitionlistener/pathDeformation.py +1462 -0
  55. transitionlistener/percolation_adaptive_gridbuilders.py +1385 -0
  56. transitionlistener/percolation_adaptive_rate.py +1049 -0
  57. transitionlistener/percolation_adaptivestepsize.py +1632 -0
  58. transitionlistener/percolation_fixedstepsize.py +618 -0
  59. transitionlistener/phases.py +1499 -0
  60. transitionlistener/plot_settings.py +121 -0
  61. transitionlistener/plots.py +1781 -0
  62. transitionlistener/runtime_options.py +278 -0
  63. transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/bandwidths.npy +0 -0
  64. transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/density.npy +0 -0
  65. transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/freqs.npy +0 -0
  66. transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/log.txt +16 -0
  67. transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/log10rhogrid.npy +0 -0
  68. transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/log10rholabels.txt +30 -0
  69. transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/pulsar_list.txt +1 -0
  70. transitionlistener/tab_data/HLV-O2-PLI.csv +82 -0
  71. transitionlistener/tab_data/HLV-O2-noise.csv +83 -0
  72. transitionlistener/tab_data/HLVK-design-PLI.csv +61 -0
  73. transitionlistener/tab_data/HLVK-design-noise.csv +83 -0
  74. transitionlistener/tab_data/NG15_PLI_hc.csv +31 -0
  75. transitionlistener/tab_data/NG15_noise_hc.csv +56 -0
  76. transitionlistener/tab_data/PLI-dataset.csv +327 -0
  77. transitionlistener/tab_data/energydensities.dat +1001 -0
  78. transitionlistener/tab_data/finiteT_b.dat.txt +1999 -0
  79. transitionlistener/tab_data/finiteT_f.dat.txt +1000 -0
  80. transitionlistener/tab_data/geff_SM.dat +10009 -0
  81. transitionlistener/tab_data/muAres_f_Hz_PLI_h2OmegaGW.csv +131 -0
  82. transitionlistener/tab_data/muAres_f_Hz_h2Omega_noise.csv +99 -0
  83. transitionlistener/tab_data/noise-dataset.csv +327 -0
  84. transitionlistener/tab_data/numberdensities.dat +1001 -0
  85. transitionlistener/tab_data/pressures.dat +1001 -0
  86. transitionlistener/thermodynamics.py +686 -0
  87. transitionlistener/transitionObservables.py +1199 -0
  88. transitionlistener/transitionObservables_fixedstep.py +976 -0
  89. transitionlistener/transitions.py +1000 -0
  90. transitionlistener/tunneling1D.py +910 -0
  91. transitionlistener-2.0.0.dist-info/METADATA +817 -0
  92. transitionlistener-2.0.0.dist-info/RECORD +95 -0
  93. transitionlistener-2.0.0.dist-info/WHEEL +4 -0
  94. transitionlistener-2.0.0.dist-info/entry_points.txt +2 -0
  95. transitionlistener-2.0.0.dist-info/licenses/LICENSE.txt +674 -0
@@ -0,0 +1,618 @@
1
+ """fixed_step_size percolation solver.
2
+
3
+ This module keeps the compatibility path separate from the default adaptive_step_size
4
+ controller. It intentionally reuses the shared thermodynamic helpers from
5
+ ``bubbledynamics`` instead of duplicating the physics expressions here.
6
+
7
+ Part of TransitionListener v2.0
8
+ Documentation: https://tasillo.de/TransitionListener/
9
+
10
+ Authors:
11
+ Jonas Matuszak <jonas.matuszak@kit.edu>
12
+ Carlo Tasillo <carlo.tasillo@ific.uv.es>
13
+ """
14
+
15
+ import numpy as np
16
+ from scipy import interpolate, optimize
17
+
18
+ from transitionlistener import errors
19
+ from transitionlistener.bubbledynamics import (
20
+ PercolationGrid,
21
+ PercolationState,
22
+ HubbleParameter,
23
+ Tb_criterion,
24
+ _temperature_grid,
25
+ calcAction,
26
+ energyDensity,
27
+ energy_criterion_BRO,
28
+ entropy_criterion_SYM_BRO,
29
+ percIntegral,
30
+ )
31
+
32
+
33
+ def _initial_percolation_scan(
34
+ grid: PercolationGrid,
35
+ settings,
36
+ outdict: dict,
37
+ pot,
38
+ phase_symmetric,
39
+ phase_broken,
40
+ CF: float,
41
+ vw: float,
42
+ verbose: bool,
43
+ ) -> PercolationState:
44
+ """Step 2: compute P(T) with a P-independent Hubble rate.
45
+
46
+ This is the historical fixed-grid solver from main. It keeps the original
47
+ equidistant TSYM logic and only records a little extra diagnostic state.
48
+ """
49
+ TSYM = grid.TSYM
50
+ Sr = np.zeros_like(TSYM)
51
+ Hr = np.zeros_like(TSYM)
52
+ Pr = np.zeros_like(TSYM)
53
+ Tb = np.zeros_like(TSYM)
54
+
55
+ iterator = 1
56
+ iteration_condition = True
57
+ lowest_temperature_reached = float(TSYM[-1])
58
+
59
+ if verbose:
60
+ print("\nPercolation step 2: calculating Tperc assuming P = 0 in the Hubble rate")
61
+
62
+ while iteration_condition:
63
+ lowest_temperature_reached = min(lowest_temperature_reached, float(TSYM[-1]))
64
+ Sr.fill(0)
65
+ Hr.fill(0)
66
+ Pr.fill(0)
67
+ Tb.fill(0)
68
+ is_Pr_converged = False
69
+
70
+ for i, T in enumerate(TSYM):
71
+ if not is_Pr_converged:
72
+ Sr[i] = calcAction(pot, T, phase_symmetric, phase_broken, outdict)
73
+ rho = energyDensity(pot, phase_symmetric, T)
74
+ Hr[i] = HubbleParameter(rho, CF)
75
+ Pr[i] = 1 - np.exp(-percIntegral(TSYM[0 : i + 1], Hr[0 : i + 1], Sr[0 : i + 1], vw=vw))
76
+ else:
77
+ Sr[i] = np.nan
78
+ rho = energyDensity(pot, phase_symmetric, T)
79
+ Hr[i] = HubbleParameter(rho, CF)
80
+ Pr[i] = Pr[i - 1]
81
+
82
+ if verbose:
83
+ print(
84
+ f"Step {i+1}/{len(TSYM)}, T = {TSYM[i] * CF:2.8g} GeV, "
85
+ f"P_true = {Pr[i]:2.5g}, S_3 = {Sr[i] * CF:2.5g} GeV, "
86
+ f"S_3/T = {Sr[i] / T:2.5g}"
87
+ )
88
+
89
+ if i >= 1 and Pr[i] > settings.f_final and Pr[i - 1] > settings.f_final:
90
+ if verbose and not is_Pr_converged:
91
+ print(
92
+ "WARNING: P > ",
93
+ settings.f_final,
94
+ " at T = ",
95
+ TSYM[i] * CF,
96
+ " GeV detected. Stop computation of action from here on "
97
+ "and only fill in the values for the Hubble rate.",
98
+ )
99
+ is_Pr_converged = True
100
+
101
+ boundary_n = min(settings.max_boundary_n, len(Pr) - 1)
102
+ if Pr[0] <= settings.f_start and Pr[-1] >= settings.f_final:
103
+ jump_indices = np.where((Pr[:-1] == 0) & (Pr[1:] == 1))[0]
104
+ has_jump_0_to_1 = jump_indices.size > 0
105
+ if has_jump_0_to_1:
106
+ max_index = jump_indices[0]
107
+ min_index = jump_indices[0] + 1
108
+ tsym_jump_max = TSYM[max_index]
109
+ tsym_jump_min = TSYM[min_index]
110
+ if verbose:
111
+ print(
112
+ "Warning: Pr includes a 0 followed by 1, i.e. a "
113
+ "discontinuous jump in true vacuum fraction."
114
+ )
115
+ print(
116
+ f"Jump occurs between the indices {max_index} and {min_index}, "
117
+ f"TSYM values: {tsym_jump_min} and {tsym_jump_max}. "
118
+ "Set these as new boundaries."
119
+ )
120
+ if tsym_jump_max / tsym_jump_min - 1 > 1e-10:
121
+ TSYM = np.linspace(tsym_jump_max, tsym_jump_min, len(TSYM))
122
+ grid.TSYM = TSYM
123
+ Sr = np.zeros_like(TSYM)
124
+ Hr = np.zeros_like(TSYM)
125
+ Pr = np.zeros_like(TSYM)
126
+ Tb = np.zeros_like(TSYM)
127
+ iterator += 1
128
+ iteration_condition = iterator < settings.maxit
129
+ else:
130
+ if verbose:
131
+ print(
132
+ "WARNING: Even though there is a jump in P_true, the "
133
+ "temperature range is already very small. We will not "
134
+ "adjust it further and call the percolation temperature "
135
+ "calculation converged."
136
+ )
137
+ iteration_condition = False
138
+
139
+ elif Pr[boundary_n] == 0 or Pr[-boundary_n] == 1:
140
+ if verbose and iterator != settings.maxit:
141
+ print(
142
+ "Warning: the temperature range for the percolation "
143
+ "temperature computation was chosen too wide in iteration ",
144
+ iterator,
145
+ ". Decrease it!",
146
+ )
147
+
148
+ if Pr[boundary_n] == 0:
149
+ Tmax_new = TSYM[np.where(Pr < settings.f_start)[0][-1]]
150
+ else:
151
+ Tmax_new = TSYM[0]
152
+
153
+ if Pr[-boundary_n] == 1:
154
+ Tmin_new = TSYM[np.where(Pr > settings.f_final)[0][0]]
155
+ else:
156
+ Tmin_new = TSYM[-1]
157
+
158
+ if Tmax_new < Tmin_new:
159
+ raise errors.PercolationError(
160
+ "The temperature range for the percolation temperature "
161
+ "computation was messed up. This should not happen. Please report this as a bug."
162
+ )
163
+ TSYM = np.linspace(Tmax_new, Tmin_new, len(TSYM))
164
+ grid.TSYM = TSYM
165
+ Sr = np.zeros_like(TSYM)
166
+ Hr = np.zeros_like(TSYM)
167
+ Pr = np.zeros_like(TSYM)
168
+ Tb = np.zeros_like(TSYM)
169
+ iterator += 1
170
+ iteration_condition = iterator < settings.maxit
171
+ else:
172
+ iteration_condition = False
173
+ else:
174
+ if verbose and iterator != settings.maxit:
175
+ print(
176
+ "Warning: the temperature range for the percolation "
177
+ "temperature computation was chosen too narrow in iteration ",
178
+ iterator,
179
+ ". Increase it!",
180
+ )
181
+ if verbose and iterator == settings.maxit:
182
+ print(
183
+ "Warning: the temperature range for the percolation "
184
+ "temperature computation was chosen too narrow. This is "
185
+ "the last iteration, so we will use the current "
186
+ "temperature range anyway."
187
+ )
188
+ if Pr[0] > settings.f_start:
189
+ Tmax_new = TSYM[0] + (grid.tmax - TSYM[0]) * settings.rel_increment
190
+ else:
191
+ Tmax_new = TSYM[0]
192
+
193
+ if Pr[-1] < settings.f_final:
194
+ if iterator >= settings.maxit - 2:
195
+ Tmin_new = grid.tmin
196
+ else:
197
+ Tmin_new = TSYM[-1] - (TSYM[-1] - grid.tmin) * settings.rel_increment
198
+ else:
199
+ Tmin_new = TSYM[-1]
200
+
201
+ TSYM = np.linspace(Tmax_new, Tmin_new, len(TSYM))
202
+ grid.TSYM = TSYM
203
+ Sr = np.zeros_like(TSYM)
204
+ Hr = np.zeros_like(TSYM)
205
+ Pr = np.zeros_like(TSYM)
206
+ Tb = np.zeros_like(TSYM)
207
+ iterator += 1
208
+ iteration_condition = iterator < settings.maxit
209
+
210
+ return PercolationState(
211
+ TSYM=grid.TSYM,
212
+ Sr=Sr,
213
+ Hr=Hr,
214
+ Pr=Pr,
215
+ Tb=Tb,
216
+ explored_tmin=lowest_temperature_reached,
217
+ support_bank=_temperature_grid(grid.TSYM),
218
+ )
219
+
220
+ def _refine_percolation_temperature(
221
+ state: PercolationState,
222
+ grid: PercolationGrid,
223
+ settings,
224
+ outdict: dict,
225
+ pot,
226
+ phase_symmetric,
227
+ phase_broken,
228
+ CF: float,
229
+ vw: float,
230
+ Tperc_prev: float,
231
+ rtol: float,
232
+ verbose: bool,
233
+ ) -> tuple[float, PercolationState]:
234
+ """Step 3: iterate with the P-dependent Hubble rate until convergence.
235
+
236
+ Refine the percolation temperature by solving the
237
+ percolation integral with the Hubble rate and the true vacuum fraction
238
+ calculated in the previous step. The function iteratively
239
+ improves the true vacuum fraction and the Hubble rate until
240
+ convergence is reached."""
241
+ TBROmin = grid.TBROmin
242
+ TBROmax = grid.TBROmax
243
+ TSYM = state.TSYM
244
+ iterator = 1
245
+ iteration_condition = True
246
+
247
+ if verbose:
248
+ print("\nPercolation step 3: calculating Tperc with P-dependent Hubble rate")
249
+
250
+ while iteration_condition:
251
+ if verbose:
252
+ print(f"Iteration {iterator}, T_perc = {Tperc_prev * CF:2.8g} GeV")
253
+
254
+ if state.explored_tmin is None:
255
+ state.explored_tmin = float(TSYM[-1])
256
+ else:
257
+ state.explored_tmin = min(float(state.explored_tmin), float(TSYM[-1]))
258
+ Pprev = state.Pr.copy()
259
+ state.Hr.fill(0)
260
+ state.Pr.fill(0)
261
+ state.Tb.fill(np.nan)
262
+ state.Sr.fill(0)
263
+ is_Pr_converged = False
264
+
265
+ for i, T in enumerate(TSYM):
266
+ if not is_Pr_converged:
267
+ eSYM = energyDensity(pot, phase_symmetric, T)
268
+ if i == 0: # High temperature bin
269
+ # Pprev must be zero here
270
+ state.Hr[i] = HubbleParameter(eSYM, CF)
271
+ state.Sr[i] = calcAction(pot, T, phase_symmetric, phase_broken, outdict)
272
+ try:
273
+ TBRO = optimize.brentq(
274
+ Tb_criterion,
275
+ TBROmin,
276
+ TBROmax,
277
+ args=(T, phase_symmetric, phase_broken, pot),
278
+ )
279
+ state.Tb[i] = TBRO
280
+ except ValueError as err:
281
+ # Sometimes, brentq fails to find a root here. This is usually due to
282
+ # an inaccuracy in phase tracing, which can be solved by increasing
283
+ # the diftol parameter in the config file.
284
+ raise errors.PercolationError(
285
+ "Error in Tb_criterion: "
286
+ f"{err}. Please check the input parameters again by hand. "
287
+ "It might be that the phase tracing is not accurate enough, "
288
+ "try increasing the diftol parameter in the config file."
289
+ )
290
+ eBRO = 0
291
+ else:
292
+ # When the previous step had negligible broken-phase
293
+ # fraction, reset to a fresh Tb_criterion value instead
294
+ # of propagating entropy from a non-existent plasma.
295
+ _P_ESTABLISHED = 1e-6
296
+ if Pprev[i - 1] < _P_ESTABLISHED:
297
+ try:
298
+ TBRO = optimize.brentq(
299
+ Tb_criterion, TBROmin, TBROmax,
300
+ args=(T, phase_symmetric, phase_broken, pot)
301
+ )
302
+ except ValueError:
303
+ TBRO = optimize.brentq(
304
+ entropy_criterion_SYM_BRO, TBROmin, TBROmax,
305
+ args=(state.Tb[i - 1], T, TSYM[i - 1], phase_broken, pot)
306
+ )
307
+ else:
308
+ # Use entropy conservation in the symmetric phase between two time steps
309
+ # to compute the broken phase energy density in step i based on the
310
+ # broken phase energy density in step i-1.
311
+ TBRO = optimize.brentq(
312
+ entropy_criterion_SYM_BRO, TBROmin, TBROmax,
313
+ args=(state.Tb[i - 1], T, TSYM[i - 1], phase_broken, pot)
314
+ )
315
+ eBRO = energyDensity(pot, phase_broken, TBRO)
316
+
317
+ P = Pprev[i]
318
+ dP = Pprev[i] - Pprev[i - 1]
319
+ energy_release = eBRO * (P - dP) + dP * eSYM
320
+ relative_energy_release = energy_release / eBRO
321
+ if relative_energy_release < 1e-50:
322
+ # If the energy release between two steps is too small, we don't need to
323
+ # calculate the broken phase temperature. The following computation in that
324
+ # case would just try to find an arbitrary argument T in front of a factor zero
325
+ # being the energy release. It is thus safer to just set TBRO to the value obtained
326
+ # in the previous step in the entropy conservation.
327
+ if verbose:
328
+ print("Energy release is too small to use energy criterion, using T_bro from entropy step")
329
+ state.Tb[i] = TBRO
330
+ else:
331
+ # Use the energy conservation to find the broken phase temperature
332
+ # based on the energy release between two steps.
333
+ try:
334
+ TBRO = optimize.brentq(
335
+ energy_criterion_BRO,
336
+ TBROmin,
337
+ TBROmax,
338
+ args=(eSYM, eBRO, Pprev[i], Pprev[i] - Pprev[i - 1], phase_broken, pot),
339
+ )
340
+ state.Tb[i] = TBRO
341
+ except ValueError as err:
342
+ # Sometimes, the energy criterion fails to find a root,
343
+ # because the energy release is too small.
344
+ # We try to limit this case by checking the relative
345
+ # energy release beforehand, but sometimes it still happens.
346
+ # In that case, we just use the value from the previous step
347
+ # and print a warning. This is not critical, as the energy
348
+ # release is small anyway.
349
+ if verbose:
350
+ print(
351
+ "Warning: energy_criterion failed. This is usually "
352
+ "because the relative energy release "
353
+ f"{relative_energy_release} is too small. We set it "
354
+ "to 0 and continue: ",
355
+ err,
356
+ )
357
+ state.Tb[i] = state.Tb[i - 1]
358
+ TBRO = state.Tb[i]
359
+ except Exception as err:
360
+ raise errors.PercolationError(
361
+ "Error in energy_criterion_BRO: "
362
+ f"{err}. Please check this input parameters again by hand."
363
+ )
364
+
365
+ eBRO = energyDensity(pot, phase_broken, TBRO)
366
+
367
+ if state.Tb[i] < TSYM[i]:
368
+ raise ValueError(
369
+ "There was a problem with the T_bro calculation, "
370
+ "T_bro < T_sym. This is (usually) not allowed by the "
371
+ "second law of thermodynamics."
372
+ )
373
+
374
+ state.Sr[i] = calcAction(pot, T, phase_symmetric, phase_broken, outdict)
375
+ state.Hr[i] = HubbleParameter(Pprev[i] * eBRO + (1 - Pprev[i]) * eSYM, CF)
376
+ state.Pr[i] = 1 - np.exp(
377
+ -percIntegral(
378
+ TSYM[0 : i + 1],
379
+ state.Hr[0 : i + 1],
380
+ state.Sr[0 : i + 1],
381
+ vw=vw,
382
+ )
383
+ )
384
+ else:
385
+ state.Sr[i] = np.nan
386
+ rho = energyDensity(pot, phase_symmetric, T)
387
+ state.Hr[i] = HubbleParameter(rho, CF)
388
+ state.Pr[i] = state.Pr[i - 1]
389
+
390
+ if verbose:
391
+ print(
392
+ f"Step {i+1}/{len(TSYM)}, T = {TSYM[i] * CF:2.8g} GeV, "
393
+ f"P_true = {state.Pr[i]:2.5g}, S_3 = {state.Sr[i] * CF:2.5g} GeV, "
394
+ f"S_3/T = {state.Sr[i] / T:2.5g}"
395
+ )
396
+
397
+ if i >= 1 and state.Pr[i] > settings.f_final and state.Pr[i - 1] > settings.f_final:
398
+ if verbose and not is_Pr_converged:
399
+ print(
400
+ "WARNING: P > ",
401
+ settings.f_final,
402
+ " at T = ",
403
+ TSYM[i] * CF,
404
+ " GeV detected. Stop computation of action from here on "
405
+ "and only fill in the values for the Hubble rate.",
406
+ )
407
+ is_Pr_converged = True
408
+
409
+ Pint = interpolate.interp1d(TSYM, state.Pr)
410
+ try:
411
+ Tperc = optimize.brentq(lambda T: Pint(T) - settings.f_perc, TSYM[0], TSYM[-1])
412
+ except ValueError as err:
413
+ msg = err.args[0]
414
+ if msg.startswith("f(a) and f(b) must have different signs"):
415
+ if Pint(TSYM[-1]) < settings.f_perc:
416
+ explored_tmin = float(TSYM[-1]) if state.explored_tmin is None else float(state.explored_tmin)
417
+ current_tmin = float(TSYM[-1])
418
+ collapse_tol = 1e-12 * max(abs(explored_tmin), abs(current_tmin), 1.0)
419
+ if explored_tmin + collapse_tol < current_tmin:
420
+ raise errors.PercolationError(
421
+ "The percolation-temperature refinement became numerically unstable: "
422
+ "the support grid previously explored lower temperatures down to "
423
+ f"{explored_tmin * CF:2.8g} GeV, but the final step-3 support "
424
+ "grid shrank back to Tmin = "
425
+ f"{current_tmin * CF:2.8g} GeV before failing with "
426
+ f"P(Tmin) = {Pint(TSYM[-1]):2.5g} < {settings.f_perc:2.5g}. "
427
+ "This usually indicates a spurious 0->1 jump in P(T); rerun "
428
+ "with higher percolation resolution."
429
+ )
430
+ raise errors.TooMuchSupercoolingError(
431
+ "The percolation temperature could not be found because the "
432
+ "true vacuum fraction only reaches "
433
+ f"{Pint(TSYM[-1])} < {settings.f_perc} at Tmin = "
434
+ f"{TSYM[-1] * CF} GeV."
435
+ )
436
+ raise errors.PercolationError(err)
437
+
438
+ except Exception as err:
439
+ msg = (
440
+ "Warning: could not compute Tperc after the third approximation step "
441
+ "with variable P in Hubble rate: "
442
+ f"{err}. Set the percolation temperature to the one from the previous step."
443
+ )
444
+ if verbose:
445
+ print(msg)
446
+ Tperc = Tperc_prev
447
+
448
+ if np.abs(Tperc - Tperc_prev) / Tperc < rtol:
449
+ if state.Pr[0] <= settings.f_start and state.Pr[-1] >= settings.f_final:
450
+ jump_indices = np.where((state.Pr[:-1] == 0) & (state.Pr[1:] == 1))[0]
451
+ has_jump_0_to_1 = jump_indices.size > 0
452
+ boundary_n = min(settings.max_boundary_n, len(state.Pr) - 1)
453
+ if has_jump_0_to_1:
454
+ max_index = jump_indices[0]
455
+ min_index = jump_indices[0] + 1
456
+ tsym_jump_max = TSYM[max_index]
457
+ tsym_jump_min = TSYM[min_index]
458
+ if verbose:
459
+ print(
460
+ "Warning: Pr includes a 0 followed by 1, i.e. a "
461
+ "discontinuous jump in true vacuum fraction."
462
+ )
463
+ print(
464
+ f"Jump occurs between the indices {max_index} and {min_index}, "
465
+ f"TSYM values: {tsym_jump_min} and {tsym_jump_max}. "
466
+ "Set these as new boundaries."
467
+ )
468
+ if tsym_jump_max / tsym_jump_min - 1 > 1e-10:
469
+ TSYM = np.linspace(tsym_jump_max, tsym_jump_min, len(TSYM))
470
+ state.TSYM = TSYM
471
+ state.Sr = np.zeros_like(TSYM)
472
+ state.Hr = np.zeros_like(TSYM)
473
+ state.Pr = np.zeros_like(TSYM)
474
+ state.Tb = np.zeros_like(TSYM)
475
+ Tperc_prev = Tperc
476
+ iterator += 1
477
+ iteration_condition = iterator < settings.maxit
478
+ else:
479
+ if verbose:
480
+ print(
481
+ "WARNING: Even though there is a jump in P_true, the "
482
+ "temperature range is already very small. We will not "
483
+ "adjust it further and call the percolation temperature "
484
+ "calculation converged."
485
+ )
486
+ print(
487
+ "\nConverged after "
488
+ f"{iterator} iterations to Tperc = "
489
+ f"{Tperc * CF:2.8g} GeV"
490
+ )
491
+ iteration_condition = False
492
+ elif state.Pr[boundary_n] == 0 or state.Pr[-boundary_n] == 1:
493
+ if verbose and iterator != settings.maxit:
494
+ print(
495
+ "Warning: the temperature range for the percolation "
496
+ "temperature computation was chosen too wide in iteration ",
497
+ iterator,
498
+ ". Decrease it!",
499
+ )
500
+ if state.Pr[boundary_n] == 0:
501
+ Tmax_new = TSYM[np.where(state.Pr < settings.f_start)[0][-1]]
502
+ else:
503
+ Tmax_new = TSYM[0]
504
+
505
+ if state.Pr[-boundary_n] == 1:
506
+ Tmin_new = TSYM[np.where(state.Pr > settings.f_final)[0][0]]
507
+ else:
508
+ Tmin_new = TSYM[-1]
509
+
510
+ if Tmax_new < Tmin_new:
511
+ raise errors.PercolationError(
512
+ "The temperature range for the percolation temperature "
513
+ "computation was messed up. It is not clear how this could "
514
+ "have happened."
515
+ )
516
+ TSYM = np.linspace(Tmax_new, Tmin_new, len(TSYM))
517
+ state.TSYM = TSYM
518
+ state.Sr = np.zeros_like(TSYM)
519
+ state.Hr = np.zeros_like(TSYM)
520
+ state.Pr = np.zeros_like(TSYM)
521
+ state.Tb = np.zeros_like(TSYM)
522
+ Tperc_prev = Tperc
523
+ iterator += 1
524
+ iteration_condition = iterator < settings.maxit
525
+ else:
526
+ if verbose:
527
+ print(
528
+ "\nConverged after "
529
+ f"{iterator} iterations to Tperc = "
530
+ f"{Tperc * CF:2.8g} GeV"
531
+ )
532
+ iteration_condition = False
533
+ else:
534
+ # The temperature range is not large enough to find a percolation temperature, we need to increase it
535
+ if verbose:
536
+ print(
537
+ "Warning: even though a percolation temperature was previously "
538
+ f"found (Tperc = {Tperc * CF:2.8g} GeV), it is not clear "
539
+ "whether the phase transition can finalize. The temperature "
540
+ "range will therefore be increased."
541
+ )
542
+ print("This was iteration", iterator, "of the third step of the percolation calculation.")
543
+ if iterator == settings.maxit - 1:
544
+ print(
545
+ "This was the penultimate iteration, the temperature range "
546
+ "will be set to the maximum possible range."
547
+ )
548
+ elif iterator == settings.maxit:
549
+ print("This was the last iteration. We stop here and return an error.")
550
+ else:
551
+ print("We will increase the temperature range and try again.")
552
+
553
+ if state.Pr[0] > settings.f_start:
554
+ Tmax_new = TSYM[0] + (grid.tmax - TSYM[0]) * settings.rel_increment
555
+ else:
556
+ Tmax_new = TSYM[0]
557
+
558
+ if state.Pr[-1] < settings.f_final:
559
+ if iterator == settings.maxit - 1:
560
+ # If we are at the last iteration, we set the lower temperature boundary
561
+ # all the way down to the minimal possible temperature allowed by the
562
+ # potential. This is to ensure that we do not miss the temperature at which
563
+ # the transition completes.
564
+ Tmin_new = grid.tmin
565
+ elif iterator == settings.maxit:
566
+ last_evaluated_tmin = float(TSYM[-1])
567
+ lower_bound_reached = (
568
+ abs(last_evaluated_tmin - float(grid.tmin))
569
+ <= 1e-12 * max(abs(last_evaluated_tmin), abs(float(grid.tmin)), 1.0)
570
+ )
571
+ if lower_bound_reached:
572
+ raise errors.EternalInflationError(
573
+ "The transition cannot completely finish because the true "
574
+ "vacuum fraction at the lowest evaluated temperature Tmin = "
575
+ f"{last_evaluated_tmin * CF:2.5g} GeV computed in step 3 "
576
+ "of the percolation computation stays below f_final: "
577
+ f"P(Tmin) = {state.Pr[-1]:2.5g} < {settings.f_final:2.5g}."
578
+ )
579
+ raise errors.PercolationError(
580
+ "The percolation computation reached the iteration limit before "
581
+ "the low-temperature tail was resolved: the lowest evaluated "
582
+ f"support point was Tmin = {last_evaluated_tmin * CF:2.5g} GeV "
583
+ f"with P(Tmin) = {state.Pr[-1]:2.5g}, while the configured lower "
584
+ f"bound is {grid.tmin * CF:2.5g} GeV. Increase the percolation "
585
+ "resolution to decide whether the transition completes or enters "
586
+ "eternal inflation."
587
+ )
588
+ else:
589
+ Tmin_new = TSYM[-1] - (TSYM[-1] - grid.tmin) * settings.rel_increment
590
+ else:
591
+ Tmin_new = TSYM[-1]
592
+
593
+ TSYM = np.linspace(Tmax_new, Tmin_new, len(TSYM))
594
+ state.TSYM = TSYM
595
+ state.Sr = np.zeros_like(TSYM)
596
+ state.Hr = np.zeros_like(TSYM)
597
+ state.Pr = np.zeros_like(TSYM)
598
+ state.Tb = np.zeros_like(TSYM)
599
+ Tperc_prev = Tperc
600
+ iterator += 1
601
+ iteration_condition = iterator < settings.maxit
602
+ else:
603
+ if verbose:
604
+ print(
605
+ "Percolation temperature T_perc = ",
606
+ Tperc,
607
+ "was found, but it is not close enough to the previous one (",
608
+ Tperc_prev,
609
+ ") at iteration ",
610
+ iterator,
611
+ ". Iterate one more time with the P(t) from the previous step and see if T_perc converges.",
612
+ )
613
+ Tperc_prev = Tperc
614
+ iterator += 1
615
+ iteration_condition = iterator < settings.maxit
616
+
617
+ state.support_bank = _temperature_grid(state.TSYM)
618
+ return Tperc, state