////////////////////////////////////////////////////////

//  Fireball Class implementation file

//

//  The Fireball class sets up multi-nucleon quasi particles

//  that may subsequently decay thermally via standard decay modes.

//  A fireball with the desired properties, including the decay

//  channels, must be available in PData before invoking this

//  constructor.

//

//                    Author:  Romain Holzmann

//                    Written: 28.04.00

//                    Revised: 21.06.00 MK

//                    Revised: 26.06.2001 A.Toia

//                    Revised: 05.09.2005 R.H.

//                    Revised: 28.03.2006 R.H.  (use TF2 for E,M sampling)

//                    Revised: 02.02.2007 R.H.  (add E p**n exp(-E/T) behavior)

//                    Revised: 16.02.2007 R.H.  (add angle-dependent temperature)

//                    Revised: 21.02.2007 R.H.  (add sampling from histogram)

//                    Revised: 10.06.2014 R.H.  (fixed bug in v1,v2 sampling)

//                    Revised: 27.05.2015 R.H.  (adapted v1,v2 behavior for spectator sources)

//

// Ref 1: Gosset et al. PRC 16 (1977) 629

//        (number of projectile participant nucleons for

//         given impact parameter b (in fm))

////////////////////////////////////////////////////////



#include <TError.h>

#include "PUtils.h"
#include "PThermal.h"
#include "PFireball.h"
#include "PDistributionManager.h"

ClassImp(PFireball)

PFireball::PFireball(const char *particle, float AGeV, float t1, float t2, float f,
		     float b, float a2, float a4, float w1, float w2, int sp) :
PParticle(particle) {
    //

    // Thermal source with temperature(s) T1 (T2), frac*f(T1) + (1-frac)*f(T2),

    // optional blast, optional polar anisotropies (A2,A4), optional flow (v1,v2).

    //

    prodId = makeStaticData()->GetParticleID(particle);
    makeDistributionManager()->LinkDB(); //Fill data base with life


    //get primary model

    model = makeDynamicData()->GetParticleModel(prodId);

    SetID(500 + prodId);
    quasistable = 1;

    PThermal::thermal_unstable_width = makeStaticData()->GetBatchValue("_system_thermal_unstable_width");
    
    //  quasistable = (PData::UMass(prodId)-PData::LMass(prodId) < 0.01); // (quasi)stable particle

    if (makeStaticData()->GetParticleTotalWidth(prodId) > *PThermal::thermal_unstable_width) {
	cout << "unstable" << endl;
	quasistable = 0;
    }
    // This must be consistent with the definition in PThermal


    T1 = t1 > 0. ? t1 : 0.05;
    T2 = t2 >= 0. ? t2 : 0.;
    if (f <= 0.) 
	frac = 1.;
    else 
	frac = f;
    if (b < 0.) {  // neg. blast flags power of E p**n term

	if (T2 > T1) 
	    T2 = T1;  // T1 = T(0 deg) and T2 = T(90 deg) with T1>=T2

	power1 = frac;
	power2 = -b;
	A2 = a2;
	A4 = a4;
	blast = 0.;
	frac = 1.;
    } else {
	if (f > 1.) 
	    frac = 1.;
	power1 = power2 = 0.;
	A2 = a2;
	A4 = a4;
	blast = b < 1.0 ? b : 0.0;
    }
    v1 = w1;
    v2 = w2;
    Ap = 40.;
    At = 40.;
    prob = 0.1;
    flag = 0;
    meanN = 0.;
    spect = sp;

    fA     = NULL;
    fE     = NULL;
    fE_1d  = NULL;
    pfE    = NULL;
    afE    = NULL;
    fE1_1d = NULL;
    fE1    = NULL;
    fE2_1d = NULL;
    fE2    = NULL;
    fE3    = NULL;
    fMt    = NULL;
    fHisto = NULL;
    trueThermal = kTRUE;
    sample_option = 0; //no rotation by default

    mesh_option   = 0; //no mesh by default

    updateFunctions();
    part   = NULL;
    mt_fac = 0.;
    sig    = 0.;
    rapidity_function=NULL;
    didx_old = -1;
    setToMidrapidity(AGeV);   // move source to midrapidity for Ebeam is AGeV

}

void PFireball::SetEpsilon(Double_t e) {
    if (fE)  fE->SetEpsilon(e);
    if (fE1) fE1->SetEpsilon(e);
    if (fE2) fE2->SetEpsilon(e);
    if (fE3) fE3->SetEpsilon(e);
}

void PFireball::SetNpx(Int_t my_npx) {
    npx =       my_npx;
    if (fE)     fE->SetNpx(npx);
    if (fE1)    fE1->SetNpx(npx);
    if (fE2)    fE2->SetNpx(npx);
    if (fE3)    fE3->SetNpx(npx);
    if (fE_1d)  fE->SetNpx(npx);
    if (fE1_1d) fE1->SetNpx(npx);
    if (fE2_1d) fE2->SetNpx(npx);
}

void PFireball::SetNpy(Int_t my_npy) {
    npy =    my_npy;
    if (fE)  fE->SetNpy(npy);
    if (fE1) fE1->SetNpy(npy);
    if (fE2) fE2->SetNpy(npy);
    if (fE3) fE3->SetNpy(npy);
}

