Warning, /include/Herwig/PDT/ThreeBodyAllOnCalculator.tcc is written in an unsupported language. File is not indexed.
0001 // -*- C++ -*-
0002 //
0003 // ThreeBodyAllOnCalculator.tcc is a part of Herwig - A multi-purpose Monte Carlo event generator
0004 // Copyright (C) 2002-2019 The Herwig Collaboration
0005 //
0006 // Herwig is licenced under version 3 of the GPL, see COPYING for details.
0007 // Please respect the MCnet academic guidelines, see GUIDELINES for details.
0008 //
0009 //
0010 // This is the implementation of the non-inlined templated member
0011 // functions of the ThreeBodyAllOnCalculator class.
0012 //
0013 using namespace Herwig;
0014
0015 // shift the variables for the outer integrand and give limits for the inner one
0016 template <class T>
0017 void ThreeBodyAllOnCalculator<T>::outerVariables(double x, Energy2 & low,
0018 Energy2 & upp) const {
0019 // first convert the value of x into the value of souter
0020 if(_mapping[_thechannel]==0) {
0021 _souter = _channelmass[_thechannel]*(_channelmass[_thechannel]+
0022 _channelwidth[_thechannel]*tan(x));
0023 }
0024 else if(_mapping[_thechannel]==1) {
0025 _souter = sqr(_channelmass[_thechannel])*(1.+1./x);
0026 }
0027 else {
0028 _souter = UnitRemoval::E2 * pow(x,1./(_channelpower[_thechannel]+1.));
0029 }
0030 // now the limits of the inner integral
0031 Energy ea(ZERO),eb(ZERO);
0032 Energy rs=sqrt(_souter);
0033 Energy2 eam2(ZERO),ebm2(ZERO);
0034 switch(_channeltype[_thechannel]) {
0035 case 1:
0036 ea = 0.5*(_souter-_m2[1]+_m2[2])/rs;
0037 eam2 = sqr(ea)-_m2[2];
0038 eb = 0.5*(_m2[0]-_souter-_m2[3])/rs;
0039 ebm2 = sqr(eb)-_m2[3];
0040 break;
0041 case 2:
0042 ea = 0.5*(_souter-_m2[1]+_m2[3])/rs;
0043 eam2 = sqr(ea)-_m2[3];
0044 eb = 0.5*(_m2[0]-_souter-_m2[2])/rs;
0045 ebm2 = sqr(eb)-_m2[2];
0046 break;
0047 case 3:
0048 ea = 0.5*(_souter-_m2[2]+_m2[3])/rs;
0049 eam2 = sqr(ea)-_m2[3];
0050 eb = 0.5*(_m2[0]-_souter-_m2[1])/rs;
0051 ebm2 = sqr(eb)-_m2[1];
0052 break;
0053 default:
0054 assert(false);
0055 }
0056 Energy eam = sqrt(max(ZERO,eam2));
0057 Energy ebm = sqrt(max(ZERO,ebm2));
0058 Energy2 sum = sqr(ea+eb);
0059 // calculate the limits
0060 low = sum - sqr(eam+ebm);
0061 upp = sum - sqr(eam-ebm);
0062 }
0063
0064 template <class T>
0065 Energy2 ThreeBodyAllOnCalculator<T>::operator ()(Energy2 y) const {
0066 assert(!std::isnan(double(y/MeV2)));
0067 // set up the values of the s variables
0068 Energy2 s12(ZERO),s23(ZERO),s13(ZERO),
0069 m2sum(_m2[0]+_m2[1]+_m2[2]+_m2[3]);
0070 switch(_channeltype[_thechannel]) {
0071 case 1:
0072 s12 = _souter;
0073 s23 = y;
0074 s13 = m2sum-s12-s23;
0075 break;
0076 case 2:
0077 s23 = y;
0078 s13 = _souter;
0079 s12 = m2sum-s23-s13;
0080 break;
0081 case 3:
0082 s23 = _souter;
0083 s13 = y;
0084 s12 = m2sum-s23-s13;
0085 break;
0086 }
0087 // compute the jacobian
0088 // computer the denominator for the jacobian
0089 InvEnergy2 jacdem = ZERO;
0090 Energy2 sjac(ZERO);
0091 Energy2 rm2,rw2;
0092 for(unsigned int ix=0,N=_channeltype.size(); ix<N; ++ix) {
0093 switch(_channeltype[ix]) {
0094 case 1:
0095 sjac = s12;
0096 break;
0097 case 2:
0098 sjac = s13;
0099 break;
0100 case 3:
0101 sjac = s23;
0102 break;
0103 }
0104 assert(!std::isnan(double(sjac/MeV2)));
0105 InvEnergy2 term;
0106
0107 if(_mapping[ix]==0) {
0108 rm2 = sqr(_channelmass[ix]);
0109 rw2 = sqr(_channelwidth[ix]);
0110 Energy4 tmp = sqr(sjac-rm2) + rw2*rm2;
0111 term = _channelweights[ix]*_channelmass[ix]*_channelwidth[ix]/tmp;
0112 }
0113 else if(_mapping[ix]==1) {
0114 term = _channelweights[ix]*sqr(_channelmass[ix]/(sjac-sqr(_channelmass[ix])));
0115 }
0116 else if(_mapping[ix]==2) {
0117 term = UnitRemoval::InvE2 * _channelweights[ix]*(_channelpower[ix]+1.)*
0118 pow(sjac*UnitRemoval::InvE2, _channelpower[ix]);
0119 }
0120 else
0121 assert(false);
0122 jacdem += term;
0123 }
0124 // now computer the matrix element
0125 return _theME.threeBodyMatrixElement(_mode,_m2[0],s12,s13,
0126 s23,_m[1],_m[2],_m[3])/jacdem;
0127 }
0128
0129 // calculate the width for a given mass
0130 template <class T>
0131 Energy ThreeBodyAllOnCalculator<T>::partialWidth(Energy2 q2) const {
0132 Outer outer(this,_relerr);
0133 _m[0] = sqrt(q2);
0134 _m2[0]=q2;
0135 // check the decay is kinematically allowed
0136 if(_m[0]<_m[1]+_m[2]+_m[3]) return ZERO;
0137 // set up for the different channels
0138 unsigned int N = _channeltype.size();
0139 vector<double> rupp(N,0.),rlow(N,0.);
0140 for(unsigned int ix=0; ix<N; ++ix) {
0141 Energy2 upp(ZERO),low(ZERO);
0142 // work out the kinematic limits
0143 switch(_channeltype[ix]) {
0144 case 1:
0145 upp = sqr(_m[0]-_m[3]);
0146 low = sqr(_m[1]+_m[2]);
0147 break;
0148 case 2:
0149 upp = sqr(_m[0]-_m[2]);
0150 low = sqr(_m[1]+_m[3]);
0151 break;
0152 case 3:
0153 upp = sqr(_m[0]-_m[1]);
0154 low = sqr(_m[2]+_m[3]);
0155 break;
0156 default:
0157 assert(false);
0158 }
0159 // transform them
0160 if(_channelmass[ix] > ZERO) {
0161 if(_channelwidth[ix] > 1e-8*MeV) {
0162 rupp[ix] = atan2((upp-_channelmass[ix]*_channelmass[ix]),
0163 _channelmass[ix]*_channelwidth[ix]);
0164 rlow[ix] = atan2((low-_channelmass[ix]*_channelmass[ix]),
0165 _channelmass[ix]*_channelwidth[ix]);
0166 _mapping[ix] = 0;
0167 if(rupp[ix]/rlow[ix]>0.&&_channelwidth[ix]/_channelmass[ix]<1e-6) {
0168 _mapping[ix] = 1;
0169 Energy2 m2=sqr(_channelmass[ix]);
0170 rupp[ix] = m2/(low-m2);
0171 rlow[ix] = m2/(upp-m2);
0172 }
0173 }
0174 else {
0175 _mapping[ix] = 1;
0176 Energy2 m2=sqr(_channelmass[ix]);
0177 rupp[ix] = m2/(low-m2);
0178 rlow[ix] = m2/(upp-m2);
0179 }
0180 }
0181 else {
0182 _mapping[ix] = 2;
0183 rupp[ix] = pow(upp*UnitRemoval::InvE2, _channelpower[ix]+1.);
0184 rlow[ix] = pow(low*UnitRemoval::InvE2, _channelpower[ix]+1.);
0185 }
0186 }
0187 // perform the integrals for all the different channels
0188 Energy4 sum(ZERO);
0189 for(unsigned int ix=0,N=_channeltype.size(); ix<N; ++ix) {
0190 // perform the integral using GSLIntegrator class
0191 _thechannel=ix;
0192 GSLIntegrator intb(1e-35,_relerr,1000);
0193 sum += _channelweights[ix] * intb.value(outer,rlow[ix],rupp[ix]);
0194 }
0195 // final factors
0196 Energy3 fact = pow<3,1>(Constants::twopi * _m[0]);
0197 return sum/fact/32.;
0198 }