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.
- transitionlistener/__init__.py +21 -0
- transitionlistener/bubbledynamics.py +2250 -0
- transitionlistener/bubbledynamics_fixedstep.py +2929 -0
- transitionlistener/check_installation.py +309 -0
- transitionlistener/ckm.py +91 -0
- transitionlistener/colors.py +288 -0
- transitionlistener/config.py +185 -0
- transitionlistener/constants.py +64 -0
- transitionlistener/counterterms/__init__.py +230 -0
- transitionlistener/counterterms/cw.py +298 -0
- transitionlistener/counterterms/tensors.py +343 -0
- transitionlistener/counterterms/twohdm.py +520 -0
- transitionlistener/counterterms/twohdm_solver.py +374 -0
- transitionlistener/errors.py +315 -0
- transitionlistener/examples/bp_et.yaml +64 -0
- transitionlistener/examples/bp_lisa.yaml +70 -0
- transitionlistener/examples/bp_muares.yaml +69 -0
- transitionlistener/examples/bp_pta.yaml +64 -0
- transitionlistener/examples/example_dark_photon.yaml +73 -0
- transitionlistener/examples/example_grid.yaml +55 -0
- transitionlistener/examples/example_line.yaml +51 -0
- transitionlistener/examples/example_point.yaml +73 -0
- transitionlistener/examples/example_random_conformal.yaml +42 -0
- transitionlistener/examples/example_ultranest.yaml +39 -0
- transitionlistener/finiteT.py +468 -0
- transitionlistener/generic_potential.py +1521 -0
- transitionlistener/gridplots.py +592 -0
- transitionlistener/gwfopt.py +604 -0
- transitionlistener/helper_functions.py +843 -0
- transitionlistener/hydrodynamics.py +647 -0
- transitionlistener/interface/__init__.py +95 -0
- transitionlistener/interface/check.py +51 -0
- transitionlistener/interface/cli.py +211 -0
- transitionlistener/interface/config_loader.py +264 -0
- transitionlistener/interface/logging_utils.py +30 -0
- transitionlistener/interface/output_schema.py +296 -0
- transitionlistener/interface/pipeline.py +300 -0
- transitionlistener/interface/samplers.py +565 -0
- transitionlistener/interface/scans.py +468 -0
- transitionlistener/interface/single_point.py +581 -0
- transitionlistener/interface/state.py +61 -0
- transitionlistener/lineplots.py +597 -0
- transitionlistener/logo/TL-logo_large.png +0 -0
- transitionlistener/logo/TL-logo_small.png +0 -0
- transitionlistener/models/TL_2HDM.py +512 -0
- transitionlistener/models/TL_conformal_dark_u1.py +202 -0
- transitionlistener/models/TL_dark_U1.py +198 -0
- transitionlistener/models/TL_dark_U1_g_parameterization.py +198 -0
- transitionlistener/models/TL_dark_flipflop.py +274 -0
- transitionlistener/models/templatePotential.py +260 -0
- transitionlistener/nucleation.py +412 -0
- transitionlistener/observability.py +790 -0
- transitionlistener/particles.py +436 -0
- transitionlistener/pathDeformation.py +1462 -0
- transitionlistener/percolation_adaptive_gridbuilders.py +1385 -0
- transitionlistener/percolation_adaptive_rate.py +1049 -0
- transitionlistener/percolation_adaptivestepsize.py +1632 -0
- transitionlistener/percolation_fixedstepsize.py +618 -0
- transitionlistener/phases.py +1499 -0
- transitionlistener/plot_settings.py +121 -0
- transitionlistener/plots.py +1781 -0
- transitionlistener/runtime_options.py +278 -0
- transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/bandwidths.npy +0 -0
- transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/density.npy +0 -0
- transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/freqs.npy +0 -0
- transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/log.txt +16 -0
- transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/log10rhogrid.npy +0 -0
- transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/log10rholabels.txt +30 -0
- transitionlistener/tab_data/30f_fs{hd}_100fDMGP_ceffyl/pulsar_list.txt +1 -0
- transitionlistener/tab_data/HLV-O2-PLI.csv +82 -0
- transitionlistener/tab_data/HLV-O2-noise.csv +83 -0
- transitionlistener/tab_data/HLVK-design-PLI.csv +61 -0
- transitionlistener/tab_data/HLVK-design-noise.csv +83 -0
- transitionlistener/tab_data/NG15_PLI_hc.csv +31 -0
- transitionlistener/tab_data/NG15_noise_hc.csv +56 -0
- transitionlistener/tab_data/PLI-dataset.csv +327 -0
- transitionlistener/tab_data/energydensities.dat +1001 -0
- transitionlistener/tab_data/finiteT_b.dat.txt +1999 -0
- transitionlistener/tab_data/finiteT_f.dat.txt +1000 -0
- transitionlistener/tab_data/geff_SM.dat +10009 -0
- transitionlistener/tab_data/muAres_f_Hz_PLI_h2OmegaGW.csv +131 -0
- transitionlistener/tab_data/muAres_f_Hz_h2Omega_noise.csv +99 -0
- transitionlistener/tab_data/noise-dataset.csv +327 -0
- transitionlistener/tab_data/numberdensities.dat +1001 -0
- transitionlistener/tab_data/pressures.dat +1001 -0
- transitionlistener/thermodynamics.py +686 -0
- transitionlistener/transitionObservables.py +1199 -0
- transitionlistener/transitionObservables_fixedstep.py +976 -0
- transitionlistener/transitions.py +1000 -0
- transitionlistener/tunneling1D.py +910 -0
- transitionlistener-2.0.0.dist-info/METADATA +817 -0
- transitionlistener-2.0.0.dist-info/RECORD +95 -0
- transitionlistener-2.0.0.dist-info/WHEEL +4 -0
- transitionlistener-2.0.0.dist-info/entry_points.txt +2 -0
- transitionlistener-2.0.0.dist-info/licenses/LICENSE.txt +674 -0
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Coleman–Weinberg counterterm solver for the CP-conserving 2HDM.
|
|
3
|
+
|
|
4
|
+
This module evaluates the analytic curvature tensors at the vacuum and matches
|
|
5
|
+
the BSMPT counterterm prescriptions. It is invoked directly from the 2HDM
|
|
6
|
+
model so that the model file itself remains agnostic of the 8-dimensional
|
|
7
|
+
tensor algebra.
|
|
8
|
+
|
|
9
|
+
Part of TransitionListener v2.0
|
|
10
|
+
Documentation: https://tasillo.de/TransitionListener/
|
|
11
|
+
|
|
12
|
+
Authors:
|
|
13
|
+
Jonas Matuszak <jonas.matuszak@kit.edu>
|
|
14
|
+
Carlo Tasillo <carlo.tasillo@ific.uv.es>
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import copy
|
|
20
|
+
from functools import lru_cache
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
from typing import Tuple
|
|
23
|
+
|
|
24
|
+
import numpy as np
|
|
25
|
+
import sympy as sp
|
|
26
|
+
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
27
|
+
|
|
28
|
+
from transitionlistener import errors
|
|
29
|
+
from transitionlistener.ckm import wolfenstein_ckm
|
|
30
|
+
from transitionlistener.constants import SM_FERMION_MASSES_GEV
|
|
31
|
+
from transitionlistener.generic_potential import console as tl_console
|
|
32
|
+
from . import CounterTerms, generate_counterterms, tensors as tensor_utils
|
|
33
|
+
|
|
34
|
+
CKM_DEFAULT = wolfenstein_ckm()
|
|
35
|
+
GENERATED_TENSOR_FILE = (
|
|
36
|
+
Path(__file__).resolve().parents[3]
|
|
37
|
+
/ "models"
|
|
38
|
+
/ "generated"
|
|
39
|
+
/ "2hdm_curvature_tensors.json"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
CONDITION_SPECS = (
|
|
43
|
+
("grad", 4),
|
|
44
|
+
("grad", 6),
|
|
45
|
+
("hess", (4, 4)),
|
|
46
|
+
("hess", (6, 6)),
|
|
47
|
+
("hess", (4, 6)),
|
|
48
|
+
("hess", (5, 5)),
|
|
49
|
+
("hess", (0, 0)),
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
PARAMETER_SYMBOLS = ("dm11", "dm22", "dm12", "dl1", "dl2", "dl3", "dl5")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _load_dataset() -> Tuple[dict, dict]:
|
|
56
|
+
"""
|
|
57
|
+
Load (or build) the cached curvature tensor dataset for the 2HDM.
|
|
58
|
+
|
|
59
|
+
The JSON file is generated on demand using the SymPy-based generator when it
|
|
60
|
+
is missing, ensuring that production runs never fail due to a stale cache.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
if GENERATED_TENSOR_FILE.exists():
|
|
64
|
+
tl_console.print(
|
|
65
|
+
"[green]Loaded cached 2HDM curvature tensors.[/green]"
|
|
66
|
+
)
|
|
67
|
+
return tensor_utils.load_tensor_dataset(GENERATED_TENSOR_FILE)
|
|
68
|
+
|
|
69
|
+
with Progress(
|
|
70
|
+
SpinnerColumn("bouncingBall"),
|
|
71
|
+
TextColumn("Generating 2HDM curvature tensors…"),
|
|
72
|
+
transient=True,
|
|
73
|
+
console=tl_console,
|
|
74
|
+
) as progress:
|
|
75
|
+
task = progress.add_task("generate", total=None)
|
|
76
|
+
try:
|
|
77
|
+
generate_counterterms("models.TL_2HDM")
|
|
78
|
+
finally:
|
|
79
|
+
progress.update(task, advance=1.0)
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
dataset = tensor_utils.load_tensor_dataset(GENERATED_TENSOR_FILE)
|
|
83
|
+
except errors.InitPotentialError as retry_exc:
|
|
84
|
+
raise errors.InitPotentialError(
|
|
85
|
+
"Failed to load generated curvature tensors for the 2HDM after "
|
|
86
|
+
"regeneration. Inspect SymPy generation logs for details."
|
|
87
|
+
) from retry_exc
|
|
88
|
+
|
|
89
|
+
tl_console.print("[green]Curvature tensors generated successfully.[/green]")
|
|
90
|
+
return dataset
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _tensor_parameter_values(model) -> dict[str, complex]:
|
|
94
|
+
"""
|
|
95
|
+
Assemble the parameter substitution dictionary used by the tensor evaluator.
|
|
96
|
+
|
|
97
|
+
Values are expressed in physical units (GeV or dimensionless) because the
|
|
98
|
+
generated SymPy expressions follow the BSMPT normalisation.
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
cf_sq = model.conversionFactor**2
|
|
102
|
+
values: dict[str, complex] = {
|
|
103
|
+
"lambda1": float(model.lambda1),
|
|
104
|
+
"lambda2": float(model.lambda2),
|
|
105
|
+
"lambda3": float(model.lambda3),
|
|
106
|
+
"lambda4": float(model.lambda4),
|
|
107
|
+
"lambda5": float(model.lambda5),
|
|
108
|
+
"m11sq": float(model.m11_sq * cf_sq),
|
|
109
|
+
"m22sq": float(model.m22_sq * cf_sq),
|
|
110
|
+
"m12sq": float(model.m12_sq * cf_sq),
|
|
111
|
+
"tan_beta": float(model.tan_beta),
|
|
112
|
+
"v1": float(model.v1_GeV),
|
|
113
|
+
"v2": float(model.v2_GeV),
|
|
114
|
+
"yukawa_type": float(model.yukawa_type),
|
|
115
|
+
"Cg": float(model.g2),
|
|
116
|
+
"Cgs": float(model.g1),
|
|
117
|
+
}
|
|
118
|
+
values.update({key: float(mass) for key, mass in SM_FERMION_MASSES_GEV.items()})
|
|
119
|
+
values.update({key: complex(val) for key, val in CKM_DEFAULT.items()})
|
|
120
|
+
return values
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@lru_cache(maxsize=1)
|
|
124
|
+
def _counterterm_matrix_factory():
|
|
125
|
+
"""
|
|
126
|
+
Build the SymPy representation of the on-shell renormalisation conditions.
|
|
127
|
+
|
|
128
|
+
Following Eqs. (3.59)–(3.63) of arXiv:1803.02846, we impose two tadpole
|
|
129
|
+
conditions and five mass-matrix conditions (CP-even, CP-odd, and charged
|
|
130
|
+
sectors). The result is a 7×7 matrix ``M(v_1, v_2)`` such that
|
|
131
|
+
``M · δ = -Δ`` where ``δ`` collects the counterterms and ``Δ`` the Coleman–
|
|
132
|
+
Weinberg corrections.
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
dm11, dm22, dm12, dl1, dl2, dl3, dl5 = sp.symbols(
|
|
136
|
+
"dm11 dm22 dm12 dl1 dl2 dl3 dl5",
|
|
137
|
+
real=True,
|
|
138
|
+
)
|
|
139
|
+
delta_params = (dm11, dm22, dm12, dl1, dl2, dl3, dl5)
|
|
140
|
+
|
|
141
|
+
(
|
|
142
|
+
phi1p_R,
|
|
143
|
+
phi1p_I,
|
|
144
|
+
phi2p_R,
|
|
145
|
+
phi2p_I,
|
|
146
|
+
phi1_R,
|
|
147
|
+
phi1_I,
|
|
148
|
+
phi2_R,
|
|
149
|
+
phi2_I,
|
|
150
|
+
) = sp.symbols(
|
|
151
|
+
"phi1p_R phi1p_I phi2p_R phi2p_I phi1_R phi1_I phi2_R phi2_I",
|
|
152
|
+
real=True,
|
|
153
|
+
)
|
|
154
|
+
fields = [
|
|
155
|
+
phi1p_R,
|
|
156
|
+
phi1p_I,
|
|
157
|
+
phi2p_R,
|
|
158
|
+
phi2p_I,
|
|
159
|
+
phi1_R,
|
|
160
|
+
phi1_I,
|
|
161
|
+
phi2_R,
|
|
162
|
+
phi2_I,
|
|
163
|
+
]
|
|
164
|
+
|
|
165
|
+
phi1 = sp.Matrix(
|
|
166
|
+
[
|
|
167
|
+
(phi1p_R + sp.I * phi1p_I) / sp.sqrt(2),
|
|
168
|
+
(phi1_R + sp.I * phi1_I) / sp.sqrt(2),
|
|
169
|
+
]
|
|
170
|
+
)
|
|
171
|
+
phi2 = sp.Matrix(
|
|
172
|
+
[
|
|
173
|
+
(phi2p_R + sp.I * phi2p_I) / sp.sqrt(2),
|
|
174
|
+
(phi2_R + sp.I * phi2_I) / sp.sqrt(2),
|
|
175
|
+
]
|
|
176
|
+
)
|
|
177
|
+
phi1_sq = sp.simplify((phi1.conjugate().T * phi1)[0])
|
|
178
|
+
phi2_sq = sp.simplify((phi2.conjugate().T * phi2)[0])
|
|
179
|
+
phi12 = sp.simplify((phi1.conjugate().T * phi2)[0])
|
|
180
|
+
phi21 = sp.simplify((phi2.conjugate().T * phi1)[0])
|
|
181
|
+
|
|
182
|
+
Vct = (
|
|
183
|
+
dm11 * phi1_sq
|
|
184
|
+
+ dm22 * phi2_sq
|
|
185
|
+
- dm12 * (phi12 + phi21)
|
|
186
|
+
+ (dl1 / 2) * phi1_sq**2
|
|
187
|
+
+ (dl2 / 2) * phi2_sq**2
|
|
188
|
+
+ dl3 * phi1_sq * phi2_sq
|
|
189
|
+
+ (dl5 / 2) * (phi12**2 + phi21**2)
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
grad_exprs = [sp.diff(Vct, field) for field in fields]
|
|
193
|
+
hess_exprs = [
|
|
194
|
+
[sp.diff(grad_exprs[i], field_j) for field_j in fields]
|
|
195
|
+
for i in range(len(fields))
|
|
196
|
+
]
|
|
197
|
+
|
|
198
|
+
v1_sym, v2_sym = sp.symbols("v1 v2", real=True)
|
|
199
|
+
vacuum_subs = {
|
|
200
|
+
phi1p_R: 0,
|
|
201
|
+
phi1p_I: 0,
|
|
202
|
+
phi2p_R: 0,
|
|
203
|
+
phi2p_I: 0,
|
|
204
|
+
phi1_I: 0,
|
|
205
|
+
phi2_I: 0,
|
|
206
|
+
phi1_R: v1_sym,
|
|
207
|
+
phi2_R: v2_sym,
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
condition_rows = []
|
|
211
|
+
for kind, index in CONDITION_SPECS:
|
|
212
|
+
if kind == "grad":
|
|
213
|
+
expr = grad_exprs[index]
|
|
214
|
+
else:
|
|
215
|
+
i, j = index
|
|
216
|
+
expr = hess_exprs[i][j]
|
|
217
|
+
expr = sp.simplify(expr.subs(vacuum_subs))
|
|
218
|
+
row = [sp.simplify(sp.diff(expr, param)) for param in delta_params]
|
|
219
|
+
condition_rows.append(row)
|
|
220
|
+
|
|
221
|
+
matrix = sp.Matrix(condition_rows)
|
|
222
|
+
return sp.lambdify((v1_sym, v2_sym), matrix, "numpy")
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def _counterterm_matrix(v1: float, v2: float) -> np.ndarray:
|
|
226
|
+
r"""Evaluate the linear counterterm system matrix :math:`M(v_1, v_2)`.
|
|
227
|
+
|
|
228
|
+
The matrix is defined through the on-shell matching equations
|
|
229
|
+
|
|
230
|
+
.. math::
|
|
231
|
+
M(v_1, v_2)\,\delta = -\Delta,
|
|
232
|
+
|
|
233
|
+
where :math:`\delta = (\delta m_{11}^2, \delta m_{22}^2, \delta m_{12}^2,
|
|
234
|
+
\delta\lambda_1, \delta\lambda_2, \delta\lambda_3, \delta\lambda_5)`.
|
|
235
|
+
"""
|
|
236
|
+
matrix_func = _counterterm_matrix_factory()
|
|
237
|
+
return np.asarray(matrix_func(v1, v2), dtype=float)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def _condition_vector(grad_phys: np.ndarray, hess_phys: np.ndarray) -> np.ndarray:
|
|
241
|
+
"""Collect the tadpole and Hessian conditions into the solver right-hand side."""
|
|
242
|
+
values = []
|
|
243
|
+
for kind, index in CONDITION_SPECS:
|
|
244
|
+
if kind == "grad":
|
|
245
|
+
values.append(-grad_phys[index])
|
|
246
|
+
else:
|
|
247
|
+
i, j = index
|
|
248
|
+
values.append(-hess_phys[i, j])
|
|
249
|
+
return np.asarray(values, dtype=float)
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def compute_counterterms(
|
|
253
|
+
model,
|
|
254
|
+
) -> Tuple[CounterTerms, np.ndarray, np.ndarray, np.ndarray]:
|
|
255
|
+
"""
|
|
256
|
+
Evaluate the Coleman–Weinberg gradient/Hessian and solve for the 2HDM counterterms.
|
|
257
|
+
|
|
258
|
+
Parameters
|
|
259
|
+
----------
|
|
260
|
+
model:
|
|
261
|
+
Initialised 2HDM model instance providing vevs, couplings, and conversion
|
|
262
|
+
factors.
|
|
263
|
+
|
|
264
|
+
Returns
|
|
265
|
+
-------
|
|
266
|
+
counterterms, gradient, hessian, residual:
|
|
267
|
+
Counterterm container together with the Coleman–Weinberg derivatives in
|
|
268
|
+
the internal TransitionListener unit system, and the residual of the
|
|
269
|
+
renormalisation conditions (also expressed in internal units).
|
|
270
|
+
"""
|
|
271
|
+
|
|
272
|
+
metadata, tensors = _load_dataset()
|
|
273
|
+
arrays = tensor_utils.evaluate_curvature_arrays(
|
|
274
|
+
tensors,
|
|
275
|
+
copy.deepcopy(metadata),
|
|
276
|
+
_tensor_parameter_values(model),
|
|
277
|
+
yukawa_key=model._YUKAWA_TYPE_MAP[int(model.yukawa_type)],
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
vev = np.zeros(8, dtype=float)
|
|
281
|
+
vev[4] = float(model.v1_GeV)
|
|
282
|
+
vev[6] = float(model.v2_GeV)
|
|
283
|
+
|
|
284
|
+
grad_phys, hess_phys = model.coleman_weinberg_from_curvatures(
|
|
285
|
+
arrays,
|
|
286
|
+
vev,
|
|
287
|
+
scale=float(model.v_GeV),
|
|
288
|
+
)
|
|
289
|
+
grad_phys = np.real_if_close(grad_phys, tol=1e8)
|
|
290
|
+
hess_phys = np.real_if_close(hess_phys, tol=1e8)
|
|
291
|
+
if np.iscomplexobj(grad_phys):
|
|
292
|
+
if not np.allclose(grad_phys.imag, 0.0, atol=1e-12):
|
|
293
|
+
raise ValueError(
|
|
294
|
+
"Coleman–Weinberg gradient carries sizeable imaginary parts."
|
|
295
|
+
)
|
|
296
|
+
grad_phys = grad_phys.real
|
|
297
|
+
if np.iscomplexobj(hess_phys):
|
|
298
|
+
if not np.allclose(hess_phys.imag, 0.0, atol=1e-12):
|
|
299
|
+
raise ValueError(
|
|
300
|
+
"Coleman–Weinberg Hessian carries sizeable imaginary parts."
|
|
301
|
+
)
|
|
302
|
+
hess_phys = hess_phys.real
|
|
303
|
+
hess_phys = tensor_utils.ensure_symmetric(np.asarray(hess_phys, dtype=float))
|
|
304
|
+
|
|
305
|
+
v1 = float(model.v1_GeV)
|
|
306
|
+
v2 = float(model.v2_GeV)
|
|
307
|
+
A = _counterterm_matrix(v1, v2)
|
|
308
|
+
b = _condition_vector(grad_phys, hess_phys)
|
|
309
|
+
try:
|
|
310
|
+
(
|
|
311
|
+
dm11_sq_GeV2,
|
|
312
|
+
dm22_sq_GeV2,
|
|
313
|
+
dm12_sq_GeV2,
|
|
314
|
+
dlambda1,
|
|
315
|
+
dlambda2,
|
|
316
|
+
dlambda3,
|
|
317
|
+
dlambda5,
|
|
318
|
+
) = np.linalg.solve(A, b)
|
|
319
|
+
except np.linalg.LinAlgError as exc:
|
|
320
|
+
raise ValueError(
|
|
321
|
+
"Failed to solve the counterterm system; vacuum configuration is "
|
|
322
|
+
"singular."
|
|
323
|
+
) from exc
|
|
324
|
+
dlambda4 = 0.0
|
|
325
|
+
|
|
326
|
+
cf = model.conversionFactor
|
|
327
|
+
grad_internal = np.asarray(
|
|
328
|
+
np.where(np.abs(grad_phys) < 1e-10, 0.0, grad_phys * cf),
|
|
329
|
+
dtype=float,
|
|
330
|
+
)
|
|
331
|
+
hess_internal = np.asarray(
|
|
332
|
+
np.where(
|
|
333
|
+
np.abs(hess_phys) < 1e-10,
|
|
334
|
+
0.0,
|
|
335
|
+
hess_phys * (cf * cf),
|
|
336
|
+
),
|
|
337
|
+
dtype=float,
|
|
338
|
+
)
|
|
339
|
+
hess_internal = tensor_utils.ensure_symmetric(hess_internal)
|
|
340
|
+
|
|
341
|
+
dm11_sq_internal = dm11_sq_GeV2 * (cf * cf)
|
|
342
|
+
dm22_sq_internal = dm22_sq_GeV2 * (cf * cf)
|
|
343
|
+
dm12_sq_internal = dm12_sq_GeV2 * (cf * cf)
|
|
344
|
+
|
|
345
|
+
counterterm_values = {
|
|
346
|
+
"dlambda1": float(dlambda1),
|
|
347
|
+
"dlambda2": float(dlambda2),
|
|
348
|
+
"dlambda3": float(dlambda3),
|
|
349
|
+
"dlambda4": float(dlambda4),
|
|
350
|
+
"dlambda5": float(dlambda5),
|
|
351
|
+
"dm11_sq": float(dm11_sq_internal),
|
|
352
|
+
"dm22_sq": float(dm22_sq_internal),
|
|
353
|
+
"dm12_sq": float(dm12_sq_internal),
|
|
354
|
+
}
|
|
355
|
+
counterterms = CounterTerms.from_dict(counterterm_values)
|
|
356
|
+
|
|
357
|
+
counterterm_vector = np.array(
|
|
358
|
+
[
|
|
359
|
+
dm11_sq_GeV2,
|
|
360
|
+
dm22_sq_GeV2,
|
|
361
|
+
dm12_sq_GeV2,
|
|
362
|
+
dlambda1,
|
|
363
|
+
dlambda2,
|
|
364
|
+
dlambda3,
|
|
365
|
+
dlambda5,
|
|
366
|
+
],
|
|
367
|
+
dtype=float,
|
|
368
|
+
)
|
|
369
|
+
residual_phys = A @ counterterm_vector - b
|
|
370
|
+
residual_internal = residual_phys.copy()
|
|
371
|
+
residual_internal[:2] *= cf
|
|
372
|
+
residual_internal[2:] *= cf * cf
|
|
373
|
+
|
|
374
|
+
return counterterms, grad_internal, hess_internal, residual_internal
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
"""Custom exception hierarchy that exposes user-friendly error messages.
|
|
2
|
+
|
|
3
|
+
The exceptions defined here are tailored to the various subsystems of
|
|
4
|
+
TransitionListener. They encapsulate common failure modes (configuration,
|
|
5
|
+
phase reconstruction, tunnelling, percolation, hydrodynamics) and attach
|
|
6
|
+
error codes where the command-line interface needs to surface diagnostic
|
|
7
|
+
information to end users.
|
|
8
|
+
|
|
9
|
+
Part of TransitionListener v2.0
|
|
10
|
+
Documentation: https://tasillo.de/TransitionListener/
|
|
11
|
+
|
|
12
|
+
Authors:
|
|
13
|
+
Jonas Matuszak <jonas.matuszak@kit.edu>
|
|
14
|
+
Carlo Tasillo <carlo.tasillo@ific.uv.es>
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
# Terminal errors
|
|
18
|
+
class NoModelError(Exception):
|
|
19
|
+
"""Raised when the model file is not found or cannot be loaded."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, message="No model found. Please check the model file path."):
|
|
22
|
+
"""Initialise the error with a descriptive default message."""
|
|
23
|
+
super().__init__(message)
|
|
24
|
+
|
|
25
|
+
class NoConfigError(Exception):
|
|
26
|
+
"""Raised when the configuration file is missing or unreadable."""
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
message="No config file found. Please check the config file path.",
|
|
31
|
+
):
|
|
32
|
+
"""Initialise the error with a descriptive default message."""
|
|
33
|
+
super().__init__(message)
|
|
34
|
+
|
|
35
|
+
class NoLoggerError(Exception):
|
|
36
|
+
"""Raised when logging cannot be initialised."""
|
|
37
|
+
|
|
38
|
+
def __init__(self, message="Could not create logger."):
|
|
39
|
+
"""Initialise the error with a descriptive default message."""
|
|
40
|
+
super().__init__(message)
|
|
41
|
+
|
|
42
|
+
# Errors that are caught during the run
|
|
43
|
+
class TooSmalldVError(Exception):
|
|
44
|
+
"""
|
|
45
|
+
Used when the potential is too flat to be integrated. This means that the
|
|
46
|
+
bounce solution would be an extreme thin wall bubble with low latent heat,
|
|
47
|
+
likely not giving rise to any gravitational waves.
|
|
48
|
+
"""
|
|
49
|
+
pass
|
|
50
|
+
|
|
51
|
+
class InfiniteActionError(Exception):
|
|
52
|
+
"""
|
|
53
|
+
This is a hot fix for the infinite action error: When this error is raised,
|
|
54
|
+
the action is actually not infinite, but so large that the numerical
|
|
55
|
+
integration of the bubble profile fails.
|
|
56
|
+
"""
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
class ZeroActionError(Exception):
|
|
60
|
+
"""
|
|
61
|
+
This is a hot fix for the zero action error: When this error is raised,
|
|
62
|
+
the action is actually not zero, but so small that the numerical
|
|
63
|
+
integration of the bubble profile fails.
|
|
64
|
+
"""
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
class DeformationError(Exception):
|
|
68
|
+
"""Raised when the path deformation algorithm fails to converge."""
|
|
69
|
+
|
|
70
|
+
def __init__(
|
|
71
|
+
self,
|
|
72
|
+
message=(
|
|
73
|
+
"Deformation doesn't appear to be converging. Stopping at the point of best "
|
|
74
|
+
"convergence."
|
|
75
|
+
),
|
|
76
|
+
):
|
|
77
|
+
"""Initialise the error with the convergence diagnostic message."""
|
|
78
|
+
super().__init__(message)
|
|
79
|
+
|
|
80
|
+
class PotentialError(Exception):
|
|
81
|
+
"""
|
|
82
|
+
Used when the potential does not have the expected characteristics.
|
|
83
|
+
|
|
84
|
+
The error messages should be tuples, with the second item being one of
|
|
85
|
+
``(\"no barrier\", \"stable, not metastable\")``.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
def __init__(
|
|
89
|
+
self,
|
|
90
|
+
message=(
|
|
91
|
+
"There was an error with the potential. It could be that there is no barrier "
|
|
92
|
+
"for instance."
|
|
93
|
+
),
|
|
94
|
+
error_type="no barrier",
|
|
95
|
+
):
|
|
96
|
+
"""Store both the human-readable explanation and the machine-readable tag."""
|
|
97
|
+
super().__init__(message)
|
|
98
|
+
self.error_type = error_type
|
|
99
|
+
|
|
100
|
+
class ParamNamesError(Exception):
|
|
101
|
+
"""Raised when the parameter names do not match the model definition."""
|
|
102
|
+
|
|
103
|
+
def __init__(self, message="Parameter names do not match the model parameters."):
|
|
104
|
+
"""Initialise the error with a descriptive default message."""
|
|
105
|
+
super().__init__(message)
|
|
106
|
+
|
|
107
|
+
class GWParamsError(Exception):
|
|
108
|
+
"""Raised when the gravitational wave parameters are inconsistent or incomplete."""
|
|
109
|
+
|
|
110
|
+
def __init__(self, message="The given GW params do not match the required ones."):
|
|
111
|
+
"""Initialise the error with a descriptive default message."""
|
|
112
|
+
super().__init__(message)
|
|
113
|
+
|
|
114
|
+
# Errors that are raise during the run and are
|
|
115
|
+
# only caught in the main function together with the
|
|
116
|
+
# error code
|
|
117
|
+
class TachyonError(Exception):
|
|
118
|
+
"""Raised when a tachyonic mass is detected at the zero-temperature minimum."""
|
|
119
|
+
|
|
120
|
+
def __init__(
|
|
121
|
+
self,
|
|
122
|
+
message="Tachyonic boson mass at zero temperature minimum.",
|
|
123
|
+
):
|
|
124
|
+
"""Attach the CLI error code identifying tachyonic ground states."""
|
|
125
|
+
super().__init__(message)
|
|
126
|
+
self.errorcode = 1
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class NucleationError(Exception):
|
|
130
|
+
"""Raised when the nucleation temperature could not be identified."""
|
|
131
|
+
|
|
132
|
+
def __init__(self, message="Nucleation temperature not found."):
|
|
133
|
+
"""Attach the CLI error code identifying nucleation failures."""
|
|
134
|
+
super().__init__(message)
|
|
135
|
+
self.errorcode = 2
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class WrongT0MinimumError(Exception):
|
|
139
|
+
"""Raised when the expected T = 0 minimum does not match the last minimum."""
|
|
140
|
+
|
|
141
|
+
def __init__(
|
|
142
|
+
self,
|
|
143
|
+
message="Expected T = 0 minimum does not match found last minimum.",
|
|
144
|
+
):
|
|
145
|
+
"""Attach the CLI error code identifying mis-matched zero-temperature minima."""
|
|
146
|
+
super().__init__(message)
|
|
147
|
+
self.errorcode = 3
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class NoPhases(Exception):
|
|
151
|
+
"""Raised when the phase tracing routine cannot identify any phases or the user
|
|
152
|
+
tries to compute transitions without tracing first."""
|
|
153
|
+
|
|
154
|
+
def __init__(self, message=""):
|
|
155
|
+
"""Attach the CLI error code identifying missing phases."""
|
|
156
|
+
super().__init__(message)
|
|
157
|
+
self.errorcode = 4
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class OnlyOnePhase(Exception):
|
|
161
|
+
"""Raised when phase tracing yields only a single phase. In that case,
|
|
162
|
+
no transitions can be computed."""
|
|
163
|
+
|
|
164
|
+
def __init__(self, message="Only one phase has been found."):
|
|
165
|
+
"""Attach the CLI error code identifying incomplete phase scans."""
|
|
166
|
+
super().__init__(message)
|
|
167
|
+
self.errorcode = 5
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class NoTransitionFound(Exception):
|
|
171
|
+
"""Raised when no viable transition is found between identified phases."""
|
|
172
|
+
|
|
173
|
+
def __init__(self, message="No transition was found."):
|
|
174
|
+
"""Attach the CLI error code identifying missing transitions."""
|
|
175
|
+
super().__init__(message)
|
|
176
|
+
self.errorcode = 6
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
class PercolationApproximation1Error(Exception):
|
|
180
|
+
"""Raised when the percolation temperature approximation fails to converge."""
|
|
181
|
+
|
|
182
|
+
def __init__(
|
|
183
|
+
self,
|
|
184
|
+
message="Percolation temperature using approximation 1 could not be found.",
|
|
185
|
+
):
|
|
186
|
+
"""Attach the CLI error code identifying percolation-approximation failures."""
|
|
187
|
+
super().__init__(message)
|
|
188
|
+
self.errorcode = 7
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class TooMuchSupercoolingError(Exception):
|
|
192
|
+
"""Raised when excessive supercooling prevents bubble nucleation within Hubble time."""
|
|
193
|
+
|
|
194
|
+
def __init__(
|
|
195
|
+
self,
|
|
196
|
+
message=(
|
|
197
|
+
"No transition found because the high-temperature phase is too supercooled "
|
|
198
|
+
"to allow for the nucleation of one bubble per Hubble volume until today."
|
|
199
|
+
),
|
|
200
|
+
):
|
|
201
|
+
"""Attach the CLI error code identifying over-supercooled transitions."""
|
|
202
|
+
super().__init__(message)
|
|
203
|
+
self.errorcode = 8
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
class OnlySecondOrderTransitionsError(Exception):
|
|
207
|
+
"""Raised when the scan identifies only second-order transitions."""
|
|
208
|
+
|
|
209
|
+
def __init__(
|
|
210
|
+
self,
|
|
211
|
+
message="Only second-order transition(s) found. No first-order transitions.",
|
|
212
|
+
):
|
|
213
|
+
"""Attach the CLI error code identifying missing first-order transitions."""
|
|
214
|
+
super().__init__(message)
|
|
215
|
+
self.errorcode = 9
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
class PercolationError(Exception):
|
|
219
|
+
"""Raised when the percolation temperature could not be determined."""
|
|
220
|
+
|
|
221
|
+
def __init__(self, message="Percolation temperature could not be found."):
|
|
222
|
+
"""Attach the CLI error code identifying percolation failures."""
|
|
223
|
+
super().__init__(message)
|
|
224
|
+
self.errorcode = 10
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
class TunnelingError(Exception):
|
|
228
|
+
"""Raised when tunnelling fails to produce an action."""
|
|
229
|
+
|
|
230
|
+
def __init__(self, message="Tunneling action not found."):
|
|
231
|
+
"""Attach the CLI error code identifying tunnelling failures."""
|
|
232
|
+
super().__init__(message)
|
|
233
|
+
self.errorcode = 11
|
|
234
|
+
|
|
235
|
+
class InitPotentialError(Exception):
|
|
236
|
+
"""
|
|
237
|
+
Used when there is a problem creating the potential
|
|
238
|
+
|
|
239
|
+
The error message should be something like ``\"potential unbounded from below\"``
|
|
240
|
+
or ``\"unphysical Lagrangian parameters\"``.
|
|
241
|
+
"""
|
|
242
|
+
|
|
243
|
+
def __init__(
|
|
244
|
+
self,
|
|
245
|
+
message="There was an error with the initialisation of the potential.",
|
|
246
|
+
error_type="unbounded from below",
|
|
247
|
+
):
|
|
248
|
+
"""Attach both the human-readable explanation and a machine-readable tag."""
|
|
249
|
+
super().__init__(message)
|
|
250
|
+
self.error_type = error_type
|
|
251
|
+
self.errorcode = 12
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class SplineError(Exception):
|
|
255
|
+
"""Raised when constructing a spline along the tunnelling path fails."""
|
|
256
|
+
|
|
257
|
+
def __init__(self, message="A spline error occurred."):
|
|
258
|
+
"""Attach the CLI error code identifying spline construction failures."""
|
|
259
|
+
super().__init__(message)
|
|
260
|
+
self.errorcode = 13
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
class WrongHighTPhaseError(Exception):
|
|
264
|
+
"""Raised when the high-temperature phase differs from the expected one."""
|
|
265
|
+
|
|
266
|
+
def __init__(
|
|
267
|
+
self,
|
|
268
|
+
message="The high-temperature phase does not match the expected one.",
|
|
269
|
+
):
|
|
270
|
+
"""Attach the CLI error code identifying high-temperature phase mismatches."""
|
|
271
|
+
super().__init__(message)
|
|
272
|
+
self.errorcode = 14
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
class EternalInflationError(Exception):
|
|
276
|
+
"""Raised when the eternal-inflation criterion is fulfilled."""
|
|
277
|
+
|
|
278
|
+
def __init__(self, message="Eternal inflation criterion is fulfilled."):
|
|
279
|
+
"""Attach the CLI error code identifying eternal-inflation issues."""
|
|
280
|
+
super().__init__(message)
|
|
281
|
+
self.errorcode = 15
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
class Timeout(Exception):
|
|
285
|
+
"""Raised when a long-running calculation exceeds the allowed runtime."""
|
|
286
|
+
|
|
287
|
+
def __init__(self, message="The calculation timed out."):
|
|
288
|
+
"""Attach the CLI error code identifying timeout situations."""
|
|
289
|
+
super().__init__(message)
|
|
290
|
+
self.errorcode = 16
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
class ActionRateJitterError(Exception):
|
|
294
|
+
"""Raised when the sampled bounce action implies a non-smooth nucleation rate."""
|
|
295
|
+
|
|
296
|
+
def __init__(
|
|
297
|
+
self,
|
|
298
|
+
message=(
|
|
299
|
+
"Detected a large non-smooth jitter in Gamma/H^4 across the active "
|
|
300
|
+
"percolation band. This indicates an instability of the bounce "
|
|
301
|
+
"computation or a wrong tunnelling branch."
|
|
302
|
+
),
|
|
303
|
+
):
|
|
304
|
+
"""Attach the CLI error code identifying action/rate smoothness failures."""
|
|
305
|
+
super().__init__(message)
|
|
306
|
+
self.errorcode = 17
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
class UnexpectedError(Exception):
|
|
310
|
+
"""Raised when an unclassified failure occurs in the CLI."""
|
|
311
|
+
|
|
312
|
+
def __init__(self, message="An unexpected error occurred."):
|
|
313
|
+
"""Attach the catch-all CLI error code."""
|
|
314
|
+
super().__init__(message)
|
|
315
|
+
self.errorcode = 999
|