void PFireball::sampleECM(Double_t &E, Double_t &M, int didx) {
    if (fE) {
	if (didx != didx_old) {
	    didx_old = didx; //prevent random initialization each time

	    if (didx < 0) 
		fE->SetParameter(5,-1.1);
	    else 
		fE->SetParameter(5,(double) didx);
	}
	if (!mesh_option) {
	    fE->MakeIntegral();
	    fE->GetRandom2(E, M);
	} else {
	    if (!afE) {
		//add an adaptive mesh

		char *modname = new char[120];
		char *desname = new char[120];
		const char *prodname = makeStaticData()->GetParticleName(prodId);
		sprintf(modname, "%s_fireball@%s/thermal", prodname, prodname);
		sprintf(desname, "Thermal model for %s", prodname);
		Info("sampleECM", "Creating mesh for '%s'. This can take some time....", desname);
		pfE = new PFunction(modname, desname, -1);
		pfE->SetFunction(fE);
		afE = new PAdaptiveMeshN(0x3, 2, pfE, 0.022);
		afE->SetRange(0, fE->GetXmin(), fE->GetXmax());
		afE->SetRange(1, fE->GetYmin(), fE->GetYmax());
		afE->SetThreshold(1.5, 0.0001);
		afE->SetMCPoints(100);
		afE->Divide(5, 2);
		//afE->Divide(5, 0);

		Info("sampleECM", "...done");
	    }
	    afE->GetRandom();
	    E=afE->GetArrayValue(0);
	    M=afE->GetArrayValue(1);
	}
	if (sample_option) {
	    double E_tmp = (E*0.5+2*M)*0.5;
	    double M_tmp = (2*M-E*0.5)*0.5;
	    E = E_tmp;
	    M = M_tmp;
	}
    } else if (fE_1d) {
	E = fE_1d->GetRandom();
    }
}

void PFireball::updateFunctions(int id) {

    if (id) prodId = id;
    SetID(500 + prodId);
    Double_t M    = makeStaticData()->GetParticleMass(prodId);
    Double_t Mmin = PData::LMass(prodId);
    Double_t Mmax = PData::UMass(prodId);
    Double_t Emin = Mmin;
    Double_t Emax = Mmax + 10.*(T1+T2)/(1.-blast);
    npx = 200;
    npy = 1000;
    
#if 0

    if (quasistable) {
	Mmin = 0.999*makeStaticData()->GetParticleMass(prodId);  // mass axis is dummy

	Mmax = 1.001*makeStaticData()->GetParticleMass(prodId);
	Emin = M;
	Emax = Mmax + 20.*(T1+T2)/(1.-blast);
	npx=500;
	npy = 5;  // TF2 needs at least 5 points/axis

    }
#endif


    if (quasistable) {

	if (!fE_1d) {
	    fE_1d = new TF1("dNdE", PThermal::dNdE, Emin, Emax, 7); // energy formula

	    gROOT->GetListOfFunctions()->Remove(fE_1d);
	    fE_1d->SetNpx(npx);
	} else 
	    fE_1d->SetRange(Emin, Mmin);
	fE_1d->SetParameters(makeStaticData()->GetParticleMass(prodId), T1, T2, frac, blast); 
	fE_1d->Eval(0);
	
	if (!fE1_1d) {
	    fE1_1d = new TF1("dNdE1", PThermal::dNdE1, Emin, Emax, 6); // energy formula

	    gROOT->GetListOfFunctions()->Remove(fE1_1d);
	    fE1_1d->SetNpx(npx);
	} else 
	    fE1_1d->SetRange(Emin, Mmin);
	fE1_1d->SetParameters(makeStaticData()->GetParticleMass(prodId), T1, T2, frac, blast);
    
	if (!fE2_1d) {
	    fE2_1d = new PF2("dNdE2", PThermal::dNdE2, Emin, Emax, 6); // energy formula

	    gROOT->GetListOfFunctions()->Remove(fE2_1d);
	    fE2_1d->SetNpx(npx);
	} else 
	    fE2_1d->SetRange(Emin, Mmin);
	fE2_1d->SetParameters(makeStaticData()->GetParticleMass(prodId), T1, T2, frac, blast);	

    } else {

	if (!fE) {
	    fE = new PF2("d2NdEdM", PThermal::d2NdEdM, Emin, Emax, Mmin, Mmax, 7); // energy formula

	    gROOT->GetListOfFunctions()->Remove(fE);
	    fE->SetNpx(npx);
	    fE->SetNpy(npy);	
	} else 
	    fE->SetRange(Emin, Mmin, Emax, Mmax);
	fE->SetParameters(T1, T2, frac, blast, float(prodId), -1.1, sample_option); //option=0: normal operation 

	fE->Eval(0,0);
    
	if (!fE1) {
	    fE1 = new PF2("d2NdEdM1", PThermal::d2NdEdM1, Emin, Emax, Mmin, Mmax, 6); // energy formula

	    gROOT->GetListOfFunctions()->Remove(fE1);
	    fE1->SetNpx(npx);
	    fE1->SetNpy(npy);
	} else 
	    fE1->SetRange(Emin, Mmin, Emax, Mmax);
	fE1->SetParameters(T1, T2, frac, blast, float(prodId), -1.1);
    
	if (!fE2) {
	    fE2 = new PF2("d2NdEdM2", PThermal::d2NdEdM2, Emin, Emax, Mmin, Mmax, 6); // energy formula

	    gROOT->GetListOfFunctions()->Remove(fE2);
	    fE2->SetNpx(npx);
	    fE2->SetNpy(npy);
	} else 
	    fE2->SetRange(Emin, Mmin, Emax, Mmax);
	fE2->SetParameters(T1, T2, frac, blast, float(prodId), -1.1);
    }
    
    if (!fE3) {
	fE3 = new PF2("d2NdEdTheta", PThermal::d2NdEdTheta, Emin, Emax, 0., TMath::Pi(), 7);
	gROOT->GetListOfFunctions()->Remove(fE3);
	fE3->SetNpx(npx);
	fE3->SetNpy(180);
    } else 
	fE3->SetRange(Emin, 0., Emax,TMath::Pi());
    fE3->SetParameters(T1,T2, power1, power2, makeStaticData()->GetParticleMass(prodId), A2, A4);
    
    if (!fA) {
	fA = new TF1("dNdTheta", PThermal::dNdTheta, 0., TMath::Pi(), 2);  // polar formula

	gROOT->GetListOfFunctions()->Remove(fA);
	fA->SetNpx(180);
    }
    fA->SetParameters(A2, A4);
    
    if (!fMt) {
	fMt = new TF1("dNdMt", PThermal::dNdMt, M, Emax, 4);               // mt formula

	gROOT->GetListOfFunctions()->Remove(fMt);
	fMt->SetNpx(500);
    } else 
	fMt->SetRange(M, Emax);
    fMt->SetParameters(M, T1, T2, frac);
}

