using namespace std;
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cmath>
#include "PHadronDecayM1.h"
PHadronDecayM1::PHadronDecayM1() {
};
PHadronDecayM1::PHadronDecayM1(const Char_t *id, const Char_t *de, Int_t key) :
PHadronDecay(id, de, key) {
if (is_channel < 0)
Warning("PHadronDecayM1", "The model (%s) should be bound to CHANNELS only", de);
Int_t tid[11];
tid[0] = 10;
makeStaticData()->GetDecayModeByKey(key, tid);
parent_id = makeStaticData()->GetDecayParentByKey(key);
if (tid[0] != 2)
Warning("PHadronDecayM1", "(%s): Only 2 body decay", de);
if (makeStaticData()->GetParticleTotalWidth(tid[2]) >
makeStaticData()->GetParticleTotalWidth(tid[1])) {
unstable_position = 2;
stable_position = 1;
} else{
unstable_position = 1;
stable_position = 2;
}
unstable_mass = makeStaticData()->GetParticleMass(tid[unstable_position]);
unstable_ml = PData::LMass(tid[unstable_position]);
stable_mass = makeStaticData()->GetParticleMass(tid[stable_position]);
unstable_id = tid[unstable_position];
stable_id = tid[stable_position];
scale = 1.1;
id1 = tid[1];
id2 = tid[2];
parent = NULL;
daughter1 = NULL;
daughter2 = NULL;
model1 = NULL;
model2 = NULL;
didx1 = -1;
didx2 = -1;
didx_unstable = -1;
};
PDistribution *PHadronDecayM1::Clone(const char*) const {
return new PHadronDecayM1((const PHadronDecayM1 &)* this);
};
Bool_t PHadronDecayM1::Init(void) {
parent = GetParticle("parent");
if (!parent) {
Warning("Init", "Parent not found");
return kFALSE;
}
daughter1 = GetParticle(makeStaticData()->GetParticleName(id1));
daughter2 = GetParticle(makeStaticData()->GetParticleName(id2));
return kTRUE;
}
Double_t PHadronDecayM1::EvalPar(const Double_t *x, const Double_t *params) {
if (params) {
draw_option = (int)params[0];
didx_option = (int)params[1];
}
return Eval(x[0]);
}
Double_t PHadronDecayM1::Eval(Double_t x, Double_t, Double_t, Double_t) const {
Double_t res;
Double_t mass[3];
Int_t didx[3];
didx[0] = didx[1] = didx[2] = -1;
PChannelModel *pmodel = makeDynamicData()->GetParticleModel(parent_id);
mass[unstable_position] = x;
mass[stable_position] = stable_mass;
didx[unstable_position] = didx_option;
if (draw_option == 0) {
if (!pmodel)
return ((PChannelModel*)this)->GetWeight(mass, didx);
Double_t w = 0;
Double_t dm = PData::UMass(parent_id)-PData::LMass(parent_id);
for (mass[0]=PData::LMass(parent_id); mass[0]<(PData::LMass(parent_id)+dm);
mass[0]+=dm/100.) {
w += ((PChannelModel*)this)->GetWeight(mass,didx)*pmodel->GetWeight(mass,(Int_t*)&is_channel);
}
return w;
} else if (draw_option == 1) {
((PChannelModel*)this)->GetWidth(x,&res);
return res;
} else if (draw_option == 2) {
((PChannelModel*)this)->GetBR(x,&res);
return res;
}
return 0;
}
int PHadronDecayM1::GetDepth(int i) {
Int_t a1=0, a2=0;
model1 = makeDynamicData()->GetParticleModel(id1);
model2 = makeDynamicData()->GetParticleModel(id2);
if (model1) a1 = model1->GetDepth(i);
if (model2) a2 = model2->GetDepth(i);
makeStaticData()->SetDecayEmin(is_channel,
TMath::Min(makeStaticData()->GetParticleEmin(id1),
makeStaticData()->GetParticleEmin(id2)));
return TMath::Max(a1+1, a2+1);
}
Bool_t PHadronDecayM1::Prepare(void) {
didx1 = daughter1->GetDecayModeIndex(1);
didx2 = daughter2->GetDecayModeIndex(1);
if (unstable_position == 1)
didx_unstable = didx1;
else
didx_unstable = didx2;
return kTRUE;
}
void PHadronDecayM1::SubPrint(Int_t) const {
if (model1) {cout << " "; cout << model1->GetDescription();}
if (model2) {cout << " "; cout << model2->GetDescription();}
}
Double_t PHadronDecayM1::GetWeight(void) {
Double_t mass[3];
mass[0] = parent->M();
mass[1] = daughter1->M();
mass[2] = daughter2->M();
return GetWeight(mass);
}
Double_t PHadronDecayM1::GetWeight(Double_t *mass, Int_t *didx) {
int didx_local1 = didx1,
didx_local2 = didx2;
if (didx) {
didx_local1 = didx[1];
didx_local2 = didx[2];
}
if (unstable_position == 1)
return BWWeight(unstable_id, mass[0], mass[1], mass[2], didx_local1, 0, didx_local2);
return BWWeight(unstable_id, mass[0], mass[2], mass[1], didx_local2, 0, didx_local1);
}
Bool_t PHadronDecayM1::SampleMass(void) {
Double_t mass[3];
mass[0] = parent->M();
if (!SampleMass(mass)) return kFALSE;
daughter1->SetM(mass[1]);
daughter2->SetM(mass[2]);
return kTRUE;
};
Bool_t PHadronDecayM1::SampleMass(Double_t *mass, Int_t *didx) {
if (didx)
didx_unstable = didx[unstable_position];
Double_t ecm = mass[0];
if (sampleM1(ecm)) {
mass[unstable_position] = unstable_dynamic_mass;
mass[stable_position] = stable_mass;
} else {
Warning("SampleMass", "failed in [%s], ecm=%f", GetIdentifier(), ecm);
return kFALSE;
}
if (ecm < (stable_mass+unstable_dynamic_mass)) {
Warning("SampleMass", "Violation of energy");
return kFALSE;
}
return kTRUE;
};
Bool_t PHadronDecayM1::GetWidth(Double_t mass, Double_t *width, Int_t) {
if (makeStaticData()->GetPWidx(is_channel) == -1)
return 0.;
if (!makeStaticData()->GetPWidx(is_channel)) {
Info("GetWidth", "Called for %s", makeStaticData()->GetDecayName(is_channel));
makeDynamicData()->GetParticleDepth(parent_id);
mmin = makeStaticData()->GetDecayEmin(is_channel);
Double_t w0 = makeStaticData()->GetDecayBR(is_channel);
mmax = PData::UMass(parent_id);
Double_t dm = (mmax-mmin)/(maxmesh-3.);
double mass_threshold, mass_ceiling;
mass_threshold = PData::LMass(unstable_id);
mass_ceiling = mmax-PData::LMass(stable_id);
mesh = new PMesh(maxmesh-2, "mesh");
for (int i=0; i<maxmesh-2; ++i) {
Double_t mm = mmin+i*dm;
Double_t temp0 = 0.;
Double_t temp0_norm = 0.;
Double_t bw_max = 0;
for (int mc=0; mc<mc_max; mc++) {
Double_t running_unstable_mass = mass_threshold+((Double_t(mc)/Double_t(mc_max))
*(mass_ceiling-mass_threshold));
Double_t w = makeDynamicData()->GetParticleTotalWeight(running_unstable_mass ,unstable_id);
if (w > bw_max)
bw_max = w;
}
if (bw_max > 0)
for (int mc=0; mc<mc_max; mc++) {
Double_t temp1 = 0.;
Double_t running_unstable_mass = mass_threshold+((Double_t(mc)/Double_t(mc_max))
*(mass_ceiling-mass_threshold));
if (mm > (running_unstable_mass+stable_mass)) {
temp1 = PKinematics::pcms(mm, running_unstable_mass, stable_mass);
Double_t w = makeDynamicData()->GetParticleTotalWeight(running_unstable_mass, unstable_id);
temp1 *= w;
if (w > (0.01*bw_max)) {
temp0_norm += temp1;
temp1 *= HadronWidth(mm,running_unstable_mass, stable_mass);
temp0 += temp1;
}
}
}
if (temp0_norm > 0)
temp0 /= temp0_norm;
temp0 *= w0;
mesh->SetNode(i, temp0);
}
mesh->SetMin(mmin);
mesh->SetMax(mmax);
makeStaticData()->SetPWidx(is_channel, 1);
}
if (mesh) {
*width = mesh->GetLinearIP(mass);
return kTRUE;
}
return kFALSE;
}
bool PHadronDecayM1:: sampleM1(const double &ecm) {
double unstable_mh = ecm-stable_mass,
ma, peak, a1, a2, area, b=-1, max1;
unstable_dynamic_mass = 0.;
if (unstable_mh <= unstable_ml) {
Warning("sampleM1", "not enough energy");
return kFALSE;
}
abort = kFALSE;
repeat:
if (unstable_mh > unstable_mass) {
peak = BWWeight(unstable_id, scale*ecm, unstable_mass, stable_mass, didx_unstable);
ma = 0.5*(unstable_mass+unstable_mh);
a2 = 0.5*peak*(unstable_mh-ma);
b = peak/(unstable_mh - ma);
} else {
peak = scale*maxBWWeight(unstable_id,ecm,unstable_ml,unstable_mh,max1,stable_mass, didx_unstable);
ma = unstable_mh;
a2 = 0.;
}
if (peak == 0.) {
unstable_dynamic_mass = 0.;
return kTRUE;
}
a1 = peak*(ma-unstable_ml);
area = a1 + a2;
double a, f, y, da;
do {
a = area * PUtils::sampleFlat();
if (a <= a1) {
f = peak;
unstable_dynamic_mass = a/f + unstable_ml;
} else {
da = 2.*(area-a);
f = sqrt(da*b);
unstable_dynamic_mass = unstable_mh - da/f;
}
y = BWWeight(unstable_id, ecm, unstable_dynamic_mass, stable_mass, didx_unstable);
} while (f*PUtils::sampleFlat() > y);
if (f < y) {
scale = scale*y/f + 0.1;
goto repeat;
}
return kTRUE;
}
double PHadronDecayM1::BWWeight(const int &i1, const double &m,
const double &m1, const double &m2, int didx_local1,
int i2, int didx_local2) {
double pCms = PKinematics::pcms(m, m1, m2);
PChannelModel *i1_model = makeDynamicData()->GetParticleModel(i1);
if (!i1_model) {
Warning("BWWeight", "No target model i1");
return 0;
}
double bw = pCms*i1_model->GetWeight((Double_t*)&m1,&didx_local1);
if (i2) {
PChannelModel *i2_model = makeDynamicData()->GetParticleModel(i2);
if (!i2_model) {
Warning("BWWeight", "No target model i2");
return bw;
}
bw *= i2_model->GetWeight((Double_t*)&m2,&didx_local2);
}
return bw;
}
double PHadronDecayM1::maxBWWeight(const int &i1, const double &m, const double &lower,
const double &upper, double &max1, const double &m2, int didx_local1,
int i2, int didx_local2) {
#define SHFT2(a,b,c) (a)=(b);(b)=(c);
#define SHFT3(a,b,c,d) (a)=(b);(b)=(c);(c)=(d);
const double R = 0.61803399;
const double C = 1.-R;
const double tol = 1.e-3;
double ax, bx, cx;
double f1=0, f2=0, x0, x1, x2, x3;
ax = lower;
bx = C*lower+R*upper;
cx = upper;
x0 = ax;
x3 = cx;
if ( fabs(cx-bx)>fabs(bx-ax) ) {
x1 = bx;
x2 = bx+C*(cx-bx);
} else {
x2 = bx;
x1 = bx-C*(bx-ax);
}
Int_t counter = 0;
while ((f1 == 0) && (f2 == 0) && (counter < 10)) {
f1 = BWWeight(i1, m, x1, m2, didx_local1, i2);
f2 = BWWeight(i1, m, x2, m2, didx_local1, i2);
if ((f1 == 0) && (f2 == 0))
x2 += (x3-x2)*0.1;
counter++;
}
if (counter == 10) {
abort = kTRUE;
return 0;
}
while ((fabs(x3-x0)>tol*(fabs(x1)+fabs(x2))) && (counter < 100)) {
if (f2 > f1) {
SHFT3(x0, x1, x2, R*x1+C*x3);
SHFT2(f1, f2, BWWeight(i1, m, x2, m2, didx_local1, i2, didx_local2));
} else {
SHFT3(x3, x2, x1, R*x2+C*x0);
SHFT2(f2, f1, BWWeight(i1, m, x1, m2, didx_local1, i2, didx_local2));
}
}
if (counter == 100) {
abort = kTRUE;
return 0;
}
if (f1 > f2) {
max1 = x1;
return f1;
} else {
max1 = x2;
return f2;
}
}
ClassImp(PHadronDecayM1)