26 #include "RConfigure.h"
29 #include "TLorentzVector.h"
39 #ifdef R__HAS_MATHMORE
40 #include "Math/SpecFuncMathMore.h"
51 for (
Gw::Spin i = -Ii ; i <= Ii ; i+=1) {
52 temp += TMath::Exp(-(i.Get()*i.Get())/(2*sigma*sigma));
54 printf(
"temp = %f , sigma = %f , exp = %f\n",temp,sigma,TMath::Exp(-(i.Get()*i.Get())/(2*sigma*sigma)));
57 return TMath::Exp(-(m.
Get()*m.
Get())/(2*sigma*sigma))/temp;
61 Double_t CG = TMath::Power(-1,j1.
Get()-j2.
Get()+M.
Get())
62 * TMath::Sqrt(2*J.
Get()+1)
73 Double_t B(
const Gw::Spin &Ii, Int_t lambda)
75 Double_t result = 0, CG = 0;
80 CG = ClebschGordan(Ii,s_zero,Ii,s_zero,s_lambda,s_zero);
81 result = TMath::Sqrt(2*Ii.
Get()+1)*TMath::Power(-1,Ii.
Get())*CG;
87 CG = ClebschGordan(Ii,m_s_1_2,Ii,s_1_2,s_lambda,s_zero);
88 result = TMath::Sqrt(2*Ii.
Get()+1)*(-1)*TMath::Power(-1,Ii.
Get()+0.5)*CG;
95 Double_t B(
const Gw::Spin &Ii, Double_t lambda, Double_t sigma)
98 Double_t result = 0.0, CG = 0.0;
Gw::Spin s_lambda(lambda,1);
100 for (
Gw::Spin m = -Ii ; m <= Ii ; m+=1)
103 CG = ClebschGordan(Ii,m_m,Ii,m,s_lambda,s_zero);
105 result += TMath::Power(-1,Ii.
Get()+m.
Get())*CG*P(Ii,m,sigma);
107 result = TMath::Sqrt(2*Ii.
Get()+1)*result;
112 Double_t F(
const Gw::Spin &Ii,
const Gw::Spin &If, Int_t L1, Int_t L2, Double_t lambda)
114 Double_t threeJ, sixJ, result;
116 threeJ = ROOT::Math::wigner_3j(2*L1,2*L2,2*lambda,2,-2,0);
119 result = TMath::Power(-1,1+Ii.
Get()+If.
Get())*TMath::Sqrt((2*lambda+1)*(2*L1+1)*(2*L2+1)*(2*Ii.
Get()+1))*threeJ*sixJ;
126 Double_t Wth(Double_t *x, Double_t *par)
129 p2 = ROOT::Math::legendre(2,TMath::Cos(x[0]));
130 p4 = ROOT::Math::legendre(4,TMath::Cos(x[0]));
132 return par[0]+par[1]*p2+par[2]*p4;
134 Double_t WthDeg(Double_t *x, Double_t *par)
137 p2 = ROOT::Math::legendre(2,TMath::Cos(x[0]*TMath::Pi()/180.));
138 p4 = ROOT::Math::legendre(4,TMath::Cos(x[0]*TMath::Pi()/180.));
140 return par[0]+par[1]*p2+par[2]*p4;
143 Double_t WthCos(Double_t *x, Double_t *par)
146 p2 = ROOT::Math::legendre(2,x[0]);
147 p4 = ROOT::Math::legendre(4,x[0]);
149 return par[0]+par[1]*p2+par[2]*p4;
158 fLevelScheme(0x0), fFeeding(), fRandFeeding(), fRandDown(), fAD(), fRand0(), fTmp(), fEoC(),
160 fMinEnergyFactor(10.0),
162 fCutLifeTime(0.0000000001),
165 fTmp.SetOwner(kTRUE);
166 fRandDown.SetOwner(kTRUE);
167 fFeeding.SetOwner(kTRUE);
168 fRandFeeding.SetOwner(kTRUE);
176 if ( fLevelScheme ) {
185 if ( opt.Contains(
"all") ) {
186 delete fLevelScheme; fLevelScheme = 0x0;
189 fRand0.
Clear(); fFeeding.Clear(); fRandFeeding.Clear(); fRandDown.Clear(); fTmp.Clear(); fAD.Clear();
199 TString lname(filename), lopt(opt);
200 if ( lname.Contains(
".root")) {
201 TFile lroot(filename);
202 if ( lroot.IsOpen() ) {
207 printf(
"Impossible to find levelscheme %s in %s \n",filename,opt);
214 ok = newlev->
Import(filename,opt);
217 if ( newlev && ok ) {
218 if ( fLevelScheme ) {
221 fLevelScheme = newlev;
230 if ( tname ==
"ADType" ) {
240 if ( tname ==
"MinEnergyFactor" ) {
244 if ( tname ==
"CutLifeTime" ) {
253 if ( fLevelScheme->
GetLinks().GetSize() == 0 )
return;
255 Int_t i, iend, j, jend;
Link *gam1 = NULL, *gam2 = NULL;
261 fRandDown.Expand(fLevelScheme->
GetLinks().GetSize());
262 fRandFeeding.Expand(fLevelScheme->
GetLinks().GetSize()); fFeeding.Expand(fLevelScheme->
GetLinks().GetSize()); fAD.Expand(fLevelScheme->
GetLinks().GetSize());
267 Float_t min = 1000000; Int_t nbwrong = 0;
268 iend = jend = fLevelScheme->
GetLinks().GetSize();
269 for (i = 0; i < iend; i++) {
280 printf(
"\n WARNING in BaseGEM::Import \n");
281 printf(
" %d links have been found with an intensity = 0 in %s \n",nbwrong,fLevelScheme->
GetName());
282 printf(
" The intensity of those links are set to the weakest intensity %f / %f \n \n",min,
fMinEnergyFactor);
283 for (i = 0; i < iend; i++) {
292 RandObj *down, *downfeeding; TObject *obj;
293 Float_t sum_int_up_in, sum_int_up_out, sum_int_down_in, sum_int_down_out;
295 for (i = 0; i < iend; i++) {
317 sum_int_down_out = 0;
319 for (j = 0; j < jend; j++) {
321 if ( i == j )
continue;
325 if ( gam1->
GetIL() == gam2->GetFL() ) {
326 sum_int_up_in += gam2->GetStrength().Get();
328 if ( gam1->
GetIL() == gam2->GetIL() ) {
329 sum_int_up_out += gam2->GetStrength().Get();
334 downfeeding->
Add(obj,gam2->GetStrength().Get());
336 if ( gam1->
GetFL() == gam2->GetIL() ) {
337 sum_int_down_out += gam2->GetStrength().Get();
342 down->
Add(obj,gam2->GetStrength().Get());
345 if ( gam1->
GetFL() == gam2->GetFL() ) {
346 sum_int_down_in += gam2->GetStrength().Get();
353 if ( sum_int_up_out > sum_int_up_in ) {
359 if ( sum_int_down_in > sum_int_down_out ) { down->
Add(&fEoC,sum_int_down_in - sum_int_down_out); }
362 fRandFeeding.AddAt(downfeeding,i);
363 fRandDown.AddAt(down,i);
367 if (
fADType == 1 && gam1->InheritsFrom(
"Gw::GammaLink") && gamma->
GetLambda() > 0 ) {
369 #ifdef R__HAS_MATHMORE
370 Int_t lambda_max = 0, L, L1, L2; Double_t a0,a2,a4;
382 if ( delta == 0.0 ) {
384 a0 = B(Ii,0)*F(Ii,If,L,L,0);
385 if ( lambda_max >=2 )
386 a2 = B(Ii,2)*F(Ii,If,L,L,2);
387 if ( lambda_max >=4 )
388 a4 = B(Ii,4)*F(Ii,If,L,L,4);
397 a2 = B(Ii,2)*( F(Ii,If,L1,L1,2) + 2*delta*F(Ii,If,L1,L2,2) + delta*delta*F(Ii,If,L2,L2,2) ) / (1+delta*delta);
399 a4 = B(Ii,4)*( F(Ii,If,L1,L1,4) + 2*delta*F(Ii,If,L1,L2,4) + delta*delta*F(Ii,If,L2,L2,4) ) / (1+delta*delta);
408 if ( delta == 0.0 ) {
411 a0 = B(Ii,0,
fSigma)*F(Ii,If,L,L,0);
413 a2 = B(Ii,2,
fSigma)*F(Ii,If,L,L,2);
415 a4 = B(Ii,4,
fSigma)*F(Ii,If,L,L,4);
424 a2 = B(Ii,2,
fSigma)*( F(Ii,If,L1,L1,2) + 2*delta*F(Ii,If,L1,L2,2) + delta*delta*F(Ii,If,L2,L2,2) ) / (1+delta*delta);
426 a4 = B(Ii,4,
fSigma)*( F(Ii,If,L1,L1,4) + 2*delta*F(Ii,If,L1,L2,4) + delta*delta*F(Ii,If,L2,L2,4) ) / (1+delta*delta);
432 TString name_function = Form(
"%s_link_%.1f_%.1f_%.1f",fLevelScheme->
GetName(),gamma->
GetEnergy().
Get(),Ii.
Get(),If.
Get());
433 TF1 *W =
new TF1(name_function.Data(),Wth,0,TMath::Pi(),3);
434 W->SetParameter(0,1);
435 W->SetParameter(1,a2/a0);
436 W->SetParameter(2,a4/a0);
442 gROOT->GetListOfFunctions()->Remove(W);
444 W =
new TF1(name_function.Data(),Wth,0,TMath::Pi(),3);
445 W->SetParameter(0,1);
446 W->SetParameter(1,a2/a0);
447 W->SetParameter(2,a4/a0);
451 printf(
" *** Error, cannot set Angular Distribution in BaseGEM, ROOT MathMore lib probably not installed \n");
455 printf(
" There are %d gammas feeding the gamma # %d \n",downfeeding->
GetSize(),i);
456 printf(
" There are %d gammas de-exciting the gamma # %d \n",down->
GetSize(),i);
495 TObject *obj;
Link *link; Int_t result = 0;
497 if ( fRandFeeding.At( which_first ) == 0x0 )
501 if ( !opt.Contains(
"add",TString::kIgnoreCase) )
502 cas.Clear(
"nodelete");
505 obj = ((
RandObj *)fRandFeeding.At( which_first ))->Rand();
506 while ( obj != &fEoC ) {
507 link = (
Link *)fLevelScheme->
GetLinks().At(obj->GetUniqueID());
509 obj = ((
RandObj *)fRandDown.At( obj->GetUniqueID() ))->Rand();
514 tmp.SetOwner(kFALSE); tmp.Clear(
"nodelete"); tmp.AddAll(&cas); cas.Clear(
"nodelete");
516 for (Int_t i = tmp.GetEntries()-1; i >=0; i-- )
528 Int_t which_first = 0;
529 fRand0.
Rand(which_first);
538 TObject *generator = fAD.At(which_gamma);
539 if ( generator == 0x0 || forceiso ) {
542 vector.SetXYZT(x,y,z,0);
548 TVector3 v; Double_t theta = 0, phi = 0;
550 TF1 *angdistri2d = (TF1 *)generator;
551 theta = angdistri2d->GetRandom();
553 v.SetMagThetaPhi(1,theta,phi);
555 vector.SetVect(v); vector.SetT(0.0);
561 Int_t
BaseGEM::DoCascade(TSeqCollection &cas, TSeqCollection &directions, Int_t which_first, Option_t *o)
563 TObject *obj;
Link *link; Int_t result = 0, result_one_link = 0;
565 if ( fRandFeeding.At( which_first ) == 0x0 )
569 if ( !opt.Contains(
"add",TString::kIgnoreCase) ) {
570 cas.Clear(
"nodelete");
571 directions.Clear(
"nodelete");
575 obj = ((
RandObj *)fRandFeeding.At( which_first ))->Rand();
576 while ( obj != &fEoC ) {
577 link = (
Link *)fLevelScheme->
GetLinks().At(obj->GetUniqueID());
578 result_one_link += link->
DoCascade(cas,o);
580 for (Int_t i = result; i < result + result_one_link; i++) {
581 if ( directions.At(i) == 0 ) {
582 directions.AddAt(
new TLorentzVector(),i);
585 if ( result_one_link == 1 ) {
586 TLorentzVector *lv = (TLorentzVector *)directions.At(result);
587 if ( cas.At(result) == link ) {
594 for (Int_t i = 0; i < result_one_link; i++) {
595 TLorentzVector *lv = (TLorentzVector *)directions.At(result+i);
598 printf(
"*** TO BE IMPLEMENTED in BaseGEM::DoCascade TSeqCollection &cas, TSeqCollection &directions, Int_t which_first, Option_t *o *** /n");
599 printf(
"*** Isotropic has been forced for %d links produced by link # %d *** /n",result_one_link,obj->GetUniqueID());
601 result += result_one_link;
602 obj = ((
RandObj *)fRandDown.At( obj->GetUniqueID() ))->Rand();
606 TObjArray tmpg(30), tmpd(30);
607 tmpg.SetOwner(kFALSE); tmpg.Clear(
"nodelete"); tmpg.AddAll(&cas); cas.Clear(
"nodelete");
608 tmpd.SetOwner(kFALSE); tmpd.Clear(
"nodelete"); tmpd.AddAll(&directions); directions.Clear(
"nodelete");
610 for (Int_t i = tmpg.GetEntries()-1; i >=0; i-- ) {
612 directions.Add(tmpd.At(i));
624 if ( !opt.Contains(
"add",TString::kIgnoreCase) ) {
625 cas.Clear(
"nodelete");
626 directions.Clear(
"nodelete");
630 Int_t which_first = 0;
631 fRand0.
Rand(which_first);
633 return DoCascade(cas,directions,which_first,o);
virtual TObject * Rand()
it returns a pointer to a randomly selected object from the collection
printf("******************************************************************** \n")
virtual void Set(Data_T data)
set the measure and its error (default err=0)
virtual Int_t Import(const Char_t *, Option_t *)
to init this level scheme from an existing formatted file (ENSDF, Radware ..)
virtual void Clear(Option_t *opt="all")
Clear everything.
Class to get randomly cascades of gammas on the basis of a level scheme.
virtual Measure< Float_t > & GetMixing()
to get/modify the mixing ratio and its error
header file for a NuclearLevel
Float_t Get() const
To get the spin as a float.
virtual Level * GetIL()
to get the initial level
A class to select randomly an object in a TObjArray of objects.
A spin is defined by two integers: a numerator and a denominator.
virtual void Clear(Option_t *opt="")
clear everything (the objects in the collection are not deleted)
virtual const char * GetName() const
virtual void DoAngularDistribution(Int_t which_gamma, TLorentzVector &, Bool_t forceiso=false)
Double_t fMinEnergyFactor
virtual Level * GetFL()
to get the final level
header file for a GammaLink
Int_t GetInTwoHalfUnit() const
to get the spin in two half unit
const TList & GetLinks()
to get the list of links
A link between two levels.
TRandom * Current() const
to get the current TRandomom object
virtual Data_T Get() const
get the value, can be overloaded
virtual Int_t DoCascade(TSeqCollection &, Option_t *="")
to add this link to a cascade
virtual void Add(TObject *, Float_t)
it adds an object with a weight to this collection.
virtual Int_t GetSize() const
virtual Measure< Float_t > & GetEnergy()
to get/modify the gamma-ray energy and its error
virtual Measure< Float_t > & GetTau()
to get the characteritic time and modify it if it is needed
Bool_t IsHalfInt() const
To get the spin as a float.
virtual Measure< Float_t > & GetStrength()
to get the strength and modify it if it is needed
virtual Int_t DoCascade(TSeqCollection &cascade, Option_t *opt="")
cascade simulation
virtual Level * SetFL(Level *final)
to change the final level - return the previous one
static Random * Instance()
to access the unique instance
virtual UShort_t GetLambda() const
returns the numeric part of the multipolarity
virtual Int_t Import(const Char_t *, Option_t *opt="152DY")
Load the level scheme and init the Monte-Carlo.
A GammaLink binds two nuclear levels.
Bool_t SetParameter(const char *name, Int_t value)
to set some parameters that modify the way the simulation is performed. return false is the parameter...
virtual void InitRandom()
to be called to init the random generator
header file for a BaseGEM (gamma-rays generator)
header file for a spin quantum number
virtual Level * SetIL(Level *initial)
to change the final level - return the previous one