void PFireball::setToMidrapidity(float agev) {  // boost thermal source to

    // the correct rapidity with agev the energy/nucleon of the projectile (in GeV/u):

    // 0 for target-like spectators, beam rapidity for projectile-like spectators,

    // midrapidity for participants

    if (agev <= 0.0) return;
    if (spect == 0) {   
	double bx = 0.;
	double by = 0.;
	double bz = sqrt(agev/(agev+2.*0.9315));
	Boost(bx, by, bz);
        y0 = 0.5*log((1.+bz)/(1.-bz));  // midrapidity

    } else if (spect == 1) {
	return;
    } else if (spect == 2) {
	double bx = 0.; 
	double by = 0.;
	double bz = sqrt(agev*(agev+2*0.9315))/(agev+0.9315); 
	Boost(bx, by, bz);
    }
}

void PFireball::Print(const Option_t *delme) const {
    if (fHisto != NULL) {
	printf("%s d2N/dpdTheta sampled from histogram: %s\n", delme, fHisto->GetTitle());
    } else if(power1 == 0) {
	printf("%s  Thermal %s with:\n%s  T1=%5.3f  frac=%5.3f  T2=%5.3f  blast=%5.3f \n", delme,
	       makeStaticData()->GetParticleName(prodId), delme, T1, frac, T2, blast);
    } else {
	printf("%s  Thermal %s with:\n%s  T1=%5.3f  pow1=%3.1f  T2=%5.3f  pow2=%3.1f \n", delme,
	       makeStaticData()->GetParticleName(prodId), delme, T1, power1, T2, power2);
    }
    printf("%s  A2=%5.2f  A4=%5.2f  v1=%5.2f  v2=%5.2f\n", delme, A2, A4, v1, v2);
    if (flag) 
	printf("%s   Aproj=%4.0f  Atarg=%4.0f  Pprod=%8.2e\n", delme, Ap, At, prob); 
    if (spect == 0) {
	printf("%s  participant\n", delme);
	printf("%s  rapidity=%f;  beta=%f;  weight=%f;  mult=%f\n", delme, Rapidity(), Beta(), W(), mult);
    } else if (spect == 1) {
	printf("%s  target-like spectator\n", delme);
	printf("%s  no Boost; rapidity=%f;  weight=%f;  mult=%f\n", delme, Rapidity(), W(), mult);
    } else if (spect == 2) {
	printf("%s  projectile-like spectator\n", delme);
	printf("%s  rapidity=%f;  beta=%f;  weight=%f;  mult=%f\n", delme, Rapidity(), Beta(), W(), mult);
    }

    if (flag) {
	printAverages();   // b sampling is on

    } else {
	printf("%s  meanN=%f\n", delme, meanN);
    }
}

void PFireball::printAverages() const {
    Float_t b;
    Float_t avb = 0.;
    Float_t Apart;
    Float_t avApart = 0.;
    Int_t   nSample = 10000;
    for (Int_t i=0; i<nSample; i++) {
	b = sampleB();
	avb += b;
	Apart = NparSmeared(Ap,At,b) + NparSmeared(At,Ap,b);    // av. nb. of participants

	avApart += Apart;
    }
    avb     /= (Float_t)nSample;
    avApart /= (Float_t)nSample;
    Float_t avM = avApart*prob;
  
    printf(" impact parameter range: %5.2f - %5.2f fm\n", bmin, bmax);
    printf(" average b=%5.2f  average Apart=%5.1f  average M=%8.2e\n\n", avb, avApart, avM);
}

Double_t PFireball::AvApart(Double_t, Double_t, Double_t, Double_t) {
    Int_t nSample = 10000;
    Float_t b;
    Float_t Apart;
    Float_t avApart = 0.;
    for (Int_t i=0; i<nSample; i++) {
	b = sampleB();
	Apart = Npar(Ap,At,b) + Npar(At,Ap,b);    // av. nb. of participants

	avApart += Apart;
    }
    return avApart/(Float_t)nSample;
}

