88#include < complex>
99#include < functional>
1010
11+ // references for value updates:
12+ // [C1] CODATA 2022: P.J. Mohr et al, Rev. Mod. Phys. 97 (2025) 025002
13+ // [C2] M.M. Restrepo and E.G. Myers, PRL 131 (2023) 243002
1114namespace TBeta
1215{
1316 static constexpr double pi = 3.141592653589793238462643383279502884 ; // Pi
1417 static constexpr double twopi = 2.0 * pi; // 2 Pi
15- static constexpr double me = 510.99895 ; // electron mass [keV]
18+ static constexpr double me = 510.99895069 ; // [C1] electron mass [keV]
1619 static constexpr double gA = 1.2646 ; // nucleon axial coupling
1720 static constexpr double gAq = 1.24983 ; // quenched gA
1821 static constexpr double gV = 1.0 ; // nucleon vector coupling
19- static constexpr double MTr = 2808920.8205 ; // bare nuclear tritium mass [keV]
20- static constexpr double Mf = 2808391.2193 ; // bare nuclear 3He+ mass [keV]
21- static constexpr double alpha = 7.2973525693e -3 ; // fine structure constant
22+ static constexpr double MTr = 2808921.1367789 ; // [C2] bare nuclear tritium mass [keV]
23+ static constexpr double Mf = 2808391.6111557 ; // [C2] bare nuclear 3He+ mass [keV]
24+ static constexpr double alpha = 7.2973525643e -3 ; // [C1] ine structure constant
2225 static constexpr double Gf = 1.1663787e-17 ; // Fermi interaction strength [keV^-2]
2326 static constexpr double Rn = 2.884e-3 ; // nuclear radius of 3He [me]
2427 static constexpr double keVInvSec = 1.52e18 ; // conversion [keV s]
@@ -39,12 +42,17 @@ namespace TBeta
3942 static constexpr double dm31Sq = 2.517e-9 ;
4043 static constexpr double dm32Sq = -2.498e-9 ;
4144
45+ // formula constants
46+ static constexpr double emin = 0.2 ; // [keV] low-energy cut-off, avoiding atomic effects in S(Z,en)
47+ static constexpr double v0 = 76.0e-3 ; // =76 eV in ref [1]
48+ static constexpr double mcc = Mf / me; // mass of He3 in units of me [1]
49+
4250 //
4351 // function interfaces
4452 //
4553
4654 // heaviside function
47- inline double heavyside (double x){
55+ double heavyside (double x){
4856 double result;
4957 if (x>0.0 ) result = 1.0 ;
5058 else if (x==0.0 ) result = 0.5 ;
@@ -53,7 +61,7 @@ namespace TBeta
5361 }
5462
5563 // Lanczos approximation - needs testing!
56- inline std::complex <double > Gamma (std::complex <double > z) {
64+ std::complex <double > Gamma (std::complex <double > z) {
5765 double g = 7 ;
5866 static const double p[9 ] = {0.99999999999980993 , 676.5203681218851 , -1259.1392167224028 ,
5967 771.32342877765313 , -176.61502916214059 , 12.507343278686905 ,
@@ -107,23 +115,15 @@ namespace TBeta
107115 // [1] Preprint arXiv 1806.00369
108116 // [2] PRL 5(85) 807
109117
110- // 3-body endpoint energy of bare tritium [keV] (neutrino mass munu [keV])
111- inline double endpoint (double munu) {
112- double m2 = MTr*MTr;
113- double me2 = me*me;
114- double msum2 = (Mf+munu)*(Mf+munu);
115- return (m2 + me2 - msum2)/(2.0 *MTr) - me;
116- }
117-
118118 // Atomic 3He mass including n-th energy level binding
119- inline double MfAt (int n){
119+ double MfAt (int n){
120120 if (n<1 ) n=1 ; // remove illegal n values
121121 return Mf + me - 4.0 *Ryd/(n*n);
122122 }
123123
124124 // 3-body endpoint energy of atomic tritium [keV] (neutrino mass [keV])
125125 // and energy level n
126- inline double endAt (double munu, int n){
126+ double endAt (double munu, int n){
127127 double mat2 = MAt*MAt;
128128 double me2 = me*me;
129129 double matn = MfAt (n);
@@ -132,17 +132,16 @@ namespace TBeta
132132 }
133133
134134 // Simpson approximation of Fermi function [1] (A.2)
135- inline double Fermi (int Z, double beta) {
135+ double Fermi (int Z, double beta) {
136136 double eta = alpha * Z / beta; // Sommerfeld parameter
137137 double nom = twopi * eta * (1.002037 - 0.001427 *beta);
138138 double denom = 1.0 -std::exp (-twopi * eta);
139139 return nom / denom;
140140 }
141141
142142 // Radiative correction [1] (A.3)
143- inline double G (double en, double endp) {
144- if (endp<=en) return 0.0 ;
145- if (en<0.04 ) en = 0.04 ; // avoid zero energy
143+ double G (double en, double endp) {
144+ if (endp<=en || en<emin) return 0.0 ;
146145 double w = (en + me) / me; // total electron energy [me]
147146 double w0 = (endp + me) / me;
148147 double p = std::sqrt (w*w - 1.0 );
@@ -156,9 +155,8 @@ namespace TBeta
156155 }
157156
158157 // Orbital electron shielding [1] (A.4)
159- inline double S (int Z, double en) {
160- if (en<0.04 ) en = 0.04 ; // check announced anomaly
161- static constexpr double v0 = 1.45 *alpha*alpha * me; // =76 eV in ref [1]
158+ double S (int Z, double en) {
159+ if (en<emin) return 1.0 ; // check announced anomaly
162160 double w = (en + me) / me; // total electron energy [me]
163161 double p = std::sqrt (w*w - 1.0 );
164162 double wb = w - v0 / me;
@@ -168,13 +166,15 @@ namespace TBeta
168166 double gamma = std::sqrt (1.0 -(alpha*alpha*Z*Z));
169167 double fac1 = wb/w*std::pow (pb/p, -1.0 +2.0 *gamma);
170168 std::complex <double > arg1 (gamma, etab), arg2 (gamma, eta);
171- double nom = std::norm (Gamma (arg1));
172- double denom = std::norm (Gamma (arg2));
169+ std::complex <double > d1 = Gamma (arg1);
170+ std::complex <double > d2 = Gamma (arg2);
171+ double nom = std::norm (d1 * d1);
172+ double denom = std::norm (d2 * d2);
173173 return fac1 * std::exp (pi*(etab-eta)) * nom/denom;
174174 }
175175
176176 // Scaling od the electric field within nucleus [1] (A.7)
177- inline double L (int Z, double en) {
177+ double L (int Z, double en) {
178178 double w = (en + me) / me; // total electron energy [me]
179179 double fac = alpha * Z;
180180 double gamma = std::sqrt (1.0 -fac*fac);
@@ -184,8 +184,8 @@ namespace TBeta
184184 }
185185
186186 // Convolution of electron and neutrino wavefunctions within nucleus [1] (A.8)
187- inline double CC (int Z, double en, double endp) {
188- if (endp<=en) return 1.0 ;
187+ double CC (int Z, double en, double endp) {
188+ if (endp<=en || en<emin ) return 1.0 ;
189189 double w = (en + me) / me; // total electron energy [me]
190190 double w0 = (endp + me) / me;
191191 double fac = alpha * Z;
@@ -197,11 +197,9 @@ namespace TBeta
197197
198198
199199 // Recoiling nuclear charge field [1] (A.9)
200- inline double Q (int Z, double en, double endp) {
201- if (endp<=en) return 1.0 ;
202- if (en<0.04 ) en = 0.04 ; // avoid zero energy
203- static const double mcc = 5497.885 ;
204- static const double lt = 1.265 ;
200+ double Q (int Z, double en, double endp) {
201+ if (endp<=en || en<emin) return 1.0 ;
202+ double lt = gA / gV ;
205203 double w = (en + me) / me; // total electron energy [me]
206204 double w0 = (endp + me) / me;
207205 double p = std::sqrt (w*w - 1.0 );
@@ -212,18 +210,18 @@ namespace TBeta
212210 // Combined correction factor for atomic tritium
213211 // function of neutrino mass munu [keV], n atomic energy level
214212 // of daughter nucleus, en electron energy [kev]
215- inline double Corr (double en, double munu, int n) {
216- double arg = std::sqrt ((en+me)*(en+me)-me*me)/(en+me);
213+ double Corr (double en, double munu, int n) {
217214 double e0 = endAt (munu, n);
218- if (e0 <=en) return 1.0 ; // no correction
215+ if (e0 <=en || en<emin) return 1.0 ; // no correction
216+ double arg = std::sqrt ((en+me)*(en+me)-me*me)/(en+me);
219217 return Fermi (2 ,arg)*S (2 ,en)*G (en,e0 )*L (2 ,en)*CC (2 ,en,e0 )*Q (2 ,en,e0 );
220218 }
221219
222220 // Differential decay rate with energy en [kev], applicable to LH SM currents
223221 // for the emission of an electron antineutrino with mass munu [kev] and
224222 // the endpoint of the n-th 3He energy level. With corrections.
225- inline double stub (double en, double munu, double e0 ) { // used twice, factor out
226- if (e0 <en) return 0.0 ;
223+ double stub (double en, double munu, double e0 ) { // used twice, factor out
224+ if (e0 <en || en<emin ) return 0.0 ;
227225 double fac1 = (Gf*Gf*Vud*Vud)/(2.0 *pi*pi*pi);
228226 double denom = MTr*MTr - 2.0 *MTr*(en+me) + me*me;
229227 double nom1 = MTr*(en+me) - me*me;
@@ -243,7 +241,7 @@ namespace TBeta
243241 return fac1*(term1+term2+term3);
244242 }
245243
246- inline double Diff (double en, double munu, int n) {
244+ double Diff (double en, double munu, int n) {
247245 double e0 = endAt (munu, n);
248246 double fac = stub (en, munu, e0 );
249247 return fac * Corr (en,munu,n);
@@ -252,7 +250,7 @@ namespace TBeta
252250 // neutrino mass spectrum
253251 // order is boolean True for Normal order (NO)
254252 // False for Inverted order (IO)
255- const inline std::array<double ,3 >& nuSpectrum (bool order, double munu) {
253+ const std::array<double ,3 >& nuSpectrum (bool order, double munu) {
256254 static const std::array<double ,3 > no = {munu, std::sqrt (munu*munu+dm21Sq), std::sqrt (munu*munu+dm31Sq)};
257255 static const std::array<double ,3 > io = {std::sqrt (munu*munu-dm21Sq-dm32Sq), std::sqrt (munu*munu-dm32Sq), munu};
258256 return order ? no : io;
@@ -261,7 +259,7 @@ namespace TBeta
261259 // like Diff but summing over all three light neutrinos with weights.
262260 // order is boolean True for Normal order (NO)
263261 // False for Inverted order (IO)
264- inline double Diff3nu (bool order, double en, double munu, int n) {
262+ double Diff3nu (bool order, double en, double munu, int n) {
265263 const std::array<double ,3 >& UeSq = order ? UeSqNO : UeSqIO;
266264 double sum = 0.0 ;
267265 for (int i=0 ;i<3 ;++i) {
@@ -273,26 +271,26 @@ namespace TBeta
273271 // like Diff but summing over all three light neutrinos with weights and
274272 // a sterile neutrino with mass mN [keV] with active-sterile mixing
275273 // strength eta (0<=eta<1)
276- inline double Diff4nu (bool order, double mN , double eta, double en, double munu, int n) {
274+ double Diff4nu (bool order, double mN , double eta, double en, double munu, int n) {
277275 double e0 = endAt (mN , n);
278276 return (1.0 -eta*eta)*Diff3nu (order, en, munu, n) + eta*eta*Diff (en, mN , n)*heavyside (e0 -en);
279277 }
280278
281279 // Sum over discrete atomic energy levels of 3He
282280 // with branching ratios, [2]
283- inline double etaL (double en) {
281+ double etaL (double en) {
284282 double denom = (en+me)*(en+me) - me*me;
285283 return -2.0 *alpha*me/std::sqrt (denom);
286284 }
287285
288- inline double aL (double en) {
286+ double aL (double en) {
289287 double eta = etaL (en);
290288 double nom = std::exp (2.0 *eta*std::atan (-2.0 /eta));
291289 double denom = (1.0 + eta*eta/4.0 )*(1.0 + eta*eta/4.0 );
292290 return eta*eta*eta*eta*nom/denom;
293291 }
294292
295- inline double Lev (int n, double en) {
293+ double Lev (int n, double en) {
296294 double al = aL (en);
297295 if (n==2 ) // special case
298296 return 0.25 * (1.0 + al*al - al);
@@ -304,7 +302,7 @@ namespace TBeta
304302 // Full (SM+sterile) differential decay rate as function of electron energy [keV].
305303 // Includes all corrections (no continuum orbital e- states) and
306304 // the first 5 bound discrete atomic states.
307- inline double dGammadE (bool order, double munu, double mN , double eta, double en) {
305+ double dGammadE (bool order, double munu, double mN , double eta, double en) {
308306 double sum = 0.0 ;
309307 for (int n=1 ;n<=5 ;++n)
310308 sum += Lev (n, en) * Diff4nu (order, mN , eta, en, munu, n);
@@ -313,40 +311,40 @@ namespace TBeta
313311
314312 // Set up all contributions including continous states and first 5
315313 // discrete states. Here consider state n as double for continuum states.
316- inline double endCont (double munu, double n) {
314+ double endCont (double munu, double n) {
317315 return endAt (munu, 1 )-4.0 *Ryd*(1.0 +1.0 /(n*n));
318316 }
319317
320- inline double CorrCont (double en, double munu, double n) {
318+ double CorrCont (double en, double munu, double n) {
321319 double e0 = endCont (munu, n);
322320 double nom = (en+me)*(en+me) - me*me;
323321 double fac = Fermi (2 ,std::sqrt (nom)/(en+me))*S (2 ,en)*G (en,e0 );
324322 return fac*L (2 ,en)*CC (2 ,en,e0 )*Q (2 ,en,e0 );
325323 }
326324
327- inline double DiffCont (double en, double munu, double n) {
325+ double DiffCont (double en, double munu, double n) {
328326 double e0 = endCont (munu, n);
329327 double fac = stub (en, munu, e0 );
330328 return fac * CorrCont (en, munu, n);
331329 }
332330
333331 // integrand over states g
334- inline double integrand (double g, double en, double munu) {
332+ double integrand (double g, double en, double munu) {
335333 double fac1 = DiffCont (en, munu, g)*twopi/(g*g*g*(std::exp (twopi*g)-1.0 ));
336334 double fac2 = g*g*g*g*std::exp (2.0 *g*std::atan (-2.0 /g))/((1.0 +g*g/4.0 )*(1.0 +g*g/4.0 ));
337335 return fac1*(fac2*fac2 + aL (en)*aL (en) - aL (en)*fac2);
338336 }
339337
340338 // Contribution only from the continuum orbital electron states.
341339 // integrate over g.
342- inline double gammaCont (double en, double munu) {
343- if (en > endCont (munu, 1e10 )) return 0.0 ;
340+ double gammaCont (double en, double munu) {
341+ if (en > endCont (munu, 1e10 ) || en<emin ) return 0.0 ;
344342 std::function<double (double ,double ,double )> fn = integrand;
345343 SimpsonIntegral sint (fn, en, munu);
346344 return sint.integrate (-99 , etaL (en), 1000 )/pi;
347345 }
348346
349- inline double dGammadECont (bool order, double munu, double mN , double eta, double en) {
347+ double dGammadECont (bool order, double munu, double mN , double eta, double en) {
350348 const std::array<double ,3 >& UeSq = order ? UeSqNO : UeSqIO;
351349 double sum = 0.0 ;
352350 for (int i=0 ;i<3 ;++i) {
@@ -355,7 +353,7 @@ namespace TBeta
355353 return (1 -eta*eta)*sum + eta*eta*gammaCont (en, mN );
356354 }
357355
358- inline double dGammadEFull (bool order, double munu, double mN , double eta, double en) {
356+ double dGammadEFull (bool order, double munu, double mN , double eta, double en) {
359357 return dGammadE (order, munu, mN , eta, en) + dGammadECont (order, munu, mN , eta, en);
360358 }
361359} // namespace TBeta
0 commit comments