void PFireball::samplePartCM(double &px, double &py, double &pz, double &E, int didx) {
    // sample particle 4-momentum (px,py,pz,E)

    Double_t E1, E2;
    Double_t M, M1, M2;
    Double_t p;
    Double_t theta;
    Double_t phi, 
	phiPlane = *(makeStaticData()->GetBatchValue("_event_plane"));
    Int_t count = 0;

    if (sig>0. || rapidity_function) {     // do mt and y sampling separately

	Double_t mt = sampleMt();                 // dN/dMt = mt^2 * K1(mt/T)

	Double_t y = 0.; 
	if (sig > 0.) 
	    y = PUtils::sampleGaus(0., sig);  // dN/dy = exp(-0.5*(y/sig)^2)

	else
	    y = rapidity_function->GetRandom();
	if (model) { 
	    do {
		model->SampleMass(&M);
		count++;
	    } while (M>mt && count<100);

	    if (count >= 100) 
		Warning("samplePartCM", "Model mass sampling failed (count>=100)");

	} else { //no model -> stable mass

	    M = makeStaticData()->GetParticleMass(prodId);
	}
	Double_t pt = sqrt(mt*mt-M*M);
	pz    = mt*sinh(y);   // in c.m. system

	E     = mt*cosh(y);
	theta = atan(pt/pz);
	//phi = 2.*TMath::Pi()*PUtils::sampleFlat();  // --> Flat sampling, no v1,v2

	Double_t cost = cos(theta);  // in c.m.

	Double_t sint = sin(theta);
        if (spect!=0) 
	    cost = sint = 1;  // do not modulate flow for spectator sources

	Double_t val, valmax;
	Int_t i = 0;
	do {           // sample phi now

	    i++;
	    phi = 2.*TMath::Pi()*PUtils::sampleFlat(); 
	    val = 1. + 2.*(v1*cos(phi)*cost + v2*cos(2.*phi)*sint);
	    valmax = 1. + 2.*(TMath::Abs(v1*cost) + TMath::Abs(v2*sint));
	} while (valmax*PUtils::sampleFlat()>val && i<100);
     
	px = pt*cos(phi+phiPlane);
	py = pt*sin(phi+phiPlane);

	return;
    }


    Int_t saveLevel = gErrorIgnoreLevel;
    //if (gErrorIgnoreLevel<=1000) gErrorIgnoreLevel = 1001; // suppress TF2 warnings


    if(fHisto != NULL) {  // if histo defined use it

	M = makeStaticData()->GetParticleMass(prodId);
	fHisto->GetRandom2(p,theta);  // sample thermal distribution from 2-d histogram

	E = sqrt(p*p+M*M);
	theta = 0.0174532925*theta;
    } else if (trueThermal) {
	theta = sampleThetaCM();
	sampleECM(E, M, didx); // sample true thermal distribution

	if (quasistable) 
	    M = makeStaticData()->GetParticleMass(prodId);   // reset to exact pole mass

	p = sqrt(TMath::Abs(E*E-M*M));
    } else if (power1==0) {
	theta = sampleThetaCM();
	sampleECM1(E1, M1, didx);  // sample thermal distribution (E*sqrt(p))

	sampleECM2(E2, M2, didx);  // sample thermal distribution (with E*p**3)

	Double_t x = 2.*theta/TMath::Pi();
	if (x>1.) x = 2. - x;
	if (x<0.) x = 0.;
	if (x>1.) x = 1.;
	//  x  = sqrt(x);

	if (x>PUtils::sampleFlat()) {
	    E = E1; 
	    M = M1;
	} else { // cook up an angle dependency of E

	    E = E2;
	    M = M2;
	}   
	if (quasistable)
	    M = makeStaticData()->GetParticleMass(prodId);   // reset to exact pole mass

	p = sqrt(TMath::Abs(E*E-M*M));
    } else {
	M = makeStaticData()->GetParticleMass(prodId);
	sampleECM3(E, theta);  // sample thermal distribution E p**n with T=T(th) and n=n(th)

	p = sqrt(TMath::Abs(E*E-M*M));
    }

    gErrorIgnoreLevel = saveLevel;

    Double_t cost  = cos(theta);
    Double_t sint  = sin(theta);
    Double_t costs = cost;
    Double_t sints = sint;
    if (spect!=0) 
	cost = sint = 1;  // do not modulate flow for spectator sources


    //    cost = sint = 1;   // for testing purposes


    Double_t val, valmax;
    Int_t i = 0;
    do {           // sample phi now

	i++;
	phi = 2.*TMath::Pi()*PUtils::sampleFlat(); 
	val = 1. + 2.*(v1*cos(phi)*cost + v2*cos(2.*phi)*sint);
	valmax = 1. + 2.*(TMath::Abs(v1*cost) + TMath::Abs(v2*sint));
    } while (valmax*PUtils::sampleFlat()>val && i<100);

    px = p*sints*cos(phi+phiPlane);
    py = p*sints*sin(phi+phiPlane);
    pz = p*costs;
}

float PFireball::sampleB() const {
    if(!flag) 
	return 0.;
    if (bmin > 0.1) 
	return sqrt((bmax*bmax-bmin*bmin)*PUtils::sampleFlat() + bmin*bmin); // random b

    float b, test;
    do {
	b    = (bmax+2.)*sqrt(PUtils::sampleFlat());
	test = 1./(1.+TMath::Exp((b-bmax)/0.5));        // nuclear density distribution

    } while (test < PUtils::sampleFlat());
    return b;
}

int PFireball::sampleNProd() {  // sample Poisson multiplicity

    //    return int(meanN);   // don't sample (for test purposes)

    return PUtils::samplePoisson(meanN);
}

int PFireball::sampleNProd(float b) {
    if(!flag || b > 1.14*(pow((double)Ap,(double)0.3333)+pow((double)At,(double)0.3333))) 
	return 0;
    float Apart = 0.;
    if (spect == 0) 
	Apart = NparSmeared(Ap,At,b) + NparSmeared(At,Ap,b); // av. nb. of participants

    else if (spect == 1)  
	Apart = At - Npar(At,Ap,b); // av. nb. of target-like spectators

    else if (spect == 2)  
	Apart = Ap - Npar(Ap,At,b); // av. nb. of projectile-like spectators


    float Nprod = prob*Apart;                       // av. nb. of produced part.

  
    if(prob < 0.25) 
	nProd = PUtils::samplePoisson(Nprod);
    // Poisson distributed nb. of product particles

    else 
	nProd = PUtils::sampleBinomial((Int_t)(Apart+0.5),prob);
    // use binomial to make sure that nProd <= Apart

    return nProd;
}

float PFireball::Npar(float ap, float at, float b) {
    //    number of projectile participant nucleons

    //    for given impact parameter b (in fm) (Ref 1)


    float Rp = 1.14*pow((double)ap,(double)0.3333); // in fm

    float Rt = 1.14*pow((double)at,(double)0.3333);
    if(b > Rp+Rt) return 0;
    float beta = b/(Rp+Rt);
    float nu = Rp/(Rp+Rt);
    float mu = Rt/Rp;

    float F = 0.;
    if (nu > 0.5) {                  // Ap > At

	if (nu > 0.5*(1.0+beta)) {
	    F = (1.0-pow(1.-mu*mu,1.5)) * sqrt(1.-(beta/nu)*(beta/nu));
	} else {
	    F = 0.75*sqrt(1.-nu) * (1.-beta)/nu * (1.-beta)/nu
		- 0.125*( 3.*sqrt(1.-nu)/mu
			  - (1.-pow(1.-mu*mu,1.5)) * sqrt(1.-(1.-mu)*(1.-mu))/(mu*mu*mu) )
                *pow((1.-beta)/nu,3.);
	}
    } else {                        // Ap < At

	if(nu > 0.5*(1.-beta)) {
	    F = 0.75*sqrt(1.-nu) * (1.-beta)/nu * (1.-beta)/nu
		-0.125*(3.*sqrt(1.-nu)-1.) * pow((1.-beta)/nu,3.);
	} else {
	    F = 1.;
	}
    }
    return F*ap;
}

float PFireball::NparSmeared(float ap, float at, float b)  const {
    //    number of projectile participant nucleons

    //    for given impact parameter b (in fm) with smeared nuclear surface


    float Rp = 1.14*pow((double)ap,(double)0.3333)+1.; // + 1 fm tail

    float Rt = 1.14*pow((double)at,(double)0.3333)+1.; // + 1 fm tail

    if(b > Rp+Rt) return 0;
    float beta = b/(Rp+Rt);
    float nu = Rp/(Rp+Rt);
    float mu = Rt/Rp;

    float F = 0.;
    if (nu > 0.5) {                  // Ap > At

	if (nu > 0.5*(1.0+beta)) {
	    F = (1.0-pow(1.-mu*mu,1.5)) * sqrt(1.-(beta/nu)*(beta/nu));
	} else {
	    F = 0.75*sqrt(1.-nu) * (1.-beta)/nu * (1.-beta)/nu
		- 0.125*( 3.*sqrt(1.-nu)/mu
			  - (1.-pow(1.-mu*mu,1.5)) * sqrt(1.-(1.-mu)*(1.-mu))/(mu*mu*mu) )
                *pow((1.-beta)/nu,3.);
	}
    } else {                        // Ap < At

	if(nu > 0.5*(1.-beta)) {
	    F = 0.75*sqrt(1.-nu) * (1.-beta)/nu * (1.-beta)/nu
		-0.125*(3.*sqrt(1.-nu)-1.) * pow((1.-beta)/nu,3.);
	} else {
	    F = 1.;
	}
    }
    return F*ap;
}

PChannel *PFireball::makeChannel(Int_t nMax, Float_t nMean) {
    //

    // set up a reaction channel for this thermal source

    //

    if (nMean > 0.) 
	setMeanN(nMean);

    part    = new PParticle*[nMax+1];
    part[0] = this;
    for (Int_t i=1; i<=nMax; i++) {
	part[i] = new PParticle((char*)makeStaticData()->GetParticleName(prodId)); 
    }
    PChannel* chan = new PChannel(part, nMax, 1);
    return chan;
}

Float_t PFireball::mtIntegral(Double_t m, Float_t T) { // integral of thermal

                                                       // mt distribution

    if (m<=0. || T<=0.) 
	return 0.;
    return T*exp(-m/T)*sqrt(m)*(1.5*T+m)
	+ 1.329340*pow((double)T,(double)2.5)*(1.-TMath::Erf(sqrt(m/T)));
}













 PFireball.cc:1
 PFireball.cc:2
 PFireball.cc:3
 PFireball.cc:4
 PFireball.cc:5
 PFireball.cc:6
 PFireball.cc:7
 PFireball.cc:8
 PFireball.cc:9
 PFireball.cc:10
 PFireball.cc:11
 PFireball.cc:12
 PFireball.cc:13
 PFireball.cc:14
 PFireball.cc:15
 PFireball.cc:16
 PFireball.cc:17
 PFireball.cc:18
 PFireball.cc:19
 PFireball.cc:20
 PFireball.cc:21
 PFireball.cc:22
 PFireball.cc:23
 PFireball.cc:24
 PFireball.cc:25
 PFireball.cc:26
 PFireball.cc:27
 PFireball.cc:28
 PFireball.cc:29
 PFireball.cc:30
 PFireball.cc:31
 PFireball.cc:32
 PFireball.cc:33
 PFireball.cc:34
 PFireball.cc:35
 PFireball.cc:36
 PFireball.cc:37
 PFireball.cc:38
 PFireball.cc:39
 PFireball.cc:40
 PFireball.cc:41
 PFireball.cc:42
 PFireball.cc:43
 PFireball.cc:44
 PFireball.cc:45
 PFireball.cc:46
 PFireball.cc:47
 PFireball.cc:48
 PFireball.cc:49
 PFireball.cc:50
 PFireball.cc:51
 PFireball.cc:52
 PFireball.cc:53
 PFireball.cc:54
 PFireball.cc:55
 PFireball.cc:56
 PFireball.cc:57
 PFireball.cc:58
 PFireball.cc:59
 PFireball.cc:60
 PFireball.cc:61
 PFireball.cc:62
 PFireball.cc:63
 PFireball.cc:64
 PFireball.cc:65
 PFireball.cc:66
 PFireball.cc:67
 PFireball.cc:68
 PFireball.cc:69
 PFireball.cc:70
 PFireball.cc:71
 PFireball.cc:72
 PFireball.cc:73
 PFireball.cc:74
 PFireball.cc:75
 PFireball.cc:76
 PFireball.cc:77
 PFireball.cc:78
 PFireball.cc:79
 PFireball.cc:80
 PFireball.cc:81
 PFireball.cc:82
 PFireball.cc:83
 PFireball.cc:84
 PFireball.cc:85
 PFireball.cc:86
 PFireball.cc:87
 PFireball.cc:88
 PFireball.cc:89
 PFireball.cc:90
 PFireball.cc:91
 PFireball.cc:92
 PFireball.cc:93
 PFireball.cc:94
 PFireball.cc:95
 PFireball.cc:96
 PFireball.cc:97
 PFireball.cc:98
 PFireball.cc:99
 PFireball.cc:100
 PFireball.cc:101
 PFireball.cc:102
 PFireball.cc:103
 PFireball.cc:104
 PFireball.cc:105
 PFireball.cc:106
 PFireball.cc:107
 PFireball.cc:108
 PFireball.cc:109
 PFireball.cc:110
 PFireball.cc:111
 PFireball.cc:112
 PFireball.cc:113
 PFireball.cc:114
 PFireball.cc:115
 PFireball.cc:116
 PFireball.cc:117
 PFireball.cc:118
 PFireball.cc:119
 PFireball.cc:120
 PFireball.cc:121
 PFireball.cc:122
 PFireball.cc:123
 PFireball.cc:124
 PFireball.cc:125
 PFireball.cc:126
 PFireball.cc:127
 PFireball.cc:128
 PFireball.cc:129
 PFireball.cc:130
 PFireball.cc:131
 PFireball.cc:132
 PFireball.cc:133
 PFireball.cc:134
 PFireball.cc:135
 PFireball.cc:136
 PFireball.cc:137
 PFireball.cc:138
 PFireball.cc:139
 PFireball.cc:140
 PFireball.cc:141
 PFireball.cc:142
 PFireball.cc:143
 PFireball.cc:144
 PFireball.cc:145
 PFireball.cc:146
 PFireball.cc:147
 PFireball.cc:148
 PFireball.cc:149
 PFireball.cc:150
 PFireball.cc:151
 PFireball.cc:152
 PFireball.cc:153
 PFireball.cc:154
 PFireball.cc:155
 PFireball.cc:156
 PFireball.cc:157
 PFireball.cc:158
 PFireball.cc:159
 PFireball.cc:160
 PFireball.cc:161
 PFireball.cc:162
 PFireball.cc:163
 PFireball.cc:164
 PFireball.cc:165
 PFireball.cc:166
 PFireball.cc:167
 PFireball.cc:168
 PFireball.cc:169
 PFireball.cc:170
 PFireball.cc:171
 PFireball.cc:172
 PFireball.cc:173
 PFireball.cc:174
 PFireball.cc:175
 PFireball.cc:176
 PFireball.cc:177
 PFireball.cc:178
 PFireball.cc:179
 PFireball.cc:180
 PFireball.cc:181
 PFireball.cc:182
 PFireball.cc:183
 PFireball.cc:184
 PFireball.cc:185
 PFireball.cc:186
 PFireball.cc:187
 PFireball.cc:188
 PFireball.cc:189
 PFireball.cc:190
 PFireball.cc:191
 PFireball.cc:192
 PFireball.cc:193
 PFireball.cc:194
 PFireball.cc:195
 PFireball.cc:196
 PFireball.cc:197
 PFireball.cc:198
 PFireball.cc:199
 PFireball.cc:200
 PFireball.cc:201
 PFireball.cc:202
 PFireball.cc:203
 PFireball.cc:204
 PFireball.cc:205
 PFireball.cc:206
 PFireball.cc:207
 PFireball.cc:208
 PFireball.cc:209
 PFireball.cc:210
 PFireball.cc:211
 PFireball.cc:212
 PFireball.cc:213
 PFireball.cc:214
 PFireball.cc:215
 PFireball.cc:216
 PFireball.cc:217
 PFireball.cc:218
 PFireball.cc:219
 PFireball.cc:220
 PFireball.cc:221
 PFireball.cc:222
 PFireball.cc:223
 PFireball.cc:224
 PFireball.cc:225
 PFireball.cc:226
 PFireball.cc:227
 PFireball.cc:228
 PFireball.cc:229
 PFireball.cc:230
 PFireball.cc:231
 PFireball.cc:232
 PFireball.cc:233
 PFireball.cc:234
 PFireball.cc:235
 PFireball.cc:236
 PFireball.cc:237
 PFireball.cc:238
 PFireball.cc:239
 PFireball.cc:240
 PFireball.cc:241
 PFireball.cc:242
 PFireball.cc:243
 PFireball.cc:244
 PFireball.cc:245
 PFireball.cc:246
 PFireball.cc:247
 PFireball.cc:248
 PFireball.cc:249
 PFireball.cc:250
 PFireball.cc:251
 PFireball.cc:252
 PFireball.cc:253
 PFireball.cc:254
 PFireball.cc:255
 PFireball.cc:256
 PFireball.cc:257
 PFireball.cc:258
 PFireball.cc:259
 PFireball.cc:260
 PFireball.cc:261
 PFireball.cc:262
 PFireball.cc:263
 PFireball.cc:264
 PFireball.cc:265
 PFireball.cc:266
 PFireball.cc:267
 PFireball.cc:268
 PFireball.cc:269
 PFireball.cc:270
 PFireball.cc:271
 PFireball.cc:272
 PFireball.cc:273
 PFireball.cc:274
 PFireball.cc:275
 PFireball.cc:276
 PFireball.cc:277
 PFireball.cc:278
 PFireball.cc:279
 PFireball.cc:280
 PFireball.cc:281
 PFireball.cc:282
 PFireball.cc:283
 PFireball.cc:284
 PFireball.cc:285
 PFireball.cc:286
 PFireball.cc:287
 PFireball.cc:288
 PFireball.cc:289
 PFireball.cc:290
 PFireball.cc:291
 PFireball.cc:292
 PFireball.cc:293
 PFireball.cc:294
 PFireball.cc:295
 PFireball.cc:296
 PFireball.cc:297
 PFireball.cc:298
 PFireball.cc:299
 PFireball.cc:300
 PFireball.cc:301
 PFireball.cc:302
 PFireball.cc:303
 PFireball.cc:304
 PFireball.cc:305
 PFireball.cc:306
 PFireball.cc:307
 PFireball.cc:308
 PFireball.cc:309
 PFireball.cc:310
 PFireball.cc:311
 PFireball.cc:312
 PFireball.cc:313
 PFireball.cc:314
 PFireball.cc:315
 PFireball.cc:316
 PFireball.cc:317
 PFireball.cc:318
 PFireball.cc:319
 PFireball.cc:320
 PFireball.cc:321
 PFireball.cc:322
 PFireball.cc:323
 PFireball.cc:324
 PFireball.cc:325
 PFireball.cc:326
 PFireball.cc:327
 PFireball.cc:328
 PFireball.cc:329
 PFireball.cc:330
 PFireball.cc:331
 PFireball.cc:332
 PFireball.cc:333
 PFireball.cc:334
 PFireball.cc:335
 PFireball.cc:336
 PFireball.cc:337
 PFireball.cc:338
 PFireball.cc:339
 PFireball.cc:340
 PFireball.cc:341
 PFireball.cc:342
 PFireball.cc:343
 PFireball.cc:344
 PFireball.cc:345
 PFireball.cc:346
 PFireball.cc:347
 PFireball.cc:348
 PFireball.cc:349
 PFireball.cc:350
 PFireball.cc:351
 PFireball.cc:352
 PFireball.cc:353
 PFireball.cc:354
 PFireball.cc:355
 PFireball.cc:356
 PFireball.cc:357
 PFireball.cc:358
 PFireball.cc:359
 PFireball.cc:360
 PFireball.cc:361
 PFireball.cc:362
 PFireball.cc:363
 PFireball.cc:364
 PFireball.cc:365
 PFireball.cc:366
 PFireball.cc:367
 PFireball.cc:368
 PFireball.cc:369
 PFireball.cc:370
 PFireball.cc:371
 PFireball.cc:372
 PFireball.cc:373
 PFireball.cc:374
 PFireball.cc:375
 PFireball.cc:376
 PFireball.cc:377
 PFireball.cc:378
 PFireball.cc:379
 PFireball.cc:380
 PFireball.cc:381
 PFireball.cc:382
 PFireball.cc:383
 PFireball.cc:384
 PFireball.cc:385
 PFireball.cc:386
 PFireball.cc:387
 PFireball.cc:388
 PFireball.cc:389
 PFireball.cc:390
 PFireball.cc:391
 PFireball.cc:392
 PFireball.cc:393
 PFireball.cc:394
 PFireball.cc:395
 PFireball.cc:396
 PFireball.cc:397
 PFireball.cc:398
 PFireball.cc:399
 PFireball.cc:400
 PFireball.cc:401
 PFireball.cc:402
 PFireball.cc:403
 PFireball.cc:404
 PFireball.cc:405
 PFireball.cc:406
 PFireball.cc:407
 PFireball.cc:408
 PFireball.cc:409
 PFireball.cc:410
 PFireball.cc:411
 PFireball.cc:412
 PFireball.cc:413
 PFireball.cc:414
 PFireball.cc:415
 PFireball.cc:416
 PFireball.cc:417
 PFireball.cc:418
 PFireball.cc:419
 PFireball.cc:420
 PFireball.cc:421
 PFireball.cc:422
 PFireball.cc:423
 PFireball.cc:424
 PFireball.cc:425
 PFireball.cc:426
 PFireball.cc:427
 PFireball.cc:428
 PFireball.cc:429
 PFireball.cc:430
 PFireball.cc:431
 PFireball.cc:432
 PFireball.cc:433
 PFireball.cc:434
 PFireball.cc:435
 PFireball.cc:436
 PFireball.cc:437
 PFireball.cc:438
 PFireball.cc:439
 PFireball.cc:440
 PFireball.cc:441
 PFireball.cc:442
 PFireball.cc:443
 PFireball.cc:444
 PFireball.cc:445
 PFireball.cc:446
 PFireball.cc:447
 PFireball.cc:448
 PFireball.cc:449
 PFireball.cc:450
 PFireball.cc:451
 PFireball.cc:452
 PFireball.cc:453
 PFireball.cc:454
 PFireball.cc:455
 PFireball.cc:456
 PFireball.cc:457
 PFireball.cc:458
 PFireball.cc:459
 PFireball.cc:460
 PFireball.cc:461
 PFireball.cc:462
 PFireball.cc:463
 PFireball.cc:464
 PFireball.cc:465
 PFireball.cc:466
 PFireball.cc:467
 PFireball.cc:468
 PFireball.cc:469
 PFireball.cc:470
 PFireball.cc:471
 PFireball.cc:472
 PFireball.cc:473
 PFireball.cc:474
 PFireball.cc:475
 PFireball.cc:476
 PFireball.cc:477
 PFireball.cc:478
 PFireball.cc:479
 PFireball.cc:480
 PFireball.cc:481
 PFireball.cc:482
 PFireball.cc:483
 PFireball.cc:484
 PFireball.cc:485
 PFireball.cc:486
 PFireball.cc:487
 PFireball.cc:488
 PFireball.cc:489
 PFireball.cc:490
 PFireball.cc:491
 PFireball.cc:492
 PFireball.cc:493
 PFireball.cc:494
 PFireball.cc:495
 PFireball.cc:496
 PFireball.cc:497
 PFireball.cc:498
 PFireball.cc:499
 PFireball.cc:500
 PFireball.cc:501
 PFireball.cc:502
 PFireball.cc:503
 PFireball.cc:504
 PFireball.cc:505
 PFireball.cc:506
 PFireball.cc:507
 PFireball.cc:508
 PFireball.cc:509
 PFireball.cc:510
 PFireball.cc:511
 PFireball.cc:512
 PFireball.cc:513
 PFireball.cc:514
 PFireball.cc:515
 PFireball.cc:516
 PFireball.cc:517
 PFireball.cc:518
 PFireball.cc:519
 PFireball.cc:520
 PFireball.cc:521
 PFireball.cc:522
 PFireball.cc:523
 PFireball.cc:524
 PFireball.cc:525
 PFireball.cc:526
 PFireball.cc:527
 PFireball.cc:528
 PFireball.cc:529
 PFireball.cc:530
 PFireball.cc:531
 PFireball.cc:532
 PFireball.cc:533
 PFireball.cc:534
 PFireball.cc:535
 PFireball.cc:536
 PFireball.cc:537
 PFireball.cc:538
 PFireball.cc:539
 PFireball.cc:540
 PFireball.cc:541
 PFireball.cc:542
 PFireball.cc:543
 PFireball.cc:544
 PFireball.cc:545
 PFireball.cc:546
 PFireball.cc:547
 PFireball.cc:548
 PFireball.cc:549
 PFireball.cc:550
 PFireball.cc:551
 PFireball.cc:552
 PFireball.cc:553
 PFireball.cc:554
 PFireball.cc:555
 PFireball.cc:556
 PFireball.cc:557
 PFireball.cc:558
 PFireball.cc:559
 PFireball.cc:560
 PFireball.cc:561
 PFireball.cc:562
 PFireball.cc:563
 PFireball.cc:564
 PFireball.cc:565
 PFireball.cc:566
 PFireball.cc:567
 PFireball.cc:568
 PFireball.cc:569
 PFireball.cc:570
 PFireball.cc:571
 PFireball.cc:572
 PFireball.cc:573
 PFireball.cc:574
 PFireball.cc:575
 PFireball.cc:576
 PFireball.cc:577
 PFireball.cc:578
 PFireball.cc:579
 PFireball.cc:580
 PFireball.cc:581
 PFireball.cc:582
 PFireball.cc:583
 PFireball.cc:584
 PFireball.cc:585
 PFireball.cc:586
 PFireball.cc:587
 PFireball.cc:588
 PFireball.cc:589
 PFireball.cc:590
 PFireball.cc:591
 PFireball.cc:592
 PFireball.cc:593
 PFireball.cc:594
 PFireball.cc:595
 PFireball.cc:596
 PFireball.cc:597
 PFireball.cc:598
 PFireball.cc:599
 PFireball.cc:600
 PFireball.cc:601
 PFireball.cc:602
 PFireball.cc:603
 PFireball.cc:604
 PFireball.cc:605
 PFireball.cc:606
 PFireball.cc:607
 PFireball.cc:608
 PFireball.cc:609
 PFireball.cc:610
 PFireball.cc:611
 PFireball.cc:612
 PFireball.cc:613
 PFireball.cc:614
 PFireball.cc:615
 PFireball.cc:616
 PFireball.cc:617
 PFireball.cc:618
 PFireball.cc:619
 PFireball.cc:620
 PFireball.cc:621
 PFireball.cc:622
 PFireball.cc:623
 PFireball.cc:624
 PFireball.cc:625
 PFireball.cc:626
 PFireball.cc:627
 PFireball.cc:628
 PFireball.cc:629
 PFireball.cc:630
 PFireball.cc:631
 PFireball.cc:632
 PFireball.cc:633
 PFireball.cc:634
 PFireball.cc:635
 PFireball.cc:636
 PFireball.cc:637
 PFireball.cc:638